Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: store invokable application commands properly #1107

Open
wants to merge 35 commits into
base: master
Choose a base branch
from

Conversation

EQUENOS
Copy link
Member

@EQUENOS EQUENOS commented Sep 18, 2023

Summary

Currently, disnake.ext.commands framework doesn't allow registering 2 guild commands with the same type and name in different guilds, even though discord API allows to do that (see issue #260). This PR solves this problem.

Consequences

  • all_xxx_commands attributes of InteractionBotBase are now deprecated in favor of all_app_commands
  • bot.add_xxx_command methods are now deprecated in favor of add_app_command
  • bot.remove_xxx_command methods are now deprecated in favor of remove_app_command
  • bot.get_xxx_command now works in O(1) only if guild_id is specified, otherwise it's O(n) where n = len(all_app_commands)
  • bot.get_xxx_command can be ambiguous if guild_id is not specified
  • argument guild_id of bot._ordered_unsynced_commands is now deprecated

Note

The original idea of allowing to insert IDs of app commands to the corresponding invokable objects had to be abandoned. This is due to complications related to copying.

Checklist

  • If code changes were made, then they have been tested
    • I have updated the documentation to reflect the changes
    • I have formatted the code properly by running pdm lint
    • I have type-checked the code by running pdm pyright
  • This PR fixes an issue
  • This PR adds something new (e.g. new method or parameters)
  • This PR is a breaking change (e.g. methods or parameters removed/renamed)
  • This PR is not a code change (e.g. documentation, README, ...)

@EQUENOS EQUENOS added p: medium Medium priority t: refactor/typing/lint Refactors, typing changes and/or linting changes s: in progress Issue/PR is being worked on labels Sep 18, 2023
@EQUENOS EQUENOS changed the title refactor: Store invokable application commands properly refactor: store invokable application commands properly Sep 18, 2023
@EQUENOS EQUENOS added s: needs review Issue/PR is awaiting reviews t: deprecation Deprecation of existing features t: bugfix and removed s: in progress Issue/PR is being worked on labels Sep 18, 2023
Copy link
Member

@shiftinv shiftinv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a bunch of mostly minor comments, but overall this looks really cool 👀

changelog/260.deprecate.0.rst Show resolved Hide resolved
changelog/260.deprecate.0.rst Outdated Show resolved Hide resolved
disnake/ext/commands/errors.py Show resolved Hide resolved
disnake/ext/commands/errors.py Outdated Show resolved Hide resolved
disnake/ext/commands/interaction_bot_base.py Outdated Show resolved Hide resolved
disnake/ext/commands/interaction_bot_base.py Outdated Show resolved Hide resolved
disnake/ext/commands/interaction_bot_base.py Outdated Show resolved Hide resolved
disnake/ext/commands/interaction_bot_base.py Show resolved Hide resolved
docs/ext/commands/api/exceptions.rst Outdated Show resolved Hide resolved
disnake/interactions/application_command.py Outdated Show resolved Hide resolved
@shiftinv
Copy link
Member

Haven't tested much yet - not sure what exactly happened, but something somewhere ended up trying to register subcommands as top-level commands: https://gist.github.com/shiftinv/eddfcae9ca1f34790ced4a5288e3691f

@EQUENOS
Copy link
Member Author

EQUENOS commented Sep 23, 2023

Haven't tested much yet - not sure what exactly happened, but something somewhere ended up trying to register subcommands as top-level commands: https://gist.github.com/shiftinv/eddfcae9ca1f34790ced4a5288e3691f

Fixed this in 1f10a8d

disnake/ext/commands/interaction_bot_base.py Outdated Show resolved Hide resolved
disnake/ext/commands/interaction_bot_base.py Outdated Show resolved Hide resolved
disnake/ext/commands/__init__.py Outdated Show resolved Hide resolved
)

test_guilds = (None,) if self._test_guilds is None else self._test_guilds
guild_ids = app_command.guild_ids or test_guilds
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a note to the .name and .guild_ids attributes that any changes after adding the command to the bot (e.g. through @bot.slash_command, bot.add_cog, etc.) are not supported and may result in undefined behavior.
I know of one instance where cmd.guild_ids is modified in a cog constructor, but from what I can tell that'll still work fine even after this change, since it runs before add_cog gets called.

Comment on lines 837 to +840
for app_command in self.__cog_app_commands__:
if isinstance(app_command, InvokableSlashCommand):
bot.remove_slash_command(app_command.name)
elif isinstance(app_command, InvokableUserCommand):
bot.remove_user_command(app_command.name)
elif isinstance(app_command, InvokableMessageCommand):
bot.remove_message_command(app_command.name)
bot._remove_app_commands(
app_command.body.type, app_command.name, guild_ids=app_command.guild_ids
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't pose an issue right now, but may need to check for SubCommand(Group) here too.

Comment on lines +177 to +178
guild_id: Optional[:class:`int`]
ID of the guild the command is registered to.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
guild_id: Optional[:class:`int`]
ID of the guild the command is registered to.
guild_id: Optional[:class:`int`]
ID of the guild the command is registered to.
.. versionadded:: 2.10

Comment on lines +366 to +367
# localization may be called multiple times for the same command but it's harmless
app_command.body.localize(self.i18n)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you mentioned in the comment, calling this multiple times is perfectly fine, but could this just be moved out of the loop instead?

Comment on lines +449 to +451
guild_id: Optional[:class:`int`]
The ID of the guild from which this command should be removed,
or ``None`` if it's global.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
guild_id: Optional[:class:`int`]
The ID of the guild from which this command should be removed,
or ``None`` if it's global.
guild_id: Optional[:class:`int`]
The ID of the guild from which this command should be removed,
or ``None`` if it's global. If ``test_guilds`` is specified in the bot constructor,
passing ``None`` here will remove the command from those guilds instead.


def get_slash_command(
self, name: str
self, name: str, guild_id: Optional[int] = MISSING
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nit, same for the two methods below

Suggested change
self, name: str, guild_id: Optional[int] = MISSING
self, name: str, *, guild_id: Optional[int] = MISSING

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p: medium Medium priority s: needs review Issue/PR is awaiting reviews t: bugfix t: deprecation Deprecation of existing features t: refactor/typing/lint Refactors, typing changes and/or linting changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Separate application commands with same name+type but in different guilds don't work
3 participants