From 14d5b7898657663a10e8f834e13249751980910f Mon Sep 17 00:00:00 2001 From: vi <8530778+shiftinv@users.noreply.github.com> Date: Sat, 28 Dec 2024 18:05:38 +0100 Subject: [PATCH] fix(commands): some caveats related to guild cache in user app interactions (#1262) --- disnake/ext/commands/cooldowns.py | 4 +++- disnake/ext/commands/core.py | 10 ++++++++-- disnake/interactions/application_command.py | 7 +++++++ disnake/interactions/base.py | 7 +++++++ disnake/interactions/message.py | 7 +++++++ disnake/interactions/modal.py | 7 +++++++ 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/disnake/ext/commands/cooldowns.py b/disnake/ext/commands/cooldowns.py index cda127398a..aa364948f2 100644 --- a/disnake/ext/commands/cooldowns.py +++ b/disnake/ext/commands/cooldowns.py @@ -49,7 +49,9 @@ def get_key(self, msg: Message) -> Any: elif self is BucketType.role: # if author is not a Member we are in a private-channel context; returning its id # yields the same result as for a guild with only the @everyone role - return (msg.author.top_role if isinstance(msg.author, Member) else msg.channel).id + return ( + msg.author.top_role if msg.guild and isinstance(msg.author, Member) else msg.channel + ).id def __call__(self, msg: Message) -> Any: return self.get_key(msg) diff --git a/disnake/ext/commands/core.py b/disnake/ext/commands/core.py index eb7d190b0e..f69c367b5f 100644 --- a/disnake/ext/commands/core.py +++ b/disnake/ext/commands/core.py @@ -2426,11 +2426,14 @@ def dm_only() -> Callable[[T], T]: This check raises a special exception, :exc:`.PrivateMessageOnly` that is inherited from :exc:`.CheckFailure`. + .. note:: + For application commands, consider setting the allowed :ref:`contexts ` instead. + .. versionadded:: 1.1 """ def predicate(ctx: AnyContext) -> bool: - if ctx.guild is not None: + if (ctx.guild if isinstance(ctx, Context) else ctx.guild_id) is not None: raise PrivateMessageOnly return True @@ -2444,10 +2447,13 @@ def guild_only() -> Callable[[T], T]: This check raises a special exception, :exc:`.NoPrivateMessage` that is inherited from :exc:`.CheckFailure`. + + .. note:: + For application commands, consider setting the allowed :ref:`contexts ` instead. """ def predicate(ctx: AnyContext) -> bool: - if ctx.guild is None: + if (ctx.guild if isinstance(ctx, Context) else ctx.guild_id) is None: raise NoPrivateMessage return True diff --git a/disnake/interactions/application_command.py b/disnake/interactions/application_command.py index 2148d7df9c..4fb2ee70a3 100644 --- a/disnake/interactions/application_command.py +++ b/disnake/interactions/application_command.py @@ -77,6 +77,13 @@ class ApplicationCommandInteraction(Interaction[ClientT]): author: Union[:class:`User`, :class:`Member`] The user or member that sent the interaction. + + .. note:: + In scenarios where an interaction occurs in a guild but :attr:`.guild` is unavailable, + such as with user-installed applications in guilds, some attributes of :class:`Member`\\s + that depend on the guild/role cache will not work due to an API limitation. + This includes :attr:`~Member.roles`, :attr:`~Member.top_role`, :attr:`~Member.role_icon`, + and :attr:`~Member.guild_permissions`. locale: :class:`Locale` The selected language of the interaction's author. diff --git a/disnake/interactions/base.py b/disnake/interactions/base.py index 92b69a2cac..eb28fec4eb 100644 --- a/disnake/interactions/base.py +++ b/disnake/interactions/base.py @@ -145,6 +145,13 @@ class Interaction(Generic[ClientT]): author: Union[:class:`User`, :class:`Member`] The user or member that sent the interaction. + + .. note:: + In scenarios where an interaction occurs in a guild but :attr:`.guild` is unavailable, + such as with user-installed applications in guilds, some attributes of :class:`Member`\\s + that depend on the guild/role cache will not work due to an API limitation. + This includes :attr:`~Member.roles`, :attr:`~Member.top_role`, :attr:`~Member.role_icon`, + and :attr:`~Member.guild_permissions`. locale: :class:`Locale` The selected language of the interaction's author. diff --git a/disnake/interactions/message.py b/disnake/interactions/message.py index ee1f401f8c..5205bbfe56 100644 --- a/disnake/interactions/message.py +++ b/disnake/interactions/message.py @@ -66,6 +66,13 @@ class MessageInteraction(Interaction[ClientT]): author: Union[:class:`User`, :class:`Member`] The user or member that sent the interaction. + + .. note:: + In scenarios where an interaction occurs in a guild but :attr:`.guild` is unavailable, + such as with user-installed applications in guilds, some attributes of :class:`Member`\\s + that depend on the guild/role cache will not work due to an API limitation. + This includes :attr:`~Member.roles`, :attr:`~Member.top_role`, :attr:`~Member.role_icon`, + and :attr:`~Member.guild_permissions`. locale: :class:`Locale` The selected language of the interaction's author. diff --git a/disnake/interactions/modal.py b/disnake/interactions/modal.py index bc9141e09e..7c661ed3dd 100644 --- a/disnake/interactions/modal.py +++ b/disnake/interactions/modal.py @@ -58,6 +58,13 @@ class ModalInteraction(Interaction[ClientT]): author: Union[:class:`User`, :class:`Member`] The user or member that sent the interaction. + + .. note:: + In scenarios where an interaction occurs in a guild but :attr:`.guild` is unavailable, + such as with user-installed applications in guilds, some attributes of :class:`Member`\\s + that depend on the guild/role cache will not work due to an API limitation. + This includes :attr:`~Member.roles`, :attr:`~Member.top_role`, :attr:`~Member.role_icon`, + and :attr:`~Member.guild_permissions`. locale: :class:`Locale` The selected language of the interaction's author.