From 25588955e4e3bee9f9bbe8efaf8ade1b29a1de5a Mon Sep 17 00:00:00 2001 From: Rapptz Date: Thu, 7 Jan 2016 17:59:26 -0500 Subject: [PATCH] [commands] Add a way to enable or disable certain commands. --- discord/ext/commands/core.py | 39 ++++++++++++++++++++++++++++------ discord/ext/commands/errors.py | 7 +++++- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index 06c64b1bd..b86211dee 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -66,6 +66,11 @@ class Command: pass_context : bool A boolean that indicates that the current :class:`Context` should be passed as the **first parameter**. Defaults to `False`. + enabled : bool + A boolean that indicates if the command is currently enabled. + If the command is invoked while it is disabled, then + :exc:`DisabledCommand` is raised to the :func:`on_command_error` + event. Defaults to ``True``. checks A list of predicates that verifies if the command could be executed with the given :class:`Context` as the sole parameter. If an exception @@ -77,6 +82,7 @@ class Command: def __init__(self, name, callback, **kwargs): self.name = name self.callback = callback + self.enabled = kwargs.get('enabled', True) self.help = kwargs.get('help') self.brief = kwargs.get('brief') self.aliases = kwargs.get('aliases', []) @@ -206,15 +212,18 @@ class Command: return True def _verify_checks(self, ctx): - predicates = self.checks - if predicates: - try: + try: + if not self.enabled: + raise DisabledCommand('{0.name} command is disabled'.format(self)) + + predicates = self.checks + if predicates: check = all(predicate(ctx) for predicate in predicates) if not check: raise CheckFailure('The check functions for command {0.name} failed.'.format(self)) - except CommandError as exc: - ctx.bot.dispatch('command_error', exc, ctx) - return False + except CommandError as exc: + ctx.bot.dispatch('command_error', exc, ctx) + return False return True @@ -291,6 +300,24 @@ class GroupMixin: """ return self.commands.pop(name, None) + def get_command(self, name): + """Get a :class:`Command` or subclasses from the internal list + of commands. + + This could also be used as a way to get aliases. + + Parameters + ----------- + name : str + The name of the command to get. + + Returns + -------- + Command or subclass + The command that was requested. If not found, returns ``None``. + """ + return self.commands.get(name, None) + def command(self, *args, **kwargs): """A shortcut decorator that invokes :func:`command` and adds it to the internal command list via :meth:`add_command`. diff --git a/discord/ext/commands/errors.py b/discord/ext/commands/errors.py index 9ffb6bd41..08545ade0 100644 --- a/discord/ext/commands/errors.py +++ b/discord/ext/commands/errors.py @@ -27,7 +27,8 @@ from discord.errors import DiscordException __all__ = [ 'CommandError', 'MissingRequiredArgument', 'BadArgument', - 'NoPrivateMessage', 'CheckFailure', 'CommandNotFound' ] + 'NoPrivateMessage', 'CheckFailure', 'CommandNotFound', + 'DisabledCommand' ] class CommandError(DiscordException): """The base exception type for all command related errors. @@ -69,3 +70,7 @@ class NoPrivateMessage(CommandError): class CheckFailure(CommandError): """Exception raised when the predicates in :attr:`Command.checks` have failed.""" pass + +class DisabledCommand(CommandError): + """Exception raised when the command being invoked is disabled.""" + pass