diff --git a/CHANGELOG.md b/CHANGELOG.md index c5696f04d6..49122efaf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ These changes are available on the `master` branch, but have not yet been releas ### Changed +- Changed `BaseView.on_timeout` and `Paginator.on_timeout` behavior: views no longer + raise errors on timeout. + ([#3019](https://github.com/Pycord-Development/pycord/pull/3019)) + ### Fixed - Fixed breaking change in `ui.Select` Generic typing by adding default values to diff --git a/discord/ext/pages/pagination.py b/discord/ext/pages/pagination.py index 8dbf1c0f43..5db5c80fa4 100644 --- a/discord/ext/pages/pagination.py +++ b/discord/ext/pages/pagination.py @@ -24,6 +24,7 @@ from __future__ import annotations +import contextlib from typing import List import discord @@ -597,11 +598,12 @@ async def on_timeout(self) -> None: page = self.pages[self.current_page] page = self.get_page_content(page) files = page.update_files() - await self.message.edit( - view=self, - files=files or [], - attachments=[], - ) + async with contextlib.suppress(discord.HTTPException): + await self.message.edit( + view=self, + files=files or [], + attachments=[], + ) async def disable( self, @@ -709,7 +711,9 @@ async def goto_page( try: if interaction: - await interaction.response.defer() # needed to force webhook message edit route for files kwarg support + await ( + interaction.response.defer() + ) # needed to force webhook message edit route for files kwarg support await interaction.followup.edit_message( message_id=self.message.id, content=page.content, diff --git a/discord/ui/view.py b/discord/ui/view.py index 9d03339d09..ab2224e347 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -26,6 +26,7 @@ from __future__ import annotations import asyncio +import contextlib import os import sys import time @@ -42,6 +43,8 @@ from typing_extensions import Self +import discord + from ..components import ActionRow as ActionRowComponent from ..components import Button as ButtonComponent from ..components import Component @@ -55,7 +58,6 @@ from ..components import TextDisplay as TextDisplayComponent from ..components import Thumbnail as ThumbnailComponent from ..components import _component_factory -from ..utils import find from .core import ItemInterface from .item import ItemCallbackType, ViewItem @@ -96,7 +98,6 @@ def _walk_all_components_v2(components: list[Component]) -> Iterator[Component]: def _component_to_item(component: Component) -> ViewItem[V]: - if isinstance(component, ButtonComponent): from .button import Button @@ -309,7 +310,8 @@ async def on_timeout(self) -> None: message = self.message if message: - m = await message.edit(view=self) + async with contextlib.suppress(discord.HTTPException): + m = await message.edit(view=self) if m: self._message = m @@ -681,7 +683,7 @@ def add_item(self, item: ViewItem[V]) -> Self: if item._underlying.is_v2(): raise ValueError( - f"cannot use V2 components in View. Use DesignerView instead." + "cannot use V2 components in View. Use DesignerView instead." ) if isinstance(item._underlying, ActionRowComponent): for i in item.children: @@ -718,7 +720,9 @@ def clear_items(self) -> None: def refresh(self, components: list[Component]): # This is pretty hacky at the moment old_state: dict[tuple[int, str], ViewItem[V]] = { - (item.type.value, item.custom_id): item for item in self.children if item.is_dispatchable() # type: ignore + (item.type.value, item.custom_id): item + for item in self.children + if item.is_dispatchable() # type: ignore } children: list[ViewItem[V]] = [ item for item in self.children if not item.is_dispatchable() @@ -878,7 +882,7 @@ def add_item(self, item: ViewItem[V]) -> Self: if isinstance(item._underlying, (SelectComponent, ButtonComponent)): raise ValueError( - f"cannot add Select or Button to DesignerView directly. Use ActionRow instead." + "cannot add Select or Button to DesignerView directly. Use ActionRow instead." ) super().add_item(item) @@ -942,7 +946,10 @@ def add_view(self, view: BaseView, message_id: int | None = None): view._start_listening_from_store(self) for item in view.walk_children(): if item.is_storable(): - self._views[(item.type.value, message_id, item.custom_id)] = (view, item) # type: ignore + self._views[(item.type.value, message_id, item.custom_id)] = ( + view, + item, + ) # type: ignore if message_id is not None: self._synced_message_views[message_id] = view