mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-04-18 23:15:48 +00:00
[commands] Add support for setting a fallback slash subcommand
This allows the group callback to be invoked as a slash subcommand
This commit is contained in:
parent
e9ff6b4be8
commit
8a1800bd12
@ -202,7 +202,7 @@ def replace_parameters(parameters: Dict[str, Parameter], signature: inspect.Sign
|
||||
|
||||
|
||||
class HybridAppCommand(discord.app_commands.Command[CogT, P, T]):
|
||||
def __init__(self, wrapped: HybridCommand[CogT, Any, T]) -> None:
|
||||
def __init__(self, wrapped: Command[CogT, Any, T]) -> None:
|
||||
signature = inspect.signature(wrapped.callback)
|
||||
params = replace_parameters(wrapped.params, signature)
|
||||
wrapped.callback.__signature__ = signature.replace(parameters=params)
|
||||
@ -216,7 +216,7 @@ class HybridAppCommand(discord.app_commands.Command[CogT, P, T]):
|
||||
finally:
|
||||
del wrapped.callback.__signature__
|
||||
|
||||
self.wrapped: HybridCommand[CogT, Any, T] = wrapped
|
||||
self.wrapped: Command[CogT, Any, T] = wrapped
|
||||
self.binding = wrapped.cog
|
||||
|
||||
def _copy_with(self, **kwargs) -> Self:
|
||||
@ -435,11 +435,19 @@ class HybridGroup(Group[CogT, P, T]):
|
||||
decorator or functional interface.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
fallback: Optional[:class:`str`]
|
||||
The command name to use as a fallback for the application command. Since
|
||||
application command groups cannot be invoked, this creates a subcommand within
|
||||
the group that can be invoked with the given group callback. If ``None``
|
||||
then no fallback command is given. Defaults to ``None``.
|
||||
"""
|
||||
|
||||
__commands_is_hybrid__: ClassVar[bool] = True
|
||||
|
||||
def __init__(self, *args: Any, **attrs: Any) -> None:
|
||||
def __init__(self, *args: Any, fallback: Optional[str] = None, **attrs: Any) -> None:
|
||||
super().__init__(*args, **attrs)
|
||||
self.invoke_without_command = True
|
||||
parent = None
|
||||
@ -458,6 +466,83 @@ class HybridGroup(Group[CogT, P, T]):
|
||||
|
||||
# This prevents the group from re-adding the command at __init__
|
||||
self.app_command.parent = parent
|
||||
self.fallback: Optional[str] = fallback
|
||||
|
||||
if fallback is not None:
|
||||
command = HybridAppCommand(self)
|
||||
command.name = fallback
|
||||
self.app_command.add_command(command)
|
||||
|
||||
@property
|
||||
def _fallback_command(self) -> Optional[HybridAppCommand[CogT, ..., T]]:
|
||||
return self.app_command.get_command(self.fallback) # type: ignore
|
||||
|
||||
@property
|
||||
def cog(self) -> CogT:
|
||||
return self._cog
|
||||
|
||||
@cog.setter
|
||||
def cog(self, value: CogT) -> None:
|
||||
self._cog = value
|
||||
fallback = self._fallback_command
|
||||
if fallback:
|
||||
fallback.binding = value
|
||||
|
||||
async def can_run(self, ctx: Context[BotT], /) -> bool:
|
||||
fallback = self._fallback_command
|
||||
if ctx.interaction is not None and fallback:
|
||||
return await fallback._check_can_run(ctx.interaction)
|
||||
else:
|
||||
return await super().can_run(ctx)
|
||||
|
||||
async def _parse_arguments(self, ctx: Context[BotT]) -> None:
|
||||
interaction = ctx.interaction
|
||||
fallback = self._fallback_command
|
||||
if interaction is not None and fallback:
|
||||
ctx.kwargs = await fallback._transform_arguments(interaction, interaction.namespace)
|
||||
else:
|
||||
return await super()._parse_arguments(ctx)
|
||||
|
||||
def _ensure_assignment_on_copy(self, other: Self) -> Self:
|
||||
copy = super()._ensure_assignment_on_copy(other)
|
||||
copy.fallback = self.fallback
|
||||
return copy
|
||||
|
||||
def autocomplete(
|
||||
self, name: str
|
||||
) -> Callable[[AutocompleteCallback[CogT, ChoiceT]], AutocompleteCallback[CogT, ChoiceT]]:
|
||||
"""A decorator that registers a coroutine as an autocomplete prompt for a parameter.
|
||||
|
||||
This is the same as :meth:`~discord.app_commands.Command.autocomplete`. It is only
|
||||
applicable for the application command and doesn't do anything if the command is
|
||||
a regular command.
|
||||
|
||||
This is only available if the group has a fallback application command registered.
|
||||
|
||||
.. note::
|
||||
|
||||
Similar to the :meth:`~discord.app_commands.Command.autocomplete` method, this
|
||||
takes :class:`~discord.Interaction` as a parameter rather than a :class:`Context`.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
name: :class:`str`
|
||||
The parameter name to register as autocomplete.
|
||||
|
||||
Raises
|
||||
-------
|
||||
TypeError
|
||||
The coroutine passed is not actually a coroutine or
|
||||
the parameter is not found or of an invalid type.
|
||||
"""
|
||||
if self._fallback_command:
|
||||
return self._fallback_command.autocomplete(name)
|
||||
else:
|
||||
|
||||
def decorator(func: AutocompleteCallback[CogT, ChoiceT]) -> AutocompleteCallback[CogT, ChoiceT]:
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
def add_command(self, command: Union[HybridGroup[CogT, ..., Any], HybridCommand[CogT, ..., Any]], /) -> None:
|
||||
"""Adds a :class:`.HybridCommand` into the internal list of commands.
|
||||
|
Loading…
x
Reference in New Issue
Block a user