-
-
Notifications
You must be signed in to change notification settings - Fork 751
Delete automated infraction messages after a period of time #3339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,14 +2,17 @@ | |
| import typing as t | ||
| from abc import abstractmethod | ||
| from collections.abc import Awaitable, Callable | ||
| from datetime import UTC, datetime, timedelta | ||
| from gettext import ngettext | ||
|
|
||
| import arrow | ||
| import dateutil.parser | ||
| import discord | ||
| from async_rediscache import RedisCache | ||
| from discord.ext.commands import Context | ||
| from pydis_core.site_api import ResponseCodeError | ||
| from pydis_core.utils import scheduling | ||
| from pydis_core.utils.channel import get_or_fetch_channel | ||
|
|
||
| from bot import constants | ||
| from bot.bot import Bot | ||
|
|
@@ -24,18 +27,26 @@ | |
|
|
||
| log = get_logger(__name__) | ||
|
|
||
| AUTOMATED_TIDY_UP_HOURS = 8 | ||
|
|
||
|
|
||
| class InfractionScheduler: | ||
| """Handles the application, pardoning, and expiration of infractions.""" | ||
|
|
||
| messages_to_tidy: RedisCache = RedisCache() | ||
|
|
||
| def __init__(self, bot: Bot, supported_infractions: t.Container[str]): | ||
| self.bot = bot | ||
| self.scheduler = scheduling.Scheduler(self.__class__.__name__) | ||
| self.tidy_up_scheduler = scheduling.Scheduler( | ||
| f"{self.__class__.__name__}TidyUp" | ||
| ) | ||
| self.supported_infractions = supported_infractions | ||
|
|
||
| async def cog_unload(self) -> None: | ||
| """Cancel scheduled tasks.""" | ||
| self.scheduler.cancel_all() | ||
| self.tidy_up_scheduler.cancel_all() | ||
|
|
||
| @property | ||
| def mod_log(self) -> ModLog: | ||
|
|
@@ -76,7 +87,47 @@ async def cog_load(self) -> None: | |
|
|
||
| self.scheduler.schedule_at(next_reschedule_point, -1, self.cog_load()) | ||
|
|
||
| log.trace("Done rescheduling") | ||
| log.trace("Done rescheduling expirations, scheduling tidy up tasks.") | ||
|
|
||
| for key, expire_at in await self.messages_to_tidy.items(): | ||
| channel_id, message_id = map(int, key.split(":")) | ||
| expire_at = dateutil.parser.isoparse(expire_at) | ||
|
|
||
| log.trace( | ||
| "Scheduling tidy up for message %s in channel %s at %s", | ||
| message_id, channel_id, expire_at | ||
| ) | ||
|
|
||
| self.tidy_up_scheduler.schedule_at( | ||
| expire_at, | ||
| message_id, | ||
| self._delete_infraction_message(channel_id, message_id) | ||
| ) | ||
|
|
||
| async def _delete_infraction_message( | ||
| self, | ||
| channel_id: int, | ||
| message_id: int | ||
| ) -> None: | ||
| """ | ||
| Delete a message in the given channel. | ||
|
|
||
| This is used to delete infraction messages after a certain period of time. | ||
| """ | ||
| try: | ||
| channel = await get_or_fetch_channel(self.bot, channel_id) | ||
| message = await channel.fetch_message(message_id) | ||
| await message.delete() | ||
|
jb3 marked this conversation as resolved.
|
||
| log.trace(f"Deleted infraction message {message_id} in channel {channel_id}.") | ||
| except discord.NotFound: | ||
| log.warning(f"Channel or message {message_id} not found in channel {channel_id}.") | ||
| except discord.Forbidden: | ||
| log.warning(f"Bot lacks permissions to delete message {message_id} in channel {channel_id}.") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unsure if this should always be a warning, since trying to delete messages in closed threads will also raise Forbidden iirc. No point in sending that specific case to sentry
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I hadn't realised that manage messages does not override this. I'll drop it to an info log. |
||
| except discord.HTTPException: | ||
| log.exception(f"Issue during scheduled deletion of message {message_id} in channel {channel_id}.") | ||
| return # Keep the task in Redis on HTTP errors | ||
|
|
||
| await self.messages_to_tidy.delete(f"{channel_id}:{message_id}") | ||
|
|
||
| async def reapply_infraction( | ||
| self, | ||
|
|
@@ -269,7 +320,25 @@ async def apply_infraction( | |
| # Send a confirmation message to the invoking context. | ||
| log.trace(f"Sending infraction #{id_} confirmation message.") | ||
| mentions = discord.AllowedMentions(users=[user], roles=False) | ||
| await ctx.send(f"{dm_result}{confirm_msg}{infr_message}.", allowed_mentions=mentions) | ||
| sent_msg = await ctx.send(f"{dm_result}{confirm_msg}{infr_message}.", allowed_mentions=mentions) | ||
|
|
||
| if infraction["actor"] == self.bot.user.id: | ||
| expire_message_time = datetime.now(UTC) + timedelta(hours=AUTOMATED_TIDY_UP_HOURS) | ||
|
|
||
| log.trace(f"Scheduling message tidy for infraction #{id_} in {AUTOMATED_TIDY_UP_HOURS} hours.") | ||
|
|
||
| # Schedule the message to be deleted after a certain period of time. | ||
| self.tidy_up_scheduler.schedule_at( | ||
| expire_message_time, | ||
| sent_msg.id, | ||
| self._delete_infraction_message(ctx.channel.id, sent_msg.id) | ||
| ) | ||
|
|
||
| # Persist to Redis to handle for bot restarts. | ||
| await self.messages_to_tidy.set( | ||
| f"{ctx.channel.id}:{sent_msg.id}", | ||
| expire_message_time.isoformat(), | ||
| ) | ||
|
|
||
| if jump_url is None: | ||
| jump_url = "(Infraction issued in a ModMail channel.)" | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.