aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Akarys42 <[email protected]>2019-11-27 18:37:16 +0100
committerGravatar Akarys42 <[email protected]>2019-11-27 18:37:16 +0100
commit461826cff98c66646d6f545fc1e711675ac6492f (patch)
tree1c0172d9fba0cfc189f0b6503879efd74f40c8d7
parentRe-indent arguments (diff)
Move attachments re-uploading to DeletionContext.add()
So they are re-uploaded before being deleted
-rw-r--r--bot/cogs/antispam.py41
-rw-r--r--bot/cogs/moderation/modlog.py30
2 files changed, 47 insertions, 24 deletions
diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py
index a450c18ce..8009c9d42 100644
--- a/bot/cogs/antispam.py
+++ b/bot/cogs/antispam.py
@@ -1,11 +1,13 @@
+import asyncio
import logging
from collections.abc import Mapping
from dataclasses import dataclass, field
from datetime import datetime, timedelta
+from io import BytesIO
from operator import itemgetter
from typing import Dict, Iterable, List, Set
-from discord import Colour, Member, Message, NotFound, Object, TextChannel
+from discord import Colour, File, Member, Message, NotFound, Object, TextChannel
from discord.ext.commands import Bot, Cog
from bot import rules
@@ -40,11 +42,13 @@ class DeletionContext:
"""Represents a Deletion Context for a single spam event."""
channel: TextChannel
+ bot: Bot
members: Dict[int, Member] = field(default_factory=dict)
rules: Set[str] = field(default_factory=set)
messages: Dict[int, Message] = field(default_factory=dict)
+ attachments: List[List[str]] = field(default_factory=list)
- def add(self, rule_name: str, members: Iterable[Member], messages: Iterable[Message]) -> None:
+ async def add(self, rule_name: str, members: Iterable[Member], messages: Iterable[Message]) -> None:
"""Adds new rule violation events to the deletion context."""
self.rules.add(rule_name)
@@ -56,6 +60,9 @@ class DeletionContext:
if message.id not in self.messages:
self.messages[message.id] = message
+ # Re-upload attachments :
+ self.attachments.append(await reupload_attachments(self.bot, message))
+
async def upload_messages(self, actor_id: int, modlog: ModLog) -> None:
"""Method that takes care of uploading the queue and posting modlog alert."""
triggered_by_users = ", ".join(f"{m} (`{m.id}`)" for m in self.members.values())
@@ -68,7 +75,7 @@ class DeletionContext:
# For multiple messages or those with excessive newlines, use the logs API
if len(self.messages) > 1 or 'newlines' in self.rules:
- url = await modlog.upload_log(self.messages.values(), actor_id)
+ url = await modlog.upload_log(self.messages.values(), actor_id, attachments=self.attachments)
mod_alert_message += f"A complete log of the offending messages can be found [here]({url})"
else:
mod_alert_message += "Message:\n"
@@ -180,13 +187,16 @@ class AntiSpam(Cog):
# If there's no spam event going on for this channel, start a new Message Deletion Context
if message.channel.id not in self.message_deletion_queue:
log.trace(f"Creating queue for channel `{message.channel.id}`")
- self.message_deletion_queue[message.channel.id] = DeletionContext(channel=message.channel)
+ self.message_deletion_queue[message.channel.id] = DeletionContext(
+ channel=message.channel,
+ bot=self.bot
+ )
self.queue_consumption_tasks = self.bot.loop.create_task(
self._process_deletion_context(message.channel.id)
)
# Add the relevant of this trigger to the Deletion Context
- self.message_deletion_queue[message.channel.id].add(
+ await self.message_deletion_queue[message.channel.id].add(
rule_name=rule_name,
members=members,
messages=relevant_messages
@@ -242,6 +252,9 @@ class AntiSpam(Cog):
async def _process_deletion_context(self, context_id: int) -> None:
"""Processes the Deletion Context queue."""
+ log.trace("Sleeping before processing message deletion queue.")
+ await asyncio.sleep(10)
+
if context_id not in self.message_deletion_queue:
log.error(f"Started processing deletion queue for context `{context_id}`, but it was not found!")
return
@@ -250,6 +263,24 @@ class AntiSpam(Cog):
await deletion_context.upload_messages(self.bot.user.id, self.mod_log)
+async def reupload_attachments(
+ bot: Bot,
+ message: Message,
+ channel_id: int = GuildConfig.attachment_repost
+) -> List[str]:
+ """Re-upload message's attachments to the the channel_id and return the list of re-posted attachments URLs."""
+ if not message.attachments:
+ return []
+ channel = bot.get_channel(channel_id)
+ out = []
+ for attachment in message.attachments:
+ with BytesIO() as buffer:
+ await attachment.save(buffer, use_cached=True)
+ reupload: Message = await channel.send(file=File(buffer, filename=attachment.filename))
+ out.append(reupload.attachments[0].url)
+ return out
+
+
def validate_config(rules: Mapping = AntiSpamConfig.rules) -> Dict[str, str]:
"""Validates the antispam configs."""
validation_errors = {}
diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py
index 945d7822b..9251b79fb 100644
--- a/bot/cogs/moderation/modlog.py
+++ b/bot/cogs/moderation/modlog.py
@@ -2,7 +2,6 @@ import asyncio
import logging
import typing as t
from datetime import datetime
-from io import BytesIO
import discord
from dateutil.relativedelta import relativedelta
@@ -35,7 +34,12 @@ class ModLog(Cog, name="ModLog"):
self._cached_deletes = []
self._cached_edits = []
- async def upload_log(self, messages: t.List[discord.Message], actor_id: int) -> str:
+ async def upload_log(
+ self,
+ messages: t.List[discord.Message],
+ actor_id: int,
+ attachments: t.List[t.List[str]] = None
+ ) -> str:
"""
Uploads the log data to the database via an API endpoint for uploading logs.
@@ -43,6 +47,9 @@ class ModLog(Cog, name="ModLog"):
Returns a URL that can be used to view the log.
"""
+ if attachments is None:
+ attachments = []
+
response = await self.bot.api_client.post(
'bot/deleted-messages',
json={
@@ -55,9 +62,9 @@ class ModLog(Cog, name="ModLog"):
'channel_id': message.channel.id,
'content': message.content,
'embeds': [embed.to_dict() for embed in message.embeds],
- 'attachments': await self.reupload_attachments(message) if message.attachments else [],
+ 'attachments': attachment,
}
- for message in messages
+ for message, attachment in zip(messages, attachments)
]
}
)
@@ -118,21 +125,6 @@ class ModLog(Cog, name="ModLog"):
return await self.bot.get_context(log_message) # Optionally return for use with antispam
- async def reupload_attachments(
- self,
- message: discord.Message,
- channel_id: int = GuildConstant.attachment_repost
- ) -> t.List[str]:
- """Re-upload message's attachments to the the channel_id and return the list of re-posted attachments URLs."""
- channel = self.bot.get_channel(channel_id)
- out = []
- for attachment in message.attachments:
- with BytesIO() as buffer:
- await attachment.save(buffer, use_cached=True)
- reupload: discord.Message = await channel.send(file=discord.File(buffer, filename=attachment.filename))
- out.append(reupload.attachments[0].url)
- return out
-
@Cog.listener()
async def on_guild_channel_create(self, channel: GUILD_CHANNEL) -> None:
"""Log channel create event to mod log."""