mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-04-18 15:06:07 +00:00
Add support for Interaction Callback Resource
Co-authored-by: Danny <1695103+Rapptz@users.noreply.github.com>
This commit is contained in:
parent
fa158a5eba
commit
5b78097cef
@ -54,6 +54,8 @@ __all__ = (
|
||||
'Interaction',
|
||||
'InteractionMessage',
|
||||
'InteractionResponse',
|
||||
'InteractionCallback',
|
||||
'InteractionCallbackActivityInstance',
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -61,6 +63,8 @@ if TYPE_CHECKING:
|
||||
Interaction as InteractionPayload,
|
||||
InteractionData,
|
||||
ApplicationCommandInteractionData,
|
||||
InteractionCallback as InteractionCallbackPayload,
|
||||
InteractionCallbackActivity as InteractionCallbackActivityPayload,
|
||||
)
|
||||
from .types.webhook import (
|
||||
Webhook as WebhookPayload,
|
||||
@ -90,6 +94,10 @@ if TYPE_CHECKING:
|
||||
DMChannel,
|
||||
GroupChannel,
|
||||
]
|
||||
InteractionCallbackResource = Union[
|
||||
"InteractionMessage",
|
||||
"InteractionCallbackActivityInstance",
|
||||
]
|
||||
|
||||
MISSING: Any = utils.MISSING
|
||||
|
||||
@ -469,6 +477,7 @@ class Interaction(Generic[ClientT]):
|
||||
attachments: Sequence[Union[Attachment, File]] = MISSING,
|
||||
view: Optional[View] = MISSING,
|
||||
allowed_mentions: Optional[AllowedMentions] = None,
|
||||
poll: Poll = MISSING,
|
||||
) -> InteractionMessage:
|
||||
"""|coro|
|
||||
|
||||
@ -503,6 +512,14 @@ class Interaction(Generic[ClientT]):
|
||||
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
|
||||
-------
|
||||
@ -532,6 +549,7 @@ class Interaction(Generic[ClientT]):
|
||||
view=view,
|
||||
allowed_mentions=allowed_mentions,
|
||||
previous_allowed_mentions=previous_mentions,
|
||||
poll=poll,
|
||||
) as params:
|
||||
adapter = async_context.get()
|
||||
http = self._state.http
|
||||
@ -624,6 +642,106 @@ class Interaction(Generic[ClientT]):
|
||||
return await translator.translate(string, locale=locale, context=context)
|
||||
|
||||
|
||||
class InteractionCallbackActivityInstance:
|
||||
"""Represents an activity instance launched as an interaction response.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
Attributes
|
||||
----------
|
||||
id: :class:`str`
|
||||
The activity instance ID.
|
||||
"""
|
||||
|
||||
__slots__ = ('id',)
|
||||
|
||||
def __init__(self, data: InteractionCallbackActivityPayload) -> None:
|
||||
self.id: str = data['id']
|
||||
|
||||
|
||||
class InteractionCallback(Generic[ClientT]):
|
||||
"""Represents an interaction response callback.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
Attributes
|
||||
----------
|
||||
id: :class:`int`
|
||||
The interaction ID.
|
||||
type: :class:`InteractionResponseType`
|
||||
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`. 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',
|
||||
'type',
|
||||
'id',
|
||||
'_thinking',
|
||||
'_ephemeral',
|
||||
'message_id',
|
||||
'activity_id',
|
||||
'resource',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
data: InteractionCallbackPayload,
|
||||
parent: Interaction[ClientT],
|
||||
state: ConnectionState,
|
||||
type: InteractionResponseType,
|
||||
) -> None:
|
||||
self._state: ConnectionState = state
|
||||
self._parent: Interaction[ClientT] = parent
|
||||
self.type: InteractionResponseType = type
|
||||
self._update(data)
|
||||
|
||||
def _update(self, data: InteractionCallbackPayload) -> None:
|
||||
interaction = data['interaction']
|
||||
|
||||
self.id: int = int(interaction['id'])
|
||||
self._thinking: bool = interaction.get('response_message_loading', False)
|
||||
self._ephemeral: bool = interaction.get('response_message_ephemeral', False)
|
||||
|
||||
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[InteractionCallbackResource] = None
|
||||
|
||||
resource = data.get('resource')
|
||||
if resource is not None:
|
||||
|
||||
self.type = try_enum(InteractionResponseType, resource['type'])
|
||||
|
||||
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=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."""
|
||||
return self._thinking
|
||||
|
||||
def is_ephemeral(self) -> bool:
|
||||
""":class:`bool`: Whether the response was ephemeral."""
|
||||
return self._ephemeral
|
||||
|
||||
|
||||
class InteractionResponse(Generic[ClientT]):
|
||||
"""Represents a Discord interaction response.
|
||||
|
||||
@ -653,7 +771,12 @@ class InteractionResponse(Generic[ClientT]):
|
||||
""":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,
|
||||
) -> Optional[InteractionCallback[ClientT]]:
|
||||
"""|coro|
|
||||
|
||||
Defers the interaction response.
|
||||
@ -667,6 +790,9 @@ class InteractionResponse(Generic[ClientT]):
|
||||
- :attr:`InteractionType.component`
|
||||
- :attr:`InteractionType.modal_submit`
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This now returns a :class:`InteractionCallback` instance.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
ephemeral: :class:`bool`
|
||||
@ -685,6 +811,11 @@ class InteractionResponse(Generic[ClientT]):
|
||||
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)
|
||||
@ -709,7 +840,7 @@ class InteractionResponse(Generic[ClientT]):
|
||||
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,
|
||||
@ -718,6 +849,12 @@ class InteractionResponse(Generic[ClientT]):
|
||||
params=params,
|
||||
)
|
||||
self._response_type = InteractionResponseType(defer_type)
|
||||
return InteractionCallback(
|
||||
data=response,
|
||||
parent=self._parent,
|
||||
state=self._parent._state,
|
||||
type=self._response_type,
|
||||
)
|
||||
|
||||
async def pong(self) -> None:
|
||||
"""|coro|
|
||||
@ -767,11 +904,14 @@ class InteractionResponse(Generic[ClientT]):
|
||||
silent: bool = False,
|
||||
delete_after: Optional[float] = None,
|
||||
poll: Poll = MISSING,
|
||||
) -> None:
|
||||
) -> 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`]
|
||||
@ -825,6 +965,11 @@ class InteractionResponse(Generic[ClientT]):
|
||||
The length of ``embeds`` was invalid.
|
||||
InteractionResponded
|
||||
This interaction has already been responded to before.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`InteractionCallback`
|
||||
The interaction callback data.
|
||||
"""
|
||||
if self._response_type:
|
||||
raise InteractionResponded(self._parent)
|
||||
@ -855,7 +1000,7 @@ class InteractionResponse(Generic[ClientT]):
|
||||
)
|
||||
|
||||
http = parent._state.http
|
||||
await adapter.create_interaction_response(
|
||||
response = await adapter.create_interaction_response(
|
||||
parent.id,
|
||||
parent.token,
|
||||
session=parent._session,
|
||||
@ -886,6 +1031,13 @@ class InteractionResponse(Generic[ClientT]):
|
||||
|
||||
asyncio.create_task(inner_call())
|
||||
|
||||
return InteractionCallback(
|
||||
data=response,
|
||||
parent=self._parent,
|
||||
state=self._parent._state,
|
||||
type=self._response_type,
|
||||
)
|
||||
|
||||
async def edit_message(
|
||||
self,
|
||||
*,
|
||||
@ -897,12 +1049,15 @@ class InteractionResponse(Generic[ClientT]):
|
||||
allowed_mentions: Optional[AllowedMentions] = MISSING,
|
||||
delete_after: Optional[float] = None,
|
||||
suppress_embeds: bool = MISSING,
|
||||
) -> None:
|
||||
) -> 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`]
|
||||
@ -948,6 +1103,11 @@ class InteractionResponse(Generic[ClientT]):
|
||||
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 editing the message was not possible.
|
||||
"""
|
||||
if self._response_type:
|
||||
raise InteractionResponded(self._parent)
|
||||
@ -990,7 +1150,7 @@ class InteractionResponse(Generic[ClientT]):
|
||||
)
|
||||
|
||||
http = parent._state.http
|
||||
await adapter.create_interaction_response(
|
||||
response = await adapter.create_interaction_response(
|
||||
parent.id,
|
||||
parent.token,
|
||||
session=parent._session,
|
||||
@ -1015,15 +1175,29 @@ class InteractionResponse(Generic[ClientT]):
|
||||
|
||||
asyncio.create_task(inner_call())
|
||||
|
||||
async def send_modal(self, modal: Modal, /) -> None:
|
||||
return InteractionCallback(
|
||||
data=response,
|
||||
parent=self._parent,
|
||||
state=self._parent._state,
|
||||
type=self._response_type,
|
||||
)
|
||||
|
||||
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`
|
||||
The modal to send.
|
||||
with_response: :class:`bool`
|
||||
Whether to return the interaction response callback resource.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
Raises
|
||||
-------
|
||||
@ -1031,6 +1205,11 @@ class InteractionResponse(Generic[ClientT]):
|
||||
Sending the modal failed.
|
||||
InteractionResponded
|
||||
This interaction has already been responded to before.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`InteractionCallback`
|
||||
The interaction callback data.
|
||||
"""
|
||||
if self._response_type:
|
||||
raise InteractionResponded(self._parent)
|
||||
@ -1041,7 +1220,7 @@ class InteractionResponse(Generic[ClientT]):
|
||||
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,
|
||||
@ -1053,6 +1232,13 @@ class InteractionResponse(Generic[ClientT]):
|
||||
self._parent._state.store_view(modal)
|
||||
self._response_type = InteractionResponseType.modal
|
||||
|
||||
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|
|
||||
|
||||
@ -1154,6 +1340,7 @@ class InteractionMessage(Message):
|
||||
view: Optional[View] = MISSING,
|
||||
allowed_mentions: Optional[AllowedMentions] = None,
|
||||
delete_after: Optional[float] = None,
|
||||
poll: Poll = MISSING,
|
||||
) -> InteractionMessage:
|
||||
"""|coro|
|
||||
|
||||
@ -1188,6 +1375,15 @@ class InteractionMessage(Message):
|
||||
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
|
||||
-------
|
||||
@ -1212,6 +1408,7 @@ class InteractionMessage(Message):
|
||||
attachments=attachments,
|
||||
view=view,
|
||||
allowed_mentions=allowed_mentions,
|
||||
poll=poll,
|
||||
)
|
||||
if delete_after is not None:
|
||||
await self.delete(delay=delete_after)
|
||||
|
@ -42,6 +42,16 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
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]
|
||||
|
||||
@ -301,3 +311,27 @@ MessageInteractionMetadata = Union[
|
||||
MessageComponentMessageInteractionMetadata,
|
||||
ModalSubmitMessageInteractionMetadata,
|
||||
]
|
||||
|
||||
|
||||
class InteractionCallbackResponse(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 InteractionCallback(TypedDict):
|
||||
interaction: InteractionCallbackResponse
|
||||
resource: NotRequired[InteractionCallbackResource]
|
||||
|
@ -90,6 +90,9 @@ if TYPE_CHECKING:
|
||||
)
|
||||
from ..types.emoji import PartialEmoji as PartialEmojiPayload
|
||||
from ..types.snowflake import SnowflakeList
|
||||
from ..types.interactions import (
|
||||
InteractionCallback as InteractionCallbackResponsePayload,
|
||||
)
|
||||
|
||||
BE = TypeVar('BE', bound=BaseException)
|
||||
_State = Union[ConnectionState, '_WebhookState']
|
||||
@ -435,13 +438,14 @@ class AsyncWebhookAdapter:
|
||||
proxy: Optional[str] = None,
|
||||
proxy_auth: Optional[aiohttp.BasicAuth] = None,
|
||||
params: MultipartParameters,
|
||||
) -> Response[None]:
|
||||
) -> Response[InteractionCallbackResponsePayload]:
|
||||
route = Route(
|
||||
'POST',
|
||||
'/interactions/{webhook_id}/{webhook_token}/callback',
|
||||
webhook_id=interaction_id,
|
||||
webhook_token=token,
|
||||
)
|
||||
request_params = {'with_response': '1'}
|
||||
|
||||
if params.files:
|
||||
return self.request(
|
||||
@ -451,9 +455,17 @@ class AsyncWebhookAdapter:
|
||||
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,
|
||||
|
@ -28,6 +28,22 @@ InteractionResponse
|
||||
.. autoclass:: InteractionResponse()
|
||||
:members:
|
||||
|
||||
InteractionCallback
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. attributetable:: InteractionCallback
|
||||
|
||||
.. autoclass:: InteractionCallback()
|
||||
:members:
|
||||
|
||||
InteractionCallbackActivityInstance
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. attributetable:: InteractionCallbackActivityInstance
|
||||
|
||||
.. autoclass:: InteractionCallbackActivityInstance()
|
||||
:members:
|
||||
|
||||
InteractionMessage
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user