diff --git a/README.md b/README.md index cd51c6b..9406164 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,29 @@ -A chatbot to help with live stream production/effects. +A chatbot to help with live stream production and effects. -# Credentials Setup: +___ -## For Twitch Credentials in twitch_cred.py +# Credentials: + +## Credentials Setup: + +Create a json based on the templates and put them into the `/credentials/` folder. +Refer to the `/credential_templates/` folder for examples. + +### For Twitch Credentials Username = `TwitchUsername` -Helix ID = `https://dev.twitch.tv/console/apps` +Helix Client ID = `https://dev.twitch.tv/console/apps` Oauth = `https://twitchapps.com/tmi/` V5 Client ID = `https://twitchtokengenerator.com/` -## For Database Credentials in db_cred.py -engine = `"mysql+mysqlconnector://root:password@localhost:3306/DatabaseName"` +### For Database Credentials +Engine = `"mysql+mysqlconnector://root:password@localhost:3306/DatabaseName"` + +## Credential Usage: + +Place json credentials in the `/credentials/` folder. +To load them, run `load_credentials()` from `Credentials_Module` in the `credentials.py` script. + +___ \ No newline at end of file diff --git a/credential_templates/credential_template_db.json b/credential_templates/credential_template_db.json new file mode 100644 index 0000000..5500814 --- /dev/null +++ b/credential_templates/credential_template_db.json @@ -0,0 +1,9 @@ +{ + "nickname": "AnythingYouWant", + "username": "", + "password": "", + "ipAddress": "", + "port": "", + "databaseName": "", + "engine": "mysql+mysqlconnector://root:password@localhost:3306/DatabaseName" +} \ No newline at end of file diff --git a/credential_templates/credential_template_discord.json b/credential_templates/credential_template_discord.json new file mode 100644 index 0000000..68038f9 --- /dev/null +++ b/credential_templates/credential_template_discord.json @@ -0,0 +1,6 @@ +{ + "username": "discord", + "helix": "secret discord", + "oauth": "token discord", + "v5_client": "I have no idea here" +} \ No newline at end of file diff --git a/credential_templates/credential_template_twitch.json b/credential_templates/credential_template_twitch.json new file mode 100644 index 0000000..c889bf2 --- /dev/null +++ b/credential_templates/credential_template_twitch.json @@ -0,0 +1,6 @@ +{ + "username": "something", + "helix": "Helix Client ID", + "oauth": "token", + "v5_client": "Client ID" +} \ No newline at end of file diff --git a/credentials.py b/credentials.py new file mode 100644 index 0000000..07b28c7 --- /dev/null +++ b/credentials.py @@ -0,0 +1,124 @@ +import json +import os +from enum import Enum + + +class Credential(Enum): + Twitch_Credential = 1 + Discord_Credential = 2 + DB_Credential = 3 + + +class Twitch_Credential(): + # Username = Twitch Username + # Helix ID = https://dev.twitch.tv/console/apps + # Oauth = https://twitchapps.com/tmi/ + # V5 Client ID = https://twitchtokengenerator.com/ + def __init__(self, username, helix, oauth, v5_client): + # super().__init__() + self.username = username + self.helix = helix + self.oauth = oauth + self.v5_client = v5_client + + +class Discord_Credential(): + # Discord Credentials explanations here. + def __init__(self, username, helix, oauth, v5_client): + # super().__init__() + # all of this is completely made up, i just wanted to make sure your file name switch worked right + self.username = username + self.helix = helix + self.oauth = oauth + self.v5_client = v5_client + +class DB_Credential(): + # engine = "mysql+mysqlconnector://root:password@localhost:3306/DatabaseName" + def __init__(self, nickname, username, password, ipAddress, port, databaseName, engine_url): + #super().__init__() + self.nickname = nickname + self.username = username + self.password = password + self.ipAddress = ipAddress + self.port = port + self.databaseName = databaseName + self.engine_url = engine_url + + def create_engine_url(self): + new_engine_url = "mysql+mysqlconnector://" + self.username + ":" + self.password + "@" + self.ipAddress + ":" + self.port + "/" + self.databaseName + self.engine_url = new_engine_url + return new_engine_url + + +class Credentials_Module(): + def __init__(self): + super().__init__() + self.Twitch_Credentials_List: list = [] + self.Discord_Credentials_List: list = [] + self.DB_Credentials_List: list = [] + + def load_credentials(self): + fileList = self.list_credential_files() + for file in fileList: + if file.lower().find("twitch") != -1: + credential_loading_function = self.credentialLoadingFunctions.get(Credential.Twitch_Credential) + output = credential_loading_function(self, file) + self.Twitch_Credentials_List.append(output) + if file.lower().find("discord") != -1: + credential_loading_function = self.credentialLoadingFunctions.get(Credential.Discord_Credential) + output = credential_loading_function(self, file) + self.Discord_Credentials_List.append(output) + if file.lower().find("db") != -1: + credential_loading_function = self.credentialLoadingFunctions.get(Credential.DB_Credential) + output = credential_loading_function(self, file) + self.DB_Credentials_List.append(output) + + def list_credential_files(self): + credentialPath = self.get_credentials_dir() + fileList: list = [] + for dirName, subdirList, fileList in os.walk(credentialPath): + break + return fileList + + # Based on similar function in tts.py + def get_credentials_dir(self): + dir = os.path.join(os.getcwd(), "credentials") # this is platform-agnostic + if not os.path.exists(dir): + os.mkdir(dir) + return dir + + def load_Twitch_Credential(self, fileName: str): + file_path = os.path.join(self.get_credentials_dir(), fileName) + f = open(file_path) + raw_json = json.loads(f.read()) + tobj = Twitch_Credential(**raw_json) + return tobj + + def load_Discord_Credential(self, fileName: str): + file_path = os.path.join(self.get_credentials_dir(), fileName) + f = open(file_path) + raw_json = json.loads(f.read()) + tobj = Discord_Credential(**raw_json) + return tobj + + def load_DB_Credential(self, fileName: str): + file_path = os.path.join(self.get_credentials_dir(), fileName) + f = open(file_path) + raw_json = json.loads(f.read()) + tobj = DB_Credential(**raw_json) + return tobj + + def find_Credential(self): + pass + + credentialLoadingFunctions = { # this is a mapping of the Credential enum to function pointers + Credential.Twitch_Credential: load_Twitch_Credential, + Credential.Discord_Credential: load_Discord_Credential, + Credential.DB_Credential: load_DB_Credential + + } + + +if __name__ == '__main__': + creds = Credentials_Module() + creds.load_credentials() diff --git a/db.py b/db.py index 253afb1..f4fe217 100644 --- a/db.py +++ b/db.py @@ -1,4 +1,6 @@ -import db_cred as db_credentials +import credentials + +import config as config import pandas as pd from sqlalchemy import create_engine @@ -7,12 +9,22 @@ from sqlalchemy import create_engine class db_module(): def __init__(self): super().__init__() + self.dbCredential: credentials.DB_Credential self.currentWorkingDB: str self.engine = None - def setup_engine(self): - self.engine = create_engine(db_credentials.engine_url) - print("Engine Created") + def setup_engine(self, credential: credentials.DB_Credential): + createEngine = True + if credential is None: + if self.dbCredential is None: + createEngine = False + else: + credential = self.dbCredential + + if createEngine: + self.engine = create_engine(credential.engine_url) + self.currentWorkingDB = credential.databaseName + print("Engine Created") def create_table(self, tableName: str = ""): pass diff --git a/db_cred.py b/db_cred.py deleted file mode 100644 index 13fc233..0000000 --- a/db_cred.py +++ /dev/null @@ -1 +0,0 @@ -engine_url = "mysql+mysqlconnector://" diff --git a/main.py b/main.py index 173bb9f..bda265c 100644 --- a/main.py +++ b/main.py @@ -4,20 +4,44 @@ import sys import time -import twitch_script_class +import twitch_script import utilities_script as utility -twitch_chat: twitch_script_class.Twitch_Module +import credentials +twitch_chat: twitch_script.Twitch_Module +credentials_manager: credentials.Credentials_Module def main(): - print("Connecting to Channels...") - global twitch_chat - twitch_chat = twitch_script_class.Twitch_Module() + global credentials_manager + print("Loading credentials...") + credentials_manager = credentials.Credentials_Module() + credentials_manager.load_credentials() + + twitch_chat = twitch_script.Twitch_Module() + + dbCert: credentials.DB_Credential + if credentials_manager.DB_Credentials_List is not None: + for cert in credentials_manager.DB_Credentials_List: + if cert.nickname == "praxis_bot": + print("DB Certificate Found: {" + cert.nickname + "}") + dbCert = cert + + twitchCert: credentials.Twitch_Credential + if credentials_manager.Twitch_Credentials_List is not None: + for cert in credentials_manager.Twitch_Credentials_List: + if cert.username == "praxis_bot": + print("Twitch Certificate Found: {" + cert.username + "}") + twitchCert = cert + + twitch_chat.db_manager.setup_engine(dbCert) + print("Loading Credential: {" + cert.username + "} into Twitch_Module") + twitch_chat.twitchCredential = twitchCert + print("Connecting to Channel: " + "thecuriousnerd") + twitch_chat.join_channel(None, "thecuriousnerd") - twitch_chat.join_channel("thecuriousnerd") # twitch_chat.send_message("activated") diff --git a/tests/test_twitch_script_class.py b/tests/test_twitch_script_class.py index 63a6f52..76b6121 100644 --- a/tests/test_twitch_script_class.py +++ b/tests/test_twitch_script_class.py @@ -4,7 +4,7 @@ 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.does not produces false positives'] +testInvalidUrls = ['this is just a sentence. With a period', 'gotta have some other stuff', 'bad punctuation. does produces false positives'] class TwitchBotTest(unittest.TestCase): diff --git a/twitch_cred.py b/twitch_cred.py deleted file mode 100644 index e5dd8d4..0000000 --- a/twitch_cred.py +++ /dev/null @@ -1,12 +0,0 @@ -# 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 = "" - -#Username = Twitch Username -#Helix ID https://dev.twitch.tv/console/apps -#Oauth https://twitchapps.com/tmi/ -#V5 Client ID https://twitchtokengenerator.com/ diff --git a/twitch_script_class.py b/twitch_script.py similarity index 93% rename from twitch_script_class.py rename to twitch_script.py index fe6cd5f..ccc5156 100644 --- a/twitch_script_class.py +++ b/twitch_script.py @@ -7,13 +7,18 @@ import twitch.chat import config as config import db import tts -import twitch_cred as twitch_credentials +import credentials class Twitch_Module(): def __init__(self): super().__init__() + self.twitchCredential: credentials.Twitch_Credential + self.dbCredential: credentials.DB_Credential + + self.db_manager: db.db_module = db.db_module() self.chat: twitch.Chat + self.tts_enabled: bool = False self.tts_whitelist_enabled: bool = False self.links_allowed: bool = True @@ -22,14 +27,16 @@ class Twitch_Module(): 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): + def join_channel(self, credential: credentials.Twitch_Credential, channel_name:str): channel_name = "#" + channel_name + if credential is None: + credential = self.twitchCredential self.chat = twitch.Chat( - channel=channel_name, - nickname=twitch_credentials.username, - oauth=twitch_credentials.oauth, - helix=twitch.Helix(twitch_credentials.helix, use_cache=True) + channel = channel_name, + nickname = credential.username, + oauth = credential.oauth, + helix = twitch.Helix(credential.helix, use_cache=True) ) self.chat.subscribe(self.twitch_chat)