From bf61dd32af45ad1a4a3139db4ea90ee4d889d7b5 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Sat, 18 Sep 2021 14:16:19 +0200 Subject: [PATCH] Change the way iter_participants filters are specified --- readthedocs/misc/v2-migration-guide.rst | 25 ++++++++++++++++-- telethon/_client/chats.py | 28 +++++++++++++------- telethon/_client/telegramclient.py | 18 ++++++++----- telethon/_misc/enums.py | 35 ++++++++++++++++++------- telethon/enums.py | 1 + 5 files changed, 80 insertions(+), 27 deletions(-) diff --git a/readthedocs/misc/v2-migration-guide.rst b/readthedocs/misc/v2-migration-guide.rst index b28cf2bf..62a8bc30 100644 --- a/readthedocs/misc/v2-migration-guide.rst +++ b/readthedocs/misc/v2-migration-guide.rst @@ -240,6 +240,25 @@ The following ``utils`` methods no longer exist or have been made private: // 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 ----------------------------------------------------------- @@ -345,12 +364,14 @@ actually using. Now it returns an ``int`` value indicating the number of message 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. 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 ----------------------------------------------------- diff --git a/telethon/_client/chats.py b/telethon/_client/chats.py index 1aa0724d..ffa06ac7 100644 --- a/telethon/_client/chats.py +++ b/telethon/_client/chats.py @@ -5,7 +5,7 @@ import string import typing from .. import hints, errors, _tl -from .._misc import helpers, utils, requestiter, tlobject +from .._misc import helpers, utils, requestiter, tlobject, enums from ..types import _custom if typing.TYPE_CHECKING: @@ -95,15 +95,25 @@ class _ChatAction: class _ParticipantsIter(requestiter.RequestIter): async def _init(self, entity, filter, search): - if isinstance(filter, type): - if filter in (_tl.ChannelParticipantsBanned, - _tl.ChannelParticipantsKicked, - _tl.ChannelParticipantsSearch, - _tl.ChannelParticipantsContacts): - # These require a `q` parameter (support types for convenience) - filter = filter('') + if not filter: + if search: + filter = _tl.ChannelParticipantsSearch(search) 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) ty = helpers._entity_type(entity) diff --git a/telethon/_client/telegramclient.py b/telethon/_client/telegramclient.py index b1c07a35..839e1ea3 100644 --- a/telethon/_client/telegramclient.py +++ b/telethon/_client/telegramclient.py @@ -729,7 +729,7 @@ class TelegramClient: limit: float = (), *, 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. @@ -749,16 +749,22 @@ class TelegramClient: search (`str`, optional): 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 Note that you might not have permissions for some filter. This has no effect for normal chats or users. - .. note:: + The available filters are: - The filter :tl:`ChannelParticipantsBanned` will return - *restricted* users. If you want *banned* users you should - use :tl:`ChannelParticipantsKicked` instead. + * ``'admin'`` + * ``'bot'`` + * ``'kicked'`` + * ``'banned'`` + * ``'contact'`` Yields The :tl:`User` objects returned by :tl:`GetParticipants` diff --git a/telethon/_misc/enums.py b/telethon/_misc/enums.py index 107bbc31..edce6776 100644 --- a/telethon/_misc/enums.py +++ b/telethon/_misc/enums.py @@ -9,14 +9,29 @@ class ConnectionMode(Enum): HTTP = 'http' -def parse_conn_mode(mode): - if isinstance(mode, ConnectionMode): - return mode - elif isinstance(mode, str): - for cm in ConnectionMode: - if mode == cm.value: - return cm +class Participant(Enum): + ADMIN = 'admin' + BOT = 'bot' + KICKED = 'kicked' + BANNED = 'banned' + CONTACT = 'contact' - raise ValueError(f'unknown connection mode: {mode!r}') - else: - raise TypeError(f'not a valid connection mode: {type(mode).__name__!r}') + +def _mk_parser(cls): + 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) diff --git a/telethon/enums.py b/telethon/enums.py index 42e588c0..8de39a15 100644 --- a/telethon/enums.py +++ b/telethon/enums.py @@ -1,3 +1,4 @@ from ._misc.enums import ( ConnectionMode, + Participant, )