diff options
Diffstat (limited to 'bot/exts/moderation/modlog.py')
-rw-r--r-- | bot/exts/moderation/modlog.py | 72 |
1 files changed, 48 insertions, 24 deletions
diff --git a/bot/exts/moderation/modlog.py b/bot/exts/moderation/modlog.py index 462f8533d..796c1f021 100644 --- a/bot/exts/moderation/modlog.py +++ b/bot/exts/moderation/modlog.py @@ -11,13 +11,13 @@ from deepdiff import DeepDiff from discord import Colour, Message, Thread from discord.abc import GuildChannel from discord.ext.commands import Cog, Context -from discord.utils import escape_markdown +from discord.utils import escape_markdown, format_dt, snowflake_time from bot.bot import Bot from bot.constants import Categories, Channels, Colours, Emojis, Event, Guild as GuildConstant, Icons, Roles, URLs from bot.log import get_logger +from bot.utils import time from bot.utils.messages import format_user -from bot.utils.time import humanize_delta log = get_logger(__name__) @@ -41,7 +41,6 @@ class ModLog(Cog, name="ModLog"): self.bot = bot self._ignored = {event: [] for event in Event} - self._cached_deletes = [] self._cached_edits = [] async def upload_log( @@ -97,6 +96,7 @@ class ModLog(Cog, name="ModLog"): footer: t.Optional[str] = None, ) -> Context: """Generate log embed and send to logging channel.""" + await self.bot.wait_until_guild_available() # Truncate string directly here to avoid removing newlines embed = discord.Embed( description=text[:4093] + "..." if len(text) > 4096 else text @@ -116,7 +116,7 @@ class ModLog(Cog, name="ModLog"): if ping_everyone: if content: - content = f"<@&{Roles.moderators}>\n{content}" + content = f"<@&{Roles.moderators}> {content}" else: content = f"<@&{Roles.moderators}>" @@ -407,7 +407,7 @@ class ModLog(Cog, name="ModLog"): now = datetime.now(timezone.utc) difference = abs(relativedelta(now, member.created_at)) - message = format_user(member) + "\n\n**Account age:** " + humanize_delta(difference) + message = format_user(member) + "\n\n**Account age:** " + time.humanize_delta(difference) if difference.days < 1 and difference.months < 1 and difference.years < 1: # New user account! message = f"{Emojis.new} {message}" @@ -552,29 +552,28 @@ class ModLog(Cog, name="ModLog"): return channel.id in GuildConstant.modlog_blacklist - @Cog.listener() - async def on_message_delete(self, message: discord.Message) -> None: - """Log message delete event to message change log.""" + async def log_cached_deleted_message(self, message: discord.Message) -> None: + """ + Log the message's details to message change log. + + This is called when a cached message is deleted. + """ channel = message.channel author = message.author if self.is_message_blacklisted(message): return - self._cached_deletes.append(message.id) - if message.id in self._ignored[Event.message_delete]: self._ignored[Event.message_delete].remove(message.id) return - if author.bot: - return - if channel.category: response = ( f"**Author:** {format_user(author)}\n" f"**Channel:** {channel.category}/#{channel.name} (`{channel.id}`)\n" f"**Message ID:** `{message.id}`\n" + f"**Sent at:** {format_dt(message.created_at)}\n" f"[Jump to message]({message.jump_url})\n" "\n" ) @@ -583,6 +582,7 @@ class ModLog(Cog, name="ModLog"): f"**Author:** {format_user(author)}\n" f"**Channel:** #{channel.name} (`{channel.id}`)\n" f"**Message ID:** `{message.id}`\n" + f"**Sent at:** {format_dt(message.created_at)}\n" f"[Jump to message]({message.jump_url})\n" "\n" ) @@ -610,17 +610,15 @@ class ModLog(Cog, name="ModLog"): channel_id=Channels.message_log ) - @Cog.listener() - async def on_raw_message_delete(self, event: discord.RawMessageDeleteEvent) -> None: - """Log raw message delete event to message change log.""" - if self.is_channel_ignored(event.channel_id): - return - - await asyncio.sleep(1) # Wait here in case the normal event was fired + async def log_uncached_deleted_message(self, event: discord.RawMessageDeleteEvent) -> None: + """ + Log the message's details to message change log. - if event.message_id in self._cached_deletes: - # It was in the cache and the normal event was fired, so we can just ignore it - self._cached_deletes.remove(event.message_id) + This is called when a message absent from the cache is deleted. + Hence, the message contents aren't logged. + """ + await self.bot.wait_until_guild_available() + if self.is_channel_ignored(event.channel_id): return if event.message_id in self._ignored[Event.message_delete]: @@ -633,6 +631,7 @@ class ModLog(Cog, name="ModLog"): response = ( f"**Channel:** {channel.category}/#{channel.name} (`{channel.id}`)\n" f"**Message ID:** `{event.message_id}`\n" + f"**Sent at:** {format_dt(snowflake_time(event.message_id))}\n" "\n" "This message was not cached, so the message content cannot be displayed." ) @@ -640,6 +639,7 @@ class ModLog(Cog, name="ModLog"): response = ( f"**Channel:** #{channel.name} (`{channel.id}`)\n" f"**Message ID:** `{event.message_id}`\n" + f"**Sent at:** {format_dt(snowflake_time(event.message_id))}\n" "\n" "This message was not cached, so the message content cannot be displayed." ) @@ -652,6 +652,14 @@ class ModLog(Cog, name="ModLog"): ) @Cog.listener() + async def on_raw_message_delete(self, event: discord.RawMessageDeleteEvent) -> None: + """Log message deletions to message change log.""" + if event.cached_message is not None: + await self.log_cached_deleted_message(event.cached_message) + else: + await self.log_uncached_deleted_message(event) + + @Cog.listener() async def on_message_edit(self, msg_before: discord.Message, msg_after: discord.Message) -> None: """Log message edit event to message change log.""" if self.is_message_blacklisted(msg_before): @@ -709,7 +717,7 @@ class ModLog(Cog, name="ModLog"): # datetime as the baseline and create a human-readable delta between this edit event # and the last time the message was edited timestamp = msg_before.edited_at - delta = humanize_delta(relativedelta(msg_after.edited_at, msg_before.edited_at)) + delta = time.humanize_delta(msg_after.edited_at, msg_before.edited_at) footer = f"Last edited {delta} ago" else: # Message was not previously edited, use the created_at datetime as the baseline, no @@ -725,6 +733,10 @@ class ModLog(Cog, name="ModLog"): @Cog.listener() async def on_raw_message_edit(self, event: discord.RawMessageUpdateEvent) -> None: """Log raw message edit event to message change log.""" + if event.guild_id is None: + return # ignore DM edits + + await self.bot.wait_until_guild_available() try: channel = self.bot.get_channel(int(event.data["channel_id"])) message = await channel.fetch_message(event.message_id) @@ -773,6 +785,10 @@ class ModLog(Cog, name="ModLog"): @Cog.listener() async def on_thread_update(self, before: Thread, after: Thread) -> None: """Log thread archiving, un-archiving and name edits.""" + if self.is_channel_ignored(after.id): + log.trace("Ignoring update of thread %s (%d)", after.mention, after.id) + return + if before.name != after.name: await self.send_log_message( Icons.hash_blurple, @@ -809,6 +825,10 @@ class ModLog(Cog, name="ModLog"): @Cog.listener() async def on_thread_delete(self, thread: Thread) -> None: """Log thread deletion.""" + if self.is_channel_ignored(thread.id): + log.trace("Ignoring deletion of thread %s (%d)", thread.mention, thread.id) + return + await self.send_log_message( Icons.hash_red, Colours.soft_red, @@ -827,6 +847,10 @@ class ModLog(Cog, name="ModLog"): if thread.me: return + if self.is_channel_ignored(thread.id): + log.trace("Ignoring creation of thread %s (%d)", thread.mention, thread.id) + return + await self.send_log_message( Icons.hash_green, Colours.soft_green, |