Browse Source

Implement `Guild.fetch_members`

Also implements `MemberIterator`.
pull/2255/head
NCPlayz 6 years ago
committed by Rapptz
parent
commit
851f83c821
  1. 49
      discord/guild.py
  2. 10
      discord/http.py
  3. 41
      discord/iterators.py

49
discord/guild.py

@ -41,7 +41,7 @@ from .enums import VoiceRegion, Status, ChannelType, try_enum, VerificationLevel
from .mixins import Hashable
from .user import User
from .invite import Invite
from .iterators import AuditLogIterator
from .iterators import AuditLogIterator, MemberIterator
from .webhook import Webhook
from .widget import Widget
from .asset import Asset
@ -1152,6 +1152,53 @@ class Guild(Hashable):
return [convert(d) for d in data]
def fetch_members(self, *, limit=1, after=None):
"""|coro|
Retrieves an :class:`.AsyncIterator` that enables receiving the guild's members.
.. note::
This method is an API call. For general usage, consider :attr:`members` instead.
.. versionadded:: 1.3.0
All parameters are optional.
Parameters
----------
limit: Optional[:class:`int`]
The number of members to retrieve.
Defaults to 1.
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.
Raises
------
HTTPException
Getting the members failed.
Yields
------
:class:`.Member`
The member with the member data parsed.
Examples
--------
Usage ::
async for member in guild.fetch_members(limit=150):
print(member.name)
Flattening into a list ::
members = await guild.fetch_members(limit=150).flatten()
# members is now a list of Member...
"""
return MemberIterator(self, limit=limit, after=after)
async def fetch_member(self, member_id):
"""|coro|

10
discord/http.py

@ -621,6 +621,16 @@ class HTTPClient:
def get_all_guild_channels(self, guild_id):
return self.request(Route('GET', '/guilds/{guild_id}/channels', guild_id=guild_id))
def get_members(self, guild_id, limit, after):
params = {
'limit': limit,
}
if after:
params['after'] = after
r = Route('GET', '/guilds/{guild_id}/members', guild_id=guild_id)
return self.request(r, params=params)
def get_member(self, guild_id, member_id):
return self.request(Route('GET', '/guilds/{guild_id}/members/{member_id}', guild_id=guild_id, member_id=member_id))

41
discord/iterators.py

@ -587,3 +587,44 @@ class GuildIterator(_AsyncIterator):
self.limit -= retrieve
self.after = Object(id=int(data[0]['id']))
return data
class MemberIterator(_AsyncIterator):
def __init__(self, guild, limit=1, after=None):
if isinstance(after, datetime.datetime):
after = Object(id=time_snowflake(after, high=True))
self.guild = guild
self.limit = limit
self.after = after or OLDEST_OBJECT
self.state = self.guild._state
self.get_members = self.state.http.get_members
self.members = asyncio.Queue(loop=self.state.loop)
async def next(self):
if self.members.empty():
await self.fill_members()
try:
return self.members.get_nowait()
except asyncio.QueueEmpty:
raise NoMoreItems()
async def fill_members(self):
if self.limit > 0:
retrieve = self.limit if self.limit <= 1000 else 1000
after = self.after.id if self.after else None
data = await self.get_members(self.guild.id, retrieve, after)
if data:
self.limit -= retrieve
self.after = Object(id=int(data[-1]['user']['id']))
for element in reversed(data):
await self.members.put(self.create_member(element))
def create_member(self, data):
from .member import Member
return Member(data=data, guild=self.guild, state=self.state)

Loading…
Cancel
Save