From 46a290aad3ebfae58e618945dc546b937649be17 Mon Sep 17 00:00:00 2001 From: SeaswimmerTheFsh Date: Tue, 16 Jan 2024 14:23:45 +0000 Subject: [PATCH] feat(aurora): merged all of the changes made in the configuration rewrite into the codebase of the cog itself --- aurora/abc.py | 65 ------- aurora/aurora.py | 110 ++++++++++-- aurora/configuration/commands.py | 95 ----------- aurora/configuration/embed.py | 154 ----------------- aurora/configuration/menus/__init__.py | 0 aurora/configuration/utils.py | 37 ---- aurora/{configuration => menus}/__init__.py | 0 aurora/{configuration => }/menus/addrole.py | 2 +- aurora/{configuration => }/menus/guild.py | 4 +- aurora/{configuration => }/menus/immune.py | 2 +- aurora/{configuration => }/menus/overrides.py | 4 +- aurora/utilities/factory.py | 160 +++++++++++++++++- aurora/utilities/utils.py | 36 +++- 13 files changed, 297 insertions(+), 372 deletions(-) delete mode 100644 aurora/abc.py delete mode 100644 aurora/configuration/commands.py delete mode 100644 aurora/configuration/embed.py delete mode 100644 aurora/configuration/menus/__init__.py delete mode 100644 aurora/configuration/utils.py rename aurora/{configuration => menus}/__init__.py (100%) rename aurora/{configuration => }/menus/addrole.py (98%) rename aurora/{configuration => }/menus/guild.py (98%) rename aurora/{configuration => }/menus/immune.py (98%) rename aurora/{configuration => }/menus/overrides.py (97%) diff --git a/aurora/abc.py b/aurora/abc.py deleted file mode 100644 index a228aaa..0000000 --- a/aurora/abc.py +++ /dev/null @@ -1,65 +0,0 @@ -from abc import ABC, abstractmethod - -from redbot.core import commands -from redbot.core.bot import Red - -from .utilities.config import config - - -class CompositeMetaClass(type(commands.Cog), type(ABC)): - """ - This allows the metaclass used for proper type detection to - coexist with discord.py's metaclass - """ - -class Mixin(ABC): - """ - Base class for well behaved type hint detection with composite class. - - Basically, to keep developers sane when not all attributes are defined in each mixin. - """ - - def __init__(self, *_args): - super().__init__() - self.config: config - self.bot: Red - - ####################################################################### - # configuration/commands.py # - ####################################################################### - - @abstractmethod - async def aurora(self, ctx: commands.Context) -> None: - raise NotImplementedError() - - @abstractmethod - async def aurora_settings(self, ctx: commands.Context) -> None: - raise NotImplementedError() - - @abstractmethod - async def aurora_settings_overrides(self, ctx: commands.Context) -> None: - raise NotImplementedError() - - @abstractmethod - async def aurora_settings_guild(self, ctx: commands.Context) -> None: - raise NotImplementedError() - - @abstractmethod - async def aurora_settings_addrole(self, ctx: commands.Context) -> None: - raise NotImplementedError() - - @abstractmethod - async def aurora_settings_immunity(self, ctx: commands.Context) -> None: - raise NotImplementedError() - - @abstractmethod - async def aurora_import(self, ctx: commands.Context) -> None: - raise NotImplementedError() - - @abstractmethod - async def aurora_import_aurora(self, ctx: commands.Context) -> None: - raise NotImplementedError() - - @abstractmethod - async def aurora_import_galacticbot(self, ctx: commands.Context) -> None: - raise NotImplementedError() diff --git a/aurora/aurora.py b/aurora/aurora.py index d41662f..783f0a2 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -21,16 +21,20 @@ from redbot.core.app_commands import Choice from redbot.core.bot import Red from redbot.core.utils.chat_formatting import box, error, warning -from .abc import CompositeMetaClass -from .configuration.commands import Configuration -from .utilities.config import config, register_config -from .utilities.database import connect, create_guild_table, fetch_case, mysql_log -from .utilities.factory import case_factory, changes_factory, evidenceformat_factory, message_factory -from .utilities.logger import logger -from .utilities.utils import convert_timedelta_to_str, check_moddable, check_permissions, fetch_channel_dict, fetch_user_dict, generate_dict, log, send_evidenceformat +from aurora.importers.aurora import ImportAuroraView +from aurora.importers.galacticbot import ImportGalacticBotView +from aurora.menus.addrole import Addrole +from aurora.menus.guild import Guild +from aurora.menus.immune import Immune +from aurora.menus.overrides import Overrides +from aurora.utilities.config import config, register_config +from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log +from aurora.utilities.factory import case_factory, changes_factory, evidenceformat_factory, message_factory, overrides, immune, guild, addrole +from aurora.utilities.logger import logger +from aurora.utilities.utils import convert_timedelta_to_str, check_moddable, check_permissions, fetch_channel_dict, fetch_user_dict, generate_dict, log, send_evidenceformat -class Aurora(Configuration, commands.Cog, metaclass=CompositeMetaClass): # pylint: disable=too-many-ancestors +class Aurora(commands.Cog): """Aurora is a fully-featured moderation system. It is heavily inspired by GalacticBot, and is designed to be a more user-friendly alternative to Red's core Mod cogs. This cog stores all of its data in an SQLite database.""" @@ -1019,12 +1023,96 @@ class Aurora(Configuration, commands.Cog, metaclass=CompositeMetaClass): # pylin completion_time = (time.time() - current_time) * 1000 logger.debug("Completed expiry loop in %sms with %s users unbanned", f"{completion_time:.6f}", global_num) - @commands.command(aliases=["tdc"]) - async def timedeltaconvert(self, ctx: commands.Context, *, duration: str): +######################################################################################################################## +### Configuration Commands # +######################################################################################################################## + + @commands.group(autohelp=True, aliases=["moderation", "mod"]) + async def aurora(self, ctx: commands.Context): + """Settings and miscellaneous commands for Aurora.""" + + @aurora.group(autohelp=True, name="settings", aliases=["config", "options", "set"]) + async def aurora_settings(self, ctx: commands.Context): + """Configure Aurora's settings.""" + + @aurora_settings.command(name="overrides", aliases=["override", "user"]) + async def aurora_settings_overrides(self, ctx: commands.Context): + """Manage Aurora's user overriddable settings.""" + await ctx.send(embed=await overrides(ctx), view=Overrides(ctx)) + + @aurora_settings.command(name="guild", aliases=["server"]) + @commands.admin_or_permissions(manage_guild=True) + @commands.guild_only() + async def aurora_settings_guild(self, ctx: commands.Context): + """Manage Aurora's guild settings.""" + await ctx.send(embed=await guild(ctx), view=Guild(ctx)) + + @aurora_settings.command(name="addrole", aliases=["removerole"]) + @commands.admin_or_permissions(manage_guild=True) + @commands.guild_only() + async def aurora_settings_addrole(self, ctx: commands.Context): + """Manage the addrole whitelist. + + Roles added to this list are also applied to `/removerole`.""" + await ctx.send(embed=await addrole(ctx), view=Addrole(ctx)) + + @aurora_settings.command(name="immunity") + @commands.admin_or_permissions(manage_guild=True) + @commands.guild_only() + async def aurora_settings_immunity(self, ctx: commands.Context): + """Manage the immunity whitelist.""" + await ctx.send(embed=await immune(ctx), view=Immune(ctx)) + + @aurora.group(autohelp=True, name="import") + @commands.admin() + @commands.guild_only() + async def aurora_import(self, ctx: commands.Context): + """Import moderation history from other bots.""" + + @aurora_import.command(name="aurora") + @commands.admin() + async def aurora_import_aurora(self, ctx: commands.Context): + """Import moderation history from another bot using Aurora.""" + if ( + ctx.message.attachments + and ctx.message.attachments[0].content_type + == "application/json; charset=utf-8" + ): + message = await ctx.send( + warning( + "Are you sure you want to import moderations from another bot?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*" + ) + ) + await message.edit(view=ImportAuroraView(60, ctx, message)) + else: + await ctx.send(error("Please provide a valid Aurora export file.")) + + @aurora_import.command(name="galacticbot") + @commands.admin() + async def aurora_import_galacticbot(self, ctx: commands.Context): + """Import moderation history from GalacticBot.""" + if ( + ctx.message.attachments + and ctx.message.attachments[0].content_type + == "application/json; charset=utf-8" + ): + message = await ctx.send( + warning( + "Are you sure you want to import GalacticBot moderations?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*" + ) + ) + await message.edit(view=ImportGalacticBotView(60, ctx, message)) + else: + await ctx.send( + error("Please provide a valid GalacticBot moderation export file.") + ) + + @aurora.command(aliases=["tdc", 'td', 'timedeltaconvert']) + async def timedelta(self, ctx: commands.Context, *, duration: str): """This command converts a duration to a [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) Python object. **Example usage** - `[p]timedeltaconvert 1 day 15hr 82 minutes 52s` + `[p]timedelta 1 day 15hr 82 minutes 52s` **Output** `1 day, 16:22:52`""" try: diff --git a/aurora/configuration/commands.py b/aurora/configuration/commands.py deleted file mode 100644 index 08ea6d3..0000000 --- a/aurora/configuration/commands.py +++ /dev/null @@ -1,95 +0,0 @@ -from redbot.core import commands -from redbot.core.utils.chat_formatting import error, warning - -from aurora.configuration.menus.addrole import Addrole -from aurora.configuration.menus.guild import Guild -from aurora.configuration.menus.immune import Immune -from aurora.configuration.menus.overrides import Overrides -from aurora.configuration.embed import addrole, overrides, immune, guild -from aurora.abc import Mixin -from aurora.importers.aurora import ImportAuroraView -from aurora.importers.galacticbot import ImportGalacticBotView - - -class Configuration(Mixin): - """Configuration commands for Aurora.""" - - @commands.group(autohelp=True, aliases=["moderation", "mod"]) - async def aurora(self, ctx: commands.Context): - """Settings and miscellaneous commands for Aurora.""" - - @aurora.group(autohelp=True, name="settings", aliases=["config", "options", "set"]) - async def aurora_settings(self, ctx: commands.Context): - """Configure Aurora's settings.""" - - @aurora_settings.command(name="overrides", aliases=["override", "user"]) - async def aurora_settings_overrides(self, ctx: commands.Context): - """Manage Aurora's user overriddable settings.""" - await ctx.send(embed=await overrides(ctx), view=Overrides(ctx)) - - @aurora_settings.command(name="guild", aliases=["server"]) - @commands.admin_or_permissions(manage_guild=True) - @commands.guild_only() - async def aurora_settings_guild(self, ctx: commands.Context): - """Manage Aurora's guild settings.""" - await ctx.send(embed=await guild(ctx), view=Guild(ctx)) - - @aurora_settings.command(name="addrole", aliases=["removerole"]) - @commands.admin_or_permissions(manage_guild=True) - @commands.guild_only() - async def aurora_settings_addrole(self, ctx: commands.Context): - """Manage the addrole whitelist. - - Roles added to this list are also applied to `/removerole`.""" - await ctx.send(embed=await addrole(ctx), view=Addrole(ctx)) - - @aurora_settings.command(name="immunity") - @commands.admin_or_permissions(manage_guild=True) - @commands.guild_only() - async def aurora_settings_immunity(self, ctx: commands.Context): - """Manage the immunity whitelist.""" - await ctx.send(embed=await immune(ctx), view=Immune(ctx)) - - @aurora.group(autohelp=True, name="import") - @commands.admin() - @commands.guild_only() - async def aurora_import(self, ctx: commands.Context): - """Import moderation history from other bots.""" - - @aurora_import.command(name="aurora") - @commands.admin() - async def aurora_import_aurora(self, ctx: commands.Context): - """Import moderation history from another bot using Aurora.""" - if ( - ctx.message.attachments - and ctx.message.attachments[0].content_type - == "application/json; charset=utf-8" - ): - message = await ctx.send( - warning( - "Are you sure you want to import moderations from another bot?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*" - ) - ) - await message.edit(view=ImportAuroraView(60, ctx, message)) - else: - await ctx.send(error("Please provide a valid Aurora export file.")) - - @aurora_import.command(name="galacticbot") - @commands.admin() - async def aurora_import_galacticbot(self, ctx: commands.Context): - """Import moderation history from GalacticBot.""" - if ( - ctx.message.attachments - and ctx.message.attachments[0].content_type - == "application/json; charset=utf-8" - ): - message = await ctx.send( - warning( - "Are you sure you want to import GalacticBot moderations?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*" - ) - ) - await message.edit(view=ImportGalacticBotView(60, ctx, message)) - else: - await ctx.send( - error("Please provide a valid GalacticBot moderation export file.") - ) diff --git a/aurora/configuration/embed.py b/aurora/configuration/embed.py deleted file mode 100644 index 1fd78aa..0000000 --- a/aurora/configuration/embed.py +++ /dev/null @@ -1,154 +0,0 @@ -from discord import Embed -from redbot.core import commands -from redbot.core.utils.chat_formatting import bold, error, warning - -from aurora.configuration.utils import get_bool_emoji, get_pagesize_str -from aurora.utilities.config import config - -async def _core(ctx: commands.Context) -> Embed: - """Generates the core embed for configuration menus to use.""" - e = Embed( - title="Aurora Configuration Menu", - color=await ctx.embed_color() - ) - e.set_thumbnail(url=ctx.bot.user.display_avatar.url) - return e - -async def overrides(ctx: commands.Context) -> Embed: - """Generates a configuration menu embed for a user's overrides.""" - - override_settings = { - "ephemeral": await config.user(ctx.author).history_ephemeral(), - "inline": await config.user(ctx.author).history_inline(), - "inline_pagesize": await config.user(ctx.author).history_inline_pagesize(), - "pagesize": await config.user(ctx.author).history_pagesize(), - "auto_evidenceformat": await config.user(ctx.author).auto_evidenceformat() - } - - override_str = [ - '- ' + bold("Auto Evidence Format: ") + get_bool_emoji(override_settings['auto_evidenceformat']), - '- ' + bold("Ephemeral: ") + get_bool_emoji(override_settings['ephemeral']), - '- ' + bold("History Inline: ") + get_bool_emoji(override_settings['inline']), - '- ' + bold("History Inline Pagesize: ") + get_pagesize_str(override_settings['inline_pagesize']), - '- ' + bold("History Pagesize: ") + get_pagesize_str(override_settings['pagesize']), - ] - override_str = '\n'.join(override_str) - - e = await _core(ctx) - e.title += ": User Overrides" - e.description = """ - Use the buttons below to manage your user overrides. - These settings will override the relevant guild settings.\n - """ + override_str - return e - -async def guild(ctx: commands.Context) -> Embed: - """Generates a configuration menu field value for a guild's settings.""" - - guild_settings = { - "show_moderator": await config.guild(ctx.guild).show_moderator(), - "use_discord_permissions": await config.guild(ctx.guild).use_discord_permissions(), - "ignore_modlog": await config.guild(ctx.guild).ignore_modlog(), - "ignore_other_bots": await config.guild(ctx.guild).ignore_other_bots(), - "dm_users": await config.guild(ctx.guild).dm_users(), - "log_channel": await config.guild(ctx.guild).log_channel(), - "history_ephemeral": await config.guild(ctx.guild).history_ephemeral(), - "history_inline": await config.guild(ctx.guild).history_inline(), - "history_pagesize": await config.guild(ctx.guild).history_pagesize(), - "history_inline_pagesize": await config.guild(ctx.guild).history_inline_pagesize(), - "auto_evidenceformat": await config.guild(ctx.guild).auto_evidenceformat(), - } - - channel = ctx.guild.get_channel(guild_settings['log_channel']) - if channel is None: - channel = warning("Not Set") - else: - channel = channel.mention - - guild_str = [ - '- '+ bold("Show Moderator: ") + get_bool_emoji(guild_settings['show_moderator']), - '- '+ bold("Use Discord Permissions: ") + get_bool_emoji(guild_settings['use_discord_permissions']), - '- '+ bold("Ignore Modlog: ") + get_bool_emoji(guild_settings['ignore_modlog']), - '- '+ bold("Ignore Other Bots: ") + get_bool_emoji(guild_settings['ignore_other_bots']), - '- '+ bold("DM Users: ") + get_bool_emoji(guild_settings['dm_users']), - '- '+ bold("Auto Evidence Format: ") + get_bool_emoji(guild_settings['auto_evidenceformat']), - '- '+ bold("Ephemeral: ") + get_bool_emoji(guild_settings['history_ephemeral']), - '- '+ bold("History Inline: ") + get_bool_emoji(guild_settings['history_inline']), - '- '+ bold("History Pagesize: ") + get_pagesize_str(guild_settings['history_pagesize']), - '- '+ bold("History Inline Pagesize: ") + get_pagesize_str(guild_settings['history_inline_pagesize']), - '- '+ bold("Log Channel: ") + channel - ] - guild_str = '\n'.join(guild_str) - - e = await _core(ctx) - e.title += ": Server Configuration" - e.description = """ - Use the buttons below to manage Aurora's server configuration.\n - """ + guild_str - return e - -async def addrole(ctx: commands.Context) -> Embed: - """Generates a configuration menu field value for a guild's addrole whitelist.""" - - whitelist = await config.guild(ctx.guild).addrole_whitelist() - if whitelist: - whitelist = [ctx.guild.get_role(role).mention or error(f"`{role}` (Not Found)") for role in whitelist] - whitelist = '\n'.join(whitelist) - else: - whitelist = warning("No roles are on the addrole whitelist!") - - e = await _core(ctx) - e.title += ": Addrole Whitelist" - e.description = "Use the select menu below to manage this guild's addrole whitelist." - - if len(whitelist) > 4000 and len(whitelist) < 5000: - lines = whitelist.split('\n') - chunks = [] - chunk = "" - for line in lines: - if len(chunk) + len(line) > 1024: - chunks.append(chunk) - chunk = line - else: - chunk += '\n' + line if chunk else line - chunks.append(chunk) - - for chunk in chunks: - e.add_field(name="", value=chunk) - else: - e.description += '\n\n' + whitelist - - return e - -async def immune(ctx: commands.Context) -> Embed: - """Generates a configuration menu field value for a guild's immune roles.""" - - immune_roles = await config.guild(ctx.guild).immune_roles() - if immune_roles: - immune_str = [ctx.guild.get_role(role).mention or error(f"`{role}` (Not Found)") for role in immune_roles] - immune_str = '\n'.join(immune_str) - else: - immune_str = warning("No roles are set as immune roles!") - - e = await _core(ctx) - e.title += ": Immune Roles" - e.description = "Use the select menu below to manage this guild's immune roles." - - if len(immune_str) > 4000 and len(immune_str) < 5000: - lines = immune_str.split('\n') - chunks = [] - chunk = "" - for line in lines: - if len(chunk) + len(line) > 1024: - chunks.append(chunk) - chunk = line - else: - chunk += '\n' + line if chunk else line - chunks.append(chunk) - - for chunk in chunks: - e.add_field(name="", value=chunk) - else: - e.description += '\n\n' + immune_str - - return e diff --git a/aurora/configuration/menus/__init__.py b/aurora/configuration/menus/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/aurora/configuration/utils.py b/aurora/configuration/utils.py deleted file mode 100644 index fab5426..0000000 --- a/aurora/configuration/utils.py +++ /dev/null @@ -1,37 +0,0 @@ -from typing import Union - -from discord import SelectOption - -def get_bool_emoji(value: bool) -> str: - """Returns a unicode emoji based on a boolean value.""" - if value is True: - return "\N{WHITE HEAVY CHECK MARK}" - if value is False: - return "\N{NO ENTRY SIGN}" - return "\N{BLACK QUESTION MARK ORNAMENT}\N{VARIATION SELECTOR-16}" - -def get_pagesize_str(value: Union[int, None]) -> str: - """Returns a string based on a pagesize value.""" - if value is None: - return "\N{BLACK QUESTION MARK ORNAMENT}\N{VARIATION SELECTOR-16}" - return str(value) + " cases per page" - -def create_pagesize_options() -> list[SelectOption]: - """Returns a list of SelectOptions for pagesize configuration.""" - options = [] - options.append( - SelectOption( - label="Default", - value="default", - description="Reset the pagesize to the default value.", - ) - ) - for i in range(1, 21): - options.append( - SelectOption( - label=str(i), - value=str(i), - description=f"Set the pagesize to {i}.", - ) - ) - return options diff --git a/aurora/configuration/__init__.py b/aurora/menus/__init__.py similarity index 100% rename from aurora/configuration/__init__.py rename to aurora/menus/__init__.py diff --git a/aurora/configuration/menus/addrole.py b/aurora/menus/addrole.py similarity index 98% rename from aurora/configuration/menus/addrole.py rename to aurora/menus/addrole.py index a28ba9c..0e0257a 100644 --- a/aurora/configuration/menus/addrole.py +++ b/aurora/menus/addrole.py @@ -2,7 +2,7 @@ from discord import ButtonStyle, ui, Interaction from redbot.core import commands from redbot.core.utils.chat_formatting import error -from aurora.configuration.embed import addrole +from aurora.utilities.factory import addrole from aurora.utilities.config import config class Addrole(ui.View): diff --git a/aurora/configuration/menus/guild.py b/aurora/menus/guild.py similarity index 98% rename from aurora/configuration/menus/guild.py rename to aurora/menus/guild.py index fd1dfa0..7067c29 100644 --- a/aurora/configuration/menus/guild.py +++ b/aurora/menus/guild.py @@ -1,8 +1,8 @@ from discord import ui, ButtonStyle, Interaction from redbot.core import commands -from aurora.configuration.embed import guild -from aurora.configuration.utils import create_pagesize_options +from aurora.utilities.factory import guild +from aurora.utilities.utils import create_pagesize_options from aurora.utilities.config import config class Guild(ui.View): diff --git a/aurora/configuration/menus/immune.py b/aurora/menus/immune.py similarity index 98% rename from aurora/configuration/menus/immune.py rename to aurora/menus/immune.py index 49df36a..cdeaa1b 100644 --- a/aurora/configuration/menus/immune.py +++ b/aurora/menus/immune.py @@ -2,7 +2,7 @@ from discord import ButtonStyle, ui, Interaction from redbot.core import commands from redbot.core.utils.chat_formatting import error -from aurora.configuration.embed import immune +from aurora.utilities.factory import immune from aurora.utilities.config import config class Immune(ui.View): diff --git a/aurora/configuration/menus/overrides.py b/aurora/menus/overrides.py similarity index 97% rename from aurora/configuration/menus/overrides.py rename to aurora/menus/overrides.py index f7abd97..1e062a1 100644 --- a/aurora/configuration/menus/overrides.py +++ b/aurora/menus/overrides.py @@ -1,8 +1,8 @@ from discord import ui, ButtonStyle, Interaction from redbot.core import commands -from aurora.configuration.embed import overrides -from aurora.configuration.utils import create_pagesize_options +from aurora.utilities.factory import overrides +from aurora.utilities.utils import create_pagesize_options from aurora.utilities.config import config class Overrides(ui.View): diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index 02dbc99..a92c6c1 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -5,10 +5,11 @@ from datetime import datetime, timedelta import humanize from discord import Color, Embed, Guild, Interaction, InteractionMessage, User, Member -from redbot.core.utils.chat_formatting import box +from redbot.core import commands +from redbot.core.utils.chat_formatting import box, bold, error, warning -from .config import config -from .utils import fetch_channel_dict, fetch_user_dict, get_next_case_number +from aurora.utilities.config import config +from aurora.utilities.utils import fetch_channel_dict, fetch_user_dict, get_next_case_number, get_bool_emoji, get_pagesize_str async def message_factory(color: Color, guild: Guild, reason: str, moderation_type: str, moderator: Union[Member, User] = None, duration: timedelta = None, response: InteractionMessage = None) -> Embed: @@ -223,3 +224,156 @@ async def evidenceformat_factory(interaction: Interaction, case_dict: dict) -> s content += f"\nReason: {case_dict['reason']}" return box(content, 'prolog') + + +######################################################################################################################## +### Configuration Embeds # +######################################################################################################################## + +async def _core(ctx: commands.Context) -> Embed: + """Generates the core embed for configuration menus to use.""" + e = Embed( + title="Aurora Configuration Menu", + color=await ctx.embed_color() + ) + e.set_thumbnail(url=ctx.bot.user.display_avatar.url) + return e + +async def overrides(ctx: commands.Context) -> Embed: + """Generates a configuration menu embed for a user's overrides.""" + + override_settings = { + "ephemeral": await config.user(ctx.author).history_ephemeral(), + "inline": await config.user(ctx.author).history_inline(), + "inline_pagesize": await config.user(ctx.author).history_inline_pagesize(), + "pagesize": await config.user(ctx.author).history_pagesize(), + "auto_evidenceformat": await config.user(ctx.author).auto_evidenceformat() + } + + override_str = [ + '- ' + bold("Auto Evidence Format: ") + get_bool_emoji(override_settings['auto_evidenceformat']), + '- ' + bold("Ephemeral: ") + get_bool_emoji(override_settings['ephemeral']), + '- ' + bold("History Inline: ") + get_bool_emoji(override_settings['inline']), + '- ' + bold("History Inline Pagesize: ") + get_pagesize_str(override_settings['inline_pagesize']), + '- ' + bold("History Pagesize: ") + get_pagesize_str(override_settings['pagesize']), + ] + override_str = '\n'.join(override_str) + + e = await _core(ctx) + e.title += ": User Overrides" + e.description = """ + Use the buttons below to manage your user overrides. + These settings will override the relevant guild settings.\n + """ + override_str + return e + +async def guild(ctx: commands.Context) -> Embed: + """Generates a configuration menu field value for a guild's settings.""" + + guild_settings = { + "show_moderator": await config.guild(ctx.guild).show_moderator(), + "use_discord_permissions": await config.guild(ctx.guild).use_discord_permissions(), + "ignore_modlog": await config.guild(ctx.guild).ignore_modlog(), + "ignore_other_bots": await config.guild(ctx.guild).ignore_other_bots(), + "dm_users": await config.guild(ctx.guild).dm_users(), + "log_channel": await config.guild(ctx.guild).log_channel(), + "history_ephemeral": await config.guild(ctx.guild).history_ephemeral(), + "history_inline": await config.guild(ctx.guild).history_inline(), + "history_pagesize": await config.guild(ctx.guild).history_pagesize(), + "history_inline_pagesize": await config.guild(ctx.guild).history_inline_pagesize(), + "auto_evidenceformat": await config.guild(ctx.guild).auto_evidenceformat(), + } + + channel = ctx.guild.get_channel(guild_settings['log_channel']) + if channel is None: + channel = warning("Not Set") + else: + channel = channel.mention + + guild_str = [ + '- '+ bold("Show Moderator: ") + get_bool_emoji(guild_settings['show_moderator']), + '- '+ bold("Use Discord Permissions: ") + get_bool_emoji(guild_settings['use_discord_permissions']), + '- '+ bold("Ignore Modlog: ") + get_bool_emoji(guild_settings['ignore_modlog']), + '- '+ bold("Ignore Other Bots: ") + get_bool_emoji(guild_settings['ignore_other_bots']), + '- '+ bold("DM Users: ") + get_bool_emoji(guild_settings['dm_users']), + '- '+ bold("Auto Evidence Format: ") + get_bool_emoji(guild_settings['auto_evidenceformat']), + '- '+ bold("Ephemeral: ") + get_bool_emoji(guild_settings['history_ephemeral']), + '- '+ bold("History Inline: ") + get_bool_emoji(guild_settings['history_inline']), + '- '+ bold("History Pagesize: ") + get_pagesize_str(guild_settings['history_pagesize']), + '- '+ bold("History Inline Pagesize: ") + get_pagesize_str(guild_settings['history_inline_pagesize']), + '- '+ bold("Log Channel: ") + channel + ] + guild_str = '\n'.join(guild_str) + + e = await _core(ctx) + e.title += ": Server Configuration" + e.description = """ + Use the buttons below to manage Aurora's server configuration.\n + """ + guild_str + return e + +async def addrole(ctx: commands.Context) -> Embed: + """Generates a configuration menu field value for a guild's addrole whitelist.""" + + whitelist = await config.guild(ctx.guild).addrole_whitelist() + if whitelist: + whitelist = [ctx.guild.get_role(role).mention or error(f"`{role}` (Not Found)") for role in whitelist] + whitelist = '\n'.join(whitelist) + else: + whitelist = warning("No roles are on the addrole whitelist!") + + e = await _core(ctx) + e.title += ": Addrole Whitelist" + e.description = "Use the select menu below to manage this guild's addrole whitelist." + + if len(whitelist) > 4000 and len(whitelist) < 5000: + lines = whitelist.split('\n') + chunks = [] + chunk = "" + for line in lines: + if len(chunk) + len(line) > 1024: + chunks.append(chunk) + chunk = line + else: + chunk += '\n' + line if chunk else line + chunks.append(chunk) + + for chunk in chunks: + e.add_field(name="", value=chunk) + else: + e.description += '\n\n' + whitelist + + return e + +async def immune(ctx: commands.Context) -> Embed: + """Generates a configuration menu field value for a guild's immune roles.""" + + immune_roles = await config.guild(ctx.guild).immune_roles() + if immune_roles: + immune_str = [ctx.guild.get_role(role).mention or error(f"`{role}` (Not Found)") for role in immune_roles] + immune_str = '\n'.join(immune_str) + else: + immune_str = warning("No roles are set as immune roles!") + + e = await _core(ctx) + e.title += ": Immune Roles" + e.description = "Use the select menu below to manage this guild's immune roles." + + if len(immune_str) > 4000 and len(immune_str) < 5000: + lines = immune_str.split('\n') + chunks = [] + chunk = "" + for line in lines: + if len(chunk) + len(line) > 1024: + chunks.append(chunk) + chunk = line + else: + chunk += '\n' + line if chunk else line + chunks.append(chunk) + + for chunk in chunks: + e.add_field(name="", value=chunk) + else: + e.description += '\n\n' + immune_str + + return e diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index aeab27e..4555509 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -4,7 +4,7 @@ import json from datetime import timedelta as td from typing import Union -from discord import Guild, Interaction, Member, User +from discord import Guild, Interaction, Member, User, SelectOption from discord.errors import Forbidden, NotFound from redbot.core import commands from redbot.core.utils.chat_formatting import error @@ -228,3 +228,37 @@ def convert_timedelta_to_str(timedelta: td) -> str: minutes = (total_seconds % 3600) // 60 seconds = total_seconds % 60 return f"{hours}:{minutes}:{seconds}" + +def get_bool_emoji(value: bool) -> str: + """Returns a unicode emoji based on a boolean value.""" + if value is True: + return "\N{WHITE HEAVY CHECK MARK}" + if value is False: + return "\N{NO ENTRY SIGN}" + return "\N{BLACK QUESTION MARK ORNAMENT}\N{VARIATION SELECTOR-16}" + +def get_pagesize_str(value: Union[int, None]) -> str: + """Returns a string based on a pagesize value.""" + if value is None: + return "\N{BLACK QUESTION MARK ORNAMENT}\N{VARIATION SELECTOR-16}" + return str(value) + " cases per page" + +def create_pagesize_options() -> list[SelectOption]: + """Returns a list of SelectOptions for pagesize configuration.""" + options = [] + options.append( + SelectOption( + label="Default", + value="default", + description="Reset the pagesize to the default value.", + ) + ) + for i in range(1, 21): + options.append( + SelectOption( + label=str(i), + value=str(i), + description=f"Set the pagesize to {i}.", + ) + ) + return options