aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--discord/ext/commands/bot.py25
-rw-r--r--discord/ext/commands/core.py20
-rw-r--r--discord/ext/commands/errors.py6
3 files changed, 49 insertions, 2 deletions
diff --git a/discord/ext/commands/bot.py b/discord/ext/commands/bot.py
index 64dd8062..de5821e5 100644
--- a/discord/ext/commands/bot.py
+++ b/discord/ext/commands/bot.py
@@ -140,6 +140,7 @@ class BotBase(GroupMixin):
self._after_invoke = None
self.description = inspect.cleandoc(description) if description else ''
self.pm_help = pm_help
+ self.owner_id = options.get('owner_id')
self.command_not_found = options.pop('command_not_found', 'No command called "{}" found.')
self.command_has_no_subcommands = options.pop('command_has_no_subcommands', 'Command {0.name} has no subcommands.')
@@ -275,6 +276,26 @@ class BotBase(GroupMixin):
return (yield from discord.utils.async_all(f(ctx) for f in self._checks))
+ @asyncio.coroutine
+ def is_owner(self, user):
+ """Checks if a :class:`User` or :class:`Member` is the owner of
+ this bot.
+
+ If an :attr:`owner_id` is not set, it is fetched automatically
+ through the use of :meth:`application_info`.
+
+ Parameters
+ -----------
+ user: :class:`abc.User`
+ The user to check for.
+ """
+
+ if self.owner_id is None:
+ app = yield from self.application_info()
+ self.owner_id = owner_id = app.owner.id
+ return user.id == owner_id
+ return user.id == self.owner_id
+
def before_invoke(self, coro):
"""A decorator that registers a coroutine as a pre-invoke hook.
@@ -815,6 +836,10 @@ class Bot(BotBase, discord.Client):
subcommand but the command does not have any subcommands. Defaults to
``"Command {0.name} has no subcommands."``. The first format argument is the
:class:`Command` attempted to get a subcommand and the second is the name.
+ owner_id: Optional[int]
+ The ID that owns the bot. If this is not set and is then queried via
+ :meth:`is_owner` then it is fetched automatically using
+ :meth:`application_info`.
"""
pass
diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py
index 635294f7..f64e7482 100644
--- a/discord/ext/commands/core.py
+++ b/discord/ext/commands/core.py
@@ -37,7 +37,7 @@ from . import converter as converters
__all__ = [ 'Command', 'Group', 'GroupMixin', 'command', 'group',
'has_role', 'has_permissions', 'has_any_role', 'check',
'bot_has_role', 'bot_has_permissions', 'bot_has_any_role',
- 'cooldown', 'guild_only', ]
+ 'cooldown', 'guild_only', 'is_owner']
def wrap_callback(coro):
@functools.wraps(coro)
@@ -1104,6 +1104,24 @@ def guild_only():
return check(predicate)
+def is_owner():
+ """A :func:`check` that checks if the person invoking this command is the
+ owner of the bot.
+
+ This is powered by :meth:`Bot.is_owner`.
+
+ This check raises a special exception, :exc:`NotOwner` that is derived
+ from :exc:`CheckFailure`.
+ """
+
+ @asyncio.coroutine
+ def predicate(ctx):
+ if not (yield from ctx.bot.is_owner(ctx.author)):
+ raise NotOwner('You do not own this bot.')
+ return True
+
+ return check(predicate)
+
def cooldown(rate, per, type=BucketType.default):
"""A decorator that adds a cooldown to a :class:`Command`
or its subclasses.
diff --git a/discord/ext/commands/errors.py b/discord/ext/commands/errors.py
index a6ee8cdc..829fb011 100644
--- a/discord/ext/commands/errors.py
+++ b/discord/ext/commands/errors.py
@@ -29,7 +29,7 @@ from discord.errors import DiscordException
__all__ = [ 'CommandError', 'MissingRequiredArgument', 'BadArgument',
'NoPrivateMessage', 'CheckFailure', 'CommandNotFound',
'DisabledCommand', 'CommandInvokeError', 'TooManyArguments',
- 'UserInputError', 'CommandOnCooldown' ]
+ 'UserInputError', 'CommandOnCooldown', 'NotOwner' ]
class CommandError(DiscordException):
"""The base exception type for all command related errors.
@@ -100,6 +100,10 @@ class NoPrivateMessage(CheckFailure):
"""
pass
+class NotOwner(CheckFailure):
+ """Exception raised when the message author is not the owner of the bot."""
+ pass
+
class DisabledCommand(CommandError):
"""Exception raised when the command being invoked is disabled."""
pass