bot6/commands.py

244 lines
7.8 KiB
Python

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