Browse Source

Make it paginate instead using the after param

pull/10205/head
Soheab_ 4 weeks ago
parent
commit
e59658418c
  1. 110
      discord/abc.py
  2. 5
      discord/http.py

110
discord/abc.py

@ -1710,15 +1710,20 @@ class Messageable:
data = await self._state.http.get_message(channel.id, id) data = await self._state.http.get_message(channel.id, id)
return self._state.create_message(channel=channel, data=data) return self._state.create_message(channel=channel, data=data)
async def pins(self, *, before: Optional[datetime] = None, limit: Optional[int] = None) -> List[Message]: async def pins(
"""|coro| self,
*,
Retrieves a maximum of 50 pinned messages from the destination. limit: Optional[int] = None,
before: SnowflakeTime = MISSING,
after: SnowflakeTime = MISSING,
) -> AsyncIterator[Message]:
"""Retrieves an :term:`asynchronous iterator` of the pinned messages in the channel.
Requires the :attr:`~discord.Permissions.view_channel` permission. You must have :attr:`~discord.Permissions.view_channel` and
:attr:`~discord.Permissions.read_message_history` to get these.
No pins will be returned if the user is missing the .. versionchanged:: 2.6
:attr:`~discord.Permissions.read_message_history` permission. Due to a change in Discord's API, this now returns a paginated iterator instead of a list.
.. note:: .. note::
@ -1729,15 +1734,22 @@ class Messageable:
Parameters Parameters
----------- -----------
before: Optional[:class:`datetime.datetime`] before: Optional[:class:`datetime.datetime`]
Retrieve pinned messages before this time. Retrieve pinned messages before this time or snowflake.
If a datetime is provided, it is recommended to use a UTC aware datetime. 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. If the datetime is naive, it is assumed to be local time.
.. versionadded:: 2.6 .. versionadded:: 2.6
limit: Optional[int] after: Optional[:class:`datetime.datetime`]
The maximum number of pinned messages to retrieve. Defaults to 50. Retrieve pinned messages after this time or snowflake.
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.
This must be a number between 2 and 50. .. versionadded:: 2.6
limit: Optional[int]
The number of pinned messages to retrieve. If ``None``, it retrieves
every pinned message in the channel. Note, however, that this would
make it a slow operation.
Defaults to ``50``.
.. versionadded:: 2.6 .. versionadded:: 2.6
@ -1755,23 +1767,69 @@ class Messageable:
List[:class:`~discord.Message`] List[:class:`~discord.Message`]
The messages that are currently pinned. The messages that are currently pinned.
""" """
if before is not None: if before is not MISSING and after is not MISSING:
if not isinstance(before, datetime): raise TypeError('pins pagination does not support both before and after')
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.'
)
state = self._state endpoint = self._state.http.pins_from
channel = await self._get_channel() channel = await self._get_channel()
data = await state.http.pins_from(channel.id, before=before.isoformat() if before else None, limit=limit) state = self._state
ret: List[Message] = []
for m in data["items"]: async def _before_strategy(retrieve: int, before: Optional[SnowflakeTime], limit: Optional[int]):
message = state.create_message(channel=channel, data=m["message"]) before_time = (
message._pinned_at = utils.parse_time(m.get("pinned_at")) before.isoformat()
ret.append(message) if isinstance(before, datetime)
return ret else utils.snowflake_time(before.id).isoformat()
if before
else None
)
data = await endpoint(channel.id, limit=retrieve, before=before_time)
if data and data['items']:
if limit is not None:
limit -= len(data)
before = utils.parse_time(data['items'][-1]['pinned_at'])
return data, before, limit
async def _after_strategy(retrieve: int, after: Optional[SnowflakeTime], limit: Optional[int]):
after_time = (
after.isoformat()
if isinstance(after, datetime)
else utils.snowflake_time(after.id).isoformat()
if after
else None
)
data = await endpoint(channel.id, limit=retrieve, after=after_time)
if data and data['items']:
if limit is not None:
limit -= len(data)
after = utils.parse_time(data['items'][-1]['pinned_at'])
return data, after, limit
if before:
strategy, time = _before_strategy, before
else:
strategy, time = _after_strategy, after
while True:
retrieve = 50 if limit is None else min(limit, 50)
if retrieve < 1:
return
data, time, limit = await strategy(retrieve, time, limit)
# Terminate loop on next iteration; there's no data left after this
if len(data) < 50:
limit = 0
for m in data["items"]:
message = state.create_message(channel=channel, data=m['message'])
message._pinned_at = utils.parse_time(m['pinned_at'])
yield message
async def history( async def history(
self, self,

5
discord/http.py

@ -1059,12 +1059,15 @@ class HTTPClient:
def pins_from( def pins_from(
self, self,
channel_id: Snowflake, channel_id: Snowflake,
before: Optional[str] = None,
limit: Optional[int] = None, limit: Optional[int] = None,
before: Optional[str] = None,
after: Optional[str] = None,
) -> Response[message.ChannelPins]: ) -> Response[message.ChannelPins]:
params = {} params = {}
if before is not None: if before is not None:
params['before'] = before params['before'] = before
if after is not None:
params['after'] = after
if limit is not None: if limit is not None:
params['limit'] = limit params['limit'] = limit

Loading…
Cancel
Save