Ignore aggressive parameter in iter_participants

It's broken (it causes flood wait immediately).
Closes #3787.
This commit is contained in:
Lonami Exo 2022-09-20 17:35:25 +02:00
parent e6ebe6b334
commit d7424ccb90

View File

@ -97,7 +97,7 @@ class _ChatAction:
class _ParticipantsIter(RequestIter): class _ParticipantsIter(RequestIter):
async def _init(self, entity, filter, search, aggressive): async def _init(self, entity, filter, search):
if isinstance(filter, type): if isinstance(filter, type):
if filter in (types.ChannelParticipantsBanned, if filter in (types.ChannelParticipantsBanned,
types.ChannelParticipantsKicked, types.ChannelParticipantsKicked,
@ -122,7 +122,8 @@ class _ParticipantsIter(RequestIter):
self.filter_entity = lambda ent: True self.filter_entity = lambda ent: True
# Only used for channels, but we should always set the attribute # Only used for channels, but we should always set the attribute
self.requests = [] # Called `requests` even though it's just one for legacy purposes.
self.requests = None
if ty == helpers._EntityType.CHANNEL: if ty == helpers._EntityType.CHANNEL:
if self.limit <= 0: if self.limit <= 0:
@ -133,22 +134,13 @@ class _ParticipantsIter(RequestIter):
raise StopAsyncIteration raise StopAsyncIteration
self.seen = set() self.seen = set()
if aggressive and not filter: self.requests = functions.channels.GetParticipantsRequest(
self.requests.extend(functions.channels.GetParticipantsRequest( channel=entity,
channel=entity, filter=filter or types.ChannelParticipantsSearch(search),
filter=types.ChannelParticipantsSearch(x), offset=0,
offset=0, limit=_MAX_PARTICIPANTS_CHUNK_SIZE,
limit=_MAX_PARTICIPANTS_CHUNK_SIZE, hash=0
hash=0 )
) for x in (search or string.ascii_lowercase))
else:
self.requests.append(functions.channels.GetParticipantsRequest(
channel=entity,
filter=filter or types.ChannelParticipantsSearch(search),
offset=0,
limit=_MAX_PARTICIPANTS_CHUNK_SIZE,
hash=0
))
elif ty == helpers._EntityType.CHAT: elif ty == helpers._EntityType.CHAT:
full = await self.client( full = await self.client(
@ -190,21 +182,14 @@ class _ParticipantsIter(RequestIter):
if not self.requests: if not self.requests:
return True return True
# Only care about the limit for the first request self.requests.limit = min(self.limit - self.requests.offset, _MAX_PARTICIPANTS_CHUNK_SIZE)
# (small amount of people, won't be aggressive).
#
# Most people won't care about getting exactly 12,345
# members so it doesn't really matter not to be 100%
# precise with being out of the offset/limit here.
self.requests[0].limit = min(
self.limit - self.requests[0].offset, _MAX_PARTICIPANTS_CHUNK_SIZE)
if self.requests[0].offset > self.limit: if self.requests.offset > self.limit:
return True return True
if self.total is None: if self.total is None:
f = self.requests[0].filter f = self.requests.filter
if len(self.requests) > 1 or ( if (
not isinstance(f, types.ChannelParticipantsRecent) not isinstance(f, types.ChannelParticipantsRecent)
and (not isinstance(f, types.ChannelParticipantsSearch) or f.q) and (not isinstance(f, types.ChannelParticipantsSearch) or f.q)
): ):
@ -212,42 +197,40 @@ class _ParticipantsIter(RequestIter):
# if there's a filter which would reduce the real total number. # if there's a filter which would reduce the real total number.
# getParticipants is cheaper than getFull. # getParticipants is cheaper than getFull.
self.total = (await self.client(functions.channels.GetParticipantsRequest( self.total = (await self.client(functions.channels.GetParticipantsRequest(
channel=self.requests[0].channel, channel=self.requests.channel,
filter=types.ChannelParticipantsRecent(), filter=types.ChannelParticipantsRecent(),
offset=0, offset=0,
limit=1, limit=1,
hash=0 hash=0
))).count ))).count
results = await self.client(self.requests) participants = await self.client(self.requests)
for i in reversed(range(len(self.requests))): if self.total is None:
participants = results[i] # Will only get here if there was one request with a filter that matched all users.
if self.total is None: self.total = participants.count
# Will only get here if there was one request with a filter that matched all users. if not participants.users:
self.total = participants.count self.requests = None
if not participants.users: return
self.requests.pop(i)
continue
self.requests[i].offset += len(participants.participants) self.requests.offset += len(participants.participants)
users = {user.id: user for user in participants.users} users = {user.id: user for user in participants.users}
for participant in participants.participants: for participant in participants.participants:
if isinstance(participant, types.ChannelParticipantBanned): if isinstance(participant, types.ChannelParticipantBanned):
if not isinstance(participant.peer, types.PeerUser): if not isinstance(participant.peer, types.PeerUser):
# May have the entire channel banned. See #3105. # May have the entire channel banned. See #3105.
continue
user_id = participant.peer.user_id
else:
user_id = participant.user_id
user = users[user_id]
if not self.filter_entity(user) or user.id in self.seen:
continue continue
self.seen.add(user_id) user_id = participant.peer.user_id
user = users[user_id] else:
user.participant = participant user_id = participant.user_id
self.buffer.append(user)
user = users[user_id]
if not self.filter_entity(user) or user.id in self.seen:
continue
self.seen.add(user_id)
user = users[user_id]
user.participant = participant
self.buffer.append(user)
class _AdminLogIter(RequestIter): class _AdminLogIter(RequestIter):
@ -431,9 +414,6 @@ class ChatMethods:
search (`str`, optional): search (`str`, optional):
Look for participants with this string in name/username. Look for participants with this string in name/username.
If ``aggressive is True``, the symbols from this string will
be used.
filter (:tl:`ChannelParticipantsFilter`, optional): filter (:tl:`ChannelParticipantsFilter`, optional):
The filter to be used, if you want e.g. only admins The filter to be used, if you want e.g. only admins
Note that you might not have permissions for some filter. Note that you might not have permissions for some filter.
@ -446,14 +426,11 @@ class ChatMethods:
use :tl:`ChannelParticipantsKicked` instead. use :tl:`ChannelParticipantsKicked` instead.
aggressive (`bool`, optional): aggressive (`bool`, optional):
Aggressively looks for all participants in the chat. Does nothing. This is kept for backwards-compatibility.
This is useful for channels since 20 July 2018, There have been several changes to Telegram's API that limits
Telegram added a server-side limit where only the the amount of members that can be retrieved, and this was a
first 200 members can be retrieved. With this flag hack that no longer works.
set, more than 200 will be often be retrieved.
This has no effect if a ``filter`` is given.
Yields Yields
The :tl:`User` objects returned by :tl:`GetParticipantsRequest` The :tl:`User` objects returned by :tl:`GetParticipantsRequest`
@ -482,8 +459,7 @@ class ChatMethods:
limit, limit,
entity=entity, entity=entity,
filter=filter, filter=filter,
search=search, search=search
aggressive=aggressive
) )
async def get_participants( async def get_participants(