1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
import contextlib
import logging
from discord.ext.commands import (
BadArgument,
BotMissingPermissions,
CommandError,
CommandInvokeError,
CommandNotFound,
NoPrivateMessage,
UserInputError,
)
from discord.ext.commands import Bot, Context
from bot.api import ResponseCodeError
log = logging.getLogger(__name__)
class ErrorHandler:
"""Handles errors emitted from commands."""
def __init__(self, bot: Bot):
self.bot = bot
async def on_command_error(self, ctx: Context, e: CommandError) -> None:
"""Provide command error handling."""
command = ctx.command
parent = None
if command is not None:
parent = command.parent
if parent and command:
help_command = (self.bot.get_command("help"), parent.name, command.name)
elif command:
help_command = (self.bot.get_command("help"), command.name)
else:
help_command = (self.bot.get_command("help"),)
if hasattr(command, "on_error"):
log.debug(f"Command {command} has a local error handler, ignoring.")
return
if isinstance(e, CommandNotFound) and not hasattr(ctx, "invoked_from_error_handler"):
tags_get_command = self.bot.get_command("tags get")
ctx.invoked_from_error_handler = True
# Return to not raise the exception
with contextlib.suppress(ResponseCodeError):
return await ctx.invoke(tags_get_command, tag_name=ctx.invoked_with)
elif isinstance(e, BadArgument):
await ctx.send(f"Bad argument: {e}\n")
await ctx.invoke(*help_command)
elif isinstance(e, UserInputError):
await ctx.send("Something about your input seems off. Check the arguments:")
await ctx.invoke(*help_command)
elif isinstance(e, NoPrivateMessage):
await ctx.send("Sorry, this command can't be used in a private message!")
elif isinstance(e, BotMissingPermissions):
await ctx.send(
f"Sorry, it looks like I don't have the permissions I need to do that.\n\n"
f"Here's what I'm missing: **{e.missing_perms}**"
)
elif isinstance(e, CommandInvokeError):
if isinstance(e.original, ResponseCodeError):
if e.original.response.status == 404:
await ctx.send("There does not seem to be anything matching your query.")
elif e.original.response.status == 400:
content = await e.original.response.json()
log.debug("API gave bad request on command. Response: %r.", content)
await ctx.send("According to the API, your request is malformed.")
elif 500 <= e.original.response.status < 600:
await ctx.send("Sorry, there seems to be an internal issue with the API.")
else:
await ctx.send(
"Got an unexpected status code from the "
f"API (`{e.original.response.code}`)."
)
else:
await ctx.send(
f"Sorry, an unexpected error occurred. Please let us know!\n\n```{e}```"
)
raise e.original
else:
raise e
def setup(bot: Bot) -> None:
"""Error handler cog load."""
bot.add_cog(ErrorHandler(bot))
log.info("Cog loaded: Events")
|