Skip to content

Commit 1aaa721

Browse files
NeloBlivionDorukyumpre-commit-ci[bot]Paillat-devLulalaby
authored
fix: Prevent crashes from View.refresh (#3059)
Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Paillat <paillat@pycord.dev> Co-authored-by: Lala Sabathil <lala@pycord.dev>
1 parent fc25e1b commit 1aaa721

File tree

7 files changed

+26
-15
lines changed

7 files changed

+26
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ These changes are available on the `master` branch, but have not yet been releas
3434
([#3178](https://github.com/Pycord-Development/pycord/pull/3178))
3535
- Fixed a `KeyError` when fetching an app's information or checking for app ownership
3636
with `is_owner`.
37+
- Fixed certain scenarios where received components could crash the app.
38+
([#3059](https://github.com/Pycord-Development/pycord/pull/3059))
3739

3840
### Deprecated
3941

discord/abc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1732,7 +1732,7 @@ async def send(
17321732
if view.is_dispatchable():
17331733
state.store_view(view, ret.id)
17341734
view.message = ret
1735-
view.refresh(ret.components)
1735+
view._refresh(ret.components)
17361736

17371737
if delete_after is not None:
17381738
await ret.delete(delay=delete_after)

discord/interactions.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,9 @@ async def edit_original_response(
621621
previous_allowed_mentions=previous_mentions,
622622
suppress_embeds=suppress_embeds,
623623
)
624-
if view and self.message:
625-
self._state.prevent_view_updates_for(self.message.id)
624+
_target = self.message or self._original_response
625+
if view and _target:
626+
self._state.prevent_view_updates_for(_target.id)
626627
adapter = async_context.get()
627628
http = self._state.http
628629
data = await adapter.edit_original_interaction_response(
@@ -641,7 +642,7 @@ async def edit_original_response(
641642
message = InteractionMessage(state=state, channel=self.channel, data=data) # type: ignore
642643
if view:
643644
if not view.is_finished():
644-
view.refresh(message.components)
645+
view._refresh(message.components)
645646
if view.is_dispatchable():
646647
self._state.store_view(view, message.id)
647648

@@ -1308,7 +1309,7 @@ async def edit_message(
13081309
raise InteractionResponded(self._parent)
13091310

13101311
parent = self._parent
1311-
msg = parent.message
1312+
msg = parent.message or parent._original_response
13121313
state = parent._state
13131314
message_id = msg.id if msg else None
13141315
if parent.type not in (InteractionType.component, InteractionType.modal_submit):

discord/message.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,7 +1918,7 @@ async def edit(
19181918

19191919
if view and not view.is_finished():
19201920
view.message = message
1921-
view.refresh(message.components)
1921+
view._refresh(message.components)
19221922
if view.is_dispatchable():
19231923
self._state.store_view(view, self.id)
19241924

@@ -2587,7 +2587,7 @@ async def edit(self, **fields: Any) -> Message | None:
25872587
msg = self._state.create_message(channel=self.channel, data=data) # type: ignore
25882588
if view and not view.is_finished():
25892589
view.message = msg
2590-
view.refresh(msg.components)
2590+
view._refresh(msg.components)
25912591
if view.is_dispatchable():
25922592
self._state.store_view(view, self.id)
25932593
return msg

discord/ui/modal.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ def remove_item(self, item: InputText) -> Self:
364364
pass
365365
return self
366366

367-
def refresh(self, interaction: Interaction, data: list[ComponentPayload]):
367+
def _refresh(self, interaction: Interaction, data: list[ComponentPayload]):
368368
components = [
369369
component
370370
for parent_component in data
@@ -448,7 +448,7 @@ def add_item(self, item: ModalItem) -> Self:
448448
super().add_item(item)
449449
return self
450450

451-
def refresh(self, interaction: Interaction, data: list[ComponentPayload]):
451+
def _refresh(self, interaction: Interaction, data: list[ComponentPayload]):
452452
for component, child in zip(data, self.children):
453453
child.refresh_from_modal(interaction, component)
454454

@@ -520,7 +520,7 @@ async def dispatch(self, user_id: int, custom_id: str, interaction: Interaction)
520520

521521
try:
522522
components = interaction.data["components"]
523-
modal.refresh(interaction, components)
523+
modal._refresh(interaction, components)
524524
await modal.callback(interaction)
525525
self.remove_modal(modal, user_id)
526526
except Exception as e:

discord/ui/view.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import asyncio
2929
import contextlib
30+
import logging
3031
import os
3132
import sys
3233
import time
@@ -83,6 +84,8 @@
8384
from ..state import ConnectionState
8485
from ..types.components import Component as ComponentPayload
8586

87+
_log = logging.getLogger(__name__)
88+
8689
V = TypeVar("V", bound="BaseView", covariant=True)
8790

8891

@@ -756,7 +759,7 @@ def clear_items(self) -> Self:
756759
self.__weights.clear()
757760
return self
758761

759-
def refresh(self, components: list[Component]):
762+
def _refresh(self, components: list[Component]):
760763
# This is pretty hacky at the moment
761764
old_state: dict[tuple[int, str], ViewItem[V]] = {
762765
(item.type.value, item.custom_id): item
@@ -935,7 +938,7 @@ def add_item(self, item: ViewItem[V]) -> Self:
935938
super().add_item(item)
936939
return self
937940

938-
def refresh(self, components: list[Component]):
941+
def _refresh(self, components: list[Component]):
939942
# Refreshes view data using discord's values
940943
# Assumes the components and items are identical
941944
if not components:
@@ -1039,4 +1042,9 @@ def update_from_message(self, message_id: int, components: list[ComponentPayload
10391042
# pre-req: is_message_tracked == true
10401043
view = self._synced_message_views[message_id]
10411044
components = [_component_factory(d, state=self._state) for d in components]
1042-
view.refresh(components)
1045+
try:
1046+
view._refresh(components)
1047+
except Exception:
1048+
_log.exception(
1049+
f"Failed to refresh View {view} from Message {message_id} due to mismatched state. Items may not have complete data."
1050+
)

discord/webhook/async_.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,7 +1940,7 @@ async def send(
19401940
if self.parent and not view.parent:
19411941
view.parent = self.parent
19421942
if msg:
1943-
view.refresh(msg.components)
1943+
view._refresh(msg.components)
19441944
if view.is_dispatchable():
19451945
self._state.store_view(view, message_id)
19461946

@@ -2164,7 +2164,7 @@ async def edit_message(
21642164
message = self._create_message(data)
21652165
if view and not view.is_finished():
21662166
view.message = message
2167-
view.refresh(message.components)
2167+
view._refresh(message.components)
21682168
if view.is_dispatchable():
21692169
self._state.store_view(view, message_id)
21702170
return message

0 commit comments

Comments
 (0)