Skip to content

Commit 6dde43c

Browse files
committed
Adjust core error handling
1 parent dee45a4 commit 6dde43c

File tree

2 files changed

+50
-22
lines changed

2 files changed

+50
-22
lines changed

commanderbot/core/commander_bot_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
from commanderbot.lib.event_data import EventData
88

99
EventErrorHandler: TypeAlias = Callable[
10-
[Exception, EventData, bool], Coroutine[Any, Any, Any]
10+
[Exception, EventData, bool], Coroutine[Any, Any, Optional[bool]]
1111
]
1212

1313
CommandErrorHandler: TypeAlias = Callable[
14-
[Exception, Context, bool], Coroutine[Any, Any, Any]
14+
[Exception, Context, bool], Coroutine[Any, Any, Optional[bool]]
1515
]
1616

1717

commanderbot/core/error_handling.py

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from discord.ext.commands.errors import (
88
BotMissingPermissions,
99
CheckFailure,
10+
CommandInvokeError,
1011
CommandNotFound,
1112
MissingPermissions,
1213
NoPrivateMessage,
@@ -24,6 +25,12 @@ class ErrorHandling:
2425
event_error_handlers: List[EventErrorHandler] = field(default_factory=list)
2526
command_error_handlers: List[CommandErrorHandler] = field(default_factory=list)
2627

28+
def _get_root_error(self, error: Exception) -> Exception:
29+
if isinstance(error, CommandInvokeError):
30+
return error.original
31+
else:
32+
return error
33+
2734
def add_event_error_handler(self, handler: EventErrorHandler):
2835
self.event_error_handlers.append(handler)
2936

@@ -42,48 +49,68 @@ async def reply(
4249
allowed_mentions=allowed_mentions or AllowedMentions.none(),
4350
)
4451

45-
async def on_event_error(self, error: Exception, event_data: EventData):
46-
# TODO Can we handle certain types of event errors? #enhance
47-
handled = False
52+
async def on_event_error(self, ex: Exception, event_data: EventData):
53+
# Extract the root error.
54+
error = self._get_root_error(ex)
4855

49-
# Re-raise the error so that it can be printed to the console.
50-
try:
51-
raise error
52-
except:
53-
self.log.exception(f"Ignoring exception in event `{event_data.name}`")
56+
# Attempt to handle the error ourselves.
57+
handled = await self.try_handle_event_error(error, event_data)
5458

5559
# Run the error through our registered event error handlers.
5660
for handler in self.event_error_handlers:
5761
try:
58-
await handler(error, event_data, handled)
62+
if result := await handler(error, event_data, handled):
63+
handled = result
5964
except:
6065
# If something went wrong here, print another exception to the console.
6166
self.log.exception("Handler for command errors caused another error:")
6267

63-
async def on_command_error(self, error: Exception, ctx: Context):
64-
# Attempt to handle the error.
65-
handled = await self.try_handle_command_error(ctx, error)
66-
67-
# If it wasn't handled, re-raise so it can be printed to the console, and then
68-
# let the user know something went wrong.
68+
# If it wasn't handled, re-raise so it can be printed to the console.
6969
if not handled:
7070
try:
7171
raise error
7272
except:
7373
self.log.exception(
74-
f"Ignoring exception in cog `{ctx.cog}` from command: {ctx.command}"
74+
f"Ignoring unhandled exception in event `{event_data.name}`"
7575
)
76-
await self.reply(ctx, f"🔥 Something went wrong trying to do that.")
7776

78-
# Run the error through our registered command error handlers.
77+
async def try_handle_event_error(
78+
self, error: Exception, event_data: EventData
79+
) -> bool:
80+
# TODO Can we handle certain types of event errors? #enhance
81+
return False
82+
83+
async def on_command_error(self, ex: Exception, ctx: Context):
84+
# Extract the root error.
85+
error = self._get_root_error(ex)
86+
87+
# Attempt to handle the error ourselves.
88+
handled = await self.try_handle_command_error(error, ctx)
89+
90+
# Pipe the error through our registered command error handlers, regardless of
91+
# whether the error was handled. Handlers can decide on their own whether to do
92+
# anything with errors that have already been handled.
7993
for handler in self.command_error_handlers:
8094
try:
81-
await handler(error, ctx, handled)
95+
if result := await handler(error, ctx, handled):
96+
handled = result
8297
except:
8398
# If something went wrong here, print another exception to the console.
8499
self.log.exception("Handler for command errors caused another error:")
85100

86-
async def try_handle_command_error(self, ctx: Context, error: Exception) -> bool:
101+
# If it wasn't handled, re-raise so it can be printed to the console, and then
102+
# let the user know something went wrong.
103+
if not handled:
104+
try:
105+
raise error
106+
except:
107+
cog_name = ctx.cog.__cog_name__ if ctx.cog else None
108+
self.log.exception(
109+
f"Ignoring unhandled exception in cog `{cog_name}` from command: `{ctx.command}`"
110+
)
111+
await self.reply(ctx, f"🔥 Something went wrong trying to do that.")
112+
113+
async def try_handle_command_error(self, error: Exception, ctx: Context) -> bool:
87114
if isinstance(error, CommandNotFound):
88115
return True
89116
elif isinstance(error, UserInputError):
@@ -105,4 +132,5 @@ async def try_handle_command_error(self, ctx: Context, error: Exception) -> bool
105132
elif isinstance(error, ResponsiveException):
106133
await error.respond(ctx)
107134
return True
135+
108136
return False

0 commit comments

Comments
 (0)