diff --git a/src/bots/Discord.py b/src/bots/Discord.py index edc57aa..c446659 100644 --- a/src/bots/Discord.py +++ b/src/bots/Discord.py @@ -76,6 +76,9 @@ async def on_message(self, message): "color": 0xcc0000 })) + if cmd["subcommands"]: + return await cmd["subcommands"].__dict__[args[1]](args[2:], message, self) + await cmd["f"](args[1:], message, self) else: @@ -153,6 +156,8 @@ async def on_interaction(self, interaction: discord.Interaction): ), "color": 0xcc0000 })) + if cmd["subcommands"]: + return await cmd["subcommands"].__dict__[interaction.options[0]["name"]](interaction.args, interaction, self) await cmd["f"](interaction.args, interaction, self) async def on_member_join(self, member): diff --git a/src/bots/cmd_handler.py b/src/bots/cmd_handler.py index fb6c0bb..c9e4635 100644 --- a/src/bots/cmd_handler.py +++ b/src/bots/cmd_handler.py @@ -18,16 +18,32 @@ commands = {} -def command(discord=False, tfm=False, whisper_command=False, aliases=None, allowed_roles=None): +def command(discord=False, tfm=False, whisper_command=False, aliases=None, allowed_roles=None, subcommands=None): def decorator(f): functools.wraps(f) - commands[f.__name__] = { "f": f, "discord": discord, "tfm": tfm, "whisper_command": whisper_command, "allowed_roles": allowed_roles } + commands[f.__name__] = { + "f": f, + "name": f.__name__, + "discord": discord, + "tfm": tfm, + "whisper_command": whisper_command, + "allowed_roles": allowed_roles, + "subcommands": subcommands + } if aliases: for alias in aliases: - commands[alias] = { "f": f, "discord": discord, "tfm": tfm, "whisper_command": whisper_command, "allowed_roles": allowed_roles } + commands[alias] = { + "f": f, + "name": f.__name__, + "discord": discord, + "tfm": tfm, + "whisper_command": whisper_command, + "allowed_roles": allowed_roles, + "subcommands": subcommands + } def wrapper(*args, **kwargs): return f(*args, **kwargs) @@ -47,7 +63,7 @@ def wrapper(*args, **kwargs): from .commands import qotd as qhandler -@command(discord = True, allowed_roles = [ data["roles"]["admin"], data["roles"]["mod"] ]) +@command(discord = True, allowed_roles = [ data["roles"]["admin"], data["roles"]["mod"] ], subcommands = qhandler) async def qotd(args, msg, client): """Question of the day @@ -55,9 +71,10 @@ async def qotd(args, msg, client): option (string): add, queue data (string): Relevant data """ - if len(args) > 0: - if hasattr(qhandler, args[0]): - await qhandler.__getattribute__(args[0])(args[1:], msg, client) + #if len(args) > 0: + # if hasattr(qhandler, args[0]): + # await qhandler.__getattribute__(args[0])(args[1:], msg, client) + pass from .commands import mod @@ -547,6 +564,33 @@ async def botw(args, msg, client): await msg.reply(embed = Embed.from_dict(embed)) +def get_cmd(data, subcommand=None): + """Helper function for `update`""" + + doc = parse_doc(data["f"]) + cmd_data = { + "name": data["name"], + "type": 1, + "description": doc.short_description, + "options": [] + } + if data["subcommands"]: + for scmd, f in data["subcommands"].__dict__.items(): + if scmd.startswith("__"): continue + # shitty implementation for subcommands I know but it should be fine for now + cmd_data["options"].append(get_cmd({ "name": scmd, "f": f, "subcommands": None }, subcommand=True)) + else: + for param in doc.params: + param_data = { + "name": param.arg_name, + "description": param.description, + "required": not param.is_optional + } + param_data["type"] = AppCommandOptionType[param.type_name][1] + cmd_data["options"].append(param_data) + return cmd_data + + @command(discord=True) async def update(args, msg, client): """Updates the application commands @@ -557,33 +601,20 @@ async def update(args, msg, client): await msg.reply("Updating...") i = 0 cmdlist = list(commands.keys()) + headers = { + "Authorization": "Bot {}".format(os.environ["DISCORD"]) + } while i < len(cmdlist): cmd = cmdlist[i] - data = commands[cmd] - doc = parse_doc(data["f"]) - cmd_data = { - "name": cmd, - "type": 1, - "description": doc.short_description, - "options": [] - } - for param in doc.params: - param_data = { - "name": param.arg_name, - "description": param.description, - "required": not param.is_optional - } - param_data["type"] = AppCommandOptionType[param.type_name][1] - cmd_data["options"].append(param_data) - headers = { - "Authorization": "Bot {}".format(os.environ["DISCORD"]) - } - r = requests.post(f"https://discord.com/api/v10/applications/{client.application_id}/guilds/{client.main_guild.id}/commands", headers=headers, json=cmd_data) + data = get_cmd(commands[cmd]) + + r = requests.post(f"https://discord.com/api/v10/applications/{client.application_id}/guilds/{client.main_guild.id}/commands", headers=headers, json=data) if r.status_code == 429: time.sleep(2) continue print(r.status_code, r.content) time.sleep(1) + i += 1 await msg.channel.send(":white_check_mark: Updated!") diff --git a/src/bots/commands/qotd.py b/src/bots/commands/qotd.py index 3a9c038..d3e89f2 100644 --- a/src/bots/commands/qotd.py +++ b/src/bots/commands/qotd.py @@ -1,4 +1,6 @@ async def queue(args, msg, client): + """Check the question queueu + """ import json from discord import Embed @@ -14,6 +16,12 @@ async def queue(args, msg, client): })) async def add(args, msg, client): + """Adds a question + + Args: + index (integer): The place to add in the queue + question (string): The question + """ if args[0].isnumeric(): client.questions["questions"].insert(int(args[0]), " ".join(args[1:])) else: @@ -23,6 +31,11 @@ async def add(args, msg, client): await msg.reply("Added the question!") async def remove(args, msg, client): + """Removes a question + + Args: + index (integer, optional): The question number to remove. Removes first question if none + """ try: client.questions["questions"].pop(int(args[0] if len(args) > 0 else "1") -1) await client.update_qotd() @@ -32,11 +45,16 @@ async def remove(args, msg, client): async def ask(args, msg, client): + """Asks the first available question in the queue + + Args: + force (boolean, optional): Whether to bypass the time limit + """ from datetime import datetime, timedelta from discord import Embed from data import data import json - force = len(args) > 0 and args[0] == "force" + force = len(args) > 0 and ("force", "true") in args[0].lower() now, lastpost = datetime.now(), datetime.fromtimestamp(client.questions["last-post"]) cooldown_over = now > (lastpost + timedelta(seconds = 1 * 60 * 60 * 24)) qotd_channel = client.get_channel(data["channels"]["qotd"]) diff --git a/src/utils.py b/src/utils.py index 2316751..364ad82 100644 --- a/src/utils.py +++ b/src/utils.py @@ -93,8 +93,10 @@ def __init__(self, interaction, client): self.reply = interaction.response.send_message self.options = interaction.data.get("options", []) self.content = [] - for option in self.options: - # todo: see how it works with mentions later - self.content.append(option["value"]) + if get(self.options, 0, None): + for option in self.options if not self.options[0].get("options") else self.options[0]["options"]: + if option.get("value") and option["value"]: + self.content.append(str(option["value"])) self.content = " ".join(self.content) + # splitting args after joining to avoid having empty string args self.args = self.content.split(" ")