added basic structure and functionality
authorGeorgios Atheridis <atheridis@tutamail.com>
Tue, 22 Mar 2022 10:36:39 +0000 (12:36 +0200)
committerGeorgios Atheridis <atheridis@tutamail.com>
Tue, 22 Mar 2022 10:36:39 +0000 (12:36 +0200)
aptbot/__main__.py
aptbot/args.py [new file with mode: 0644]
aptbot/bot.py [new file with mode: 0644]

index 3339ef24c16ed92750dd0e0b5fcb46b0cb680a65..d01dfbd461758793c78b528a05d441caa165187d 100644 (file)
@@ -1,5 +1,67 @@
+import socket
+import aptbot.args
+import time
+import aptbot.bot
+import os
+import sys
+from threading import Thread
+from dotenv import load_dotenv
+
+load_dotenv()
+
+PORT = 26538
+LOCALHOST = "127.0.0.1"
+
+
+def loop(bot: aptbot.bot.Bot):
+    while True:
+        messages = bot.receive_messages()
+        for message in messages:
+            pass
+        time.sleep(0.001)
+
+
+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()
+    s = socket.socket()
+    s.bind(("", PORT))
+    s.listen(5)
+
+    while True:
+        c, addr = s.accept()
+        msg = c.recv(1024).decode()
+        bot.send_privmsg("skgyorugo", msg)
+        time.sleep(1)
+
+
+def send(acc: str):
+    s = socket.socket()
+    s.connect(("", PORT))
+    print("Socket connected")
+    s.send(acc.encode())
+    s.close()
+
+
 def main():
-    pass
+    argsv = aptbot.args.parse_arguments()
+    if argsv.enable:
+        listener()
+    if argsv.add_account:
+        send(argsv.add_account)
+    print("hi")
+
 
 if __name__ == "__main__":
     main()
diff --git a/aptbot/args.py b/aptbot/args.py
new file mode 100644 (file)
index 0000000..c292819
--- /dev/null
@@ -0,0 +1,24 @@
+import argparse
+
+
+def parse_arguments() -> argparse.Namespace:
+    arg_parser = argparse.ArgumentParser(
+        prog="aptbot",
+        description="A chat bot for twitch.tv"
+    )
+
+    arg_parser.add_argument(
+        "-a",
+        "--add-account",
+        type=str,
+        help=f"Add an account to connect with the bot"
+    )
+
+    arg_parser.add_argument(
+        "--enable",
+        default=False,
+        action="store_true",
+        help=f"Enable the bot"
+    )
+
+    return arg_parser.parse_args()
diff --git a/aptbot/bot.py b/aptbot/bot.py
new file mode 100644 (file)
index 0000000..71f59ed
--- /dev/null
@@ -0,0 +1,108 @@
+import socket
+from enum import Enum
+from dataclasses import dataclass
+from typing import Optional
+
+
+class Commands(Enum):
+    CLEARCHAT = "CLEARCHAT"
+    CLEARMSG = "CLEARMSG"
+    HOSTTARGET = "HOSTTARGET"
+    NOTICE = "NOTICE"
+    RECONNECT = "RECONNECT"
+    ROOMSTATE = "ROOMSTATE"
+    USERNOTICE = "USERNOTICE"
+    USERSTATE = "USERSTATE"
+    GLOBALUSERSTATE = "GLOBALUSERSTATE"
+    PRIVMSG = "PRIVMSG"
+    JOIN = "JOIN"
+    PART = "PART"
+
+
+@dataclass
+class Message:
+    tags: dict
+    nick: str
+    command: Optional[Commands]
+    channel: str
+    value: str
+
+
+class Bot:
+    def __init__(self, nick: str, oauth_token: str, client_id: str):
+        self.irc = socket.socket()
+        self.server = "irc.twitch.tv"
+        self.port = 6667
+        self.nick = nick
+        self.oauth_token = oauth_token
+        self.client_id = client_id
+
+    def send_command(self, command: str):
+        self.irc.send((command + "\r\n").encode())
+
+    def connect(self):
+        self.irc.connect((self.server, self.port))
+        self.send_command(f"PASS oauth:{self.oauth_token}")
+        self.send_command(f"NICK {self.nick}")
+        self.send_command(f"CAP REQ :twitch.tv/membership")
+        self.send_command(f"CAP REQ :twitch.tv/tags")
+        self.send_command(f"CAP REQ :twitch.tv/commands")
+
+    def join_channel(self, channel: str):
+        self.send_command(f"{Commands.JOIN.value} #{channel}")
+
+    def leave_channel(self, channel: str):
+        self.send_command(f"{Commands.PART.value} #{channel}")
+
+    def send_privmsg(self, channel: str, text: str):
+        self.send_command(f"{Commands.PRIVMSG.value} #{channel} :{text}")
+
+    @staticmethod
+    def parse_message(received_msg: str) -> Message:
+        message = Message({}, "", None, "", "")
+
+        value_start = received_msg.find(
+            ':',
+            received_msg.find(' ', received_msg.find(' ') + 1)
+        )
+        if value_start != -1:
+            message.value = received_msg[value_start:][1:]
+            received_msg = received_msg[:value_start - 1]
+
+        parts = received_msg.split(' ')
+
+        for part in parts:
+            if part.startswith('@'):
+                part = part[1:]
+                for tag in part.split(';'):
+                    tag = tag.split('=')
+                    try:
+                        message.tags[tag[0]] = tag[1]
+                    except IndexError:
+                        message.tags[tag[0]] = ""
+            elif part.startswith(':'):
+                part = part[1:]
+                if '!' in part:
+                    message.nick = part.split('!')[0]
+            elif part in set(command.value for command in Commands):
+                message.command = Commands(part)
+            elif part.startswith('#'):
+                part = part[1:]
+                message.channel = part
+
+        return message
+
+    def _handle_message(self, received_msg: str) -> Message:
+        if received_msg == "PING :tmi.twitch.tv":
+            self.send_command("PONG :tmi.twitch.tv")
+            return Message({}, "", None, "", "")
+        elif not received_msg:
+            return Message({}, "", None, "", "")
+        return Bot.parse_message(received_msg)
+
+    def receive_messages(self) -> list:
+        messages = []
+        received_msgs = self.irc.recv(2048).decode()
+        for received_msgs in received_msgs.split("\r\n"):
+            messages.append(self._handle_message(received_msgs))
+        return messages