diff --git a/disnake/ext/commands/base_core.py b/disnake/ext/commands/base_core.py index a7fc6ef32a..22d3f7449d 100644 --- a/disnake/ext/commands/base_core.py +++ b/disnake/ext/commands/base_core.py @@ -255,6 +255,7 @@ def _update_copy(self: AppCommandT, kwargs: Dict[str, Any]) -> AppCommandT: def _apply_guild_only(self) -> None: # If we have a `GuildCommandInteraction` annotation, set `contexts` accordingly. 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 self.body.contexts = InteractionContextTypes(guild=True) diff --git a/disnake/interactions/application_command.py b/disnake/interactions/application_command.py index b2d2fa2794..337e22139f 100644 --- a/disnake/interactions/application_command.py +++ b/disnake/interactions/application_command.py @@ -154,6 +154,7 @@ 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 class GuildCommandInteraction(ApplicationCommandInteraction[ClientT]): """An :class:`ApplicationCommandInteraction` subclass, primarily meant for annotations. diff --git a/disnake/interactions/base.py b/disnake/interactions/base.py index ff459d63f5..c3407b53ec 100644 --- a/disnake/interactions/base.py +++ b/disnake/interactions/base.py @@ -291,15 +291,26 @@ def user(self) -> Union[User, Member]: @property def guild(self) -> Optional[Guild]: - """Optional[:class:`Guild`]: The guild the interaction was sent from.""" + """Optional[:class:`Guild`]: The guild the interaction was sent from. + + .. note:: + In some scenarios, e.g. for user-installed applications, this will usually be + ``None``, despite the interaction originating from a guild. + This will only return a full :class:`Guild` for cached guilds, + i.e. those the bot is already a member of. + + To check whether an interaction was sent from a guild, consider using + :attr:`guild_id` or :attr:`context` instead. + """ return self._state._get_guild(self.guild_id) @utils.cached_slot_property("_cs_me") def me(self) -> Union[Member, ClientUser]: - """Union[:class:`.Member`, :class:`.ClientUser`]: - Similar to :attr:`.Guild.me` except it may return the :class:`.ClientUser` in private message contexts. + """Union[:class:`.Member`, :class:`.ClientUser`]: Similar to :attr:`.Guild.me`, + except it may return the :class:`.ClientUser` in private message contexts or + when the bot is not a member of the guild (e.g. in the case of user-installed applications). """ - # TODO: guild.me will return None once we start using the partial guild from the interaction + # NOTE: guild.me will return None if we start using the partial guild from the interaction return self.guild.me if self.guild is not None else self.client.user @property @@ -649,7 +660,7 @@ async def delete(delay: float) -> None: raise # legacy namings - # these MAY begin a deprecation warning in 2.7 but SHOULD have a deprecation version in 2.8 + # TODO: these should have a deprecation warning before 3.0 original_message = original_response edit_original_message = edit_original_response delete_original_message = delete_original_response