mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-10-18 04:00:39 +00:00
Handle resolved data for modal components and types
This commit is contained in:
@@ -828,7 +828,8 @@ class ConnectionState(Generic[ClientT]):
|
|||||||
inner_data = data['data']
|
inner_data = data['data']
|
||||||
custom_id = inner_data['custom_id']
|
custom_id = inner_data['custom_id']
|
||||||
components = inner_data['components']
|
components = inner_data['components']
|
||||||
self._view_store.dispatch_modal(custom_id, interaction, components)
|
resolved = inner_data.get('resolved', {})
|
||||||
|
self._view_store.dispatch_modal(custom_id, interaction, components, resolved)
|
||||||
self.dispatch('interaction', interaction)
|
self.dispatch('interaction', interaction)
|
||||||
|
|
||||||
def parse_presence_update(self, data: gw.PresenceUpdateEvent) -> None:
|
def parse_presence_update(self, data: gw.PresenceUpdateEvent) -> None:
|
||||||
|
@@ -36,6 +36,7 @@ from .role import Role
|
|||||||
from .snowflake import Snowflake
|
from .snowflake import Snowflake
|
||||||
from .user import User
|
from .user import User
|
||||||
from .guild import GuildFeature
|
from .guild import GuildFeature
|
||||||
|
from .components import ComponentBase
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .message import Message
|
from .message import Message
|
||||||
@@ -204,19 +205,19 @@ class SelectMessageComponentInteractionData(_BaseMessageComponentInteractionData
|
|||||||
MessageComponentInteractionData = Union[ButtonMessageComponentInteractionData, SelectMessageComponentInteractionData]
|
MessageComponentInteractionData = Union[ButtonMessageComponentInteractionData, SelectMessageComponentInteractionData]
|
||||||
|
|
||||||
|
|
||||||
class ModalSubmitTextInputInteractionData(TypedDict):
|
class ModalSubmitTextInputInteractionData(ComponentBase):
|
||||||
type: Literal[4]
|
type: Literal[4]
|
||||||
custom_id: str
|
custom_id: str
|
||||||
value: str
|
value: str
|
||||||
|
|
||||||
|
|
||||||
class ModalSubmitStringSelectInteractionData(TypedDict):
|
class ModalSubmitSelectInteractionData(ComponentBase):
|
||||||
type: Literal[3]
|
type: Literal[3, 5, 6, 7, 8]
|
||||||
custom_id: str
|
custom_id: str
|
||||||
values: List[str]
|
values: List[str]
|
||||||
|
|
||||||
|
|
||||||
ModalSubmitComponentItemInteractionData = Union[ModalSubmitTextInputInteractionData, ModalSubmitStringSelectInteractionData]
|
ModalSubmitComponentItemInteractionData = Union[ModalSubmitSelectInteractionData, ModalSubmitTextInputInteractionData]
|
||||||
|
|
||||||
|
|
||||||
class ModalSubmitActionRowInteractionData(TypedDict):
|
class ModalSubmitActionRowInteractionData(TypedDict):
|
||||||
@@ -224,19 +225,27 @@ class ModalSubmitActionRowInteractionData(TypedDict):
|
|||||||
components: List[ModalSubmitComponentItemInteractionData]
|
components: List[ModalSubmitComponentItemInteractionData]
|
||||||
|
|
||||||
|
|
||||||
class ModalSubmitLabelInteractionData(TypedDict):
|
class ModalSubmitTextDisplayInteractionData(ComponentBase):
|
||||||
|
type: Literal[10]
|
||||||
|
content: str
|
||||||
|
|
||||||
|
|
||||||
|
class ModalSubmitLabelInteractionData(ComponentBase):
|
||||||
type: Literal[18]
|
type: Literal[18]
|
||||||
component: ModalSubmitComponentItemInteractionData
|
component: ModalSubmitComponentItemInteractionData
|
||||||
|
|
||||||
|
|
||||||
ModalSubmitComponentInteractionData = Union[
|
ModalSubmitComponentInteractionData = Union[
|
||||||
ModalSubmitLabelInteractionData, ModalSubmitActionRowInteractionData, ModalSubmitComponentItemInteractionData
|
ModalSubmitActionRowInteractionData,
|
||||||
|
ModalSubmitTextDisplayInteractionData,
|
||||||
|
ModalSubmitLabelInteractionData,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class ModalSubmitInteractionData(TypedDict):
|
class ModalSubmitInteractionData(TypedDict):
|
||||||
custom_id: str
|
custom_id: str
|
||||||
components: List[ModalSubmitComponentInteractionData]
|
components: List[ModalSubmitComponentInteractionData]
|
||||||
|
resolved: NotRequired[ResolvedData]
|
||||||
|
|
||||||
|
|
||||||
InteractionData = Union[
|
InteractionData = Union[
|
||||||
|
@@ -45,6 +45,7 @@ if TYPE_CHECKING:
|
|||||||
from .action_row import ActionRow
|
from .action_row import ActionRow
|
||||||
from .container import Container
|
from .container import Container
|
||||||
from .dynamic import DynamicItem
|
from .dynamic import DynamicItem
|
||||||
|
from ..app_commands.namespace import ResolveKey
|
||||||
|
|
||||||
I = TypeVar('I', bound='Item[Any]')
|
I = TypeVar('I', bound='Item[Any]')
|
||||||
V = TypeVar('V', bound='BaseView', covariant=True)
|
V = TypeVar('V', bound='BaseView', covariant=True)
|
||||||
@@ -97,6 +98,9 @@ class Item(Generic[V]):
|
|||||||
def _refresh_component(self, component: Component) -> None:
|
def _refresh_component(self, component: Component) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _handle_submit(self, interaction: Interaction, data: Dict[str, Any], resolved: Dict[ResolveKey, Any]) -> None:
|
||||||
|
return self._refresh_state(interaction, data)
|
||||||
|
|
||||||
def _refresh_state(self, interaction: Interaction, data: Dict[str, Any]) -> None:
|
def _refresh_state(self, interaction: Interaction, data: Dict[str, Any]) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@@ -36,12 +36,17 @@ from .item import Item
|
|||||||
from .view import BaseView
|
from .view import BaseView
|
||||||
from .select import BaseSelect
|
from .select import BaseSelect
|
||||||
from .text_input import TextInput
|
from .text_input import TextInput
|
||||||
|
from ..interactions import Namespace
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
from ..interactions import Interaction
|
from ..interactions import Interaction
|
||||||
from ..types.interactions import ModalSubmitComponentInteractionData as ModalSubmitComponentInteractionDataPayload
|
from ..types.interactions import (
|
||||||
|
ModalSubmitComponentInteractionData as ModalSubmitComponentInteractionDataPayload,
|
||||||
|
ResolvedData as ResolvedDataPayload,
|
||||||
|
)
|
||||||
|
from ..app_commands.namespace import ResolveKey
|
||||||
|
|
||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
@@ -168,27 +173,41 @@ class Modal(BaseView):
|
|||||||
"""
|
"""
|
||||||
_log.error('Ignoring exception in modal %r:', self, exc_info=error)
|
_log.error('Ignoring exception in modal %r:', self, exc_info=error)
|
||||||
|
|
||||||
def _refresh(self, interaction: Interaction, components: Sequence[ModalSubmitComponentInteractionDataPayload]) -> None:
|
def _refresh(
|
||||||
|
self,
|
||||||
|
interaction: Interaction,
|
||||||
|
components: Sequence[ModalSubmitComponentInteractionDataPayload],
|
||||||
|
resolved: Dict[ResolveKey, Any],
|
||||||
|
) -> None:
|
||||||
for component in components:
|
for component in components:
|
||||||
if component['type'] == 1:
|
if component['type'] == 1:
|
||||||
self._refresh(interaction, component['components'])
|
self._refresh(interaction, component['components'], resolved) # type: ignore
|
||||||
elif component['type'] == 18:
|
elif component['type'] == 18:
|
||||||
self._refresh(interaction, [component['component']])
|
self._refresh(interaction, [component['component']], resolved) # type: ignore
|
||||||
else:
|
else:
|
||||||
custom_id = component.get('custom_id')
|
custom_id = component.get('custom_id')
|
||||||
if custom_id is None:
|
if custom_id is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
item = find(lambda i: getattr(i, 'custom_id', None) == custom_id, self.walk_children())
|
item = find(
|
||||||
|
lambda i: getattr(i, 'custom_id', None) == custom_id,
|
||||||
|
self.walk_children(),
|
||||||
|
)
|
||||||
if item is None:
|
if item is None:
|
||||||
_log.debug('Modal interaction referencing unknown item custom_id %s. Discarding', custom_id)
|
_log.debug('Modal interaction referencing unknown item custom_id %s. Discarding', custom_id)
|
||||||
continue
|
continue
|
||||||
item._refresh_state(interaction, component) # type: ignore
|
|
||||||
|
|
||||||
async def _scheduled_task(self, interaction: Interaction, components: List[ModalSubmitComponentInteractionDataPayload]):
|
item._handle_submit(interaction, component, resolved) # type: ignore
|
||||||
|
|
||||||
|
async def _scheduled_task(
|
||||||
|
self,
|
||||||
|
interaction: Interaction,
|
||||||
|
components: List[ModalSubmitComponentInteractionDataPayload],
|
||||||
|
resolved: Dict[ResolveKey, Any],
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
self._refresh_timeout()
|
self._refresh_timeout()
|
||||||
self._refresh(interaction, components)
|
self._refresh(interaction, components, resolved)
|
||||||
|
|
||||||
allow = await self.interaction_check(interaction)
|
allow = await self.interaction_check(interaction)
|
||||||
if not allow:
|
if not allow:
|
||||||
@@ -225,10 +244,18 @@ class Modal(BaseView):
|
|||||||
return components
|
return components
|
||||||
|
|
||||||
def _dispatch_submit(
|
def _dispatch_submit(
|
||||||
self, interaction: Interaction, components: List[ModalSubmitComponentInteractionDataPayload]
|
self,
|
||||||
|
interaction: Interaction,
|
||||||
|
components: List[ModalSubmitComponentInteractionDataPayload],
|
||||||
|
resolved: ResolvedDataPayload,
|
||||||
) -> asyncio.Task[None]:
|
) -> asyncio.Task[None]:
|
||||||
|
try:
|
||||||
|
namespace = Namespace._get_resolved_items(interaction, resolved)
|
||||||
|
except KeyError:
|
||||||
|
namespace = {}
|
||||||
|
|
||||||
return asyncio.create_task(
|
return asyncio.create_task(
|
||||||
self._scheduled_task(interaction, components), name=f'discord-ui-modal-dispatch-{self.id}'
|
self._scheduled_task(interaction, components, namespace), name=f'discord-ui-modal-dispatch-{self.id}'
|
||||||
)
|
)
|
||||||
|
|
||||||
def to_dict(self) -> Dict[str, Any]:
|
def to_dict(self) -> Dict[str, Any]:
|
||||||
|
@@ -78,6 +78,7 @@ if TYPE_CHECKING:
|
|||||||
from ..types.interactions import SelectMessageComponentInteractionData
|
from ..types.interactions import SelectMessageComponentInteractionData
|
||||||
from ..app_commands import AppCommandChannel, AppCommandThread
|
from ..app_commands import AppCommandChannel, AppCommandThread
|
||||||
from ..interactions import Interaction
|
from ..interactions import Interaction
|
||||||
|
from ..app_commands.namespace import ResolveKey
|
||||||
|
|
||||||
ValidSelectType: TypeAlias = Literal[
|
ValidSelectType: TypeAlias = Literal[
|
||||||
ComponentType.string_select,
|
ComponentType.string_select,
|
||||||
@@ -356,7 +357,24 @@ class BaseSelect(Item[V]):
|
|||||||
def _refresh_component(self, component: SelectMenu) -> None:
|
def _refresh_component(self, component: SelectMenu) -> None:
|
||||||
self._underlying = component
|
self._underlying = component
|
||||||
|
|
||||||
def _refresh_state(self, interaction: Interaction, data: SelectMessageComponentInteractionData) -> None:
|
def _handle_submit(
|
||||||
|
self, interaction: Interaction, data: SelectMessageComponentInteractionData, resolved: Dict[ResolveKey, Any]
|
||||||
|
) -> None:
|
||||||
|
payload: List[PossibleValue]
|
||||||
|
values = selected_values.get({})
|
||||||
|
string_values = data.get('values', [])
|
||||||
|
payload = [v for k, v in resolved.items() if k.id in string_values]
|
||||||
|
if not payload:
|
||||||
|
payload = list(string_values)
|
||||||
|
|
||||||
|
self._values = values[self.custom_id] = payload
|
||||||
|
selected_values.set(values)
|
||||||
|
|
||||||
|
def _refresh_state(
|
||||||
|
self,
|
||||||
|
interaction: Interaction,
|
||||||
|
data: SelectMessageComponentInteractionData,
|
||||||
|
) -> None:
|
||||||
values = selected_values.get({})
|
values = selected_values.get({})
|
||||||
payload: List[PossibleValue]
|
payload: List[PossibleValue]
|
||||||
try:
|
try:
|
||||||
@@ -366,7 +384,7 @@ class BaseSelect(Item[V]):
|
|||||||
)
|
)
|
||||||
payload = list(resolved.values())
|
payload = list(resolved.values())
|
||||||
except KeyError:
|
except KeyError:
|
||||||
payload = data.get('values', []) # type: ignore
|
payload = list(data.get('values', []))
|
||||||
|
|
||||||
self._values = values[self.custom_id] = payload
|
self._values = values[self.custom_id] = payload
|
||||||
selected_values.set(values)
|
selected_values.set(values)
|
||||||
|
@@ -85,7 +85,10 @@ if TYPE_CHECKING:
|
|||||||
from ..interactions import Interaction
|
from ..interactions import Interaction
|
||||||
from ..message import Message
|
from ..message import Message
|
||||||
from ..types.components import ComponentBase as ComponentBasePayload
|
from ..types.components import ComponentBase as ComponentBasePayload
|
||||||
from ..types.interactions import ModalSubmitComponentInteractionData as ModalSubmitComponentInteractionDataPayload
|
from ..types.interactions import (
|
||||||
|
ModalSubmitComponentInteractionData as ModalSubmitComponentInteractionDataPayload,
|
||||||
|
ResolvedData as ResolvedDataPayload,
|
||||||
|
)
|
||||||
from ..state import ConnectionState
|
from ..state import ConnectionState
|
||||||
from .modal import Modal
|
from .modal import Modal
|
||||||
|
|
||||||
@@ -1041,13 +1044,14 @@ class ViewStore:
|
|||||||
custom_id: str,
|
custom_id: str,
|
||||||
interaction: Interaction,
|
interaction: Interaction,
|
||||||
components: List[ModalSubmitComponentInteractionDataPayload],
|
components: List[ModalSubmitComponentInteractionDataPayload],
|
||||||
|
resolved: ResolvedDataPayload,
|
||||||
) -> None:
|
) -> None:
|
||||||
modal = self._modals.get(custom_id)
|
modal = self._modals.get(custom_id)
|
||||||
if modal is None:
|
if modal is None:
|
||||||
_log.debug('Modal interaction referencing unknown custom_id %s. Discarding', custom_id)
|
_log.debug('Modal interaction referencing unknown custom_id %s. Discarding', custom_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
self.add_task(modal._dispatch_submit(interaction, components))
|
self.add_task(modal._dispatch_submit(interaction, components, resolved))
|
||||||
|
|
||||||
def remove_interaction_mapping(self, interaction_id: int) -> None:
|
def remove_interaction_mapping(self, interaction_id: int) -> None:
|
||||||
# This is called before re-adding the view
|
# This is called before re-adding the view
|
||||||
|
Reference in New Issue
Block a user