From 173f27cdfe2e265bdd98f3b739ae5f2a7e868b23 Mon Sep 17 00:00:00 2001 From: Developer Anonymous Date: Fri, 4 Oct 2024 16:34:06 +0200 Subject: [PATCH 01/22] Added more InteractionCallback things --- discord/interactions.py | 205 ++++++++++++++++++++++++++++++++-- discord/types/interactions.py | 25 +++++ discord/webhook/async_.py | 19 +++- 3 files changed, 239 insertions(+), 10 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index e0fb7ed8654b..589f3ea76865 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -61,6 +61,8 @@ Interaction as InteractionPayload, InteractionData, ApplicationCommandInteractionData, + InteractionCallbackResponse as InteractionCallbackResponsePayload, + InteractionCallbackActivity as InteractionCallbackActivityPayload, ) from .types.webhook import ( Webhook as WebhookPayload, @@ -466,6 +468,7 @@ async def edit_original_response( attachments: Sequence[Union[Attachment, File]] = MISSING, view: Optional[View] = MISSING, allowed_mentions: Optional[AllowedMentions] = None, + poll: Poll = MISSING, ) -> InteractionMessage: """|coro| @@ -500,6 +503,14 @@ async def edit_original_response( view: Optional[:class:`~discord.ui.View`] The updated view to update this message with. If ``None`` is passed then the view is removed. + poll: :class:`Poll` + The poll to create when editing the message. + + .. versionadded:: 2.5 + + .. note:: + + This is only accepted when the response type is :attr:`InteractionResponseType.deferred_channel_message`. Raises ------- @@ -529,6 +540,7 @@ async def edit_original_response( view=view, allowed_mentions=allowed_mentions, previous_allowed_mentions=previous_mentions, + poll=poll, ) as params: adapter = async_context.get() http = self._state.http @@ -621,6 +633,98 @@ async def translate( return await translator.translate(string, locale=locale, context=context) +class InteractionCallbackActivity: + """Represents an activity instance returned by an interaction callback. + + .. versionadded:: 2.5 + + Attributes + ---------- + id: :class:`str` + The activity instance ID. + """ + + __slots__ = ('id',) + + def __init__(self, *, data: InteractionCallbackActivityPayload) -> None: + self.id: str = data['id'] + + def __repr__(self) -> str: + return f'' + + +class InteractionCallback(Generic[ClientT]): + """Represents a Discord response to an interaction. + + .. versionadded:: 2.5 + """ + + __slots__ = ( + 'id', + '_parent', + '_state', + 'interaction_type', + 'activity_instance_id', + 'activity_instance', + 'response_message_id', + 'response_message_loading', + 'response_message_ephemeral', + 'response_message', + 'response_channel', + 'callback_type', + ) + + def __init__( + self, + *, + parent: Interaction[ClientT], + channel: InteractionChannel, + data: InteractionCallbackResponsePayload, + ) -> None: + self._parent: Interaction[ClientT] = parent + self._state: ConnectionState = parent._state + self.response_channel: InteractionChannel = channel + self._update(data) + + def _update(self, data: InteractionCallbackResponsePayload) -> None: + interaction = data['interaction'] + self.id: int = int(interaction['id']) + self.interaction_type: InteractionType = try_enum(InteractionType, interaction['type']) + self.activity_instance_id: Optional[str] = interaction.get('activity_instance_id') + response_id = interaction.get('response_message_id') + self.response_message_id: Optional[int] = int( + response_id, + ) if response_id is not None else None + self.response_message_loading: Optional[bool] = interaction.get('response_message_loading') + self.response_message_ephemeral: Optional[bool] = interaction.get('response_message_ephemeral') + + resource = data.get('resource', {}) + self.callback_type: Optional[InteractionResponseType] = None + self.activity_instance: Optional[InteractionCallbackActivity] = None + self.response_message: Optional[InteractionMessage] = None + + try: + self.callback_type = try_enum(InteractionResponseType, resource['type']) + except KeyError: + pass + + try: + self.activity_instance = InteractionCallbackActivity( + data=resource['activity_instance'], + ) + except KeyError: + pass + + try: + self.response_message = InteractionMessage( + state=self._state, + channel=self.response_channel, # type: ignore + data=resource['message'], + ) + except KeyError: + pass + + class InteractionResponse(Generic[ClientT]): """Represents a Discord interaction response. @@ -650,7 +754,13 @@ def type(self) -> Optional[InteractionResponseType]: """:class:`InteractionResponseType`: The type of response that was sent, ``None`` if response is not done.""" return self._response_type - async def defer(self, *, ephemeral: bool = False, thinking: bool = False) -> None: + async def defer( + self, + *, + ephemeral: bool = False, + thinking: bool = False, + with_response: bool = True, + ) -> Optional[InteractionCallback]: """|coro| Defers the interaction response. @@ -675,6 +785,10 @@ async def defer(self, *, ephemeral: bool = False, thinking: bool = False) -> Non In UI terms, this is represented as if the bot is thinking of a response. It is your responsibility to eventually send a followup message via :attr:`Interaction.followup` to make this thinking state go away. Application commands (AKA Slash commands) cannot use :attr:`InteractionResponseType.deferred_message_update`. + with_response: :class:`bool` + Whether to return the interaction response callback resource. + + .. versionadded:: 2.5 Raises ------- @@ -682,6 +796,11 @@ async def defer(self, *, ephemeral: bool = False, thinking: bool = False) -> Non Deferring the interaction failed. InteractionResponded This interaction has already been responded to before. + + Returns + ------- + Optional[:class:`InteractionCallback`] + The interaction callback resource, or ``None``. """ if self._response_type: raise InteractionResponded(self._parent) @@ -706,15 +825,22 @@ async def defer(self, *, ephemeral: bool = False, thinking: bool = False) -> Non adapter = async_context.get() params = interaction_response_params(type=defer_type, data=data) http = parent._state.http - await adapter.create_interaction_response( + response = await adapter.create_interaction_response( parent.id, parent.token, session=parent._session, proxy=http.proxy, proxy_auth=http.proxy_auth, params=params, + with_response=with_response, ) self._response_type = InteractionResponseType(defer_type) + if response: + return InteractionCallback( + parent=parent, + channel=parent.channel, # type: ignore + data=response, + ) async def pong(self) -> None: """|coro| @@ -764,7 +890,8 @@ async def send_message( silent: bool = False, delete_after: Optional[float] = None, poll: Poll = MISSING, - ) -> None: + with_response: bool = True, + ) -> Optional[InteractionCallback]: """|coro| Responds to this interaction by sending a message. @@ -811,6 +938,10 @@ async def send_message( The poll to send with this message. .. versionadded:: 2.4 + with_response: :class:`bool` + Whether to return the interaction response callback resource. + + .. versionadded:: 2.5 Raises ------- @@ -822,6 +953,11 @@ async def send_message( The length of ``embeds`` was invalid. InteractionResponded This interaction has already been responded to before. + + Returns + ------- + Optional[:class:`InteractionCallback`] + The interaction callback data, or ``None``. """ if self._response_type: raise InteractionResponded(self._parent) @@ -852,13 +988,14 @@ async def send_message( ) http = parent._state.http - await adapter.create_interaction_response( + response = await adapter.create_interaction_response( parent.id, parent.token, session=parent._session, proxy=http.proxy, proxy_auth=http.proxy_auth, params=params, + with_response=with_response, ) if view is not MISSING and not view.is_finished(): @@ -882,6 +1019,12 @@ async def inner_call(delay: float = delete_after): pass asyncio.create_task(inner_call()) + if response: + return InteractionCallback( + parent=parent, + channel=parent.channel, # type: ignore + data=response, + ) async def edit_message( self, @@ -894,7 +1037,8 @@ async def edit_message( allowed_mentions: Optional[AllowedMentions] = MISSING, delete_after: Optional[float] = None, suppress_embeds: bool = MISSING, - ) -> None: + with_response: bool = True, + ) -> Optional[InteractionCallback]: """|coro| Responds to this interaction by editing the original message of @@ -936,6 +1080,10 @@ async def edit_message( Using this parameter requires :attr:`~.Permissions.manage_messages`. .. versionadded:: 2.4 + with_response: :class:`bool` + Whether to return the interaction response callback resource. + + .. versionadded:: 2.5 Raises ------- @@ -945,6 +1093,11 @@ async def edit_message( You specified both ``embed`` and ``embeds``. InteractionResponded This interaction has already been responded to before. + + Returns + ------- + Optional[:class:`InteractionCallback`] + The interaction callback data, or ``None``. """ if self._response_type: raise InteractionResponded(self._parent) @@ -987,13 +1140,14 @@ async def edit_message( ) http = parent._state.http - await adapter.create_interaction_response( + response = await adapter.create_interaction_response( parent.id, parent.token, session=parent._session, proxy=http.proxy, proxy_auth=http.proxy_auth, params=params, + with_response=with_response, ) if view and not view.is_finished(): @@ -1012,7 +1166,14 @@ async def inner_call(delay: float = delete_after): asyncio.create_task(inner_call()) - async def send_modal(self, modal: Modal, /) -> None: + if response: + return InteractionCallback( + parent=parent, + channel=parent.channel, # type: ignore + data=response, + ) + + async def send_modal(self, modal: Modal, /, *, with_response: bool = True) -> Optional[InteractionCallback]: """|coro| Responds to this interaction by sending a modal. @@ -1021,6 +1182,10 @@ async def send_modal(self, modal: Modal, /) -> None: ----------- modal: :class:`~discord.ui.Modal` The modal to send. + with_response: :class:`bool` + Whether to return the interaction response callback resource. + + .. versionadded:: 2.5 Raises ------- @@ -1028,6 +1193,11 @@ async def send_modal(self, modal: Modal, /) -> None: Sending the modal failed. InteractionResponded This interaction has already been responded to before. + + Returns + ------- + Optional[:class:`InteractionCallback`] + The interaction callback data, or ``None``. """ if self._response_type: raise InteractionResponded(self._parent) @@ -1038,18 +1208,26 @@ async def send_modal(self, modal: Modal, /) -> None: http = parent._state.http params = interaction_response_params(InteractionResponseType.modal.value, modal.to_dict()) - await adapter.create_interaction_response( + response = await adapter.create_interaction_response( parent.id, parent.token, session=parent._session, proxy=http.proxy, proxy_auth=http.proxy_auth, params=params, + with_response=with_response, ) if not modal.is_finished(): self._parent._state.store_view(modal) self._response_type = InteractionResponseType.modal + if response: + return InteractionCallback( + parent=parent, + channel=parent.channel, # type: ignore + data=response, + ) + async def autocomplete(self, choices: Sequence[Choice[ChoiceT]]) -> None: """|coro| @@ -1151,6 +1329,7 @@ async def edit( view: Optional[View] = MISSING, allowed_mentions: Optional[AllowedMentions] = None, delete_after: Optional[float] = None, + poll: Poll = MISSING, ) -> InteractionMessage: """|coro| @@ -1185,6 +1364,15 @@ async def edit( then it is silently ignored. .. versionadded:: 2.2 + poll: :class:`~discord.Poll` + The poll to create when editing the message. + + .. versionadded:: 2.5 + + .. note:: + + This is only accepted if the interaction response's :attr:`InteractionResponse.type` + attribute is :attr:`InteractionResponseType.deferred_channel_message`. Raises ------- @@ -1209,6 +1397,7 @@ async def edit( attachments=attachments, view=view, allowed_mentions=allowed_mentions, + poll=poll, ) if delete_after is not None: await self.delete(delay=delete_after) diff --git a/discord/types/interactions.py b/discord/types/interactions.py index 7aac5df7d095..d6e1c289eb7d 100644 --- a/discord/types/interactions.py +++ b/discord/types/interactions.py @@ -42,6 +42,7 @@ InteractionType = Literal[1, 2, 3, 4, 5] +InteractionResponseType = Literal[1, 4, 5, 6, 7, 8, 9, 10,] InteractionContextType = Literal[0, 1, 2] InteractionInstallationType = Literal[0, 1] @@ -263,3 +264,27 @@ class MessageInteractionMetadata(TypedDict): original_response_message_id: NotRequired[Snowflake] interacted_message_id: NotRequired[Snowflake] triggering_interaction_metadata: NotRequired[MessageInteractionMetadata] + + +class InteractionCallback(TypedDict): + id: Snowflake + type: InteractionType + activity_instance_id: NotRequired[str] + response_message_id: NotRequired[Snowflake] + response_message_loading: NotRequired[bool] + response_message_ephemeral: NotRequired[bool] + + +class InteractionCallbackActivity(TypedDict): + id: str + + +class InteractionCallbackResource(TypedDict): + type: InteractionResponseType + activity_instance: NotRequired[InteractionCallbackActivity] + message: NotRequired[Message] + + +class InteractionCallbackResponse(TypedDict): + interaction: InteractionCallback + resource: NotRequired[InteractionCallbackResource] diff --git a/discord/webhook/async_.py b/discord/webhook/async_.py index 3b0416f9a72c..26510b58548c 100644 --- a/discord/webhook/async_.py +++ b/discord/webhook/async_.py @@ -90,6 +90,9 @@ ) from ..types.emoji import PartialEmoji as PartialEmojiPayload from ..types.snowflake import SnowflakeList + from ..types.interactions import ( + InteractionCallbackResponse as InteractionCallbackResponsePayload, + ) BE = TypeVar('BE', bound=BaseException) _State = Union[ConnectionState, '_WebhookState'] @@ -434,7 +437,8 @@ def create_interaction_response( proxy: Optional[str] = None, proxy_auth: Optional[aiohttp.BasicAuth] = None, params: MultipartParameters, - ) -> Response[None]: + with_response: bool = MISSING, + ) -> Response[Optional[InteractionCallbackResponsePayload]]: route = Route( 'POST', '/interactions/{webhook_id}/{webhook_token}/callback', @@ -442,6 +446,9 @@ def create_interaction_response( webhook_token=token, ) + if with_response is not MISSING: + request_params = {'with_response': with_response} + if params.files: return self.request( route, @@ -450,9 +457,17 @@ def create_interaction_response( proxy_auth=proxy_auth, files=params.files, multipart=params.multipart, + params=request_params, ) else: - return self.request(route, session=session, proxy=proxy, proxy_auth=proxy_auth, payload=params.payload) + return self.request( + route, + session=session, + proxy=proxy, + proxy_auth=proxy_auth, + payload=params.payload, + params=request_params, + ) def get_original_interaction_response( self, From baa22521dd11f4292e6d7d9a820b9a64be566940 Mon Sep 17 00:00:00 2001 From: Developer Anonymous Date: Fri, 4 Oct 2024 16:39:55 +0200 Subject: [PATCH 02/22] __all__ & docs --- discord/interactions.py | 2 ++ docs/interactions/api.rst | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/discord/interactions.py b/discord/interactions.py index 589f3ea76865..ba3511078420 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -54,6 +54,8 @@ 'Interaction', 'InteractionMessage', 'InteractionResponse', + 'InteractionCallback', + 'InteractionCallbackActivity', ) if TYPE_CHECKING: diff --git a/docs/interactions/api.rst b/docs/interactions/api.rst index aeb6a25c613d..c8ec4d18db3e 100644 --- a/docs/interactions/api.rst +++ b/docs/interactions/api.rst @@ -28,6 +28,22 @@ InteractionResponse .. autoclass:: InteractionResponse() :members: +InteractionCallback +~~~~~~~~~~~~~~~~~~~ + +.. attributetable:: InteractionCallback + +.. autoclass:: InteractionCallback() + :members: + +InteractionCallbackActivity +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. attributetable:: InteractionCallbackActivity + +.. autoclass:: InteractionCallbackActivity() + :members: + InteractionMessage ~~~~~~~~~~~~~~~~~~~ From d98bbda5b29a7765f86d7ac27e29a8b4d01d39b2 Mon Sep 17 00:00:00 2001 From: Developer Anonymous Date: Fri, 4 Oct 2024 16:44:25 +0200 Subject: [PATCH 03/22] Black --- discord/interactions.py | 10 +++++++--- discord/types/interactions.py | 11 ++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index ba3511078420..ab9512e04e37 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -694,9 +694,13 @@ def _update(self, data: InteractionCallbackResponsePayload) -> None: self.interaction_type: InteractionType = try_enum(InteractionType, interaction['type']) self.activity_instance_id: Optional[str] = interaction.get('activity_instance_id') response_id = interaction.get('response_message_id') - self.response_message_id: Optional[int] = int( - response_id, - ) if response_id is not None else None + self.response_message_id: Optional[int] = ( + int( + response_id, + ) + if response_id is not None + else None + ) self.response_message_loading: Optional[bool] = interaction.get('response_message_loading') self.response_message_ephemeral: Optional[bool] = interaction.get('response_message_ephemeral') diff --git a/discord/types/interactions.py b/discord/types/interactions.py index d6e1c289eb7d..fdbc03edee28 100644 --- a/discord/types/interactions.py +++ b/discord/types/interactions.py @@ -42,7 +42,16 @@ InteractionType = Literal[1, 2, 3, 4, 5] -InteractionResponseType = Literal[1, 4, 5, 6, 7, 8, 9, 10,] +InteractionResponseType = Literal[ + 1, + 4, + 5, + 6, + 7, + 8, + 9, + 10, +] InteractionContextType = Literal[0, 1, 2] InteractionInstallationType = Literal[0, 1] From dd0a4ee6e745168d58492bbbd8ea3e4efe6bbc3a Mon Sep 17 00:00:00 2001 From: Developer Anonymous Date: Fri, 4 Oct 2024 16:52:27 +0200 Subject: [PATCH 04/22] Added repr to interaction callback --- discord/interactions.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/discord/interactions.py b/discord/interactions.py index ab9512e04e37..47c237b5dba4 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -688,6 +688,9 @@ def __init__( self.response_channel: InteractionChannel = channel self._update(data) + def __repr__(self) -> str: + return f'' + def _update(self, data: InteractionCallbackResponsePayload) -> None: interaction = data['interaction'] self.id: int = int(interaction['id']) From 8f8fc4e511fff671a4783da9c76f547e38b016a1 Mon Sep 17 00:00:00 2001 From: Developer Anonymous Date: Fri, 4 Oct 2024 21:43:05 +0200 Subject: [PATCH 05/22] Added overloads and enhanced InteractionCallback docstring --- discord/interactions.py | 135 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 5 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index 47c237b5dba4..2f541f0ac37e 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -27,7 +27,7 @@ from __future__ import annotations import logging -from typing import Any, Dict, Optional, Generic, TYPE_CHECKING, Sequence, Tuple, Union, List +from typing import Any, Dict, Literal, Optional, Generic, TYPE_CHECKING, Sequence, Tuple, Union, List, overload import asyncio import datetime @@ -659,6 +659,29 @@ class InteractionCallback(Generic[ClientT]): """Represents a Discord response to an interaction. .. versionadded:: 2.5 + + Attributes + ---------- + id: :class:`int` + The interaction ID this callback responds to. + interaction_type: :class:`InteractionType` + The interaction type. + callback_type: Optional[:class:`InteractionResponseType`] + The interaction response type. + activity_instance_id: Optional[:class:`str`] + The activity instance ID this interaction was invoked from. + activity_instance: Optional[:class:`InteractionCallbackActivity`] + The resolved activity instance this interaction was invoked from. + response_message_id: Optional[:class:`int`] + The message ID of the interaction response. + response_message_loading: :class:`bool` + Whether the response message showed the application was thinking. + response_message_ephemeral: :class:`bool` + Whether the response message was ephemeral. + response_message: :class:`InteractionMessage` + The resolved response message. + response_channel: Union[:class:`abc.GuildChannel`, :class:`abc.PrivateChannel`, :class:`Thread`] + The channel this interaction was invoked from. """ __slots__ = ( @@ -763,13 +786,33 @@ def type(self) -> Optional[InteractionResponseType]: """:class:`InteractionResponseType`: The type of response that was sent, ``None`` if response is not done.""" return self._response_type + @overload + async def defer( + self, + *, + ephemeral: bool = ..., + thinking: bool = ..., + with_response: Literal[True] = True, + ) -> InteractionCallback[ClientT]: + ... + + @overload + async def defer( + self, + *, + ephemeral: bool = ..., + thinking: bool = ..., + with_response: Literal[False] = ..., + ) -> None: + ... + async def defer( self, *, ephemeral: bool = False, thinking: bool = False, with_response: bool = True, - ) -> Optional[InteractionCallback]: + ) -> Optional[InteractionCallback[ClientT]]: """|coro| Defers the interaction response. @@ -883,6 +926,48 @@ async def pong(self) -> None: ) self._response_type = InteractionResponseType.pong + @overload + async def send_message( + self, + content: Optional[Any] = ..., + *, + embed: Embed = ..., + embeds: Sequence[Embed] = ..., + file: File = ..., + files: Sequence[File] = ..., + view: View = ..., + tts: bool = ..., + ephemeral: bool = ..., + allowed_mentions: AllowedMentions = ..., + suppress_embeds: bool = ..., + silent: bool = ..., + delete_after: Optional[float] = ..., + poll: Poll = ..., + with_response: Literal[True] = True, + ) -> InteractionCallback[ClientT]: + ... + + @overload + async def send_message( + self, + content: Optional[Any] = ..., + *, + embed: Embed = ..., + embeds: Sequence[Embed] = ..., + file: File = ..., + files: Sequence[File] = ..., + view: View = ..., + tts: bool = ..., + ephemeral: bool = ..., + allowed_mentions: AllowedMentions = ..., + suppress_embeds: bool = ..., + silent: bool = ..., + delete_after: Optional[float] = ..., + poll: Poll = ..., + with_response: Literal[False] = ..., + ) -> None: + ... + async def send_message( self, content: Optional[Any] = None, @@ -900,7 +985,7 @@ async def send_message( delete_after: Optional[float] = None, poll: Poll = MISSING, with_response: bool = True, - ) -> Optional[InteractionCallback]: + ) -> Optional[InteractionCallback[ClientT]]: """|coro| Responds to this interaction by sending a message. @@ -1035,6 +1120,38 @@ async def inner_call(delay: float = delete_after): data=response, ) + @overload + async def edit_message( + self, + *, + content: Optional[Any] = ..., + embed: Optional[Embed] = ..., + embeds: Sequence[Embed] = ..., + attachments: Sequence[Union[Attachment, File]] = ..., + view: Optional[View] = ..., + allowed_mentions: Optional[AllowedMentions] = ..., + delete_after: Optional[float] = ..., + suppress_embeds: bool = ..., + with_response: Literal[True] = True, + ) -> InteractionCallback[ClientT]: + ... + + @overload + async def edit_message( + self, + *, + content: Optional[Any] = ..., + embed: Optional[Embed] = ..., + embeds: Sequence[Embed] = ..., + attachments: Sequence[Union[Attachment, File]] = ..., + view: Optional[View] = ..., + allowed_mentions: Optional[AllowedMentions] = ..., + delete_after: Optional[float] = ..., + suppress_embeds: bool = ..., + with_response: Literal[False] = ..., + ) -> None: + ... + async def edit_message( self, *, @@ -1047,7 +1164,7 @@ async def edit_message( delete_after: Optional[float] = None, suppress_embeds: bool = MISSING, with_response: bool = True, - ) -> Optional[InteractionCallback]: + ) -> Optional[InteractionCallback[ClientT]]: """|coro| Responds to this interaction by editing the original message of @@ -1182,7 +1299,15 @@ async def inner_call(delay: float = delete_after): data=response, ) - async def send_modal(self, modal: Modal, /, *, with_response: bool = True) -> Optional[InteractionCallback]: + @overload + async def send_modal(self, modal: Modal, /, *, with_response: Literal[True] = True) -> InteractionCallback[ClientT]: + ... + + @overload + async def send_modal(self, modal: Modal, /, *, with_response: Literal[False] = ...) -> None: + ... + + async def send_modal(self, modal: Modal, /, *, with_response: bool = True) -> Optional[InteractionCallback[ClientT]]: """|coro| Responds to this interaction by sending a modal. From a16f63c946233ae72978d9cd52674148cd7924d8 Mon Sep 17 00:00:00 2001 From: DA-344 Date: Sat, 5 Oct 2024 19:06:52 +0200 Subject: [PATCH 06/22] Updated overloads and docstrings with the reviews --- discord/interactions.py | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index 2f541f0ac37e..a3c447218073 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -674,12 +674,17 @@ class InteractionCallback(Generic[ClientT]): The resolved activity instance this interaction was invoked from. response_message_id: Optional[:class:`int`] The message ID of the interaction response. - response_message_loading: :class:`bool` + response_message_loading: Optional[:class:`bool`] Whether the response message showed the application was thinking. - response_message_ephemeral: :class:`bool` + response_message_ephemeral: Optional[:class:`bool`] Whether the response message was ephemeral. - response_message: :class:`InteractionMessage` + response_message: Optional[:class:`InteractionMessage`] The resolved response message. + + .. note:: + + The has a value only when the interaction response is of type + :attr:`InteractionResponseType.channel_message` or :attr:`InteractionResponseType.message_update`. response_channel: Union[:class:`abc.GuildChannel`, :class:`abc.PrivateChannel`, :class:`Thread`] The channel this interaction was invoked from. """ @@ -720,13 +725,7 @@ def _update(self, data: InteractionCallbackResponsePayload) -> None: self.interaction_type: InteractionType = try_enum(InteractionType, interaction['type']) self.activity_instance_id: Optional[str] = interaction.get('activity_instance_id') response_id = interaction.get('response_message_id') - self.response_message_id: Optional[int] = ( - int( - response_id, - ) - if response_id is not None - else None - ) + self.response_message_id: Optional[int] = int(response_id) if response_id is not None else None self.response_message_loading: Optional[bool] = interaction.get('response_message_loading') self.response_message_ephemeral: Optional[bool] = interaction.get('response_message_ephemeral') @@ -792,7 +791,7 @@ async def defer( *, ephemeral: bool = ..., thinking: bool = ..., - with_response: Literal[True] = True, + with_response: Literal[True] = ..., ) -> InteractionCallback[ClientT]: ... @@ -802,7 +801,7 @@ async def defer( *, ephemeral: bool = ..., thinking: bool = ..., - with_response: Literal[False] = ..., + with_response: Literal[False] = False, ) -> None: ... @@ -943,7 +942,7 @@ async def send_message( silent: bool = ..., delete_after: Optional[float] = ..., poll: Poll = ..., - with_response: Literal[True] = True, + with_response: Literal[True] = ..., ) -> InteractionCallback[ClientT]: ... @@ -964,7 +963,7 @@ async def send_message( silent: bool = ..., delete_after: Optional[float] = ..., poll: Poll = ..., - with_response: Literal[False] = ..., + with_response: Literal[False] = False, ) -> None: ... @@ -1132,7 +1131,7 @@ async def edit_message( allowed_mentions: Optional[AllowedMentions] = ..., delete_after: Optional[float] = ..., suppress_embeds: bool = ..., - with_response: Literal[True] = True, + with_response: Literal[True] = ..., ) -> InteractionCallback[ClientT]: ... @@ -1148,7 +1147,7 @@ async def edit_message( allowed_mentions: Optional[AllowedMentions] = ..., delete_after: Optional[float] = ..., suppress_embeds: bool = ..., - with_response: Literal[False] = ..., + with_response: Literal[False] = False, ) -> None: ... @@ -1300,11 +1299,11 @@ async def inner_call(delay: float = delete_after): ) @overload - async def send_modal(self, modal: Modal, /, *, with_response: Literal[True] = True) -> InteractionCallback[ClientT]: + async def send_modal(self, modal: Modal, /, *, with_response: Literal[True] = ...) -> InteractionCallback[ClientT]: ... @overload - async def send_modal(self, modal: Modal, /, *, with_response: Literal[False] = ...) -> None: + async def send_modal(self, modal: Modal, /, *, with_response: Literal[False] = False) -> None: ... async def send_modal(self, modal: Modal, /, *, with_response: bool = True) -> Optional[InteractionCallback[ClientT]]: From 802adeddc95d17de9b62106279fd2a1ac9e9023e Mon Sep 17 00:00:00 2001 From: DA-344 Date: Sat, 5 Oct 2024 19:11:57 +0200 Subject: [PATCH 07/22] Rephrase response_message note --- discord/interactions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index a3c447218073..59ec18cb1b2b 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -683,8 +683,8 @@ class InteractionCallback(Generic[ClientT]): .. note:: - The has a value only when the interaction response is of type - :attr:`InteractionResponseType.channel_message` or :attr:`InteractionResponseType.message_update`. + This is ``None`` if the interaction response type is not :attr:`InteractionResponseType.channel_message` + or :attr:`InteractionResponseType.message_update`. response_channel: Union[:class:`abc.GuildChannel`, :class:`abc.PrivateChannel`, :class:`Thread`] The channel this interaction was invoked from. """ From 524ffd4d57167649678178aab0fc0b68fd86a317 Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:32:20 +0200 Subject: [PATCH 08/22] Update Interaciton._original_response on interaction callbacks and rename response_message_loading to response_message_thinking --- discord/interactions.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index 59ec18cb1b2b..3352c01ce4c3 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -697,7 +697,7 @@ class InteractionCallback(Generic[ClientT]): 'activity_instance_id', 'activity_instance', 'response_message_id', - 'response_message_loading', + 'response_message_thinking', 'response_message_ephemeral', 'response_message', 'response_channel', @@ -715,6 +715,7 @@ def __init__( self._state: ConnectionState = parent._state self.response_channel: InteractionChannel = channel self._update(data) + parent._original_response = self.response_message def __repr__(self) -> str: return f'' @@ -726,7 +727,7 @@ def _update(self, data: InteractionCallbackResponsePayload) -> None: self.activity_instance_id: Optional[str] = interaction.get('activity_instance_id') response_id = interaction.get('response_message_id') self.response_message_id: Optional[int] = int(response_id) if response_id is not None else None - self.response_message_loading: Optional[bool] = interaction.get('response_message_loading') + self.response_message_thinking: Optional[bool] = interaction.get('response_message_loading') self.response_message_ephemeral: Optional[bool] = interaction.get('response_message_ephemeral') resource = data.get('resource', {}) From b2128ac15bb7f6253528a4fee4c43b994cd73fc8 Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:11:16 +0200 Subject: [PATCH 09/22] Rename some attributes and remove Optional[bool] --- discord/interactions.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index 3352c01ce4c3..a71aba096c5b 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -674,9 +674,9 @@ class InteractionCallback(Generic[ClientT]): The resolved activity instance this interaction was invoked from. response_message_id: Optional[:class:`int`] The message ID of the interaction response. - response_message_loading: Optional[:class:`bool`] + response_message_loading: :class:`bool` Whether the response message showed the application was thinking. - response_message_ephemeral: Optional[:class:`bool`] + response_message_ephemeral: :class:`bool` Whether the response message was ephemeral. response_message: Optional[:class:`InteractionMessage`] The resolved response message. @@ -725,10 +725,9 @@ def _update(self, data: InteractionCallbackResponsePayload) -> None: self.id: int = int(interaction['id']) self.interaction_type: InteractionType = try_enum(InteractionType, interaction['type']) self.activity_instance_id: Optional[str] = interaction.get('activity_instance_id') - response_id = interaction.get('response_message_id') - self.response_message_id: Optional[int] = int(response_id) if response_id is not None else None - self.response_message_thinking: Optional[bool] = interaction.get('response_message_loading') - self.response_message_ephemeral: Optional[bool] = interaction.get('response_message_ephemeral') + self.response_message_id: Optional[int] = utils._get_as_snowflake(interaction, 'response_message_id') + self.response_message_thinking: bool = interaction.get('response_message_loading', False) + self.response_message_ephemeral: bool = interaction.get('response_message_ephemeral', False) resource = data.get('resource', {}) self.callback_type: Optional[InteractionResponseType] = None From 115a817a2340ee3360f29edc7da278870a06e45e Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:52:30 +0100 Subject: [PATCH 10/22] chore: Update thins thongs --- discord/interactions.py | 217 +++++++++++++++++++++------------- discord/types/interactions.py | 4 +- discord/webhook/async_.py | 2 +- docs/interactions/api.rst | 8 ++ 4 files changed, 143 insertions(+), 88 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index a71aba096c5b..abbe2ee67ed4 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -55,6 +55,7 @@ 'InteractionMessage', 'InteractionResponse', 'InteractionCallback', + 'InteractionCallbackResource', 'InteractionCallbackActivity', ) @@ -63,8 +64,10 @@ Interaction as InteractionPayload, InteractionData, ApplicationCommandInteractionData, - InteractionCallbackResponse as InteractionCallbackResponsePayload, + InteractionCallback as InteractionCallbackPayload, InteractionCallbackActivity as InteractionCallbackActivityPayload, + InteractionCallbackResponse as InteractionCallbackResponsePayload, + InteractionCallbackResource as InteractionCallbackResourcePayload, ) from .types.webhook import ( Webhook as WebhookPayload, @@ -655,106 +658,150 @@ def __repr__(self) -> str: return f'' -class InteractionCallback(Generic[ClientT]): - """Represents a Discord response to an interaction. - - .. versionadded:: 2.5 +class InteractionCallback: + """Represents an interaction callback invoking interaction. - Attributes - ---------- + Attribute + --------- id: :class:`int` - The interaction ID this callback responds to. - interaction_type: :class:`InteractionType` - The interaction type. - callback_type: Optional[:class:`InteractionResponseType`] + The ID of the interaction. + type: :class:`InteractionType` The interaction response type. activity_instance_id: Optional[:class:`str`] - The activity instance ID this interaction was invoked from. - activity_instance: Optional[:class:`InteractionCallbackActivity`] - The resolved activity instance this interaction was invoked from. - response_message_id: Optional[:class:`int`] - The message ID of the interaction response. - response_message_loading: :class:`bool` - Whether the response message showed the application was thinking. - response_message_ephemeral: :class:`bool` - Whether the response message was ephemeral. - response_message: Optional[:class:`InteractionMessage`] - The resolved response message. - - .. note:: - - This is ``None`` if the interaction response type is not :attr:`InteractionResponseType.channel_message` - or :attr:`InteractionResponseType.message_update`. - response_channel: Union[:class:`abc.GuildChannel`, :class:`abc.PrivateChannel`, :class:`Thread`] - The channel this interaction was invoked from. + The ID of the activity that was launched as response of this interaction. + message_id: Optional[:class:`int`] + The ID of the message that was sent as response of this interaction. """ __slots__ = ( - 'id', - '_parent', '_state', - 'interaction_type', + 'id', + '_message', + 'type', 'activity_instance_id', - 'activity_instance', - 'response_message_id', - 'response_message_thinking', - 'response_message_ephemeral', - 'response_message', - 'response_channel', - 'callback_type', + 'message_id', + ) + + def __init__(self, *, data: InteractionCallbackPayload, state: ConnectionState) -> None: + self._state: ConnectionState = state + self.id: int = int(data['id']) + self._message: Optional[Message] = None + self._update(data) + + def _update(self, data: InteractionCallbackResponsePayload) -> None: + self.type: InteractionType = try_enum(InteractionType, data['type']) + self.activity_instance_id: Optional[str] = data.get('activity_instance_id') + self.message_id: Optional[int] = utils._get_as_snowflake(data, 'response_message_id') + + @property + def message(self) -> Optional[Message]: + """Optional[:class:`Message`]: Returns the cached message, or ``None``.""" + return self._message or self._state._get_message(self.message_id) + + +class InteractionCallbackResource(Generic[ClientT]): + """Represents an interaction callback's resource. + + Attributes + ---------- + type: :class:`InteractionResponseType` + The interaction callback response type. + activity: Optional[:class:`InteractionCallbackActivity`] + The activity that was launched as a response to the interaction. + message: Optional[:class:`InteractionMessage`] + The message that was sent as a response to the interaction. + """ + + __slots__ = ( + '_state', + '_parent', + 'activity', + 'message', + 'type', ) def __init__( self, *, - parent: Interaction[ClientT], - channel: InteractionChannel, - data: InteractionCallbackResponsePayload, + data: InteractionCallbackResourcePayload, + state: ConnectionState, + parent: InteractionCallbackResponse, ) -> None: - self._parent: Interaction[ClientT] = parent - self._state: ConnectionState = parent._state - self.response_channel: InteractionChannel = channel + self._state: ConnectionState = state + self._parent: InteractionCallbackResponse = parent + self.activity: Optional[InteractionCallbackActivity] = None + self.message: Optional[InteractionMessage] = None self._update(data) - parent._original_response = self.response_message - - def __repr__(self) -> str: - return f'' - - def _update(self, data: InteractionCallbackResponsePayload) -> None: - interaction = data['interaction'] - self.id: int = int(interaction['id']) - self.interaction_type: InteractionType = try_enum(InteractionType, interaction['type']) - self.activity_instance_id: Optional[str] = interaction.get('activity_instance_id') - self.response_message_id: Optional[int] = utils._get_as_snowflake(interaction, 'response_message_id') - self.response_message_thinking: bool = interaction.get('response_message_loading', False) - self.response_message_ephemeral: bool = interaction.get('response_message_ephemeral', False) - - resource = data.get('resource', {}) - self.callback_type: Optional[InteractionResponseType] = None - self.activity_instance: Optional[InteractionCallbackActivity] = None - self.response_message: Optional[InteractionMessage] = None + def _update(self, data: InteractionCallbackResourcePayload) -> None: try: - self.callback_type = try_enum(InteractionResponseType, resource['type']) + self.type: InteractionResponseType = try_enum(InteractionResponseType, data['type']) except KeyError: pass try: - self.activity_instance = InteractionCallbackActivity( - data=resource['activity_instance'], - ) + self.activity = InteractionCallbackActivity(data=data['activity_instance']) except KeyError: pass try: - self.response_message = InteractionMessage( + self.message = InteractionMessage( state=self._state, - channel=self.response_channel, # type: ignore - data=resource['message'], + channel=self._parent._parent.channel, # type: ignore + data=data['message'], ) except KeyError: pass + self._parent.response._message = self.message + + +class InteractionCallbackResponse(Generic[ClientT]): + """Represents a Discord response to an interaction. + + .. versionadded:: 2.5 + + Attributes + ---------- + interaction: :class:`InteractionCallback` + The interaction callback response. + resource: :class:`InteractionCallbackResource` + The interaction callback resource. + """ + + __slots__ = ( + '_parent', + '_state', + 'interaction', + 'resource', + ) + + def __init__( + self, + *, + parent: Interaction[ClientT], + data: InteractionCallbackPayload, + ) -> None: + self._parent: Interaction[ClientT] = parent + self._state: ConnectionState = parent._state + + self.interaction: InteractionCallback = InteractionCallback(data=data['interaction'], state=self._state) + self.resource: Optional[InteractionCallbackResource] = None + + def __repr__(self) -> str: + return f'' + + def _update(self, data: InteractionCallbackPayload) -> None: + interaction = data['interaction'] + resource = data.get('resource', {}) + self.interaction._update(interaction) + if self.resource: + self.resource._update(resource) + else: + self.resource = InteractionCallbackResource(data=resource, state=self._state, parent=self) # type: ignore + + self._parent._original_response = self.interaction.message # type: ignore + class InteractionResponse(Generic[ClientT]): """Represents a Discord interaction response. @@ -792,7 +839,7 @@ async def defer( ephemeral: bool = ..., thinking: bool = ..., with_response: Literal[True] = ..., - ) -> InteractionCallback[ClientT]: + ) -> InteractionCallbackResponse[ClientT]: ... @overload @@ -801,7 +848,7 @@ async def defer( *, ephemeral: bool = ..., thinking: bool = ..., - with_response: Literal[False] = False, + with_response: Literal[False] = ..., ) -> None: ... @@ -811,7 +858,7 @@ async def defer( ephemeral: bool = False, thinking: bool = False, with_response: bool = True, - ) -> Optional[InteractionCallback[ClientT]]: + ) -> Optional[InteractionCallbackResponse[ClientT]]: """|coro| Defers the interaction response. @@ -887,7 +934,7 @@ async def defer( ) self._response_type = InteractionResponseType(defer_type) if response: - return InteractionCallback( + return InteractionCallbackResponse( parent=parent, channel=parent.channel, # type: ignore data=response, @@ -943,7 +990,7 @@ async def send_message( delete_after: Optional[float] = ..., poll: Poll = ..., with_response: Literal[True] = ..., - ) -> InteractionCallback[ClientT]: + ) -> InteractionCallbackResponse[ClientT]: ... @overload @@ -963,7 +1010,7 @@ async def send_message( silent: bool = ..., delete_after: Optional[float] = ..., poll: Poll = ..., - with_response: Literal[False] = False, + with_response: Literal[False] = ..., ) -> None: ... @@ -984,7 +1031,7 @@ async def send_message( delete_after: Optional[float] = None, poll: Poll = MISSING, with_response: bool = True, - ) -> Optional[InteractionCallback[ClientT]]: + ) -> Optional[InteractionCallbackResponse[ClientT]]: """|coro| Responds to this interaction by sending a message. @@ -1113,7 +1160,7 @@ async def inner_call(delay: float = delete_after): asyncio.create_task(inner_call()) if response: - return InteractionCallback( + return InteractionCallbackResponse( parent=parent, channel=parent.channel, # type: ignore data=response, @@ -1132,7 +1179,7 @@ async def edit_message( delete_after: Optional[float] = ..., suppress_embeds: bool = ..., with_response: Literal[True] = ..., - ) -> InteractionCallback[ClientT]: + ) -> InteractionCallbackResponse[ClientT]: ... @overload @@ -1147,7 +1194,7 @@ async def edit_message( allowed_mentions: Optional[AllowedMentions] = ..., delete_after: Optional[float] = ..., suppress_embeds: bool = ..., - with_response: Literal[False] = False, + with_response: Literal[False] = ..., ) -> None: ... @@ -1292,21 +1339,21 @@ async def inner_call(delay: float = delete_after): asyncio.create_task(inner_call()) if response: - return InteractionCallback( + return InteractionCallbackResponse( parent=parent, channel=parent.channel, # type: ignore data=response, ) @overload - async def send_modal(self, modal: Modal, /, *, with_response: Literal[True] = ...) -> InteractionCallback[ClientT]: + async def send_modal(self, modal: Modal, /, *, with_response: Literal[True] = ...) -> InteractionCallbackResponse[ClientT]: ... @overload - async def send_modal(self, modal: Modal, /, *, with_response: Literal[False] = False) -> None: + async def send_modal(self, modal: Modal, /, *, with_response: Literal[False] = ...) -> None: ... - async def send_modal(self, modal: Modal, /, *, with_response: bool = True) -> Optional[InteractionCallback[ClientT]]: + async def send_modal(self, modal: Modal, /, *, with_response: bool = True) -> Optional[InteractionCallbackResponse[ClientT]]: """|coro| Responds to this interaction by sending a modal. @@ -1355,7 +1402,7 @@ async def send_modal(self, modal: Modal, /, *, with_response: bool = True) -> Op self._response_type = InteractionResponseType.modal if response: - return InteractionCallback( + return InteractionCallbackResponse( parent=parent, channel=parent.channel, # type: ignore data=response, diff --git a/discord/types/interactions.py b/discord/types/interactions.py index fdbc03edee28..00e1fa7139b1 100644 --- a/discord/types/interactions.py +++ b/discord/types/interactions.py @@ -275,7 +275,7 @@ class MessageInteractionMetadata(TypedDict): triggering_interaction_metadata: NotRequired[MessageInteractionMetadata] -class InteractionCallback(TypedDict): +class InteractionCallbackResponse(TypedDict): id: Snowflake type: InteractionType activity_instance_id: NotRequired[str] @@ -294,6 +294,6 @@ class InteractionCallbackResource(TypedDict): message: NotRequired[Message] -class InteractionCallbackResponse(TypedDict): +class InteractionCallback(TypedDict): interaction: InteractionCallback resource: NotRequired[InteractionCallbackResource] diff --git a/discord/webhook/async_.py b/discord/webhook/async_.py index 93184415aaf2..bd6d2e335613 100644 --- a/discord/webhook/async_.py +++ b/discord/webhook/async_.py @@ -91,7 +91,7 @@ from ..types.emoji import PartialEmoji as PartialEmojiPayload from ..types.snowflake import SnowflakeList from ..types.interactions import ( - InteractionCallbackResponse as InteractionCallbackResponsePayload, + InteractionCallback as InteractionCallbackResponsePayload, ) BE = TypeVar('BE', bound=BaseException) diff --git a/docs/interactions/api.rst b/docs/interactions/api.rst index c8ec4d18db3e..6ac76285f8c3 100644 --- a/docs/interactions/api.rst +++ b/docs/interactions/api.rst @@ -28,6 +28,14 @@ InteractionResponse .. autoclass:: InteractionResponse() :members: +InteractionCallbackResource +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. attributetable:: InteractionCallbackResource + +.. autoclass:: InteractionCallbackResource() + :members: + InteractionCallback ~~~~~~~~~~~~~~~~~~~ From f113e50d7c855d5062b8baeabfe1db21c6a4a658 Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:56:31 +0100 Subject: [PATCH 11/22] chore: revert this change --- discord/interactions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index abbe2ee67ed4..c4f8abb9aef7 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -848,7 +848,7 @@ async def defer( *, ephemeral: bool = ..., thinking: bool = ..., - with_response: Literal[False] = ..., + with_response: Literal[False] = False, ) -> None: ... @@ -1010,7 +1010,7 @@ async def send_message( silent: bool = ..., delete_after: Optional[float] = ..., poll: Poll = ..., - with_response: Literal[False] = ..., + with_response: Literal[False] = False, ) -> None: ... @@ -1194,7 +1194,7 @@ async def edit_message( allowed_mentions: Optional[AllowedMentions] = ..., delete_after: Optional[float] = ..., suppress_embeds: bool = ..., - with_response: Literal[False] = ..., + with_response: Literal[False] = False, ) -> None: ... @@ -1350,7 +1350,7 @@ async def send_modal(self, modal: Modal, /, *, with_response: Literal[True] = .. ... @overload - async def send_modal(self, modal: Modal, /, *, with_response: Literal[False] = ...) -> None: + async def send_modal(self, modal: Modal, /, *, with_response: Literal[False] = False) -> None: ... async def send_modal(self, modal: Modal, /, *, with_response: bool = True) -> Optional[InteractionCallbackResponse[ClientT]]: From d00b606d5c287f59a7f0a8c0c0839c8f30c54a74 Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:00:36 +0100 Subject: [PATCH 12/22] fix: docs and lint --- discord/interactions.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index 17ce82fad594..b1efe92dc942 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -664,8 +664,8 @@ def __repr__(self) -> str: class InteractionCallback: """Represents an interaction callback invoking interaction. - Attribute - --------- + Attributes + ---------- id: :class:`int` The ID of the interaction. type: :class:`InteractionType` @@ -1349,14 +1349,18 @@ async def inner_call(delay: float = delete_after): ) @overload - async def send_modal(self, modal: Modal, /, *, with_response: Literal[True] = ...) -> InteractionCallbackResponse[ClientT]: + async def send_modal( + self, modal: Modal, /, *, with_response: Literal[True] = ... + ) -> InteractionCallbackResponse[ClientT]: ... @overload async def send_modal(self, modal: Modal, /, *, with_response: Literal[False] = False) -> None: ... - async def send_modal(self, modal: Modal, /, *, with_response: bool = True) -> Optional[InteractionCallbackResponse[ClientT]]: + async def send_modal( + self, modal: Modal, /, *, with_response: bool = True + ) -> Optional[InteractionCallbackResponse[ClientT]]: """|coro| Responds to this interaction by sending a modal. From 3585be901c8a590e9314eb46a1b5e2b921a417f3 Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:08:05 +0100 Subject: [PATCH 13/22] chore: fix lint --- discord/interactions.py | 13 +++++++------ discord/types/interactions.py | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index b1efe92dc942..a77889c95835 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -685,12 +685,15 @@ class InteractionCallback: 'message_id', ) - def __init__(self, *, data: InteractionCallbackPayload, state: ConnectionState) -> None: + def __init__(self, *, data: InteractionCallbackResponsePayload, state: ConnectionState) -> None: self._state: ConnectionState = state self.id: int = int(data['id']) self._message: Optional[Message] = None self._update(data) + def __repr__(self) -> str: + return f'' + def _update(self, data: InteractionCallbackResponsePayload) -> None: self.type: InteractionType = try_enum(InteractionType, data['type']) self.activity_instance_id: Optional[str] = data.get('activity_instance_id') @@ -756,8 +759,6 @@ def _update(self, data: InteractionCallbackResourcePayload) -> None: except KeyError: pass - self._parent.response._message = self.message - class InteractionCallbackResponse(Generic[ClientT]): """Represents a Discord response to an interaction. @@ -792,14 +793,14 @@ def __init__( self.resource: Optional[InteractionCallbackResource] = None def __repr__(self) -> str: - return f'' + return f'' def _update(self, data: InteractionCallbackPayload) -> None: interaction = data['interaction'] resource = data.get('resource', {}) self.interaction._update(interaction) if self.resource: - self.resource._update(resource) + self.resource._update(resource) # pyright: ignore[reportArgumentType] else: self.resource = InteractionCallbackResource(data=resource, state=self._state, parent=self) # type: ignore @@ -1213,7 +1214,7 @@ async def edit_message( delete_after: Optional[float] = None, suppress_embeds: bool = MISSING, with_response: bool = True, - ) -> Optional[InteractionCallback[ClientT]]: + ) -> Optional[InteractionCallbackResponse[ClientT]]: """|coro| Responds to this interaction by editing the original message of diff --git a/discord/types/interactions.py b/discord/types/interactions.py index c41e55c839e4..3f3516c3a696 100644 --- a/discord/types/interactions.py +++ b/discord/types/interactions.py @@ -333,5 +333,5 @@ class InteractionCallbackResource(TypedDict): class InteractionCallback(TypedDict): - interaction: InteractionCallback + interaction: InteractionCallbackResponse resource: NotRequired[InteractionCallbackResource] From 36cb749a57afef619c82693c23c4ea14fd1e5029 Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Tue, 21 Jan 2025 16:47:01 +0100 Subject: [PATCH 14/22] chore: Remove channel= param --- discord/interactions.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index a77889c95835..2d444499b70e 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -759,6 +759,8 @@ def _update(self, data: InteractionCallbackResourcePayload) -> None: except KeyError: pass + self._parent.interaction._message = self.message + class InteractionCallbackResponse(Generic[ClientT]): """Represents a Discord response to an interaction. @@ -940,7 +942,6 @@ async def defer( if response: return InteractionCallbackResponse( parent=parent, - channel=parent.channel, # type: ignore data=response, ) @@ -1166,7 +1167,6 @@ async def inner_call(delay: float = delete_after): if response: return InteractionCallbackResponse( parent=parent, - channel=parent.channel, # type: ignore data=response, ) @@ -1345,7 +1345,6 @@ async def inner_call(delay: float = delete_after): if response: return InteractionCallbackResponse( parent=parent, - channel=parent.channel, # type: ignore data=response, ) @@ -1412,7 +1411,6 @@ async def send_modal( if response: return InteractionCallbackResponse( parent=parent, - channel=parent.channel, # type: ignore data=response, ) From a667e67b75d93a2430bbab8cdfef2e387ff7c5d0 Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Mon, 17 Feb 2025 16:58:04 +0100 Subject: [PATCH 15/22] chore: Update based off discussion - See [this message in the #bikeshedding channel on the discord.py Discord server](https://discord.com/channels/336642139381301249/1294389448863125505/1340297281676775485) for details on why. --- discord/interactions.py | 378 ++++++++++---------------------------- discord/webhook/async_.py | 7 +- docs/interactions/api.rst | 18 +- 3 files changed, 100 insertions(+), 303 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index 2d444499b70e..7ab9b5b98387 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -55,8 +55,7 @@ 'InteractionMessage', 'InteractionResponse', 'InteractionCallback', - 'InteractionCallbackResource', - 'InteractionCallbackActivity', + 'InteractionCallbackActivityInstance', ) if TYPE_CHECKING: @@ -66,8 +65,6 @@ ApplicationCommandInteractionData, InteractionCallback as InteractionCallbackPayload, InteractionCallbackActivity as InteractionCallbackActivityPayload, - InteractionCallbackResponse as InteractionCallbackResponsePayload, - InteractionCallbackResource as InteractionCallbackResourcePayload, ) from .types.webhook import ( Webhook as WebhookPayload, @@ -641,8 +638,8 @@ async def translate( return await translator.translate(string, locale=locale, context=context) -class InteractionCallbackActivity: - """Represents an activity instance returned by an interaction callback. +class InteractionCallbackActivityInstance: + """Represents an activity instance launched as an interaction response. .. versionadded:: 2.5 @@ -654,159 +651,78 @@ class InteractionCallbackActivity: __slots__ = ('id',) - def __init__(self, *, data: InteractionCallbackActivityPayload) -> None: + def __init__(self, data: InteractionCallbackActivityPayload) -> None: self.id: str = data['id'] - def __repr__(self) -> str: - return f'' - +class InteractionCallback(Generic[ClientT]): + """Represents an interaction response callback. -class InteractionCallback: - """Represents an interaction callback invoking interaction. + .. versionadded:: 2.5 Attributes ---------- id: :class:`int` - The ID of the interaction. - type: :class:`InteractionType` - The interaction response type. - activity_instance_id: Optional[:class:`str`] - The ID of the activity that was launched as response of this interaction. - message_id: Optional[:class:`int`] - The ID of the message that was sent as response of this interaction. - """ - - __slots__ = ( - '_state', - 'id', - '_message', - 'type', - 'activity_instance_id', - 'message_id', - ) - - def __init__(self, *, data: InteractionCallbackResponsePayload, state: ConnectionState) -> None: - self._state: ConnectionState = state - self.id: int = int(data['id']) - self._message: Optional[Message] = None - self._update(data) - - def __repr__(self) -> str: - return f'' - - def _update(self, data: InteractionCallbackResponsePayload) -> None: - self.type: InteractionType = try_enum(InteractionType, data['type']) - self.activity_instance_id: Optional[str] = data.get('activity_instance_id') - self.message_id: Optional[int] = utils._get_as_snowflake(data, 'response_message_id') - - @property - def message(self) -> Optional[Message]: - """Optional[:class:`Message`]: Returns the cached message, or ``None``.""" - return self._message or self._state._get_message(self.message_id) - - -class InteractionCallbackResource(Generic[ClientT]): - """Represents an interaction callback's resource. - - Attributes - ---------- + The interaction ID. type: :class:`InteractionResponseType` The interaction callback response type. - activity: Optional[:class:`InteractionCallbackActivity`] - The activity that was launched as a response to the interaction. - message: Optional[:class:`InteractionMessage`] - The message that was sent as a response to the interaction. + resource: Optional[Union[:class:`InteractionMessage`, :class:`InteractionCallbackActivityInstance`]] + The resource that the interaction response created. If a message was sent, this will be + a :class:`InteractionMessage`, else if an activity was launched this will be a + :class:`InteractionCallbackActivityInstance`. In any other case, this will be ``None``. + message_id: Optional[:class:`int`] + The message ID of the resource. Only available if the resource is a :class:`InteractionMessage`. + activity_id: Optional[:class:`str`] + The activity ID of the resource. Only available if the resource is a :class:`InteractionCallbackActivityInstance`. """ - __slots__ = ( - '_state', - '_parent', - 'activity', - 'message', - 'type', - ) - def __init__( self, *, - data: InteractionCallbackResourcePayload, + data: InteractionCallbackPayload, + parent: Interaction[ClientT], state: ConnectionState, - parent: InteractionCallbackResponse, + type: InteractionResponseType, ) -> None: self._state: ConnectionState = state - self._parent: InteractionCallbackResponse = parent - self.activity: Optional[InteractionCallbackActivity] = None - self.message: Optional[InteractionMessage] = None + self._parent: Interaction[ClientT] = parent + self.type: InteractionResponseType = type self._update(data) - def _update(self, data: InteractionCallbackResourcePayload) -> None: - try: - self.type: InteractionResponseType = try_enum(InteractionResponseType, data['type']) - except KeyError: - pass - - try: - self.activity = InteractionCallbackActivity(data=data['activity_instance']) - except KeyError: - pass - - try: - self.message = InteractionMessage( - state=self._state, - channel=self._parent._parent.channel, # type: ignore - data=data['message'], - ) - except KeyError: - pass - - self._parent.interaction._message = self.message - - -class InteractionCallbackResponse(Generic[ClientT]): - """Represents a Discord response to an interaction. + def _update(self, data: InteractionCallbackPayload) -> None: + interaction = data['interaction'] - .. versionadded:: 2.5 + self.id: int = int(interaction['id']) + self._thinking: bool = interaction.get('response_message_loading', False) + self._ephemeral: bool = interaction.get('response_message_ephemeral', False) - Attributes - ---------- - interaction: :class:`InteractionCallback` - The interaction callback response. - resource: :class:`InteractionCallbackResource` - The interaction callback resource. - """ + self.message_id: Optional[int] = utils._get_as_snowflake(interaction, 'response_message_id') + self.activity_id: Optional[str] = interaction.get('activity_instance_id') - __slots__ = ( - '_parent', - '_state', - 'interaction', - 'resource', - ) + self.resource: Optional[Union[InteractionMessage, InteractionCallbackActivityInstance]] = None - def __init__( - self, - *, - parent: Interaction[ClientT], - data: InteractionCallbackPayload, - ) -> None: - self._parent: Interaction[ClientT] = parent - self._state: ConnectionState = parent._state + if 'resource' in data: + resource = data['resource'] - self.interaction: InteractionCallback = InteractionCallback(data=data['interaction'], state=self._state) - self.resource: Optional[InteractionCallbackResource] = None + self.type = try_enum(InteractionResponseType, resource['type']) - def __repr__(self) -> str: - return f'' + if 'message' in resource and resource['message']: + self.resource = InteractionMessage( + state=self._state, + channel=self._parent.channel, # type: ignore # channel should be the correct type here + data=resource['message'], + ) + elif 'activity_instance' in resource and resource['activity_instance']: + self.resource = InteractionCallbackActivityInstance( + resource['activity_instance'], + ) - def _update(self, data: InteractionCallbackPayload) -> None: - interaction = data['interaction'] - resource = data.get('resource', {}) - self.interaction._update(interaction) - if self.resource: - self.resource._update(resource) # pyright: ignore[reportArgumentType] - else: - self.resource = InteractionCallbackResource(data=resource, state=self._state, parent=self) # type: ignore + def is_thinking(self) -> bool: + """:class:`bool`: Whether the response was a thinking defer.""" + return self._thinking - self._parent._original_response = self.interaction.message # type: ignore + def is_ephemeral(self) -> bool: + """:class:`bool`: Whether the response was ephemeral.""" + return self._ephemeral class InteractionResponse(Generic[ClientT]): @@ -838,33 +754,12 @@ def type(self) -> Optional[InteractionResponseType]: """:class:`InteractionResponseType`: The type of response that was sent, ``None`` if response is not done.""" return self._response_type - @overload - async def defer( - self, - *, - ephemeral: bool = ..., - thinking: bool = ..., - with_response: Literal[True] = ..., - ) -> InteractionCallbackResponse[ClientT]: - ... - - @overload - async def defer( - self, - *, - ephemeral: bool = ..., - thinking: bool = ..., - with_response: Literal[False] = False, - ) -> None: - ... - async def defer( self, *, ephemeral: bool = False, thinking: bool = False, - with_response: bool = True, - ) -> Optional[InteractionCallbackResponse[ClientT]]: + ) -> Optional[InteractionCallback[ClientT]]: """|coro| Defers the interaction response. @@ -878,6 +773,9 @@ async def defer( - :attr:`InteractionType.component` - :attr:`InteractionType.modal_submit` + .. versionchanged:: 2.5 + This now returns a :class:`InteractionCallback` instance. + Parameters ----------- ephemeral: :class:`bool` @@ -889,10 +787,6 @@ async def defer( In UI terms, this is represented as if the bot is thinking of a response. It is your responsibility to eventually send a followup message via :attr:`Interaction.followup` to make this thinking state go away. Application commands (AKA Slash commands) cannot use :attr:`InteractionResponseType.deferred_message_update`. - with_response: :class:`bool` - Whether to return the interaction response callback resource. - - .. versionadded:: 2.5 Raises ------- @@ -936,14 +830,14 @@ async def defer( proxy=http.proxy, proxy_auth=http.proxy_auth, params=params, - with_response=with_response, ) self._response_type = InteractionResponseType(defer_type) - if response: - return InteractionCallbackResponse( - parent=parent, - data=response, - ) + return InteractionCallback( + data=response, + parent=self._parent, + state=self._parent._state, + type=self._response_type, + ) async def pong(self) -> None: """|coro| @@ -977,48 +871,6 @@ async def pong(self) -> None: ) self._response_type = InteractionResponseType.pong - @overload - async def send_message( - self, - content: Optional[Any] = ..., - *, - embed: Embed = ..., - embeds: Sequence[Embed] = ..., - file: File = ..., - files: Sequence[File] = ..., - view: View = ..., - tts: bool = ..., - ephemeral: bool = ..., - allowed_mentions: AllowedMentions = ..., - suppress_embeds: bool = ..., - silent: bool = ..., - delete_after: Optional[float] = ..., - poll: Poll = ..., - with_response: Literal[True] = ..., - ) -> InteractionCallbackResponse[ClientT]: - ... - - @overload - async def send_message( - self, - content: Optional[Any] = ..., - *, - embed: Embed = ..., - embeds: Sequence[Embed] = ..., - file: File = ..., - files: Sequence[File] = ..., - view: View = ..., - tts: bool = ..., - ephemeral: bool = ..., - allowed_mentions: AllowedMentions = ..., - suppress_embeds: bool = ..., - silent: bool = ..., - delete_after: Optional[float] = ..., - poll: Poll = ..., - with_response: Literal[False] = False, - ) -> None: - ... - async def send_message( self, content: Optional[Any] = None, @@ -1035,12 +887,14 @@ async def send_message( silent: bool = False, delete_after: Optional[float] = None, poll: Poll = MISSING, - with_response: bool = True, - ) -> Optional[InteractionCallbackResponse[ClientT]]: + ) -> InteractionCallback[ClientT]: """|coro| Responds to this interaction by sending a message. + .. versionchanged:: 2.5 + This now returns a :class:`InteractionCallback` instance. + Parameters ----------- content: Optional[:class:`str`] @@ -1083,10 +937,6 @@ async def send_message( The poll to send with this message. .. versionadded:: 2.4 - with_response: :class:`bool` - Whether to return the interaction response callback resource. - - .. versionadded:: 2.5 Raises ------- @@ -1101,8 +951,8 @@ async def send_message( Returns ------- - Optional[:class:`InteractionCallback`] - The interaction callback data, or ``None``. + :class:`InteractionCallback` + The interaction callback data. """ if self._response_type: raise InteractionResponded(self._parent) @@ -1140,7 +990,6 @@ async def send_message( proxy=http.proxy, proxy_auth=http.proxy_auth, params=params, - with_response=with_response, ) if view is not MISSING and not view.is_finished(): @@ -1164,43 +1013,13 @@ async def inner_call(delay: float = delete_after): pass asyncio.create_task(inner_call()) - if response: - return InteractionCallbackResponse( - parent=parent, - data=response, - ) - @overload - async def edit_message( - self, - *, - content: Optional[Any] = ..., - embed: Optional[Embed] = ..., - embeds: Sequence[Embed] = ..., - attachments: Sequence[Union[Attachment, File]] = ..., - view: Optional[View] = ..., - allowed_mentions: Optional[AllowedMentions] = ..., - delete_after: Optional[float] = ..., - suppress_embeds: bool = ..., - with_response: Literal[True] = ..., - ) -> InteractionCallbackResponse[ClientT]: - ... - - @overload - async def edit_message( - self, - *, - content: Optional[Any] = ..., - embed: Optional[Embed] = ..., - embeds: Sequence[Embed] = ..., - attachments: Sequence[Union[Attachment, File]] = ..., - view: Optional[View] = ..., - allowed_mentions: Optional[AllowedMentions] = ..., - delete_after: Optional[float] = ..., - suppress_embeds: bool = ..., - with_response: Literal[False] = False, - ) -> None: - ... + return InteractionCallback( + data=response, + parent=self._parent, + state=self._parent._state, + type=self._response_type, + ) async def edit_message( self, @@ -1213,13 +1032,15 @@ async def edit_message( allowed_mentions: Optional[AllowedMentions] = MISSING, delete_after: Optional[float] = None, suppress_embeds: bool = MISSING, - with_response: bool = True, - ) -> Optional[InteractionCallbackResponse[ClientT]]: + ) -> Optional[InteractionCallback[ClientT]]: """|coro| Responds to this interaction by editing the original message of a component or modal interaction. + .. versionchanged:: 2.5 + This now returns a :class:`InteractionCallback` instance. + Parameters ----------- content: Optional[:class:`str`] @@ -1256,10 +1077,6 @@ async def edit_message( Using this parameter requires :attr:`~.Permissions.manage_messages`. .. versionadded:: 2.4 - with_response: :class:`bool` - Whether to return the interaction response callback resource. - - .. versionadded:: 2.5 Raises ------- @@ -1273,7 +1090,7 @@ async def edit_message( Returns ------- Optional[:class:`InteractionCallback`] - The interaction callback data, or ``None``. + The interaction callback data, or ``None`` if editing the message was not possible. """ if self._response_type: raise InteractionResponded(self._parent) @@ -1323,7 +1140,6 @@ async def edit_message( proxy=http.proxy, proxy_auth=http.proxy_auth, params=params, - with_response=with_response, ) if view and not view.is_finished(): @@ -1342,29 +1158,21 @@ async def inner_call(delay: float = delete_after): asyncio.create_task(inner_call()) - if response: - return InteractionCallbackResponse( - parent=parent, - data=response, - ) - - @overload - async def send_modal( - self, modal: Modal, /, *, with_response: Literal[True] = ... - ) -> InteractionCallbackResponse[ClientT]: - ... - - @overload - async def send_modal(self, modal: Modal, /, *, with_response: Literal[False] = False) -> None: - ... + return InteractionCallback( + data=response, + parent=self._parent, + state=self._parent._state, + type=self._response_type, + ) - async def send_modal( - self, modal: Modal, /, *, with_response: bool = True - ) -> Optional[InteractionCallbackResponse[ClientT]]: + async def send_modal(self, modal: Modal, /) -> InteractionCallback[ClientT]: """|coro| Responds to this interaction by sending a modal. + .. versionchanged:: 2.5 + This now returns a :class:`InteractionCallback` instance. + Parameters ----------- modal: :class:`~discord.ui.Modal` @@ -1383,8 +1191,8 @@ async def send_modal( Returns ------- - Optional[:class:`InteractionCallback`] - The interaction callback data, or ``None``. + :class:`InteractionCallback` + The interaction callback data. """ if self._response_type: raise InteractionResponded(self._parent) @@ -1402,17 +1210,17 @@ async def send_modal( proxy=http.proxy, proxy_auth=http.proxy_auth, params=params, - with_response=with_response, ) if not modal.is_finished(): self._parent._state.store_view(modal) self._response_type = InteractionResponseType.modal - if response: - return InteractionCallbackResponse( - parent=parent, - data=response, - ) + return InteractionCallback( + data=response, + parent=self._parent, + state=self._parent._state, + type=self._response_type, + ) async def autocomplete(self, choices: Sequence[Choice[ChoiceT]]) -> None: """|coro| diff --git a/discord/webhook/async_.py b/discord/webhook/async_.py index bd6d2e335613..b727cdb91ce7 100644 --- a/discord/webhook/async_.py +++ b/discord/webhook/async_.py @@ -437,17 +437,14 @@ def create_interaction_response( proxy: Optional[str] = None, proxy_auth: Optional[aiohttp.BasicAuth] = None, params: MultipartParameters, - with_response: bool = MISSING, - ) -> Response[Optional[InteractionCallbackResponsePayload]]: + ) -> Response[InteractionCallbackResponsePayload]: route = Route( 'POST', '/interactions/{webhook_id}/{webhook_token}/callback', webhook_id=interaction_id, webhook_token=token, ) - - if with_response is not MISSING: - request_params = {'with_response': with_response} + request_params = {'with_response': '1'} if params.files: return self.request( diff --git a/docs/interactions/api.rst b/docs/interactions/api.rst index 6ac76285f8c3..0bf69903bfc7 100644 --- a/docs/interactions/api.rst +++ b/docs/interactions/api.rst @@ -28,28 +28,20 @@ InteractionResponse .. autoclass:: InteractionResponse() :members: -InteractionCallbackResource -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. attributetable:: InteractionCallbackResource - -.. autoclass:: InteractionCallbackResource() - :members: - InteractionCallback -~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. attributetable:: InteractionCallback .. autoclass:: InteractionCallback() :members: -InteractionCallbackActivity -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +InteractionCallbackActivityInstance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. attributetable:: InteractionCallbackActivity +.. attributetable:: InteractionCallbackActivityInstance -.. autoclass:: InteractionCallbackActivity() +.. autoclass:: InteractionCallbackActivityInstance() :members: InteractionMessage From 5b08698784266d322512739b764da14a3e194150 Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Mon, 17 Feb 2025 16:58:56 +0100 Subject: [PATCH 16/22] chore: Remove unused imports --- discord/interactions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/interactions.py b/discord/interactions.py index 7ab9b5b98387..ab2c9ccfbf77 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -27,7 +27,7 @@ from __future__ import annotations import logging -from typing import Any, Dict, Literal, Optional, Generic, TYPE_CHECKING, Sequence, Tuple, Union, List, overload +from typing import Any, Dict, Optional, Generic, TYPE_CHECKING, Sequence, Tuple, Union, List import asyncio import datetime From 1563a3e828a1b0f6f8e426f8daf7b4e0cde82822 Mon Sep 17 00:00:00 2001 From: DA-344 <108473820+DA-344@users.noreply.github.com> Date: Mon, 17 Feb 2025 17:00:57 +0100 Subject: [PATCH 17/22] chore: run black --- discord/interactions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/discord/interactions.py b/discord/interactions.py index ab2c9ccfbf77..3dcf1e360fd2 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -654,6 +654,7 @@ class InteractionCallbackActivityInstance: def __init__(self, data: InteractionCallbackActivityPayload) -> None: self.id: str = data['id'] + class InteractionCallback(Generic[ClientT]): """Represents an interaction response callback. From c7372adf8559d53dd5d7f17833f4e1534285429c Mon Sep 17 00:00:00 2001 From: DA344 <108473820+DA-344@users.noreply.github.com> Date: Tue, 18 Feb 2025 07:46:48 +0100 Subject: [PATCH 18/22] Update discord/interactions.py Co-authored-by: Danny <1695103+Rapptz@users.noreply.github.com> --- discord/interactions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/interactions.py b/discord/interactions.py index 3dcf1e360fd2..4adfc39d6362 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -668,7 +668,7 @@ class InteractionCallback(Generic[ClientT]): The interaction callback response type. resource: Optional[Union[:class:`InteractionMessage`, :class:`InteractionCallbackActivityInstance`]] The resource that the interaction response created. If a message was sent, this will be - a :class:`InteractionMessage`, else if an activity was launched this will be a + a :class:`InteractionMessage`. If an activity was launched this will be a :class:`InteractionCallbackActivityInstance`. In any other case, this will be ``None``. message_id: Optional[:class:`int`] The message ID of the resource. Only available if the resource is a :class:`InteractionMessage`. From 62cda7541798d1acdd3b3620fc35e63211914b66 Mon Sep 17 00:00:00 2001 From: DA344 <108473820+DA-344@users.noreply.github.com> Date: Tue, 18 Feb 2025 07:52:19 +0100 Subject: [PATCH 19/22] chore: Add slots to InteractionCallback --- discord/interactions.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/discord/interactions.py b/discord/interactions.py index 4adfc39d6362..968fcfb35c68 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -94,6 +94,10 @@ DMChannel, GroupChannel, ] + InteractionCallbackResource = Union[ + InteractionMessage, + InteractionCallbackActivityInstance, + ] MISSING: Any = utils.MISSING @@ -676,6 +680,18 @@ class InteractionCallback(Generic[ClientT]): The activity ID of the resource. Only available if the resource is a :class:`InteractionCallbackActivityInstance`. """ + __slots__ = ( + '_state', + '_parent', + 'type', + 'id,', + '_thinking', + '_ephemeral', + 'message_id', + 'activity_id', + 'resource', + ) + def __init__( self, *, @@ -699,7 +715,7 @@ def _update(self, data: InteractionCallbackPayload) -> None: self.message_id: Optional[int] = utils._get_as_snowflake(interaction, 'response_message_id') self.activity_id: Optional[str] = interaction.get('activity_instance_id') - self.resource: Optional[Union[InteractionMessage, InteractionCallbackActivityInstance]] = None + self.resource: Optional[InteractionCallbackResource] = None if 'resource' in data: resource = data['resource'] From 197773c32e295e5c3ea8919c81890b54c3d59409 Mon Sep 17 00:00:00 2001 From: DA344 <108473820+DA-344@users.noreply.github.com> Date: Tue, 18 Feb 2025 07:56:32 +0100 Subject: [PATCH 20/22] Fix slots and type alias --- discord/interactions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index 968fcfb35c68..04700ad5fadc 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -95,8 +95,8 @@ GroupChannel, ] InteractionCallbackResource = Union[ - InteractionMessage, - InteractionCallbackActivityInstance, + "InteractionMessage", + "InteractionCallbackActivityInstance", ] MISSING: Any = utils.MISSING @@ -684,7 +684,7 @@ class InteractionCallback(Generic[ClientT]): '_state', '_parent', 'type', - 'id,', + 'id', '_thinking', '_ephemeral', 'message_id', From 2592bf175e84bd3d658cc4c84c1126e43409c967 Mon Sep 17 00:00:00 2001 From: DA344 <108473820+DA-344@users.noreply.github.com> Date: Tue, 18 Feb 2025 07:58:12 +0100 Subject: [PATCH 21/22] Update discord/interactions.py Co-authored-by: Danny <1695103+Rapptz@users.noreply.github.com> --- discord/interactions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index 04700ad5fadc..f39878082955 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -717,8 +717,8 @@ def _update(self, data: InteractionCallbackPayload) -> None: self.resource: Optional[InteractionCallbackResource] = None - if 'resource' in data: - resource = data['resource'] + resource = data.get('resource') + if resource is not None: self.type = try_enum(InteractionResponseType, resource['type']) From 7ad73d020dc7bf0f2ee5e22365420051d8e9d66d Mon Sep 17 00:00:00 2001 From: DA344 <108473820+DA-344@users.noreply.github.com> Date: Tue, 18 Feb 2025 08:06:58 +0100 Subject: [PATCH 22/22] Update discord/interactions.py Co-authored-by: Danny <1695103+Rapptz@users.noreply.github.com> --- discord/interactions.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/discord/interactions.py b/discord/interactions.py index f39878082955..07c600a5dde0 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -722,16 +722,16 @@ def _update(self, data: InteractionCallbackPayload) -> None: self.type = try_enum(InteractionResponseType, resource['type']) - if 'message' in resource and resource['message']: + message = resource.get('message') + activity_instance = resource.get('activity_instance') + if message is not None: self.resource = InteractionMessage( state=self._state, channel=self._parent.channel, # type: ignore # channel should be the correct type here - data=resource['message'], - ) - elif 'activity_instance' in resource and resource['activity_instance']: - self.resource = InteractionCallbackActivityInstance( - resource['activity_instance'], + data=message, ) + elif activity_instance is not None: + self.resource = InteractionCallbackActivityInstance(activity_instance) def is_thinking(self) -> bool: """:class:`bool`: Whether the response was a thinking defer."""