mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-09-09 11:17:06 +00:00
Add support for Modal Interactions
This commit is contained in:
@ -29,6 +29,7 @@ from itertools import groupby
|
||||
|
||||
import traceback
|
||||
import asyncio
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
@ -40,6 +41,7 @@ from ..components import (
|
||||
Button as ButtonComponent,
|
||||
SelectMenu as SelectComponent,
|
||||
)
|
||||
from ..utils import MISSING
|
||||
|
||||
__all__ = (
|
||||
'View',
|
||||
@ -50,7 +52,12 @@ if TYPE_CHECKING:
|
||||
from ..interactions import Interaction
|
||||
from ..message import Message
|
||||
from ..types.components import Component as ComponentPayload
|
||||
from ..types.interactions import ModalSubmitComponentInteractionData as ModalSubmitComponentInteractionDataPayload
|
||||
from ..state import ConnectionState
|
||||
from .modal import Modal
|
||||
|
||||
|
||||
_log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _walk_all_components(components: List[Component]) -> Iterator[Component]:
|
||||
@ -138,6 +145,7 @@ class View:
|
||||
"""
|
||||
|
||||
__discord_ui_view__: ClassVar[bool] = True
|
||||
__discord_ui_modal__: ClassVar[bool] = False
|
||||
__view_children_items__: ClassVar[List[ItemCallbackType]] = []
|
||||
|
||||
def __init_subclass__(cls) -> None:
|
||||
@ -152,16 +160,19 @@ class View:
|
||||
|
||||
cls.__view_children_items__ = children
|
||||
|
||||
def __init__(self, *, timeout: Optional[float] = 180.0):
|
||||
self.timeout = timeout
|
||||
self.children: List[Item] = []
|
||||
def _init_children(self) -> List[Item]:
|
||||
children = []
|
||||
for func in self.__view_children_items__:
|
||||
item: Item = func.__discord_ui_model_type__(**func.__discord_ui_model_kwargs__)
|
||||
item.callback = partial(func, self, item)
|
||||
item.callback = partial(func, self, item) # type: ignore
|
||||
item._view = self
|
||||
setattr(self, func.__name__, item)
|
||||
self.children.append(item)
|
||||
children.append(item)
|
||||
return children
|
||||
|
||||
def __init__(self, *, timeout: Optional[float] = 180.0):
|
||||
self.timeout = timeout
|
||||
self.children: List[Item] = self._init_children()
|
||||
self.__weights = _ViewWeights(self.children)
|
||||
loop = asyncio.get_running_loop()
|
||||
self.id: str = os.urandom(16).hex()
|
||||
@ -464,6 +475,8 @@ class ViewStore:
|
||||
self._views: Dict[Tuple[int, Optional[int], str], Tuple[View, Item]] = {}
|
||||
# message_id: View
|
||||
self._synced_message_views: Dict[int, View] = {}
|
||||
# custom_id: Modal
|
||||
self._modals: Dict[str, Modal] = {}
|
||||
self._state: ConnectionState = state
|
||||
|
||||
@property
|
||||
@ -487,6 +500,10 @@ class ViewStore:
|
||||
del self._views[k]
|
||||
|
||||
def add_view(self, view: View, message_id: Optional[int] = None):
|
||||
if view.__discord_ui_modal__:
|
||||
self._modals[view.custom_id] = view # type: ignore
|
||||
return
|
||||
|
||||
self.__verify_integrity()
|
||||
|
||||
view._start_listening_from_store(self)
|
||||
@ -498,6 +515,10 @@ class ViewStore:
|
||||
self._synced_message_views[message_id] = view
|
||||
|
||||
def remove_view(self, view: View):
|
||||
if view.__discord_ui_modal__:
|
||||
self._modals.pop(view.custom_id, None) # type: ignore
|
||||
return
|
||||
|
||||
for item in view.children:
|
||||
if item.is_dispatchable():
|
||||
self._views.pop((item.type.value, item.custom_id), None) # type: ignore
|
||||
@ -507,7 +528,7 @@ class ViewStore:
|
||||
del self._synced_message_views[key]
|
||||
break
|
||||
|
||||
def dispatch(self, component_type: int, custom_id: str, interaction: Interaction):
|
||||
def dispatch_view(self, component_type: int, custom_id: str, interaction: Interaction):
|
||||
self.__verify_integrity()
|
||||
message_id: Optional[int] = interaction.message and interaction.message.id
|
||||
key = (component_type, message_id, custom_id)
|
||||
@ -518,9 +539,18 @@ class ViewStore:
|
||||
return
|
||||
|
||||
view, item = value
|
||||
item.refresh_state(interaction)
|
||||
item.refresh_state(interaction.data) # type: ignore
|
||||
view._dispatch_item(item, interaction)
|
||||
|
||||
def dispatch_modal(self, custom_id: str, interaction: Interaction, components: List[ModalSubmitComponentInteractionDataPayload]):
|
||||
modal = self._modals.get(custom_id)
|
||||
if modal is None:
|
||||
_log.debug("Modal interaction referencing unknown custom_id %s. Discarding", custom_id)
|
||||
return
|
||||
|
||||
modal.refresh(components)
|
||||
modal._dispatch_submit(interaction)
|
||||
|
||||
def is_message_tracked(self, message_id: int):
|
||||
return message_id in self._synced_message_views
|
||||
|
||||
|
Reference in New Issue
Block a user