aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/constants.py5
-rw-r--r--bot/exts/evergreen/error_handler.py36
2 files changed, 40 insertions, 1 deletions
diff --git a/bot/constants.py b/bot/constants.py
index 28ec477d..28103022 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -22,6 +22,7 @@ __all__ = (
"Wolfram",
"Reddit",
"RedisConfig",
+ "RedirectOutput",
"MODERATION_ROLES",
"STAFF_ROLES",
"WHITELISTED_CHANNELS",
@@ -305,6 +306,10 @@ class Source:
github_avatar_url = "https://avatars1.githubusercontent.com/u/9919"
+class RedirectOutput:
+ delete_delay: int = 10
+
+
class Reddit:
subreddits = ["r/Python"]
diff --git a/bot/exts/evergreen/error_handler.py b/bot/exts/evergreen/error_handler.py
index de8e53d0..cd53f932 100644
--- a/bot/exts/evergreen/error_handler.py
+++ b/bot/exts/evergreen/error_handler.py
@@ -1,3 +1,4 @@
+import difflib
import logging
import math
import random
@@ -8,13 +9,16 @@ from discord.ext import commands
from sentry_sdk import push_scope
from bot.bot import Bot
-from bot.constants import Channels, Colours, ERROR_REPLIES, NEGATIVE_REPLIES
+from bot.constants import Channels, Colours, ERROR_REPLIES, NEGATIVE_REPLIES, RedirectOutput
from bot.utils.decorators import InChannelCheckFailure, InMonthCheckFailure
from bot.utils.exceptions import UserNotPlayingError
log = logging.getLogger(__name__)
+QUESTION_MARK_ICON = "https://cdn.discordapp.com/emojis/512367613339369475.png"
+
+
class CommandErrorHandler(commands.Cog):
"""A error handler for the PythonDiscord server."""
@@ -58,6 +62,7 @@ class CommandErrorHandler(commands.Cog):
)
if isinstance(error, commands.CommandNotFound):
+ await self.send_command_suggestion(ctx, ctx.invoked_with)
return
if isinstance(error, (InChannelCheckFailure, InMonthCheckFailure)):
@@ -129,6 +134,35 @@ class CommandErrorHandler(commands.Cog):
log.exception(f"Unhandled command error: {str(error)}", exc_info=error)
+ async def send_command_suggestion(self, ctx: commands.Context, command_name: str) -> None:
+ """Sends user similar commands if any can be found."""
+ 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 commands.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=QUESTION_MARK_ICON)
+ e.description = misspelled_content.replace(command_name, similar_command_name, 1)
+ await ctx.send(embed=e, delete_after=RedirectOutput.delete_delay)
+
def setup(bot: Bot) -> None:
"""Load the ErrorHandler cog."""