from functools import wraps from irctokens import build from youtube import YouTube class Command: def __init__(self, config): self.config = config self.commands = [] def mesg(self, msg): self.util.mesg(msg) 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 # func.admin_commands=adm_cmds if not self.admin: self.err_perm() else: # return func(self) 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 # func.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 if cmd == "help" or cmd.startswith("help "): command = "help" elif cmd.startswith("echo "): command = "echo" elif cmd.startswith("w ") or cmd.startswith("weather "): command = "weather" elif cmd.startswith("me "): command = "me" elif cmd == "dbg" or cmd.startswith("dbg "): command = "dbg" elif cmd == "dbg2" or cmd.startswith("dbg2 "): command = "dbg2" elif ( "https://www.youtube.com/watch?v=" or "https://m.youtube.com/watch?v=" or "https://youtu.be/" ) in cmd or cmd.startswith("yt "): command = "yt" elif cmd.startswith("\x01") or self.is_ctcp: command = "ctcp" else: # self.mesg(cmd) return if command not in self.config.cmd.disabled: eval(f"self.{command}()") @internal @cmd def ctcp(self, prefix, cmd, pm, line, admin, mesg): """CTCP responses""" notice = self.notice ctcp = cmd[1:] if ctcp.startswith("PING"): if not ctcp.endswith("\x01"): ctcp = ctcp + "\x01" print(ctcp) self.notice(ctcp) elif ctcp.startswith("SOURCE"): self.notice("\x01SOURCE " + self.config.self.source + "\x01") elif ctcp.startswith("CLIENTINFO"): self.notice("\x01CLIENTINFO PING SOURCE\x01") @adm def quit(self, prefix, cmd, pm, line, admin, mesg): if admin and (cmd == "q" or cmd == "quit"): self.util.quit() elif is_adm and (cmd.startswith("q ") or cmd.startswith("quit ")): self.util.quit(cmd.split(" ", 1)[1]) @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""" if cmd.startswith("yt "): cmd = cmd[3:] # cmd=cmd.split()[0] urls = [ i for i in cmd.split() if i.startswith( "https://www.youtube.com/watch?v=" or "https://m.youtube.com/watch?v=" or "https://youtu.be/" ) ] # mesg(urls) for video in urls: try: a = YouTube.yt(YouTube, video) except Exception as e: a = e mesg(a) @cmd def echo(self, prefix, cmd, pm, line, admin, mesg): """simple echo command""" mesg(cmd.split(" ", 1)[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)) @cmd def weather(self, prefix, cmd, pm, line, admin, mesg): """crude weather command""" cmd = " ".join(cmd.split(" ", 1)[1:]) loc = cmd.split("?")[0].strip() mf = "m" # celsius by default if len(cmd.split("?")) >= 2: argsplit = cmd.split("?")[1].split() if "f" in argsplit or "u" in argsplit: mf = "u" # farenheit a = __import__("http.client").client.HTTPSConnection("wttr.in") a.request("GET", f"/{loc}?A&T&0&n&F&{mf}") b = a.getresponse().read().decode("utf-8") mesg(" ".join(b.split("\n")[3].strip().split(" ")[-2:])) # mesg(cmd.split(" ", 1)[1])