From 6039e720790dc00ad2d4edcc1b089cbb31fd2f16 Mon Sep 17 00:00:00 2001 From: Georgios Atheridis Date: Tue, 22 Mar 2022 22:12:26 +0200 Subject: [PATCH] added fundamental message and channel interpreter --- aptbot/__main__.py | 120 ++++++++++++++++++++++++++++++++++++++------- aptbot/args.py | 14 ++++++ aptbot/bot.py | 28 ++++++++++- 3 files changed, 143 insertions(+), 19 deletions(-) diff --git a/aptbot/__main__.py b/aptbot/__main__.py index d01dfbd..9227412 100644 --- a/aptbot/__main__.py +++ b/aptbot/__main__.py @@ -4,9 +4,22 @@ import time import aptbot.bot import os import sys +import importlib +import importlib.util from threading import Thread from dotenv import load_dotenv + +if "XDG_CONFIG_HOME" in os.environ: + CONFIG_HOME = os.environ["XDG_CONFIG_HOME"] +elif "APPDATA" in os.environ: + CONFIG_HOME = os.environ["APPDATA"] +else: + CONFIG_HOME = os.path.join(os.environ["HOME"], ".config") + +CONFIG_PATH = os.path.join(CONFIG_HOME, f"aptbot") + + load_dotenv() PORT = 26538 @@ -17,50 +30,123 @@ def loop(bot: aptbot.bot.Bot): while True: messages = bot.receive_messages() for message in messages: - pass + if message.channel: + account_path = os.path.join(CONFIG_PATH, f"{message.channel}") + module_path = os.path.join( + account_path, f"message_interpreter.py") + spec = importlib.util.spec_from_file_location( + "message_interpreter", + module_path, + ) + if spec and spec.loader: + foo = importlib.util.module_from_spec(spec) + spec.loader.exec_module(foo) + method = Thread(target=foo.main, args=(bot, message, )) + method.daemon = True + method.start() + # foo.main(bot, message) + print(message) time.sleep(0.001) +def initialize(bot: aptbot.bot.Bot): + channels = os.listdir(CONFIG_PATH) + for channel in channels: + bot.join_channel(channel) + + def listener(): NICK = os.getenv("APTBOT_NICK") OAUTH = os.getenv("APTBOT_OAUTH") CLIENT_ID = os.getenv("APTBOT_CLIENT_ID") - print(NICK) - print(OAUTH) - print(CLIENT_ID) if NICK and OAUTH and CLIENT_ID: bot = aptbot.bot.Bot(NICK, OAUTH, CLIENT_ID) else: sys.exit(1) bot.connect() - bot.join_channel("skgyorugo") - Thread(target=loop, args=(bot,)).start() + message_loop = Thread(target=loop, args=(bot,)) + message_loop.daemon = True + message_loop.start() s = socket.socket() - s.bind(("", PORT)) + s.bind((LOCALHOST, PORT)) s.listen(5) + initialize(bot) while True: - c, addr = s.accept() + c, _ = s.accept() msg = c.recv(1024).decode() - bot.send_privmsg("skgyorugo", msg) + msg = msg.split("===") + try: + command = msg[0] + channel = msg[1] + msg = msg[2] + except IndexError: + pass + else: + if "JOIN" in command: + bot.join_channel(channel) + elif "SEND" in command: + bot.send_privmsg(channel, msg) + elif "KILL" in command: + sys.exit() time.sleep(1) -def send(acc: str): - s = socket.socket() - s.connect(("", PORT)) - print("Socket connected") - s.send(acc.encode()) - s.close() +def send(func,): + def inner(*args, **kwargs): + s = socket.socket() + s.connect((LOCALHOST, PORT)) + func(s, *args, **kwargs) + s.close() + return inner + + +def add_account(s: socket.socket, acc: str): + account_path = os.path.join(CONFIG_PATH, f"{acc}") + + os.makedirs(account_path, exist_ok=True) + + f = open(os.path.join(account_path, "message_interpreter.py"), "a") + f.write("""from aptbot.bot import Bot, Message, Commands +def main(bot, message: Message): + pass""") + f.close() + + command = "JOIN" + channel = acc + msg = "" + s.send(bytes(f"{command}==={channel}==={msg}", "utf-8")) + + +def send_msg(s: socket.socket, msg: str): + command = "SEND" + channel = "skgyorugo" + msg = msg + s.send(bytes(f"{command}==={channel}==={msg}", "utf-8")) + + +def disable(s: socket.socket): + command = "KILL" + channel = "" + msg = "" + s.send(bytes(f"{command}==={channel}==={msg}", "utf-8")) def main(): argsv = aptbot.args.parse_arguments() if argsv.enable: listener() + + s = socket.socket() + s.connect((LOCALHOST, PORT)) + if argsv.add_account: - send(argsv.add_account) - print("hi") + add_account(s, argsv.add_account) + if argsv.send_message: + send_msg(s, argsv.send_message) + if argsv.disable: + disable(s) + s.close() if __name__ == "__main__": diff --git a/aptbot/args.py b/aptbot/args.py index c292819..78f5f51 100644 --- a/aptbot/args.py +++ b/aptbot/args.py @@ -14,6 +14,13 @@ def parse_arguments() -> argparse.Namespace: help=f"Add an account to connect with the bot" ) + arg_parser.add_argument( + "-s", + "--send-message", + type=str, + help=f"Send a message to skgyorugo" + ) + arg_parser.add_argument( "--enable", default=False, @@ -21,4 +28,11 @@ def parse_arguments() -> argparse.Namespace: help=f"Enable the bot" ) + arg_parser.add_argument( + "--disable", + default=False, + action="store_true", + help=f"Disable the bot" + ) + return arg_parser.parse_args() diff --git a/aptbot/bot.py b/aptbot/bot.py index 71f59ed..3c609a0 100644 --- a/aptbot/bot.py +++ b/aptbot/bot.py @@ -1,4 +1,6 @@ import socket +import time +import sys from enum import Enum from dataclasses import dataclass from typing import Optional @@ -36,8 +38,10 @@ class Bot: self.nick = nick self.oauth_token = oauth_token self.client_id = client_id + self.connected_channels = [] def send_command(self, command: str): + print(f"< {command}") self.irc.send((command + "\r\n").encode()) def connect(self): @@ -50,9 +54,15 @@ class Bot: def join_channel(self, channel: str): self.send_command(f"{Commands.JOIN.value} #{channel}") + self.connected_channels.append(channel) + + def join_channels(self, channels: list[str]): + for channel in channels: + self.join_channel(channel) def leave_channel(self, channel: str): self.send_command(f"{Commands.PART.value} #{channel}") + self.connected_channels.remove(channel) def send_privmsg(self, channel: str, text: str): self.send_command(f"{Commands.PRIVMSG.value} #{channel} :{text}") @@ -100,9 +110,23 @@ class Bot: return Message({}, "", None, "", "") return Bot.parse_message(received_msg) - def receive_messages(self) -> list: + def receive_messages(self) -> list[Message]: messages = [] - received_msgs = self.irc.recv(2048).decode() + i = 0 + while i < 5: + try: + received_msgs = self.irc.recv(2048).decode() + except ConnectionResetError as e: + print(f"There was an error connecting with error {e}") + print("Trying to connect again") + time.sleep(2**i) + self.connect() + self.join_channels(self.connected_channels) + i += 1 + else: + break + else: + sys.exit(1) for received_msgs in received_msgs.split("\r\n"): messages.append(self._handle_message(received_msgs)) return messages -- 2.30.2