aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar ks129 <[email protected]>2021-01-17 08:55:29 +0200
committerGravatar GitHub <[email protected]>2021-01-17 08:55:29 +0200
commit4eb4e805ffce27c51db0e08bb9804b47b5f8b379 (patch)
tree6bd8f5e25b5f3b2bbe45067f2749380836d32f74
parentRelock Pipfile (diff)
parentMerge pull request #1360 from HassanAbouelela/fixes_tag_suggestions (diff)
Merge branch 'master' into branding-manager
-rw-r--r--Pipfile.lock8
-rw-r--r--bot/exts/backend/error_handler.py46
-rw-r--r--bot/exts/info/tags.py28
-rw-r--r--bot/exts/moderation/verification.py4
-rw-r--r--bot/exts/moderation/watchchannels/talentpool.py3
5 files changed, 74 insertions, 15 deletions
diff --git a/Pipfile.lock b/Pipfile.lock
index 8fd7f0964..636d07b1a 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -587,7 +587,7 @@
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
],
- "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'",
"version": "==2.4.7"
},
"python-dateutil": {
@@ -653,7 +653,7 @@
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==1.15.0"
},
"snowballstemmer": {
@@ -1095,7 +1095,7 @@
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==1.15.0"
},
"snowballstemmer": {
@@ -1110,7 +1110,7 @@
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
- "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'",
"version": "==0.10.2"
},
"urllib3": {
diff --git a/bot/exts/backend/error_handler.py b/bot/exts/backend/error_handler.py
index 0aeffe290..9398aa8ec 100644
--- a/bot/exts/backend/error_handler.py
+++ b/bot/exts/backend/error_handler.py
@@ -1,4 +1,5 @@
import contextlib
+import difflib
import logging
import random
import typing as t
@@ -9,7 +10,7 @@ from sentry_sdk import push_scope
from bot.api import ResponseCodeError
from bot.bot import Bot
-from bot.constants import Colours, ERROR_REPLIES
+from bot.constants import Colours, ERROR_REPLIES, Icons, MODERATION_ROLES
from bot.converters import TagNameConverter
from bot.errors import LockedResourceError
from bot.exts.backend.branding._errors import BrandingError
@@ -159,10 +160,51 @@ class ErrorHandler(Cog):
)
else:
with contextlib.suppress(ResponseCodeError):
- await ctx.invoke(tags_get_command, tag_name=tag_name)
+ if await ctx.invoke(tags_get_command, tag_name=tag_name):
+ return
+
+ if not any(role.id in MODERATION_ROLES for role in ctx.author.roles):
+ tags_cog = self.bot.get_cog("Tags")
+ command_name = ctx.invoked_with
+ sent = await tags_cog.display_tag(ctx, command_name)
+
+ if not sent:
+ await self.send_command_suggestion(ctx, command_name)
+
# Return to not raise the exception
return
+ async def send_command_suggestion(self, ctx: Context, command_name: str) -> None:
+ """Sends user similar commands if any can be found."""
+ # No similar tag found, or tag on cooldown -
+ # searching for a similar command
+ raw_commands = []
+ for cmd in self.bot.walk_commands():
+ if not cmd.hidden:
+ raw_commands += (cmd.name, *cmd.aliases)
+ if similar_command_data := difflib.get_close_matches(command_name, raw_commands, 1):
+ similar_command_name = similar_command_data[0]
+ similar_command = self.bot.get_command(similar_command_name)
+
+ if not similar_command:
+ return
+
+ log_msg = "Cancelling attempt to suggest a command due to failed checks."
+ try:
+ if not await similar_command.can_run(ctx):
+ log.debug(log_msg)
+ return
+ except errors.CommandError as cmd_error:
+ log.debug(log_msg)
+ await self.on_command_error(ctx, cmd_error)
+ return
+
+ misspelled_content = ctx.message.content
+ e = Embed()
+ e.set_author(name="Did you mean:", icon_url=Icons.questionmark)
+ e.description = f"{misspelled_content.replace(command_name, similar_command_name, 1)}"
+ await ctx.send(embed=e, delete_after=10.0)
+
async def handle_user_input_error(self, ctx: Context, e: errors.UserInputError) -> None:
"""
Send an error message in `ctx` for UserInputError, sometimes invoking the help command too.
diff --git a/bot/exts/info/tags.py b/bot/exts/info/tags.py
index da4154316..00b4d1a78 100644
--- a/bot/exts/info/tags.py
+++ b/bot/exts/info/tags.py
@@ -182,10 +182,15 @@ class Tags(Cog):
matching_tags = self._get_tags_via_content(any, keywords or 'any', ctx.author)
await self._send_matching_tags(ctx, keywords, matching_tags)
- @tags_group.command(name='get', aliases=('show', 'g'))
- async def get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None:
- """Get a specified tag, or a list of all tags if no tag is specified."""
+ async def display_tag(self, ctx: Context, tag_name: str = None) -> bool:
+ """
+ If a tag is not found, display similar tag names as suggestions.
+ If a tag is not specified, display a paginated embed of all tags.
+
+ Tags are on cooldowns on a per-tag, per-channel basis. If a tag is on cooldown, display
+ nothing and return False.
+ """
def _command_on_cooldown(tag_name: str) -> bool:
"""
Check if the command is currently on cooldown, on a per-tag, per-channel basis.
@@ -212,7 +217,7 @@ class Tags(Cog):
f"{ctx.author} tried to get the '{tag_name}' tag, but the tag is on cooldown. "
f"Cooldown ends in {time_left:.1f} seconds."
)
- return
+ return False
if tag_name is not None:
temp_founds = self._get_tag(tag_name)
@@ -237,6 +242,7 @@ class Tags(Cog):
await ctx.send(embed=Embed.from_dict(tag['embed'])),
[ctx.author.id],
)
+ return True
elif founds and len(tag_name) >= 3:
await wait_for_deletion(
await ctx.send(
@@ -247,6 +253,7 @@ class Tags(Cog):
),
[ctx.author.id],
)
+ return True
else:
tags = self._cache.values()
@@ -255,6 +262,7 @@ class Tags(Cog):
description="**There are no tags in the database!**",
colour=Colour.red()
))
+ return True
else:
embed: Embed = Embed(title="**Current tags**")
await LinePaginator.paginate(
@@ -268,6 +276,18 @@ class Tags(Cog):
empty=False,
max_lines=15
)
+ return True
+
+ return False
+
+ @tags_group.command(name='get', aliases=('show', 'g'))
+ async def get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> bool:
+ """
+ Get a specified tag, or a list of all tags if no tag is specified.
+
+ Returns False if a tag is on cooldown, or if no matches are found.
+ """
+ return await self.display_tag(ctx, tag_name)
def setup(bot: Bot) -> None:
diff --git a/bot/exts/moderation/verification.py b/bot/exts/moderation/verification.py
index 2a24c8ec6..bfe9b74b4 100644
--- a/bot/exts/moderation/verification.py
+++ b/bot/exts/moderation/verification.py
@@ -81,13 +81,11 @@ class Verification(Cog):
if member.guild.id != constants.Guild.id:
return # Only listen for PyDis events
- raw_member = await self.bot.http.get_member(member.guild.id, member.id)
-
# If the user has the pending flag set, they will be using the alternate
# gate and will not need a welcome DM with verification instructions.
# We will send them an alternate DM once they verify with the welcome
# video when they pass the gate.
- if raw_member.get("pending"):
+ if member.pending:
return
log.trace(f"Sending on join message to new member: {member.id}")
diff --git a/bot/exts/moderation/watchchannels/talentpool.py b/bot/exts/moderation/watchchannels/talentpool.py
index df2ce586e..dd3349c3a 100644
--- a/bot/exts/moderation/watchchannels/talentpool.py
+++ b/bot/exts/moderation/watchchannels/talentpool.py
@@ -122,8 +122,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"):
if history:
total = f"({len(history)} previous nominations in total)"
start_reason = f"Watched: {textwrap.shorten(history[0]['reason'], width=500, placeholder='...')}"
- end_reason = f"Unwatched: {textwrap.shorten(history[0]['end_reason'], width=500, placeholder='...')}"
- msg += f"\n\nUser's previous watch reasons {total}:```{start_reason}\n\n{end_reason}```"
+ msg += f"\n\nUser's previous watch reasons {total}:```{start_reason}```"
await ctx.send(msg)