Let PEP8 do it's thing and reformat all the files.

Removed bots.py and slurs.py and moved them into config.py. twitch_script_class.py has been updated to handle this
added a test harness for twitch_script_class.py
contains_url and contains_slur are both validated
refactored contains_url to use a simple(ish) regex instead of an if cascade

Let PEP8 do it's thing and reformat all the files.
Removed bots.py and slurs.py and moved them into config.py. twitch_script_class.py has been updated to handle this
added a test harness for twitch_script_class.py
contains_url and contains_slur are both validated
refactored contains_url to use a simple(ish) regex instead of an if cascade
This commit is contained in:
dtookey 2020-09-20 11:40:51 -04:00
parent 994981cfdb
commit 3e24942d54
13 changed files with 140 additions and 116 deletions

View File

@ -1 +0,0 @@
botList = ["Nightbot", "StreamElements", "Moobot", "praxis_bot"]

3
config.py Normal file
View File

@ -0,0 +1,3 @@
botList = ("Nightbot", "StreamElements", "Moobot", "praxis_bot")
slurList = ("fag", "faggot", "niga", "nigga", "nigger", "retard", "tard", "rtard", "coon")

27
db.py
View File

@ -1,10 +1,9 @@
import mysql.connector
import os
import db_cred as db_credentials
import pandas as pd
from sqlalchemy import create_engine
class db_module():
def __init__(self):
super().__init__()
@ -15,27 +14,26 @@ class db_module():
self.engine = create_engine(db_credentials.engine_url)
print("Engine Created")
def create_table(self, tableName:str = ""):
def create_table(self, tableName: str = ""):
pass
def does_table_exist(self, tableName:str = ""):
def does_table_exist(self, tableName: str = ""):
pass
def delete_table(self, tableName:str = ""):
def delete_table(self, tableName: str = ""):
pass
#This was a old function used prior to the creation of this class. I need to remake it.
def get_data_old(self, tableName:str = "", key:str = ""):
# This was a old function used prior to the creation of this class. I need to remake it.
def get_data_old(self, tableName: str = "", key: str = ""):
table = '_channel_commands'
table = tableName
df = pd.read_sql_query('SELECT * FROM '+ table, engine)
df = pd.read_sql_query('SELECT * FROM ' + table, engine)
stmt = "trigger == '" + key + "'"
temp = df.query(stmt)
result = temp.get("response")
#print(result)
# print(result)
i = len(temp.index.values)
if i == 1:
@ -45,20 +43,19 @@ class db_module():
output = "$$None$$"
return output
def get_data(self, tableName:str = "", key:str = ""):
def get_data(self, tableName: str = "", key: str = ""):
pass
def insert_data(self, tableName:str = "", param:str = ""):
def insert_data(self, tableName: str = "", param: str = ""):
pass
def edit_data(self, tableName:str = "", key:str = "", param:str = ""):
def edit_data(self, tableName: str = "", key: str = "", param: str = ""):
pass
def delete_data(self, tableName:str = "", key:str = ""):
def delete_data(self, tableName: str = "", key: str = ""):
pass
if __name__ == "__main__":
db_connection = db_module()
db_connection.setup_engine()

View File

@ -1,6 +1,7 @@
import pygetwindow as gw
from pynput.keyboard import Key, Controller
import time
keyboard = Controller()

15
main.py
View File

@ -1,12 +1,5 @@
# Install these:
# pip install mysql-connector-python
# pip install pynput
# pip install twitch-python
# pip install SQLAlchemy
# pip install pandas
# pip install numpy
# pip install gTTS
# pip install playsound
# I moved all the requirements into requirements.txt.
# you can install everything with pip install -r requirements.txt while you're in the directory
import sys
import time
@ -17,6 +10,7 @@ import utilities_script as utility
twitch_chat: twitch_script_class.Twitch_Module
def main():
print("Connecting to Channels...")
@ -24,9 +18,8 @@ def main():
twitch_chat = twitch_script_class.Twitch_Module()
twitch_chat.join_channel("thecuriousnerd")
#twitch_chat.send_message("activated")
# twitch_chat.send_message("activated")
if __name__ == "__main__":
main()

8
requirements.txt Normal file
View File

@ -0,0 +1,8 @@
mysql-connector-python
pynput
twitch-python
SQLAlchemy
pandas
numpy
gTTS
playsound

View File

@ -1 +0,0 @@
slurList = ["fag", "faggot", "niga", "nigga", "nigger", "retard", "tard", "rtard", "coon"]

View File

