Aurora Configuration Rewrite #15
13 changed files with 297 additions and 372 deletions
|
@ -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()
|
|
110
aurora/aurora.py
110
aurora/aurora.py
|
@ -21,16 +21,20 @@ from redbot.core.app_commands import Choice
|
||||||
from redbot.core.bot import Red
|
from redbot.core.bot import Red
|
||||||
from redbot.core.utils.chat_formatting import box, error, warning
|
from redbot.core.utils.chat_formatting import box, error, warning
|
||||||
|
|
||||||
from .abc import CompositeMetaClass
|
from aurora.importers.aurora import ImportAuroraView
|
||||||
from .configuration.commands import Configuration
|
from aurora.importers.galacticbot import ImportGalacticBotView
|
||||||
from .utilities.config import config, register_config
|
from aurora.menus.addrole import Addrole
|
||||||
from .utilities.database import connect, create_guild_table, fetch_case, mysql_log
|
from aurora.menus.guild import Guild
|
||||||
from .utilities.factory import case_factory, changes_factory, evidenceformat_factory, message_factory
|
from aurora.menus.immune import Immune
|
||||||
from .utilities.logger import logger
|
from aurora.menus.overrides import Overrides
|
||||||
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.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.
|
"""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.
|
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."""
|
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
|
completion_time = (time.time() - current_time) * 1000
|
||||||
logger.debug("Completed expiry loop in %sms with %s users unbanned", f"{completion_time:.6f}", global_num)
|
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.
|
"""This command converts a duration to a [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) Python object.
|
||||||
|
|
||||||
**Example usage**
|
**Example usage**
|
||||||
`[p]timedeltaconvert 1 day 15hr 82 minutes 52s`
|
`[p]timedelta 1 day 15hr 82 minutes 52s`
|
||||||
**Output**
|
**Output**
|
||||||
`1 day, 16:22:52`"""
|
`1 day, 16:22:52`"""
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -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.")
|
|
||||||
)
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -2,7 +2,7 @@ from discord import ButtonStyle, ui, Interaction
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
from redbot.core.utils.chat_formatting import error
|
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
|
from aurora.utilities.config import config
|
||||||
|
|
||||||
class Addrole(ui.View):
|
class Addrole(ui.View):
|
|
@ -1,8 +1,8 @@
|
||||||
from discord import ui, ButtonStyle, Interaction
|
from discord import ui, ButtonStyle, Interaction
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
|
|
||||||
from aurora.configuration.embed import guild
|
from aurora.utilities.factory import guild
|
||||||
from aurora.configuration.utils import create_pagesize_options
|
from aurora.utilities.utils import create_pagesize_options
|
||||||
from aurora.utilities.config import config
|
from aurora.utilities.config import config
|
||||||
|
|
||||||
class Guild(ui.View):
|
class Guild(ui.View):
|
|
@ -2,7 +2,7 @@ from discord import ButtonStyle, ui, Interaction
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
from redbot.core.utils.chat_formatting import error
|
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
|
from aurora.utilities.config import config
|
||||||
|
|
||||||
class Immune(ui.View):
|
class Immune(ui.View):
|
|
@ -1,8 +1,8 @@
|
||||||
from discord import ui, ButtonStyle, Interaction
|
from discord import ui, ButtonStyle, Interaction
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
|
|
||||||
from aurora.configuration.embed import overrides
|
from aurora.utilities.factory import overrides
|
||||||
from aurora.configuration.utils import create_pagesize_options
|
from aurora.utilities.utils import create_pagesize_options
|
||||||
from aurora.utilities.config import config
|
from aurora.utilities.config import config
|
||||||
|
|
||||||
class Overrides(ui.View):
|
class Overrides(ui.View):
|
|
@ -5,10 +5,11 @@ from datetime import datetime, timedelta
|
||||||
|
|
||||||
import humanize
|
import humanize
|
||||||
from discord import Color, Embed, Guild, Interaction, InteractionMessage, User, Member
|
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 aurora.utilities.config import config
|
||||||
from .utils import fetch_channel_dict, fetch_user_dict, get_next_case_number
|
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:
|
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']}"
|
content += f"\nReason: {case_dict['reason']}"
|
||||||
|
|
||||||
return box(content, 'prolog')
|
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
|
||||||
|
|
|
@ -4,7 +4,7 @@ import json
|
||||||
from datetime import timedelta as td
|
from datetime import timedelta as td
|
||||||
from typing import Union
|
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 discord.errors import Forbidden, NotFound
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
from redbot.core.utils.chat_formatting import error
|
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
|
minutes = (total_seconds % 3600) // 60
|
||||||
seconds = total_seconds % 60
|
seconds = total_seconds % 60
|
||||||
return f"{hours}:{minutes}:{seconds}"
|
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
|
||||||
|
|
Loading…
Reference in a new issue