From 84c87597ba585ba2612b7174cd5180c6403fb58b Mon Sep 17 00:00:00 2001 From: Tom Sputz Date: Mon, 30 Sep 2019 22:42:24 +0100 Subject: Forward arguments to get --- bot/cogs/doc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/doc.py b/bot/cogs/doc.py index e5c51748f..4fadcb8db 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 self.get_command(ctx, symbol) @docs_group.command(name='get', aliases=('g',)) async def get_command(self, ctx: commands.Context, symbol: commands.clean_content = None) -> None: -- cgit v1.2.3 From 11451fb010eb3afdc48ddcc4ab13fa24614920a0 Mon Sep 17 00:00:00 2001 From: sco1 Date: Mon, 30 Sep 2019 21:33:39 -0400 Subject: Update contrib doc for new wiki links --- CONTRIBUTING.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a0a1200ec..41df8fa20 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,9 +36,10 @@ All projects evolve over time, and this contribution guide is no different. This ## Supplemental Information ### Developer Environment -A working environment for the [PyDis site](https://github.com/python-discord/site) is required to develop the bot. Instructions for setting up environments for both the site and the bot can be found on the PyDis Wiki: - * [Site](https://wiki.pythondiscord.com/wiki/contributing/project/site) - * [Bot](https://wiki.pythondiscord.com/wiki/contributing/project/bot) +Instructions for setting the bot developer environment can be found on the PyDis site: + * [Bot](https://pythondiscord.com/pages/contributing/bot/) + +To provide a standalone development environment for this project, docker compose is utilized to pull the current version of the [site backend](https://github.com/python-discord/site). While appropriate for bot-only contributions, any contributions that necessitate backend changes will require the site repository to be appropriately configured as well. Instructions for setting up the site environment can be found on the [PyDis site](https://pythondiscord.com/pages/contributing/site/). When pulling down changes from GitHub, remember to sync your environment using `pipenv sync --dev` to ensure you're using the most up-to-date versions the project's dependencies. -- cgit v1.2.3 From 4c3714bf406ff750ddc306457f41b4871160338f Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Tue, 1 Oct 2019 11:34:24 +0200 Subject: Make `!tags edit` use PATCH to update tags https://github.com/python-discord/bot/issues/474 This commit makes sure we're using the PATCH method to update tags, instead of the POST method. The problem was that the `!tags edit` command was an alias of `!tags set`, which uses the POST method to post new tags to the API. However, when a tag with a given name already exists, the API will refuse a POST request in an attempt to update it; we need to use the PATCH method to the `bot/tags/{tag_name}` endpoint instead. I fixed this by creating a separate subcommand, `!tags edit`, that uses the correct PATCH method to update an existing tag. This commit closes #474 --- bot/cogs/tags.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) 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: -- cgit v1.2.3 From 35c4d06a1807bbc491a75459d8bf7790d1467731 Mon Sep 17 00:00:00 2001 From: "S. Co1" Date: Tue, 1 Oct 2019 09:40:28 -0400 Subject: Remove single-item list It looks silly --- CONTRIBUTING.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 41df8fa20..39f76c7b4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,8 +36,7 @@ All projects evolve over time, and this contribution guide is no different. This ## Supplemental Information ### Developer Environment -Instructions for setting the bot developer environment can be found on the PyDis site: - * [Bot](https://pythondiscord.com/pages/contributing/bot/) +Instructions for setting the bot developer environment can be found on the [PyDis wiki](https://pythondiscord.com/pages/contributing/bot/) To provide a standalone development environment for this project, docker compose is utilized to pull the current version of the [site backend](https://github.com/python-discord/site). While appropriate for bot-only contributions, any contributions that necessitate backend changes will require the site repository to be appropriately configured as well. Instructions for setting up the site environment can be found on the [PyDis site](https://pythondiscord.com/pages/contributing/site/). -- cgit v1.2.3 From 9fff510e0ba493760a14728f2c71fb338b3d8460 Mon Sep 17 00:00:00 2001 From: Ayplo Date: Tue, 1 Oct 2019 16:30:50 +0100 Subject: Update bot/cogs/doc.py Co-Authored-By: S. Co1 --- bot/cogs/doc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/doc.py b/bot/cogs/doc.py index 4fadcb8db..40b31f90c 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 self.get_command(ctx, symbol) + 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: -- cgit v1.2.3 From 7bc7be9a6f1e60913d0bbbde8980af657e493177 Mon Sep 17 00:00:00 2001 From: "S. Co1" Date: Tue, 1 Oct 2019 11:34:21 -0400 Subject: Update docs cog docstring & fix URL converter attribute error --- bot/cogs/doc.py | 6 +++--- bot/converters.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bot/cogs/doc.py b/bot/cogs/doc.py index 40b31f90c..c9e6b3b91 100644 --- a/bot/cogs/doc.py +++ b/bot/cogs/doc.py @@ -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/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'): -- cgit v1.2.3 From 514576666ff7856ca09e049cb90ee8ac993107e2 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Tue, 1 Oct 2019 23:41:09 +0200 Subject: Create !tools alias and split !site resources. This splits the former !site resources into two separate commands, one for !site resources and one for !site tools. This makes sense now that we've split up the lists into two pages. It also adds a new alias, !tools, to call this command. This addresses #478. https://github.com/python-discord/bot/issues/478 --- bot/cogs/alias.py | 8 ++++++++ bot/cogs/site.py | 27 ++++++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/bot/cogs/alias.py b/bot/cogs/alias.py index 80ff37983..0df5498a1 100644 --- a/bot/cogs/alias.py +++ b/bot/cogs/alias.py @@ -53,6 +53,14 @@ class Alias (Cog): """Alias for invoking site resources.""" await self.invoke(ctx, "site resources") + @command(name="tools", hidden=True) + async def site_tools_alias(self, ctx): + """ + Alias for invoking 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 bigbrother watch [user] [reason].""" diff --git a/bot/cogs/site.py b/bot/cogs/site.py index 4a423faa9..8a8fed575 100644 --- a/bot/cogs/site.py +++ b/bot/cogs/site.py @@ -44,17 +44,30 @@ 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): + """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) -- cgit v1.2.3 From a994c2c2b67521b8a739536ae0c9d47de75ce7b8 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Tue, 1 Oct 2019 23:49:10 +0200 Subject: Fix missing type annotations and docstring errors. --- bot/cogs/alias.py | 7 ++----- bot/cogs/site.py | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/bot/cogs/alias.py b/bot/cogs/alias.py index 0df5498a1..0f49a400c 100644 --- a/bot/cogs/alias.py +++ b/bot/cogs/alias.py @@ -54,11 +54,8 @@ class Alias (Cog): await self.invoke(ctx, "site resources") @command(name="tools", hidden=True) - async def site_tools_alias(self, ctx): - """ - Alias for invoking site tools. - """ - + async def site_tools_alias(self, ctx: Context) -> None: + """Alias for invoking site tools.""" await self.invoke(ctx, "site tools") @command(name="watch", hidden=True) diff --git a/bot/cogs/site.py b/bot/cogs/site.py index 8a8fed575..c3bdf85e4 100644 --- a/bot/cogs/site.py +++ b/bot/cogs/site.py @@ -57,9 +57,8 @@ class Site(Cog): await ctx.send(embed=embed) @site_group.command(name="tools") - async def site_tools(self, ctx: Context): + 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") -- cgit v1.2.3 From a70cf2070f6af0b7710b0934b7e812dce78330d0 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Wed, 2 Oct 2019 06:44:21 +0200 Subject: Fix `cog_unload` bug in WatchChannel ABC https://github.com/python-discord/bot/issues/482 There was small bug in the `cog_unload` method of the WatchChannel ABC in `bot.cogs.watchchannels.watchchannel`. The problem was that it tries to check if the Task assigned to `self._consume_task` is done by accessing its `done` method. However, if a watch channel has not yet relayed messages after the bot has started, it will not have a consumption task yet, meaning this `_consume_task` attribute will be assigned to `None`. The solution is to change the `if` condition to: `if self._consume_task and not self._consume_task.done():` This commit closes #482 --- bot/cogs/watchchannels/watchchannel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/watchchannels/watchchannel.py b/bot/cogs/watchchannels/watchchannel.py index ce8014d69..760e012eb 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() -- cgit v1.2.3 From ce6a16d69291f92ca27ba0dfc83cb479f87bb384 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Thu, 3 Oct 2019 07:41:25 +1000 Subject: Fix mutes not being re-applied on rejoins. --- bot/cogs/moderation.py | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/bot/cogs/moderation.py b/bot/cogs/moderation.py index b596f36e6..5aa873a47 100644 --- a/bot/cogs/moderation.py +++ b/bot/cogs/moderation.py @@ -80,6 +80,43 @@ class Moderation(Scheduler, Cog): if infraction["expires_at"] is not None: self.schedule_task(self.bot.loop, infraction["id"], infraction) + @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] + + # transform expiration to delay in seconds + expiration_datetime = datetime.fromisoformat(mute["expires_at"][:-1]) + delay = expiration_datetime - datetime.utcnow() + delay_seconds = delay.total_seconds() + + # if under a minute or in the past + if delay_seconds < 60: + log.debug(f"Marking infraction {mute['id']} as inactive (expired).") + await self._deactivate_infraction(mute) + self.cancel_task(mute["id"]) + + # Notify the user that they've been unmuted. + await self.notify_pardon( + user=member, + title="You have been unmuted.", + content="You may now send messages in the server.", + icon_url=Icons.user_unmute + ) + return + + # allowing modlog 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 @with_role(*MODERATION_ROLES) @@ -955,6 +992,11 @@ class Moderation(Scheduler, Cog): user_id = infraction_object["user"] infraction_type = infraction_object["type"] + await self.bot.api_client.patch( + 'bot/infractions/' + str(infraction_object['id']), + json={"active": False} + ) + if infraction_type == "mute": member: Member = guild.get_member(user_id) if member: @@ -970,11 +1012,6 @@ class Moderation(Scheduler, Cog): except NotFound: log.info(f"Tried to unban user `{user_id}`, but Discord does not have an active ban registered.") - await self.bot.api_client.patch( - 'bot/infractions/' + str(infraction_object['id']), - json={"active": False} - ) - def _infraction_to_string(self, infraction_object: Dict[str, Union[str, int, bool]]) -> str: """Convert the infraction object to a string representation.""" actor_id = infraction_object["actor"] -- cgit v1.2.3