From 7fb97fbcadaa3850ad518868119feb171caea3d4 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 03:59:21 +0100 Subject: [PATCH 01/29] new message types --- discord/enums.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/discord/enums.py b/discord/enums.py index 14aa54d460..0038a15aff 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -265,6 +265,12 @@ class MessageType(Enum): stage_raise_hand = 30 stage_topic = 31 guild_application_premium_subscription = 32 + guild_incident_alert_mode_enabled = 36 + guild_incident_alert_mode_disabled = 37 + guild_incident_report_raid = 38 + guild_incident_report_false_alarm = 39 + purchase_notification = 44 + poll_result = 46 class VoiceRegion(Enum): From 58e7c6cf731c6ca8c1428a02c562b1443da71e6e Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 04:00:32 +0100 Subject: [PATCH 02/29] new embed type --- discord/types/embed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/types/embed.py b/discord/types/embed.py index dbfcb14c87..4321197692 100644 --- a/discord/types/embed.py +++ b/discord/types/embed.py @@ -76,7 +76,7 @@ class EmbedAuthor(TypedDict, total=False): EmbedType = Literal[ - "rich", "image", "video", "gifv", "article", "link", "auto_moderation_message" + "rich", "image", "video", "gifv", "article", "link", "auto_moderation_message", "poll_result" ] From 901bdfe05f929185e75593244e73015f0c767d6b Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 04:54:29 +0100 Subject: [PATCH 03/29] implement types --- discord/types/message.py | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/discord/types/message.py b/discord/types/message.py index f138609d1b..a2680b650c 100644 --- a/discord/types/message.py +++ b/discord/types/message.py @@ -99,7 +99,11 @@ class MessageApplication(TypedDict): name: str +MessageReferenceType = Literal[0, 1] + + class MessageReference(TypedDict, total=False): + type: NotRequired[MessageReferenceType] message_id: Snowflake channel_id: Snowflake guild_id: Snowflake @@ -111,6 +115,29 @@ class MessageReference(TypedDict, total=False): ] +class MessageCall(TypedDict): + participants: SnowflakeList + ended_timestamp: NotRequired[str] + + +class ForwardedMessage(TypedDict): + type: MessageType + content: str + embeds: list[Embed] + attachments: list[Attachment] + timestamp: str + edited_timestamp: str | None + flags: NotRequired[int] + mentions: list[UserWithMember] + mention_roles: SnowflakeList + sticker_items: NotRequired[list[StickerItem]] + components: NotRequired[list[Component]] + + +class MessageSnapshot(TypedDict): + message: ForwardedMessage + + class Message(TypedDict): guild_id: NotRequired[Snowflake] member: NotRequired[Member] @@ -144,6 +171,8 @@ class Message(TypedDict): pinned: bool type: MessageType poll: Poll + call: MessageCall + message_snapshots: NotRequired[list[MessageSnapshot]] AllowedMentionType = Literal["roles", "users", "everyone"] @@ -154,8 +183,3 @@ class AllowedMentions(TypedDict): roles: SnowflakeList users: SnowflakeList replied_user: bool - - -class MessageCall(TypedDict): - participants: SnowflakeList - ended_timestamp: NotRequired[str] From ceaffaf236d4f9201236e35998ff3499589c1794 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 05:10:19 +0100 Subject: [PATCH 04/29] update MessageReference --- discord/enums.py | 7 +++++++ discord/message.py | 19 +++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/discord/enums.py b/discord/enums.py index 0038a15aff..b53f7de8a0 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -1059,6 +1059,13 @@ class PollLayoutType(Enum): default = 1 +class MessageReferenceType(Enum): + """The message reference's type""" + + default = 0 + forward = 1 + + T = TypeVar("T") diff --git a/discord/message.py b/discord/message.py index 37ffd86f53..23c986039b 100644 --- a/discord/message.py +++ b/discord/message.py @@ -45,7 +45,7 @@ from .components import _component_factory from .embeds import Embed from .emoji import Emoji -from .enums import ChannelType, MessageType, try_enum +from .enums import ChannelType, MessageType, MessageReferenceType, try_enum from .errors import InvalidArgument from .file import File from .flags import AttachmentFlags, MessageFlags @@ -477,6 +477,11 @@ class MessageReference: Attributes ---------- + type: Optional[:class:`MessageReferenceType`] + The type of message reference. If this is not provided, assume default behavior. + + .. versionadded:: 2.7 + message_id: Optional[:class:`int`] The id of the message referenced. channel_id: :class:`int` @@ -507,6 +512,7 @@ class MessageReference: "guild_id", "fail_if_not_exists", "resolved", + "type", "_state", ) @@ -517,9 +523,11 @@ def __init__( channel_id: int, guild_id: int | None = None, fail_if_not_exists: bool = True, + type: MessageReferenceType | None = None ): self._state: ConnectionState | None = None self.resolved: Message | DeletedReferencedMessage | None = None + self.type: MessageReferenceType | None = type self.message_id: int | None = message_id self.channel_id: int = channel_id self.guild_id: int | None = guild_id @@ -530,6 +538,7 @@ def with_state( cls: type[MR], state: ConnectionState, data: MessageReferencePayload ) -> MR: self = cls.__new__(cls) + self.type = try_enum(MessageReferenceType, data.get("type")) self.message_id = utils._get_as_snowflake(data, "message_id") self.channel_id = int(data.pop("channel_id")) self.guild_id = utils._get_as_snowflake(data, "guild_id") @@ -540,7 +549,7 @@ def with_state( @classmethod def from_message( - cls: type[MR], message: Message, *, fail_if_not_exists: bool = True + cls: type[MR], message: Message, *, fail_if_not_exists: bool = True, type: MessageReferenceType = None ) -> MR: """Creates a :class:`MessageReference` from an existing :class:`~discord.Message`. @@ -556,6 +565,11 @@ def from_message( .. versionadded:: 1.7 + type: Optional[:class:`MessageReferenceType`] + The type of reference to create. Defaults to reply. + + .. versionadded:: 2.7 + Returns ------- :class:`MessageReference` @@ -566,6 +580,7 @@ def from_message( channel_id=message.channel.id, guild_id=getattr(message.guild, "id", None), fail_if_not_exists=fail_if_not_exists, + type=type, ) self._state = message._state return self From 5baa51389d3455cafb8a158ef7b850cabcbe1f3a Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 07:05:25 +0100 Subject: [PATCH 05/29] forwarding --- discord/abc.py | 6 +- discord/enums.py | 2 + discord/message.py | 183 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 175 insertions(+), 16 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index d699f44702..01b3e8f650 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1493,8 +1493,8 @@ async def send( .. versionadded:: 1.4 reference: Union[:class:`~discord.Message`, :class:`~discord.MessageReference`, :class:`~discord.PartialMessage`] - A reference to the :class:`~discord.Message` to which you are replying, this can be created using - :meth:`~discord.Message.to_reference` or passed directly as a :class:`~discord.Message`. You can control + A reference to the :class:`~discord.Message` you are replying to or forwarding, this can be created using + :meth:`~discord.Message.to_reference` or passed directly as a :class:`~discord.Message`. When replying, you can control whether this mentions the author of the referenced message using the :attr:`~discord.AllowedMentions.replied_user` attribute of ``allowed_mentions`` or by setting ``mention_author``. @@ -1588,6 +1588,8 @@ async def send( if reference is not None: try: reference = reference.to_message_reference_dict() + if not isinstance(reference, MessageReference): + utils.warn_deprecated(f"Passing {type(reference).__name__} to reference", "MessageReference", "2.7", "3.0") except AttributeError: raise InvalidArgument( "reference parameter must be Message, MessageReference, or" diff --git a/discord/enums.py b/discord/enums.py index b53f7de8a0..4859952272 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -76,6 +76,8 @@ "EntitlementOwnerType", "IntegrationType", "InteractionContextType", + "PollLayoutType", + "MessageReferenceType", ) diff --git a/discord/message.py b/discord/message.py index 23c986039b..efad28df93 100644 --- a/discord/message.py +++ b/discord/message.py @@ -83,6 +83,8 @@ from .types.message import MessageApplication as MessageApplicationPayload from .types.message import MessageCall as MessageCallPayload from .types.message import MessageReference as MessageReferencePayload + from .types.message import ForwardedMessage as ForwardedMessagePayload + from .types.message import MessageSnapshot as MessageSnapshotPayload from .types.message import Reaction as ReactionPayload from .types.poll import Poll as PollPayload from .types.snowflake import SnowflakeList @@ -101,6 +103,7 @@ "MessageReference", "MessageCall", "DeletedReferencedMessage", + "ForwardedMessage" ) @@ -477,8 +480,8 @@ class MessageReference: Attributes ---------- - type: Optional[:class:`MessageReferenceType`] - The type of message reference. If this is not provided, assume default behavior. + type: Optional[:class:`~discord.MessageReferenceType`] + The type of message reference. If this is not provided, assume default behavior (reply). .. versionadded:: 2.7 @@ -523,11 +526,11 @@ def __init__( channel_id: int, guild_id: int | None = None, fail_if_not_exists: bool = True, - type: MessageReferenceType | None = None + type: MessageReferenceType = MessageReferenceType.default ): self._state: ConnectionState | None = None self.resolved: Message | DeletedReferencedMessage | None = None - self.type: MessageReferenceType | None = type + self.type: MessageReferenceType = type self.message_id: int | None = message_id self.channel_id: int = channel_id self.guild_id: int | None = guild_id @@ -538,9 +541,9 @@ def with_state( cls: type[MR], state: ConnectionState, data: MessageReferencePayload ) -> MR: self = cls.__new__(cls) - self.type = try_enum(MessageReferenceType, data.get("type")) + self.type = try_enum(MessageReferenceType, data.get("type")) or MessageReferenceType.default self.message_id = utils._get_as_snowflake(data, "message_id") - self.channel_id = int(data.pop("channel_id")) + self.channel_id = utils._get_as_snowflake(data, "channel_id") self.guild_id = utils._get_as_snowflake(data, "guild_id") self.fail_if_not_exists = data.get("fail_if_not_exists", True) self._state = state @@ -549,7 +552,7 @@ def with_state( @classmethod def from_message( - cls: type[MR], message: Message, *, fail_if_not_exists: bool = True, type: MessageReferenceType = None + cls: type[MR], message: Message, *, fail_if_not_exists: bool = True, type: MessageReferenceType = MessageReferenceType.default ) -> MR: """Creates a :class:`MessageReference` from an existing :class:`~discord.Message`. @@ -565,8 +568,8 @@ def from_message( .. versionadded:: 1.7 - type: Optional[:class:`MessageReferenceType`] - The type of reference to create. Defaults to reply. + type: Optional[:class:`~discord.MessageReferenceType`] + The type of reference to create. Defaults to :attr:`MessageReferenceType.default` (reply). .. versionadded:: 2.7 @@ -602,7 +605,8 @@ def jump_url(self) -> str: def __repr__(self) -> str: return ( f"" + f" channel_id={self.channel_id!r} guild_id={self.guild_id!r}" + f" type={self.type!r}>" ) def to_dict(self) -> MessageReferencePayload: @@ -610,6 +614,7 @@ def to_dict(self) -> MessageReferencePayload: {"message_id": self.message_id} if self.message_id is not None else {} ) result["channel_id"] = self.channel_id + result["type"] = self.type and self.type.value if self.guild_id is not None: result["guild_id"] = self.guild_id if self.fail_if_not_exists is not None: @@ -647,6 +652,106 @@ def ended_at(self) -> datetime.datetime | None: return self._ended_timestamp +class ForwardedMessage: + """Represents the snapshotted contents from a forwarded message. Forwarded messages are immutable; any updates to the original message won't be reflected. + + .. versionadded:: 2.7 + + Attributes + ---------- + type: :class:`MessageType` + The type of message. In most cases this should not be checked, but it is helpful + in cases where it might be a system message for :attr:`system_content`. + content: :class:`str` + The contents of the original message. + embeds: List[:class:`Embed`] + A list of embeds the original message had. + attachments: List[:class:`Attachment`] + A list of attachments given to the original message. + flags: :class:`MessageFlags` + Extra features of the message. + mentions: List[Union[:class:`abc.User`, :class:`Object`]] + A list of :class:`Member` that were mentioned. + role_mentions: List[Union[:class:`Role`, :class:`Object`]] + A list of :class:`Role` that were mentioned. + stickers: List[:class:`StickerItem`] + A list of sticker items given to the original message. + components: List[:class:`Component`] + A list of components in the original message. + """ + + __slots__ = ( + "message_id", + "channel_id", + "guild_id", + "fail_if_not_exists", + "resolved", + "type", + "_state", + ) + + def __init__( + self, + *, + state: ConnectionState, + reference: MessageReference, + data: ForwardedMessagePayload, + ): + self._state: ConnectionState = state + self.id: int = reference.message_id + self.channel = state.get_channel(reference.channel_id) or (reference.channel_id and Object(reference.channel_id)) + self.guild = state._get_guild(reference.guild_id) or (reference.guild_id and Object(reference.guild_id)) + self.content: str = data["content"] + self.embeds: list[Embed] = [Embed.from_dict(a) for a in data["embeds"]] + self.attachments: list[Attachment] = [ + Attachment(data=a, state=state) for a in data["attachments"] + ] + self.flags: MessageFlags = MessageFlags._from_value(data.get("flags", 0)) + self.stickers: list[StickerItem] = [ + StickerItem(data=d, state=state) for d in data.get("sticker_items", []) + ] + self.components: list[Component] = [ + _component_factory(d) for d in data.get("components", []) + ] + self._edited_timestamp: datetime.datetime | None = utils.parse_time( + data["edited_timestamp"] + ) + + @property + def created_at(self) -> datetime.datetime: + """The original message's creation time in UTC.""" + return utils.snowflake_time(self.id) + + @property + def edited_at(self) -> datetime.datetime | None: + """An aware UTC datetime object containing the + edited time of the original message. + """ + return self._edited_timestamp + + +class MessageSnapshot: + """Represents a message snapshot. + + .. versionadded:: 2.7 + + Attributes + ---------- + message: :class:`ForwardedMessage` + The forwarded message, which includes a minimal subset of fields from the original message. + """ + + def __init__( + self, + *, + state: ConnectionState, + reference: MessageReference, + data: MessageSnapshotPayload, + ): + self._state: ConnectionState = state + self.message: ForwardedMessage = ForwardedMessage(state=state, reference=reference, data=data) + + def flatten_handlers(cls): prefix = len("_handle_") handlers = [ @@ -799,6 +904,10 @@ class Message(Hashable): The call information associated with this message, if applicable. .. versionadded:: 2.6 + snapshots: Optional[List[:class:`MessageSnapshots`]] + The snapshots attached to this message, if applicable. + + .. versionadded:: 2.7 """ __slots__ = ( @@ -837,6 +946,7 @@ class Message(Hashable): "thread", "_poll", "call", + "snapshots", ) if TYPE_CHECKING: @@ -916,6 +1026,14 @@ def __init__( # the channel will be the correct type here ref.resolved = self.__class__(channel=chan, data=resolved, state=state) # type: ignore + self.snapshots: list[MessageSnapshot] + try: + self.snapshots = [MessageSnapshot( + state=state, reference=self.reference, data=ms, + ) for ms in data["message_snapshots"]] + except KeyError: + self.snapshots = [] + from .interactions import InteractionMetadata, MessageInteraction self._interaction: MessageInteraction | None @@ -1939,7 +2057,38 @@ async def reply(self, content: str | None = None, **kwargs) -> Message: you specified both ``file`` and ``files``. """ - return await self.channel.send(content, reference=self, **kwargs) + return await self.channel.send(content, reference=self.to_reference(), **kwargs) + + async def forward(self, channel: MessageableChannel | PartialMessageableChannel, **kwargs) -> Message: + """|coro| + + A shortcut method to :meth:`.abc.Messageable.send` to forward the + :class:`.Message` to a channel. + + .. versionadded:: 2.7 + + Parameters + ---------- + channel: Union[:class:`Emoji`, :class:`Reaction`, :class:`PartialEmoji`, :class:`str`] + The emoji to react with. + + Returns + ------- + :class:`.Message` + The message that was sent. + + Raises + ------ + ~discord.HTTPException + Sending the message failed. + ~discord.Forbidden + You do not have the proper permissions to send the message. + ~discord.InvalidArgument + The ``files`` list is not of the appropriate size, or + you specified both ``file`` and ``files``. + """ + + return await channel.send(reference=self.to_reference(type=MessageReferenceType.forward)) async def end_poll(self) -> Message: """|coro| @@ -1969,7 +2118,7 @@ async def end_poll(self) -> Message: return message - def to_reference(self, *, fail_if_not_exists: bool = True) -> MessageReference: + def to_reference(self, *, fail_if_not_exists: bool = True, type: MessageReferenceType = None) -> MessageReference: """Creates a :class:`~discord.MessageReference` from the current message. .. versionadded:: 1.6 @@ -1982,6 +2131,11 @@ def to_reference(self, *, fail_if_not_exists: bool = True) -> MessageReference: .. versionadded:: 1.7 + type: Optional[:class:`~discord.MessageReferenceType`] + The type of message reference. Defaults to a reply. + + .. versionadded:: 2.7 + Returns ------- :class:`~discord.MessageReference` @@ -1989,13 +2143,14 @@ def to_reference(self, *, fail_if_not_exists: bool = True) -> MessageReference: """ return MessageReference.from_message( - self, fail_if_not_exists=fail_if_not_exists + self, fail_if_not_exists=fail_if_not_exists, type=type ) - def to_message_reference_dict(self) -> MessageReferencePayload: + def to_message_reference_dict(self, type: MessageReferenceType = None) -> MessageReferencePayload: data: MessageReferencePayload = { "message_id": self.id, "channel_id": self.channel.id, + "type": type and type.value, } if self.guild is not None: From b64ec06d28ab9e5152d0d50247a9cd14203dcb61 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 06:08:45 +0000 Subject: [PATCH 06/29] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/abc.py | 7 ++++- discord/message.py | 58 ++++++++++++++++++++++++++++++------------ discord/types/embed.py | 9 ++++++- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index 01b3e8f650..f121989404 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1589,7 +1589,12 @@ async def send( try: reference = reference.to_message_reference_dict() if not isinstance(reference, MessageReference): - utils.warn_deprecated(f"Passing {type(reference).__name__} to reference", "MessageReference", "2.7", "3.0") + utils.warn_deprecated( + f"Passing {type(reference).__name__} to reference", + "MessageReference", + "2.7", + "3.0", + ) except AttributeError: raise InvalidArgument( "reference parameter must be Message, MessageReference, or" diff --git a/discord/message.py b/discord/message.py index 16c45797fd..32161cff4a 100644 --- a/discord/message.py +++ b/discord/message.py @@ -46,7 +46,7 @@ from .components import _component_factory from .embeds import Embed from .emoji import Emoji -from .enums import ChannelType, MessageType, MessageReferenceType, try_enum +from .enums import ChannelType, MessageReferenceType, MessageType, try_enum from .errors import InvalidArgument from .file import File from .flags import AttachmentFlags, MessageFlags @@ -79,12 +79,12 @@ from .types.member import Member as MemberPayload from .types.member import UserWithMember as UserWithMemberPayload from .types.message import Attachment as AttachmentPayload + from .types.message import ForwardedMessage as ForwardedMessagePayload from .types.message import Message as MessagePayload from .types.message import MessageActivity as MessageActivityPayload from .types.message import MessageApplication as MessageApplicationPayload from .types.message import MessageCall as MessageCallPayload from .types.message import MessageReference as MessageReferencePayload - from .types.message import ForwardedMessage as ForwardedMessagePayload from .types.message import MessageSnapshot as MessageSnapshotPayload from .types.message import Reaction as ReactionPayload from .types.poll import Poll as PollPayload @@ -104,7 +104,7 @@ "MessageReference", "MessageCall", "DeletedReferencedMessage", - "ForwardedMessage" + "ForwardedMessage", ) @@ -527,7 +527,7 @@ def __init__( channel_id: int, guild_id: int | None = None, fail_if_not_exists: bool = True, - type: MessageReferenceType = MessageReferenceType.default + type: MessageReferenceType = MessageReferenceType.default, ): self._state: ConnectionState | None = None self.resolved: Message | DeletedReferencedMessage | None = None @@ -542,7 +542,10 @@ def with_state( cls: type[MR], state: ConnectionState, data: MessageReferencePayload ) -> MR: self = cls.__new__(cls) - self.type = try_enum(MessageReferenceType, data.get("type")) or MessageReferenceType.default + self.type = ( + try_enum(MessageReferenceType, data.get("type")) + or MessageReferenceType.default + ) self.message_id = utils._get_as_snowflake(data, "message_id") self.channel_id = utils._get_as_snowflake(data, "channel_id") self.guild_id = utils._get_as_snowflake(data, "guild_id") @@ -553,7 +556,11 @@ def with_state( @classmethod def from_message( - cls: type[MR], message: Message, *, fail_if_not_exists: bool = True, type: MessageReferenceType = MessageReferenceType.default + cls: type[MR], + message: Message, + *, + fail_if_not_exists: bool = True, + type: MessageReferenceType = MessageReferenceType.default, ) -> MR: """Creates a :class:`MessageReference` from an existing :class:`~discord.Message`. @@ -700,8 +707,12 @@ def __init__( ): self._state: ConnectionState = state self.id: int = reference.message_id - self.channel = state.get_channel(reference.channel_id) or (reference.channel_id and Object(reference.channel_id)) - self.guild = state._get_guild(reference.guild_id) or (reference.guild_id and Object(reference.guild_id)) + self.channel = state.get_channel(reference.channel_id) or ( + reference.channel_id and Object(reference.channel_id) + ) + self.guild = state._get_guild(reference.guild_id) or ( + reference.guild_id and Object(reference.guild_id) + ) self.content: str = data["content"] self.embeds: list[Embed] = [Embed.from_dict(a) for a in data["embeds"]] self.attachments: list[Attachment] = [ @@ -750,7 +761,9 @@ def __init__( data: MessageSnapshotPayload, ): self._state: ConnectionState = state - self.message: ForwardedMessage = ForwardedMessage(state=state, reference=reference, data=data) + self.message: ForwardedMessage = ForwardedMessage( + state=state, reference=reference, data=data + ) def flatten_handlers(cls): @@ -1029,9 +1042,14 @@ def __init__( self.snapshots: list[MessageSnapshot] try: - self.snapshots = [MessageSnapshot( - state=state, reference=self.reference, data=ms, - ) for ms in data["message_snapshots"]] + self.snapshots = [ + MessageSnapshot( + state=state, + reference=self.reference, + data=ms, + ) + for ms in data["message_snapshots"] + ] except KeyError: self.snapshots = [] @@ -2060,7 +2078,9 @@ async def reply(self, content: str | None = None, **kwargs) -> Message: return await self.channel.send(content, reference=self.to_reference(), **kwargs) - async def forward(self, channel: MessageableChannel | PartialMessageableChannel, **kwargs) -> Message: + async def forward( + self, channel: MessageableChannel | PartialMessageableChannel, **kwargs + ) -> Message: """|coro| A shortcut method to :meth:`.abc.Messageable.send` to forward the @@ -2089,7 +2109,9 @@ async def forward(self, channel: MessageableChannel | PartialMessageableChannel, you specified both ``file`` and ``files``. """ - return await channel.send(reference=self.to_reference(type=MessageReferenceType.forward)) + return await channel.send( + reference=self.to_reference(type=MessageReferenceType.forward) + ) async def end_poll(self) -> Message: """|coro| @@ -2119,7 +2141,9 @@ async def end_poll(self) -> Message: return message - def to_reference(self, *, fail_if_not_exists: bool = True, type: MessageReferenceType = None) -> MessageReference: + def to_reference( + self, *, fail_if_not_exists: bool = True, type: MessageReferenceType = None + ) -> MessageReference: """Creates a :class:`~discord.MessageReference` from the current message. .. versionadded:: 1.6 @@ -2147,7 +2171,9 @@ def to_reference(self, *, fail_if_not_exists: bool = True, type: MessageReferenc self, fail_if_not_exists=fail_if_not_exists, type=type ) - def to_message_reference_dict(self, type: MessageReferenceType = None) -> MessageReferencePayload: + def to_message_reference_dict( + self, type: MessageReferenceType = None + ) -> MessageReferencePayload: data: MessageReferencePayload = { "message_id": self.id, "channel_id": self.channel.id, diff --git a/discord/types/embed.py b/discord/types/embed.py index 4321197692..60c5afea0d 100644 --- a/discord/types/embed.py +++ b/discord/types/embed.py @@ -76,7 +76,14 @@ class EmbedAuthor(TypedDict, total=False): EmbedType = Literal[ - "rich", "image", "video", "gifv", "article", "link", "auto_moderation_message", "poll_result" + "rich", + "image", + "video", + "gifv", + "article", + "link", + "auto_moderation_message", + "poll_result", ] From c99efe658bcdb87e684131bb43ded89b8dd05459 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 07:12:03 +0100 Subject: [PATCH 07/29] s --- discord/message.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/discord/message.py b/discord/message.py index 32161cff4a..be60593cb1 100644 --- a/discord/message.py +++ b/discord/message.py @@ -688,16 +688,6 @@ class ForwardedMessage: A list of components in the original message. """ - __slots__ = ( - "message_id", - "channel_id", - "guild_id", - "fail_if_not_exists", - "resolved", - "type", - "_state", - ) - def __init__( self, *, From dde7436d9a0cafba31e65b05f058d991a600c611 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 07:20:19 +0100 Subject: [PATCH 08/29] fix --- discord/message.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/discord/message.py b/discord/message.py index be60593cb1..70f1f9580a 100644 --- a/discord/message.py +++ b/discord/message.py @@ -696,6 +696,7 @@ def __init__( data: ForwardedMessagePayload, ): self._state: ConnectionState = state + self._reference = reference self.id: int = reference.message_id self.channel = state.get_channel(reference.channel_id) or ( reference.channel_id and Object(reference.channel_id) @@ -730,6 +731,11 @@ def edited_at(self) -> datetime.datetime | None: edited time of the original message. """ return self._edited_timestamp + + def __repr__(self) -> str: + return ( + f"" + ) class MessageSnapshot: @@ -751,9 +757,11 @@ def __init__( data: MessageSnapshotPayload, ): self._state: ConnectionState = state - self.message: ForwardedMessage = ForwardedMessage( - state=state, reference=reference, data=data - ) + self.message: ForwardedMessage | None + if fm := data.get("message"): + ForwardedMessage( + state=state, reference=reference, data=fm + ) def flatten_handlers(cls): From ea21897327a6eda8e0d65c74d388c04e38bebde2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 06:20:41 +0000 Subject: [PATCH 09/29] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/message.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/discord/message.py b/discord/message.py index 70f1f9580a..c015b15733 100644 --- a/discord/message.py +++ b/discord/message.py @@ -731,11 +731,9 @@ def edited_at(self) -> datetime.datetime | None: edited time of the original message. """ return self._edited_timestamp - + def __repr__(self) -> str: - return ( - f"" - ) + return f"" class MessageSnapshot: @@ -759,9 +757,7 @@ def __init__( self._state: ConnectionState = state self.message: ForwardedMessage | None if fm := data.get("message"): - ForwardedMessage( - state=state, reference=reference, data=fm - ) + ForwardedMessage(state=state, reference=reference, data=fm) def flatten_handlers(cls): From 3f6be7547e05cdf646a25f61a6c16d5c79881e83 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 07:24:29 +0100 Subject: [PATCH 10/29] final? --- discord/message.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discord/message.py b/discord/message.py index c015b15733..1d3617c33c 100644 --- a/discord/message.py +++ b/discord/message.py @@ -733,7 +733,7 @@ def edited_at(self) -> datetime.datetime | None: return self._edited_timestamp def __repr__(self) -> str: - return f"" + return f"" class MessageSnapshot: @@ -757,7 +757,7 @@ def __init__( self._state: ConnectionState = state self.message: ForwardedMessage | None if fm := data.get("message"): - ForwardedMessage(state=state, reference=reference, data=fm) + self.message = ForwardedMessage(state=state, reference=reference, data=fm) def flatten_handlers(cls): From cd632c343db19f49f3ab569e408415c80d0db0cc Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 07:34:32 +0100 Subject: [PATCH 11/29] fix import --- discord/abc.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index f121989404..ef63c2c8b0 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1587,7 +1587,8 @@ async def send( if reference is not None: try: - reference = reference.to_message_reference_dict() + _reference = reference.to_message_reference_dict() + from .message import MessageReference if not isinstance(reference, MessageReference): utils.warn_deprecated( f"Passing {type(reference).__name__} to reference", @@ -1632,7 +1633,7 @@ async def send( embeds=embeds, nonce=nonce, enforce_nonce=enforce_nonce, - message_reference=reference, + message_reference=_reference, stickers=stickers, components=components, flags=flags, @@ -1660,7 +1661,7 @@ async def send( nonce=nonce, enforce_nonce=enforce_nonce, allowed_mentions=allowed_mentions, - message_reference=reference, + message_reference=_reference, stickers=stickers, components=components, flags=flags, @@ -1679,7 +1680,7 @@ async def send( nonce=nonce, enforce_nonce=enforce_nonce, allowed_mentions=allowed_mentions, - message_reference=reference, + message_reference=_reference, stickers=stickers, components=components, flags=flags, From 74546979eb62499fc8b537bc078669154c96576c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 06:34:55 +0000 Subject: [PATCH 12/29] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/abc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/discord/abc.py b/discord/abc.py index ef63c2c8b0..9c127b7ea4 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1589,6 +1589,7 @@ async def send( try: _reference = reference.to_message_reference_dict() from .message import MessageReference + if not isinstance(reference, MessageReference): utils.warn_deprecated( f"Passing {type(reference).__name__} to reference", From 4bb20d84ea0387b8d42631f6402844a2f6a506b8 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 6 Oct 2024 07:37:39 +0100 Subject: [PATCH 13/29] frfr --- discord/abc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/discord/abc.py b/discord/abc.py index 9c127b7ea4..bb36bd0591 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1585,6 +1585,7 @@ async def send( allowed_mentions = allowed_mentions or AllowedMentions().to_dict() allowed_mentions["replied_user"] = bool(mention_author) + _reference = None if reference is not None: try: _reference = reference.to_message_reference_dict() From c7da3b810679e6ed2c33abb134f9fba3b4f24e3a Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Tue, 4 Feb 2025 18:40:35 +0100 Subject: [PATCH 14/29] conflict 1 --- discord/abc.py | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index 47b9c5578f..c7c9e54c31 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1625,27 +1625,7 @@ async def send( if file is not None: if not isinstance(file, File): raise InvalidArgument("file parameter must be File") - - try: - data = await state.http.send_files( - channel.id, - files=[file], - allowed_mentions=allowed_mentions, - content=content, - tts=tts, - embed=embed, - embeds=embeds, - nonce=nonce, - enforce_nonce=enforce_nonce, - message_reference=_reference, - stickers=stickers, - components=components, - flags=flags, - poll=poll, - ) - finally: - file.close() - + files = [file] elif files is not None: if len(files) > 10: raise InvalidArgument( From a4657dac3baeff8af3696564020a7e690f99ae2d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:41:43 +0000 Subject: [PATCH 15/29] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/enums.py | 1 - 1 file changed, 1 deletion(-) diff --git a/discord/enums.py b/discord/enums.py index 5d29eb4c61..b0f477c3a8 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -1078,7 +1078,6 @@ class SubscriptionStatus(Enum): inactive = 2 - T = TypeVar("T") From 1d6b0bfa308c558bf7b160e7d96e9197642d4e2e Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Tue, 4 Feb 2025 18:43:24 +0100 Subject: [PATCH 16/29] fix docstr --- discord/message.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discord/message.py b/discord/message.py index e7494f5502..10b3fb3a4d 100644 --- a/discord/message.py +++ b/discord/message.py @@ -2088,8 +2088,8 @@ async def forward( Parameters ---------- - channel: Union[:class:`Emoji`, :class:`Reaction`, :class:`PartialEmoji`, :class:`str`] - The emoji to react with. + channel: Union[:class:`TextChannel`, :class:`Thread`, :class:`DMChannel`, :class:`GroupChannel`, :class:`PartialMessageable`] + The channel to forward this to. Returns ------- From acd29ef31bb7b2797b0597d080617c99f21f4018 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Wed, 5 Feb 2025 18:53:43 +0100 Subject: [PATCH 17/29] adjustments --- discord/channel.py | 3 +++ discord/message.py | 24 +++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/discord/channel.py b/discord/channel.py index 687baa5e5a..be6c68b38a 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -3412,6 +3412,9 @@ def get_partial_message(self, message_id: int, /) -> PartialMessage: return PartialMessage(channel=self, id=message_id) + def __repr__(self) -> str: + return f"" + def _guild_channel_factory(channel_type: int): value = try_enum(ChannelType, channel_type) diff --git a/discord/message.py b/discord/message.py index 10b3fb3a4d..f87df0ec29 100644 --- a/discord/message.py +++ b/discord/message.py @@ -668,8 +668,14 @@ class ForwardedMessage: Attributes ---------- type: :class:`MessageType` - The type of message. In most cases this should not be checked, but it is helpful + The type of the original message. In most cases this should not be checked, but it is helpful in cases where it might be a system message for :attr:`system_content`. + original_message: Optional[Union[:class:`Message`, :class:`PartialMessage`]] + The original message that was forwarded, if available. + channel: Union[:class:`TextChannel`, :class:`Thread`, :class:`DMChannel`, :class:`GroupChannel`, :class:`PartialMessageable`] + The :class:`TextChannel` or :class:`Thread` that the original message was sent from. + guild: Optional[Union[:class:`Guild`, :class:`Object`]] + The guild that the original message belonged to, if applicable. content: :class:`str` The contents of the original message. embeds: List[:class:`Embed`] @@ -677,11 +683,11 @@ class ForwardedMessage: attachments: List[:class:`Attachment`] A list of attachments given to the original message. flags: :class:`MessageFlags` - Extra features of the message. + Extra features of the original message. mentions: List[Union[:class:`abc.User`, :class:`Object`]] - A list of :class:`Member` that were mentioned. + A list of :class:`Member` that were originally mentioned. role_mentions: List[Union[:class:`Role`, :class:`Object`]] - A list of :class:`Role` that were mentioned. + A list of :class:`Role` that were originally mentioned. stickers: List[:class:`StickerItem`] A list of sticker items given to the original message. components: List[:class:`Component`] @@ -699,8 +705,9 @@ def __init__( self._reference = reference self.id: int = reference.message_id self.channel = state.get_channel(reference.channel_id) or ( - reference.channel_id and Object(reference.channel_id) + reference.channel_id and PartialMessageable(state=state, id=reference.channel_id, ) ) + self.original_message = state.get_message(self.id) or (self.id and channel.get_partial_message(self.id)) self.guild = state._get_guild(reference.guild_id) or ( reference.guild_id and Object(reference.guild_id) ) @@ -759,6 +766,9 @@ def __init__( if fm := data.get("message"): self.message = ForwardedMessage(state=state, reference=reference, data=fm) + def __repr__(self) -> str: + return f"" + def flatten_handlers(cls): prefix = len("_handle_") @@ -2076,7 +2086,7 @@ async def reply(self, content: str | None = None, **kwargs) -> Message: return await self.channel.send(content, reference=self.to_reference(), **kwargs) - async def forward( + async def forward_to( self, channel: MessageableChannel | PartialMessageableChannel, **kwargs ) -> Message: """|coro| @@ -2108,7 +2118,7 @@ async def forward( """ return await channel.send( - reference=self.to_reference(type=MessageReferenceType.forward) + reference=self.to_reference(type=MessageReferenceType.forward), **kwargs ) async def end_poll(self) -> Message: From ac39fc36ef8d1d39f50ac6b5bda9433946333d70 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:54:09 +0000 Subject: [PATCH 18/29] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/message.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/discord/message.py b/discord/message.py index f87df0ec29..cf3486fe46 100644 --- a/discord/message.py +++ b/discord/message.py @@ -705,9 +705,15 @@ def __init__( self._reference = reference self.id: int = reference.message_id self.channel = state.get_channel(reference.channel_id) or ( - reference.channel_id and PartialMessageable(state=state, id=reference.channel_id, ) + reference.channel_id + and PartialMessageable( + state=state, + id=reference.channel_id, + ) + ) + self.original_message = state.get_message(self.id) or ( + self.id and channel.get_partial_message(self.id) ) - self.original_message = state.get_message(self.id) or (self.id and channel.get_partial_message(self.id)) self.guild = state._get_guild(reference.guild_id) or ( reference.guild_id and Object(reference.guild_id) ) From 63f16756e63dcfcdf0ef0a12998882b847b8e9a7 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Wed, 5 Feb 2025 18:55:57 +0100 Subject: [PATCH 19/29] _get_message --- discord/message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/message.py b/discord/message.py index cf3486fe46..9708dca92c 100644 --- a/discord/message.py +++ b/discord/message.py @@ -711,7 +711,7 @@ def __init__( id=reference.channel_id, ) ) - self.original_message = state.get_message(self.id) or ( + self.original_message = state._get_message(self.id) or ( self.id and channel.get_partial_message(self.id) ) self.guild = state._get_guild(reference.guild_id) or ( From 389ffa77e525a836cbcdbfe6dbbbde2c0cef29af Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Wed, 5 Feb 2025 19:07:52 +0100 Subject: [PATCH 20/29] fix reference kwarg --- discord/abc.py | 7 ++++--- discord/message.py | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index b6d45489ed..52777859f7 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1588,10 +1588,11 @@ async def send( _reference = None if reference is not None: try: - _reference = reference.to_message_reference_dict() from .message import MessageReference - - if not isinstance(reference, MessageReference): + if isinstance(reference, MessageReference): + _reference = reference + else: + _reference = reference.to_message_reference_dict() utils.warn_deprecated( f"Passing {type(reference).__name__} to reference", "MessageReference", diff --git a/discord/message.py b/discord/message.py index 9708dca92c..12262915b9 100644 --- a/discord/message.py +++ b/discord/message.py @@ -711,12 +711,12 @@ def __init__( id=reference.channel_id, ) ) - self.original_message = state._get_message(self.id) or ( - self.id and channel.get_partial_message(self.id) - ) self.guild = state._get_guild(reference.guild_id) or ( reference.guild_id and Object(reference.guild_id) ) + self.original_message = state._get_message(self.id) or ( + self.id and self.channel.get_partial_message(self.id) + ) self.content: str = data["content"] self.embeds: list[Embed] = [Embed.from_dict(a) for a in data["embeds"]] self.attachments: list[Attachment] = [ From 0d4919775983204b02a4e84bf645d9213fd8f45a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2025 18:08:18 +0000 Subject: [PATCH 21/29] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/abc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/discord/abc.py b/discord/abc.py index 52777859f7..3dc9575447 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1589,6 +1589,7 @@ async def send( if reference is not None: try: from .message import MessageReference + if isinstance(reference, MessageReference): _reference = reference else: From 579751a34ece5714879947098140981374925193 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Wed, 5 Feb 2025 19:13:37 +0100 Subject: [PATCH 22/29] undo --- discord/abc.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index 3dc9575447..b6d45489ed 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1588,12 +1588,10 @@ async def send( _reference = None if reference is not None: try: + _reference = reference.to_message_reference_dict() from .message import MessageReference - if isinstance(reference, MessageReference): - _reference = reference - else: - _reference = reference.to_message_reference_dict() + if not isinstance(reference, MessageReference): utils.warn_deprecated( f"Passing {type(reference).__name__} to reference", "MessageReference", From 95474f8ade4c38d771604eb0a6394ccfde9672cc Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Wed, 5 Feb 2025 21:41:37 +0100 Subject: [PATCH 23/29] add system_content support --- discord/message.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/discord/message.py b/discord/message.py index 12262915b9..f3f4167fa9 100644 --- a/discord/message.py +++ b/discord/message.py @@ -1433,11 +1433,14 @@ def system_content(self) -> str: regardless of the :attr:`Message.type`. In the case of :attr:`MessageType.default` and :attr:`MessageType.reply`\, - this just returns the regular :attr:`Message.content`. Otherwise, this + this just returns the regular :attr:`Message.content`, and forwarded messages + will display the original message's content from :attr:`Message.snapshots`. Otherwise, this returns an English message denoting the contents of the system message. """ if self.type is MessageType.default: + if self.snapshots: + return self.snapshots[0].message and self.snapshots[0].message.content return self.content if self.type is MessageType.recipient_add: From 39652ab9f939e1f9ffff70f2a81393879fcccb0b Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Wed, 5 Feb 2025 22:02:19 +0100 Subject: [PATCH 24/29] adjustments --- discord/ext/commands/context.py | 4 ++++ discord/message.py | 1 + 2 files changed, 5 insertions(+) diff --git a/discord/ext/commands/context.py b/discord/ext/commands/context.py index c140586faa..cbb9bf0fcf 100644 --- a/discord/ext/commands/context.py +++ b/discord/ext/commands/context.py @@ -403,3 +403,7 @@ async def send_help(self, *args: Any) -> Any: @discord.utils.copy_doc(Message.reply) async def reply(self, content: str | None = None, **kwargs: Any) -> Message: return await self.message.reply(content, **kwargs) + + @discord.utils.copy_doc(Message.forward_to) + async def forward_to(self, channel: discord.abc.Messageable, **kwargs: Any) -> Message: + return await self.message.forward_to(channel, **kwargs) diff --git a/discord/message.py b/discord/message.py index f3f4167fa9..2e7d320037 100644 --- a/discord/message.py +++ b/discord/message.py @@ -2255,6 +2255,7 @@ class PartialMessage(Hashable): clear_reaction = Message.clear_reaction clear_reactions = Message.clear_reactions reply = Message.reply + forward_to = Message.forward_to to_reference = Message.to_reference to_message_reference_dict = Message.to_message_reference_dict From 8879fd65cac0234be0f8934ff8f9f1aca9a3d457 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2025 21:02:50 +0000 Subject: [PATCH 25/29] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/ext/commands/context.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/discord/ext/commands/context.py b/discord/ext/commands/context.py index cbb9bf0fcf..e2be74a21b 100644 --- a/discord/ext/commands/context.py +++ b/discord/ext/commands/context.py @@ -405,5 +405,7 @@ async def reply(self, content: str | None = None, **kwargs: Any) -> Message: return await self.message.reply(content, **kwargs) @discord.utils.copy_doc(Message.forward_to) - async def forward_to(self, channel: discord.abc.Messageable, **kwargs: Any) -> Message: + async def forward_to( + self, channel: discord.abc.Messageable, **kwargs: Any + ) -> Message: return await self.message.forward_to(channel, **kwargs) From 01ef32ee5e06351a71f0a23fdd30043196f10038 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Thu, 6 Feb 2025 04:15:36 +0100 Subject: [PATCH 26/29] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f94bd51ec..f06ddeaf19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,8 @@ These changes are available on the `master` branch, but have not yet been releas ([#2579](https://github.com/Pycord-Development/pycord/pull/2579)) - Added new `Subscription` object and related methods/events. ([#2564](https://github.com/Pycord-Development/pycord/pull/2564)) +- Added `Message.forward_to`, `Message.snapshots` and related attributes. + ([#2598](https://github.com/Pycord-Development/pycord/pull/2598)) ### Fixed From cf98e47bb190feea3487cb9f32481193d1552eef Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Thu, 6 Feb 2025 04:04:36 +0000 Subject: [PATCH 27/29] add has_snapshot flag --- discord/flags.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/discord/flags.py b/discord/flags.py index 7073a56e35..3a4c8d27bc 100644 --- a/discord/flags.py +++ b/discord/flags.py @@ -411,6 +411,14 @@ def is_voice_message(self): """ return 8192 + @flag_value + def has_snapshot(self): + """:class:`bool`: Returns ``True`` if this message has a snapshot from message forwarding. + + .. versionadded:: 2.7 + """ + return 1 << 14 + @fill_with_flags() class PublicUserFlags(BaseFlags): From b78152a5d372e02f4cd121425c2d61304e920a3d Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Thu, 27 Mar 2025 07:59:33 +0100 Subject: [PATCH 28/29] Apply suggestions from code review Co-authored-by: JustaSqu1d <89910983+JustaSqu1d@users.noreply.github.com> Signed-off-by: Lala Sabathil --- CHANGELOG.md | 2 +- discord/enums.py | 2 +- discord/message.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46ca1d2e29..779a8fbb68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,7 +49,7 @@ These changes are available on the `master` branch, but have not yet been releas ([#2579](https://github.com/Pycord-Development/pycord/pull/2579)) - Added new `Subscription` object and related methods/events. ([#2564](https://github.com/Pycord-Development/pycord/pull/2564)) -- Added `Message.forward_to`, `Message.snapshots` and related attributes. +- Added `Message.forward_to`, `Message.snapshots`, and other related attributes. ([#2598](https://github.com/Pycord-Development/pycord/pull/2598)) - Added ability to change the API's base URL with `Route.API_BASE_URL`. ([#2714](https://github.com/Pycord-Development/pycord/pull/2714)) diff --git a/discord/enums.py b/discord/enums.py index b0f477c3a8..01d10275c8 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -1064,7 +1064,7 @@ class PollLayoutType(Enum): class MessageReferenceType(Enum): - """The message reference's type""" + """The type of the message reference object""" default = 0 forward = 1 diff --git a/discord/message.py b/discord/message.py index 2e7d320037..3523d84f83 100644 --- a/discord/message.py +++ b/discord/message.py @@ -482,7 +482,7 @@ class MessageReference: Attributes ---------- type: Optional[:class:`~discord.MessageReferenceType`] - The type of message reference. If this is not provided, assume default behavior (reply). + The type of message reference. If this is not provided, assume the default behavior (i.e., reply). .. versionadded:: 2.7 @@ -661,7 +661,7 @@ def ended_at(self) -> datetime.datetime | None: class ForwardedMessage: - """Represents the snapshotted contents from a forwarded message. Forwarded messages are immutable; any updates to the original message won't be reflected. + """Represents the snapshotted contents from a forwarded message. Forwarded messages are immutable; any updates to the original message will not be reflected. .. versionadded:: 2.7 From c51f5f434ecab0c8eeba2134414d59df1a0d68a9 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Fri, 16 May 2025 21:41:01 +0100 Subject: [PATCH 29/29] Update abc.py adjust wording --- discord/abc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index c38426f127..5c67c098c2 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1497,9 +1497,9 @@ async def send( .. versionadded:: 1.4 reference: Union[:class:`~discord.Message`, :class:`~discord.MessageReference`, :class:`~discord.PartialMessage`] - A reference to the :class:`~discord.Message` you are replying to or forwarding, this can be created using - :meth:`~discord.Message.to_reference` or passed directly as a :class:`~discord.Message`. When replying, you can control - whether this mentions the author of the referenced message using the + A reference to the :class:`~discord.Message` being replied to or forwarded. This can be created using + :meth:`~discord.Message.to_reference`. + When replying, you can control whether this mentions the author of the referenced message using the :attr:`~discord.AllowedMentions.replied_user` attribute of ``allowed_mentions`` or by setting ``mention_author``.