Last active
April 3, 2025 19:21
-
Star
(123)
You must be signed in to star a gist -
Fork
(10)
You must be signed in to fork a gist
-
-
Save EvieePy/7822af90858ef65012ea500bcecf1612 to your computer and use it in GitHub Desktop.
Simple Error Handling for Prefix and App commands - discord.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import discord | |
from discord import app_commands | |
from discord.ext import commands | |
LOGGER: logging.Logger = logging.getLogger(__name__) | |
class CommandErrors(commands.Cog): | |
def __init__(self, bot: commands.Bot) -> None: | |
# Save the default handlers incase we have to unload this extension... | |
self.original_command_error = bot.on_command_error | |
self.original_app_error = bot.tree.on_error | |
# Assign the new handlers to the bot... | |
bot.on_command_error = self.on_command_error | |
bot.tree.on_error = self.on_app_command_error | |
self.bot = bot | |
async def cog_unload(self) -> None: | |
"""Load the original error handlers back into the bot when this Cog unloads.""" | |
self.bot.on_command_error = self.original_command_error | |
self.bot.tree.on_error = self.original_app_error | |
async def send( | |
self, | |
content: str, | |
/, | |
context: commands.Context[commands.Bot] | discord.Interaction[commands.Bot], | |
ephemeral: bool = True | |
) -> None: | |
"""Simple generic method for sending a response. | |
This method catches and logs discord.HTTPExceptions. | |
Parameters | |
---------- | |
content: str | |
The content to send in the response. | |
context: commands.Context | discord.Interaction | |
The context or interaction surrounding the command or app command. | |
ephemeral: bool | |
Optional bool indicating whether the repsonse should attempted to be sent ephemerally. Defaults to True. | |
""" | |
if isinstance(context, commands.Context): | |
send = context.send | |
else: | |
send = context.response.send_message if not context.response.is_done() else context.followup.send | |
try: | |
await send(content=content, ephemeral=ephemeral) | |
except discord.HTTPException as e: | |
msg = f'Ignoring HTTPException in %r for %r: %s\n\n' | |
LOGGER.error(msg, self.send.__name__, self.__class__.__name__, e, exc_info=e) | |
async def on_command_error(self, ctx: commands.Context[commands.Bot], error: commands.CommandError) -> None: | |
"""Prefix command error handler.""" | |
# Don't continue if we have a command specific handler... | |
if ctx.command and ctx.command.has_error_handler(): | |
return | |
# Don't continue if we have a Cog error handler... | |
elif ctx.cog and ctx.cog.has_error_handler(): | |
return | |
error = getattr(error, 'original', error) | |
ignored = (commands.CommandNotFound, commands.NotOwner) | |
# Don't continue if the error is in ignored... | |
if isinstance(error, ignored): | |
return | |
# Example of handling some command errors... | |
# If we don't handle the Exception we log it to console... | |
elif isinstance(error, commands.NoPrivateMessage): | |
await self.send("This command can not be used in Private Messages.", context=ctx) | |
elif isinstance(error, commands.DisabledCommand): | |
await self.send("This command has been disabled by the owner.", context=ctx) | |
else: | |
LOGGER.error("Ignoring exception in command %s", ctx.command, exc_info=error) | |
async def on_app_command_error( | |
self, | |
interaction: discord.Interaction[commands.Bot], | |
error: app_commands.AppCommandError, | |
) -> None: | |
"""AppCommand error handler.""" | |
command = interaction.command | |
# Default logging if the AppCommand is None... | |
if command is None: | |
LOGGER.error("Ignoring exception in command tree", exc_info=error) | |
return | |
# Don't continue if we have a command specific handler... | |
if command.on_error: | |
return | |
# Example of responding to an error... | |
if isinstance(error, app_commands.CommandOnCooldown): | |
retry_after = error.cooldown.get_retry_after() | |
await self.send(f"This command is on cooldown. Try again in {retry_after:.2f} seconds...", context=interaction) | |
else: | |
# Respond to all unhandled errors as an example... Could be removed to show the default response from Discord. | |
# All unhandled errors are also logged to console... | |
await self.send(f"**This application received an unhandled exception:**\n\n{error}", context=interaction) | |
LOGGER.error('Ignoring exception in command %r', command.name, exc_info=error) | |
async def setup(bot: commands.Bot) -> None: | |
await bot.add_cog(CommandErrors(bot)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import discord | |
from discord import app_commands | |
from discord.ext import commands | |
LOGGER: logging.Logger = logging.getLogger(__name__) | |
class CommandErrors(commands.Cog): | |
def __init__(self, bot: commands.Bot) -> None: | |
self.original_command_error = bot.on_command_error | |
self.original_app_error = bot.tree.on_error | |
bot.on_command_error = self.on_command_error | |
bot.tree.on_error = self.on_app_command_error | |
self.bot = bot | |
async def cog_unload(self) -> None: | |
"""Load the original error handlers back into the bot when this Cog unloads.""" | |
self.bot.on_command_error = self.original_command_error | |
self.bot.tree.on_error = self.original_app_error | |
async def send( | |
self, | |
content: str, | |
/, | |
context: commands.Context[commands.Bot] | discord.Interaction[commands.Bot], | |
ephemeral: bool = True | |
) -> None: | |
"""Simple generic method for sending a response. | |
Parameters | |
---------- | |
content: str | |
The content to send in the response. | |
context: commands.Context | discord.Interaction | |
The context or interaction surrounding the command or app command. | |
ephemeral: bool | |
Optional bool indicating whether the repsonse should attempted to be sent ephemerally. Defaults to True. | |
""" | |
if isinstance(context, commands.Context): | |
send = context.send | |
else: | |
send = context.response.send_message if not context.response.is_done() else context.followup.send | |
try: | |
await send(content=content, ephemeral=ephemeral) | |
except discord.HTTPException as e: | |
msg = f'Ignoring HTTPException in %r for %r: %s\n\n' | |
LOGGER.error(msg, self.send.__name__, self.__class__.__name__, e, exc_info=e) | |
async def on_command_error(self, ctx: commands.Context[commands.Bot], error: commands.CommandError) -> None: | |
"""Prefix command error handler.""" | |
if ctx.command and ctx.command.has_error_handler(): | |
return | |
elif ctx.cog and ctx.cog.has_error_handler(): | |
return | |
error = getattr(error, 'original', error) | |
ignored = (commands.CommandNotFound, commands.NotOwner) | |
if isinstance(error, ignored): | |
return | |
elif isinstance(error, commands.NoPrivateMessage): | |
await self.send("This command can not be used in Private Messages.", context=ctx) | |
elif isinstance(error, commands.DisabledCommand): | |
await self.send("This command has been disabled by the owner.", context=ctx) | |
else: | |
LOGGER.error("Ignoring exception in command %s", ctx.command, exc_info=error) | |
async def on_app_command_error( | |
self, | |
interaction: discord.Interaction[commands.Bot], | |
error: app_commands.AppCommandError, | |
) -> None: | |
"""AppCommand error handler.""" | |
command = interaction.command | |
if command is None: | |
LOGGER.error("Ignoring exception in command tree", exc_info=error) | |
return | |
if command.on_error: | |
return | |
if isinstance(error, app_commands.CommandOnCooldown): | |
retry_after = error.cooldown.get_retry_after() | |
await self.send(f"This command is on cooldown. Try again in {retry_after:.2f} seconds...", context=interaction) | |
else: | |
await self.send(f"**This application received an unhandled exception:**\n\n{error}", context=interaction) | |
LOGGER.error('Ignoring exception in command %r', command.name, exc_info=error) | |
async def setup(bot: commands.Bot) -> None: | |
await bot.add_cog(CommandErrors(bot)) |
how to use this in my bot
i mean how to import this
@benjamonnguyen You don't have the right permissions to do whatever you're trying to do
how to use this in my bot i mean how to import this
you dont have to import anything to make use of it. just make sure that its in your cogs folder
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Daudd yea, you're right. Fixed my code.