feat(aurora): boilerplate for all currently added moderation types
Some checks failed
Actions / Build Documentation (MkDocs) (pull_request) Failing after 26s
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 40s

This commit is contained in:
Seaswimmer 2024-07-06 13:03:59 -04:00
parent a05e957dde
commit 8f0425456c
Signed by: cswimr
GPG key ID: 3813315477F26F82
4 changed files with 201 additions and 21 deletions

View file

@ -1,5 +1,8 @@
from discord import File, Guild, Member, User
from math import ceil
from discord import File, Guild, Member, TextChannel, User
from discord.abc import Messageable
from discord.errors import HTTPException, NotFound
from redbot.core import app_commands, commands
from redbot.core.bot import Red
@ -19,6 +22,86 @@ def get_icon(bot: Red) -> File:
return get_footer_image(cog)
raise ValueError("Aurora cog not found. How was this managed?")
@type_registry.register(key="note")
class Note(Type):
key="note"
string="note"
verb="noted"
@type_registry.register(key="warn")
class Warn(Type):
key="warn"
string="warn"
verb="warned"
@type_registry.register(key="addrole")
class AddRole(Type):
key="addrole"
string="addrole"
verb="added a role to"
@type_registry.register(key="removerole")
class RemoveRole(Type):
key="removerole"
string="removerole"
verb="removed a role from"
@type_registry.register(key="mute")
class Mute(Type):
key="mute"
string="mute"
verb="muted"
@type_registry.register(key="unmute")
class Unmute(Type):
key="unmute"
string="unmute"
verb="unmuted"
@type_registry.register(key="kick")
class Kick(Type):
key="kick"
string="kick"
verb="kicked"
@classmethod
async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None) -> 'Kick':
"""Kick a user."""
bot = ctx.bot
response_message = await ctx.send(f"{target.mention} has been {cls.verb}!\n{bold('Reason:')} {inline(reason)}")
if silent is False:
try:
embed = await message_factory(
bot,
await bot.get_embed_color(ctx.channel),
ctx.guild,
reason,
cls(),
ctx.author,
None,
response_message
)
await target.send(embed=embed, file=get_icon(bot))
except HTTPException:
pass
await target.kick(reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}")
moderation = await Moderation.log(
bot,
ctx.guild.id,
ctx.author.id,
cls(),
'user',
target.id,
None,
None,
reason
)
await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}")
await log(ctx, moderation.id)
await send_evidenceformat(ctx, moderation.id)
return cls
@type_registry.register(key="ban")
class Ban(Type):
key="ban"
@ -31,7 +114,7 @@ class Ban(Type):
bot = ctx.bot
try:
await ctx.guild.fetch_ban(target)
await ctx.send(content=error(f"{target.mention} is already banned!"), ephemeral=True)
await ctx.send(content=error(f"{target.mention} is already {cls.verb}!"), ephemeral=True)
except NotFound:
pass
@ -58,7 +141,7 @@ class Ban(Type):
except HTTPException:
pass
await ctx.guild.ban(target, reason=f"Banned by {ctx.author.id} for: {reason}", delete_message_seconds=delete_messages_seconds)
await ctx.guild.ban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}", delete_message_seconds=delete_messages_seconds)
moderation = await Moderation.log(
bot,
ctx.guild.id,
@ -110,7 +193,7 @@ class Tempban(Ban):
bot = ctx.bot
try:
await ctx.guild.fetch_ban(target)
await ctx.send(content=error(f"{target.mention} is already banned!"), ephemeral=True)
await ctx.send(content=error(f"{target.mention} is already {Ban.verb}!"), ephemeral=True)
except NotFound:
pass
@ -145,7 +228,7 @@ class Tempban(Ban):
except HTTPException:
pass
await ctx.guild.ban(target, reason=f"Tempbanned by {ctx.author.id} for: {reason} (Duration: {parsed_time})", delete_message_seconds=delete_messages_seconds)
await ctx.guild.ban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason} (Duration: {parsed_time})", delete_message_seconds=delete_messages_seconds)
moderation = await Moderation.log(
bot,
ctx.guild.id,
@ -161,3 +244,101 @@ class Tempban(Ban):
await log(ctx, moderation.id)
await send_evidenceformat(ctx, moderation.id)
return cls
@type_registry.register(key="unban")
class Unban(Type):
key="unban"
string="unban"
verb="unbanned"
@classmethod
async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, reason: str = None) -> 'Unban':
"""Unban a user."""
bot = ctx.bot
try:
await ctx.guild.fetch_ban(target)
except NotFound:
await ctx.send(content=error(f"{target.mention} is not {Ban.verb}!"), ephemeral=True)
return
response_message = await ctx.send(f"{target.mention} has been {cls.verb}!\n{bold('Reason:')} {inline(reason)}")
if silent is False:
try:
embed = await message_factory(
bot,
await bot.get_embed_color(ctx.channel),
ctx.guild,
reason,
cls(),
ctx.author,
None,
response_message
)
await target.send(embed=embed, file=get_icon(bot))
except HTTPException:
pass
await ctx.guild.unban(target, reason=f"{str.title(cls.verb)} by {ctx.author.id} for: {reason}")
moderation = await Moderation.log(
bot,
ctx.guild.id,
ctx.author.id,
cls(),
'user',
target.id,
None,
None,
reason
)
await response_message.edit(content=f"{target.mention} has been {cls.verb}! (Case {inline(f'#{moderation.id}')})\n{bold('Reason:')} {inline(reason)}")
await log(ctx, moderation.id)
await send_evidenceformat(ctx, moderation.id)
return cls
@type_registry.register(key="slowmode")
class Slowmode(Type):
key="slowmode"
string="slowmode"
verb="set the slowmode in"
channel=True
@classmethod
async def handler(cls, ctx: commands.Context, target: Messageable, silent: bool, duration: str, reason: str) -> 'Slowmode': # pylint: disable=unused-argument
"""Set the slowmode in a channel."""
bot = ctx.bot
parsed_time = parse_relativedelta(duration)
if not parsed_time:
await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True)
try:
parsed_time = timedelta_from_relativedelta(parsed_time)
except ValueError:
await ctx.send(content=error("Please provide a valid duration!"), ephemeral=True)
if ceil(parsed_time.total_seconds()) > 21600:
await ctx.send(content=error("The slowmode duration cannot exceed 6 hours!"), ephemeral=True)
return
if isinstance(target, TextChannel):
await target.edit(slowmode_delay=ceil(parsed_time.total_seconds()))
moderation = await Moderation.log(
bot,
ctx.guild.id,
ctx.author.id,
cls(),
'channel',
target.id,
None,
parsed_time,
None
)
await ctx.send(f"{ctx.author.mention} has {cls.verb} {target.mention} to {humanize_timedelta(parsed_time)}!\n{bold('Reason:')} {inline(reason)}")
await log(ctx, moderation.id)
return cls
@type_registry.register(key="lockdown")
class Lockdown(Type):
key="lockdown"
string="lockdown"
verb="locked down"
channel=True

