diff options
Diffstat (limited to 'bot')
| -rw-r--r-- | bot/constants.py | 5 | ||||
| -rw-r--r-- | bot/exts/evergreen/error_handler.py | 36 | 
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.""" | 
