From 9c345ed96b048e5f60eb8fa022e6387c04a3f90d Mon Sep 17 00:00:00 2001 From: Seaswimmer Date: Mon, 12 Aug 2024 17:39:13 -0400 Subject: [PATCH] feat(aurora): add per-type configuration options and a menu to configure them none of the options do anything yet, this is just creating the configuration keys and the menu to modify them --- aurora/aurora.py | 20 +++++++++++-- aurora/menus/types.py | 58 +++++++++++++++++++++++++++++++++++++ aurora/models/type.py | 4 +-- aurora/utilities/config.py | 10 +++++++ aurora/utilities/factory.py | 36 +++++++++++++++++++++++ 5 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 aurora/menus/types.py diff --git a/aurora/aurora.py b/aurora/aurora.py index 3e4ab35..4e5f36a 100644 --- a/aurora/aurora.py +++ b/aurora/aurora.py @@ -15,6 +15,7 @@ from math import ceil import discord from dateutil.parser import ParserError, parse from discord.ext import tasks +from menus.types import Types from redbot.core import app_commands, commands, data_manager from redbot.core.app_commands import Choice from redbot.core.bot import Red @@ -31,7 +32,7 @@ from .models.change import Change from .models.moderation import Moderation from .models.type import type_registry from .utilities.config import config, register_config -from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, overrides_embed +from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, overrides_embed, type_embed from .utilities.json import dump from .utilities.logger import logger from .utilities.moderate import moderate @@ -44,7 +45,7 @@ class Aurora(commands.Cog): This cog stores all of its data in an SQLite database.""" __author__ = ["SeaswimmerTheFsh"] - __version__ = "2.4.1" + __version__ = "2.4.2" __documentation__ = "https://seacogs.coastalcommits.com/aurora/" async def red_delete_data_for_user(self, *, requester, user_id: int): @@ -1115,6 +1116,21 @@ class Aurora(commands.Cog): msg = await ctx.send(embed=await guild_embed(ctx)) await msg.edit(view=Guild(ctx, msg, 60)) + @aurora_settings.command(name="type") + @commands.admin_or_permissions(manage_guild=True) + @commands.guild_only() + async def aurora_settings_type(self, ctx: commands.Context, moderation_type: str): + """Manage configuration options for specific moderation types. + + See [the documentation](https://seacogs.coastalcommits.com/Aurora/Types) for a list of built-in moderation types.""" + registered_type = type_registry.get(moderation_type) + if not registered_type: + types = "`, `".join(type_registry.keys()) + await ctx.send(error("`moderation_type` is not a valid moderation type.\nValid types are:\n" + types)) + return + msg = await ctx.send(embed=await type_embed(ctx, registered_type)) + await msg.edit(view=Types(ctx, msg, registered_type)) + @aurora_settings.command(name="addrole", aliases=["removerole"]) @commands.admin_or_permissions(manage_guild=True) @commands.guild_only() diff --git a/aurora/menus/types.py b/aurora/menus/types.py new file mode 100644 index 0000000..8946c28 --- /dev/null +++ b/aurora/menus/types.py @@ -0,0 +1,58 @@ +from discord import ButtonStyle, Interaction, Message, ui +from redbot.core import commands + +from ..models.type import Type +from ..utilities.config import config +from ..utilities.factory import type_embed + + +class Types(ui.View): + def __init__(self, ctx: commands.Context, message: Message, moderation_type: Type, timeout: int | None = None): + super().__init__() + self.ctx = ctx + self.message = message + self.type = moderation_type + self.timeout = timeout + + async def on_timeout(self): + await self.message.edit(view=None) + + @ui.button(label="Show in History", style=ButtonStyle.green, row=0) + async def show_in_history(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument + if not interaction.user.guild_permissions.manage_guild and not interaction.user.guild_permissions.administrator: + await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) + return + await interaction.response.defer() + current_setting = await config.custom("type", interaction.guild.id, self.type.key).show_in_history() + await config.custom("type", interaction.guild.id, self.type.key).show_in_history.set(not current_setting) + await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) + + @ui.button(label="Show Moderator", style=ButtonStyle.green, row=0) + async def show_moderator(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument + if not interaction.user.guild_permissions.manage_guild and not interaction.user.guild_permissions.administrator: + await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) + return + await interaction.response.defer() + current_setting = await config.custom("type", interaction.guild.id, self.type.key).show_moderator() + await config.custom("type", interaction.guild.id, self.type.key).show_moderator.set(not current_setting) + await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) + + @ui.button(label="Use Discord Permissions", style=ButtonStyle.green, row=0) + async def use_discord_permissions(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument + if not interaction.user.guild_permissions.manage_guild and not interaction.user.guild_permissions.administrator: + await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) + return + await interaction.response.defer() + current_setting = await config.custom("type", interaction.guild.id, self.type.key).use_discord_permissions() + await config.custom("type", interaction.guild.id, self.type.key).use_discord_permissions.set(not current_setting) + await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) + + @ui.button(label="DM Users", style=ButtonStyle.green, row=0) + async def dm_users(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument + if not interaction.user.guild_permissions.manage_guild and not interaction.user.guild_permissions.administrator: + await interaction.response.send_message("You must have the manage guild permission to change this setting.", ephemeral=True) + return + await interaction.response.defer() + current_setting = await config.custom("type", interaction.guild.id, self.type.key).dm_users() + await config.custom("type", interaction.guild.id, self.type.key).dm_users.set(not current_setting) + await interaction.message.edit(embed=await type_embed(self.ctx, self.type)) diff --git a/aurora/models/type.py b/aurora/models/type.py index a979d2b..d5cf568 100644 --- a/aurora/models/type.py +++ b/aurora/models/type.py @@ -1,12 +1,12 @@ from abc import abstractmethod -from typing import Any, List, Tuple +from typing import Any, Dict, Tuple from class_registry import AutoRegister, ClassRegistry from discord import Interaction, Member, User from discord.abc import Messageable from redbot.core import commands -type_registry: List['Type'] = ClassRegistry(attr_name='key', unique=True) +type_registry: Dict['str', 'Type'] = ClassRegistry(attr_name='key', unique=True) class Type(metaclass=AutoRegister(type_registry)): """This is a base class for moderation types. diff --git a/aurora/utilities/config.py b/aurora/utilities/config.py index 0b5e503..5fa9f19 100644 --- a/aurora/utilities/config.py +++ b/aurora/utilities/config.py @@ -27,3 +27,13 @@ def register_config(config_obj: Config): history_inline_pagesize=None, auto_evidenceformat=None, ) + + moderation_type = { + "show_in_history": bool, + "show_moderator": bool, + "use_discord_permissions": bool, + "dm_users": bool, + } + + config_obj.init_custom("type", 2) + config_obj.register_custom("type", **moderation_type) diff --git a/aurora/utilities/factory.py b/aurora/utilities/factory.py index e90af3c..dc38918 100644 --- a/aurora/utilities/factory.py +++ b/aurora/utilities/factory.py @@ -544,3 +544,39 @@ async def immune_embed(ctx: commands.Context) -> Embed: e.description += "\n\n" + immune_str return e + +async def type_embed(ctx: commands.Context, moderation_type = Type) -> Embed: + """Generates a configuration menu field value for a guild's settings.""" + + type_settings = { + "show_in_history": await config.custom("type", ctx.guild.id, moderation_type.key).show_in_history(), + "show_moderator": await config.custom("type", ctx.guild.id, moderation_type.key).show_moderator(), + "use_discord_permissions": await config.custom("type", ctx.guild.id, moderation_type.key).use_discord_permissions(), + "dm_users": await config.custom("type", ctx.guild.id, moderation_type.key).dm_users(), + } + + guild_str = [ + "- " + + bold("Show in History: ") + + get_bool_emoji(type_settings["show_in_history"]), + "- " + + bold("Show Moderator: ") + + get_bool_emoji(type_settings["show_moderator"]), + "- " + + bold("Use Discord Permissions: ") + + get_bool_emoji(type_settings["use_discord_permissions"]), + "- " + + bold("DM Users: ") + + get_bool_emoji(type_settings["dm_users"]), + ] + guild_str = "\n".join(guild_str) + + e = await _config(ctx) + e.title += ": Server Configuration" + e.description = ( + """ + Use the buttons below to manage Aurora's server configuration.\n + """ + + guild_str + ) + return e