Skip to content

Commit

Permalink
feat: also set integration_types if GuildCommandInteraction is used
Browse files Browse the repository at this point in the history
  • Loading branch information
shiftinv committed Nov 27, 2024
1 parent 0ee644d commit 1d949f6
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 13 deletions.
19 changes: 12 additions & 7 deletions disnake/ext/commands/base_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,13 @@ def _update_copy(self: AppCommandT, kwargs: Dict[str, Any]) -> AppCommandT:
return self.copy()

def _apply_guild_only(self) -> None:
# If we have a `GuildCommandInteraction` annotation, set `contexts` accordingly.
# If we have a `GuildCommandInteraction` annotation, set `contexts` and `integration_types` accordingly.
# This matches the old pre-user-apps behavior.
if self._guild_only:
# FIXME(3.0): this should raise if contexts were set elsewhere already
# n.b. this overwrites any user-specified `contexts` parameter,
# which is fine at least as long as no new contexts are added to the API
# n.b. this overwrites any user-specified parameter
# FIXME(3.0): this should raise if these were set elsewhere (except `*_command_attrs`) already
self.body.contexts = InteractionContextTypes(guild=True)
self.body.integration_types = ApplicationIntegrationTypes(guild=True)

@property
def dm_permission(self) -> bool:
Expand Down Expand Up @@ -842,9 +843,13 @@ def decorator(func: T) -> T:
raise TypeError(
"Cannot set `integration_types` on subcommands or subcommand groups"
)
if func.body.integration_types is not None:
raise ValueError("Cannot set `integration_types` in both parameter and decorator")
func.body.integration_types = integration_types
# special case - don't overwrite if `_guild_only` was set, since that takes priority
if not func._guild_only:
if func.body.integration_types is not None:
raise ValueError(
"Cannot set `integration_types` in both parameter and decorator"
)
func.body.integration_types = integration_types
else:
func.__integration_types__ = integration_types # type: ignore
return func
Expand Down
11 changes: 5 additions & 6 deletions disnake/interactions/application_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,13 @@ def filled_options(self) -> Dict[str, Any]:
return kwargs


# TODO(3.0): make these classes @type_check_only and not affect runtime behavior, or even remove entirely
# TODO(3.0): consider making these classes @type_check_only and not affect runtime behavior, or even remove entirely
class GuildCommandInteraction(ApplicationCommandInteraction[ClientT]):
"""An :class:`ApplicationCommandInteraction` subclass, primarily meant for annotations.
This prevents the command from being invoked in DMs by automatically adjusting the
:attr:`~InteractionContextTypes.bot_dm` and :attr:`~InteractionContextTypes.private_channel` flags of
:attr:`ApplicationCommand.contexts` to ``False`` for user/message commands and top-level slash commands.
This restricts the command to only be usable in guilds and only as a guild-installed command,
by automatically setting :attr:`ApplicationCommand.contexts` to :attr:`~InteractionContextTypes.guild` only
and :attr:`ApplicationCommand.integration_types` to :attr:`~ApplicationIntegrationTypes.guild` only.
Note that this does not apply to slash subcommands, subcommand groups, or autocomplete callbacks.
Additionally, annotations of some attributes are modified to match the expected types in guilds.
Expand All @@ -171,7 +170,7 @@ class GuildCommandInteraction(ApplicationCommandInteraction[ClientT]):
guild: Guild
guild_id: int
guild_locale: Locale
me: Member # TODO: this might be inaccurate now
me: Member


class UserCommandInteraction(ApplicationCommandInteraction[ClientT]):
Expand Down
2 changes: 2 additions & 0 deletions tests/ext/commands/test_base_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,15 @@ def test_contexts_guildcommandinteraction(meta: DecoratorMeta) -> None:
class Cog(commands.Cog):
# this shouldn't raise, it should be silently ignored
@commands.contexts(bot_dm=True)
@commands.integration_types(user=True)
# this is a legacy parameter, essentially the same as using `GuildCommandInteraction`
@meta.decorator(guild_only=True)
async def cmd(self, _) -> None:
...

for c in (Cog, Cog()):
assert c.cmd.contexts == disnake.InteractionContextTypes(guild=True)
assert c.cmd.integration_types == disnake.ApplicationIntegrationTypes(guild=True)


def test_localization_copy() -> None:
Expand Down

0 comments on commit 1d949f6

Please sign in to comment.