diff options
author | 2024-03-29 23:41:13 +0100 | |
---|---|---|
committer | 2024-03-29 23:41:13 +0100 | |
commit | f494b237338a509b22a391be8653f39b4b4ab18b (patch) | |
tree | 2905af78382e157e3d149b21e059e26a1f9c246f | |
parent | do not edit discord timeout for users who left the server (diff) |
cap timeout duration upon edit
-rw-r--r-- | bot/exts/moderation/infraction/_utils.py | 22 | ||||
-rw-r--r-- | bot/exts/moderation/infraction/infractions.py | 10 | ||||
-rw-r--r-- | bot/exts/moderation/infraction/management.py | 1 |
3 files changed, 25 insertions, 8 deletions
diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py index c3dfb8310..d616e4009 100644 --- a/bot/exts/moderation/infraction/_utils.py +++ b/bot/exts/moderation/infraction/_utils.py @@ -1,5 +1,9 @@ + +import datetime + import arrow import discord +from dateutil.relativedelta import relativedelta from discord import Member from discord.ext.commands import Context from pydis_core.site_api import ResponseCodeError @@ -61,6 +65,8 @@ INFRACTION_DESCRIPTION_WARNING_TEMPLATE = ( ) +MAXIMUM_TIMEOUT_DAYS = datetime.timedelta(days=28) + async def post_user(ctx: Context, user: MemberOrUser) -> dict | None: """ Create a new user in the database. @@ -301,6 +307,22 @@ async def send_private_embed(user: MemberOrUser, embed: discord.Embed) -> bool: return False +def cap_timeout_duration(duration: datetime.datetime | relativedelta) -> tuple[bool, datetime.datetime]: + """Caps the duration of a duration to Discord's limit.""" + now = arrow.utcnow() + capped = False + if isinstance(duration, relativedelta): + duration += now + + if duration > now + MAXIMUM_TIMEOUT_DAYS: + duration = now + MAXIMUM_TIMEOUT_DAYS - datetime.timedelta(minutes=1) # Duration cap is exclusive. + capped = True + elif duration > now + MAXIMUM_TIMEOUT_DAYS - datetime.timedelta(minutes=1): + # Duration cap is exclusive. This is to still allow specifying "28d". + duration -= datetime.timedelta(minutes=1) + return capped, duration + + async def confirm_elevated_user_ban(ctx: Context, user: MemberOrUser) -> bool: """ If user has an elevated role, require confirmation before banning. diff --git a/bot/exts/moderation/infraction/infractions.py b/bot/exts/moderation/infraction/infractions.py index cf8803487..3b2f2810a 100644 --- a/bot/exts/moderation/infraction/infractions.py +++ b/bot/exts/moderation/infraction/infractions.py @@ -230,10 +230,8 @@ class Infractions(InfractionScheduler, commands.Cog): if duration is None: duration = await Duration().convert(ctx, "1h") else: - now = arrow.utcnow() - if isinstance(duration, relativedelta): - duration += now - if duration > now + MAXIMUM_TIMEOUT_DAYS: + capped, duration = _utils.cap_timeout_duration(duration) + if capped: cap_message_for_user = TIMEOUT_CAP_MESSAGE.format(user.mention) if is_mod_channel(ctx.channel): await ctx.reply(f":warning: {cap_message_for_user}") @@ -241,10 +239,6 @@ class Infractions(InfractionScheduler, commands.Cog): await self.bot.get_channel(Channels.mods).send( f":warning: {ctx.author.mention} {cap_message_for_user}" ) - duration = now + MAXIMUM_TIMEOUT_DAYS - timedelta(minutes=1) # Duration cap is exclusive. - elif duration > now + MAXIMUM_TIMEOUT_DAYS - timedelta(minutes=1): - # Duration cap is exclusive. This is to still allow specifying "28d". - duration -= timedelta(minutes=1) await self.apply_timeout(ctx, user, reason, duration_or_expiry=duration) diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index 0a33c84ab..e5216cac9 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -233,6 +233,7 @@ class ModManagement(commands.Cog): self.infractions_cog.schedule_expiration(new_infraction) # Timeouts are handled by Discord itself, so we need to edit the expiry in Discord as well if user and infraction["type"] == "timeout": + _, duration = _utils.cap_timeout_duration(expiry) await user.edit(reason=reason, timed_out_until=expiry) log_text += f""" |