aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/cogs/moderation/infractions.py20
-rw-r--r--bot/cogs/moderation/scheduler.py26
-rw-r--r--bot/cogs/moderation/superstarify.py2
-rw-r--r--bot/cogs/moderation/utils.py30
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(