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
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
-----------------------------------------------------

View File

@ -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)

View File

@ -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`

View File

@ -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)

View File

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