feat(aurora): merged all of the changes made in the configuration rewrite into the codebase of the cog itself

This commit is contained in:
Seaswimmer 2024-01-16 14:23:45 +00:00
parent 3b8506cba8
commit 46a290aad3
Signed by untrusted user: cswimr
GPG key ID: D74DDDDF420E13DF
13 changed files with 297 additions and 372 deletions

View file

@ -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()

View file

@ -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:

View file

@ -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.")
)

View file

@ -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

View file

@ -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

View file

@ -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):

View file

@ -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):

View file

@ -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):

View file

@ -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):

View file

@ -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

View file

@ -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