[commands] Add custom exception classes for built-in checks

Added:
* MissingRole
* BotMissingRole
* MissingAnyRole
* BotMissingAnyRole
This commit is contained in:
Vexs
2019-04-10 02:31:55 -05:00
committed by Rapptz
parent 746e20a826
commit bb3ebc0ebc
3 changed files with 241 additions and 47 deletions

View File

@ -1302,6 +1302,15 @@ def has_role(item):
If the message is invoked in a private message context then the check will
return ``False``.
This check raises one of two special exceptions, :exc:`.MissingRole` if the user
is missing a role, or :exc:`.NoPrivateMessage` if it is used in a private message.
Both inherit from :exc:`.CheckFailure`.
.. versionchanged:: 1.1.0
Raise :exc:`.MissingRole` or :exc:`.NoPrivateMessage`
instead of generic :exc:`.CheckFailure`
Parameters
-----------
item: Union[:class:`int`, :class:`str`]
@ -1310,13 +1319,15 @@ def has_role(item):
def predicate(ctx):
if not isinstance(ctx.channel, discord.abc.GuildChannel):
return False
raise NoPrivateMessage()
if isinstance(item, int):
role = discord.utils.get(ctx.author.roles, id=item)
else:
role = discord.utils.get(ctx.author.roles, name=item)
return role is not None
if role is None:
raise MissingRole(item)
return True
return check(predicate)
@ -1327,6 +1338,15 @@ def has_any_role(*items):
Similar to :func:`.has_role`\, the names or IDs passed in must be exact.
This check raises one of two special exceptions, :exc:`.MissingAnyRole` if the user
is missing all roles, or :exc:`.NoPrivateMessage` if it is used in a private message.
Both inherit from :exc:`.CheckFailure`.
.. versionchanged:: 1.1.0
Raise :exc:`.MissingAnyRole` or :exc:`.NoPrivateMessage`
instead of generic :exc:`.CheckFailure`
Parameters
-----------
items: List[Union[:class:`str`, :class:`int`]]
@ -1344,10 +1364,67 @@ def has_any_role(*items):
"""
def predicate(ctx):
if not isinstance(ctx.channel, discord.abc.GuildChannel):
return False
raise NoPrivateMessage()
getter = functools.partial(discord.utils.get, ctx.author.roles)
return any(getter(id=item) is not None if isinstance(item, int) else getter(name=item) is not None for item in items)
if any(getter(id=item) is not None if isinstance(item, int) else getter(name=item) is not None for item in items):
return True
raise MissingAnyRole(items)
return check(predicate)
def bot_has_role(item):
"""Similar to :func:`.has_role` except checks if the bot itself has the
role.
This check raises one of two special exceptions, :exc:`.BotMissingRole` if the bot
is missing the role, or :exc:`.NoPrivateMessage` if it is used in a private message.
Both inherit from :exc:`.CheckFailure`.
.. versionchanged:: 1.1.0
Raise :exc:`.BotMissingRole` or :exc:`.NoPrivateMessage`
instead of generic :exc:`.CheckFailure`
"""
def predicate(ctx):
ch = ctx.channel
if not isinstance(ch, discord.abc.GuildChannel):
raise NoPrivateMessage()
me = ch.guild.me
if isinstance(item, int):
role = discord.utils.get(me.roles, id=item)
else:
role = discord.utils.get(me.roles, name=item)
if role is None:
raise BotMissingRole(item)
return True
return check(predicate)
def bot_has_any_role(*items):
"""Similar to :func:`.has_any_role` except checks if the bot itself has
any of the roles listed.
This check raises one of two special exceptions, :exc:`.BotMissingAnyRole` if the bot
is missing all roles, or :exc:`.NoPrivateMessage` if it is used in a private message.
Both inherit from :exc:`.CheckFailure`.
.. versionchanged:: 1.1.0
Raise :exc:`.BotMissingAnyRole` or :exc:`.NoPrivateMessage`
instead of generic checkfailure
"""
def predicate(ctx):
ch = ctx.channel
if not isinstance(ch, discord.abc.GuildChannel):
raise NoPrivateMessage()
me = ch.guild.me
getter = functools.partial(discord.utils.get, me.roles)
if any(getter(id=item) is not None if isinstance(item, int) else getter(name=item) is not None for item in items):
return True
raise BotMissingAnyRole(items)
return check(predicate)
def has_permissions(**perms):
@ -1389,36 +1466,6 @@ def has_permissions(**perms):
return check(predicate)
def bot_has_role(item):
"""Similar to :func:`.has_role` except checks if the bot itself has the
role.
"""
def predicate(ctx):
ch = ctx.channel
if not isinstance(ch, discord.abc.GuildChannel):
return False
me = ch.guild.me
if isinstance(item, int):
role = discord.utils.get(me.roles, id=item)
else:
role = discord.utils.get(me.roles, name=item)
return role is not None
return check(predicate)
def bot_has_any_role(*items):
"""Similar to :func:`.has_any_role` except checks if the bot itself has
any of the roles listed.
"""
def predicate(ctx):
ch = ctx.channel
if not isinstance(ch, discord.abc.GuildChannel):
return False
me = ch.guild.me
getter = functools.partial(discord.utils.get, me.roles)
return any(getter(id=item) is not None if isinstance(item, int) else getter(name=item) is not None for item in items)
return check(predicate)
def bot_has_permissions(**perms):
"""Similar to :func:`.has_permissions` except checks if the bot itself has
the permissions listed.
@ -1469,7 +1516,7 @@ def guild_only():
def predicate(ctx):
if ctx.guild is None:
raise NoPrivateMessage('This command cannot be used in private messages.')
raise NoPrivateMessage()
return True
return check(predicate)
@ -1492,9 +1539,20 @@ def is_owner():
return check(predicate)
def is_nsfw():
"""A :func:`.check` that checks if the channel is a NSFW channel."""
"""A :func:`.check` that checks if the channel is a NSFW channel.
This check raises a special exception, :exc:`.NSFWChannelRequired`
that is derived from :exc:`.CheckFailure`.
.. versionchanged:: 1.1.0
Raise :exc:`.NSFWChannelRequired instead of generic :exc:`.CheckFailure`.`
"""
def pred(ctx):
return isinstance(ctx.channel, discord.TextChannel) and ctx.channel.is_nsfw()
ch = ctx.channel
if isinstance(ch, discord.TextChannel) and ch.is_nsfw():
return True
raise NSFWChannelRequired(ch)
return check(pred)
def cooldown(rate, per, type=BucketType.default):