diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 14d1663988..d21f42de20 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - repo: https://github.com/PyCQA/autoflake - rev: v1.6.1 + rev: v1.7.6 hooks: - id: autoflake # args: @@ -15,7 +15,7 @@ repos: # - --remove-duplicate-keys # - --remove-unused-variables - repo: https://github.com/asottile/pyupgrade - rev: v2.38.2 + rev: v3.1.0 hooks: - id: pyupgrade args: [--py38-plus] @@ -24,7 +24,7 @@ repos: hooks: - id: isort - repo: https://github.com/psf/black - rev: 22.8.0 + rev: 22.10.0 hooks: - id: black args: [--safe, --quiet] @@ -73,7 +73,7 @@ repos: # - id: mypy - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.0-alpha.0 + rev: v3.0.0-alpha.2 hooks: - id: prettier args: [--prose-wrap=always, --print-width=88] diff --git a/discord/bot.py b/discord/bot.py index 697a9be144..3bde440f70 100644 --- a/discord/bot.py +++ b/discord/bot.py @@ -179,7 +179,7 @@ def get_application_command( self, name: str, guild_ids: list[int] | None = None, - type: type[ApplicationCommand] = SlashCommand, + type: type[ApplicationCommand] = ApplicationCommand, ) -> ApplicationCommand | None: """Get a :class:`.ApplicationCommand` from the internal list of commands. @@ -189,23 +189,39 @@ def get_application_command( Parameters ---------- name: :class:`str` - The name of the command to get. + The qualified name of the command to get. guild_ids: List[:class:`int`] The guild ids associated to the command to get. type: Type[:class:`.ApplicationCommand`] - The type of the command to get. Defaults to :class:`.SlashCommand`. + The type of the command to get. Defaults to :class:`.ApplicationCommand`. Returns ------- Optional[:class:`.ApplicationCommand`] The command that was requested. If not found, returns ``None``. """ - - for command in self._application_commands.values(): + commands = self._application_commands.values() + for command in commands: if command.name == name and isinstance(command, type): if guild_ids is not None and command.guild_ids != guild_ids: return return command + elif (names := name.split())[0] == command.name and isinstance( + command, SlashCommandGroup + ): + while len(names) > 1: + command = get(commands, name=names.pop(0)) + if not isinstance(command, SlashCommandGroup) or ( + guild_ids is not None and command.guild_ids != guild_ids + ): + return + commands = command.subcommands + command = get(commands, name=names.pop()) + if not isinstance(command, type) or ( + guild_ids is not None and command.guild_ids != guild_ids + ): + return + return command async def get_desynced_commands( self, @@ -645,7 +661,15 @@ async def sync_commands( register all commands. By default, this coroutine is called inside the :func:`.on_connect` event. If you choose to override the - :func:`.on_connect` event, then you should invoke this coroutine as well. + :func:`.on_connect` event, then you should invoke this coroutine as well such as the follwing: + + .. code-block:: python + + @bot.event + async def on_connect(): + if bot.auto_sync_commands: + await bot.sync_commands() + print(f"{bot.user.name} connected.") .. note:: If you remove all guild commands from a particular guild, the library may not be able to detect and update @@ -1500,7 +1524,7 @@ class Bot(BotBase, Client): .. versionadded:: 2.0 auto_sync_commands: :class:`bool` - Whether to automatically sync slash commands. This will call sync_commands in on_connect, and in + Whether to automatically sync slash commands. This will call :meth:`~.Bot.sync_commands` in :func:`discord.on_connect`, and in :attr:`.process_application_commands` if the command is not found. Defaults to ``True``. .. versionadded:: 2.0 diff --git a/discord/ext/bridge/core.py b/discord/ext/bridge/core.py index 8063a14cc1..2f90888301 100644 --- a/discord/ext/bridge/core.py +++ b/discord/ext/bridge/core.py @@ -99,6 +99,8 @@ class BridgeSlashGroup(SlashCommandGroup): __slots__ = ("module",) def __init__(self, callback, *args, **kwargs): + if perms := getattr(callback, "__default_member_permissions__", None): + kwargs["default_member_permissions"] = perms super().__init__(*args, **kwargs) self.callback = callback self.__original_kwargs__["callback"] = callback @@ -453,13 +455,13 @@ def predicate(func: Callable | ApplicationCommand): from ..commands import has_permissions func = has_permissions(**perms)(func) - Permissions(**perms) + _perms = Permissions(**perms) if isinstance(func, ApplicationCommand): - func.default_member_permissions = perms + func.default_member_permissions = _perms else: - func.__default_member_permissions__ = perms + func.__default_member_permissions__ = _perms - return perms + return func return predicate diff --git a/discord/interactions.py b/discord/interactions.py index c772190812..9b7291faa5 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -325,7 +325,7 @@ async def original_response(self) -> InteractionMessage: self._original_response = message return message - @utils.deprecated("Interaction.original_response", "2.1") + @utils.deprecated("Interaction.original_response", "2.2") async def original_message(self): """An alias for :meth:`original_response`. @@ -341,7 +341,7 @@ async def original_message(self): ClientException The channel for the message could not be resolved. """ - return self.original_response() + return await self.original_response() async def edit_original_response( self, @@ -447,7 +447,7 @@ async def edit_original_response( return message - @utils.deprecated("Interaction.edit_original_response", "2.1") + @utils.deprecated("Interaction.edit_original_response", "2.2") async def edit_original_message(self, **kwargs): """An alias for :meth:`edit_original_response`. @@ -467,7 +467,7 @@ async def edit_original_message(self, **kwargs): ValueError The length of ``embeds`` was invalid. """ - return self.edit_original_response(**kwargs) + return await self.edit_original_response(**kwargs) async def delete_original_response(self, *, delay: float | None = None) -> None: """|coro| @@ -505,7 +505,7 @@ async def delete_original_response(self, *, delay: float | None = None) -> None: else: await func - @utils.deprecated("Interaction.delete_original_response", "2.1") + @utils.deprecated("Interaction.delete_original_response", "2.2") async def delete_original_message(self, **kwargs): """An alias for :meth:`delete_original_response`. @@ -516,7 +516,7 @@ async def delete_original_message(self, **kwargs): Forbidden Deleted a message that is not yours. """ - return self.delete_original_response(**kwargs) + return await self.delete_original_response(**kwargs) def to_dict(self) -> dict[str, Any]: """ diff --git a/docs/api.rst b/docs/api.rst index 8c390adcaf..6da8fd479a 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -572,6 +572,11 @@ Connection The warnings on :func:`on_ready` also apply. + .. warning:: + + Overriding this event will not call :meth:`Bot.sync_commands`. + As a result, :class:`ApplicationCommand` will not be registered. + .. function:: on_shard_connect(shard_id) Similar to :func:`on_connect` except used by :class:`AutoShardedClient`