From b9d483c15464f4b11575090b27306f2accc47acf Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 20 Jun 2020 08:47:24 +0300 Subject: Watchchannel: Moved message consuming task cancelling exception Moved exception logging when cog is being unloaded and messages is still not consumed from `cog_unload` to `consume_messages` itself in try-except block to avoid case when requesting result too early (before cancel finished). --- bot/cogs/watchchannels/watchchannel.py | 53 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/bot/cogs/watchchannels/watchchannel.py b/bot/cogs/watchchannels/watchchannel.py index 436778c46..d78d45f26 100644 --- a/bot/cogs/watchchannels/watchchannel.py +++ b/bot/cogs/watchchannels/watchchannel.py @@ -169,32 +169,38 @@ class WatchChannel(metaclass=CogABCMeta): async def consume_messages(self, delay_consumption: bool = True) -> None: """Consumes the message queues to log watched users' messages.""" - if delay_consumption: - self.log.trace(f"Sleeping {BigBrotherConfig.log_delay} seconds before consuming message queue") - await asyncio.sleep(BigBrotherConfig.log_delay) + try: + if delay_consumption: + self.log.trace(f"Sleeping {BigBrotherConfig.log_delay} seconds before consuming message queue") + await asyncio.sleep(BigBrotherConfig.log_delay) - self.log.trace("Started consuming the message queue") + self.log.trace("Started consuming the message queue") - # If the previous consumption Task failed, first consume the existing comsumption_queue - if not self.consumption_queue: - self.consumption_queue = self.message_queue.copy() - self.message_queue.clear() + # If the previous consumption Task failed, first consume the existing comsumption_queue + if not self.consumption_queue: + self.consumption_queue = self.message_queue.copy() + self.message_queue.clear() - for user_channel_queues in self.consumption_queue.values(): - for channel_queue in user_channel_queues.values(): - while channel_queue: - msg = channel_queue.popleft() + for user_channel_queues in self.consumption_queue.values(): + for channel_queue in user_channel_queues.values(): + while channel_queue: + msg = channel_queue.popleft() - self.log.trace(f"Consuming message {msg.id} ({len(msg.attachments)} attachments)") - await self.relay_message(msg) + self.log.trace(f"Consuming message {msg.id} ({len(msg.attachments)} attachments)") + await self.relay_message(msg) - self.consumption_queue.clear() + self.consumption_queue.clear() - if self.message_queue: - self.log.trace("Channel queue not empty: Continuing consuming queues") - self._consume_task = self.bot.loop.create_task(self.consume_messages(delay_consumption=False)) - else: - self.log.trace("Done consuming messages.") + if self.message_queue: + self.log.trace("Channel queue not empty: Continuing consuming queues") + self._consume_task = self.bot.loop.create_task(self.consume_messages(delay_consumption=False)) + else: + self.log.trace("Done consuming messages.") + except asyncio.CancelledError as e: + self.log.exception( + "The consume task was canceled. Messages may be lost.", + exc_info=e + ) async def webhook_send( self, @@ -330,10 +336,3 @@ class WatchChannel(metaclass=CogABCMeta): self.log.trace("Unloading the cog") if self._consume_task and not self._consume_task.done(): self._consume_task.cancel() - try: - self._consume_task.result() - except asyncio.CancelledError as e: - self.log.exception( - "The consume task was canceled. Messages may be lost.", - exc_info=e - ) -- cgit v1.2.3 From ac302d3d2360c3b379632ce033884127321a76b5 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 20 Jun 2020 12:08:29 +0300 Subject: Infractions: Fix cases when user leave from guild before assigning roles When user left from guild before bot can add Muted role, then catch this error and log. --- bot/cogs/moderation/infractions.py | 11 +++++++---- bot/cogs/moderation/scheduler.py | 9 +++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/bot/cogs/moderation/infractions.py b/bot/cogs/moderation/infractions.py index 3b28526b2..c03c8d974 100644 --- a/bot/cogs/moderation/infractions.py +++ b/bot/cogs/moderation/infractions.py @@ -223,10 +223,13 @@ class Infractions(InfractionScheduler, commands.Cog): self.mod_log.ignore(Event.member_update, user.id) async def action() -> None: - await user.add_roles(self._muted_role, reason=reason) - - log.trace(f"Attempting to kick {user} from voice because they've been muted.") - await user.move_to(None, reason=reason) + try: + await user.add_roles(self._muted_role, reason=reason) + except discord.NotFound: + log.info(f"User {user} ({user.id}) left from guild. Can't give Muted role.") + else: + log.trace(f"Attempting to kick {user} from voice because they've been muted.") + await user.move_to(None, reason=reason) await self.apply_infraction(ctx, infraction, user, action()) diff --git a/bot/cogs/moderation/scheduler.py b/bot/cogs/moderation/scheduler.py index d75a72ddb..28547545e 100644 --- a/bot/cogs/moderation/scheduler.py +++ b/bot/cogs/moderation/scheduler.py @@ -71,8 +71,13 @@ class InfractionScheduler(Scheduler): return # Allowing mod log since this is a passive action that should be logged. - await apply_coro - log.info(f"Re-applied {infraction['type']} to user {infraction['user']} upon rejoining.") + try: + await apply_coro + except discord.NotFound: + # When user joined and then right after this left again before action completed, this can't add roles + log.info(f"Can't reapply {infraction['type']} to user {infraction['user']} because user left again.") + else: + log.info(f"Re-applied {infraction['type']} to user {infraction['user']} upon rejoining.") async def apply_infraction( self, -- cgit v1.2.3 From 429cc865309242f0cf37147f9c3f05036972eb8c Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 20 Jun 2020 21:33:36 +0300 Subject: Implement bot closing tasks waiting + breaking `close` to multiple parts Made to resolve problem with Reddit cog that revoking access token raise exception because session is closed. To solve this, I made `Bot.closing_tasks` that bot wait before closing. Moved all extensions and cogs removing to `remove_extension` what is called before closing everything else because need to call `cog_unload`. --- bot/bot.py | 30 ++++++++++++++++++++++++++++-- bot/cogs/reddit.py | 4 +++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/bot/bot.py b/bot/bot.py index 313652d11..c9eb24bb5 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -2,7 +2,7 @@ import asyncio import logging import socket import warnings -from typing import Optional +from typing import List, Optional import aiohttp import aioredis @@ -49,6 +49,9 @@ class Bot(commands.Bot): self.stats = AsyncStatsClient(self.loop, statsd_url, 8125, prefix="bot") + # All tasks that need to block closing until finished + self.closing_tasks: List[asyncio.Task] = [] + async def _create_redis_session(self) -> None: """ Create the Redis connection pool, and then open the redis event gate. @@ -89,9 +92,32 @@ class Bot(commands.Bot): self._recreate() super().clear() + def remove_extensions(self) -> None: + """Remove all extensions and Cog to close bot. Copy from discord.py's own `close` for right closing order.""" + for extension in tuple(self.extensions): + try: + self.unload_extension(extension) + except Exception: + pass + + for cog in tuple(self.cogs): + try: + self.remove_cog(cog) + except Exception: + pass + async def close(self) -> None: """Close the Discord connection and the aiohttp session, connector, statsd client, and resolver.""" - await super().close() + # Remove extensions and cogs before calling super().close() to allow task finish before HTTP session close + self.remove_extensions() + + # Wait until all tasks that have to be completed before bot is closing is done + for task in self.closing_tasks: + log.trace(f"Waiting for task {task.get_name()} before closing.") + await task + + # Now actually do full close of bot + await super(commands.Bot, self).close() await self.api_client.close() diff --git a/bot/cogs/reddit.py b/bot/cogs/reddit.py index 3b77538a0..5a63d71fc 100644 --- a/bot/cogs/reddit.py +++ b/bot/cogs/reddit.py @@ -44,7 +44,9 @@ class Reddit(Cog): """Stop the loop task and revoke the access token when the cog is unloaded.""" self.auto_poster_loop.cancel() if self.access_token and self.access_token.expires_at > datetime.utcnow(): - asyncio.create_task(self.revoke_access_token()) + task = asyncio.create_task(self.revoke_access_token()) + task.set_name("revoke_reddit_access_token") + self.bot.closing_tasks.append(task) async def init_reddit_ready(self) -> None: """Sets the reddit webhook when the cog is loaded.""" -- cgit v1.2.3 From 177e4d4f68f407ac2808b18badd32a29d26034ff Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sun, 21 Jun 2020 08:22:56 +0300 Subject: Reddit: Remove unnecessary revoke task name changing --- bot/cogs/reddit.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bot/cogs/reddit.py b/bot/cogs/reddit.py index 5a63d71fc..681d1997f 100644 --- a/bot/cogs/reddit.py +++ b/bot/cogs/reddit.py @@ -45,7 +45,6 @@ class Reddit(Cog): self.auto_poster_loop.cancel() if self.access_token and self.access_token.expires_at > datetime.utcnow(): task = asyncio.create_task(self.revoke_access_token()) - task.set_name("revoke_reddit_access_token") self.bot.closing_tasks.append(task) async def init_reddit_ready(self) -> None: -- cgit v1.2.3 From 1fd30faaeaa2dfc3e38426db9112628bfdba0f04 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sun, 21 Jun 2020 09:29:22 +0300 Subject: Reddit: Don't define revoke task as variable but instantly append --- bot/cogs/reddit.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bot/cogs/reddit.py b/bot/cogs/reddit.py index 681d1997f..850d3afb2 100644 --- a/bot/cogs/reddit.py +++ b/bot/cogs/reddit.py @@ -44,8 +44,7 @@ class Reddit(Cog): """Stop the loop task and revoke the access token when the cog is unloaded.""" self.auto_poster_loop.cancel() if self.access_token and self.access_token.expires_at > datetime.utcnow(): - task = asyncio.create_task(self.revoke_access_token()) - self.bot.closing_tasks.append(task) + self.bot.closing_tasks.append(asyncio.create_task(self.revoke_access_token())) async def init_reddit_ready(self) -> None: """Sets the reddit webhook when the cog is loaded.""" -- cgit v1.2.3 From f4004d814c1babfb5906afb8cd9944ceef90a2a3 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sun, 21 Jun 2020 09:30:47 +0300 Subject: Silence: Add mod alert sending to `closing_tasks` to avoid error --- bot/cogs/moderation/silence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/moderation/silence.py b/bot/cogs/moderation/silence.py index c8ab6443b..34baa2bcb 100644 --- a/bot/cogs/moderation/silence.py +++ b/bot/cogs/moderation/silence.py @@ -176,7 +176,7 @@ class Silence(Scheduler, commands.Cog): if self.muted_channels: channels_string = ''.join(channel.mention for channel in self.muted_channels) message = f"<@&{Roles.moderators}> channels left silenced on cog unload: {channels_string}" - asyncio.create_task(self._mod_alerts_channel.send(message)) + self.bot.closing_tasks.append(asyncio.create_task(self._mod_alerts_channel.send(message))) # This cannot be static (must have a __func__ attribute). def cog_check(self, ctx: Context) -> bool: -- cgit v1.2.3 From b040a38ea1e3c7baddb54395a1f09d11fdd4e818 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Thu, 23 Jul 2020 07:51:56 +0300 Subject: Add copyright about `_remove_extension` + make function private --- bot/bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/bot.py b/bot/bot.py index c9eb24bb5..f5f76b7f8 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -92,8 +92,8 @@ class Bot(commands.Bot): self._recreate() super().clear() - def remove_extensions(self) -> None: - """Remove all extensions and Cog to close bot. Copy from discord.py's own `close` for right closing order.""" + def _remove_extensions(self) -> None: + """Remove all extensions and Cog to close bot. Copyright (c) 2015-2020 Rapptz (discord.py, MIT License).""" for extension in tuple(self.extensions): try: self.unload_extension(extension) -- cgit v1.2.3 From 360ce808bdc12ab8dfc998927d6a07658aa2b633 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Thu, 23 Jul 2020 07:56:12 +0300 Subject: Improve extension + cogs removing comment on `close` Co-authored-by: Mark --- bot/bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/bot.py b/bot/bot.py index f5f76b7f8..7a8f9932c 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -108,7 +108,7 @@ class Bot(commands.Bot): async def close(self) -> None: """Close the Discord connection and the aiohttp session, connector, statsd client, and resolver.""" - # Remove extensions and cogs before calling super().close() to allow task finish before HTTP session close + # Done before super().close() to allow tasks finish before the HTTP session closes. self.remove_extensions() # Wait until all tasks that have to be completed before bot is closing is done -- cgit v1.2.3 From 65c4312515de65a59b7553b0581c31d0d9fa098b Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Fri, 31 Jul 2020 18:00:36 +0300 Subject: Simplify bot shutdown cogs removing Unloading extensions already remove all cogs that is inside it and this is enough good for this case, because bot still call dpy's internal function later to remove cogs not related with extensions (when exist). --- bot/bot.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/bot/bot.py b/bot/bot.py index 7a8f9932c..5e05d1596 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -93,16 +93,10 @@ class Bot(commands.Bot): super().clear() def _remove_extensions(self) -> None: - """Remove all extensions and Cog to close bot. Copyright (c) 2015-2020 Rapptz (discord.py, MIT License).""" - for extension in tuple(self.extensions): + """Remove all extensions to trigger cog unloads.""" + for ext in self.extensions.keys(): try: - self.unload_extension(extension) - except Exception: - pass - - for cog in tuple(self.cogs): - try: - self.remove_cog(cog) + self.unload_extension(ext) except Exception: pass -- cgit v1.2.3 From 2dc0ee180330bcf2687d62e174abeea79e963775 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Fri, 31 Jul 2020 18:04:38 +0300 Subject: Use asyncio.gather instead manual looping and awaiting --- bot/bot.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bot/bot.py b/bot/bot.py index 5e05d1596..2f366a3ef 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -106,9 +106,8 @@ class Bot(commands.Bot): self.remove_extensions() # Wait until all tasks that have to be completed before bot is closing is done - for task in self.closing_tasks: - log.trace(f"Waiting for task {task.get_name()} before closing.") - await task + log.trace("Waiting for tasks before closing.") + await asyncio.gather(*self.closing_tasks) # Now actually do full close of bot await super(commands.Bot, self).close() -- cgit v1.2.3 From 7b83b7c67b0d00fce0c7c88b9b306e82ca2f5622 Mon Sep 17 00:00:00 2001 From: Eivind Teig Date: Sat, 12 Sep 2020 01:28:39 +0200 Subject: Make nomination reason optional. We want to make the nominate command more attractive for our members of staff. --- bot/cogs/watchchannels/talentpool.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/cogs/watchchannels/talentpool.py b/bot/cogs/watchchannels/talentpool.py index 76d6fe9bd..6ba397308 100644 --- a/bot/cogs/watchchannels/talentpool.py +++ b/bot/cogs/watchchannels/talentpool.py @@ -1,7 +1,7 @@ import logging import textwrap from collections import ChainMap -from typing import Union +from typing import Union, Optional from discord import Color, Embed, Member, User from discord.ext.commands import Cog, Context, group @@ -65,7 +65,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): @nomination_group.command(name='watch', aliases=('w', 'add', 'a'), root_aliases=("nominate",)) @with_role(*STAFF_ROLES) - async def watch_command(self, ctx: Context, user: FetchedMember, *, reason: str) -> None: + async def watch_command(self, ctx: Context, user: FetchedMember, *, reason: Optional[str] = '') -> None: """ Relay messages sent by the given `user` to the `#talent-pool` channel. -- cgit v1.2.3 From d75e1bc101578d3ce318ab0614aa448053daba7d Mon Sep 17 00:00:00 2001 From: Eivind Teig Date: Sat, 12 Sep 2020 01:30:50 +0200 Subject: Only show reason if it exist. Reduce the footer to not include reason if it does not exist. --- bot/cogs/watchchannels/watchchannel.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bot/cogs/watchchannels/watchchannel.py b/bot/cogs/watchchannels/watchchannel.py index a58b604c0..eb6d6f992 100644 --- a/bot/cogs/watchchannels/watchchannel.py +++ b/bot/cogs/watchchannels/watchchannel.py @@ -285,7 +285,10 @@ class WatchChannel(metaclass=CogABCMeta): else: message_jump = f"in [#{msg.channel.name}]({msg.jump_url})" - footer = f"Added {time_delta} by {actor} | Reason: {reason}" + # Add reason to the footer if it exists. + footer = f"Added {time_delta} by {actor}" + if reason: + footer += f" | Reason: {reason}" embed = Embed(description=f"{msg.author.mention} {message_jump}") embed.set_footer(text=textwrap.shorten(footer, width=128, placeholder="...")) -- cgit v1.2.3 From 0e24d104ac47685df4dbec2e8262da4a8c6c61d9 Mon Sep 17 00:00:00 2001 From: Eivind Teig Date: Sat, 12 Sep 2020 01:31:17 +0200 Subject: Update user cache after nomination reason edit. --- bot/cogs/watchchannels/talentpool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/watchchannels/talentpool.py b/bot/cogs/watchchannels/talentpool.py index 6ba397308..7e3aed971 100644 --- a/bot/cogs/watchchannels/talentpool.py +++ b/bot/cogs/watchchannels/talentpool.py @@ -203,7 +203,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): f"{self.api_endpoint}/{nomination_id}", json={field: reason} ) - + await self.fetch_user_cache() # Update cache. await ctx.send(f":white_check_mark: Updated the {field} of the nomination!") @Cog.listener() -- cgit v1.2.3 From 057efd069a7fc060a82d3a88afcce157d33c6267 Mon Sep 17 00:00:00 2001 From: Eivind Teig Date: Sat, 12 Sep 2020 01:38:57 +0200 Subject: Fix import order to pass linting tests. --- bot/cogs/watchchannels/talentpool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/watchchannels/talentpool.py b/bot/cogs/watchchannels/talentpool.py index 7e3aed971..66de567f9 100644 --- a/bot/cogs/watchchannels/talentpool.py +++ b/bot/cogs/watchchannels/talentpool.py @@ -1,7 +1,7 @@ import logging import textwrap from collections import ChainMap -from typing import Union, Optional +from typing import Optional, Union from discord import Color, Embed, Member, User from discord.ext.commands import Cog, Context, group -- cgit v1.2.3 From 040ac421a26a270e64d9ed745fe28ee886181fed Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Fri, 9 Oct 2020 18:59:58 +0300 Subject: Make bot shutdown remove all other non-extension cogs again --- bot/bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/bot.py b/bot/bot.py index 2f366a3ef..10c4c901b 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -110,7 +110,7 @@ class Bot(commands.Bot): await asyncio.gather(*self.closing_tasks) # Now actually do full close of bot - await super(commands.Bot, self).close() + await super().close() await self.api_client.close() -- cgit v1.2.3 From ff5c90bf12f14abb4d0a5bc73af435e53ffc7e3e Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Fri, 9 Oct 2020 19:35:33 +0300 Subject: Fix calling extensions removing function with wrong name --- bot/bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/bot.py b/bot/bot.py index b51e41117..e6d77344e 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -145,7 +145,7 @@ class Bot(commands.Bot): async def close(self) -> None: """Close the Discord connection and the aiohttp session, connector, statsd client, and resolver.""" # Done before super().close() to allow tasks finish before the HTTP session closes. - self.remove_extensions() + self._remove_extensions() # Wait until all tasks that have to be completed before bot is closing is done log.trace("Waiting for tasks before closing.") -- cgit v1.2.3 From 5a5a948efd954c8e878db50b6a5ec480fd97b3ec Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 10 Oct 2020 08:13:19 +0300 Subject: Fix name of extensions removing function --- bot/bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/bot.py b/bot/bot.py index b51e41117..e6d77344e 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -145,7 +145,7 @@ class Bot(commands.Bot): async def close(self) -> None: """Close the Discord connection and the aiohttp session, connector, statsd client, and resolver.""" # Done before super().close() to allow tasks finish before the HTTP session closes. - self.remove_extensions() + self._remove_extensions() # Wait until all tasks that have to be completed before bot is closing is done log.trace("Waiting for tasks before closing.") -- cgit v1.2.3 From b702618d8a9189e19c3107c79e23105e288798b0 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 10 Oct 2020 08:38:49 +0300 Subject: Get all extensions first for unloading to avoid iteration error --- bot/bot.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bot/bot.py b/bot/bot.py index e6d77344e..9a60474b3 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -136,7 +136,9 @@ class Bot(commands.Bot): def _remove_extensions(self) -> None: """Remove all extensions to trigger cog unloads.""" - for ext in self.extensions.keys(): + extensions = list(self.extensions.keys()) + + for ext in extensions: try: self.unload_extension(ext) except Exception: -- cgit v1.2.3 From d0af250507371739c652abfcc47efa4a86ce1166 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 10 Oct 2020 08:41:32 +0300 Subject: Use done callback instead of plain try-except inside function --- bot/exts/moderation/watchchannels/_watchchannel.py | 56 ++++++++++++---------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/bot/exts/moderation/watchchannels/_watchchannel.py b/bot/exts/moderation/watchchannels/_watchchannel.py index 4715dce14..b576f2888 100644 --- a/bot/exts/moderation/watchchannels/_watchchannel.py +++ b/bot/exts/moderation/watchchannels/_watchchannel.py @@ -171,38 +171,32 @@ class WatchChannel(metaclass=CogABCMeta): async def consume_messages(self, delay_consumption: bool = True) -> None: """Consumes the message queues to log watched users' messages.""" - try: - if delay_consumption: - self.log.trace(f"Sleeping {BigBrotherConfig.log_delay} seconds before consuming message queue") - await asyncio.sleep(BigBrotherConfig.log_delay) + if delay_consumption: + self.log.trace(f"Sleeping {BigBrotherConfig.log_delay} seconds before consuming message queue") + await asyncio.sleep(BigBrotherConfig.log_delay) - self.log.trace("Started consuming the message queue") + self.log.trace("Started consuming the message queue") - # If the previous consumption Task failed, first consume the existing comsumption_queue - if not self.consumption_queue: - self.consumption_queue = self.message_queue.copy() - self.message_queue.clear() + # If the previous consumption Task failed, first consume the existing comsumption_queue + if not self.consumption_queue: + self.consumption_queue = self.message_queue.copy() + self.message_queue.clear() - for user_channel_queues in self.consumption_queue.values(): - for channel_queue in user_channel_queues.values(): - while channel_queue: - msg = channel_queue.popleft() + for user_channel_queues in self.consumption_queue.values(): + for channel_queue in user_channel_queues.values(): + while channel_queue: + msg = channel_queue.popleft() - self.log.trace(f"Consuming message {msg.id} ({len(msg.attachments)} attachments)") - await self.relay_message(msg) + self.log.trace(f"Consuming message {msg.id} ({len(msg.attachments)} attachments)") + await self.relay_message(msg) - self.consumption_queue.clear() + self.consumption_queue.clear() - if self.message_queue: - self.log.trace("Channel queue not empty: Continuing consuming queues") - self._consume_task = self.bot.loop.create_task(self.consume_messages(delay_consumption=False)) - else: - self.log.trace("Done consuming messages.") - except asyncio.CancelledError as e: - self.log.exception( - "The consume task was canceled. Messages may be lost.", - exc_info=e - ) + if self.message_queue: + self.log.trace("Channel queue not empty: Continuing consuming queues") + self._consume_task = self.bot.loop.create_task(self.consume_messages(delay_consumption=False)) + else: + self.log.trace("Done consuming messages.") async def webhook_send( self, @@ -348,4 +342,14 @@ class WatchChannel(metaclass=CogABCMeta): """Takes care of unloading the cog and canceling the consumption task.""" self.log.trace("Unloading the cog") if self._consume_task and not self._consume_task.done(): + def done_callback(task: asyncio.Task) -> None: + """Send exception when consuming task have been cancelled.""" + try: + task.exception() + except asyncio.CancelledError: + self.log.error( + f"The consume task of {type(self).__name__} was canceled. Messages may be lost." + ) + + self._consume_task.add_done_callback(done_callback) self._consume_task.cancel() -- cgit v1.2.3 From 8ed147c402a3a6b5e98b29c3ed385460f3216efd Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 10 Oct 2020 09:05:00 +0300 Subject: Catch HTTPException when muting user --- bot/exts/moderation/infraction/infractions.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bot/exts/moderation/infraction/infractions.py b/bot/exts/moderation/infraction/infractions.py index ccddd4530..b638f4dc6 100644 --- a/bot/exts/moderation/infraction/infractions.py +++ b/bot/exts/moderation/infraction/infractions.py @@ -242,8 +242,13 @@ class Infractions(InfractionScheduler, commands.Cog): async def action() -> None: try: await user.add_roles(self._muted_role, reason=reason) - except discord.NotFound: - log.info(f"User {user} ({user.id}) left from guild. Can't give Muted role.") + except discord.HTTPException as e: + if e.code == 10007: + log.info(f"User {user} ({user.id}) left from guild. Can't give Muted role.") + else: + log.warning( + f"Got response {e.code} (HTTP {e.status}) while giving muted role to {user} ({user.id})." + ) else: log.trace(f"Attempting to kick {user} from voice because they've been muted.") await user.move_to(None, reason=reason) -- cgit v1.2.3 From 027666f95ccaf07dfc73d2bfb7487e5a61bcd2d2 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 7 Nov 2020 09:45:19 +0200 Subject: Remove both cogs and extensions on closing --- bot/bot.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/bot/bot.py b/bot/bot.py index 9a60474b3..fbd97dc18 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -3,6 +3,7 @@ import logging import socket import warnings from collections import defaultdict +from contextlib import suppress from typing import Dict, List, Optional import aiohttp @@ -134,20 +135,12 @@ class Bot(commands.Bot): self._recreate() super().clear() - def _remove_extensions(self) -> None: - """Remove all extensions to trigger cog unloads.""" - extensions = list(self.extensions.keys()) - - for ext in extensions: - try: - self.unload_extension(ext) - except Exception: - pass - async def close(self) -> None: """Close the Discord connection and the aiohttp session, connector, statsd client, and resolver.""" # Done before super().close() to allow tasks finish before the HTTP session closes. - self._remove_extensions() + with suppress(Exception): + [self.unload_extension(ext) for ext in tuple(self.extensions)] + [self.remove_cog(cog) for cog in tuple(self.cogs)] # Wait until all tasks that have to be completed before bot is closing is done log.trace("Waiting for tasks before closing.") -- cgit v1.2.3 From d15c4fc004e73669014baa25c675a7bf7b8064f9 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 7 Nov 2020 09:47:05 +0200 Subject: Use result instead exception for watchchannel closing task --- bot/exts/moderation/watchchannels/_watchchannel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/moderation/watchchannels/_watchchannel.py b/bot/exts/moderation/watchchannels/_watchchannel.py index b576f2888..8894762f3 100644 --- a/bot/exts/moderation/watchchannels/_watchchannel.py +++ b/bot/exts/moderation/watchchannels/_watchchannel.py @@ -345,7 +345,7 @@ class WatchChannel(metaclass=CogABCMeta): def done_callback(task: asyncio.Task) -> None: """Send exception when consuming task have been cancelled.""" try: - task.exception() + task.result() except asyncio.CancelledError: self.log.error( f"The consume task of {type(self).__name__} was canceled. Messages may be lost." -- cgit v1.2.3 From 6a81f714c6648d7dd12982b38c7161cdee9e602e Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 7 Nov 2020 09:57:23 +0200 Subject: Catch not found exception in scheduler --- bot/exts/moderation/infraction/_scheduler.py | 29 ++++++++++++++++++++++++--- bot/exts/moderation/infraction/infractions.py | 16 ++++----------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index ed67e3b26..6efa5b1e0 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -79,6 +79,16 @@ class InfractionScheduler: except discord.NotFound: # When user joined and then right after this left again before action completed, this can't add roles log.info(f"Can't reapply {infraction['type']} to user {infraction['user']} because user left again.") + except discord.HTTPException as e: + if e.code == 10007: + log.info(f"Can't reapply {infraction['type']} to user {infraction['user']} because user left again.") + else: + log.warning( + ( + f"Got unexpected HTTPException (HTTP {e.status}, Discord code {e.code})" + f"when awaiting {infraction['type']} coroutine for {infraction['user']}." + ) + ) else: log.info(f"Re-applied {infraction['type']} to user {infraction['user']} upon rejoining.") @@ -160,6 +170,8 @@ class InfractionScheduler: if expiry: # Schedule the expiration of the infraction. self.schedule_expiration(infraction) + except discord.NotFound: + log.info(f"Can't apply {infraction['type']} to user {infraction['user']} because user left from guild.") except discord.HTTPException as e: # Accordingly display that applying the infraction failed. # Don't use ctx.message.author; antispam only patches ctx.author. @@ -171,6 +183,10 @@ class InfractionScheduler: log_msg = f"Failed to apply {' '.join(infr_type.split('_'))} infraction #{id_} to {user}" if isinstance(e, discord.Forbidden): log.warning(f"{log_msg}: bot lacks permissions.") + elif e.code == 10007: + log.info( + f"Can't apply {infraction['type']} to user {infraction['user']} because user left from guild." + ) else: log.exception(log_msg) failed = True @@ -342,10 +358,17 @@ class InfractionScheduler: log.warning(f"Failed to deactivate infraction #{id_} ({type_}): bot lacks permissions.") log_text["Failure"] = "The bot lacks permissions to do this (role hierarchy?)" log_content = mod_role.mention + except discord.NotFound: + log.info(f"Can't pardon {infraction['type']} for user {infraction['user']} because user left from guild.") except discord.HTTPException as e: - log.exception(f"Failed to deactivate infraction #{id_} ({type_})") - log_text["Failure"] = f"HTTPException with status {e.status} and code {e.code}." - log_content = mod_role.mention + if e.code == 10007: + log.info( + f"Can't pardon {infraction['type']} for user {infraction['user']} because user left from guild." + ) + else: + log.exception(f"Failed to deactivate infraction #{id_} ({type_})") + log_text["Failure"] = f"HTTPException with status {e.status} and code {e.code}." + log_content = mod_role.mention # Check if the user is currently being watched by Big Brother. try: diff --git a/bot/exts/moderation/infraction/infractions.py b/bot/exts/moderation/infraction/infractions.py index 8abb199db..746d4e154 100644 --- a/bot/exts/moderation/infraction/infractions.py +++ b/bot/exts/moderation/infraction/infractions.py @@ -277,18 +277,10 @@ class Infractions(InfractionScheduler, commands.Cog): self.mod_log.ignore(Event.member_update, user.id) async def action() -> None: - try: - await user.add_roles(self._muted_role, reason=reason) - except discord.HTTPException as e: - if e.code == 10007: - log.info(f"User {user} ({user.id}) left from guild. Can't give Muted role.") - else: - log.warning( - f"Got response {e.code} (HTTP {e.status}) while giving muted role to {user} ({user.id})." - ) - else: - log.trace(f"Attempting to kick {user} from voice because they've been muted.") - await user.move_to(None, reason=reason) + await user.add_roles(self._muted_role, reason=reason) + + log.trace(f"Attempting to kick {user} from voice because they've been muted.") + await user.move_to(None, reason=reason) await self.apply_infraction(ctx, infraction, user, action()) -- cgit v1.2.3 From 8a2865651556a598b5e96447c6ed4231829c46cf Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Wed, 2 Dec 2020 17:55:33 +0200 Subject: Merge NotFound caching with HttpException caching with status code --- bot/exts/moderation/infraction/_scheduler.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 6efa5b1e0..5726a5879 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -76,11 +76,9 @@ class InfractionScheduler: # Allowing mod log since this is a passive action that should be logged. try: await apply_coro - except discord.NotFound: - # When user joined and then right after this left again before action completed, this can't add roles - log.info(f"Can't reapply {infraction['type']} to user {infraction['user']} because user left again.") except discord.HTTPException as e: - if e.code == 10007: + # When user joined and then right after this left again before action completed, this can't apply roles + if e.code == 10007 or e.status == 404: log.info(f"Can't reapply {infraction['type']} to user {infraction['user']} because user left again.") else: log.warning( @@ -170,8 +168,6 @@ class InfractionScheduler: if expiry: # Schedule the expiration of the infraction. self.schedule_expiration(infraction) - except discord.NotFound: - log.info(f"Can't apply {infraction['type']} to user {infraction['user']} because user left from guild.") except discord.HTTPException as e: # Accordingly display that applying the infraction failed. # Don't use ctx.message.author; antispam only patches ctx.author. @@ -183,7 +179,7 @@ class InfractionScheduler: log_msg = f"Failed to apply {' '.join(infr_type.split('_'))} infraction #{id_} to {user}" if isinstance(e, discord.Forbidden): log.warning(f"{log_msg}: bot lacks permissions.") - elif e.code == 10007: + elif e.code == 10007 or e.status == 404: log.info( f"Can't apply {infraction['type']} to user {infraction['user']} because user left from guild." ) @@ -358,10 +354,8 @@ class InfractionScheduler: log.warning(f"Failed to deactivate infraction #{id_} ({type_}): bot lacks permissions.") log_text["Failure"] = "The bot lacks permissions to do this (role hierarchy?)" log_content = mod_role.mention - except discord.NotFound: - log.info(f"Can't pardon {infraction['type']} for user {infraction['user']} because user left from guild.") except discord.HTTPException as e: - if e.code == 10007: + if e.code == 10007 or e.status == 404: log.info( f"Can't pardon {infraction['type']} for user {infraction['user']} because user left from guild." ) -- cgit v1.2.3 From 50db55dd25f065222213510188e62b0d951b95c8 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Wed, 2 Dec 2020 17:57:00 +0200 Subject: Fix user leaving from guild log grammar --- bot/exts/moderation/infraction/_scheduler.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 5726a5879..835f3a2e1 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -79,7 +79,9 @@ class InfractionScheduler: except discord.HTTPException as e: # When user joined and then right after this left again before action completed, this can't apply roles if e.code == 10007 or e.status == 404: - log.info(f"Can't reapply {infraction['type']} to user {infraction['user']} because user left again.") + log.info( + f"Can't reapply {infraction['type']} to user {infraction['user']} because user left the guild." + ) else: log.warning( ( @@ -357,7 +359,7 @@ class InfractionScheduler: except discord.HTTPException as e: if e.code == 10007 or e.status == 404: log.info( - f"Can't pardon {infraction['type']} for user {infraction['user']} because user left from guild." + f"Can't pardon {infraction['type']} for user {infraction['user']} because user left the guild." ) else: log.exception(f"Failed to deactivate infraction #{id_} ({type_})") -- cgit v1.2.3 From 7c2ceede521fd0599b0fa1e55b8485008d80e08e Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Wed, 2 Dec 2020 17:57:52 +0200 Subject: Log exception instead warning for unexpected HttpException --- bot/exts/moderation/infraction/_scheduler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 835f3a2e1..22739d332 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -83,7 +83,7 @@ class InfractionScheduler: f"Can't reapply {infraction['type']} to user {infraction['user']} because user left the guild." ) else: - log.warning( + log.exception( ( f"Got unexpected HTTPException (HTTP {e.status}, Discord code {e.code})" f"when awaiting {infraction['type']} coroutine for {infraction['user']}." -- cgit v1.2.3 From fc5930775ee2ae33ba88264a08c10b83761a8781 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Wed, 2 Dec 2020 17:58:25 +0200 Subject: Remove second unnecessary parenthesis --- bot/exts/moderation/infraction/_scheduler.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 22739d332..8a45692d5 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -84,10 +84,8 @@ class InfractionScheduler: ) else: log.exception( - ( - f"Got unexpected HTTPException (HTTP {e.status}, Discord code {e.code})" - f"when awaiting {infraction['type']} coroutine for {infraction['user']}." - ) + f"Got unexpected HTTPException (HTTP {e.status}, Discord code {e.code})" + f"when awaiting {infraction['type']} coroutine for {infraction['user']}." ) else: log.info(f"Re-applied {infraction['type']} to user {infraction['user']} upon rejoining.") -- cgit v1.2.3 From eb73d3030d6f1d1aaf16defee9992f6336321f64 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Wed, 2 Dec 2020 18:00:34 +0200 Subject: Add failure message when applying infraction fails because user left --- bot/exts/moderation/infraction/_scheduler.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 8a45692d5..ca4d18c98 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -359,6 +359,8 @@ class InfractionScheduler: log.info( f"Can't pardon {infraction['type']} for user {infraction['user']} because user left the guild." ) + log_text["Failure"] = f"User left the guild." + log_content = mod_role.mention else: log.exception(f"Failed to deactivate infraction #{id_} ({type_})") log_text["Failure"] = f"HTTPException with status {e.status} and code {e.code}." -- cgit v1.2.3 From 690ccd246e12d18a8c804b0802772f4a66a96bb8 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Wed, 2 Dec 2020 18:43:22 +0200 Subject: Fix removing extensions and cogs for bot shutdown --- bot/bot.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bot/bot.py b/bot/bot.py index cdb4e72a9..06b1bd6e0 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -175,9 +175,13 @@ class Bot(commands.Bot): async def close(self) -> None: """Close the Discord connection and the aiohttp session, connector, statsd client, and resolver.""" # Done before super().close() to allow tasks finish before the HTTP session closes. - with suppress(Exception): - [self.unload_extension(ext) for ext in tuple(self.extensions)] - [self.remove_cog(cog) for cog in tuple(self.cogs)] + for ext in list(self.extensions): + with suppress(Exception): + self.unload_extension(ext) + + for cog in list(self.cogs): + with suppress(Exception): + self.remove_cog(cog) # Wait until all tasks that have to be completed before bot is closing is done log.trace("Waiting for tasks before closing.") -- cgit v1.2.3 From 00ff5738ea29d51d2db4c633a112da0b1a71aedd Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Wed, 2 Dec 2020 18:49:02 +0200 Subject: Remove unnecessary f-string --- bot/exts/moderation/infraction/_scheduler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index ca4d18c98..44c31cd13 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -359,7 +359,7 @@ class InfractionScheduler: log.info( f"Can't pardon {infraction['type']} for user {infraction['user']} because user left the guild." ) - log_text["Failure"] = f"User left the guild." + log_text["Failure"] = "User left the guild." log_content = mod_role.mention else: log.exception(f"Failed to deactivate infraction #{id_} ({type_})") -- cgit v1.2.3 From 9d96d490e33861bc037e693d0d8f885c05f28fc2 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Thu, 17 Dec 2020 17:53:15 +0200 Subject: Log info instead error for watchchannel consume task cancel --- bot/exts/moderation/watchchannels/_watchchannel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/moderation/watchchannels/_watchchannel.py b/bot/exts/moderation/watchchannels/_watchchannel.py index 8894762f3..f9fc12dc3 100644 --- a/bot/exts/moderation/watchchannels/_watchchannel.py +++ b/bot/exts/moderation/watchchannels/_watchchannel.py @@ -347,7 +347,7 @@ class WatchChannel(metaclass=CogABCMeta): try: task.result() except asyncio.CancelledError: - self.log.error( + self.log.info( f"The consume task of {type(self).__name__} was canceled. Messages may be lost." ) -- cgit v1.2.3 From d3492b961618f4d6d0ec6622cffda3dadcd4b7a4 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sat, 19 Dec 2020 11:39:19 -0800 Subject: Fix flake8 pre-commit hook running through PyCharm --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 876d32b15..1597592ca 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,6 +21,6 @@ repos: name: Flake8 description: This hook runs flake8 within our project's pipenv environment. entry: pipenv run flake8 - language: python + language: system types: [python] require_serial: true -- cgit v1.2.3 From dd2497338721dff3d34b7127883c2c6d65cd08c5 Mon Sep 17 00:00:00 2001 From: Steele Date: Fri, 25 Dec 2020 14:10:43 -0500 Subject: `!user` command says if user is "Verified" Previously, `!user` said if the user is "Pending", whereas "Verified" is the boolean opposite. --- bot/exts/info/information.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py index 2057876e4..b2138b03f 100644 --- a/bot/exts/info/information.py +++ b/bot/exts/info/information.py @@ -229,9 +229,9 @@ class Information(Cog): if on_server: joined = time_since(user.joined_at, max_units=3) roles = ", ".join(role.mention for role in user.roles[1:]) - membership = {"Joined": joined, "Pending": user.pending, "Roles": roles or None} + membership = {"Joined": joined, "Verified": not user.pending, "Roles": roles or None} if not is_mod_channel(ctx.channel): - membership.pop("Pending") + membership.pop("Verified") membership = textwrap.dedent("\n".join([f"{key}: {value}" for key, value in membership.items()])) else: -- cgit v1.2.3 From fc8a1246b281fd0d495955e0b84c6fc75a59ba4d Mon Sep 17 00:00:00 2001 From: Steele Date: Wed, 30 Dec 2020 16:39:49 -0500 Subject: "Pending: False" to "Verified: True" to agree with new semantics. --- tests/bot/exts/info/test_information.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bot/exts/info/test_information.py b/tests/bot/exts/info/test_information.py index 043cce8de..d077be960 100644 --- a/tests/bot/exts/info/test_information.py +++ b/tests/bot/exts/info/test_information.py @@ -355,7 +355,7 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase): self.assertEqual( textwrap.dedent(f""" Joined: {"1 year ago"} - Pending: {"False"} + Verified: {"True"} Roles: &Moderators """).strip(), embed.fields[1].value -- cgit v1.2.3 From c9e8340749ac8ca8013062fb98adfd24c66f0417 Mon Sep 17 00:00:00 2001 From: Den4200 Date: Fri, 1 Jan 2021 20:28:28 -0500 Subject: Update discord.py to fix webhook message publishing. Related to #1342. --- Pipfile | 2 +- Pipfile.lock | 103 ++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 60 insertions(+), 45 deletions(-) diff --git a/Pipfile b/Pipfile index 3ff653749..1a9c271b4 100644 --- a/Pipfile +++ b/Pipfile @@ -14,7 +14,7 @@ beautifulsoup4 = "~=4.9" colorama = {version = "~=0.4.3",sys_platform = "== 'win32'"} coloredlogs = "~=14.0" deepdiff = "~=4.0" -"discord.py" = {git = "https://github.com/Rapptz/discord.py.git", ref = "93f102ca907af6722ee03638766afd53dfe93a7f"} +"discord.py" = {git = "https://github.com/Rapptz/discord.py.git", ref = "94f76e63947b102e5de6dae9a2cd687b308033"} feedparser = "~=5.2" fuzzywuzzy = "~=0.17" lxml = "~=4.4" diff --git a/Pipfile.lock b/Pipfile.lock index 085d3d829..17d2f81ba 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "1ba637e521c654a23bcc82950e155f5366219eae00bbf809170a371122961a4f" + "sha256": "8cc7415371be66ebc4dbfc3f3f27f19f743f4f1a9952ca30abf385a06047439b" }, "pipfile-spec": 6, "requires": { @@ -232,11 +232,11 @@ }, "discord-py": { "git": "https://github.com/Rapptz/discord.py.git", - "ref": "93f102ca907af6722ee03638766afd53dfe93a7f" + "ref": "94f76e63947b102e5de6dae9a2cd687b308033dd" }, "discord.py": { "git": "https://github.com/Rapptz/discord.py.git", - "ref": "93f102ca907af6722ee03638766afd53dfe93a7f" + "ref": "94f76e63947b102e5de6dae9a2cd687b308033" }, "docutils": { "hashes": [ @@ -592,10 +592,10 @@ }, "pytz": { "hashes": [ - "sha256:3e6b7dd2d1e0a59084bcee14a17af60c5c562cdc16d828e8eba2e683d3a7e268", - "sha256:5c55e189b682d420be27c6995ba6edce0c0a77dd67bfbe2ae6607134d5851ffd" + "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4", + "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5" ], - "version": "==2020.4" + "version": "==2020.5" }, "pyyaml": { "hashes": [ @@ -834,43 +834,58 @@ }, "coverage": { "hashes": [ - "sha256:0203acd33d2298e19b57451ebb0bed0ab0c602e5cf5a818591b4918b1f97d516", - "sha256:0f313707cdecd5cd3e217fc68c78a960b616604b559e9ea60cc16795c4304259", - "sha256:1c6703094c81fa55b816f5ae542c6ffc625fec769f22b053adb42ad712d086c9", - "sha256:1d44bb3a652fed01f1f2c10d5477956116e9b391320c94d36c6bf13b088a1097", - "sha256:280baa8ec489c4f542f8940f9c4c2181f0306a8ee1a54eceba071a449fb870a0", - "sha256:29a6272fec10623fcbe158fdf9abc7a5fa032048ac1d8631f14b50fbfc10d17f", - "sha256:2b31f46bf7b31e6aa690d4c7a3d51bb262438c6dcb0d528adde446531d0d3bb7", - "sha256:2d43af2be93ffbad25dd959899b5b809618a496926146ce98ee0b23683f8c51c", - "sha256:381ead10b9b9af5f64646cd27107fb27b614ee7040bb1226f9c07ba96625cbb5", - "sha256:47a11bdbd8ada9b7ee628596f9d97fbd3851bd9999d398e9436bd67376dbece7", - "sha256:4d6a42744139a7fa5b46a264874a781e8694bb32f1d76d8137b68138686f1729", - "sha256:50691e744714856f03a86df3e2bff847c2acede4c191f9a1da38f088df342978", - "sha256:530cc8aaf11cc2ac7430f3614b04645662ef20c348dce4167c22d99bec3480e9", - "sha256:582ddfbe712025448206a5bc45855d16c2e491c2dd102ee9a2841418ac1c629f", - "sha256:63808c30b41f3bbf65e29f7280bf793c79f54fb807057de7e5238ffc7cc4d7b9", - "sha256:71b69bd716698fa62cd97137d6f2fdf49f534decb23a2c6fc80813e8b7be6822", - "sha256:7858847f2d84bf6e64c7f66498e851c54de8ea06a6f96a32a1d192d846734418", - "sha256:78e93cc3571fd928a39c0b26767c986188a4118edc67bc0695bc7a284da22e82", - "sha256:7f43286f13d91a34fadf61ae252a51a130223c52bfefb50310d5b2deb062cf0f", - "sha256:86e9f8cd4b0cdd57b4ae71a9c186717daa4c5a99f3238a8723f416256e0b064d", - "sha256:8f264ba2701b8c9f815b272ad568d555ef98dfe1576802ab3149c3629a9f2221", - "sha256:9342dd70a1e151684727c9c91ea003b2fb33523bf19385d4554f7897ca0141d4", - "sha256:9361de40701666b034c59ad9e317bae95c973b9ff92513dd0eced11c6adf2e21", - "sha256:9669179786254a2e7e57f0ecf224e978471491d660aaca833f845b72a2df3709", - "sha256:aac1ba0a253e17889550ddb1b60a2063f7474155465577caa2a3b131224cfd54", - "sha256:aef72eae10b5e3116bac6957de1df4d75909fc76d1499a53fb6387434b6bcd8d", - "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270", - "sha256:c1b78fb9700fc961f53386ad2fd86d87091e06ede5d118b8a50dea285a071c24", - "sha256:c3888a051226e676e383de03bf49eb633cd39fc829516e5334e69b8d81aae751", - "sha256:c5f17ad25d2c1286436761b462e22b5020d83316f8e8fcb5deb2b3151f8f1d3a", - "sha256:c851b35fc078389bc16b915a0a7c1d5923e12e2c5aeec58c52f4aa8085ac8237", - "sha256:cb7df71de0af56000115eafd000b867d1261f786b5eebd88a0ca6360cccfaca7", - "sha256:cedb2f9e1f990918ea061f28a0f0077a07702e3819602d3507e2ff98c8d20636", - "sha256:e8caf961e1b1a945db76f1b5fa9c91498d15f545ac0ababbe575cfab185d3bd8" + "sha256:08b3ba72bd981531fd557f67beee376d6700fba183b167857038997ba30dd297", + "sha256:2757fa64e11ec12220968f65d086b7a29b6583d16e9a544c889b22ba98555ef1", + "sha256:3102bb2c206700a7d28181dbe04d66b30780cde1d1c02c5f3c165cf3d2489497", + "sha256:3498b27d8236057def41de3585f317abae235dd3a11d33e01736ffedb2ef8606", + "sha256:378ac77af41350a8c6b8801a66021b52da8a05fd77e578b7380e876c0ce4f528", + "sha256:38f16b1317b8dd82df67ed5daa5f5e7c959e46579840d77a67a4ceb9cef0a50b", + "sha256:3911c2ef96e5ddc748a3c8b4702c61986628bb719b8378bf1e4a6184bbd48fe4", + "sha256:3a3c3f8863255f3c31db3889f8055989527173ef6192a283eb6f4db3c579d830", + "sha256:3b14b1da110ea50c8bcbadc3b82c3933974dbeea1832e814aab93ca1163cd4c1", + "sha256:535dc1e6e68fad5355f9984d5637c33badbdc987b0c0d303ee95a6c979c9516f", + "sha256:6f61319e33222591f885c598e3e24f6a4be3533c1d70c19e0dc59e83a71ce27d", + "sha256:723d22d324e7997a651478e9c5a3120a0ecbc9a7e94071f7e1954562a8806cf3", + "sha256:76b2775dda7e78680d688daabcb485dc87cf5e3184a0b3e012e1d40e38527cc8", + "sha256:782a5c7df9f91979a7a21792e09b34a658058896628217ae6362088b123c8500", + "sha256:7e4d159021c2029b958b2363abec4a11db0ce8cd43abb0d9ce44284cb97217e7", + "sha256:8dacc4073c359f40fcf73aede8428c35f84639baad7e1b46fce5ab7a8a7be4bb", + "sha256:8f33d1156241c43755137288dea619105477961cfa7e47f48dbf96bc2c30720b", + "sha256:8ffd4b204d7de77b5dd558cdff986a8274796a1e57813ed005b33fd97e29f059", + "sha256:93a280c9eb736a0dcca19296f3c30c720cb41a71b1f9e617f341f0a8e791a69b", + "sha256:9a4f66259bdd6964d8cf26142733c81fb562252db74ea367d9beb4f815478e72", + "sha256:9a9d4ff06804920388aab69c5ea8a77525cf165356db70131616acd269e19b36", + "sha256:a2070c5affdb3a5e751f24208c5c4f3d5f008fa04d28731416e023c93b275277", + "sha256:a4857f7e2bc6921dbd487c5c88b84f5633de3e7d416c4dc0bb70256775551a6c", + "sha256:a607ae05b6c96057ba86c811d9c43423f35e03874ffb03fbdcd45e0637e8b631", + "sha256:a66ca3bdf21c653e47f726ca57f46ba7fc1f260ad99ba783acc3e58e3ebdb9ff", + "sha256:ab110c48bc3d97b4d19af41865e14531f300b482da21783fdaacd159251890e8", + "sha256:b239711e774c8eb910e9b1ac719f02f5ae4bf35fa0420f438cdc3a7e4e7dd6ec", + "sha256:be0416074d7f253865bb67630cf7210cbc14eb05f4099cc0f82430135aaa7a3b", + "sha256:c46643970dff9f5c976c6512fd35768c4a3819f01f61169d8cdac3f9290903b7", + "sha256:c5ec71fd4a43b6d84ddb88c1df94572479d9a26ef3f150cef3dacefecf888105", + "sha256:c6e5174f8ca585755988bc278c8bb5d02d9dc2e971591ef4a1baabdf2d99589b", + "sha256:c89b558f8a9a5a6f2cfc923c304d49f0ce629c3bd85cb442ca258ec20366394c", + "sha256:cc44e3545d908ecf3e5773266c487ad1877be718d9dc65fc7eb6e7d14960985b", + "sha256:cc6f8246e74dd210d7e2b56c76ceaba1cc52b025cd75dbe96eb48791e0250e98", + "sha256:cd556c79ad665faeae28020a0ab3bda6cd47d94bec48e36970719b0b86e4dcf4", + "sha256:ce6f3a147b4b1a8b09aae48517ae91139b1b010c5f36423fa2b866a8b23df879", + "sha256:ceb499d2b3d1d7b7ba23abe8bf26df5f06ba8c71127f188333dddcf356b4b63f", + "sha256:cef06fb382557f66d81d804230c11ab292d94b840b3cb7bf4450778377b592f4", + "sha256:e448f56cfeae7b1b3b5bcd99bb377cde7c4eb1970a525c770720a352bc4c8044", + "sha256:e52d3d95df81c8f6b2a1685aabffadf2d2d9ad97203a40f8d61e51b70f191e4e", + "sha256:ee2f1d1c223c3d2c24e3afbb2dd38be3f03b1a8d6a83ee3d9eb8c36a52bee899", + "sha256:f2c6888eada180814b8583c3e793f3f343a692fc802546eed45f40a001b1169f", + "sha256:f51dbba78d68a44e99d484ca8c8f604f17e957c1ca09c3ebc2c7e3bbd9ba0448", + "sha256:f54de00baf200b4539a5a092a759f000b5f45fd226d6d25a76b0dff71177a714", + "sha256:fa10fee7e32213f5c7b0d6428ea92e3a3fdd6d725590238a3f92c0de1c78b9d2", + "sha256:fabeeb121735d47d8eab8671b6b031ce08514c86b7ad8f7d5490a7b6dcd6267d", + "sha256:fac3c432851038b3e6afe086f777732bcf7f6ebbfd90951fa04ee53db6d0bcdd", + "sha256:fda29412a66099af6d6de0baa6bd7c52674de177ec2ad2630ca264142d69c6c7", + "sha256:ff1330e8bc996570221b450e2d539134baa9465f5cb98aff0e0f73f34172e0ae" ], "index": "pypi", - "version": "==5.3" + "version": "==5.3.1" }, "coveralls": { "hashes": [ @@ -972,11 +987,11 @@ }, "identify": { "hashes": [ - "sha256:943cd299ac7f5715fcb3f684e2fc1594c1e0f22a90d15398e5888143bd4144b5", - "sha256:cc86e6a9a390879dcc2976cef169dd9cc48843ed70b7380f321d1b118163c60e" + "sha256:7aef7a5104d6254c162990e54a203cdc0fd202046b6c415bd5d636472f6565c4", + "sha256:b2c71bf9f5c482c389cef816f3a15f1c9d7429ad70f497d4a2e522442d80c6de" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.5.10" + "version": "==1.5.11" }, "idna": { "hashes": [ -- cgit v1.2.3 From de32c8780d1d812fd0d088438ca9680a6e02b1e3 Mon Sep 17 00:00:00 2001 From: xithrius Date: Sat, 2 Jan 2021 21:54:17 -0800 Subject: No nominaton reason blank replaced by italic None --- bot/exts/moderation/watchchannels/talentpool.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bot/exts/moderation/watchchannels/talentpool.py b/bot/exts/moderation/watchchannels/talentpool.py index 7004b559a..fdba6606d 100644 --- a/bot/exts/moderation/watchchannels/talentpool.py +++ b/bot/exts/moderation/watchchannels/talentpool.py @@ -246,6 +246,8 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): log.debug(active) log.debug(type(nomination_object["inserted_at"])) + reason = nomination_object["reason"] or "*None*" + start_date = time.format_infraction(nomination_object["inserted_at"]) if active: lines = textwrap.dedent( @@ -254,7 +256,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): Status: **Active** Date: {start_date} Actor: {actor.mention if actor else actor_id} - Reason: {nomination_object["reason"]} + Reason: {reason} Nomination ID: `{nomination_object["id"]}` =============== """ @@ -267,7 +269,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): Status: Inactive Date: {start_date} Actor: {actor.mention if actor else actor_id} - Reason: {nomination_object["reason"]} + Reason: {reason} End date: {end_date} Unwatch reason: {nomination_object["end_reason"]} -- cgit v1.2.3 From b336e9721e6fb77a66536176e33587b8f9e09111 Mon Sep 17 00:00:00 2001 From: Xithrius <15021300+Xithrius@users.noreply.github.com> Date: Sat, 2 Jan 2021 23:28:47 -0800 Subject: Set reason to default as an empty string. Co-authored-by: Dennis Pham --- bot/exts/moderation/watchchannels/_watchchannel.py | 5 +---- bot/exts/moderation/watchchannels/talentpool.py | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/bot/exts/moderation/watchchannels/_watchchannel.py b/bot/exts/moderation/watchchannels/_watchchannel.py index d1e976190..f9fc12dc3 100644 --- a/bot/exts/moderation/watchchannels/_watchchannel.py +++ b/bot/exts/moderation/watchchannels/_watchchannel.py @@ -285,10 +285,7 @@ class WatchChannel(metaclass=CogABCMeta): else: message_jump = f"in [#{msg.channel.name}]({msg.jump_url})" - # Add reason to the footer if it exists. - footer = f"Added {time_delta} by {actor}" - if reason: - footer += f" | Reason: {reason}" + footer = f"Added {time_delta} by {actor} | Reason: {reason}" embed = Embed(description=f"{msg.author.mention} {message_jump}") embed.set_footer(text=textwrap.shorten(footer, width=128, placeholder="...")) diff --git a/bot/exts/moderation/watchchannels/talentpool.py b/bot/exts/moderation/watchchannels/talentpool.py index fdba6606d..8dd46a951 100644 --- a/bot/exts/moderation/watchchannels/talentpool.py +++ b/bot/exts/moderation/watchchannels/talentpool.py @@ -64,7 +64,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): @nomination_group.command(name='watch', aliases=('w', 'add', 'a'), root_aliases=("nominate",)) @has_any_role(*STAFF_ROLES) - async def watch_command(self, ctx: Context, user: FetchedMember, *, reason: Optional[str] = '') -> None: + async def watch_command(self, ctx: Context, user: FetchedMember, *, reason: str = '') -> None: """ Relay messages sent by the given `user` to the `#talent-pool` channel. -- cgit v1.2.3 From 175738048d78d74d0ac46b3e9849634a93a21b4c Mon Sep 17 00:00:00 2001 From: Xithrius <15021300+Xithrius@users.noreply.github.com> Date: Sat, 2 Jan 2021 23:29:21 -0800 Subject: Removed unnecessary debugging logs. Co-authored-by: Dennis Pham --- bot/exts/moderation/watchchannels/talentpool.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/bot/exts/moderation/watchchannels/talentpool.py b/bot/exts/moderation/watchchannels/talentpool.py index 8dd46a951..311c46d3b 100644 --- a/bot/exts/moderation/watchchannels/talentpool.py +++ b/bot/exts/moderation/watchchannels/talentpool.py @@ -243,8 +243,6 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): actor = guild.get_member(actor_id) active = nomination_object["active"] - log.debug(active) - log.debug(type(nomination_object["inserted_at"])) reason = nomination_object["reason"] or "*None*" -- cgit v1.2.3 From e0fe8fd1ec73b83c934a350b189210294dbb7637 Mon Sep 17 00:00:00 2001 From: xithrius Date: Sat, 2 Jan 2021 23:31:57 -0800 Subject: Removed 'Optional' import. --- bot/exts/moderation/watchchannels/talentpool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/moderation/watchchannels/talentpool.py b/bot/exts/moderation/watchchannels/talentpool.py index 311c46d3b..df2ce586e 100644 --- a/bot/exts/moderation/watchchannels/talentpool.py +++ b/bot/exts/moderation/watchchannels/talentpool.py @@ -1,7 +1,7 @@ import logging import textwrap from collections import ChainMap -from typing import Optional, Union +from typing import Union from discord import Color, Embed, Member, User from discord.ext.commands import Cog, Context, group, has_any_role -- cgit v1.2.3