summary refs log tree commit diff
path: root/stuff.py
diff options
context:
space:
mode:
Diffstat (limited to 'stuff.py')
-rw-r--r--stuff.py291
1 files changed, 291 insertions, 0 deletions
diff --git a/stuff.py b/stuff.py
new file mode 100644
index 0000000..299555b
--- /dev/null
+++ b/stuff.py
@@ -0,0 +1,291 @@
+import irctokens
+from config import config as Config
+from util import Util
+from commands import Command
+from youtube import YouTube
+import sys, importlib, time
+
+
+def stuff(bot, sock):
+    config = Config
+    util = Util(config, sock)
+    command = Command(config)
+    server = bot.server
+    send = util.send
+
+    def mesg(msg: str, t=None):
+        util.mesg(msg, t)
+
+    #    mesg=util.mesg
+    server_caps = []
+    wanted_caps = config.capabilities
+    chan = config.server.channel  # main channel
+    autojoin_done = False
+    is_ctcp = False
+    is_pm = False
+    mode = "init"
+    nick_override = False
+
+    def auth(
+        nick=config.self.nick,
+        passwd=config.server.nickserv_pass,
+        auth="nickserv",
+        nickserv_auth=config.server.nickserv_auth,
+    ):
+        # TODO: handle auth that isn't nickserv
+        if auth.lower() == "nickserv":  # line.source.split("!")[0]
+            # TODO: on most network can probably do "PRIVMSG NickServ@services. :help"
+            # TODO: support actually checking the nickserv mask properly
+            if nickserv_auth:
+                nick_override = True
+                if config.server.nickserv_squery:
+                    util.send(
+                        irctokens.build(
+                            "SQUERY", ["NickServ", f"IDENTIFY {nick} {passwd}"]
+                        ).format()
+                    )
+                    util.send(
+                        irctokens.build(
+                            "SQUERY",
+                            ["NickServ", f"{config.server.nickserv_recover} {nick}"],
+                        ).format()
+                    )
+                else:
+                    util.mesg(f"IDENTIFY {nick} {passwd}", config.server.nickserv_path)
+                    util.mesg(
+                        f"{config.server.nickserv_recover} {nick}",
+                        config.server.nickserv_path,
+                    )
+        # attempt to re-nick just in case
+        send(irctokens.build("NICK", [config.self.nick]).format())
+
+    def configure():
+        config = importlib.reload(sys.modules["config"]).config
+        util = Util(config, sock)
+        command = importlib.reload(sys.modules["commands"]).Command(config)
+        command.YouTube = importlib.reload(sys.modules["youtube"]).YouTube
+        command.util = util
+        command.YouTube.util = util
+        prefixes = config.cmd.prefixes
+        admin_accounts = config.admin.accounts
+        admin_users = config.admin.hostmasks
+        admin_only = config.cmd.admin_only
+        return (
+            command,
+            command.util,
+            config,
+            util,
+            prefixes,
+            admin_accounts,
+            admin_users,
+            admin_only,
+        )
+
+    (
+        command,
+        command.util,
+        config,
+        util,
+        prefixes,
+        admin_accounts,
+        admin_users,
+        admin_only,
+    ) = configure()
+    send = util.send
+
+    send(irctokens.build("NICK", [config.self.nick]).format())
+    send(
+        irctokens.build(
+            "USER", [config.self.username, "0", "*", config.self.realname]
+        ).format()
+    )
+    while True:
+        self_nick = server.nickname
+        recv_data = sock.recv(1024)
+        recv_lines = server.recv(recv_data)
+
+        for line in recv_lines:
+            try:
+                server.parse_tokens(line)
+            except IndexError:
+                print("\x1b[31;1mNGIRCD SUCKS\x1b[0m ", line)
+                continue
+            stri = line.format()
+            for k, v in util.dict.items():
+                stri = stri.replace(k, v)
+            print(f"{time.strftime('%H:%M:%S')} < {stri}")
+            del stri
+
+            if line.command == "PING":
+                send(f"PONG :{line.params[0]}")
+
+            if mode == "init":
+                if line.command == "NOTICE" and line.source != None:
+                    if util.maskmatch(line.source, config.server.nickserv_mask):
+                        if config.server.nickserv_auth == True:
+                            auth()
+                if line.command == "433":  # 433 is ERR_NICKNAMEINUSE
+                    util.nick(config.self.nick + "_")
+                if (
+                    line.command == "376" or line.command == "422"
+                ):  # 376 is RPL_ENDOFMOTD and 422 is ERR_NOMOTD
+                    if config.server.nickserv_auth == True:
+                        auth()
+                    send(irctokens.build("CAP", ["LS", "302"]).format())
+                elif line.command == "CAP" and line.params[1] == "LS":
+                    if server_caps == []:
+                        server_caps = line.params[2].split()
+                    caps = [value for value in wanted_caps if value in server_caps]
+                    # single-send is more efficient
+                    # BUT a single invalid cap == no caps enabled at all!!!
+                    send(irctokens.build("CAP", ["REQ", " ".join(caps)]).format())
+                    # for i in caps:
+                    #    send(irctokens.build("CAP", ["REQ",i]).format())
+                    send(irctokens.build("CAP", ["END"]).format())
+                    mode = "boot"
+            elif mode == "boot":
+                send(irctokens.build("JOIN", [chan]).format())
+                mode = "normal"
+            elif mode == "normal" and autojoin_done == False:
+                try:
+                    for channel in config.server.autojoin:
+                        send("JOIN " + channel)
+                        time.sleep(0.25)
+                except Exception:
+                    True
+                autojoin_done = True
+            elif mode == "normal":
+                if line.command == "433" and nick_override != False:
+                    mesg("nick in use!", chan)
+                    util.nick(config.self.nick)
+                    nick_override = False
+                else:
+                    nick_override = False
+                if line.command == "INVITE":
+                    (
+                        send(irctokens.build("JOIN", [line.params[1]]).format())
+                        if line.params[1] not in config.server.blacklisted_channels
+                        else None
+                    )
+                elif line.command == "PRIVMSG":
+                    if line.tags == None or "batch" not in line.tags:
+                        is_pm = False
+                        is_ctcp = False
+                        target = line.params[0]
+                        if target == self_nick:
+                            target = line.source.split("!")[0]
+                            is_pm = True
+                        util.target = target
+                        command.util.target = target
+                        cmd = line.params[1]
+
+                        if cmd != "" and (
+                            is_pm
+                            or cmd.startswith(self_nick)
+                            or cmd[0] in prefixes
+                            or "https://" in cmd
+                            or "http://" in cmd
+                        ):
+                            # TODO: allow ignoring hostmasks
+                            if line.hostmask.nickname in config.cmd.ignored_nicks:
+                                continue
+                            try:
+                                # if message in a channel, remove prefixes
+                                if is_pm:
+                                    command.prefix = None
+                                else:
+                                    if cmd[0] in prefixes:
+                                        cmd = cmd.replace(cmd[0], "", 1)
+                                        command.prefix = cmd[0]
+                                    elif cmd.startswith(self_nick + ":"):
+                                        cmd = cmd.replace(self_nick + ":", "", 1)
+                                        command.prefix = self_nick
+                                    elif cmd.startswith(self_nick):
+                                        cmd = cmd.replace(self_nick, "", 1)
+                                        command.prefix = self_nick
+                                    else:
+                                        command.prefix = None
+                            except IndexError:
+                                continue  # skip to next command
+                                cmd = "echo IndexError or something"
+                            try:
+                                prefix = command.prefix or None
+                            except UnboundLocalError or AttributeError:
+                                prefix = None
+                                command.prefix = prefix
+                            cmd = cmd.strip()
+                            try:
+                                is_adm = (
+                                    line.tags["account"] in admin_accounts
+                                    or line.source in admin_users
+                                )
+                            except (
+                                KeyError,
+                                TypeError,
+                            ):  # either no account tag, or no tags at all
+                                is_adm = line.source in admin_users
+
+                            # update command module's info dynamically for line info
+                            command.util.target = target
+                            command._line = line
+                            command.is_ctcp = is_ctcp
+                            command.pm = is_pm
+                            command.line = cmd
+                            command.admin = is_adm
+                            command.config = config
+                            command.self_nick = self_nick
+                            command.prefix = prefix
+
+                            if is_adm and cmd.startswith("reload"):
+                                (
+                                    command,
+                                    command.util,
+                                    config,
+                                    util,
+                                    prefixes,
+                                    admin_accounts,
+                                    admin_users,
+                                    admin_only,
+                                ) = configure()
+                                util.target = target
+                                send = util.send
+                                command._line = line
+                                command.pm = is_pm
+                                command.line = cmd
+                                command.admin = is_adm
+                                command.config = config
+                                command.self_nick = self_nick
+                                command.prefix = prefix
+                                command.util = util
+                                command.util.target = target
+                                mesg("reloaded")
+                            elif (
+                                cmd.startswith("eval ")
+                                and "eval" not in config.cmd.disabled
+                            ):
+                                if is_adm:
+                                    try:
+                                        result = eval(
+                                            cmd[len("eval ") :].strip() or "None"
+                                        )
+                                    except Exception as e:
+                                        mesg("Error: " + str(e))
+                                else:
+                                    mesg("Error: you're not authorized to eval")
+                            elif (
+                                cmd.startswith("exec ")
+                                and "exec" not in config.cmd.disabled
+                            ):
+                                if is_adm:
+                                    try:
+                                        result = exec(
+                                            cmd[len("exec ") :].strip() or "None"
+                                        )
+                                    except Exception as e:
+                                        mesg("Error: " + str(e))
+                                else:
+                                    mesg("Error: you're not authorized to exec")
+
+                            # handle normal commands
+                            else:
+                                command.preq_cmd()