aboutsummaryrefslogtreecommitdiff
path: root/discord/ext/commands/bot.py
diff options
context:
space:
mode:
authorRapptz <[email protected]>2017-01-27 18:53:21 -0500
committerRapptz <[email protected]>2017-01-27 18:53:21 -0500
commit1c49374210b3f22eb044fd4b19ae9ae82bf4a45a (patch)
treec95f03232ce8a3cb9fc7d5cc1147838d19429b68 /discord/ext/commands/bot.py
parent[commands] Add Context.command_failed attribute. (diff)
downloaddiscord.py-1c49374210b3f22eb044fd4b19ae9ae82bf4a45a.tar.xz
discord.py-1c49374210b3f22eb044fd4b19ae9ae82bf4a45a.zip
[commands] Implement before and after invoke command hooks.
Fixes #464.
Diffstat (limited to 'discord/ext/commands/bot.py')
-rw-r--r--discord/ext/commands/bot.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/discord/ext/commands/bot.py b/discord/ext/commands/bot.py
index 1913a319..d080d64a 100644
--- a/discord/ext/commands/bot.py
+++ b/discord/ext/commands/bot.py
@@ -136,6 +136,8 @@ class BotBase(GroupMixin):
self.cogs = {}
self.extensions = {}
self._checks = []
+ self._before_invoke = None
+ self._after_invoke = None
self.description = inspect.cleandoc(description) if description else ''
self.pm_help = pm_help
self.command_not_found = options.pop('command_not_found', 'No command called "{}" found.')
@@ -269,6 +271,71 @@ class BotBase(GroupMixin):
def can_run(self, ctx):
return all(f(ctx) for f in self._checks)
+ def before_invoke(self, coro):
+ """A decorator that registers a coroutine as a pre-invoke hook.
+
+ A pre-invoke hook is called directly before the command is
+ called. This makes it a useful function to set up database
+ connections or any type of set up required.
+
+ This pre-invoke hook takes a sole parameter, a :class:`Context`.
+
+ .. note::
+
+ The :meth:`before_invoke` and :meth:`after_invoke` hooks are
+ only called if all checks and argument parsing procedures pass
+ without error. If any check or argument parsing procedures fail
+ then the hooks are not called.
+
+ Parameters
+ -----------
+ coro
+ The coroutine to register as the pre-invoke hook.
+
+ Raises
+ -------
+ discord.ClientException
+ The coroutine is not actually a coroutine.
+ """
+ if not asyncio.iscoroutinefunction(coro):
+ raise discord.ClientException('The error handler must be a coroutine.')
+
+ self._before_invoke = coro
+ return coro
+
+ def after_invoke(self, coro):
+ """A decorator that registers a coroutine as a post-invoke hook.
+
+ A post-invoke hook is called directly after the command is
+ called. This makes it a useful function to clean-up database
+ connections or any type of clean up required.
+
+ This post-invoke hook takes a sole parameter, a :class:`Context`.
+
+ .. note::
+
+ Similar to :meth:`before_invoke`\, this is not called unless
+ checks and argument parsing procedures succeed. This hook is,
+ however, **always** called regardless of the internal command
+ callback raising an error (i.e. :exc:`CommandInvokeError`\).
+ This makes it ideal for clean-up scenarios.
+
+ Parameters
+ -----------
+ coro
+ The coroutine to register as the post-invoke hook.
+
+ Raises
+ -------
+ discord.ClientException
+ The coroutine is not actually a coroutine.
+ """
+ if not asyncio.iscoroutinefunction(coro):
+ raise discord.ClientException('The error handler must be a coroutine.')
+
+ self._after_invoke = coro
+ return coro
+
# listener registration
def add_listener(self, func, name=None):