diff options
| author | 2019-07-03 16:31:05 +0200 | |
|---|---|---|
| committer | 2019-07-03 16:31:05 +0200 | |
| commit | d8fc80cefa272901e27e54564298596ab7ce4514 (patch) | |
| tree | 5e2bded310eb605796c0df1b832c3d98987b432e | |
| parent | Applying changes requested in the reviews. (diff) | |
Applied the following changes requested by reviews:
- Bot responses are now plain messages instead of embeds;
- The message history in the WatchChannel cog is now stored using a new dataclass, MessageHistory;
- Removed the truncation option from the modified name field in logging;
- bigbrother now provides user feedback when watching fails due to failing cache update;
- Changed the lay-out of the mod_log alert and set ping_everyone to True;
- Changed the function signature of `post_infraction` utility function to the one-parameter-per-line style;
- Moved the declaration of File within bot/utils/messages.py to before the if/else to make things DRY.
| -rw-r--r-- | bot/__init__.py | 2 | ||||
| -rw-r--r-- | bot/cogs/watchchannels/bigbrother.py | 35 | ||||
| -rw-r--r-- | bot/cogs/watchchannels/talentpool.py | 64 | ||||
| -rw-r--r-- | bot/cogs/watchchannels/watchchannel.py | 25 | ||||
| -rw-r--r-- | bot/utils/messages.py | 6 | ||||
| -rw-r--r-- | bot/utils/moderation.py | 9 |
6 files changed, 50 insertions, 91 deletions
diff --git a/bot/__init__.py b/bot/__init__.py index fecd7ceb3..b6919a489 100644 --- a/bot/__init__.py +++ b/bot/__init__.py @@ -55,7 +55,7 @@ else: logging.basicConfig( - format="%(asctime)s pd.beardfist.com Bot: | %(name)33.33s | %(levelname)8s | %(message)s", + format="%(asctime)s pd.beardfist.com Bot: | %(name)33s | %(levelname)8s | %(message)s", datefmt="%b %d %H:%M:%S", level=logging.TRACE if DEBUG_MODE else logging.INFO, handlers=logging_handlers diff --git a/bot/cogs/watchchannels/bigbrother.py b/bot/cogs/watchchannels/bigbrother.py index dc5e76f55..ff26794f7 100644 --- a/bot/cogs/watchchannels/bigbrother.py +++ b/bot/cogs/watchchannels/bigbrother.py @@ -53,36 +53,25 @@ class BigBrother(WatchChannel): in the header when relaying messages of this user to the watchchannel. """ if user.bot: - e = Embed( - description=f":x: I'm sorry {ctx.author}, I'm afraid I can't do that. I only watch humans.", - color=Color.red() - ) - await ctx.send(embed=e) + await ctx.send(f":x: I'm sorry {ctx.author}, I'm afraid I can't do that. I only watch humans.") return if not await self.fetch_user_cache(): - log.error("Failed to update user cache; can't watch user {user}") + + await ctx.send(f":x: Updating the user cache failed, can't watch user {user}") return if user.id in self.watched_users: - e = Embed( - description=":x: The specified user is already being watched.", - color=Color.red() - ) - await ctx.send(embed=e) + await ctx.send(":x: The specified user is already being watched.") return response = await post_infraction( ctx, user, type='watch', reason=reason, hidden=True ) + if response is not None: self.watched_users[user.id] = response - e = Embed( - description=f":white_check_mark: Messages sent by {user} will now be relayed to BigBrother.", - color=Color.green() - ) - await ctx.send(embed=e) - return + await ctx.send(f":white_check_mark: Messages sent by {user} will now be relayed to BigBrother.") @bigbrother_group.command(name='unwatch', aliases=('uw',)) @with_role(Roles.owner, Roles.admin, Roles.moderator) @@ -105,16 +94,8 @@ class BigBrother(WatchChannel): await post_infraction(ctx, user, type='watch', reason=f"Unwatched: {reason}", hidden=True, active=False) - e = Embed( - description=f":white_check_mark: Messages sent by {user} will no longer be relayed.", - color=Color.green() - ) - await ctx.send(embed=e) + await ctx.send(f":white_check_mark: Messages sent by {user} will no longer be relayed.") self._remove_user(user.id) else: - e = Embed( - description=":x: The specified user is currently not being watched.", - color=Color.red() - ) - await ctx.send(embed=e) + await ctx.send(":x: The specified user is currently not being watched.") diff --git a/bot/cogs/watchchannels/talentpool.py b/bot/cogs/watchchannels/talentpool.py index 5e515fe2e..45b695e55 100644 --- a/bot/cogs/watchchannels/talentpool.py +++ b/bot/cogs/watchchannels/talentpool.py @@ -57,36 +57,19 @@ class TalentPool(WatchChannel): in the header when relaying messages of this user to the watchchannel. """ if user.bot: - e = Embed( - description=f":x: **I'm sorry {ctx.author}, I'm afraid I can't do that. I only watch humans.**", - color=Color.red() - ) - await ctx.send(embed=e) + await ctx.send(f":x: I'm sorry {ctx.author}, I'm afraid I can't do that. I only watch humans.") return if isinstance(user, Member) and any(role.id in STAFF_ROLES for role in user.roles): - e = Embed( - description=f":x: **Nominating staff members, eh? You cheeky bastard.**", - color=Color.red() - ) - await ctx.send(embed=e) + await ctx.send(f":x: Nominating staff members, eh? Here's a cookie :cookie:") return if not await self.fetch_user_cache(): - log.error(f"Failed to update user cache; can't watch user {user}") - e = Embed( - description=f":x: **Failed to update the user cache; can't add {user}**", - color=Color.red() - ) - await ctx.send(embed=e) + await ctx.send(f":x: Failed to update the user cache; can't add {user}") return if user.id in self.watched_users: - e = Embed( - description=":x: **The specified user is already in the TalentPool**", - color=Color.red() - ) - await ctx.send(embed=e) + await ctx.send(":x: The specified user is already being watched in the TalentPool") return # Manual request with `raise_for_status` as False because we want the actual response @@ -105,7 +88,7 @@ class TalentPool(WatchChannel): if resp.status == 400 and response_data.get('user', False): e = Embed( - description=":x: **The specified user can't be found in the database tables**", + description=":x: The specified user can't be found in the database tables", color=Color.red() ) await ctx.send(embed=e) @@ -114,11 +97,7 @@ class TalentPool(WatchChannel): resp.raise_for_status() self.watched_users[user.id] = response_data - e = Embed( - description=f":white_check_mark: **Messages sent by {user} will now be relayed to TalentPool**", - color=Color.green() - ) - await ctx.send(embed=e) + await ctx.send(f":white_check_mark: Messages sent by {user} will now be relayed to TalentPool") @nomination_group.command(name='history', aliases=('info', 'search')) @with_role(Roles.owner, Roles.admin, Roles.moderator) @@ -132,11 +111,7 @@ class TalentPool(WatchChannel): } ) if not result: - e = Embed( - description=":warning: **This user has never been nominated**", - color=Color.blue() - ) - await ctx.send(embed=e) + await ctx.send(":warning: This user has never been nominated") return embed = Embed( @@ -170,11 +145,7 @@ class TalentPool(WatchChannel): ) if not active_nomination: - e = Embed( - description=":x: **The specified user does not have an active Nomination**", - color=Color.red() - ) - await ctx.send(embed=e) + await ctx.send(":x: The specified user does not have an active Nomination") return [nomination] = active_nomination @@ -182,11 +153,7 @@ class TalentPool(WatchChannel): f"{self.api_endpoint}/{nomination['id']}", json={'end_reason': reason} ) - e = Embed( - description=f":white_check_mark: **Messages sent by {user} will no longer be relayed**", - color=Color.green() - ) - await ctx.send(embed=e) + await ctx.send(f":white_check_mark: Messages sent by {user} will no longer be relayed") self._remove_user(user.id) @nomination_group.group(name='edit', aliases=('e',), invoke_without_command=True) @@ -210,11 +177,7 @@ class TalentPool(WatchChannel): except ClientResponseError as e: if e.status == 404: self.log.trace(f"Nomination API 404: Can't nomination with id {nomination_id}") - e = Embed( - description=f":x: **Can't find a nomination with id `{nomination_id}`**", - color=Color.red() - ) - await ctx.send(embed=e) + await ctx.send(f":x: Can't find a nomination with id `{nomination_id}`") return else: raise @@ -222,16 +185,13 @@ class TalentPool(WatchChannel): field = "reason" if nomination["active"] else "end_reason" self.log.trace(f"Changing {field} for nomination with id {nomination_id} to {reason}") + await self.bot.api_client.patch( f"{self.api_endpoint}/{nomination_id}", json={field: reason} ) - e = Embed( - description=f":white_check_mark: **Updated the {field} of the nomination!**", - color=Color.green() - ) - await ctx.send(embed=e) + await ctx.send(f":white_check_mark: Updated the {field} of the nomination!") def _nomination_to_string(self, nomination_object: dict) -> str: """Creates a string representation of a nomination.""" diff --git a/bot/cogs/watchchannels/watchchannel.py b/bot/cogs/watchchannels/watchchannel.py index 8f0bc765d..16212e3b0 100644 --- a/bot/cogs/watchchannels/watchchannel.py +++ b/bot/cogs/watchchannels/watchchannel.py @@ -5,7 +5,8 @@ import re import textwrap from abc import ABC, abstractmethod from collections import defaultdict, deque -from typing import Optional +from dataclasses import dataclass +from typing import Iterator, Optional import aiohttp import discord @@ -39,6 +40,16 @@ def proxy_user(user_id: str) -> Object: return user +@dataclass +class MessageHistory: + last_author: Optional[int] = None + last_channel: Optional[int] = None + message_count: int = 0 + + def __iter__(self) -> Iterator: + return iter((self.last_author, self.last_channel, self.message_count)) + + class WatchChannel(ABC): """ABC that implements watch channel functionality to relay all messages of a user to a watch channel.""" @@ -52,7 +63,6 @@ class WatchChannel(ABC): self.api_default_params = api_default_params # E.g., {'active': 'true', 'type': 'watch'} self.log = logger # Logger of the child cog for a correct name in the logs - # These attributes can be left as they are in the child class self._consume_task = None self.watched_users = defaultdict(dict) self.message_queue = defaultdict(lambda: defaultdict(deque)) @@ -61,7 +71,7 @@ class WatchChannel(ABC): self.retry_delay = 10 self.channel = None self.webhook = None - self.message_history = [None, None, 0] + self.message_history = MessageHistory() self._start = self.bot.loop.create_task(self.start_watchchannel()) @@ -118,13 +128,14 @@ class WatchChannel(ABC): TextChannel: {"**Failed to load**" if self.channel is None else "Loaded successfully"} Webhook: {"**Failed to load**" if self.webhook is None else "Loaded successfully"} - The Cog has been unloaded.""" + The Cog has been unloaded. + """ ) await self.modlog.send_log_message( title=f"Error: Failed to initialize the {self.__class__.__name__} watch channel", text=message, - ping_everyone=False, + ping_everyone=True, icon_url=Icons.token_removed, colour=Color.red() ) @@ -221,7 +232,7 @@ class WatchChannel(ABC): limit = BigBrotherConfig.header_message_limit if msg.author.id != last_author or msg.channel.id != last_channel or count >= limit: - self.message_history = [msg.author.id, msg.channel.id, 0] + self.message_history = MessageHistory(last_author=msg.author.id, last_channel=msg.channel.id) await self.send_header(msg) @@ -258,7 +269,7 @@ class WatchChannel(ABC): exc_info=exc ) - self.message_history[2] += 1 + self.message_history.message_count += 1 async def send_header(self, msg) -> None: """Sends a header embed with information about the relayed messages to the watch channel""" diff --git a/bot/utils/messages.py b/bot/utils/messages.py index 5c9b5b4d7..94a8b36ed 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -97,11 +97,13 @@ async def send_attachments(message: Message, destination: Union[TextChannel, Web if attachment.size <= MAX_SIZE - 512: with BytesIO() as file: await attachment.save(file) + attachment_file = File(file, filename=attachment.filename) + if isinstance(destination, TextChannel): - await destination.send(file=File(file, filename=attachment.filename)) + await destination.send(file=attachment_file) else: await destination.send( - file=File(file, filename=attachment.filename), + file=attachment_file, username=message.author.display_name, avatar_url=message.author.avatar_url ) diff --git a/bot/utils/moderation.py b/bot/utils/moderation.py index e81186253..c1eb98dd6 100644 --- a/bot/utils/moderation.py +++ b/bot/utils/moderation.py @@ -14,8 +14,13 @@ HEADERS = {"X-API-KEY": Keys.site_api} async def post_infraction( - ctx: Context, user: Union[Member, Object, User], type: str, reason: str, - expires_at: datetime = None, hidden: bool = False, active: bool = True + ctx: Context, + user: Union[Member, Object, User], + type: str, + reason: str, + expires_at: datetime = None, + hidden: bool = False, + active: bool = True, ): payload = { |