-
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.
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)) |
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)) |
Hey, another example to prevent for the use of on_command_error occurring when __error defined in cogs, use
Since this is probably a niche thing, and slightly confusing to those who are not familiar with name mangling, I will keep it from the actual examples. Though should someone want to add that to the global handler...
if hasattr(ctx.cog, f'_{ctx.cog.__class__.__name__}__error'):
... # Do whatever...
Would be a much simpler way of doing this.
The MissingRequiredArgument if statements need to be updated, I'm not sure what changed, whether it was the shift to rewrite or some update of the inspect lib but error.param is a inspect.Parameter object and therefore will always return false in rewrite when compared to a string.
if error.param == 'inp':
has to be replaced by
if error.param.name == 'inp':
Grammar error on L41.
Since 02/23/2019 this Error Handler doesn't work due the cog changes.
So I suggest you to updating:
@commands.Cog.listener()
async def on_command_error(self, ctx, error):
class CommandErrorHandler(commands.Cog):
It's an easter egg!
What is this licensed under?
Grammar error on L41.
That's try:
The printing default traceback thing doesn't work
The printing default traceback thing doesn't work
Yeah doesn't work me either
@hello.error
async def hello_error(self, ctx, error):
is it the right way of having arguments
mine not working
mine not working
are you gonna give an error? or say what it is doing? or show your source so people can see what you messed up?
could this possibly be updated because command.has_error_handler and cog.has_error_handler exists?
Using these, we can just put this in the main on_command_error():
if ctx.command.has_error_handler() or ctx.cog.has_error_handler():
return
Using these, we can just put this in the main on_command_error():
if ctx.command.has_error_handler or ctx.cog.has_error_handler: return
Isn't it should be has_error_handler()?
Does anyone know how to handle this error?
'Forbidden: 403 Forbidden (error code: 50001): Missing Access'
@Daudd yea, you're right. Fixed my code.
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
Hey, another example to prevent for the use of
on_command_error
occurring when__error
defined in cogs, useAlso maybe include
__error
for in cogs.