diff options
author | 2019-10-03 10:33:45 -0700 | |
---|---|---|
committer | 2019-10-03 10:44:32 -0700 | |
commit | cbdd384c7383fd13070988da03cbaaf481977b0e (patch) | |
tree | e0d7ca2e5b4c6472e5586f6acd7122ae8011f92d | |
parent | Mention moderators in the mod log when an infraction fails to expire (diff) | |
parent | Merge pull request #486 from python-discord/mute-fix (diff) |
Merge remote-tracking branch 'origin/master' into moderation-cleanup
-rw-r--r-- | bot/cogs/alias.py | 5 | ||||
-rw-r--r-- | bot/cogs/doc.py | 8 | ||||
-rw-r--r-- | bot/cogs/moderation/infractions.py | 33 | ||||
-rw-r--r-- | bot/cogs/site.py | 26 | ||||
-rw-r--r-- | bot/cogs/tags.py | 33 | ||||
-rw-r--r-- | bot/cogs/watchchannels/watchchannel.py | 2 | ||||
-rw-r--r-- | bot/converters.py | 2 |
7 files changed, 94 insertions, 15 deletions
diff --git a/bot/cogs/alias.py b/bot/cogs/alias.py index 80ff37983..0f49a400c 100644 --- a/bot/cogs/alias.py +++ b/bot/cogs/alias.py @@ -53,6 +53,11 @@ class Alias (Cog): """Alias for invoking <prefix>site resources.""" await self.invoke(ctx, "site resources") + @command(name="tools", hidden=True) + async def site_tools_alias(self, ctx: Context) -> None: + """Alias for invoking <prefix>site tools.""" + await self.invoke(ctx, "site tools") + @command(name="watch", hidden=True) async def bigbrother_watch_alias(self, ctx: Context, user: Union[Member, User, proxy_user], *, reason: str) -> None: """Alias for invoking <prefix>bigbrother watch [user] [reason].""" diff --git a/bot/cogs/doc.py b/bot/cogs/doc.py index e5c51748f..c9e6b3b91 100644 --- a/bot/cogs/doc.py +++ b/bot/cogs/doc.py @@ -261,7 +261,7 @@ class Doc(commands.Cog): @commands.group(name='docs', aliases=('doc', 'd'), invoke_without_command=True) async def docs_group(self, ctx: commands.Context, symbol: commands.clean_content = None) -> None: """Lookup documentation for Python symbols.""" - await ctx.invoke(self.get_command) + await ctx.invoke(self.get_command, symbol) @docs_group.command(name='get', aliases=('g',)) async def get_command(self, ctx: commands.Context, symbol: commands.clean_content = None) -> None: @@ -319,9 +319,9 @@ class Doc(commands.Cog): Example: !docs set \ - discord \ - https://discordpy.readthedocs.io/en/rewrite/ \ - https://discordpy.readthedocs.io/en/rewrite/objects.inv + python \ + https://docs.python.org/3/ \ + https://docs.python.org/3/objects.inv """ body = { 'package': package_name, diff --git a/bot/cogs/moderation/infractions.py b/bot/cogs/moderation/infractions.py index feb22e5ab..64644ee82 100644 --- a/bot/cogs/moderation/infractions.py +++ b/bot/cogs/moderation/infractions.py @@ -1,6 +1,7 @@ import logging import textwrap import typing as t +from datetime import datetime import dateutil.parser import discord @@ -50,6 +51,36 @@ class Infractions(Scheduler, commands.Cog): if infraction["expires_at"] is not None: self.schedule_task(self.bot.loop, infraction["id"], infraction) + @commands.Cog.listener() + async def on_member_join(self, member: Member) -> None: + """Reapply active mute infractions for returning members.""" + active_mutes = await self.bot.api_client.get( + 'bot/infractions', + params={ + 'user__id': str(member.id), + 'type': 'mute', + 'active': 'true' + } + ) + if not active_mutes: + return + + # Assume a single mute because of restrictions elsewhere. + mute = active_mutes[0] + + # Calculate the time remaining, in seconds, for the mute. + expiry = dateutil.parser.isoparse(mute["expires_at"]).replace(tzinfo=None) + delta = (expiry - datetime.utcnow()).total_seconds() + + # Mark as inactive if less than a minute remains. + if delta < 60: + await self.deactivate_infraction(mute) + return + + # Allowing mod log since this is a passive action that should be logged. + await member.add_roles(self._muted_role, reason=f"Re-applying active mute: {mute['id']}") + log.debug(f"User {member.id} has been re-muted on rejoin.") + # region: Permanent infractions @command() @@ -268,6 +299,8 @@ class Infractions(Scheduler, commands.Cog): _id = infraction["id"] reason = f"Infraction #{_id} expired or was pardoned." + log.debug(f"Marking infraction #{_id} as inactive (expired).") + log_content = None log_text = { "Member": str(user_id), diff --git a/bot/cogs/site.py b/bot/cogs/site.py index 4a423faa9..c3bdf85e4 100644 --- a/bot/cogs/site.py +++ b/bot/cogs/site.py @@ -44,17 +44,29 @@ class Site(Cog): async def site_resources(self, ctx: Context) -> None: """Info about the site's Resources page.""" learning_url = f"{PAGES_URL}/resources" - tools_url = f"{PAGES_URL}/tools" - embed = Embed(title="Resources & Tools") - embed.set_footer(text=f"{learning_url} | {tools_url}") + embed = Embed(title="Resources") + embed.set_footer(text=f"{learning_url}") embed.colour = Colour.blurple() embed.description = ( f"The [Resources page]({learning_url}) on our website contains a " - "list of hand-selected goodies that we regularly recommend " - f"to both beginners and experts. The [Tools page]({tools_url}) " - "contains a couple of the most popular tools for programming in " - "Python." + "list of hand-selected learning resources that we regularly recommend " + f"to both beginners and experts." + ) + + await ctx.send(embed=embed) + + @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" + + embed = Embed(title="Tools") + embed.set_footer(text=f"{tools_url}") + embed.colour = Colour.blurple() + embed.description = ( + f"The [Tools page]({tools_url}) on our website contains a " + f"couple of the most popular tools for programming in Python." ) await ctx.send(embed=embed) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index b9dd3595e..cd70e783a 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -86,7 +86,7 @@ class Tags(Cog): max_lines=15 ) - @tags_group.command(name='set', aliases=('add', 'edit', 's')) + @tags_group.command(name='set', aliases=('add', 's')) @with_role(*MODERATION_ROLES) async def set_command( self, @@ -95,7 +95,7 @@ class Tags(Cog): *, tag_content: TagContentConverter, ) -> None: - """Create a new tag or update an existing one.""" + """Create a new tag.""" body = { 'title': tag_name.lower().strip(), 'embed': { @@ -116,6 +116,35 @@ class Tags(Cog): colour=Colour.blurple() )) + @tags_group.command(name='edit', aliases=('e', )) + @with_role(*MODERATION_ROLES) + async def edit_command( + self, + ctx: Context, + tag_name: TagNameConverter, + *, + tag_content: TagContentConverter, + ) -> None: + """Edit an existing tag.""" + body = { + 'embed': { + 'title': tag_name, + 'description': tag_content + } + } + + await self.bot.api_client.patch(f'bot/tags/{tag_name}', json=body) + + log.debug(f"{ctx.author} successfully edited the following tag in our database: \n" + f"tag_name: {tag_name}\n" + f"tag_content: '{tag_content}'\n") + + await ctx.send(embed=Embed( + title="Tag successfully edited", + description=f"**{tag_name}** edited in the database.", + colour=Colour.blurple() + )) + @tags_group.command(name='delete', aliases=('remove', 'rm', 'd')) @with_role(Roles.admin, Roles.owner) async def delete_command(self, ctx: Context, *, tag_name: TagNameConverter) -> None: diff --git a/bot/cogs/watchchannels/watchchannel.py b/bot/cogs/watchchannels/watchchannel.py index e67f4674b..0bf75a924 100644 --- a/bot/cogs/watchchannels/watchchannel.py +++ b/bot/cogs/watchchannels/watchchannel.py @@ -335,7 +335,7 @@ class WatchChannel(metaclass=CogABCMeta): def cog_unload(self) -> None: """Takes care of unloading the cog and canceling the consumption task.""" self.log.trace(f"Unloading the cog") - if not self._consume_task.done(): + if self._consume_task and not self._consume_task.done(): self._consume_task.cancel() try: self._consume_task.result() diff --git a/bot/converters.py b/bot/converters.py index 339da7b60..6d6453486 100644 --- a/bot/converters.py +++ b/bot/converters.py @@ -49,7 +49,7 @@ class ValidURL(Converter): async with ctx.bot.http_session.get(url) as resp: if resp.status != 200: raise BadArgument( - f"HTTP GET on `{url}` returned status `{resp.status_code}`, expected 200" + f"HTTP GET on `{url}` returned status `{resp.status}`, expected 200" ) except CertificateError: if url.startswith('https'): |