Praxis_Bot/twitch_script_standalone.py
2021-04-21 16:40:55 -04:00

166 lines
6.5 KiB
Python

import re
from json import loads
from urllib.parse import urlencode
import requests
import twitch
import twitch.chat
import config as config
import credentials
from cooldowns import Cooldown_Module
import commands.command_base
class Twitch_Module():
def __init__(self):
super().__init__()
self.twitchCredential: credentials.Twitch_Credential
self.chat: twitch.Chat
self.block_chat_url: bool = True
self.whitelisted_users: list = ["thecuriousnerd"]
# don't freak out, this is *merely* a regex for matching urls that will hit just about everything
self._urlMatcher = re.compile(
"(https?:(/{1,3}|[a-z0-9%])|[a-z0-9.-]+[.](com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw))")
# Default Twitch Chat limit is 20 per 30 seconds
# If Mod or Op, Twitch Chat limit is 100 per 30 seconds
self.cooldownModule: Cooldown_Module = Cooldown_Module()
self.cooldownModule.setupCooldown("twitchChat", 20, 32)
self.allow_rgbLightControl = config.autoEnabled_Twitch_rgbLightControl
def join_channel(self, credential: credentials.Twitch_Credential, channel_name: str):
channel_name = "#" + channel_name
print("Connecting to Channel: " + channel_name + "...")
if credential is None:
credential = self.twitchCredential
self.chat = twitch.Chat(
channel=channel_name,
nickname=credential.username,
oauth=credential.oauth,
# LIBRARY UPDATE BROKE THE FOLLOWING LINE [FIX THIS]
# helix = twitch.Helix(credential.helix, use_cache=True)
)
self.chat.subscribe(self.twitch_chat)
print("Connected to Channel: ", channel_name)
def leave_channel(self):
print("Leaving Channel", self.chat.channel)
self.chat.irc.leave_channel(self.chat.channel)
self.chat.irc.socket.close()
def send_message(self, message):
isBlocked = self.isChannel_inConfigList(self.chat.channel, config.block_TwitchChannelsMessaging)
# print("isBlocked: " + str(isBlocked) + " for: " + self.chat.channel)
#if self.
if self.contains_slur(message): isBlocked = True
if self.cooldownModule.isCooldownActive(
"twitchChat") == False and not isBlocked and not config.blockAll_TwitchChatChannelsMessaging:
self.chat.send(message)
# print("Sent ChatMSG")
self.cooldownModule.actionTrigger("twitchChat")
def parse_line(self, message: str):
first_space = False
start = -1
idx = -1
for x in range(0, len(message)):
c = message[x]
if c == ' ':
if first_space:
idx = x
break
else:
first_space = True
pass
else:
first_space = True
if start == -1:
start = x
if idx == -1:
idx = len(message)
command = message[start:idx]
rest = message[idx + 1:]
return command, rest
def is_command(self, word: str) -> bool:
# todo need to url-escape word
clean_param = urlencode({'name': word})
url = "http://localhost:5000/api/v1/command?%s" % clean_param
resp = requests.get(url)
return resp.status_code == 200
def exec_command(self, command: str, rest: str):
# todo need to url-escape command and rest
params = urlencode({'command_source': commands.command_base.AbstractCommand.CommandSource.default, 'command_name': command, 'rest': rest})
url = "http://localhost:5000/api/v1/exec?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
self.send_message(msg)
else:
# todo handle failed requests
pass
def send_whisper(self, user, message):
pass
# This reacts to messages
def twitch_chat(self, message: twitch.chat.Message) -> None:
print("[#" + message.channel + "](" + message.sender + ")> " + message.text)
command, rest = self.parse_line(message.text)
is_actionable = self.is_command(command)
if is_actionable:
self.exec_command(command, rest)
# Checks for basic slurs.
def contains_slur(self, message):
containsSlur: bool = False
parsedMessage = message.split(" ")
for word in parsedMessage:
for slur in config.slurList:
if word.lower() == slur:
containsSlur = True
break # we want to immediately escape if we found a slur
if containsSlur:
break
return containsSlur
def isChannel_inConfigList(self, selectedChannel, selectedList):
# print(channel)
# print(selectedList)
is_Self = False
for twitchChannel in selectedList:
if twitchChannel == selectedChannel:
is_Self = True
# if is_Self:
# print("Is Self")
# if not is_Self:
# print("Is Not Self")
return is_Self
if __name__ == "__main__":
testModule = Twitch_Module()
credentials_manager = credentials.Credentials_Module()
credentials_manager.load_credentials()
testModule.twitchCredential = credentials_manager.find_Twitch_Credential(config.credentialsNickname)
#testModule.dbCredential = credentials_manager.find_DB_Credential(config.credentialsNickname)
for twitchChannel in config.autoJoin_TwitchChannels:
testModule.join_channel(None, twitchChannel)