From 85d7a3e4d23fbb14f9276e3e9570dd71a2cef05c Mon Sep 17 00:00:00 2001 From: jan6 Date: Mon, 4 Oct 2021 00:36:22 +0300 Subject: [PATCH] idk, allowing to disable commands, moved all except eval/exec/reload into commands module, swapped around utils' argument order to funzies, idk what else, lol --- bot.py | 44 +++++++++++--------- commands.py | 117 ++++++++++++++++++++++++++++++++++++++-------------- config.py | 7 +++- stuff.py | 60 ++++++++++++++------------- util.py | 4 +- 5 files changed, 150 insertions(+), 82 deletions(-) diff --git a/bot.py b/bot.py index 24b99db..7c1a7b5 100755 --- a/bot.py +++ b/bot.py @@ -1,31 +1,37 @@ #!/usr/bin/env python3 -import ircstates,socket,ssl +import ircstates, socket, ssl from config import * from stuff import stuff from util import Util -class bot: - server=ircstates.Server(config.server.name) - host=config.server.host - port=config.server.port - if __name__==__module__=="__main__": +class bot: + server = ircstates.Server(config.server.name) + host = config.server.host + port = config.server.port + + if __name__ == __module__ == "__main__": + @classmethod def __init__(self): - if config.server.ssl: - with socket.create_connection((self.host, self.port)) as sock_raw: - ctx=ssl.create_default_context() - with ctx.wrap_socket(sock_raw, server_hostname=self.host) as sock: - try: - util=Util(sock,config) - stuff(self,sock) - except KeyboardInterrupt: util.quit("^C") - else: - with socket.create_connection((self.host, self.port)) as sock: + if config.server.ssl: + with socket.create_connection((self.host, self.port)) as sock_raw: + ctx = ssl.create_default_context() + with ctx.wrap_socket(sock_raw, server_hostname=self.host) as sock: try: - util=Util(sock,config) - stuff(self,sock) - except KeyboardInterrupt: util.quit("^C") + util = Util(config, sock) + stuff(self, sock) + except KeyboardInterrupt: + util.quit("^C") + else: + with socket.create_connection((self.host, self.port)) as sock: + try: + util = Util(config, sock) + stuff(self, sock) + except KeyboardInterrupt: + util.quit("^C") + + print("starting bot...") bot() diff --git a/commands.py b/commands.py index a89b6df..cec1550 100644 --- a/commands.py +++ b/commands.py @@ -1,50 +1,107 @@ -from util import Util class Command: - def __init__(self,sock,config): - self.sock=sock + def __init__(self,config): self.config=config - self.util=Util(sock,config) + self.commands=[] def mesg(self,msg): self.util.mesg(msg) - def err_perm(self,level="admin"): mesg("Error: insufficient privileges, you lack {level} access") - def exec_cmd(self,command,extra=[None]): - if extra!=[None]: - eval(f"self.{command}(self.prefix,self.cmd,self.pm,self.line,self.admin,extra)") - else: - eval(f"self.{command}(self.prefix,self.cmd,self.pm,self.line,self.admin)") - def echo(self,prefix,cmd,pm,line,admin): + def err_perm(self,level="admin"): self.mesg(f"Error: insufficient privileges, you lack {level} access") + def adm(func,*args, **kwargs): + 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__) + 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): + 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__) + 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 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=="dbg" or cmd.startswith("dbg "): + command="dbg" + elif cmd=="dbg2" or cmd.startswith("dbg2 "): + command="dbg2" + else:return + if command not in self.config.cmd.disabled: + eval(f"self.{command}()") + @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 dbg2(self,prefix,cmd,pm,line,admin,mesg): + mesg(dir(self)) + @adm + def dbg(self,prefix,cmd,pm,line,admin,mesg): + """temporary debug command, subject to change A LOT"""; + mesg(dir()) + @cmd + def echo(self,prefix,cmd,pm,line,admin,mesg): """simple echo command""" - self.util.mesg(cmd.split(" ",1)[1]) - def help(self,prefix,cmd,pm,line,admin,extra): - mesg=self.mesg - prefixes="\""+"\", \"".join(extra[0])+"\"" - enabled_commands=extra[1] - admin_commands=", ".join(extra[2]) - try: topic=extra[3] + mesg(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=extra[4] + 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(enabled_commands+list(abs_topics.keys()))) + 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 Exception as e: - except (TypeError,AttributeError): + 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)) - def reload(self,prefix,cmd,pm,line,admin): - mesg=self.mesg - if admin: - mesg("reloading...") - self.util.reload() - mesg("reloaded!") - else: - err_perm() diff --git a/config.py b/config.py index fa595fe..c507808 100644 --- a/config.py +++ b/config.py @@ -23,5 +23,8 @@ class config: hostmasks=["jan6!jan6@mischievous.deity"] class cmd: prefixes=["6","'"] - enabled_commands=["help","echo"] - admin_commands=["eval","exec","quit","reload"] + #disabled commands, won't run via normal means + disabled=[] + #admin-only override, + #useful for testing broken commands which should still be normal-user accessible + admin_only=[] diff --git a/stuff.py b/stuff.py index f9450bb..59eeac0 100755 --- a/stuff.py +++ b/stuff.py @@ -5,12 +5,12 @@ from commands import Command import sys, importlib def stuff(bot,sock): config=Config - util=Util(sock,config) - command=Command(sock,config) + util=Util(config,sock) + command=Command(config) server=bot.server send=util.send - quit=util.quit - mesg=util.mesg + def mesg(msg: str,t=None):util.mesg(msg,t) +# mesg=util.mesg server_caps=[] wanted_caps=config.capabilities chan=config.server.channel #autojoin channel @@ -18,16 +18,16 @@ def stuff(bot,sock): mode="init" def configure(): config=importlib.reload(sys.modules["config"]).config - command=importlib.reload(sys.modules["commands"]).Command(sock,config) - util=Util(sock,config) + util=Util(config,sock) + command=importlib.reload(sys.modules["commands"]).Command(config) + command.util=util prefixes=config.cmd.prefixes admin_accounts=config.admin.accounts admin_users=config.admin.hostmasks - enabled_commands=config.cmd.enabled_commands - admin_commands=config.cmd.admin_commands - return command,config,util,prefixes,admin_accounts,admin_users,enabled_commands,admin_commands + admin_only=config.cmd.admin_only + return command,command.util,config,util,prefixes,admin_accounts,admin_users,admin_only - command,config,util,prefixes,admin_accounts,admin_users,enabled_commands,admin_commands=configure() + command,command.util,config,util,prefixes,admin_accounts,admin_users,admin_only=configure() send(irctokens.build("NICK", [config.self.nick]).format()) send(irctokens.build("USER", [config.self.username,"0","*",config.self.realname]).format()) @@ -90,38 +90,42 @@ def stuff(bot,sock): elif cmd.startswith(self_nick): cmd=cmd.replace(self_nick, '', 1) command.prefix=self_nick + prefix=command.prefix except IndexError: continue #skip to next command cmd="echo IndexError or something" + prefix=prefix or None cmd=cmd.strip() try:is_adm=line.tags["account"] in admin_accounts or line.source in admin_users except KeyError:is_adm=line.source in admin_users - command.line=line + command.util.target=target + command._line=line command.pm=is_pm - command.cmd=cmd + command.line=cmd command.admin=is_adm command.config=config - #handle special commands (requiring extra args 'n stuff) - if cmd=="help": - command.exec_cmd("help",[prefixes,enabled_commands,admin_commands]) - elif cmd.startswith("help "): - topic=cmd.split(" ",1)[1] - command.exec_cmd("help",[prefixes,enabled_commands,admin_commands,topic,self_nick]) - elif is_adm and (cmd=="q" or cmd=="quit"): - quit() - elif is_adm and (cmd.startswith("q ") or cmd.startswith("quit")): - quit(cmd.split(" ",1)[1]) - elif is_adm and cmd.startswith("reload"): - command,config,util,prefixes,admin_accounts,admin_users,enabled_command,admin_commands=configure() + 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 + 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.target=target mesg("reloaded") - elif cmd.startswith("eval "): + 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 "): + elif cmd.startswith("exec ") and "exec" not in config.cmd.disabled: if(is_adm): try: result=exec(cmd[len("exec "):].strip() or "None") @@ -130,6 +134,4 @@ def stuff(bot,sock): else: mesg("Error: you're not authorized to exec") #handle normal commands - - if cmd.startswith("echo "): - command.exec_cmd("echo") + else: command.preq_cmd() diff --git a/util.py b/util.py index b0ed7c9..111a0c0 100644 --- a/util.py +++ b/util.py @@ -1,6 +1,6 @@ import irctokens class Util: - def __init__(self,sock,config): + def __init__(self,config,sock): self.sock=sock self.config=config self.target="" @@ -18,5 +18,5 @@ class Util: msg=str(msg).partition("\n")[0] if len(msg)>=900: msg=msg[:900] - mesg("message too long!") + self.mesg("message too long!") self.send(irctokens.build("PRIVMSG", [t,str(msg)]).format())