summary refs log tree commit diff
path: root/commands.py
diff options
context:
space:
mode:
Diffstat (limited to 'commands.py')
-rw-r--r--commands.py323
1 files changed, 323 insertions, 0 deletions
diff --git a/commands.py b/commands.py
new file mode 100644
index 0000000..0740916
--- /dev/null
+++ b/commands.py
@@ -0,0 +1,323 @@
+from functools import wraps
+from irctokens import build
+
+import importlib
+import sys
+import random
+
+
+class Command:
+    def __init__(self, config):
+        self.config = config
+        self.commands = []
+
+    def mesg(self, msg, t=None):
+        self.util.mesg(msg, t)
+
+    def notice(self, msg):
+        self.util.notice(msg)
+
+    def action(self, msg):
+        self.util.action(msg)
+
+    def send(self, msg):
+        self.util.send(msg)
+
+    def err_perm(self, level="admin"):
+        self.mesg(f"Error: insufficient privileges, you lack {level} access")
+
+    def adm(func, *args, **kwargs):
+        """decorator for admin commands"""
+        global adm_cmds
+        try:
+            if func.__name__ not in adm_cmds and func.__name__ != "_":
+                adm_cmds.append(func.__name__)
+        except NameError:
+            adm_cmds = []
+            if func.__name__ not in adm_cmds and func.__name__ != "_":
+                adm_cmds.append(func.__name__)
+
+        @wraps(func)
+        def _(self, *args, **kwargs):
+            if func.__name__ == "help":
+                self.admin_commands = adm_cmds
+            if not self.admin:
+                self.err_perm()
+            else:
+                return func(
+                    self,
+                    self.prefix,
+                    self.line,
+                    self.pm,
+                    self._line,
+                    self.admin,
+                    self.mesg,
+                )
+
+        return _
+
+    def cmd(func, *args, **kwargs):
+        """decorator for user commands"""
+        global cmds
+        try:
+            if func.__name__ not in cmds and func.__name__ != "_":
+                cmds.append(func.__name__)
+        except NameError:
+            cmds = []
+            if func.__name__ not in cmds and func.__name__ != "_":
+                cmds.append(func.__name__)
+
+        @wraps(func)
+        def _(self, *args, **kwargs):
+            if func.__name__ == "help":
+                self.commands = cmds
+            if func.__name__ not in self.config.cmd.disabled:
+                return func(
+                    self,
+                    self.prefix,
+                    self.line,
+                    self.pm,
+                    self._line,
+                    self.admin,
+                    self.mesg,
+                )
+
+        return _
+
+    def internal(func, *args, **kwargs):
+        """decorator for commands like ctcp which are for internal use, but use normal args template"""
+        global cmds
+        if func.__name__ in cmds:
+            cmds.remove(func.__name__)
+        return func
+
+    def preq_cmd(self):  # command prequisites / triggers
+        cmd = self.line
+        needs_prefix = True
+        # self.mesg(f"attempting command: {cmd}")
+        if cmd == "help" or cmd.startswith("help "):
+            command = "help"
+        elif cmd.startswith("quit"):
+            command = "quit"
+        elif cmd.startswith("echo "):
+            command = "echo"
+        elif cmd.startswith("roll ") or cmd == "roll":
+            command = "dice"
+        elif cmd.startswith("pick ") or cmd.startswith("choose "):
+            command = "choose"
+        elif cmd.startswith("yt ") or self.YouTube.match_urls(self.YouTube, cmd) != []:
+            command = "yt"
+            needs_prefix = False
+        elif cmd.startswith("w ") or cmd.startswith("weather "):
+            command = "weather"
+        elif cmd.startswith("me "):
+            command = "me"
+        elif cmd == "crapdate" or cmd.startswith("crapdate "):
+            command = "crapdate"
+        elif cmd == "dbg" or cmd.startswith("dbg "):
+            command = "dbg"
+        elif cmd == "dbg2" or cmd.startswith("dbg2 "):
+            command = "dbg2"
+        elif cmd == "version" or cmd == "ver":
+            command = "version"
+        elif cmd.startswith("\x01") or self.is_ctcp:
+            command = "ctcp"
+        else:
+            # self.mesg(cmd)
+            return
+        if command not in self.config.cmd.disabled:
+            if needs_prefix == False:
+                eval(f"self.{command}()")
+            elif not (self.prefix == None and self.pm == False):
+                eval(f"self.{command}()")
+
+    #       else:
+    #           self.mesg("this ain't a valid commanderoonie, you twat")
+
+    def getversion(self):
+        with open(self.config.self.gitdir + ".git/logs/HEAD") as f:
+            for l in f:
+                pass
+        return l.split()[1]
+
+    @internal
+    @cmd
+    def ctcp(self, prefix, cmd, pm, line, admin, mesg):
+        """CTCP responses"""
+        notice = self.notice
+        ctcp = cmd[1:]
+        ctcp_upper = ctcp.upper()
+        if not ctcp.endswith("\x01"):
+            ctcp = ctcp + "\x01"
+        if ctcp_upper.startswith("PING"):
+            ctcp = (
+                "\x01PING"
+                + ("" if 1 == len(ctcp.split(" ")) else " ")
+                + " ".join(ctcp.split(" ")[1:])
+            )
+            print(ctcp)
+            self.notice(ctcp)
+        if ctcp_upper.startswith("SOURCE"):
+            self.notice("\x01SOURCE " + self.config.self.source + "\x01")
+        elif ctcp_upper.startswith("VERSION"):
+            self.notice(f"\x01VERSION {self.getversion()}\x01")
+        elif ctcp_upper.startswith("FINGER"):
+            self.notice(
+                f"\x01FINGER {self.config.self.nick} version {self.getversion()} ({self.config.self.source})\x01"
+            )
+        elif ctcp_upper.startswith("USERINFO"):
+            self.notice("\x01USERINFO pawky's crude IRC bot\x01")
+        elif ctcp_upper.startswith("CLIENTINFO"):
+            self.notice("\x01CLIENTINFO USERINFO PING SOURCE FINGER VERSION\x01")
+
+    @adm
+    def quit(self, prefix, cmd, pm, line, admin, mesg):
+        if admin and (cmd == "q" or cmd == "quit"):
+            self.util.quit()
+        elif admin and (cmd.startswith("q ") or cmd.startswith("quit ")):
+            self.util.quit(cmd.split(" ", 1)[1])
+
+    @adm
+    def crapdate(self, prefix, cmd, pm, line, admin, mesg):
+        """hacky and crappy update command, don't use it, lol"""
+        args = cmd.split()[1:]
+        if not args:
+            args = [""]
+        popen = __import__("os").popen
+        # mesg(args)
+        if args[0] in ["log", "list"]:
+            if len(args) == 1:
+                args = args + ["", 3]
+            elif len(args) < 3:
+                args = args + ["3"]
+            for i in (
+                popen(f"git log --pretty=oneline --abbrev-commit {args[1]}")
+                .read()
+                .split("\n", int(args[2]))
+            ):
+                mesg(i)
+        else:
+            mesg(popen("git pull").read())
+            mesg(popen("git status|tr '\\n' ' '").read())
+
+    @adm
+    def dbg(self, prefix, cmd, pm, line, admin, mesg):
+        """temporary debug command, subject to change A LOT"""
+        mesg(dir())
+
+    @cmd
+    def yt(self, prefix, cmd, pm, line, admin, mesg):
+        """youtube"""
+        YouTube = self.YouTube
+        if cmd.startswith("yt "):
+            cmd = cmd[3:]
+        try:
+            YouTube.premature_optimization = self.config.cmd.yt_premature_opt
+        except AttributeError:
+            pass
+        print(f"  YT premature_optimization={YouTube.premature_optimization}")
+        urls = YouTube.match_urls(YouTube, cmd)
+        yt_failed = False
+        for video in urls:
+            if yt_failed == True:
+                yt_failed = False
+                break
+            try:
+                a, yt_failed = YouTube.yt(YouTube, video)
+            except Exception as e:
+                a = e
+                yt_failed = True
+            mesg(a)
+
+    @cmd
+    def echo(self, prefix, cmd, pm, line, admin, mesg):
+        """simple echo command | "echo ABC..." """
+        mesg("\x7f" + cmd.split(" ", 1)[1])
+
+    @cmd
+    def choose(self, prefix, cmd, pm, line, admin, mesg):
+        """simple random choice command | "choose A B C..." """
+        mesg("I choose: " + str(random.choice(cmd.split(" ", 1)[1].split(" "))))
+
+    @cmd
+    def dice(self, prefix, cmd, pm, line, admin, mesg):
+        """simple dice command | "roll [N[d[M]]]" where N is number of dice, and M is number of faces"""
+        cmd = cmd.split(" ", 1)[1]
+        amount, faces = 1, 6
+        try:
+            amount = 0 + int(cmd.split("d", 1)[0])
+            faces = 0 + int(cmd.split("d", 1)[1])
+        except:
+            pass
+        if not str(amount).isnumeric() or amount > 100:
+            amount = 1
+        if not str(faces).isnumeric() or faces > 100:
+            faces = 6
+        mesg(
+            f"rolling {amount}d{faces}: "
+            + str([random.choice([i for i in range(faces)]) for n in range(amount)])
+        )
+
+    @cmd
+    def version(self, prefix, cmd, pm, line, admin, mesg):
+        """version"""
+        mesg(
+            f"{self.config.self.nick} version {self.getversion()} ({self.config.self.source})"
+        )
+
+    @adm
+    def dbg2(self, prefix, cmd, pm, line, admin, mesg):
+        """version"""
+        with open(self.config.self.gitdir + ".git/logs/HEAD") as f:
+            for l in f:
+                pass
+        mesg("version " + l.split()[1])
+
+    @cmd
+    def me(self, prefix, cmd, pm, line, admin, mesg):
+        """simple /me command"""
+        self.action(cmd.split(" ", 1)[1])
+
+    @cmd
+    def help(self, prefix, cmd, pm, line, admin, mesg):
+        global adm_cmds
+        global cmds
+        disabled_commands = self.config.cmd.disabled
+        admin_commands, commands = [], []
+        for i in ["exec", "eval", "reload"]:
+            if i not in adm_cmds:
+                adm_cmds.append(i)
+        for i in adm_cmds:
+            if i not in disabled_commands:
+                admin_commands.append(i)
+        for i in cmds:
+            if i not in admin_commands and i not in disabled_commands:
+                commands.append(i)
+        prefixes = '"' + '", "'.join(self.config.cmd.prefixes) + '"'
+        admin_commands = ", ".join(admin_commands)
+        try:
+            topic = cmd.split(" ", 1)[1]
+        except IndexError:
+            topic = None
+        try:
+            self_nick = self.self_nick
+        except IndexError:
+            self_nick = None
+
+        abs_topics = {"prefixes": f'available prefixes are {prefixes} or "{self_nick}"'}
+        if topic == None:
+            mesg(f"available topics: " + ", ".join(list(abs_topics.keys())))
+            mesg(f"available commands: " + ", ".join(commands))
+            if admin:
+                mesg(f"admin commands: {admin_commands}")
+        else:
+            try:
+                mesg(f"{topic}: " + eval(f"self.{topic}.__doc__"))
+            except (TypeError, AttributeError) as e:
+                #                mesg(str( e.__class__.__name__ ))
+                if topic in abs_topics:
+                    mesg(f"{topic}: " + abs_topics[topic])
+                else:
+                    mesg(f'no help available for "{topic}"...')
+            except Exception as e:
+                mesg(str(e.__class__) + " " + str(e))