diff options
Diffstat (limited to 'commands.py')
-rw-r--r-- | commands.py | 323 |
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)) |