diff options
| -rw-r--r-- | bot/exts/moderation/infraction/_scheduler.py | 25 | ||||
| -rw-r--r-- | bot/exts/moderation/infraction/infractions.py | 64 | 
2 files changed, 59 insertions, 30 deletions
| diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 8286d3635..c2fd959f7 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -265,13 +265,17 @@ class InfractionScheduler:              ctx: Context,              infr_type: str,              user: UserSnowflake, -            send_msg: bool = True +            *, +            send_msg: bool = True, +            notify: 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. +        the context channel. Otherwise, no such message will be sent. + +        If `notify` is True, notify the user of the pardon via DM where applicable.          """          log.trace(f"Pardoning {infr_type} infraction for {user}.") @@ -292,7 +296,7 @@ class InfractionScheduler:              return          # Deactivate the infraction and cancel its scheduled expiration task. -        log_text = await self.deactivate_infraction(response[0], send_log=False) +        log_text = await self.deactivate_infraction(response[0], send_log=False, notify=notify)          log_text["Member"] = messages.format_user(user)          log_text["Actor"] = ctx.author.mention @@ -345,7 +349,9 @@ class InfractionScheduler:      async def deactivate_infraction(          self,          infraction: _utils.Infraction, -        send_log: bool = True +        *, +        send_log: bool = True, +        notify: bool = True      ) -> t.Dict[str, str]:          """          Deactivate an active infraction and return a dictionary of lines to send in a mod log. @@ -354,6 +360,8 @@ class InfractionScheduler:          expiration task cancelled. If `send_log` is True, a mod log is sent for the          deactivation of the infraction. +        If `notify` is True, notify the user of the pardon via DM where applicable. +          Infractions of unsupported types will raise a ValueError.          """          guild = self.bot.get_guild(constants.Guild.id) @@ -380,7 +388,7 @@ class InfractionScheduler:          try:              log.trace("Awaiting the pardon action coroutine.") -            returned_log = await self._pardon_action(infraction) +            returned_log = await self._pardon_action(infraction, notify)              if returned_log is not None:                  log_text = {**log_text, **returned_log}  # Merge the logs together @@ -468,10 +476,15 @@ class InfractionScheduler:          return log_text      @abstractmethod -    async def _pardon_action(self, infraction: _utils.Infraction) -> t.Optional[t.Dict[str, str]]: +    async def _pardon_action( +        self, +        infraction: _utils.Infraction, +        notify: bool +    ) -> t.Optional[t.Dict[str, str]]:          """          Execute deactivation steps specific to the infraction's type and return a log dict. +        If `notify` is True, notify the user of the pardon via DM where applicable.          If an infraction type is unsupported, return None instead.          """          raise NotImplementedError diff --git a/bot/exts/moderation/infraction/infractions.py b/bot/exts/moderation/infraction/infractions.py index dbf56d6bb..9d5b049e1 100644 --- a/bot/exts/moderation/infraction/infractions.py +++ b/bot/exts/moderation/infraction/infractions.py @@ -286,7 +286,7 @@ class Infractions(InfractionScheduler, commands.Cog):                  return              # Let the current mute attempt override an automatically triggered mute. -            log_text = await self.deactivate_infraction(active) +            log_text = await self.deactivate_infraction(active, notify=False)              if "Failure" in log_text:                  await ctx.send(                      f":x: can't override infraction **mute** for {user.mention}: " @@ -414,8 +414,15 @@ class Infractions(InfractionScheduler, commands.Cog):      # endregion      # region: Base pardon functions -    async def pardon_mute(self, user_id: int, guild: discord.Guild, reason: t.Optional[str]) -> t.Dict[str, str]: -        """Remove a user's muted role, DM them a notification, and return a log dict.""" +    async def pardon_mute( +        self, +        user_id: int, +        guild: discord.Guild, +        reason: t.Optional[str], +        *, +        notify: bool = True +    ) -> t.Dict[str, str]: +        """Remove a user's muted role, optionally DM them a notification, and return a log dict."""          user = guild.get_member(user_id)          log_text = {} @@ -424,16 +431,17 @@ class Infractions(InfractionScheduler, commands.Cog):              self.mod_log.ignore(Event.member_update, user.id)              await user.remove_roles(self._muted_role, reason=reason) -            # DM the user about the expiration. -            notified = await _utils.notify_pardon( -                user=user, -                title="You have been unmuted", -                content="You may now send messages in the server.", -                icon_url=_utils.INFRACTION_ICONS["mute"][1] -            ) +            if notify: +                # DM the user about the expiration. +                notified = await _utils.notify_pardon( +                    user=user, +                    title="You have been unmuted", +                    content="You may now send messages in the server.", +                    icon_url=_utils.INFRACTION_ICONS["mute"][1] +                ) +                log_text["DM"] = "Sent" if notified else "**Failed**"              log_text["Member"] = format_user(user) -            log_text["DM"] = "Sent" if notified else "**Failed**"          else:              log.info(f"Failed to unmute user {user_id}: user not found")              log_text["Failure"] = "User was not found in the guild." @@ -455,31 +463,39 @@ class Infractions(InfractionScheduler, commands.Cog):          return log_text -    async def pardon_voice_ban(self, user_id: int, guild: discord.Guild) -> t.Dict[str, str]: -        """Add Voice Verified role back to user, DM them a notification, and return a log dict.""" +    async def pardon_voice_ban( +        self, +        user_id: int, +        guild: discord.Guild, +        *, +        notify: bool = True +    ) -> t.Dict[str, str]: +        """Optionally DM the user a pardon notification and return a log dict."""          user = guild.get_member(user_id)          log_text = {}          if user: -            # DM user about infraction expiration -            notified = await _utils.notify_pardon( -                user=user, -                title="Voice ban ended", -                content="You have been unbanned and can verify yourself again in the server.", -                icon_url=_utils.INFRACTION_ICONS["voice_ban"][1] -            ) +            if notify: +                # DM user about infraction expiration +                notified = await _utils.notify_pardon( +                    user=user, +                    title="Voice ban ended", +                    content="You have been unbanned and can verify yourself again in the server.", +                    icon_url=_utils.INFRACTION_ICONS["voice_ban"][1] +                ) +                log_text["DM"] = "Sent" if notified else "**Failed**"              log_text["Member"] = format_user(user) -            log_text["DM"] = "Sent" if notified else "**Failed**"          else:              log_text["Info"] = "User was not found in the guild."          return log_text -    async def _pardon_action(self, infraction: _utils.Infraction) -> t.Optional[t.Dict[str, str]]: +    async def _pardon_action(self, infraction: _utils.Infraction, notify: bool) -> t.Optional[t.Dict[str, str]]:          """          Execute deactivation steps specific to the infraction's type and return a log dict. +        If `notify` is True, notify the user of the pardon via DM where applicable.          If an infraction type is unsupported, return None instead.          """          guild = self.bot.get_guild(constants.Guild.id) @@ -487,11 +503,11 @@ class Infractions(InfractionScheduler, commands.Cog):          reason = f"Infraction #{infraction['id']} expired or was pardoned."          if infraction["type"] == "mute": -            return await self.pardon_mute(user_id, guild, reason) +            return await self.pardon_mute(user_id, guild, reason, notify=notify)          elif infraction["type"] == "ban":              return await self.pardon_ban(user_id, guild, reason)          elif infraction["type"] == "voice_ban": -            return await self.pardon_voice_ban(user_id, guild) +            return await self.pardon_voice_ban(user_id, guild, notify=notify)      # endregion | 
