From bfaf8ecfdb2323f66f95b61d32e6b87277d4616a Mon Sep 17 00:00:00 2001 From: Rapptz Date: Sun, 12 Jan 2020 02:44:09 -0500 Subject: [PATCH] Allow Guild.fetch_members to take in limit=None Fixes #2473 --- discord/guild.py | 8 ++++---- discord/iterators.py | 30 ++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index b617e8ac2..fa7b320c6 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -633,7 +633,7 @@ class Guild(Hashable): @property def discovery_splash_url(self): """:class:`Asset`: Returns the guild's discovery splash asset. - + .. versionadded:: 1.3.0 """ return self.discovery_splash_url_as() @@ -1130,7 +1130,7 @@ class Guild(Hashable): return [convert(d) for d in data] - def fetch_members(self, *, limit=1, after=None): + def fetch_members(self, *, limit=1000, after=None): """|coro| Retrieves an :class:`.AsyncIterator` that enables receiving the guild's members. @@ -1146,8 +1146,8 @@ class Guild(Hashable): Parameters ---------- limit: Optional[:class:`int`] - The number of members to retrieve. - Defaults to 1. + The number of members to retrieve. Defaults to 1000. + Pass ``None`` to fetch all members. Note that this is potentially slow. after: Optional[Union[:class:`.abc.Snowflake`, :class:`datetime.datetime`]] Retrieve members after this date or object. If a date is provided it must be a timezone-naive datetime representing UTC time. diff --git a/discord/iterators.py b/discord/iterators.py index 556e41cab..b555daa5c 100644 --- a/discord/iterators.py +++ b/discord/iterators.py @@ -589,7 +589,7 @@ class GuildIterator(_AsyncIterator): return data class MemberIterator(_AsyncIterator): - def __init__(self, guild, limit=1, after=None): + def __init__(self, guild, limit=1000, after=None): if isinstance(after, datetime.datetime): after = Object(id=time_snowflake(after, high=True)) @@ -611,16 +611,30 @@ class MemberIterator(_AsyncIterator): except asyncio.QueueEmpty: raise NoMoreItems() - async def fill_members(self): - if self.limit > 0: - retrieve = self.limit if self.limit <= 1000 else 1000 + def _get_retrieve(self): + l = self.limit + if l is None: + r = 1000 + elif l <= 1000: + r = l + else: + r = 1000 + self.retrieve = r + return r > 0 + + async def fill_members(self): + if self._get_retrieve(): after = self.after.id if self.after else None - data = await self.get_members(self.guild.id, retrieve, after) + data = await self.get_members(self.guild.id, self.retrieve, after) + if not data: + # no data, terminate + return - if data: - self.limit -= retrieve - self.after = Object(id=int(data[-1]['user']['id'])) + if len(data) < 1000: + self.limit = 0 # terminate loop + + self.after = Object(id=int(data[-1]['user']['id'])) for element in reversed(data): await self.members.put(self.create_member(element))