@ -0,0 +1,35 @@
import unittest
import twitch_script_class
import twitch
testValidUrls = ['https://shady.ru', 'http://stolencards.zn', 'https://i.imgur.com/FL6slHd.jpg']
testInvalidUrls = ['this is just a sentence. With a period', 'gotta have some other stuff', 'bad punctuation produces false positives']
class TwitchBotTest(unittest.TestCase):
def setUp(self):
self.bot = twitch_script_class.Twitch_Module()
def test_find_url(self):
bot = self.bot
for link in testInvalidUrls:
msg = twitch.chat.Message("", "", link)
t = bot.contains_url(msg)
assert not t
for link in testValidUrls:
msg = twitch.chat.Message("", "", link)
t = bot.contains_url(msg)
assert t
def test_find_slur(self):
nonSlurMessage = twitch.chat.Message("", "", "hey look, a normal sentence")
slurMessage = twitch.chat.Message("", "", "fag is a hateful word that shouldn't be used anymore")
assert not self.bot.contains_slur(nonSlurMessage)
assert self.bot.contains_slur(slurMessage)
if __name__ == '__main__':
unittest.main()

14
tts.py
View File

@ -1,4 +1,3 @@
from gtts import gTTS
import os
import datetime
@ -6,26 +5,27 @@ import datetime
from playsound import playsound
def tts(inputText:str, *args):
def tts(inputText: str, *args):
destPath = os.getcwd() + "\\tts\\"
time = datetime.datetime.now()
fileName:str = time.strftime("%m-%d-%Y_%H-%M-%S") + "_tts.mp3"
fileName: str = time.strftime("%m-%d-%Y_%H-%M-%S") + "_tts.mp3"
if len(args) == 1:
fileName = args[0] + "_tts.mp3"
tts = gTTS(text=inputText, lang='en')
tts.save(destPath + fileName)
# tts = gTTS(text=inputText, lang='en')
# tts.save(destPath + fileName)
playsound(destPath + fileName)
#os.system(filename)
# os.system(filename)
def play_speech(fileName):
destPath = os.getcwd() + "\\tts\\"
playsound(destPath + fileName)
if __name__ == "__main__":
print("Enter Text: ")
textInput = str(input())

View File

@ -1,10 +1,11 @@
# So I'm a little conflicted here. My nit-picky self says that this should be a class you have to instantiate rather
# than static variables... I'll leave this alone for now, but you may wish to refactor this in future
username = ""
helix = ""
oauth = "oauth:"
v5_Client = ""
#Helix ID https://dev.twitch.tv/console/apps
#Oauth https://twitchapps.com/tmi/
#V5 Client ID https://twitchtokengenerator.com/
# Helix ID https://dev.twitch.tv/console/apps
# Oauth https://twitchapps.com/tmi/
# V5 Client ID https://twitchtokengenerator.com/

View File

