Change the way iter_participants filters are specified

This commit is contained in:
Lonami Exo 2021-09-18 14:16:19 +02:00
parent 8114fb6c9b
commit bf61dd32af
5 changed files with 80 additions and 27 deletions

View File

@ -240,6 +240,25 @@ The following ``utils`` methods no longer exist or have been made private:
// TODO provide the new clean utils // TODO provide the new clean utils
Changes on how to configure filters for certain client methods
--------------------------------------------------------------
Before, ``client.iter_participants`` (and ``get_participants``) would expect a type or instance
of the raw Telegram definition as a ``filter``. Now, this ``filter`` expects a string.
The supported values are:
* ``'admin'``
* ``'bot'``
* ``'kicked'``
* ``'banned'``
* ``'contact'``
If you prefer to avoid hardcoding strings, you may use ``telethon.enums.Participant``.
// TODO maintain support for the old way of doing it?
// TODO now that there's a custom filter, filter client-side for small chats?
The custom.Message class and the way it is used has changed The custom.Message class and the way it is used has changed
----------------------------------------------------------- -----------------------------------------------------------
@ -345,12 +364,14 @@ actually using. Now it returns an ``int`` value indicating the number of message
and were deleted. and were deleted.
The aggressive parameter hack has been removed Changes to the methods to retrieve participants
---------------------------------------------- -----------------------------------------------
The "aggressive" hack in ``get_participants`` (and ``iter_participants``) is now gone. The "aggressive" hack in ``get_participants`` (and ``iter_participants``) is now gone.
It was not reliable, and was a cause of flood wait errors. It was not reliable, and was a cause of flood wait errors.
The ``search`` parameter is no longer ignored when ``filter`` is specified.
The total value when getting participants has changed The total value when getting participants has changed
----------------------------------------------------- -----------------------------------------------------

View File

@ -5,7 +5,7 @@ import string
import typing import typing
from .. import hints, errors, _tl from .. import hints, errors, _tl
from .._misc import helpers, utils, requestiter, tlobject from .._misc import helpers, utils, requestiter, tlobject, enums
from ..types import _custom from ..types import _custom
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
@ -95,15 +95,25 @@ class _ChatAction:
class _ParticipantsIter(requestiter.RequestIter): class _ParticipantsIter(requestiter.RequestIter):
async def _init(self, entity, filter, search): async def _init(self, entity, filter, search):
if isinstance(filter, type): if not filter:
if filter in (_tl.ChannelParticipantsBanned, if search:
_tl.ChannelParticipantsKicked, filter = _tl.ChannelParticipantsSearch(search)
_tl.ChannelParticipantsSearch,
_tl.ChannelParticipantsContacts):
# These require a `q` parameter (support types for convenience)
filter = filter('')
else: else:
filter = filter() filter = _tl.ChannelParticipantsRecent()
else:
filter = enums.parse_participant(filter)
if filter == enums.Participant.ADMIN:
filter = _tl.ChannelParticipantsAdmins()
elif filter == enums.Participant.BOT:
filter = _tl.ChannelParticipantsBots()
elif filter == enums.Participant.KICKED:
filter = _tl.ChannelParticipantsKicked(search)
elif filter == enums.Participant.BANNED:
filter = _tl.ChannelParticipantsBanned(search)
elif filter == enums.Participant.CONTACT:
filter = _tl.ChannelParticipantsContacts(search)
else:
raise RuntimeError('unhandled enum variant')
entity = await self.client.get_input_entity(entity) entity = await self.client.get_input_entity(entity)
ty = helpers._entity_type(entity) ty = helpers._entity_type(entity)

View File

@ -729,7 +729,7 @@ class TelegramClient:
limit: float = (), limit: float = (),
*, *,
search: str = '', search: str = '',
filter: '_tl.TypeChannelParticipantsFilter' = None) -> chats._ParticipantsIter: filter: typing.Union[str, enums.Participant] = ()) -> chats._ParticipantsIter:
""" """
Iterator over the participants belonging to the specified chat. Iterator over the participants belonging to the specified chat.
@ -749,16 +749,22 @@ class TelegramClient:
search (`str`, optional): search (`str`, optional):
Look for participants with this string in name/username. Look for participants with this string in name/username.
filter (:tl:`ChannelParticipantsFilter`, optional): Note that the search is only compatible with some ``filter``
when fetching members from a channel or megagroup. This may
change in the future.
filter (`str`, 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.
This has no effect for normal chats or users. This has no effect for normal chats or users.
.. note:: The available filters are:
The filter :tl:`ChannelParticipantsBanned` will return * ``'admin'``
*restricted* users. If you want *banned* users you should * ``'bot'``
use :tl:`ChannelParticipantsKicked` instead. * ``'kicked'``
* ``'banned'``
* ``'contact'``
Yields Yields
The :tl:`User` objects returned by :tl:`GetParticipants` The :tl:`User` objects returned by :tl:`GetParticipants`

View File

@ -9,14 +9,29 @@ class ConnectionMode(Enum):
HTTP = 'http' HTTP = 'http'
def parse_conn_mode(mode): class Participant(Enum):
if isinstance(mode, ConnectionMode): ADMIN = 'admin'
return mode BOT = 'bot'
elif isinstance(mode, str): KICKED = 'kicked'
for cm in ConnectionMode: BANNED = 'banned'
if mode == cm.value: CONTACT = 'contact'
return cm
raise ValueError(f'unknown connection mode: {mode!r}')
else: def _mk_parser(cls):
raise TypeError(f'not a valid connection mode: {type(mode).__name__!r}') def parser(value):
if isinstance(value, cls):
return value
elif isinstance(value, str):
for variant in cls:
if value == variant.value:
return variant
raise ValueError(f'unknown {cls.__name__}: {value!r}')
else:
raise TypeError(f'not a valid {cls.__name__}: {type(value).__name__!r}')
return parser
parse_conn_mode = _mk_parser(ConnectionMode)
parse_participant = _mk_parser(Participant)

View File

@ -1,3 +1,4 @@
from ._misc.enums import ( from ._misc.enums import (
ConnectionMode, ConnectionMode,
Participant,
) )