|
from typing import Any, TYPE_CHECKING, List |
|
|
|
import asyncio |
|
from discord import ui, Interaction |
|
|
|
|
|
|
|
class GlobalView(ui.View): |
|
def __init__( |
|
self, |
|
author_id: int, |
|
*, |
|
absolute_timeout: bool = False, |
|
timeout: float = 180.0 |
|
) -> None: |
|
self.author_id: int = author_id |
|
# call the original __init__ |
|
# original handles the items and timeout |
|
# so we don't need to do that ourselves. |
|
# we are setting the timeout to None if absolute_timeout is True |
|
# since we handle the timeout in that case. |
|
super().__init__(timeout=timeout if not absolute_timeout else None) |
|
# author_id is a custom thing |
|
# so we need to handle that, which we did above. |
|
|
|
# absolute_timeout is also a custom thing. |
|
# it's for stopping the view exactly at the timeout you set |
|
# since the timeout resets on interaction. |
|
# we handle that here. |
|
# first check if there is even a timeout |
|
# if not, we do nothing. |
|
if timeout is not None and absolute_timeout: |
|
loop = asyncio.get_event_loop() |
|
# here we tell asyncio call to call View.stop and on_timeout after <timeout> |
|
def call_later_callback(): |
|
# stop the view |
|
self.stop() |
|
# call on_timeout |
|
loop.create_task(self.on_timeout()) |
|
|
|
loop.call_later(timeout, call_later_callback) |
|
|
|
|
|
# method that disables all items |
|
# you still need to edit the message. |
|
def disable_all_items(self): |
|
for item in self.children: |
|
if hasattr(item, "disabled"): |
|
item.disabled = True |
|
|
|
# global view timeout handler |
|
async def on_timeout(self): |
|
# defining a list of label: custom_id |
|
# so we can know which items timed out |
|
formatted_items: List[str] = [ |
|
f"{item.label}: {getattr(item, 'custom_id', None)}" |
|
for item in self.children |
|
] |
|
print( |
|
f "A timeout occurred in the following view: {self.__class__!r}\n", |
|
f"Timed out with items: {', '.join(formatted_items)}" |
|
) |
|
|
|
# global view error handler |
|
async def on_error( |
|
self, |
|
interaction: Interaction, |
|
error: Exception, |
|
item: ui.Item |
|
) -> Any: |
|
print( |
|
f"An error occurred in the following view: {self.__class__!r}\n", |
|
f"With item: {item!r}" |
|
) |
|
# do original implementation |
|
await super().on_error(interaction, error, item) |
|
|
|
# global interaction (view) check |
|
async def interaction_check(self, interaction: Interaction) -> bool: |
|
# send a message if the id of the interaction user |
|
# and view owner don't match |
|
if interaction.user.id != self.author_id: |
|
await interaction.response.send_message("This is not your view!") |
|
# return False so that the lib doesn't invoke the item callback. |
|
return False |
|
|
|
# else return True, we handled it above. |
|
return True |
thank you soheab