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

@ -1774,24 +1774,26 @@ class Messageable:
channel = await self._get_channel()
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)
# Terminate loop on next iteration; there's no data left after this
if len(data) < 100:
limit = 0
if reverse:
data = reversed(data)
if predicate:
data = filter(predicate, data)
for raw_message in data:
count = 0
for count, raw_message in enumerate(data, 1):
yield self._state.create_message(channel=channel, data=raw_message)
if count < 100:
# There's no data left after this
break
class Connectable(Protocol):
"""An ABC that details the common operations on a channel that can