Fix (Sync)Webhook.edit_message missing the view parameter

This commit is contained in:
DA344
2026-02-22 22:45:49 +01:00
committed by GitHub
parent 60e746ca94
commit 93fa3cb9d6
2 changed files with 60 additions and 15 deletions

View File

@@ -364,6 +364,7 @@ class AsyncWebhookAdapter:
multipart: Optional[List[Dict[str, Any]]] = None, multipart: Optional[List[Dict[str, Any]]] = None,
files: Optional[Sequence[File]] = None, files: Optional[Sequence[File]] = None,
thread_id: Optional[int] = None, thread_id: Optional[int] = None,
with_components: bool = False,
) -> Response[MessagePayload]: ) -> Response[MessagePayload]:
route = Route( route = Route(
'PATCH', 'PATCH',
@@ -372,7 +373,9 @@ class AsyncWebhookAdapter:
webhook_token=token, webhook_token=token,
message_id=message_id, message_id=message_id,
) )
params = None if thread_id is None else {'thread_id': thread_id} params = {'with_components': int(with_components)}
if thread_id:
params['thread_id'] = thread_id
return self.request( return self.request(
route, route,
session=session, session=session,
@@ -848,7 +851,15 @@ class WebhookMessage(Message):
See :meth:`.abc.Messageable.send` for more information. See :meth:`.abc.Messageable.send` for more information.
view: Optional[:class:`~discord.ui.View`] view: Optional[:class:`~discord.ui.View`]
The updated view to update this message with. If ``None`` is passed then The updated view to update this message with. If ``None`` is passed then
the view is removed. the view is removed. If the webhook is partial or is not managed by the
library, then you can not send interactable components. Otherwise, you
can send views with any type of components.
.. note::
To update the message to add a :class:`~discord.ui.LayoutView`, you
must explicitly set the ``content``, ``embed``, ``embeds``, and
``attachments`` parameters to either ``None`` or an empty array, as appropriate.
.. versionadded:: 2.0 .. versionadded:: 2.0
@@ -1772,7 +1783,7 @@ class Webhook(BaseWebhook):
.. versionadded:: 1.4 .. versionadded:: 1.4
view: Union[:class:`discord.ui.View`, :class:`discord.ui.LayoutView`] view: Union[:class:`discord.ui.View`, :class:`discord.ui.LayoutView`]
The view to send with the message. If the webhook is partial or The view to send with the message. If the webhook is partial or
is not managed by the library, then you can only send URL buttons. is not managed by the library, then you can not send interactable components.
Otherwise, you can send views with any type of components. Otherwise, you can send views with any type of components.
.. versionadded:: 2.0 .. versionadded:: 2.0
@@ -1857,12 +1868,10 @@ class Webhook(BaseWebhook):
if view is not MISSING: if view is not MISSING:
if not hasattr(view, '__discord_ui_view__'): if not hasattr(view, '__discord_ui_view__'):
raise TypeError(f'expected view parameter to be of type View not {view.__class__.__name__}') raise TypeError(f'expected view parameter to be of type View or LayoutView, not {view.__class__.__name__}')
if isinstance(self._state, _WebhookState) and view.is_dispatchable(): if isinstance(self._state, _WebhookState) and view.is_dispatchable():
raise ValueError( raise ValueError('Webhook views with interactable components require an associated state with the webhook')
'Webhook views with any component other than URL buttons require an associated state with the webhook'
)
if ephemeral is True and view.timeout is None and view.is_dispatchable(): if ephemeral is True and view.timeout is None and view.is_dispatchable():
view.timeout = 15 * 60.0 view.timeout = 15 * 60.0
@@ -2048,8 +2057,9 @@ class Webhook(BaseWebhook):
See :meth:`.abc.Messageable.send` for more information. See :meth:`.abc.Messageable.send` for more information.
view: Optional[Union[:class:`~discord.ui.View`, :class:`~discord.ui.LayoutView`]] view: Optional[Union[:class:`~discord.ui.View`, :class:`~discord.ui.LayoutView`]]
The updated view to update this message with. If ``None`` is passed then The updated view to update this message with. If ``None`` is passed then
the view is removed. The webhook must have state attached, similar to the view is removed. If the webhook is partial or is not managed by the
:meth:`send`. library, then you can not send interactable components. Otherwise, you
can send views with any type of components.
.. note:: .. note::
@@ -2085,11 +2095,12 @@ class Webhook(BaseWebhook):
if self.token is None: if self.token is None:
raise ValueError('This webhook does not have a token associated with it') raise ValueError('This webhook does not have a token associated with it')
if view is not MISSING: if view:
if isinstance(self._state, _WebhookState): if not hasattr(view, '__discord_ui_view__'):
raise ValueError('This webhook does not have state associated with it') raise TypeError(f'expected view parameter to be of type View or LayoutView, not {view.__class__.__name__}')
self._state.prevent_view_updates_for(message_id) if isinstance(self._state, _WebhookState) and view.is_dispatchable():
raise ValueError('Webhook views with interactable components require an associated state with the webhook')
previous_mentions: Optional[AllowedMentions] = getattr(self._state, 'allowed_mentions', None) previous_mentions: Optional[AllowedMentions] = getattr(self._state, 'allowed_mentions', None)
with handle_message_parameters( with handle_message_parameters(
@@ -2117,6 +2128,7 @@ class Webhook(BaseWebhook):
multipart=params.multipart, multipart=params.multipart,
files=params.files, files=params.files,
thread_id=thread_id, thread_id=thread_id,
with_components=bool(view),
) )
message = self._create_message(data, thread=thread) message = self._create_message(data, thread=thread)

View File

@@ -329,6 +329,7 @@ class WebhookAdapter:
multipart: Optional[List[Dict[str, Any]]] = None, multipart: Optional[List[Dict[str, Any]]] = None,
files: Optional[Sequence[File]] = None, files: Optional[Sequence[File]] = None,
thread_id: Optional[int] = None, thread_id: Optional[int] = None,
with_components: bool = False,
) -> MessagePayload: ) -> MessagePayload:
route = Route( route = Route(
'PATCH', 'PATCH',
@@ -337,7 +338,9 @@ class WebhookAdapter:
webhook_token=token, webhook_token=token,
message_id=message_id, message_id=message_id,
) )
params = None if thread_id is None else {'thread_id': thread_id} params = {'with_components': int(with_components)}
if thread_id:
params['thread_id'] = thread_id
return self.request(route, session, payload=payload, multipart=multipart, files=files, params=params) return self.request(route, session, payload=payload, multipart=multipart, files=files, params=params)
def delete_webhook_message( def delete_webhook_message(
@@ -415,6 +418,7 @@ class SyncWebhookMessage(Message):
embed: Optional[Embed] = MISSING, embed: Optional[Embed] = MISSING,
attachments: Sequence[Union[Attachment, File]] = MISSING, attachments: Sequence[Union[Attachment, File]] = MISSING,
allowed_mentions: Optional[AllowedMentions] = None, allowed_mentions: Optional[AllowedMentions] = None,
view: Optional[BaseView] = MISSING,
) -> SyncWebhookMessage: ) -> SyncWebhookMessage:
"""Edits the message. """Edits the message.
@@ -443,6 +447,19 @@ class SyncWebhookMessage(Message):
allowed_mentions: :class:`AllowedMentions` allowed_mentions: :class:`AllowedMentions`
Controls the mentions being processed in this message. Controls the mentions being processed in this message.
See :meth:`.abc.Messageable.send` for more information. See :meth:`.abc.Messageable.send` for more information.
view: Union[:class:`discord.ui.View`, :class:`discord.ui.LayoutView`]
The updated view to update this message with. This can only have non-interactible items, which do not
require a state to be attached to it. If ``None`` is passed then the view is removed.
If you want to edit a webhook message with any component attached to it, check :meth:`WebhookMessage.edit`.
.. note::
To update the message to add a :class:`~discord.ui.LayoutView`, you
must explicitly set the ``content``, ``embed``, ``embeds``, and
``attachments`` parameters to either ``None`` or an empty array, as appropriate.
.. versionadded:: 2.7
Raises Raises
------- -------
@@ -451,7 +468,7 @@ class SyncWebhookMessage(Message):
Forbidden Forbidden
Edited a message that is not yours. Edited a message that is not yours.
TypeError TypeError
You specified both ``embed`` and ``embeds`` You specified both ``embed`` and ``embeds``.
ValueError ValueError
The length of ``embeds`` was invalid or The length of ``embeds`` was invalid or
there was no token associated with this webhook. there was no token associated with this webhook.
@@ -469,6 +486,7 @@ class SyncWebhookMessage(Message):
attachments=attachments, attachments=attachments,
allowed_mentions=allowed_mentions, allowed_mentions=allowed_mentions,
thread=self._state._thread, thread=self._state._thread,
view=view,
) )
def add_files(self, *files: File) -> SyncWebhookMessage: def add_files(self, *files: File) -> SyncWebhookMessage:
@@ -1245,6 +1263,12 @@ class SyncWebhook(BaseWebhook):
If you want to edit a webhook message with any component attached to it, check :meth:`WebhookMessage.edit`. If you want to edit a webhook message with any component attached to it, check :meth:`WebhookMessage.edit`.
.. note::
To update the message to add a :class:`~discord.ui.LayoutView`, you
must explicitly set the ``content``, ``embed``, ``embeds``, and
``attachments`` parameters to either ``None`` or an empty array, as appropriate.
.. versionadded:: 2.6 .. versionadded:: 2.6
allowed_mentions: :class:`AllowedMentions` allowed_mentions: :class:`AllowedMentions`
Controls the mentions being processed in this message. Controls the mentions being processed in this message.
@@ -1270,6 +1294,13 @@ class SyncWebhook(BaseWebhook):
if self.token is None: if self.token is None:
raise ValueError('This webhook does not have a token associated with it') raise ValueError('This webhook does not have a token associated with it')
if view:
if not hasattr(view, '__discord_ui_view__'):
raise TypeError(f'expected view parameter to be of type View or LayoutView, not {view.__class__.__name__}')
if view.is_dispatchable():
raise ValueError('SyncWebhooks can not send interactable components')
previous_mentions: Optional[AllowedMentions] = getattr(self._state, 'allowed_mentions', None) previous_mentions: Optional[AllowedMentions] = getattr(self._state, 'allowed_mentions', None)
with handle_message_parameters( with handle_message_parameters(
content=content, content=content,
@@ -1278,6 +1309,7 @@ class SyncWebhook(BaseWebhook):
embeds=embeds, embeds=embeds,
allowed_mentions=allowed_mentions, allowed_mentions=allowed_mentions,
previous_allowed_mentions=previous_mentions, previous_allowed_mentions=previous_mentions,
view=view,
) as params: ) as params:
thread_id: Optional[int] = None thread_id: Optional[int] = None
if thread is not MISSING: if thread is not MISSING:
@@ -1293,6 +1325,7 @@ class SyncWebhook(BaseWebhook):
multipart=params.multipart, multipart=params.multipart,
files=params.files, files=params.files,
thread_id=thread_id, thread_id=thread_id,
with_components=bool(view),
) )
return self._create_message(data, thread=thread) return self._create_message(data, thread=thread)