From b21e0e21e50cd576a6e5cb06cad32ee100b3689c Mon Sep 17 00:00:00 2001 From: Conatum Date: Sat, 19 Mar 2022 16:17:54 +0200 Subject: [PATCH] feature (botadmin): Add `botconfig` command. --- bot/modules/sponsors/config.py | 2 + bot/modules/sysadmin/__init__.py | 1 + bot/modules/sysadmin/botconfig.py | 96 +++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 bot/modules/sysadmin/botconfig.py diff --git a/bot/modules/sponsors/config.py b/bot/modules/sponsors/config.py index f8bcde25..b4170a0f 100644 --- a/bot/modules/sponsors/config.py +++ b/bot/modules/sponsors/config.py @@ -15,6 +15,7 @@ class sponsor_prompt(String, KeyValueData, Setting): write_ward = is_owner display_name = 'sponsor_prompt' + category = 'Sponsors' desc = "Text to send after core commands to encourage checking `sponsors`." long_desc = ( "Text posted after several commands to encourage users to check the `sponsors` command. " @@ -45,6 +46,7 @@ class sponsor_message(Message, KeyValueData, Setting): write_ward = is_owner display_name = 'sponsor_message' + category = 'Sponsors' desc = "`sponsors` command response." long_desc = ( diff --git a/bot/modules/sysadmin/__init__.py b/bot/modules/sysadmin/__init__.py index 8b2cee5a..62591ad4 100644 --- a/bot/modules/sysadmin/__init__.py +++ b/bot/modules/sysadmin/__init__.py @@ -4,3 +4,4 @@ from . import exec_cmds from . import guild_log from . import status from . import blacklist +from . import botconfig diff --git a/bot/modules/sysadmin/botconfig.py b/bot/modules/sysadmin/botconfig.py new file mode 100644 index 00000000..3bccf050 --- /dev/null +++ b/bot/modules/sysadmin/botconfig.py @@ -0,0 +1,96 @@ +import difflib +import discord +from cmdClient.checks import is_owner + +from settings import UserInputError + +from utils.lib import prop_tabulate + +from .module import module + + +@module.cmd("botconfig", + desc="Update global bot configuration.", + flags=('add', 'remove'), + group="Bot Admin") +@is_owner() +async def cmd_botconfig(ctx, flags): + """ + Usage`` + {prefix}botconfig + {prefix}botconfig info + {prefix}botconfig + {prefix}botconfig + Description: + Usage directly follows the `config` command for guild configuration. + """ + # Cache and map some info for faster access + setting_displaynames = {setting.display_name.lower(): setting for setting in ctx.client.settings.settings.values()} + appid = ctx.client.conf['data_appid'] + + if not ctx.args or ctx.args.lower() in ('info', 'help'): + # Fill the setting cats + cats = {} + for setting in ctx.client.settings.settings.values(): + cat = cats.get(setting.category, []) + cat.append(setting) + cats[setting.category] = cat + + # Format the cats + sections = {} + for catname, cat in cats.items(): + catprops = { + setting.display_name: setting.get(appid).summary if not ctx.args else setting.desc + for setting in cat + } + # TODO: Add cat description here + sections[catname] = prop_tabulate(*zip(*catprops.items())) + + # Build the cat page + embed = discord.Embed( + colour=discord.Colour.orange(), + title="App Configuration" + ) + for name, section in sections.items(): + embed.add_field(name=name, value=section, inline=False) + + await ctx.reply(embed=embed) + else: + # Some args were given + parts = ctx.args.split(maxsplit=1) + + name = parts[0] + setting = setting_displaynames.get(name.lower(), None) + if setting is None: + matches = difflib.get_close_matches(name, setting_displaynames.keys(), n=2) + match = "`{}`".format('` or `'.join(matches)) if matches else None + return await ctx.error_reply( + "Couldn't find a setting called `{}`!\n" + "{}" + "Use `{}botconfig info` to see all the available settings.".format( + name, + "Maybe you meant {}?\n".format(match) if match else "", + ctx.best_prefix + ) + ) + + if len(parts) == 1 and not ctx.msg.attachments: + # config + # View config embed for provided setting + await setting.get(appid).widget(ctx, flags=flags) + else: + # config + # Attempt to set config setting + try: + parsed = await setting.parse(appid, ctx, parts[1] if len(parts) > 1 else '') + parsed.write(add_only=flags['add'], remove_only=flags['remove']) + except UserInputError as e: + await ctx.reply(embed=discord.Embed( + description="{} {}".format('❌', e.msg), + colour=discord.Colour.red() + )) + else: + await ctx.reply(embed=discord.Embed( + description="{} {}".format('✅', setting.get(appid).success_response), + colour=discord.Colour.green() + ))