Fix async iterators requesting past their bounds

This affects Messageable.history, ScheduledEvent.users, 
Client.fetch_guilds, and Guild.audit_logs.

To illustrate the problem, Messageable.history counted returned
messages to tell when to stop iteration, but did so before filtering
away those past the before or after boundaries. When both 
oldest_first=False and an after boundary were provided, this led to the
history iterator continuing to retrieve messages older than the after
boundary, which would then all be filtered away, continuing until the
message limit or the beginning of the entire channel was reached. 

A similar situation would also occur with oldest_first=True and a
before boundary provided.

This commit changes the logic in these methods to count items after
filtering, so they stop requesting more as soon as the in-bounds items
are exhausted.
This commit is contained in:
Eta
2022-11-27 00:43:24 -06:00
committed by GitHub
parent 324dfe0163
commit 4122bef8ee
4 changed files with 33 additions and 25 deletions

View File

@ -560,25 +560,27 @@ class ScheduledEvent(Hashable):
predicate = lambda u: u['user']['id'] > after.id
while True:
retrieve = min(100 if limit is None else limit, 100)
retrieve = 100 if limit is None else min(limit, 100)
if retrieve < 1:
return
data, state, limit = await strategy(retrieve, state, limit)
if len(data) < 100:
limit = 0
if reverse:
data = reversed(data)
if predicate:
data = filter(predicate, data)
users = (self._state.store_user(raw_user['user']) for raw_user in data)
count = 0
for user in users:
for count, user in enumerate(users, 1):
yield user
if count < 100:
# There's no data left after this
break
def _add_user(self, user: User) -> None:
self._users[user.id] = user