mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-07-03 00:30:01 +00:00
[commands] Add support for NSFW commands for hybrid commands
This commit is contained in:
parent
573b2121b7
commit
06c43d6772
@ -119,6 +119,11 @@ class CogMeta(type):
|
|||||||
The group description of a cog. This is only applicable for :class:`GroupCog` instances.
|
The group description of a cog. This is only applicable for :class:`GroupCog` instances.
|
||||||
By default, it's the same value as :attr:`description`.
|
By default, it's the same value as :attr:`description`.
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
group_nsfw: :class:`bool`
|
||||||
|
Whether the application command group is NSFW. This is only applicable for :class:`GroupCog` instances.
|
||||||
|
By default, it's ``False``.
|
||||||
|
|
||||||
.. versionadded:: 2.0
|
.. versionadded:: 2.0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -126,6 +131,7 @@ class CogMeta(type):
|
|||||||
__cog_description__: str
|
__cog_description__: str
|
||||||
__cog_group_name__: str
|
__cog_group_name__: str
|
||||||
__cog_group_description__: str
|
__cog_group_description__: str
|
||||||
|
__cog_group_nsfw__: bool
|
||||||
__cog_settings__: Dict[str, Any]
|
__cog_settings__: Dict[str, Any]
|
||||||
__cog_commands__: List[Command[Any, ..., Any]]
|
__cog_commands__: List[Command[Any, ..., Any]]
|
||||||
__cog_app_commands__: List[Union[app_commands.Group, app_commands.Command[Any, ..., Any]]]
|
__cog_app_commands__: List[Union[app_commands.Group, app_commands.Command[Any, ..., Any]]]
|
||||||
@ -154,6 +160,7 @@ class CogMeta(type):
|
|||||||
attrs['__cog_settings__'] = kwargs.pop('command_attrs', {})
|
attrs['__cog_settings__'] = kwargs.pop('command_attrs', {})
|
||||||
attrs['__cog_name__'] = cog_name
|
attrs['__cog_name__'] = cog_name
|
||||||
attrs['__cog_group_name__'] = group_name
|
attrs['__cog_group_name__'] = group_name
|
||||||
|
attrs['__cog_group_nsfw__'] = kwargs.pop('group_nsfw', False)
|
||||||
|
|
||||||
description = kwargs.pop('description', None)
|
description = kwargs.pop('description', None)
|
||||||
if description is None:
|
if description is None:
|
||||||
@ -268,6 +275,7 @@ class Cog(metaclass=CogMeta):
|
|||||||
group = app_commands.Group(
|
group = app_commands.Group(
|
||||||
name=cls.__cog_group_name__,
|
name=cls.__cog_group_name__,
|
||||||
description=cls.__cog_group_description__,
|
description=cls.__cog_group_description__,
|
||||||
|
nsfw=cls.__cog_group_nsfw__,
|
||||||
parent=None,
|
parent=None,
|
||||||
guild_ids=getattr(cls, '__discord_app_commands_default_guilds__', None),
|
guild_ids=getattr(cls, '__discord_app_commands_default_guilds__', None),
|
||||||
guild_only=getattr(cls, '__discord_app_commands_guild_only__', False),
|
guild_only=getattr(cls, '__discord_app_commands_guild_only__', False),
|
||||||
|
@ -2282,7 +2282,9 @@ def guild_only() -> Check[Any]:
|
|||||||
that is inherited from :exc:`.CheckFailure`.
|
that is inherited from :exc:`.CheckFailure`.
|
||||||
|
|
||||||
If used on hybrid commands, this will be equivalent to the
|
If used on hybrid commands, this will be equivalent to the
|
||||||
:func:`discord.app_commands.guild_only` decorator.
|
:func:`discord.app_commands.guild_only` decorator. In an unsupported
|
||||||
|
context, such as a subcommand, this will still fallback to applying the
|
||||||
|
check.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Due to implementation quirks, this check has to be re-implemented completely
|
# Due to implementation quirks, this check has to be re-implemented completely
|
||||||
@ -2346,13 +2348,21 @@ def is_nsfw() -> Check[Any]:
|
|||||||
This check raises a special exception, :exc:`.NSFWChannelRequired`
|
This check raises a special exception, :exc:`.NSFWChannelRequired`
|
||||||
that is derived from :exc:`.CheckFailure`.
|
that is derived from :exc:`.CheckFailure`.
|
||||||
|
|
||||||
|
If used on hybrid commands, this will be equivalent to setting the
|
||||||
|
application command's ``nsfw`` attribute to ``True``. In an unsupported
|
||||||
|
context, such as a subcommand, this will still fallback to applying the
|
||||||
|
check.
|
||||||
|
|
||||||
.. versionchanged:: 1.1
|
.. versionchanged:: 1.1
|
||||||
|
|
||||||
Raise :exc:`.NSFWChannelRequired` instead of generic :exc:`.CheckFailure`.
|
Raise :exc:`.NSFWChannelRequired` instead of generic :exc:`.CheckFailure`.
|
||||||
DM channels will also now pass this check.
|
DM channels will also now pass this check.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def pred(ctx: Context[BotT]) -> bool:
|
# Due to implementation quirks, this check has to be re-implemented completely
|
||||||
|
# to work with both app_commands and the command framework.
|
||||||
|
|
||||||
|
def predicate(ctx: Context[BotT]) -> bool:
|
||||||
ch = ctx.channel
|
ch = ctx.channel
|
||||||
if ctx.guild is None or (
|
if ctx.guild is None or (
|
||||||
isinstance(ch, (discord.TextChannel, discord.Thread, discord.VoiceChannel)) and ch.is_nsfw()
|
isinstance(ch, (discord.TextChannel, discord.Thread, discord.VoiceChannel)) and ch.is_nsfw()
|
||||||
@ -2360,7 +2370,33 @@ def is_nsfw() -> Check[Any]:
|
|||||||
return True
|
return True
|
||||||
raise NSFWChannelRequired(ch) # type: ignore
|
raise NSFWChannelRequired(ch) # type: ignore
|
||||||
|
|
||||||
return check(pred)
|
def decorator(func: Union[Command, CoroFunc]) -> Union[Command, CoroFunc]:
|
||||||
|
if isinstance(func, Command):
|
||||||
|
func.checks.append(predicate)
|
||||||
|
if hasattr(func, '__commands_is_hybrid__'):
|
||||||
|
app_command = getattr(func, 'app_command', None)
|
||||||
|
if app_command:
|
||||||
|
app_command.nsfw = True
|
||||||
|
else:
|
||||||
|
if not hasattr(func, '__commands_checks__'):
|
||||||
|
func.__commands_checks__ = []
|
||||||
|
|
||||||
|
func.__commands_checks__.append(predicate)
|
||||||
|
func.__discord_app_commands_is_nsfw__ = True
|
||||||
|
|
||||||
|
return func
|
||||||
|
|
||||||
|
if inspect.iscoroutinefunction(predicate):
|
||||||
|
decorator.predicate = predicate
|
||||||
|
else:
|
||||||
|
|
||||||
|
@functools.wraps(predicate)
|
||||||
|
async def wrapper(ctx: Context[BotT]):
|
||||||
|
return predicate(ctx)
|
||||||
|
|
||||||
|
decorator.predicate = wrapper
|
||||||
|
|
||||||
|
return decorator # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def cooldown(
|
def cooldown(
|
||||||
|
@ -290,12 +290,13 @@ class HybridAppCommand(discord.app_commands.Command[CogT, P, T]):
|
|||||||
signature = inspect.signature(wrapped.callback)
|
signature = inspect.signature(wrapped.callback)
|
||||||
params = replace_parameters(wrapped.params, wrapped.callback, signature)
|
params = replace_parameters(wrapped.params, wrapped.callback, signature)
|
||||||
wrapped.callback.__signature__ = signature.replace(parameters=params)
|
wrapped.callback.__signature__ = signature.replace(parameters=params)
|
||||||
|
nsfw = getattr(wrapped.callback, '__discord_app_commands_is_nsfw__', False)
|
||||||
try:
|
try:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
name=wrapped.name,
|
name=wrapped.name,
|
||||||
callback=wrapped.callback, # type: ignore # Signature doesn't match but we're overriding the invoke
|
callback=wrapped.callback, # type: ignore # Signature doesn't match but we're overriding the invoke
|
||||||
description=wrapped.description or wrapped.short_doc or '…',
|
description=wrapped.description or wrapped.short_doc or '…',
|
||||||
|
nsfw=nsfw,
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
del wrapped.callback.__signature__
|
del wrapped.callback.__signature__
|
||||||
@ -595,12 +596,14 @@ class HybridGroup(Group[CogT, P, T]):
|
|||||||
)
|
)
|
||||||
guild_only = getattr(self.callback, '__discord_app_commands_guild_only__', False)
|
guild_only = getattr(self.callback, '__discord_app_commands_guild_only__', False)
|
||||||
default_permissions = getattr(self.callback, '__discord_app_commands_default_permissions__', None)
|
default_permissions = getattr(self.callback, '__discord_app_commands_default_permissions__', None)
|
||||||
|
nsfw = getattr(self.callback, '__discord_app_commands_is_nsfw__', False)
|
||||||
self.app_command = app_commands.Group(
|
self.app_command = app_commands.Group(
|
||||||
name=self.name,
|
name=self.name,
|
||||||
description=self.description or self.short_doc or '…',
|
description=self.description or self.short_doc or '…',
|
||||||
guild_ids=guild_ids,
|
guild_ids=guild_ids,
|
||||||
guild_only=guild_only,
|
guild_only=guild_only,
|
||||||
default_permissions=default_permissions,
|
default_permissions=default_permissions,
|
||||||
|
nsfw=nsfw,
|
||||||
)
|
)
|
||||||
|
|
||||||
# This prevents the group from re-adding the command at __init__
|
# This prevents the group from re-adding the command at __init__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user