diff options
Diffstat (limited to '')
| -rw-r--r-- | bot/constants.py | 8 | ||||
| -rw-r--r-- | bot/converters.py | 29 | ||||
| -rw-r--r-- | bot/exts/moderation/infraction/management.py | 70 | ||||
| -rw-r--r-- | config-default.yml | 14 | 
4 files changed, 92 insertions, 29 deletions
| diff --git a/bot/constants.py b/bot/constants.py index fb280b042..08ae0d52f 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -391,12 +391,15 @@ class Channels(metaclass=YAMLGetter):      admin_announcements: int      admin_spam: int      admins: int +    admins_voice: int      announcements: int      attachment_log: int      big_brother_logs: int      bot_commands: int      change_log: int -    code_help_voice: int +    code_help_chat_1: int +    code_help_chat_2: int +    code_help_voice_1: int      code_help_voice_2: int      cooldown: int      defcon: int @@ -405,6 +408,7 @@ class Channels(metaclass=YAMLGetter):      dev_log: int      dm_log: int      esoteric: int +    general_voice: int      helpers: int      incidents: int      incidents_archive: int @@ -425,6 +429,8 @@ class Channels(metaclass=YAMLGetter):      python_news: int      reddit: int      staff_announcements: int +    staff_voice: int +    staff_voice_chat: int      talent_pool: int      user_event_announcements: int      user_log: int diff --git a/bot/converters.py b/bot/converters.py index 2e118d476..d0a9731d6 100644 --- a/bot/converters.py +++ b/bot/converters.py @@ -549,6 +549,35 @@ def _snowflake_from_regex(pattern: t.Pattern, arg: str) -> int:      return int(match.group(1)) +class Infraction(Converter): +    """ +    Attempts to convert a given infraction ID into an infraction. + +    Alternatively, `l`, `last`, or `recent` can be passed in order to +    obtain the most recent infraction by the actor. +    """ + +    async def convert(self, ctx: Context, arg: str) -> t.Optional[dict]: +        """Attempts to convert `arg` into an infraction `dict`.""" +        if arg in ("l", "last", "recent"): +            params = { +                "actor__id": ctx.author.id, +                "ordering": "-inserted_at" +            } + +            infractions = await ctx.bot.api_client.get("bot/infractions", params=params) + +            if not infractions: +                raise BadArgument( +                    "Couldn't find most recent infraction; you have never given an infraction." +                ) +            else: +                return infractions[0] + +        else: +            return await ctx.bot.api_client.get(f"bot/infractions/{arg}") + +  Expiry = t.Union[Duration, ISODateTime]  FetchedMember = t.Union[discord.Member, FetchedUser]  UserMention = partial(_snowflake_from_regex, RE_USER_MENTION) diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index 4cd7d15bf..c58410f8c 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -10,7 +10,7 @@ from discord.utils import escape_markdown  from bot import constants  from bot.bot import Bot -from bot.converters import Expiry, Snowflake, UserMention, allowed_strings, proxy_user +from bot.converters import Expiry, Infraction, Snowflake, UserMention, allowed_strings, proxy_user  from bot.exts.moderation.infraction.infractions import Infractions  from bot.exts.moderation.modlog import ModLog  from bot.pagination import LinePaginator @@ -45,11 +45,50 @@ class ModManagement(commands.Cog):          """Infraction manipulation commands."""          await ctx.send_help(ctx.command) +    @infraction_group.command(name="append", aliases=("amend", "add", "a")) +    async def infraction_append( +        self, +        ctx: Context, +        infraction: Infraction, +        duration: t.Union[Expiry, allowed_strings("p", "permanent"), None],   # noqa: F821 +        *, +        reason: str = None +    ) -> None: +        """ +        Append text and/or edit the duration of an infraction. + +        Durations are relative to the time of updating and should be appended with a unit of time. +        Units (∗case-sensitive): +        \u2003`y` - years +        \u2003`m` - months∗ +        \u2003`w` - weeks +        \u2003`d` - days +        \u2003`h` - hours +        \u2003`M` - minutes∗ +        \u2003`s` - seconds + +        Use "l", "last", or "recent" as the infraction ID to specify that the most recent infraction +        authored by the command invoker should be edited. + +        Use "p" or "permanent" to mark the infraction as permanent. Alternatively, an ISO 8601 +        timestamp can be provided for the duration. + +        If a previous infraction reason does not end with an ending punctuation mark, this automatically +        adds a period before the amended reason. +        """ +        old_reason = infraction["reason"] + +        if old_reason is not None: +            add_period = not old_reason.endswith((".", "!", "?")) +            reason = old_reason + (". " if add_period else " ") + reason + +        await self.infraction_edit(ctx, infraction, duration, reason=reason) +      @infraction_group.command(name='edit', aliases=('e',))      async def infraction_edit(          self,          ctx: Context, -        infraction_id: t.Union[int, allowed_strings("l", "last", "recent")],  # noqa: F821 +        infraction: Infraction,          duration: t.Union[Expiry, allowed_strings("p", "permanent"), None],   # noqa: F821          *,          reason: str = None @@ -77,30 +116,13 @@ class ModManagement(commands.Cog):              # Unlike UserInputError, the error handler will show a specified message for BadArgument              raise commands.BadArgument("Neither a new expiry nor a new reason was specified.") -        # Retrieve the previous infraction for its information. -        if isinstance(infraction_id, str): -            params = { -                "actor__id": ctx.author.id, -                "ordering": "-inserted_at" -            } -            infractions = await self.bot.api_client.get("bot/infractions", params=params) - -            if infractions: -                old_infraction = infractions[0] -                infraction_id = old_infraction["id"] -            else: -                await ctx.send( -                    ":x: Couldn't find most recent infraction; you have never given an infraction." -                ) -                return -        else: -            old_infraction = await self.bot.api_client.get(f"bot/infractions/{infraction_id}") +        infraction_id = infraction["id"]          request_data = {}          confirm_messages = []          log_text = "" -        if duration is not None and not old_infraction['active']: +        if duration is not None and not infraction['active']:              if reason is None:                  await ctx.send(":x: Cannot edit the expiration of an expired infraction.")                  return @@ -119,7 +141,7 @@ class ModManagement(commands.Cog):              request_data['reason'] = reason              confirm_messages.append("set a new reason")              log_text += f""" -                Previous reason: {old_infraction['reason']} +                Previous reason: {infraction['reason']}                  New reason: {reason}              """.rstrip()          else: @@ -134,7 +156,7 @@ class ModManagement(commands.Cog):          # Re-schedule infraction if the expiration has been updated          if 'expires_at' in request_data:              # A scheduled task should only exist if the old infraction wasn't permanent -            if old_infraction['expires_at']: +            if infraction['expires_at']:                  self.infractions_cog.scheduler.cancel(new_infraction['id'])              # If the infraction was not marked as permanent, schedule a new expiration task @@ -142,7 +164,7 @@ class ModManagement(commands.Cog):                  self.infractions_cog.schedule_expiration(new_infraction)              log_text += f""" -                Previous expiry: {old_infraction['expires_at'] or "Permanent"} +                Previous expiry: {infraction['expires_at'] or "Permanent"}                  New expiry: {new_infraction['expires_at'] or "Permanent"}              """.rstrip() diff --git a/config-default.yml b/config-default.yml index 82023aae1..006743342 100644 --- a/config-default.yml +++ b/config-default.yml @@ -195,13 +195,19 @@ guild:          mod_announcements:      &MOD_ANNOUNCEMENTS      372115205867700225          admin_announcements:    &ADMIN_ANNOUNCEMENTS    749736155569848370 -        # Voice -        code_help_voice:                    755154969761677312 -        code_help_voice_2:                  766330079135268884 -        voice_chat:                         412357430186344448 +        # Voice Channels          admins_voice:       &ADMINS_VOICE   500734494840717332 +        code_help_voice_1:                  751592231726481530 +        code_help_voice_2:                  764232549840846858 +        general_voice:                      751591688538947646          staff_voice:        &STAFF_VOICE    412375055910043655 +        # Voice Chat +        code_help_chat_1:                   755154969761677312 +        code_help_chat_2:                   766330079135268884 +        staff_voice_chat:                   541638762007101470 +        voice_chat:                         412357430186344448 +          # Watch          big_brother_logs:   &BB_LOGS        468507907357409333          talent_pool:        &TALENT_POOL    534321732593647616 | 
