summaryrefslogtreecommitdiff
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))