diff --git a/BotResources.py b/BotResources.py index fe7e26f..56a7000 100644 --- a/BotResources.py +++ b/BotResources.py @@ -19,12 +19,15 @@ def read_config_file(): config.read('./config.ini') config_return = { - 'Bot Token': config['Bot_Info']['Token'], + 'Token': config['Bot_Info']['Token'], 'Device ID': int(config['Device']['ID']), 'Device Name': str(config['Device']['Name']), - 'Mention Group': str(config['Bot_Info']['Mention_Group']), - 'Channel ID': int(config['Bot_Info']['Channel_ID']) } + if config.has_option('Bot_Info', 'Mention_Group'): #'Mention Group' in config['Bot_Info'].items(): + config_return['Mention Group'] = str(config['Bot_Info']['Mention_Group']) + + if 'Channel_ID' in config['Bot_Info'].keys(): + config_return['Channel ID'] = int(config['Bot_Info']['Channel_ID']) print("Found config options:") for key in config_return.keys(): @@ -36,7 +39,7 @@ def read_config_file(): def write_config_file(**kwargs): config = configparser.SafeConfigParser() - if not kwargs['init'] and exists('./config.ini'): + if 'init' not in kwargs.keys() and exists('./config.ini'): config.read('./config.ini') if not config.has_section('Bot_Info'): @@ -47,29 +50,32 @@ def write_config_file(**kwargs): if 'token' in kwargs.keys(): config['Bot_Info']['Token'] = str(kwargs['token']) - elif kwargs['init']: + elif 'init' in kwargs.keys(): config['Bot_Info']['Token'] = str(get_user_token()) if 'device_id' in kwargs.keys() or 'device_name' in kwargs.keys(): config['Device']['ID'] = str(kwargs['device_id']) config['Device']['Name'] = str(kwargs['device_name']) - elif kwargs['init']: + elif 'init' in kwargs.keys(): device_id, device_name = get_user_device_selection() config['Device']['ID'] = str(device_id) config['Device']['Name'] = str(device_name) if 'mention_group' in kwargs.keys(): config['Bot_Info']['Mention_Group'] = str(kwargs['mention_group']) - elif kwargs['init']: + elif 'init' in kwargs.keys(): config['Bot_Info']['Mention_Group'] = str(get_user_mention_group()) if 'channel_id' in kwargs.keys(): config['Bot_Info']['Channel_ID'] = str(kwargs['channel_id']) - elif kwargs['init']: + elif 'init' in kwargs.keys(): config['Bot_Info']['Channel_ID'] = str(get_user_mention_channel_id()) - with open('./config.ini', 'w') as config_file: - config.write(config_file) + try: + with open('./config.ini', 'w') as config_file: + config.write(config_file) + except Exception as e: + print(e) print("Config Saved") diff --git a/README.md b/README.md index 6bbab03..da65298 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ To change the audio source, simply delete the ```config.ini``` that was generate It will re-do the setup and allow you to select a new device. ### To-Do +- [ ] <*Bug*> Update GUI to allow stopping of bot while GUI stays open - [ ] Add method for user to change audio device without redoing entire config file - [ ] Interact with soapysdr directly from the bot - [ ] Allow chat interaction with soapysdr diff --git a/bot.py b/bot.py index 43f5b61..43a030e 100644 --- a/bot.py +++ b/bot.py @@ -24,6 +24,10 @@ class Bot(commands.Bot): def start_bot(self): self.run(self.BOT_TOKEN) + async def stop_bot(self): + await self.close() + return + def add_commands(self): @self.command(help="Use this to test if the bot is alive", brief="Sends a 'pong' in response") async def ping(ctx): diff --git a/main.py b/main.py index b619547..92d6e0c 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,14 @@ +import sys import os +import threading import time import bot -from BotResources import check_if_config_exists, write_config_file, read_config_file +import asyncio +from os.path import exists +from BotResources import check_if_config_exists, write_config_file, read_config_file, get_device_list +from PyQt6 import QtWidgets, QtGui +from PyQt6.QtCore import QObject, pyqtSignal, QThread +from PyQt6.QtWidgets import QMainWindow, QApplication # Jorn #token = 'OTE1MDY0OTk2OTk0NjMzNzI5.YaWKsA.Y9yaCGg_VXRL_qQVbs05vo7gSAc' @@ -11,6 +18,287 @@ from BotResources import check_if_config_exists, write_config_file, read_config_ #name = "VoiceMeeter Output" +class CreateConfigFile(): + def __init__(self, **kwargs): + write_config_file(**kwargs) + +class BotWorker(threading.Thread): + def __init__(self, config): + super(BotWorker, self).__init__() + self.config = config + + self.discord_bot_client = bot.Bot(Token=self.config['Token'], Device_ID=self.config['Device ID'], + Device_Name=self.config['Device Name'], + Mention_Group=self.config['Mention Group'], Channel_ID=self.config['Channel ID']) + + print(f"Verifying audio device:\t{self.config['Device Name']}") + + if not self.discord_bot_client.check_device(): + raise BotDeviceNotFound(self.config['Device Name']) + + def run(self): + print("Bot started!") + self.discord_bot_client.start_bot() + + async def stop_bot(self): + print("Stopping Bot") + await self.discord_bot_client.stop_bot() + print("ASD") + +class mainWindow(QMainWindow): + def __init__(self): + super(mainWindow, self).__init__() + print('Checking config file...') + if check_if_config_exists(): + self.config = read_config_file() + else: + self.config = None + windowDimensions, uiInformation = self.createInitVars() + self.windowDimensions = windowDimensions + self.uiInformation = uiInformation + self.device_list = get_device_list() + + self.bot_thread = None + + ### UI Init + self.labelDevice = QtWidgets.QLabel(self) + self.contextEditMenu = QtWidgets.QMenu("&Edit", self) + self.contextFileMenu = QtWidgets.QMenu("&File", self) + self.btn1 = QtWidgets.QPushButton(self) + self.btn2 = QtWidgets.QPushButton(self) + self.btn3 = QtWidgets.QPushButton(self) + self.labelTitle = QtWidgets.QLabel(self) + self.labelToken = QtWidgets.QLabel(self) + self.labelMention_Group = QtWidgets.QLabel(self) + self.labelChannel_ID = QtWidgets.QLabel(self) + self.lineToken = QtWidgets.QLineEdit(self) + self.lineMention_Group = QtWidgets.QLineEdit(self) + self.lineChannel_ID = QtWidgets.QLineEdit(self) + self.comboDevice = QtWidgets.QComboBox(self) + self.contextMenuBar = self.menuBar() + + self.createUI() + + def createUI(self): + # Load Icon if one exists + if exists('./icon.png'): + self.setWindowIcon(QtGui.QIcon('./icon.png')) + + # Loading text and UI variables + buttons = self.uiInformation['buttons'] + labels = self.uiInformation['labels'] + + # Button 1 - Connect Bot + self.btn1.setText(buttons['btn1']['Text']) + self.btn1.clicked.connect(self.btn1Clicked) + self.btn1.move(self.windowDimensions['Width'] - 220, self.windowDimensions['Height'] - 40) + + # Button 2 - Disconnect Bot + self.btn2.setText(buttons['btn2']['Text']) + self.btn2.setEnabled(False) + self.btn2.clicked.connect(self.btn2Clicked) + self.btn2.move(self.windowDimensions['Width'] - 110, self.windowDimensions['Height'] - 40) + + # Button 3 - Save Config + self.btn3.setText(buttons['btn3']['Text']) + self.btn3.clicked.connect(self.btn3Clicked) + self.btn3.move(15, self.windowDimensions['Height'] - 40) + + ### Label Init + + # Title + self.labelTitle.setText(labels['lblTitle']['Text']) + self.labelTitle.move(15, 30) + self.labelTitle.adjustSize() + + # Token + self.labelToken.setText(labels['lblToken']['Text']) + self.labelToken.move(15, 70) + + # Device + self.labelDevice.setText(labels['lblDevice']['Text']) + self.labelDevice.move(15, 190) + + # Mention Group + self.labelMention_Group.setText(str(labels['lblMention_Group']['Text'])) + self.labelMention_Group.move(15, 150) + self.labelMention_Group.adjustSize() + + # Channel ID + self.labelChannel_ID.setText(str(labels['lblChannel_ID']['Text'])) + self.labelChannel_ID.move(15, 110) + self.labelChannel_ID.adjustSize() + + ### Line Edit Init + + # Token + self.lineToken.move(150, 75) + self.lineToken.resize(420, 28) + if self.config: + if 'Token' in self.config.keys(): + self.lineToken.setText(self.config['Token']) + + # Channel ID + self.lineChannel_ID.move(150, 115) + self.lineChannel_ID.resize(420, 28) + if self.config: + if 'Channel ID' in self.config.keys(): + self.lineChannel_ID.setText(str(self.config['Channel ID'])) + + # Mention Group + self.lineMention_Group.move(150, 155) + self.lineMention_Group.resize(420, 28) + if self.config: + if 'Mention Group' in self.config.keys(): + self.lineMention_Group.setText(self.config['Mention Group']) + + + # Device + for device, dev_id in self.device_list: + self.comboDevice.addItem(device) + self.comboDevice.move(150, 195) + self.comboDevice.resize(420, 28) + if self.config: + if 'Device Name' in self.config.keys(): + self.comboDevice.setCurrentText(self.config['Device Name']) + + ### Window Setup + self.setGeometry(self.windowDimensions['Xpos'], self.windowDimensions['Ypos'], self.windowDimensions['Width'], + self.windowDimensions['Height']) + self.setFixedSize(self.windowDimensions['Width'], self.windowDimensions['Height']) + self.setWindowTitle(self.uiInformation['Title']) + + # Creating file menu + self.contextMenuBar.addMenu(self.contextFileMenu) + + # Creating edit menu + self.contextMenuBar.addMenu(self.contextEditMenu) + + self.show() + + def btn1Clicked(self): + if not self.config: + if len(self.lineToken.text()) == 59 and self.comboDevice.currentText() and len( + str(self.lineChannel_ID.text())) == len( + str("918029426397184000")) and self.lineMention_Group.text(): + self.update_config() + CreateConfigFile(token=str(self.lineToken.text()), device_name=self.config['Device Name'], + device_id=self.config['Device ID'], channel_id=self.lineChannel_ID.text(), + mention_group=self.lineMention_Group.text()) + self.config = read_config_file() + try: + clearance = 0 + if self.update_config(): + clearance += 1 + + if len(self.lineToken.text()) == 59: + clearance += 2 + + if clearance == 3: + self.bot_thread = BotWorker(self.config) + self.bot_thread.daemon = True + self.bot_thread.start() + + elif clearance < 3: + raise Exception("Error in ID or Device") + except Exception as e: + print(e) + + def btn2Clicked(self): + try: + asyncio.run(self.bot_thread.stop_bot()) + self.bot_thread = BotWorker(self.config) + except Exception as e: + print(e) + return + + def btn3Clicked(self): + print(len(self.lineToken.text())) + print(len(str(self.lineChannel_ID.text()))) + print(self.comboDevice.currentText()) + if len(self.lineToken.text()) == 59 and self.comboDevice.currentText() and len( + str(self.lineChannel_ID.text())) == len( + str("918029426397184000")) and self.lineMention_Group.text(): + print('saving.....') + self.update_config() + CreateConfigFile(token=str(self.lineToken.text()), device_name=self.config['Device Name'], + device_id=self.config['Device ID'], channel_id=self.lineChannel_ID.text(), mention_group=self.lineMention_Group.text()) + self.config = read_config_file() + print("Saved config") + return + + def update_config(self): + if not self.config: + self.config = {} + for device, device_id in get_device_list(): + if device == self.comboDevice.currentText(): + self.config['Device ID'] = device_id + self.config['Device Name'] = device + return True + return False + + def createInitVars(self): + windowDimensions = \ + { + 'Xpos': 400, + 'Ypos': 300, + 'Width': 600, + 'Height': 325 + } + + uiInformation = \ + { + 'Title': "Simple Step Time Tracking", + 'buttons': + { + 'btn1': + { + 'Text': "Connect Bot" + }, + 'btn2': + { + 'Text': "Disconnect Bot" + }, + 'btn3': + { + 'Text': "Save Config" + } + }, + + 'labels': + { + 'lblTitle': + { + 'Text': "Please enter the fields below and click Connect!" + }, + 'lblToken': + { + 'Text': "Bot Token:" + }, + 'lblChannel_ID': + { + 'Text': "Default Text Channel ID:" + }, + 'lblMention_Group': + { + 'Text': "Default Mention Group:" + }, + 'lblDevice': + { + 'Text': "Input Device:" + }, + 'lblActivity': + { + 'Text': "Activitiy" + }, + 'lblDescription': + { + 'Text': "Description" + } + } + } + + return windowDimensions, uiInformation class BotDeviceNotFound(Exception): def __init__(self, device): @@ -23,26 +311,13 @@ class BotDeviceNotFound(Exception): def main(): - print('Checking config file...') - if not check_if_config_exists(): - print("No config file exists, please enter this information now") - write_config_file(init=True) - - config = read_config_file() - print('Starting Bot...') - - discord_bot_client = bot.Bot(Token=config['Bot Token'], Device_ID=config['Device ID'], Device_Name=config['Device Name'], - Mention_Group=config['Mention Group'], Channel_ID=config['Channel ID']) - - print(f"Verifying audio device:\t{config['Device Name']}") - - if not discord_bot_client.check_device(): - raise BotDeviceNotFound(config['Device Name']) - - print("Bot started!") - - discord_bot_client.start_bot() + try: + app = QApplication(sys.argv) + window = mainWindow() + sys.exit(app.exec()) + except Exception as e: + print(e) if __name__ == '__main__': @@ -51,8 +326,10 @@ if __name__ == '__main__': while True: try: main() - except BotDeviceNotFound: + except (BotDeviceNotFound, Exception) as e: + print(e) print("Restarting...") time.sleep(2) - except KeyboardInterrupt: + except (KeyboardInterrupt, Exception) as e: + print(e) print("Exiting...")