mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-06-07 12:18:59 +00:00
Add a timeout callback for detecting when a View times out
This commit is contained in:
parent
97f308d219
commit
3f60997630
@ -47,6 +47,7 @@ __all__ = (
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..interactions import Interaction
|
from ..interactions import Interaction
|
||||||
from ..types.components import Component as ComponentPayload
|
from ..types.components import Component as ComponentPayload
|
||||||
|
from ..state import ConnectionState
|
||||||
|
|
||||||
|
|
||||||
def _walk_all_components(components: List[Component]) -> Iterator[Component]:
|
def _walk_all_components(components: List[Component]) -> Iterator[Component]:
|
||||||
@ -118,6 +119,7 @@ class View:
|
|||||||
|
|
||||||
self.id = os.urandom(16).hex()
|
self.id = os.urandom(16).hex()
|
||||||
self._cancel_callback: Optional[Callable[[View], None]] = None
|
self._cancel_callback: Optional[Callable[[View], None]] = None
|
||||||
|
self._timeout_handler: Optional[asyncio.TimerHandle] = None
|
||||||
self._stopped = asyncio.Event()
|
self._stopped = asyncio.Event()
|
||||||
|
|
||||||
def to_components(self) -> List[Dict[str, Any]]:
|
def to_components(self) -> List[Dict[str, Any]]:
|
||||||
@ -225,6 +227,13 @@ class View:
|
|||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
async def on_timeout(self) -> None:
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
A callback that is called when a view's timeout elapses without being explicitly stopped.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
async def _scheduled_task(self, state: Any, item: Item, interaction: Interaction):
|
async def _scheduled_task(self, state: Any, item: Item, interaction: Interaction):
|
||||||
try:
|
try:
|
||||||
allow = await self.interaction_check(interaction)
|
allow = await self.interaction_check(interaction)
|
||||||
@ -238,6 +247,15 @@ class View:
|
|||||||
if not interaction.response._responded:
|
if not interaction.response._responded:
|
||||||
await interaction.response.defer()
|
await interaction.response.defer()
|
||||||
|
|
||||||
|
def _start_listening(self, store: ViewStore) -> None:
|
||||||
|
self._cancel_callback = partial(store.remove_view)
|
||||||
|
if self.timeout:
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
self._timeout_handler = loop.call_later(self.timeout, self.dispatch_timeout)
|
||||||
|
|
||||||
|
def dispatch_timeout(self):
|
||||||
|
asyncio.create_task(self.on_timeout(), name=f'discord-ui-view-timeout-{self.id}')
|
||||||
|
|
||||||
def dispatch(self, state: Any, item: Item, interaction: Interaction):
|
def dispatch(self, state: Any, item: Item, interaction: Interaction):
|
||||||
asyncio.create_task(self._scheduled_task(state, item, interaction), name=f'discord-ui-view-dispatch-{self.id}')
|
asyncio.create_task(self._scheduled_task(state, item, interaction), name=f'discord-ui-view-dispatch-{self.id}')
|
||||||
|
|
||||||
@ -268,6 +286,9 @@ class View:
|
|||||||
This operation cannot be undone.
|
This operation cannot be undone.
|
||||||
"""
|
"""
|
||||||
self._stopped.set()
|
self._stopped.set()
|
||||||
|
if self._timeout_handler:
|
||||||
|
self._timeout_handler.cancel()
|
||||||
|
|
||||||
if self._cancel_callback:
|
if self._cancel_callback:
|
||||||
self._cancel_callback(self)
|
self._cancel_callback(self)
|
||||||
|
|
||||||
@ -280,12 +301,12 @@ class View:
|
|||||||
|
|
||||||
|
|
||||||
class ViewStore:
|
class ViewStore:
|
||||||
def __init__(self, state):
|
def __init__(self, state: ConnectionState):
|
||||||
# (component_type, custom_id): (View, Item, Expiry)
|
# (component_type, custom_id): (View, Item, Expiry)
|
||||||
self._views: Dict[Tuple[int, str], Tuple[View, Item, Optional[float]]] = {}
|
self._views: Dict[Tuple[int, str], Tuple[View, Item, Optional[float]]] = {}
|
||||||
# message_id: View
|
# message_id: View
|
||||||
self._synced_message_views: Dict[int, View] = {}
|
self._synced_message_views: Dict[int, View] = {}
|
||||||
self._state = state
|
self._state: ConnectionState = state
|
||||||
|
|
||||||
def __verify_integrity(self):
|
def __verify_integrity(self):
|
||||||
to_remove: List[Tuple[int, str]] = []
|
to_remove: List[Tuple[int, str]] = []
|
||||||
@ -301,7 +322,7 @@ class ViewStore:
|
|||||||
self.__verify_integrity()
|
self.__verify_integrity()
|
||||||
|
|
||||||
expiry = view._expires_at
|
expiry = view._expires_at
|
||||||
view._cancel_callback = partial(self.remove_view)
|
view._start_listening(self)
|
||||||
for item in view.children:
|
for item in view.children:
|
||||||
if item.is_dispatchable():
|
if item.is_dispatchable():
|
||||||
self._views[(item.type.value, item.custom_id)] = (view, item, expiry) # type: ignore
|
self._views[(item.type.value, item.custom_id)] = (view, item, expiry) # type: ignore
|
||||||
|
Loading…
x
Reference in New Issue
Block a user