From 7d7b2f5ed9f85e0b9b683ac6478b6b260a5e2cfb Mon Sep 17 00:00:00 2001 From: Soheab_ <33902984+Soheab@users.noreply.github.com> Date: Sat, 14 Jun 2025 15:44:59 +0200 Subject: [PATCH] Add Message.pinned_at and fix Message.pins --- discord/abc.py | 20 ++++++++++++-------- discord/http.py | 2 +- discord/message.py | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index a570510ee..28c858317 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1710,7 +1710,7 @@ class Messageable: data = await self._state.http.get_message(channel.id, id) return self._state.create_message(channel=channel, data=data) - async def pins(self, *, before: Optional[SnowflakeTime] = None, limit: Optional[int] = None) -> List[Message]: + async def pins(self, *, before: Optional[datetime] = None, limit: Optional[int] = None) -> List[Message]: """|coro| Retrieves a maximum of 50 pinned messages from the destination. @@ -1728,8 +1728,8 @@ class Messageable: Parameters ----------- - before: Optional[Union[:class:`~discord.abc.Snowflake`, :class:`datetime.datetime`]] - Retrieve pinned messages before this date or message. + before: Optional[:class:`datetime.datetime`] + Retrieve pinned messages before this time. If a datetime is provided, it is recommended to use a UTC aware datetime. If the datetime is naive, it is assumed to be local time. limit: Optional[int] @@ -1749,13 +1749,17 @@ class Messageable: List[:class:`~discord.Message`] The messages that are currently pinned. """ - if isinstance(before, datetime): - before = Object(id=utils.time_snowflake(before, high=False)) + state = self._state + if before is not None: + if not isinstance(before, datetime): + raise TypeError(f'before must be a datetime object, not {before.__class__!r}') + if before.tzinfo is None: + raise TypeError( + 'before must be an aware datetime. Consider using discord.utils.utcnow() or datetime.datetime.now().astimezone() for local time.' + ) channel = await self._get_channel() - state = self._state - data = await state.http.pins_from(channel.id, before=before.id if before else None, limit=limit) - return [state.create_message(channel=channel, data=m["message"]) for m in data["items"]] + data = await state.http.pins_from(channel.id, before=before.isoformat() if before else None, limit=limit) async def history( self, diff --git a/discord/http.py b/discord/http.py index aa2488d8a..cd6008bc7 100644 --- a/discord/http.py +++ b/discord/http.py @@ -1054,7 +1054,7 @@ class HTTPClient: def pins_from( self, channel_id: Snowflake, - before: Optional[Snowflake] = None, + before: Optional[str] = None, limit: Optional[int] = None, ) -> Response[message.ChannelPins]: params = {} diff --git a/discord/message.py b/discord/message.py index 547e9c433..7487efb27 100644 --- a/discord/message.py +++ b/discord/message.py @@ -2171,6 +2171,7 @@ class Message(PartialMessage, Hashable): 'call', 'purchase_notification', 'message_snapshots', + '_pinned_at', ) if TYPE_CHECKING: @@ -2210,6 +2211,8 @@ class Message(PartialMessage, Hashable): self.application_id: Optional[int] = utils._get_as_snowflake(data, 'application_id') self.stickers: List[StickerItem] = [StickerItem(data=d, state=state) for d in data.get('sticker_items', [])] self.message_snapshots: List[MessageSnapshot] = MessageSnapshot._from_value(state, data.get('message_snapshots')) + # Set by Messageable.pins + self._pinned_at: Optional[datetime.datetime] = None self.poll: Optional[Poll] = None try: @@ -2629,6 +2632,18 @@ class Message(PartialMessage, Hashable): if self.guild is not None: # Fall back to guild threads in case one was created after the message return self._thread or self.guild.get_thread(self.id) + + @property + def pinned_at(self) -> Optional[datetime.datetime]: + """Optional[:class:`datetime.datetime`]: An aware UTC datetime object containing the time + when the message was pinned. + + .. note:: + This is only set for messages that are returned by :meth:`Messageable.pins`. + + .. versionadded:: 2.6 + """ + return self._pinned_at @property @deprecated('interaction_metadata')