diff options
| -rw-r--r-- | bot/cogs/moderation/infractions.py | 20 | ||||
| -rw-r--r-- | bot/cogs/moderation/scheduler.py | 26 | ||||
| -rw-r--r-- | bot/cogs/moderation/superstarify.py | 2 | ||||
| -rw-r--r-- | bot/cogs/moderation/utils.py | 30 | 
4 files changed, 58 insertions, 20 deletions
| diff --git a/bot/cogs/moderation/infractions.py b/bot/cogs/moderation/infractions.py index efa19f59e..e62a36c43 100644 --- a/bot/cogs/moderation/infractions.py +++ b/bot/cogs/moderation/infractions.py @@ -199,7 +199,7 @@ class Infractions(InfractionScheduler, commands.Cog):      async def apply_mute(self, ctx: Context, user: Member, reason: str, **kwargs) -> None:          """Apply a mute infraction with kwargs passed to `post_infraction`.""" -        if await utils.has_active_infraction(ctx, user, "mute"): +        if await utils.get_active_infraction(ctx, user, "mute"):              return          infraction = await utils.post_infraction(ctx, user, "mute", reason, active=True, **kwargs) @@ -235,8 +235,22 @@ class Infractions(InfractionScheduler, commands.Cog):          Will also remove the banned user from the Big Brother watch list if applicable.          """ -        if await utils.has_active_infraction(ctx, user, "ban"): -            return +        # In the case of a permanent ban, we don't need get_active_infractions to tell us if one is active +        is_temporary = kwargs.get("expires_at") is not None +        active_infraction = await utils.get_active_infraction(ctx, user, "ban", is_temporary) + +        if active_infraction: +            if is_temporary: +                log.trace("Tempban ignored as it cannot overwrite an active ban.") +                return + +            if active_infraction.get('expires_at') is None: +                log.trace("Permaban already exists, notify.") +                await ctx.send(f":x: User is already permanently banned (#{active_infraction['id']}).") +                return + +            log.trace("Old tempban is being replaced by new permaban.") +            await self.pardon_infraction(ctx, "ban", user, is_temporary)          infraction = await utils.post_infraction(ctx, user, "ban", reason, active=True, **kwargs)          if infraction is None: diff --git a/bot/cogs/moderation/scheduler.py b/bot/cogs/moderation/scheduler.py index 917697be9..dc42bee2e 100644 --- a/bot/cogs/moderation/scheduler.py +++ b/bot/cogs/moderation/scheduler.py @@ -190,8 +190,19 @@ class InfractionScheduler(Scheduler):          log.info(f"Applied {infr_type} infraction #{id_} to {user}.") -    async def pardon_infraction(self, ctx: Context, infr_type: str, user: UserSnowflake) -> None: -        """Prematurely end an infraction for a user and log the action in the mod log.""" +    async def pardon_infraction( +            self, +            ctx: Context, +            infr_type: str, +            user: UserSnowflake, +            send_msg: bool = True +    ) -> None: +        """ +        Prematurely end an infraction for a user and log the action in the mod log. + +        If `send_msg` is True, then a pardoning confirmation message will be sent to +        the context channel.  Otherwise, no such message will be sent. +        """          log.trace(f"Pardoning {infr_type} infraction for {user}.")          # Check the current active infraction @@ -276,11 +287,12 @@ class InfractionScheduler(Scheduler):              log.info(f"Pardoned {infr_type} infraction #{id_} for {user}.")          # Send a confirmation message to the invoking context. -        log.trace(f"Sending infraction #{id_} pardon confirmation message.") -        await ctx.send( -            f"{dm_emoji}{confirm_msg} infraction **{infr_type}** for {user.mention}. " -            f"{log_text.get('Failure', '')}" -        ) +        if send_msg: +            log.trace(f"Sending infraction #{id_} pardon confirmation message.") +            await ctx.send( +                f"{dm_emoji}{confirm_msg} infraction **{infr_type}** for {user.mention}. " +                f"{log_text.get('Failure', '')}" +            )          # Send a log message to the mod log.          await self.mod_log.send_log_message( diff --git a/bot/cogs/moderation/superstarify.py b/bot/cogs/moderation/superstarify.py index ca3dc4202..29855c325 100644 --- a/bot/cogs/moderation/superstarify.py +++ b/bot/cogs/moderation/superstarify.py @@ -130,7 +130,7 @@ class Superstarify(InfractionScheduler, Cog):          An optional reason can be provided. If no reason is given, the original name will be shown          in a generated reason.          """ -        if await utils.has_active_infraction(ctx, member, "superstar"): +        if await utils.get_active_infraction(ctx, member, "superstar"):              return          # Post the infraction to the API diff --git a/bot/cogs/moderation/utils.py b/bot/cogs/moderation/utils.py index 3598f3b1f..e4e0f1ec2 100644 --- a/bot/cogs/moderation/utils.py +++ b/bot/cogs/moderation/utils.py @@ -97,8 +97,19 @@ async def post_infraction(                  return -async def has_active_infraction(ctx: Context, user: UserSnowflake, infr_type: str) -> bool: -    """Checks if a user already has an active infraction of the given type.""" +async def get_active_infraction( +        ctx: Context, +        user: UserSnowflake, +        infr_type: str, +        send_msg: bool = True +) -> t.Optional[dict]: +    """ +    Retrieves an active infraction of the given type for the user. + +    If `send_msg` is True and the user has an active infraction matching the `infr_type` parameter, +    then a message for the moderator will be sent to the context channel letting them know. +    Otherwise, no message will be sent. +    """      log.trace(f"Checking if {user} has active infractions of type {infr_type}.")      active_infractions = await ctx.bot.api_client.get( @@ -110,15 +121,16 @@ async def has_active_infraction(ctx: Context, user: UserSnowflake, infr_type: st          }      )      if active_infractions: -        log.trace(f"{user} has active infractions of type {infr_type}.") -        await ctx.send( -            f":x: According to my records, this user already has a {infr_type} infraction. " -            f"See infraction **#{active_infractions[0]['id']}**." -        ) -        return True +        # Checks to see if the moderator should be told there is an active infraction +        if send_msg: +            log.trace(f"{user} has active infractions of type {infr_type}.") +            await ctx.send( +                f":x: According to my records, this user already has a {infr_type} infraction. " +                f"See infraction **#{active_infractions[0]['id']}**." +            ) +        return active_infractions[0]      else:          log.trace(f"{user} does not have active infractions of type {infr_type}.") -        return False  async def notify_infraction( | 
