Skip to content

Commit a16fc23

Browse files
committed
fix: ♻️ Handle discord.HTTPException during message edits in Paginator and BaseView
1 parent 982f435 commit a16fc23

File tree

2 files changed

+33
-24
lines changed

2 files changed

+33
-24
lines changed

discord/ext/pages/pagination.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
from __future__ import annotations
2626

27+
import contextlib
2728
from typing import List
2829

2930
import discord
@@ -456,7 +457,8 @@ def __init__(
456457

457458
async def update(
458459
self,
459-
pages: None | (
460+
pages: None
461+
| (
460462
list[PageGroup]
461463
| list[Page]
462464
| list[str]
@@ -527,7 +529,7 @@ async def update(
527529
| list[str]
528530
| list[Page]
529531
| list[list[discord.Embed] | discord.Embed]
530-
) = (pages if pages is not None else self.pages)
532+
) = pages if pages is not None else self.pages
531533
self.show_menu = show_menu if show_menu is not None else self.show_menu
532534
if pages is not None and all(isinstance(pg, PageGroup) for pg in pages):
533535
self.page_groups = self.pages if self.show_menu else None
@@ -597,11 +599,12 @@ async def on_timeout(self) -> None:
597599
page = self.pages[self.current_page]
598600
page = self.get_page_content(page)
599601
files = page.update_files()
600-
await self.message.edit(
601-
view=self,
602-
files=files or [],
603-
attachments=[],
604-
)
602+
async with contextlib.suppress(discord.HTTPException):
603+
await self.message.edit(
604+
view=self,
605+
files=files or [],
606+
attachments=[],
607+
)
605608

606609
async def disable(
607610
self,
@@ -709,7 +712,9 @@ async def goto_page(
709712

710713
try:
711714
if interaction:
712-
await interaction.response.defer() # needed to force webhook message edit route for files kwarg support
715+
await (
716+
interaction.response.defer()
717+
) # needed to force webhook message edit route for files kwarg support
713718
await interaction.followup.edit_message(
714719
message_id=self.message.id,
715720
content=page.content,
@@ -952,9 +957,8 @@ async def send(
952957
ctx: Context,
953958
target: discord.abc.Messageable | None = None,
954959
target_message: str | None = None,
955-
reference: None | (
956-
discord.Message | discord.MessageReference | discord.PartialMessage
957-
) = None,
960+
reference: None
961+
| (discord.Message | discord.MessageReference | discord.PartialMessage) = None,
958962
allowed_mentions: discord.AllowedMentions | None = None,
959963
mention_author: bool | None = None,
960964
delete_after: float | None = None,

discord/ui/view.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from __future__ import annotations
2727

2828
import asyncio
29+
import contextlib
2930
import os
3031
import sys
3132
import time
@@ -42,20 +43,19 @@
4243

4344
from typing_extensions import Self
4445

46+
import discord
47+
4548
from ..components import ActionRow as ActionRowComponent
4649
from ..components import Button as ButtonComponent
47-
from ..components import Component
50+
from ..components import Component, FileComponent, _component_factory
4851
from ..components import Container as ContainerComponent
49-
from ..components import FileComponent
5052
from ..components import Label as LabelComponent
5153
from ..components import MediaGallery as MediaGalleryComponent
5254
from ..components import Section as SectionComponent
5355
from ..components import SelectMenu as SelectComponent
5456
from ..components import Separator as SeparatorComponent
5557
from ..components import TextDisplay as TextDisplayComponent
5658
from ..components import Thumbnail as ThumbnailComponent
57-
from ..components import _component_factory
58-
from ..utils import find
5959
from .core import ItemInterface
6060
from .item import ItemCallbackType, ViewItem
6161

@@ -96,7 +96,6 @@ def _walk_all_components_v2(components: list[Component]) -> Iterator[Component]:
9696

9797

9898
def _component_to_item(component: Component) -> ViewItem[V]:
99-
10099
if isinstance(component, ButtonComponent):
101100
from .button import Button
102101

@@ -309,7 +308,8 @@ async def on_timeout(self) -> None:
309308
message = self.message
310309

311310
if message:
312-
m = await message.edit(view=self)
311+
async with contextlib.suppress(discord.HTTPException):
312+
m = await message.edit(view=self)
313313
if m:
314314
self._message = m
315315

@@ -681,7 +681,7 @@ def add_item(self, item: ViewItem[V]) -> Self:
681681

682682
if item._underlying.is_v2():
683683
raise ValueError(
684-
f"cannot use V2 components in View. Use DesignerView instead."
684+
"cannot use V2 components in View. Use DesignerView instead."
685685
)
686686
if isinstance(item._underlying, ActionRowComponent):
687687
for i in item.children:
@@ -718,7 +718,9 @@ def clear_items(self) -> None:
718718
def refresh(self, components: list[Component]):
719719
# This is pretty hacky at the moment
720720
old_state: dict[tuple[int, str], ViewItem[V]] = {
721-
(item.type.value, item.custom_id): item for item in self.children if item.is_dispatchable() # type: ignore
721+
(item.type.value, item.custom_id): item
722+
for item in self.children
723+
if item.is_dispatchable() # type: ignore
722724
}
723725
children: list[ViewItem[V]] = [
724726
item for item in self.children if not item.is_dispatchable()
@@ -878,7 +880,7 @@ def add_item(self, item: ViewItem[V]) -> Self:
878880

879881
if isinstance(item._underlying, (SelectComponent, ButtonComponent)):
880882
raise ValueError(
881-
f"cannot add Select or Button to DesignerView directly. Use ActionRow instead."
883+
"cannot add Select or Button to DesignerView directly. Use ActionRow instead."
882884
)
883885

884886
super().add_item(item)
@@ -909,9 +911,9 @@ def is_components_v2(self) -> bool:
909911
class ViewStore:
910912
def __init__(self, state: ConnectionState):
911913
# (component_type, message_id, custom_id): (BaseView, ViewItem)
912-
self._views: dict[tuple[int, int | None, str], tuple[BaseView, ViewItem[V]]] = (
913-
{}
914-
)
914+
self._views: dict[
915+
tuple[int, int | None, str], tuple[BaseView, ViewItem[V]]
916+
] = {}
915917
# message_id: View
916918
self._synced_message_views: dict[int, BaseView] = {}
917919
self._state: ConnectionState = state
@@ -942,7 +944,10 @@ def add_view(self, view: BaseView, message_id: int | None = None):
942944
view._start_listening_from_store(self)
943945
for item in view.walk_children():
944946
if item.is_storable():
945-
self._views[(item.type.value, message_id, item.custom_id)] = (view, item) # type: ignore
947+
self._views[(item.type.value, message_id, item.custom_id)] = (
948+
view,
949+
item,
950+
) # type: ignore
946951

947952
if message_id is not None:
948953
self._synced_message_views[message_id] = view

0 commit comments

Comments
 (0)