View file

@ -2,6 +2,7 @@
from typing import Any
from discord import Guild, Member, User
from discord.abc import Messageable
from redbot.core import commands
from redbot.core.bot import Red
@ -12,23 +13,24 @@ class Type(object):
string = "type"
verb = "typed"
embed_desc = "been"
channel = False # if this is True, the overridden handler methods should be typed with `discord.abc.Messageable` instead of `discord.Member | discord.User`
def __str__(self) -> str:
return self.string
@classmethod
async def handler(cls, ctx: commands.Context, target: Member | User, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument
async def handler(cls, ctx: commands.Context, target: Member | User | Messageable, silent: bool, **kwargs) -> 'Type': # pylint: disable=unused-argument
"""This method should be overridden by any child classes, but should retain the same starting keyword arguments."""
raise NotImplementedError
@classmethod
async def resolve_handler(cls, bot: Red, guild: Guild, target: Member | User, reason: str | None = None) -> Any: # pylint: disable=unused-argument
async def resolve_handler(cls, bot: Red, guild: Guild, target: Member | User | Messageable, reason: str | None = None, **kwargs) -> Any: # pylint: disable=unused-argument
"""This method should be overridden by any resolvable child classes, but should retain the same keyword arguments.
If your moderation type should not be resolvable, do not override this."""
raise NotImplementedError
@classmethod
async def expiry_handler(cls, bot: Red, guild: Guild, target: Member | User) -> Any: # pylint: disable=unused-argument
async def expiry_handler(cls, bot: Red, guild: Guild, target: Member | User | Messageable, **kwargs) -> Any: # pylint: disable=unused-argument
"""This method should be overridden by any expirable child classes, but should retain the same keyword arguments.
If your moderation type should not expire, do not override this."""
raise NotImplementedError