diff --git a/plugins/commands.py b/plugins/commands.py index 3c12c99..318950e 100644 --- a/plugins/commands.py +++ b/plugins/commands.py @@ -1,15 +1,16 @@ -from src.plugin_base import PluginBase -from src.channel_manager import ChannelManager import sys +from src.channel_manager import ChannelManager +from src.plugin_base import PluginBase + + class Plugin(PluginBase): - def handle_message(self, source_nick, channel, message): message_parts = message.split() - self.channel_manager = ChannelManager() + self.channel_manager = ChannelManager() if message_parts[0] == '!hello': self.bot.ircsend(f'PRIVMSG {channel} :Hello, {source_nick}!') - + elif message_parts[0] == '!join': if len(message_parts) == 0: self.bot.ircsend(f'PRIVMSG {channel} :Please specify a channel to join') @@ -26,12 +27,11 @@ class Plugin(PluginBase): self.bot.ircsend(f'PART {message_parts[1]}') self.channel_manager.remove_channel(message_parts[1]) - elif message_parts[0] == "!quit": if len(message_parts) == 0: quit_message = 'EliteBot!' else: - quit_message = message[len(message_parts[0])+1:] + quit_message = message[len(message_parts[0]) + 1:] self.bot.ircsend(f'QUIT :{quit_message}') self.bot.ircsock.close() self.bot.connected = False @@ -44,7 +44,7 @@ class Plugin(PluginBase): else: raw_command = ' '.join(message_parts[1:]) self.bot.ircsend(raw_command) - + elif message_parts[0] == '!me': if len(message_parts) > 1: action_message = ' '.join(message_parts[1:]) @@ -56,4 +56,4 @@ class Plugin(PluginBase): if len(message_parts) > 1: self.bot.ircsend(f'PRIVMSG {channel} :Pinging {message_parts[1]}') else: - self.bot.ircsend(f'PRIVMSG {channel} :Please specify a nick to ping') \ No newline at end of file + self.bot.ircsend(f'PRIVMSG {channel} :Please specify a nick to ping') diff --git a/requirements.txt b/requirements.txt index e9405b3..d0fd917 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ colorama==0.4.6 +PyYAML==6.0.1 diff --git a/src/bot.py b/src/bot.py index 9bd8628..9e18df1 100644 --- a/src/bot.py +++ b/src/bot.py @@ -1,19 +1,22 @@ #!/usr/bin/env python3 +import importlib.util +import inspect +import json +import os import socket import ssl -import time -import json -import yaml -import inspect import sys -import os -import importlib.util +import time + +import yaml + from src.channel_manager import ChannelManager from src.logger import Logger from src.plugin_base import PluginBase from src.sasl import handle_sasl, handle_authenticate, handle_903 + class Bot: def __init__(self, config_file): self.config = self.load_config(config_file) @@ -51,11 +54,11 @@ class Bot: def load_plugins(self): self.plugins = [] - plugin_folder = "./plugins" + plugin_folder = './plugins' for filename in os.listdir(plugin_folder): if filename.endswith('.py'): filepath = os.path.join(plugin_folder, filename) - spec = importlib.util.spec_from_file_location("module.name", filepath) + spec = importlib.util.spec_from_file_location('module.name', filepath) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) for name, obj in inspect.getmembers(module): @@ -122,9 +125,10 @@ class Bot: try: self.ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if str(self.config["Connection"].get("Port"))[:1] == '+': + if str(self.config['Connection'].get('Port'))[:1] == '+': context = ssl.create_default_context() - self.ircsock = context.wrap_socket(self.ircsock, server_hostname=self.config["Connection"].get("Hostname")) + self.ircsock = context.wrap_socket(self.ircsock, + server_hostname=self.config['Connection'].get('Hostname')) port = int(self.config['Connection'].get('Port')[1:]) else: port = int(self.config['Connection'].get('Port')) @@ -135,7 +139,7 @@ class Bot: self.ircsock.connect_ex((self.config['Connection'].get('Hostname'), port)) self.ircsend(f'NICK {self.config["Connection"].get("Nick")}') self.ircsend(f'USER {self.config["Connection"].get("Ident")} * * :{self.config["Connection"].get("Name")}') - if self.config["SASL"].get("UseSASL"): + if self.config['SASL'].get('UseSASL'): self.ircsend('CAP REQ :sasl') except Exception as e: self.logger.error(f"Error establishing connection: {e}") diff --git a/src/channel_manager.py b/src/channel_manager.py index 92506d0..b65a6c1 100644 --- a/src/channel_manager.py +++ b/src/channel_manager.py @@ -4,12 +4,13 @@ import json import os from os import path + class ChannelManager: def __init__(self): self.channels = self._load_channels() def _load_channels(self): - os.makedirs("data", exist_ok=True) + os.makedirs('data', exist_ok=True) if not path.exists('data/channels.json'): with open('data/channels.json', 'w') as f: json.dump([], f) @@ -18,31 +19,31 @@ class ChannelManager: with open('data/channels.json', 'r') as f: return json.load(f) except json.JSONDecodeError as e: - print(f"Error decoding JSON: {e}") + print(f'Error decoding JSON: {e}') return [] except Exception as e: - print(f"Error loading channels: {e}") + print(f'Error loading channels: {e}') return [] def save_channel(self, channel): - channel = channel.lstrip(':') + channel = channel.lstrip(':') if channel not in self.channels: self.channels.append(channel) self._write_channels() def remove_channel(self, channel): - channel = channel.lstrip(':') + channel = channel.lstrip(':') if channel in self.channels: self.channels.remove(channel) self._write_channels() def _write_channels(self): - os.makedirs("data", exist_ok=True) + os.makedirs('data', exist_ok=True) try: with open('data/channels.json', 'w') as f: json.dump(self.channels, f) except Exception as e: - print(f"Error saving channels: {e}") + print(f'Error saving channels: {e}') def get_channels(self): return self.channels diff --git a/src/sasl.py b/src/sasl.py index edc8df4..513bf93 100644 --- a/src/sasl.py +++ b/src/sasl.py @@ -4,6 +4,7 @@ import base64 NULL_BYTE = '\x00' ENCODING = 'UTF-8' + def handle_sasl(config, ircsend): """ Handles SASL authentication by sending an AUTHENTICATE command. @@ -14,6 +15,7 @@ def handle_sasl(config, ircsend): """ ircsend('AUTHENTICATE PLAIN') + def handle_authenticate(args, config, ircsend): """ Handles the AUTHENTICATE command response. @@ -24,12 +26,15 @@ def handle_authenticate(args, config, ircsend): ircsend (function): Function to send IRC commands """ if args[0] == '+': - if "SASLNick" in config['SASL'] and "SASLPassword" in config['SASL']: - authpass = f"{config['SASL']['SASLNick']}{NULL_BYTE}{config['SASL']['SASLNick']}{NULL_BYTE}{config['SASL']['SASLPassword']}" + if 'SASLNick' in config['SASL'] and 'SASLPassword' in config['SASL']: + authpass = (f'{config["SASL"]["SASLNick"]}{NULL_BYTE}' + f'{config["SASL"]["SASLNick"]}{NULL_BYTE}' + f'{config["SASL"]["SASLPassword"]}') ap_encoded = base64.b64encode(authpass.encode(ENCODING)).decode(ENCODING) ircsend(f'AUTHENTICATE {ap_encoded}') else: - raise KeyError("SASLNICK and/or SASLPASS not found in config") + raise KeyError('SASLNICK and/or SASLPASS not found in config') + def handle_903(ircsend): """ @@ -38,4 +43,4 @@ def handle_903(ircsend): Parameters: ircsend (function): Function to send IRC commands """ - ircsend('CAP END') \ No newline at end of file + ircsend('CAP END')