From bed913eb358f3effa592cab507f329ce8f50171a Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 31 Oct 2019 13:07:55 +0100 Subject: Re-post attachments Before sending the attachments to API for logging, we now re-post them in the channel that have the id stored in the constant Guild.attachment_repost (it needs to be configured). These new links will never expires. --- bot/cogs/antispam.py | 4 ---- bot/cogs/moderation/modlog.py | 19 ++++++++++++++++++- bot/constants.py | 1 + config-default.yml | 1 + 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 1340eb608..a450c18ce 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -1,4 +1,3 @@ -import asyncio import logging from collections.abc import Mapping from dataclasses import dataclass, field @@ -243,9 +242,6 @@ 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 diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py index 88f2b6c67..6d4b66644 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/cogs/moderation/modlog.py @@ -2,6 +2,7 @@ import asyncio import logging import typing as t from datetime import datetime +from io import BytesIO import discord from dateutil.relativedelta import relativedelta @@ -53,7 +54,8 @@ class ModLog(Cog, name="ModLog"): 'author': message.author.id, 'channel_id': message.channel.id, 'content': message.content, - 'embeds': [embed.to_dict() for embed in message.embeds] + 'embeds': [embed.to_dict() for embed in message.embeds], + 'attachments': await self.reupload_attachments(message) if message.attachments else [], } for message in messages ] @@ -116,6 +118,21 @@ 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: + buffer = BytesIO() + await attachment.save(buffer, use_cached=True) + reupload = 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.""" diff --git a/bot/constants.py b/bot/constants.py index 838fe7a79..9582fea96 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -398,6 +398,7 @@ class Guild(metaclass=YAMLGetter): id: int ignored: List[int] staff_channels: List[int] + attachment_repost: int class Keys(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 4638a89ee..9d2ee7941 100644 --- a/config-default.yml +++ b/config-default.yml @@ -127,6 +127,7 @@ guild: staff_channels: [*ADMINS, *ADMIN_SPAM, *MOD_SPAM, *MODS, *HELPERS, *ORGANISATION, *DEFCON] ignored: [*ADMINS, *MESSAGE_LOG, *MODLOG] + attachment_repost: *MODLOG roles: admin: &ADMIN_ROLE 267628507062992896 -- cgit v1.2.3 From ded5bbe5bb6547b50647a8ed040e9803bd58a76e Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Fri, 15 Nov 2019 10:33:09 +0100 Subject: Use a context manager for the buffer Co-authored-by: Shirayuki Nekomata --- bot/cogs/moderation/modlog.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py index 6d4b66644..3c6731de6 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/cogs/moderation/modlog.py @@ -127,10 +127,10 @@ class ModLog(Cog, name="ModLog"): channel = self.bot.get_channel(channel_id) out = [] for attachment in message.attachments: - buffer = BytesIO() - await attachment.save(buffer, use_cached=True) - reupload = await channel.send(file=discord.File(buffer, filename=attachment.filename)) - out.append(reupload.attachments[0].url) + 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() -- cgit v1.2.3 From 173c5c256307b088165d6f3070336056fa673f8f Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 19 Nov 2019 09:28:10 +0100 Subject: Re-indent arguments --- bot/cogs/moderation/modlog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py index 3c6731de6..945d7822b 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/cogs/moderation/modlog.py @@ -119,9 +119,9 @@ 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 + 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) -- cgit v1.2.3 From 461826cff98c66646d6f545fc1e711675ac6492f Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Wed, 27 Nov 2019 18:37:16 +0100 Subject: Move attachments re-uploading to DeletionContext.add() So they are re-uploaded before being deleted --- bot/cogs/antispam.py | 41 ++++++++++++++++++++++++++++++++++++----- bot/cogs/moderation/modlog.py | 30 +++++++++++------------------- 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.""" -- cgit v1.2.3 From 4a1ca965e2b83ea8690b3d7408464c8205432482 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Wed, 27 Nov 2019 18:41:57 +0100 Subject: Add try/except for attachment saving --- bot/cogs/antispam.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 8009c9d42..3118e0a42 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -7,7 +7,7 @@ from io import BytesIO from operator import itemgetter from typing import Dict, Iterable, List, Set -from discord import Colour, File, Member, Message, NotFound, Object, TextChannel +from discord import Colour, File, HTTPException, Member, Message, NotFound, Object, TextChannel from discord.ext.commands import Bot, Cog from bot import rules @@ -274,10 +274,13 @@ async def reupload_attachments( 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) + try: + 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) + except (HTTPException, NotFound): + log.warning(f"Tried to re-upload attchment {attachment.id}, but it has failed.") return out -- cgit v1.2.3 From bfde96aa4ee91a800d03106855afa22b958a92a2 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 28 Nov 2019 08:32:42 +0100 Subject: Fix misspelling Co-Authored-By: Mark --- bot/cogs/antispam.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 3118e0a42..0d3d0c4cc 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -280,7 +280,7 @@ async def reupload_attachments( reupload: Message = await channel.send(file=File(buffer, filename=attachment.filename)) out.append(reupload.attachments[0].url) except (HTTPException, NotFound): - log.warning(f"Tried to re-upload attchment {attachment.id}, but it has failed.") + log.warning(f"Tried to re-upload attachment {attachment.id}, but it has failed.") return out -- cgit v1.2.3 From 1c3220345c7b04956b584ccd072d596b1d790a5d Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 28 Nov 2019 09:13:32 +0100 Subject: Update try/except block in reupload_attachments() --- bot/cogs/antispam.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 0d3d0c4cc..6444b1f14 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -279,8 +279,11 @@ async def reupload_attachments( await attachment.save(buffer, use_cached=True) reupload: Message = await channel.send(file=File(buffer, filename=attachment.filename)) out.append(reupload.attachments[0].url) - except (HTTPException, NotFound): - log.warning(f"Tried to re-upload attachment {attachment.id}, but it has failed.") + except HTTPException: + log.warning( + f"Tried to re-upload attachment {attachment.filename} " + f"with ID {attachment.id} from message {message.id}, but it has failed." + ) return out -- cgit v1.2.3 From e669f282453b21a3e40564f4b28f9cb9454487b1 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Thu, 28 Nov 2019 09:17:19 +0100 Subject: Re-upload attachments to #attachment-log --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-default.yml b/config-default.yml index 9d2ee7941..6e8c01ad5 100644 --- a/config-default.yml +++ b/config-default.yml @@ -127,7 +127,7 @@ guild: staff_channels: [*ADMINS, *ADMIN_SPAM, *MOD_SPAM, *MODS, *HELPERS, *ORGANISATION, *DEFCON] ignored: [*ADMINS, *MESSAGE_LOG, *MODLOG] - attachment_repost: *MODLOG + attachment_repost: 649243850006855680 roles: admin: &ADMIN_ROLE 267628507062992896 -- cgit v1.2.3 From 17cedcb89b7b009fab68f3b1d39e968ace0a7c91 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 15:38:33 -0800 Subject: ModLog: use more generic type annotations --- bot/cogs/moderation/modlog.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py index 9251b79fb..6fffa7170 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/cogs/moderation/modlog.py @@ -35,10 +35,10 @@ class ModLog(Cog, name="ModLog"): self._cached_edits = [] async def upload_log( - self, - messages: t.List[discord.Message], - actor_id: int, - attachments: t.List[t.List[str]] = None + self, + messages: t.Iterable[discord.Message], + actor_id: int, + attachments: t.Iterable[t.List[str]] = None ) -> str: """ Uploads the log data to the database via an API endpoint for uploading logs. -- cgit v1.2.3 From e29b65c5a2b48e8870819453581c50bbcc2326bd Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 20:20:55 -0800 Subject: Utils: support returning URLs from send_attachments --- bot/utils/messages.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bot/utils/messages.py b/bot/utils/messages.py index 549b33ca6..40c20c7ec 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -1,7 +1,7 @@ import asyncio import contextlib from io import BytesIO -from typing import Optional, Sequence, Union +from typing import List, Optional, Sequence, Union from discord import Client, Embed, File, Member, Message, Reaction, TextChannel, Webhook from discord.abc import Snowflake @@ -51,14 +51,15 @@ async def wait_for_deletion( await message.delete() -async def send_attachments(message: Message, destination: Union[TextChannel, Webhook]) -> None: +async def send_attachments(message: Message, destination: Union[TextChannel, Webhook]) -> List[str]: """ - Re-uploads each attachment in a message to the given channel or webhook. + Re-upload the message's attachments to the destination and return a list of their new URLs. Each attachment is sent as a separate message to more easily comply with the 8 MiB request size limit. If attachments are too large, they are instead grouped into a single embed which links to them. """ large = [] + urls = [] for attachment in message.attachments: try: # This should avoid most files that are too large, but some may get through hence the try-catch. @@ -69,7 +70,8 @@ async def send_attachments(message: Message, destination: Union[TextChannel, Web attachment_file = File(file, filename=attachment.filename) if isinstance(destination, TextChannel): - await destination.send(file=attachment_file) + msg = await destination.send(file=attachment_file) + urls.append(msg.attachments[0].url) else: await destination.send( file=attachment_file, @@ -95,3 +97,5 @@ async def send_attachments(message: Message, destination: Union[TextChannel, Web username=message.author.display_name, avatar_url=message.author.avatar_url ) + + return urls -- cgit v1.2.3 From 336c6d523031b611ebc4823583c7d8b4ed1964c2 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 20:23:13 -0800 Subject: Utils: use the guild's filesize_limit to determine max attachment size --- bot/utils/messages.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bot/utils/messages.py b/bot/utils/messages.py index 40c20c7ec..fa1ee80b5 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -9,8 +9,6 @@ from discord.errors import HTTPException from bot.constants import Emojis -MAX_SIZE = 1024 * 1024 * 8 # 8 Mebibytes - async def wait_for_deletion( message: Message, @@ -62,9 +60,10 @@ async def send_attachments(message: Message, destination: Union[TextChannel, Web urls = [] for attachment in message.attachments: try: - # This should avoid most files that are too large, but some may get through hence the try-catch. # Allow 512 bytes of leeway for the rest of the request. - if attachment.size <= MAX_SIZE - 512: + # This should avoid most files that are too large, + # but some may get through hence the try-catch. + if attachment.size <= destination.guild.filesize_limit - 512: with BytesIO() as file: await attachment.save(file) attachment_file = File(file, filename=attachment.filename) -- cgit v1.2.3 From 4e414108ef3e098c24b9ab14fd09550673d87207 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 20:28:20 -0800 Subject: Utils: add send_attachments param to disable linking to too-large files --- bot/utils/messages.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/bot/utils/messages.py b/bot/utils/messages.py index fa1ee80b5..232d3cba6 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -49,12 +49,17 @@ async def wait_for_deletion( await message.delete() -async def send_attachments(message: Message, destination: Union[TextChannel, Webhook]) -> List[str]: +async def send_attachments( + message: Message, + destination: Union[TextChannel, Webhook], + link_large: bool = True +) -> List[str]: """ Re-upload the message's attachments to the destination and return a list of their new URLs. - Each attachment is sent as a separate message to more easily comply with the 8 MiB request size limit. - If attachments are too large, they are instead grouped into a single embed which links to them. + Each attachment is sent as a separate message to more easily comply with the request/file size + limit. If link_large is True, attachments which are too large are instead grouped into a single + embed which links to them. """ large = [] urls = [] @@ -77,17 +82,19 @@ async def send_attachments(message: Message, destination: Union[TextChannel, Web username=message.author.display_name, avatar_url=message.author.avatar_url ) - else: + elif link_large: large.append(attachment) except HTTPException as e: - if e.status == 413: + if link_large and e.status == 413: large.append(attachment) else: raise - if large: - embed = Embed(description=f"\n".join(f"[{attachment.filename}]({attachment.url})" for attachment in large)) + if link_large and large: + desc = f"\n".join(f"[{attachment.filename}]({attachment.url})" for attachment in large) + embed = Embed(description=desc) embed.set_footer(text="Attachments exceed upload size limit.") + if isinstance(destination, TextChannel): await destination.send(embed=embed) else: -- cgit v1.2.3 From 0f71c817320c077463a483701c6d51a8fa3e2164 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 20:29:23 -0800 Subject: Utils: log send_attachments failures instead of raising exceptions --- bot/utils/messages.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/bot/utils/messages.py b/bot/utils/messages.py index 232d3cba6..a39521b72 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -1,5 +1,6 @@ import asyncio import contextlib +import logging from io import BytesIO from typing import List, Optional, Sequence, Union @@ -9,6 +10,8 @@ from discord.errors import HTTPException from bot.constants import Emojis +log = logging.getLogger(__name__) + async def wait_for_deletion( message: Message, @@ -64,6 +67,10 @@ async def send_attachments( large = [] urls = [] for attachment in message.attachments: + failure_msg = ( + f"Failed to re-upload attachment {attachment.filename} from message {message.id}" + ) + try: # Allow 512 bytes of leeway for the rest of the request. # This should avoid most files that are too large, @@ -84,11 +91,13 @@ async def send_attachments( ) elif link_large: large.append(attachment) + else: + log.warning(f"{failure_msg} because it's too large.") except HTTPException as e: if link_large and e.status == 413: large.append(attachment) else: - raise + log.warning(f"{failure_msg} with status {e.status}.") if link_large and large: desc = f"\n".join(f"[{attachment.filename}]({attachment.url})" for attachment in large) -- cgit v1.2.3 From c4f80a54cdc02ea150d956d77bd739cf5c9564d6 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 20:31:21 -0800 Subject: Utils: have send_attachments save attachments using the cached URL This makes it more likely to successfully save an attachment after it's been deleted. --- bot/utils/messages.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/utils/messages.py b/bot/utils/messages.py index a39521b72..c4e2753e0 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -77,7 +77,7 @@ async def send_attachments( # but some may get through hence the try-catch. if attachment.size <= destination.guild.filesize_limit - 512: with BytesIO() as file: - await attachment.save(file) + await attachment.save(file, use_cached=True) attachment_file = File(file, filename=attachment.filename) if isinstance(destination, TextChannel): -- cgit v1.2.3 From 62d909b7bc0586a91c08b46c128a5eb5c5e6883e Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 20:32:23 -0800 Subject: AntiSpam: replace reupload_attachments with send_attachments from utils --- bot/cogs/antispam.py | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 6444b1f14..3a654cfaa 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -3,11 +3,10 @@ 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, File, HTTPException, Member, Message, NotFound, Object, TextChannel +from discord import Colour, Member, Message, NotFound, Object, TextChannel from discord.ext.commands import Bot, Cog from bot import rules @@ -19,6 +18,7 @@ from bot.constants import ( STAFF_ROLES, ) from bot.converters import Duration +from bot.utils.messages import send_attachments log = logging.getLogger(__name__) @@ -60,8 +60,10 @@ 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)) + # Re-upload attachments + destination = self.bot.get_channel(GuildConfig.attachment_repost) + urls = await send_attachments(message, destination, link_large=False) + self.attachments.append(urls) async def upload_messages(self, actor_id: int, modlog: ModLog) -> None: """Method that takes care of uploading the queue and posting modlog alert.""" @@ -263,30 +265,6 @@ 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: - try: - 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) - except HTTPException: - log.warning( - f"Tried to re-upload attachment {attachment.filename} " - f"with ID {attachment.id} from message {message.id}, but it has failed." - ) - return out - - def validate_config(rules: Mapping = AntiSpamConfig.rules) -> Dict[str, str]: """Validates the antispam configs.""" validation_errors = {} -- cgit v1.2.3 From 2af995cdf483bf1b8a927768566d9a27cf8a07cf Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 21:07:17 -0800 Subject: AntiSpam: correct a function annotation --- bot/cogs/antispam.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 3a654cfaa..1a60897c9 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -105,7 +105,7 @@ class DeletionContext: class AntiSpam(Cog): """Cog that controls our anti-spam measures.""" - def __init__(self, bot: Bot, validation_errors: bool) -> None: + def __init__(self, bot: Bot, validation_errors: Dict[str, str]) -> None: self.bot = bot self.validation_errors = validation_errors role_id = AntiSpamConfig.punishment['role_id'] @@ -265,10 +265,10 @@ class AntiSpam(Cog): await deletion_context.upload_messages(self.bot.user.id, self.mod_log) -def validate_config(rules: Mapping = AntiSpamConfig.rules) -> Dict[str, str]: +def validate_config(_rules: Mapping = AntiSpamConfig.rules) -> Dict[str, str]: """Validates the antispam configs.""" validation_errors = {} - for name, config in rules.items(): + for name, config in _rules.items(): if name not in RULE_FUNCTION_MAPPING: log.error( f"Unrecognized antispam rule `{name}`. " -- cgit v1.2.3 From 56c1e01e3059a7163e01df5282265c1053b419c3 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 21:36:37 -0800 Subject: ModLog: fix 0 message logs uploaded when no attachments given --- bot/cogs/moderation/modlog.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py index 6fffa7170..801582a6b 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/cogs/moderation/modlog.py @@ -2,6 +2,7 @@ import asyncio import logging import typing as t from datetime import datetime +from itertools import zip_longest import discord from dateutil.relativedelta import relativedelta @@ -40,13 +41,7 @@ class ModLog(Cog, name="ModLog"): actor_id: int, attachments: t.Iterable[t.List[str]] = None ) -> str: - """ - Uploads the log data to the database via an API endpoint for uploading logs. - - Used in several mod log embeds. - - Returns a URL that can be used to view the log. - """ + """Upload message logs to the database and return a URL to a page for viewing the logs.""" if attachments is None: attachments = [] @@ -64,7 +59,7 @@ class ModLog(Cog, name="ModLog"): 'embeds': [embed.to_dict() for embed in message.embeds], 'attachments': attachment, } - for message, attachment in zip(messages, attachments) + for message, attachment in zip_longest(messages, attachments) ] } ) -- cgit v1.2.3 From 400f7c85da237a118024a4fb4e73802c8700fc46 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 3 Dec 2019 21:43:15 -0800 Subject: AntiSpam: remove bot field from DeletionContext The destination channel can be retrieved be accessing a message's guild. * Remove unused queue_consumption_tasks attribute. --- bot/cogs/antispam.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 1a60897c9..669c62c75 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -42,7 +42,6 @@ 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) @@ -61,7 +60,7 @@ class DeletionContext: self.messages[message.id] = message # Re-upload attachments - destination = self.bot.get_channel(GuildConfig.attachment_repost) + destination = message.guild.get_channel(GuildConfig.attachment_repost) urls = await send_attachments(message, destination, link_large=False) self.attachments.append(urls) @@ -77,7 +76,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, attachments=self.attachments) + url = await modlog.upload_log(self.messages.values(), actor_id, self.attachments) mod_alert_message += f"A complete log of the offending messages can be found [here]({url})" else: mod_alert_message += "Message:\n" @@ -113,7 +112,6 @@ class AntiSpam(Cog): self.expiration_date_converter = Duration() self.message_deletion_queue = dict() - self.queue_consumption_tasks = dict() self.bot.loop.create_task(self.alert_on_validation_error()) @@ -187,15 +185,11 @@ class AntiSpam(Cog): full_reason = f"`{rule_name}` rule: {reason}" # 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, - bot=self.bot - ) - self.queue_consumption_tasks = self.bot.loop.create_task( - self._process_deletion_context(message.channel.id) - ) + channel = message.channel + if channel.id not in self.message_deletion_queue: + log.trace(f"Creating queue for channel `{channel.id}`") + self.message_deletion_queue[message.channel.id] = DeletionContext(channel) + self.bot.loop.create_task(self._process_deletion_context(message.channel.id)) # Add the relevant of this trigger to the Deletion Context await self.message_deletion_queue[message.channel.id].add( @@ -212,7 +206,7 @@ class AntiSpam(Cog): self.punish(message, member, full_reason) ) - await self.maybe_delete_messages(message.channel, relevant_messages) + await self.maybe_delete_messages(channel, relevant_messages) break async def punish(self, msg: Message, member: Member, reason: str) -> None: -- cgit v1.2.3 From 75f00f3574bcee36f204fc3e5806b3bd91c91829 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sat, 14 Dec 2019 12:06:42 +0100 Subject: Relay attchments to #attachment_log --- config-default.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config-default.yml b/config-default.yml index b2f513bd3..0ecf88702 100644 --- a/config-default.yml +++ b/config-default.yml @@ -102,6 +102,7 @@ guild: admins: &ADMINS 365960823622991872 admin_spam: &ADMIN_SPAM 563594791770914816 announcements: 354619224620138496 + attachment_log: &ATTCH_LOG 649243850006855680 big_brother_logs: &BBLOGS 468507907357409333 bot: 267659945086812160 checkpoint_test: 422077681434099723 @@ -138,7 +139,7 @@ guild: staff_channels: [*ADMINS, *ADMIN_SPAM, *MOD_SPAM, *MODS, *HELPERS, *ORGANISATION, *DEFCON] ignored: [*ADMINS, *MESSAGE_LOG, *MODLOG] - attachment_repost: 649243850006855680 + attachment_repost: *ATTCH_LOG roles: admin: &ADMIN_ROLE 267628507062992896 -- cgit v1.2.3 From 68709884494b755739723c725f9998d02d17dde3 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sun, 2 Feb 2020 22:20:44 +0000 Subject: Remove prometheus related code --- Pipfile | 1 - Pipfile.lock | 297 ++++++++++++++++++++++------------------------------ bot/__main__.py | 1 - bot/bot.py | 3 - bot/cogs/metrics.py | 98 ----------------- 5 files changed, 128 insertions(+), 272 deletions(-) delete mode 100644 bot/cogs/metrics.py diff --git a/Pipfile b/Pipfile index 68362ae78..48d839fc3 100644 --- a/Pipfile +++ b/Pipfile @@ -19,7 +19,6 @@ deepdiff = "~=4.0" requests = "~=2.22" more_itertools = "~=7.2" urllib3 = ">=1.24.2,<1.25" -prometheus-async = {extras = ["aiohttp"],version = "~=19.2"} [dev-packages] coverage = "~=4.5" diff --git a/Pipfile.lock b/Pipfile.lock index ab5dfb538..279480d2a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "d9349e8c704b2b2403004039856d8d75aaebc76e4aa93390c4d177f583e73b71" + "sha256": "c27d699b4aeeed204dee41f924f682ae2a670add8549a8826e58776594370582" }, "pipfile-spec": 6, "requires": { @@ -34,31 +34,21 @@ }, "aiohttp": { "hashes": [ - "sha256:00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55", - "sha256:0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed", - "sha256:09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10", - "sha256:199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5", - "sha256:296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1", - "sha256:368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939", - "sha256:40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390", - "sha256:629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa", - "sha256:6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc", - "sha256:87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5", - "sha256:9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d", - "sha256:9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf", - "sha256:9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6", - "sha256:a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72", - "sha256:a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12", - "sha256:a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366", - "sha256:acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4", - "sha256:b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300", - "sha256:c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d", - "sha256:cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303", - "sha256:d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6", - "sha256:e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889" + "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e", + "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326", + "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a", + "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654", + "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a", + "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4", + "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17", + "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec", + "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd", + "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48", + "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59", + "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965" ], "index": "pypi", - "version": "==3.5.4" + "version": "==3.6.2" }, "aiormq": { "hashes": [ @@ -157,26 +147,25 @@ }, "deepdiff": { "hashes": [ - "sha256:3457ea7cecd51ba48015d89edbb569358af4d9b9e65e28bdb3209608420627f9", - "sha256:5e2343398e90538edaa59c0c99207e996a3a834fdc878c666376f632a760c35a" + "sha256:b3fa588d1eac7fa318ec1fb4f2004568e04cb120a1989feda8e5e7164bcbf07a", + "sha256:ed7342d3ed3c0c2058a3fb05b477c943c9959ef62223dca9baa3375718a25d87" ], "index": "pypi", - "version": "==4.0.9" + "version": "==4.2.0" }, "discord-py": { "hashes": [ - "sha256:7c843b523bb011062b453864e75c7b675a03faf573c58d14c9f096e85984329d" + "sha256:8bfe5628d31771744000f19135c386c74ac337479d7282c26cc1627b9d31f360" ], "index": "pypi", - "version": "==1.2.5" + "version": "==1.3.1" }, "docutils": { "hashes": [ - "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0", - "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827", - "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99" + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" ], - "version": "==0.15.2" + "version": "==0.16" }, "fuzzywuzzy": { "hashes": [ @@ -202,17 +191,10 @@ }, "jinja2": { "hashes": [ - "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f", - "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de" + "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", + "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" ], - "version": "==2.10.3" - }, - "jsonpickle": { - "hashes": [ - "sha256:d0c5a4e6cb4e58f6d5406bdded44365c2bcf9c836c4f52910cc9ba7245a59dc2", - "sha256:d3e922d781b1d0096df2dad89a2e1f47177d7969b596aea806a9d91b4626b29b" - ], - "version": "==1.2" + "version": "==2.11.1" }, "logmatic-python": { "hashes": [ @@ -223,35 +205,36 @@ }, "lxml": { "hashes": [ - "sha256:00ac0d64949fef6b3693813fe636a2d56d97a5a49b5bbb86e4cc4cc50ebc9ea2", - "sha256:0571e607558665ed42e450d7bf0e2941d542c18e117b1ebbf0ba72f287ad841c", - "sha256:0e3f04a7615fdac0be5e18b2406529521d6dbdb0167d2a690ee328bef7807487", - "sha256:13cf89be53348d1c17b453867da68704802966c433b2bb4fa1f970daadd2ef70", - "sha256:217262fcf6a4c2e1c7cb1efa08bd9ebc432502abc6c255c4abab611e8be0d14d", - "sha256:223e544828f1955daaf4cefbb4853bc416b2ec3fd56d4f4204a8b17007c21250", - "sha256:277cb61fede2f95b9c61912fefb3d43fbd5f18bf18a14fae4911b67984486f5d", - "sha256:3213f753e8ae86c396e0e066866e64c6b04618e85c723b32ecb0909885211f74", - "sha256:4690984a4dee1033da0af6df0b7a6bde83f74e1c0c870623797cec77964de34d", - "sha256:4fcc472ef87f45c429d3b923b925704aa581f875d65bac80f8ab0c3296a63f78", - "sha256:61409bd745a265a742f2693e4600e4dbd45cc1daebe1d5fad6fcb22912d44145", - "sha256:678f1963f755c5d9f5f6968dded7b245dd1ece8cf53c1aa9d80e6734a8c7f41d", - "sha256:6c6d03549d4e2734133badb9ab1c05d9f0ef4bcd31d83e5d2b4747c85cfa21da", - "sha256:6e74d5f4d6ecd6942375c52ffcd35f4318a61a02328f6f1bd79fcb4ffedf969e", - "sha256:7b4fc7b1ecc987ca7aaf3f4f0e71bbfbd81aaabf87002558f5bc95da3a865bcd", - "sha256:7ed386a40e172ddf44c061ad74881d8622f791d9af0b6f5be20023029129bc85", - "sha256:8f54f0924d12c47a382c600c880770b5ebfc96c9fd94cf6f6bdc21caf6163ea7", - "sha256:ad9b81351fdc236bda538efa6879315448411a81186c836d4b80d6ca8217cdb9", - "sha256:bbd00e21ea17f7bcc58dccd13869d68441b32899e89cf6cfa90d624a9198ce85", - "sha256:c3c289762cc09735e2a8f8a49571d0e8b4f57ea831ea11558247b5bdea0ac4db", - "sha256:cf4650942de5e5685ad308e22bcafbccfe37c54aa7c0e30cd620c2ee5c93d336", - "sha256:cfcbc33c9c59c93776aa41ab02e55c288a042211708b72fdb518221cc803abc8", - "sha256:e301055deadfedbd80cf94f2f65ff23126b232b0d1fea28f332ce58137bcdb18", - "sha256:ebbfe24df7f7b5c6c7620702496b6419f6a9aa2fd7f005eb731cc80d7b4692b9", - "sha256:eff69ddbf3ad86375c344339371168640951c302450c5d3e9936e98d6459db06", - "sha256:f6ed60a62c5f1c44e789d2cf14009423cb1646b44a43e40a9cf6a21f077678a1" - ], - "index": "pypi", - "version": "==4.4.2" + "sha256:06d4e0bbb1d62e38ae6118406d7cdb4693a3fa34ee3762238bcb96c9e36a93cd", + "sha256:0701f7965903a1c3f6f09328c1278ac0eee8f56f244e66af79cb224b7ef3801c", + "sha256:1f2c4ec372bf1c4a2c7e4bb20845e8bcf8050365189d86806bad1e3ae473d081", + "sha256:4235bc124fdcf611d02047d7034164897ade13046bda967768836629bc62784f", + "sha256:5828c7f3e615f3975d48f40d4fe66e8a7b25f16b5e5705ffe1d22e43fb1f6261", + "sha256:585c0869f75577ac7a8ff38d08f7aac9033da2c41c11352ebf86a04652758b7a", + "sha256:5d467ce9c5d35b3bcc7172c06320dddb275fea6ac2037f72f0a4d7472035cea9", + "sha256:63dbc21efd7e822c11d5ddbedbbb08cd11a41e0032e382a0fd59b0b08e405a3a", + "sha256:7bc1b221e7867f2e7ff1933165c0cec7153dce93d0cdba6554b42a8beb687bdb", + "sha256:8620ce80f50d023d414183bf90cc2576c2837b88e00bea3f33ad2630133bbb60", + "sha256:8a0ebda56ebca1a83eb2d1ac266649b80af8dd4b4a3502b2c1e09ac2f88fe128", + "sha256:90ed0e36455a81b25b7034038e40880189169c308a3df360861ad74da7b68c1a", + "sha256:95e67224815ef86924fbc2b71a9dbd1f7262384bca4bc4793645794ac4200717", + "sha256:afdb34b715daf814d1abea0317b6d672476b498472f1e5aacbadc34ebbc26e89", + "sha256:b4b2c63cc7963aedd08a5f5a454c9f67251b1ac9e22fd9d72836206c42dc2a72", + "sha256:d068f55bda3c2c3fcaec24bd083d9e2eede32c583faf084d6e4b9daaea77dde8", + "sha256:d5b3c4b7edd2e770375a01139be11307f04341ec709cf724e0f26ebb1eef12c3", + "sha256:deadf4df349d1dcd7b2853a2c8796593cc346600726eff680ed8ed11812382a7", + "sha256:df533af6f88080419c5a604d0d63b2c33b1c0c4409aba7d0cb6de305147ea8c8", + "sha256:e4aa948eb15018a657702fee0b9db47e908491c64d36b4a90f59a64741516e77", + "sha256:e5d842c73e4ef6ed8c1bd77806bf84a7cb535f9c0cf9b2c74d02ebda310070e1", + "sha256:ebec08091a22c2be870890913bdadd86fcd8e9f0f22bcb398abd3af914690c15", + "sha256:edc15fcfd77395e24543be48871c251f38132bb834d9fdfdad756adb6ea37679", + "sha256:f2b74784ed7e0bc2d02bd53e48ad6ba523c9b36c194260b7a5045071abbb1012", + "sha256:fa071559f14bd1e92077b1b5f6c22cf09756c6de7139370249eb372854ce51e6", + "sha256:fd52e796fee7171c4361d441796b64df1acfceb51f29e545e812f16d023c4bbc", + "sha256:fe976a0f1ef09b3638778024ab9fb8cde3118f203364212c198f71341c0715ca" + ], + "index": "pypi", + "version": "==4.5.0" }, "markdownify": { "hashes": [ @@ -266,13 +249,16 @@ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", @@ -289,7 +275,9 @@ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" ], "version": "==1.1.1" }, @@ -331,10 +319,10 @@ }, "packaging": { "hashes": [ - "sha256:aec3fdbb8bc9e4bb65f0634b9f551ced63983a529d6a8931817d52fdd0816ddb", - "sha256:fe1d8331dfa7cc0a883b49d75fc76380b2ab2734b220fbb87d774e4fd4b851f8" + "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73", + "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334" ], - "version": "==20.0" + "version": "==20.1" }, "pamqp": { "hashes": [ @@ -343,23 +331,6 @@ ], "version": "==2.3.0" }, - "prometheus-async": { - "extras": [ - "aiohttp" - ], - "hashes": [ - "sha256:227f516e5bf98a0dc602348381e182358f8b2ed24a8db05e8e34d9cf027bab83", - "sha256:3cc68d1f39e9bbf16dbd0b51103d87671b3cbd1d75a72cda472cd9a35cc9d0d2" - ], - "index": "pypi", - "version": "==19.2.0" - }, - "prometheus-client": { - "hashes": [ - "sha256:71cd24a2b3eb335cb800c7159f423df1bd4dcd5171b234be15e3f31ec9f622da" - ], - "version": "==0.7.1" - }, "pycares": { "hashes": [ "sha256:050f00b39ed77ea8a4e555f09417d4b1a6b5baa24bb9531a3e15d003d2319b3f", @@ -462,10 +433,10 @@ }, "six": { "hashes": [ - "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", - "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "version": "==1.13.0" + "version": "==1.14.0" }, "snowballstemmer": { "hashes": [ @@ -541,35 +512,30 @@ }, "websockets": { "hashes": [ - "sha256:0e2f7d6567838369af074f0ef4d0b802d19fa1fee135d864acc656ceefa33136", - "sha256:2a16dac282b2fdae75178d0ed3d5b9bc3258dabfae50196cbb30578d84b6f6a6", - "sha256:5a1fa6072405648cb5b3688e9ed3b94be683ce4a4e5723e6f5d34859dee495c1", - "sha256:5c1f55a1274df9d6a37553fef8cff2958515438c58920897675c9bc70f5a0538", - "sha256:669d1e46f165e0ad152ed8197f7edead22854a6c90419f544e0f234cc9dac6c4", - "sha256:695e34c4dbea18d09ab2c258994a8bf6a09564e762655408241f6a14592d2908", - "sha256:6b2e03d69afa8d20253455e67b64de1a82ff8612db105113cccec35d3f8429f0", - "sha256:79ca7cdda7ad4e3663ea3c43bfa8637fc5d5604c7737f19a8964781abbd1148d", - "sha256:7fd2dd9a856f72e6ed06f82facfce01d119b88457cd4b47b7ae501e8e11eba9c", - "sha256:82c0354ac39379d836719a77ee360ef865377aa6fdead87909d50248d0f05f4d", - "sha256:8f3b956d11c5b301206382726210dc1d3bee1a9ccf7aadf895aaf31f71c3716c", - "sha256:91ec98640220ae05b34b79ee88abf27f97ef7c61cf525eec57ea8fcea9f7dddb", - "sha256:952be9540d83dba815569d5cb5f31708801e0bbfc3a8c5aef1890b57ed7e58bf", - "sha256:99ac266af38ba1b1fe13975aea01ac0e14bb5f3a3200d2c69f05385768b8568e", - "sha256:9fa122e7adb24232247f8a89f2d9070bf64b7869daf93ac5e19546b409e47e96", - "sha256:a0873eadc4b8ca93e2e848d490809e0123eea154aa44ecd0109c4d0171869584", - "sha256:cb998bd4d93af46b8b49ecf5a72c0a98e5cc6d57fdca6527ba78ad89d6606484", - "sha256:e02e57346f6a68523e3c43bbdf35dde5c440318d1f827208ae455f6a2ace446d", - "sha256:e79a5a896bcee7fff24a788d72e5c69f13e61369d055f28113e71945a7eb1559", - "sha256:ee55eb6bcf23ecc975e6b47c127c201b913598f38b6a300075f84eeef2d3baff", - "sha256:f1414e6cbcea8d22843e7eafdfdfae3dd1aba41d1945f6ca66e4806c07c4f454" - ], - "version": "==6.0" - }, - "wrapt": { - "hashes": [ - "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1" - ], - "version": "==1.11.2" + "sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5", + "sha256:1d3f1bf059d04a4e0eb4985a887d49195e15ebabc42364f4eb564b1d065793f5", + "sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308", + "sha256:295359a2cc78736737dd88c343cd0747546b2174b5e1adc223824bcaf3e164cb", + "sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a", + "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c", + "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170", + "sha256:3ef56fcc7b1ff90de46ccd5a687bbd13a3180132268c4254fc0fa44ecf4fc422", + "sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8", + "sha256:5c01fd846263a75bc8a2b9542606927cfad57e7282965d96b93c387622487485", + "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f", + "sha256:751a556205d8245ff94aeef23546a1113b1dd4f6e4d102ded66c39b99c2ce6c8", + "sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc", + "sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779", + "sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989", + "sha256:9bef37ee224e104a413f0780e29adb3e514a5b698aabe0d969a6ba426b8435d1", + "sha256:c1ec8db4fac31850286b7cd3b9c0e1b944204668b8eb721674916d4e28744092", + "sha256:c8a116feafdb1f84607cb3b14aa1418424ae71fee131642fc568d21423b51824", + "sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d", + "sha256:d705f8aeecdf3262379644e4b55107a3b55860eb812b673b28d0fbc347a60c55", + "sha256:e898a0863421650f0bebac8ba40840fc02258ef4714cb7e1fd76b6a6354bda36", + "sha256:f8a7bff6e8664afc4e6c28b983845c5bc14965030e3fb98789734d416af77c4b" + ], + "version": "==8.1" }, "yarl": { "hashes": [ @@ -762,10 +728,10 @@ }, "identify": { "hashes": [ - "sha256:6f44e637caa40d1b4cb37f6ed3b262ede74901d28b1cc5b1fc07360871edd65d", - "sha256:72e9c4ed3bc713c7045b762b0d2e2115c572b85abfc1f4604f5a4fd4c6642b71" + "sha256:1222b648251bdcb8deb240b294f450fbf704c7984e08baa92507e4ea10b436d5", + "sha256:d824ebe21f38325c771c41b08a95a761db1982f1fc0eee37c6c97df3f1636b96" ], - "version": "==1.4.9" + "version": "==1.4.11" }, "idna": { "hashes": [ @@ -776,11 +742,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:bdd9b7c397c273bcc9a11d6629a38487cd07154fa255a467bf704cd2c258e359", - "sha256:f17c015735e1a88296994c0697ecea7e11db24290941983b08c9feb30921e6d8" + "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302", + "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b" ], "markers": "python_version < '3.8'", - "version": "==1.4.0" + "version": "==1.5.0" }, "mccabe": { "hashes": [ @@ -789,14 +755,6 @@ ], "version": "==0.6.1" }, - "more-itertools": { - "hashes": [ - "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", - "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" - ], - "index": "pypi", - "version": "==7.2.0" - }, "nodeenv": { "hashes": [ "sha256:561057acd4ae3809e665a9aaaf214afff110bbb6a6d5c8a96121aea6878408b3" @@ -805,10 +763,10 @@ }, "packaging": { "hashes": [ - "sha256:aec3fdbb8bc9e4bb65f0634b9f551ced63983a529d6a8931817d52fdd0816ddb", - "sha256:fe1d8331dfa7cc0a883b49d75fc76380b2ab2734b220fbb87d774e4fd4b851f8" + "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73", + "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334" ], - "version": "==20.0" + "version": "==20.1" }, "pre-commit": { "hashes": [ @@ -881,10 +839,10 @@ }, "six": { "hashes": [ - "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", - "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "version": "==1.13.0" + "version": "==1.14.0" }, "snowballstemmer": { "hashes": [ @@ -902,29 +860,30 @@ }, "typed-ast": { "hashes": [ - "sha256:1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161", - "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", - "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", - "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", - "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", - "sha256:48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47", - "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", - "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", - "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", - "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", - "sha256:7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2", - "sha256:838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e", - "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", - "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", - "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", - "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", - "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", - "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", - "sha256:fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66", - "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" + "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", + "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", + "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", + "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", + "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", + "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", + "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", + "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", + "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", + "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", + "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", + "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", + "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", + "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", + "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", + "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", + "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", + "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", + "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", + "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", + "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" ], "markers": "python_version < '3.8'", - "version": "==1.4.0" + "version": "==1.4.1" }, "unittest-xml-reporting": { "hashes": [ @@ -951,10 +910,10 @@ }, "zipp": { "hashes": [ - "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", - "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" + "sha256:ccc94ed0909b58ffe34430ea5451f07bc0c76467d7081619a454bf5c98b89e28", + "sha256:feae2f18633c32fc71f2de629bfb3bd3c9325cd4419642b1f1da42ee488d9b98" ], - "version": "==0.6.0" + "version": "==2.1.0" } } } diff --git a/bot/__main__.py b/bot/__main__.py index 61271a692..84bc7094b 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -40,7 +40,6 @@ bot.load_extension("bot.cogs.duck_pond") bot.load_extension("bot.cogs.free") bot.load_extension("bot.cogs.information") bot.load_extension("bot.cogs.jams") -bot.load_extension("bot.cogs.metrics") bot.load_extension("bot.cogs.moderation") bot.load_extension("bot.cogs.off_topic_names") bot.load_extension("bot.cogs.reddit") diff --git a/bot/bot.py b/bot/bot.py index 930aaf70e..8f808272f 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -4,7 +4,6 @@ from typing import Optional import aiohttp from discord.ext import commands -from prometheus_async.aio.web import start_http_server as start_prometheus_http_server from bot import api @@ -51,6 +50,4 @@ class Bot(commands.Bot): """Open an aiohttp session before logging in and connecting to Discord.""" self.http_session = aiohttp.ClientSession(connector=self.connector) - await start_prometheus_http_server(addr="0.0.0.0", port=9330) - log.debug("Started Prometheus server on port 9330.") await super().start(*args, **kwargs) diff --git a/bot/cogs/metrics.py b/bot/cogs/metrics.py deleted file mode 100644 index 47c3cc55e..000000000 --- a/bot/cogs/metrics.py +++ /dev/null @@ -1,98 +0,0 @@ -from collections import defaultdict - -from discord import Member, Message -from discord.ext.commands import Cog, Context -from prometheus_client import Counter, Gauge - -from bot.bot import Bot - - -class Metrics(Cog): - """ - Exports metrics for Prometheus. - - See https://github.com/prometheus/client_python for metric documentation. - """ - - PREFIX = 'pydis_bot' - - def __init__(self, bot: Bot) -> None: - self.bot = bot - - self.guild_members = Gauge( - name=f'{self.PREFIX}_guild_members', - documentation="Total members by guild by status.", - labelnames=('guild_id', 'status') - ) - self.guild_messages = Counter( - name=f'{self.PREFIX}_guild_messages', - documentation="Guild messages by guild by channel.", - labelnames=('channel_id', 'guild_id', 'channel_name') - ) - self.command_completions = Counter( - name=f'{self.PREFIX}_command_completions', - documentation="Completed commands by command, user, and guild.", - labelnames=('guild_id', 'user_id', 'user_name', 'command') - ) - - @Cog.listener() - async def on_ready(self) -> None: - """Initialize the guild member counter.""" - members_by_status = defaultdict(lambda: defaultdict(int)) - - for guild in self.bot.guilds: - if guild.large: - await self.bot.request_offline_members(guild) - for member in guild.members: - members_by_status[guild.id][member.status] += 1 - - for guild_id, members in members_by_status.items(): - for status, count in members.items(): - self.guild_members.labels(guild_id=guild_id, status=str(status)).set(count) - - @Cog.listener() - async def on_member_join(self, member: Member) -> None: - """Increment the member gauge.""" - self.guild_members.labels(guild_id=member.guild.id, status=str(member.status)).inc() - - @Cog.listener() - async def on_member_leave(self, member: Member) -> None: - """Decrement the member gauge.""" - self.guild_members.labels(guild_id=member.guild.id, status=str(member.status)).dec() - - @Cog.listener() - async def on_member_update(self, before: Member, after: Member) -> None: - """Update member gauges for the new and old status if applicable.""" - if before.status is not after.status: - self.guild_members.labels(guild_id=after.guild.id, status=str(before.status)).dec() - self.guild_members.labels(guild_id=after.guild.id, status=str(after.status)).inc() - - @Cog.listener() - async def on_message(self, message: Message) -> None: - """Increment the guild message counter.""" - self.guild_messages.labels( - channel_id=message.channel.id, - channel_name=message.channel.name, - guild_id=message.guild.id, - ).inc() - - @Cog.listener() - async def on_command_completion(self, ctx: Context) -> None: - """Increment the command completion counter.""" - if ctx.message.guild is not None: - if ctx.command.full_parent_name: - command = f'{ctx.command.full_parent_name} {ctx.command.name}' - else: - command = ctx.command.name - - self.command_completions.labels( - guild_id=ctx.message.guild.id, - user_id=ctx.author.id, - user_name=str(ctx.author), - command=command, - ).inc() - - -def setup(bot: Bot) -> None: - """Load the Metrics cog.""" - bot.add_cog(Metrics(bot)) -- cgit v1.2.3 From ae388820dc45f12b6486dfa793aecb9ba5f0345b Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 3 Feb 2020 13:27:07 +0000 Subject: Replace constant attachment-repost by the actual ID of #attachment-log --- bot/cogs/antispam.py | 2 +- bot/constants.py | 2 +- config-default.yml | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 80f82ab91..bbc1a5359 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -61,7 +61,7 @@ class DeletionContext: self.messages[message.id] = message # Re-upload attachments - destination = message.guild.get_channel(GuildConfig.attachment_repost) + destination = message.guild.get_channel(Channels.attachment_log) urls = await send_attachments(message, destination, link_large=False) self.attachments.append(urls) diff --git a/bot/constants.py b/bot/constants.py index 9a4522262..2050359cd 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -347,6 +347,7 @@ class Channels(metaclass=YAMLGetter): admins: int admin_spam: int announcements: int + attachment_repost: int big_brother_logs: int bot: int checkpoint_test: int @@ -417,7 +418,6 @@ class Guild(metaclass=YAMLGetter): id: int ignored: List[int] staff_channels: List[int] - attachment_repost: int class Keys(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 0ecf88702..5e85c897d 100644 --- a/config-default.yml +++ b/config-default.yml @@ -138,8 +138,7 @@ guild: verification: 352442727016693763 staff_channels: [*ADMINS, *ADMIN_SPAM, *MOD_SPAM, *MODS, *HELPERS, *ORGANISATION, *DEFCON] - ignored: [*ADMINS, *MESSAGE_LOG, *MODLOG] - attachment_repost: *ATTCH_LOG + ignored: [*ADMINS, *MESSAGE_LOG, *MODLOG, *ATTCH_LOG] roles: admin: &ADMIN_ROLE 267628507062992896 -- cgit v1.2.3 From 891257d1d9fc903fc007272b32bf15f315fffe99 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 3 Feb 2020 13:40:49 +0000 Subject: Change typehint name for the attachment-log constant --- bot/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/constants.py b/bot/constants.py index 223ebdaea..629985bdf 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -359,7 +359,7 @@ class Channels(metaclass=YAMLGetter): admins: int admin_spam: int announcements: int - attachment_repost: int + attachment_log: int big_brother_logs: int bot: int checkpoint_test: int -- cgit v1.2.3 From 2dc728e2d43448c67d87aa32e12598e5068c4353 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Tue, 4 Feb 2020 00:53:00 +1000 Subject: Use a trailing underscore to avoid name conflicts. Previously used a leading underscore, but that's usually meant for non-used names. --- bot/cogs/antispam.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index bbc1a5359..f67ef6f05 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -260,10 +260,10 @@ class AntiSpam(Cog): await deletion_context.upload_messages(self.bot.user.id, self.mod_log) -def validate_config(_rules: Mapping = AntiSpamConfig.rules) -> Dict[str, str]: +def validate_config(rules_: Mapping = AntiSpamConfig.rules) -> Dict[str, str]: """Validates the antispam configs.""" validation_errors = {} - for name, config in _rules.items(): + for name, config in rules_.items(): if name not in RULE_FUNCTION_MAPPING: log.error( f"Unrecognized antispam rule `{name}`. " -- cgit v1.2.3 From df023e0b03795a2a7f30d3ab523fc2998f226234 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Wed, 5 Feb 2020 22:45:18 +1000 Subject: Move tools and questions guide to under resources After the wiki pages adjustment to the resources page, these two urls are needing to be updated to point to the new correct locations for each page. Tools will be under resources, and Asking Good Questions is a guide, so will be under Guides. --- bot/cogs/site.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/cogs/site.py b/bot/cogs/site.py index 2ea8c7a2e..10180ebae 100644 --- a/bot/cogs/site.py +++ b/bot/cogs/site.py @@ -59,7 +59,7 @@ class Site(Cog): @site_group.command(name="tools") async def site_tools(self, ctx: Context) -> None: """Info about the site's Tools page.""" - tools_url = f"{PAGES_URL}/tools" + tools_url = f"{PAGES_URL}/resources/tools" embed = Embed(title="Tools") embed.set_footer(text=f"{tools_url}") @@ -74,7 +74,7 @@ class Site(Cog): @site_group.command(name="help") async def site_help(self, ctx: Context) -> None: """Info about the site's Getting Help page.""" - url = f"{PAGES_URL}/asking-good-questions" + url = f"{PAGES_URL}resources/guides/asking-good-questions" embed = Embed(title="Asking Good Questions") embed.set_footer(text=url) -- cgit v1.2.3 From b9c691646a8be52095f644ba2cd7ffd8eb36ae6e Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Thu, 6 Feb 2020 01:01:29 +1000 Subject: Add missing slash to asking good questions url. --- bot/cogs/site.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/site.py b/bot/cogs/site.py index 10180ebae..853e29568 100644 --- a/bot/cogs/site.py +++ b/bot/cogs/site.py @@ -74,7 +74,7 @@ class Site(Cog): @site_group.command(name="help") async def site_help(self, ctx: Context) -> None: """Info about the site's Getting Help page.""" - url = f"{PAGES_URL}resources/guides/asking-good-questions" + url = f"{PAGES_URL}/resources/guides/asking-good-questions" embed = Embed(title="Asking Good Questions") embed.set_footer(text=url) -- cgit v1.2.3