aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar MarkKoz <[email protected]>2019-10-03 10:33:45 -0700
committerGravatar MarkKoz <[email protected]>2019-10-03 10:44:32 -0700
commitcbdd384c7383fd13070988da03cbaaf481977b0e (patch)
treee0d7ca2e5b4c6472e5586f6acd7122ae8011f92d
parentMention moderators in the mod log when an infraction fails to expire (diff)
parentMerge pull request #486 from python-discord/mute-fix (diff)
Merge remote-tracking branch 'origin/master' into moderation-cleanup
-rw-r--r--bot/cogs/alias.py5
-rw-r--r--bot/cogs/doc.py8
-rw-r--r--bot/cogs/moderation/infractions.py33
-rw-r--r--bot/cogs/site.py26
-rw-r--r--bot/cogs/tags.py33
-rw-r--r--bot/cogs/watchchannels/watchchannel.py2
-rw-r--r--bot/converters.py2
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'):