diff options
author | 2024-02-18 21:15:26 +0100 | |
---|---|---|
committer | 2024-03-21 14:29:02 +0100 | |
commit | aad7301c270018341a979e409e952dd597c98e3c (patch) | |
tree | 1809e36655163f64f7f420aa6051b37ad2578edc | |
parent | implement the MovedCommandErrorHandler (diff) |
implement the handler for the UserInputError exception
-rw-r--r-- | bot/command_error_handlers/__init__.py | 2 | ||||
-rw-r--r-- | bot/command_error_handlers/_utils.py | 25 | ||||
-rw-r--r-- | bot/command_error_handlers/user_input_error.py | 32 | ||||
-rw-r--r-- | bot/exts/core/error_handler.py | 9 |
4 files changed, 58 insertions, 10 deletions
diff --git a/bot/command_error_handlers/__init__.py b/bot/command_error_handlers/__init__.py index 32c713bd..16d53373 100644 --- a/bot/command_error_handlers/__init__.py +++ b/bot/command_error_handlers/__init__.py @@ -5,6 +5,7 @@ from bot.bot import Bot from .command_not_found import CommandNotFoundErrorHandler from .default import DefaultCommandErrorHandler from .moved_command import MovedCommandErrorHandler +from .user_input_error import UserInputErrorHandler def bootstrap_command_error_manager(bot: Bot) -> CommandErrorManager: @@ -13,4 +14,5 @@ def bootstrap_command_error_manager(bot: Bot) -> CommandErrorManager: manager = CommandErrorManager(default=default_handler) manager.register_handler(CommandNotFoundErrorHandler(bot)) manager.register_handler(MovedCommandErrorHandler()) + manager.register_handler(UserInputErrorHandler()) return manager diff --git a/bot/command_error_handlers/_utils.py b/bot/command_error_handlers/_utils.py index 3a51bfee..410a8b9d 100644 --- a/bot/command_error_handlers/_utils.py +++ b/bot/command_error_handlers/_utils.py @@ -1,10 +1,14 @@ import random from collections.abc import Iterable -from discord import Embed +from discord import Embed, Message +from discord.ext import commands +from pydis_core.utils.logging import get_logger from bot.constants import Colours, ERROR_REPLIES +log = get_logger(__name__) + def create_error_embed(message: str, title: Iterable | str = ERROR_REPLIES) -> Embed: """Build a basic embed with red colour and either a random error title or a title provided.""" @@ -15,3 +19,22 @@ def create_error_embed(message: str, title: Iterable | str = ERROR_REPLIES) -> E embed.title = random.choice(title) embed.description = message return embed + + +def revert_cooldown_counter(command: commands.Command, message: Message) -> None: + """Undoes the last cooldown counter for user-error cases.""" + if command._buckets.valid: + bucket = command._buckets.get_bucket(message) + bucket._tokens = min(bucket.rate, bucket._tokens + 1) + log.debug("Cooldown counter reverted as the command was not used correctly.") + + +def get_parent_command_and_subcontext(context: commands.Context) -> tuple[str, commands.Context]: + """Extracts the parent command and subcontext, if any.""" + parent_command = "" + ctx = context + if sub_context := getattr(context, "subcontext", None): + parent_command = f"{context.command} " + ctx = sub_context + + return parent_command, ctx diff --git a/bot/command_error_handlers/user_input_error.py b/bot/command_error_handlers/user_input_error.py new file mode 100644 index 00000000..3f99da49 --- /dev/null +++ b/bot/command_error_handlers/user_input_error.py @@ -0,0 +1,32 @@ +from typing import NoReturn + +from discord import Interaction +from discord.ext.commands import Context, UserInputError +from pydis_core.utils.error_handling.commands import AbstractCommandErrorHandler + +from ._utils import create_error_embed, get_parent_command_and_subcontext, revert_cooldown_counter + + +class UserInputErrorHandler(AbstractCommandErrorHandler): + """An handler for the UserInputError error.""" + + async def should_handle_error(self, error: Exception) -> bool: + """A predicate that determines whether the error should be handled or not.""" + return isinstance(error, UserInputError) + + async def handle_text_command_error(self, context: Context, error: Exception) -> NoReturn: + """Handle error raised in the context of text commands.""" + revert_cooldown_counter(context.command, context.message) + parent_command, ctx = get_parent_command_and_subcontext(context) + usage = f"```\n{ctx.prefix}{parent_command}{ctx.command} {ctx.command.signature}\n```" + embed = create_error_embed( + f"Your input was invalid: {error}\n\nUsage:{usage}" + ) + await context.send(embed=embed) + + async def handle_app_command_error(self, interaction: Interaction, error: Exception) -> NoReturn: + """Handle error raised in the context of app commands.""" + embed = create_error_embed( + f"Your input was invalid: {error}\n" + ) + await interaction.response.send_message(embed=embed) diff --git a/bot/exts/core/error_handler.py b/bot/exts/core/error_handler.py index 0e5d60fc..e9a9d768 100644 --- a/bot/exts/core/error_handler.py +++ b/bot/exts/core/error_handler.py @@ -67,15 +67,6 @@ class CommandErrorHandler(commands.Cog): await ctx.send(embed=self.error_embed(str(error), NEGATIVE_REPLIES), delete_after=7.5) return - if isinstance(error, commands.UserInputError): - self.revert_cooldown_counter(ctx.command, ctx.message) - usage = f"```\n{ctx.prefix}{parent_command}{ctx.command} {ctx.command.signature}\n```" - embed = self.error_embed( - f"Your input was invalid: {error}\n\nUsage:{usage}" - ) - await ctx.send(embed=embed) - return - if isinstance(error, commands.CommandOnCooldown): mins, secs = divmod(math.ceil(error.retry_after), 60) embed = self.error_embed( |