diff --git a/discord/abc.py b/discord/abc.py index e9e8ea7cd9..e79cd7c53e 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1705,7 +1705,7 @@ async def send( if view.is_dispatchable(): state.store_view(view, ret.id) view.message = ret - view.refresh(ret.components) + view._refresh(ret.components) if delete_after is not None: await ret.delete(delay=delete_after) diff --git a/discord/interactions.py b/discord/interactions.py index fa73ec26ab..d9015b1166 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -621,8 +621,9 @@ async def edit_original_response( previous_allowed_mentions=previous_mentions, suppress=suppress_embeds, ) - if view and self.message: - self._state.prevent_view_updates_for(self.message.id) + _target = self.message or self._original_response + if view and _target: + self._state.prevent_view_updates_for(_target.id) adapter = async_context.get() http = self._state.http data = await adapter.edit_original_interaction_response( @@ -641,7 +642,7 @@ async def edit_original_response( message = InteractionMessage(state=state, channel=self.channel, data=data) # type: ignore if view: if not view.is_finished(): - view.refresh(message.components) + view._refresh(message.components) if view.is_dispatchable(): self._state.store_view(view, message.id) @@ -1308,7 +1309,7 @@ async def edit_message( raise InteractionResponded(self._parent) parent = self._parent - msg = parent.message + msg = parent.message or parent._original_response state = parent._state message_id = msg.id if msg else None if parent.type not in (InteractionType.component, InteractionType.modal_submit): diff --git a/discord/message.py b/discord/message.py index cf9a6ea27b..1b04a4c594 100644 --- a/discord/message.py +++ b/discord/message.py @@ -1917,7 +1917,7 @@ async def edit( if view and not view.is_finished(): view.message = message - view.refresh(message.components) + view._refresh(message.components) if view.is_dispatchable(): self._state.store_view(view, self.id) @@ -2586,7 +2586,7 @@ async def edit(self, **fields: Any) -> Message | None: msg = self._state.create_message(channel=self.channel, data=data) # type: ignore if view and not view.is_finished(): view.message = msg - view.refresh(msg.components) + view._refresh(msg.components) if view.is_dispatchable(): self._state.store_view(view, self.id) return msg diff --git a/discord/ui/modal.py b/discord/ui/modal.py index 1051156f80..83d4bbd34d 100644 --- a/discord/ui/modal.py +++ b/discord/ui/modal.py @@ -365,7 +365,7 @@ def remove_item(self, item: InputText) -> Self: pass return self - def refresh(self, interaction: Interaction, data: list[ComponentPayload]): + def _refresh(self, interaction: Interaction, data: list[ComponentPayload]): components = [ component for parent_component in data @@ -449,7 +449,7 @@ def add_item(self, item: ModalItem) -> Self: super().add_item(item) return self - def refresh(self, interaction: Interaction, data: list[ComponentPayload]): + def _refresh(self, interaction: Interaction, data: list[ComponentPayload]): for component, child in zip(data, self.children): child.refresh_from_modal(interaction, component) @@ -521,7 +521,7 @@ async def dispatch(self, user_id: int, custom_id: str, interaction: Interaction) try: components = interaction.data["components"] - modal.refresh(interaction, components) + modal._refresh(interaction, components) await modal.callback(interaction) self.remove_modal(modal, user_id) except Exception as e: diff --git a/discord/ui/view.py b/discord/ui/view.py index 870cfec72f..c9999c4013 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -27,6 +27,7 @@ import asyncio import contextlib +import logging import os import sys import time @@ -80,6 +81,8 @@ from ..state import ConnectionState from ..types.components import Component as ComponentPayload +_log = logging.getLogger(__name__) + V = TypeVar("V", bound="BaseView", covariant=True) @@ -739,7 +742,7 @@ def clear_items(self) -> Self: self.__weights.clear() return self - def refresh(self, components: list[Component]): + 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 @@ -918,7 +921,7 @@ def add_item(self, item: ViewItem[V]) -> Self: super().add_item(item) return self - def refresh(self, components: list[Component]): + def _refresh(self, components: list[Component]): # Refreshes view data using discord's values # Assumes the components and items are identical if not components: @@ -1022,4 +1025,9 @@ def update_from_message(self, message_id: int, components: list[ComponentPayload # pre-req: is_message_tracked == true view = self._synced_message_views[message_id] components = [_component_factory(d, state=self._state) for d in components] - view.refresh(components) + try: + view._refresh(components) + except Exception: + _log.exception( + f"Failed to refresh View {view} from Message {message_id} due to mismatched state. Items may not have complete data." + ) diff --git a/discord/webhook/async_.py b/discord/webhook/async_.py index d7f9260289..3f53fc6191 100644 --- a/discord/webhook/async_.py +++ b/discord/webhook/async_.py @@ -1928,7 +1928,7 @@ async def send( if self.parent and not view.parent: view.parent = self.parent if msg: - view.refresh(msg.components) + view._refresh(msg.components) if view.is_dispatchable(): self._state.store_view(view, message_id) @@ -2139,7 +2139,7 @@ async def edit_message( message = self._create_message(data) if view and not view.is_finished(): view.message = message - view.refresh(message.components) + view._refresh(message.components) if view.is_dispatchable(): self._state.store_view(view, message_id) return message