@ -3,20 +3,23 @@ import twitch
import twitch.chat
import twitch_cred as twitch_credentials
import bots as botList
import slurs as slurList
import config as config
import tts
import db
import re
class Twitch_Module():
def __init__(self):
super().__init__()
self.chat: twitch.Chat
self.tts_enabled:bool = False
self.tts_whitelist_enabled:bool = False
self.links_allowed:bool = True
self.whitelisted_users:list = ["thecuriousnerd", "theredpoint", "lakotor"]
self.tts_enabled: bool = False
self.tts_whitelist_enabled: bool = False
self.links_allowed: bool = True
self.whitelisted_users: list = ["thecuriousnerd", "theredpoint", "lakotor"]
# 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))")
def join_channel(self, channel_name):
channel_name = "#" + channel_name
@ -31,10 +34,8 @@ class Twitch_Module():
print("Connected to Channel: ", channel_name)
def leave_channel(self):
print("Leaving Channel",self.chat.channel)
print("Leaving Channel", self.chat.channel)
self.chat.irc.leave_channel(self.chat.channel)
self.chat.irc.socket.close()
@ -44,19 +45,18 @@ class Twitch_Module():
def send_whisper(self, user, message):
pass
#This reacts to messages
# This reacts to messages
def twitch_chat(self, message: twitch.chat.Message) -> None:
print("[#"+ message.channel + "](" + message.sender + ")> " + message.text)
print("[#" + message.channel + "](" + message.sender + ")> " + message.text)
if message.channel == "thecuriousnerd":
if self.isSenderBot(message) == False:
if not self.isSenderBot(message):
if message.sender.lower() == "thecuriousnerd":
self.eval_commands(message)
self.tts_message(message)
def eval_commands(self, message: twitch.chat.Message):
containsURL:bool = self.contains_url(message)
containsURL: bool = self.contains_url(message)
if message.text.startswith('!tts start'):
print("tts activated on #" + message.channel)
@ -71,7 +71,7 @@ class Twitch_Module():
if message.text.startswith('!test'):
print("!test Detected")
message.chat.send("test acknowledged")
#message.chat.send(f'@{message.user().display_name}, you have {message.user().view_count} views.')
# message.chat.send(f'@{message.user().display_name}, you have {message.user().view_count} views.')
if message.text.startswith('!roll'):
try:
@ -80,7 +80,6 @@ class Twitch_Module():
self.send_message("{something went wrong}")
print("{something went wrong}")
def tts_message(self, message: twitch.chat.Message):
if self.contains_slur(message) == False:
if self.tts_enabled == True:
@ -88,73 +87,62 @@ class Twitch_Module():
if message.sender.lower() == message.channel:
tts.tts(message.sender + " says, " + message.text)
else:
#tts.tts(message.sender + " says, " + message.text)
# tts.tts(message.sender + " says, " + message.text)
tts.tts(message.sender + " says, " + message.text, message.channel + " user msg")
def contains_url(self, message: twitch.chat.Message):
containsURL:bool = False
if message.text.lower().find("http") != -1:
containsURL = True
if message.text.lower().find("https") != -1:
containsURL = True
if message.text.lower().find(".com") != -1:
containsURL = True
if message.text.lower().find(".net") != -1:
containsURL = True
if message.text.lower().find(".org") != -1:
containsURL = True
if message.text.lower().find(".tv") != -1:
containsURL = True
if message.text.lower().find(".io") != -1:
containsURL = True
if containsURL == True:
print("<{ link detected! }> " + " [#"+ message.channel + "](" + message.sender + ") sent a link in chat")
containsURL = re.search(self._urlMatcher, message.text.lower()) is not None
if containsURL:
print("<{ link detected! }> " + " [#" + message.channel + "](" + message.sender + ") sent a link in chat")
return containsURL
#Checks if Sender is bot.
# Checks if Sender is bot.
def isSenderBot(self, message: twitch.chat.Message):
isBot = False
for bot in botList.botList:
for bot in config.botList:
if message.sender.lower() == bot.lower():
isBot = True
print("<{ bot detected! }> " + " [#"+ message.channel + "](" + message.sender + ") is a bot")
print("<{ bot detected! }> " + " [#" + message.channel + "](" + message.sender + ") is a bot")
return isBot
#Checks for basic slurs.
# Checks for basic slurs.
def contains_slur(self, message: twitch.chat.Message):
containsSlur:bool = False
containsSlur: bool = False
parsedMessage = message.text.split(" ")
for word in parsedMessage:
for slur in slurList.slurList:
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
if containsSlur == True:
print("<{ slur detected! }> " + " [#"+ message.channel + "](" + message.sender + ") used a slur in chat")
if containsSlur:
print("<{ slur detected! }> " + " [#" + message.channel + "](" + message.sender + ") used a slur in chat")
return containsSlur
#Rolls Dice.
# Rolls Dice.
def dice_roll(self, message: twitch.chat.Message):
diceRoll:str = ""
diceRoll: str = ""
self.send_message("Rolling Dice...")
print("Rolling Dice...")
temp_preParsedMessage = message.text.split("+")
tempParsedMessage = temp_preParsedMessage[0].split(" ")
temp_dice_stmt:str = tempParsedMessage[1]
temp_dice_stmt: str = tempParsedMessage[1]
parsedMessage = temp_dice_stmt.lower().split("d")
loopBool:bool = False
loopBool: bool = False
if parsedMessage[0] != "":
loopBool = True
if loopBool == True:
if int(parsedMessage[0]) == 1:
loopBool = False
#If roll is in xdx+x format
# If roll is in xdx+x format
if loopBool == True:
rolls:list = []
rolls: list = []
for x in range(int(parsedMessage[0])):
rolls.append(random.randint(1, int(parsedMessage[1])))
@ -162,18 +150,20 @@ class Twitch_Module():
for roll in rolls:
rollTotal = rollTotal + roll
diceRoll = diceRoll + str(roll) + ", "
diceRoll = diceRoll[:-2] #This removes the last two characters in the string
diceRoll = diceRoll[:-2] # This removes the last two characters in the string
if len(temp_preParsedMessage) == 2:
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(rollTotal + int(temp_preParsedMessage[1]))
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(
rollTotal + int(temp_preParsedMessage[1]))
else:
diceRoll = diceRoll + " = " + str(rollTotal)
#If roll is in dx+x format
# If roll is in dx+x format
if loopBool == False:
roll:int = random.randint(1, int(parsedMessage[1]))
roll: int = random.randint(1, int(parsedMessage[1]))
if len(temp_preParsedMessage) == 2:
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(roll + int(temp_preParsedMessage[1]))
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
@ -182,8 +172,8 @@ class Twitch_Module():
self.send_message(diceRoll)
#This is a old function used prior to the creation of the Twitch_Module class above.
#I need to make a new one for the class.
# This is a old function used prior to the creation of the Twitch_Module class above.
# I need to make a new one for the class.
def main_chat_commands_check(channel, sender, text):
response = db.basic_command_trigger(channel, sender, text)
if response == "$$None$$":
@ -193,7 +183,6 @@ def main_chat_commands_check(channel, sender, text):
print(response)
if __name__ == "__main__":
testChat = Twitch_Module()
testChat.join_channel("thecuriousnerd")

View File

@ -1,4 +1,3 @@
import os
clearScreen = lambda : os.system('cls' if os.name == 'nt' else 'clear')
clearScreen = lambda: os.system('cls' if os.name == 'nt' else 'clear')