Skip to content

Commit 71cf8ce

Browse files
committed
Delete automated infraction messages after a period of time
1 parent 3c72b27 commit 71cf8ce

File tree

1 file changed

+70
-2
lines changed

1 file changed

+70
-2
lines changed

bot/exts/moderation/infraction/_scheduler.py

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
import typing as t
33
from abc import abstractmethod
44
from collections.abc import Awaitable, Callable
5+
from datetime import UTC, datetime, timedelta
56
from gettext import ngettext
67

78
import arrow
89
import dateutil.parser
910
import discord
11+
from async_rediscache import RedisCache
1012
from discord.ext.commands import Context
1113
from pydis_core.site_api import ResponseCodeError
1214
from pydis_core.utils import scheduling
15+
from pydis_core.utils.channel import get_or_fetch_channel
1316

1417
from bot import constants
1518
from bot.bot import Bot
@@ -24,18 +27,26 @@
2427

2528
log = get_logger(__name__)
2629

30+
AUTOMATED_TIDY_UP_HOURS = 8
31+
2732

2833
class InfractionScheduler:
2934
"""Handles the application, pardoning, and expiration of infractions."""
3035

36+
messages_to_tidy: RedisCache = RedisCache()
37+
3138
def __init__(self, bot: Bot, supported_infractions: t.Container[str]):
3239
self.bot = bot
3340
self.scheduler = scheduling.Scheduler(self.__class__.__name__)
41+
self.tidy_up_scheduler = scheduling.Scheduler(
42+
f"{self.__class__.__name__}TidyUp"
43+
)
3444
self.supported_infractions = supported_infractions
3545

3646
async def cog_unload(self) -> None:
3747
"""Cancel scheduled tasks."""
3848
self.scheduler.cancel_all()
49+
self.tidy_up_scheduler.cancel_all()
3950

4051
@property
4152
def mod_log(self) -> ModLog:
@@ -76,7 +87,46 @@ async def cog_load(self) -> None:
7687

7788
self.scheduler.schedule_at(next_reschedule_point, -1, self.cog_load())
7889

79-
log.trace("Done rescheduling")
90+
log.trace("Done rescheduling expirations, scheduling tidy up tasks.")
91+
92+
for key, expire_at in await self.messages_to_tidy.items():
93+
channel_id, message_id = map(int, key.split(":"))
94+
expire_at = dateutil.parser.isoparse(expire_at)
95+
96+
log.trace(
97+
"Scheduling tidy up for message %s in channel %s at %s",
98+
message_id, channel_id, expire_at
99+
)
100+
101+
self.tidy_up_scheduler.schedule_at(
102+
expire_at,
103+
message_id,
104+
self._delete_infraction_message(channel_id, message_id)
105+
)
106+
107+
async def _delete_infraction_message(
108+
self,
109+
channel_id: int,
110+
message_id: int
111+
) -> None:
112+
"""
113+
Delete a message in the given channel.
114+
115+
This is used to delete infraction messages after a certain period of time.
116+
"""
117+
channel = await get_or_fetch_channel(self.bot, channel_id)
118+
if channel is None:
119+
log.warning(f"Channel {channel_id} not found for infraction message deletion.")
120+
return
121+
122+
try:
123+
message = await channel.fetch_message(message_id)
124+
await message.delete()
125+
log.trace(f"Deleted infraction message {message_id} in channel {channel_id}.")
126+
except discord.NotFound:
127+
log.warning(f"Message {message_id} not found in channel {channel_id}.")
128+
129+
await self.messages_to_tidy.delete(f"{channel_id}:{message_id}")
80130

81131
async def reapply_infraction(
82132
self,
@@ -269,7 +319,25 @@ async def apply_infraction(
269319
# Send a confirmation message to the invoking context.
270320
log.trace(f"Sending infraction #{id_} confirmation message.")
271321
mentions = discord.AllowedMentions(users=[user], roles=False)
272-
await ctx.send(f"{dm_result}{confirm_msg}{infr_message}.", allowed_mentions=mentions)
322+
sent_msg = await ctx.send(f"{dm_result}{confirm_msg}{infr_message}.", allowed_mentions=mentions)
323+
324+
if infraction["actor"] == self.bot.user.id:
325+
expire_message_time = datetime.now(UTC) + timedelta(hours=AUTOMATED_TIDY_UP_HOURS)
326+
327+
log.trace(f"Scheduling message tidy for infraction #{id_} in {AUTOMATED_TIDY_UP_HOURS} hours.")
328+
329+
# Schedule the message to be deleted after a certain period of time.
330+
self.tidy_up_scheduler.schedule_at(
331+
expire_message_time,
332+
sent_msg.id,
333+
self._delete_infraction_message(ctx.channel.id, sent_msg.id)
334+
)
335+
336+
# Persist to Redis to handle for bot restarts.
337+
await self.messages_to_tidy.set(
338+
f"{ctx.channel.id}:{sent_msg.id}",
339+
expire_message_time.isoformat(),
340+
)
273341

274342
if jump_url is None:
275343
jump_url = "(Infraction issued in a ModMail channel.)"

0 commit comments

Comments
 (0)