Add support for components V2

Co-authored-by: Michael H <michael@michaelhall.tech>
Co-authored-by: Soheab <33902984+Soheab@users.noreply.github.com>
Co-authored-by: owocado <24418520+owocado@users.noreply.github.com>
Co-authored-by: Jay3332 <40323796+jay3332@users.noreply.github.com>
Co-authored-by: Danny <1695103+Rapptz@users.noreply.github.com>
This commit is contained in:
DA344
2025-08-14 02:37:23 +02:00
committed by GitHub
parent 6ec2e5329b
commit 50caa3c82c
33 changed files with 4214 additions and 298 deletions

View File

@ -96,15 +96,14 @@ if TYPE_CHECKING:
from .types.gateway import MessageReactionRemoveEvent, MessageUpdateEvent
from .abc import Snowflake
from .abc import GuildChannel, MessageableChannel
from .components import ActionRow, ActionRowChildComponentType
from .components import MessageComponentType
from .state import ConnectionState
from .mentions import AllowedMentions
from .user import User
from .role import Role
from .ui.view import View
from .ui.view import View, LayoutView
EmojiInputType = Union[Emoji, PartialEmoji, str]
MessageComponentType = Union[ActionRow, ActionRowChildComponentType]
__all__ = (
@ -489,7 +488,7 @@ class MessageSnapshot:
Extra features of the the message snapshot.
stickers: List[:class:`StickerItem`]
A list of sticker items given to the message.
components: List[Union[:class:`ActionRow`, :class:`Button`, :class:`SelectMenu`]]
components: List[Union[:class:`ActionRow`, :class:`Button`, :class:`SelectMenu`, :class:`Container`, :class:`SectionComponent`, :class:`TextDisplay`, :class:`MediaGalleryComponent`, :class:`FileComponent`, :class:`SeparatorComponent`, :class:`ThumbnailComponent`]]
A list of components in the message.
"""
@ -533,7 +532,7 @@ class MessageSnapshot:
self.components: List[MessageComponentType] = []
for component_data in data.get('components', []):
component = _component_factory(component_data)
component = _component_factory(component_data, state) # type: ignore
if component is not None:
self.components.append(component)
@ -1306,32 +1305,6 @@ class PartialMessage(Hashable):
else:
await self._state.http.delete_message(self.channel.id, self.id)
@overload
async def edit(
self,
*,
content: Optional[str] = ...,
embed: Optional[Embed] = ...,
attachments: Sequence[Union[Attachment, File]] = ...,
delete_after: Optional[float] = ...,
allowed_mentions: Optional[AllowedMentions] = ...,
view: Optional[View] = ...,
) -> Message:
...
@overload
async def edit(
self,
*,
content: Optional[str] = ...,
embeds: Sequence[Embed] = ...,
attachments: Sequence[Union[Attachment, File]] = ...,
delete_after: Optional[float] = ...,
allowed_mentions: Optional[AllowedMentions] = ...,
view: Optional[View] = ...,
) -> Message:
...
async def edit(
self,
*,
@ -1341,7 +1314,7 @@ class PartialMessage(Hashable):
attachments: Sequence[Union[Attachment, File]] = MISSING,
delete_after: Optional[float] = None,
allowed_mentions: Optional[AllowedMentions] = MISSING,
view: Optional[View] = MISSING,
view: Optional[Union[View, LayoutView]] = MISSING,
) -> Message:
"""|coro|
@ -1391,10 +1364,16 @@ class PartialMessage(Hashable):
are used instead.
.. versionadded:: 1.4
view: Optional[:class:`~discord.ui.View`]
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 view is removed.
.. note::
If you want to update the message to have a :class:`~discord.ui.LayoutView`, you must
explicitly set the ``content``, ``embed``, ``embeds``, and ``attachments`` parameters to
``None`` if the previous message had any.
Raises
-------
HTTPException
@ -1433,8 +1412,8 @@ class PartialMessage(Hashable):
data = await self._state.http.edit_message(self.channel.id, self.id, params=params)
message = Message(state=self._state, channel=self.channel, data=data)
if view and not view.is_finished():
interaction: Optional[MessageInteraction] = getattr(self, 'interaction', None)
if view and not view.is_finished() and view.is_dispatchable():
interaction: Optional[MessageInteractionMetadata] = getattr(self, 'interaction_metadata', None)
if interaction is not None:
self._state.store_view(view, self.id, interaction_id=interaction.id)
else:
@ -1756,6 +1735,38 @@ class PartialMessage(Hashable):
return await self.guild.fetch_channel(self.id) # type: ignore # Can only be Thread in this case
@overload
async def reply(
self,
*,
file: File = ...,
view: LayoutView,
delete_after: float = ...,
nonce: Union[str, int] = ...,
allowed_mentions: AllowedMentions = ...,
reference: Union[Message, MessageReference, PartialMessage] = ...,
mention_author: bool = ...,
suppress_embeds: bool = ...,
silent: bool = ...,
) -> Message:
...
@overload
async def reply(
self,
*,
files: Sequence[File] = ...,
view: LayoutView,
delete_after: float = ...,
nonce: Union[str, int] = ...,
allowed_mentions: AllowedMentions = ...,
reference: Union[Message, MessageReference, PartialMessage] = ...,
mention_author: bool = ...,
suppress_embeds: bool = ...,
silent: bool = ...,
) -> Message:
...
@overload
async def reply(
self,
@ -2846,34 +2857,6 @@ class Message(PartialMessage, Hashable):
# Fallback for unknown message types
return ''
@overload
async def edit(
self,
*,
content: Optional[str] = ...,
embed: Optional[Embed] = ...,
attachments: Sequence[Union[Attachment, File]] = ...,
suppress: bool = ...,
delete_after: Optional[float] = ...,
allowed_mentions: Optional[AllowedMentions] = ...,
view: Optional[View] = ...,
) -> Message:
...
@overload
async def edit(
self,
*,
content: Optional[str] = ...,
embeds: Sequence[Embed] = ...,
attachments: Sequence[Union[Attachment, File]] = ...,
suppress: bool = ...,
delete_after: Optional[float] = ...,
allowed_mentions: Optional[AllowedMentions] = ...,
view: Optional[View] = ...,
) -> Message:
...
async def edit(
self,
*,
@ -2884,7 +2867,7 @@ class Message(PartialMessage, Hashable):
suppress: bool = False,
delete_after: Optional[float] = None,
allowed_mentions: Optional[AllowedMentions] = MISSING,
view: Optional[View] = MISSING,
view: Optional[Union[View, LayoutView]] = MISSING,
) -> Message:
"""|coro|
@ -2942,10 +2925,16 @@ class Message(PartialMessage, Hashable):
are used instead.
.. versionadded:: 1.4
view: Optional[:class:`~discord.ui.View`]
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 view is removed.
.. note::
If you want to update the message to have a :class:`~discord.ui.LayoutView`, you must
explicitly set the ``content``, ``embed``, ``embeds``, and ``attachments`` parameters to
``None`` if the previous message had any.
Raises
-------
HTTPException
@ -2991,7 +2980,7 @@ class Message(PartialMessage, Hashable):
data = await self._state.http.edit_message(self.channel.id, self.id, params=params)
message = Message(state=self._state, channel=self.channel, data=data)
if view and not view.is_finished():
if view and not view.is_finished() and view.is_dispatchable():
self._state.store_view(view, self.id)
if delete_after is not None: