mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-06-03 10:32:42 +00:00
Ensure views added to Client.add_view are persistent views
This commit is contained in:
parent
c811932ca7
commit
7c40e83d10
@ -1451,9 +1451,15 @@ class Client:
|
||||
-------
|
||||
TypeError
|
||||
A view was not passed.
|
||||
ValueError
|
||||
The view is not persistent. A persistent view has no timeout
|
||||
and all their components have an explicitly provided custom_id.
|
||||
"""
|
||||
|
||||
if not isinstance(view, View):
|
||||
raise TypeError(f'expected an instance of View not {view.__class__!r}')
|
||||
|
||||
if not view.is_persistent():
|
||||
raise ValueError('View is not persistent. Items need to have a custom_id set and View must have no timeout')
|
||||
|
||||
self._connection.store_view(view, message_id)
|
||||
|
@ -98,6 +98,7 @@ class Button(Item[V]):
|
||||
if custom_id is not None and url is not None:
|
||||
raise TypeError('cannot mix both url and custom_id with Button')
|
||||
|
||||
self._provided_custom_id = custom_id is not None
|
||||
if url is None and custom_id is None:
|
||||
custom_id = os.urandom(16).hex()
|
||||
|
||||
|
@ -56,6 +56,13 @@ class Item(Generic[V]):
|
||||
self._view: Optional[V] = None
|
||||
self._row: Optional[int] = None
|
||||
self._rendered_row: Optional[int] = None
|
||||
# This works mostly well but there is a gotcha with
|
||||
# the interaction with from_component, since that technically provides
|
||||
# a custom_id most dispatchable items would get this set to True even though
|
||||
# it might not be provided by the library user. However, this edge case doesn't
|
||||
# actually affect the intended purpose of this check because from_component is
|
||||
# only called upon edit and we're mainly interested during initial creation time.
|
||||
self._provided_custom_id: bool = False
|
||||
|
||||
def to_component_dict(self) -> Dict[str, Any]:
|
||||
raise NotImplementedError
|
||||
@ -77,6 +84,9 @@ class Item(Generic[V]):
|
||||
def is_dispatchable(self) -> bool:
|
||||
return False
|
||||
|
||||
def is_persistent(self) -> bool:
|
||||
return self._provided_custom_id
|
||||
|
||||
def __repr__(self) -> str:
|
||||
attrs = ' '.join(f'{key}={getattr(self, key)!r}' for key in self.__item_repr_attributes__)
|
||||
return f'<{self.__class__.__name__} {attrs}>'
|
||||
|
@ -101,6 +101,7 @@ class Select(Item[V]):
|
||||
row: Optional[int] = None,
|
||||
) -> None:
|
||||
self._selected_values: List[str] = []
|
||||
self._provided_custom_id = custom_id is not MISSING
|
||||
custom_id = os.urandom(16).hex() if custom_id is MISSING else custom_id
|
||||
options = [] if options is MISSING else options
|
||||
self._underlying = SelectMenu._raw_construct(
|
||||
|
@ -339,6 +339,14 @@ class View:
|
||||
""":class:`bool`: Whether the view has finished interacting."""
|
||||
return self._stopped.done()
|
||||
|
||||
def is_persistent(self) -> bool:
|
||||
""":class:`bool`: Whether the view is set up as persistent.
|
||||
|
||||
A persistent view has all their components with a set ``custom_id`` and
|
||||
a :attr:`timeout` set to ``None``.
|
||||
"""
|
||||
return self.timeout is None and all(item.is_persistent() for item in self.children)
|
||||
|
||||
async def wait(self) -> bool:
|
||||
"""Waits until the view has finished interacting.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user