diff options
| author | NCPlayz <[email protected]> | 2019-03-14 12:38:02 +0000 |
|---|---|---|
| committer | Rapptz <[email protected]> | 2019-03-19 09:00:18 -0400 |
| commit | f507f508a2aa56305ac90bd222f49af9cf47c49b (patch) | |
| tree | a9ba58dde45156651f76196c06514a622e7fa6a8 /discord/iterators.py | |
| parent | Organise documentation (diff) | |
| download | discord.py-f507f508a2aa56305ac90bd222f49af9cf47c49b.tar.xz discord.py-f507f508a2aa56305ac90bd222f49af9cf47c49b.zip | |
Expose Metadata
Added access to:
* `/users/@me/guilds`
* `/guilds/{guild_id}`
* `/guilds/{guild_id}/members/{member_id}`
BREAKING CHANGE:
* `get_user_info` -> `fetch_user_info` to match naming scheme.
Remove useless note
Remove `reverse` and corresponding documentation
Update documentation to reflect #1988
Rename `get_` HTTP functions to `fetch_`
Breaking Changes:
* `get_message` -> `fetch_message`
* `get_invite` -> `fetch_invite`
* `get_user_profile` -> `fetch_user_profile`
* `get_webhook_info` -> `fetch_webhook`
* `get_ban` -> `fetch_ban`
Fix InviteConverter, update migrating.rst
Rename get_message to fetch_message
Diffstat (limited to 'discord/iterators.py')
| -rw-r--r-- | discord/iterators.py | 132 |
1 files changed, 131 insertions, 1 deletions
diff --git a/discord/iterators.py b/discord/iterators.py index d77592a5..015620bc 100644 --- a/discord/iterators.py +++ b/discord/iterators.py @@ -237,7 +237,7 @@ class HistoryIterator(_AsyncIterator): elif self.limit == 101: self.limit = 100 # Thanks discord elif self.limit == 1: - raise ValueError("Use get_message.") + raise ValueError("Use fetch_message.") self._retrieve_messages = self._retrieve_messages_around_strategy if self.before and self.after: @@ -459,3 +459,133 @@ class AuditLogIterator(_AsyncIterator): continue await self.entries.put(AuditLogEntry(data=element, users=self._users, guild=self.guild)) + + +class GuildIterator(_AsyncIterator): + """Iterator for receiving the client's guilds. + + The guilds endpoint has the same two behaviours as described + in :class:`HistoryIterator`: + If `before` is specified, the guilds endpoint returns the `limit` + newest guilds before `before`, sorted with newest first. For filling over + 100 guilds, update the `before` parameter to the oldest guild received. + Guilds will be returned in order by time. + If `after` is specified, it returns the `limit` oldest guilds after `after`, + sorted with newest first. For filling over 100 guilds, update the `after` + parameter to the newest guild received, If guilds are not reversed, they + will be out of order (99-0, 199-100, so on) + + Not that if both before and after are specified, before is ignored by the + guilds endpoint. + + Parameters + ----------- + bot: :class:`discord.Client` + The client to retrieve the guilds from. + limit: :class:`int` + Maximum number of guilds to retrieve. + before: :class:`Snowflake` + Object before which all guilds must be. + after: :class:`Snowflake` + Object after which all guilds must be. + """ + def __init__(self, bot, limit, before=None, after=None): + + if isinstance(before, datetime.datetime): + before = Object(id=time_snowflake(before, high=False)) + if isinstance(after, datetime.datetime): + after = Object(id=time_snowflake(after, high=True)) + + self.bot = bot + self.limit = limit + self.before = before + self.after = after + + self._filter = None + + self.state = self.bot._connection + self.get_guilds = self.bot.http.get_guilds + self.guilds = asyncio.Queue(loop=self.state.loop) + + if self.before and self.after: + self._retrieve_guilds = self._retrieve_guilds_before_strategy + self._filter = lambda m: int(m['id']) > self.after.id + elif self.after: + self._retrieve_guilds = self._retrieve_guilds_after_strategy + else: + self._retrieve_guilds = self._retrieve_guilds_before_strategy + + async def next(self): + if self.guilds.empty(): + await self.fill_guilds() + + try: + return self.guilds.get_nowait() + except asyncio.QueueEmpty: + raise NoMoreItems() + + def _get_retrieve(self): + l = self.limit + if l is None: + r = 100 + elif l <= 100: + r = l + else: + r = 100 + + self.retrieve = r + return r > 0 + + def create_guild(self, data): + from .guild import Guild + return Guild(state=self.state, data=data) + + async def flatten(self): + result = [] + while self._get_retrieve(): + data = await self._retrieve_guilds(self.retrieve) + if len(data) < 100: + self.limit = 0 + + if self._filter: + data = filter(self._filter, data) + + for element in data: + result.append(self.create_guild(element)) + return result + + async def fill_guilds(self): + if self._get_retrieve(): + data = await self._retrieve_guilds(self.retrieve) + if self.limit is None or len(data) < 100: + self.limit = 0 + + if self._filter: + data = filter(self._filter, data) + + for element in data: + await self.guilds.put(self.create_guild(element)) + + async def _retrieve_guilds(self, retrieve): + """Retrieve guilds and update next parameters.""" + pass + + async def _retrieve_guilds_before_strategy(self, retrieve): + """Retrieve guilds using before parameter.""" + before = self.before.id if self.before else None + data = await self.get_guilds(retrieve, before=before) + if len(data): + if self.limit is not None: + self.limit -= retrieve + self.before = Object(id=int(data[-1]['id'])) + return data + + async def _retrieve_guilds_after_strategy(self, retrieve): + """Retrieve guilds using after parameter.""" + after = self.after.id if self.after else None + data = await self.get_guilds(retrieve, after=after) + if len(data): + if self.limit is not None: + self.limit -= retrieve + self.after = Object(id=int(data[0]['id'])) + return data |