mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-02-03 13:14:31 +03:00
Fix getting and using participants
This commit is contained in:
parent
cea9fc6c77
commit
48bf78a855
|
@ -10,10 +10,6 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class InlineResults(metaclass=NoPublicConstructor):
|
||||
"""
|
||||
:final:
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
client: Client,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from typing import TYPE_CHECKING, Optional, Set
|
||||
|
||||
from ...tl import abcs, functions, types
|
||||
from ..types import AsyncList, ChatLike, File, Participant, RecentAction, build_chat_map
|
||||
|
@ -21,6 +21,7 @@ class ParticipantList(AsyncList[Participant]):
|
|||
self._chat = chat
|
||||
self._peer: Optional[abcs.InputPeer] = None
|
||||
self._offset = 0
|
||||
self._seen: Set[int] = set()
|
||||
|
||||
async def _fetch_next(self) -> None:
|
||||
if self._peer is None:
|
||||
|
@ -45,10 +46,17 @@ class ParticipantList(AsyncList[Participant]):
|
|||
|
||||
chat_map = build_chat_map(result.users, result.chats)
|
||||
|
||||
self._buffer.extend(
|
||||
Participant._from_raw_channel(p, chat_map) for p in result.participants
|
||||
)
|
||||
seen_count = len(self._seen)
|
||||
for p in result.participants:
|
||||
part = Participant._from_raw_channel(p, chat_map)
|
||||
pid = part._peer_id()
|
||||
if pid not in self._seen:
|
||||
self._seen.add(pid)
|
||||
self._buffer.append(part)
|
||||
|
||||
self._total = result.count
|
||||
self._offset += len(result.participants)
|
||||
self._done = len(self._seen) == seen_count
|
||||
|
||||
elif isinstance(self._peer, types.InputPeerChat):
|
||||
result = await self._client(
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from .admin_right import AdminRight
|
||||
from .async_list import AsyncList
|
||||
from .callback_answer import CallbackAnswer
|
||||
from .chat import (
|
||||
|
@ -22,6 +23,7 @@ from .password_token import PasswordToken
|
|||
from .recent_action import RecentAction
|
||||
|
||||
__all__ = [
|
||||
"AdminRight",
|
||||
"AsyncList",
|
||||
"CallbackAnswer",
|
||||
"Channel",
|
||||
|
|
104
client/src/telethon/_impl/client/types/admin_right.py
Normal file
104
client/src/telethon/_impl/client/types/admin_right.py
Normal file
|
@ -0,0 +1,104 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
from typing import Set
|
||||
|
||||
from ...tl import abcs, types
|
||||
|
||||
|
||||
class AdminRight(Enum):
|
||||
"""
|
||||
A right that can be granted to a chat's administrator.
|
||||
|
||||
.. note::
|
||||
|
||||
The specific values of the enumeration are not covered by `semver <https://semver.org/>`_.
|
||||
They also may do nothing in future updates if Telegram decides to change them.
|
||||
"""
|
||||
|
||||
CHANGE_INFO = "change_info"
|
||||
"""Allows editing the description in a group or channel."""
|
||||
|
||||
POST_MESSAGES = "post_messages"
|
||||
"""Allows sending messages in a broadcast channel."""
|
||||
|
||||
EDIT_MESSAGES = "edit_messages"
|
||||
"""Allows editing messages in a group or channel."""
|
||||
|
||||
DELETE_MESSAGES = "delete_messages"
|
||||
"""Allows deleting messages in a group or channel."""
|
||||
|
||||
BAN_USERS = "ban_users"
|
||||
"""Allows setting the banned rights of other users in a group or channel."""
|
||||
|
||||
INVITE_USERS = "invite_users"
|
||||
"""Allows inviting other users to the group or channel."""
|
||||
|
||||
PIN_MESSAGES = "pin_messages"
|
||||
"""Allows pinning a message to the group or channel."""
|
||||
|
||||
MANAGE_ADMINS = "add_admins"
|
||||
"""Allows setting the same or less administrator rights to other users in the group or channel."""
|
||||
|
||||
REMAIN_ANONYMOUS = "anonymous"
|
||||
"""Allows the administrator to remain anonymous."""
|
||||
|
||||
MANAGE_CALLS = "manage_call"
|
||||
"""Allows managing group or channel calls."""
|
||||
|
||||
OTHER = "other"
|
||||
"""Unspecified."""
|
||||
|
||||
MANAGE_TOPICS = "manage_topics"
|
||||
"""Allows managing the topics in a group."""
|
||||
|
||||
POST_STORIES = "post_stories"
|
||||
"""Allows posting stories in a channel."""
|
||||
|
||||
EDIT_STORIES = "edit_stories"
|
||||
"""Allows editing stories in a channel."""
|
||||
|
||||
DELETE_STORIES = "delete_stories"
|
||||
"""Allows deleting stories in a channel."""
|
||||
|
||||
@classmethod
|
||||
def _from_raw(cls, rights: abcs.ChatAdminRights) -> Set[AdminRight]:
|
||||
assert isinstance(rights, types.ChatAdminRights)
|
||||
all_rights = (
|
||||
cls.CHANGE_INFO if rights.change_info else None,
|
||||
cls.POST_MESSAGES if rights.post_messages else None,
|
||||
cls.EDIT_MESSAGES if rights.edit_messages else None,
|
||||
cls.DELETE_MESSAGES if rights.delete_messages else None,
|
||||
cls.BAN_USERS if rights.ban_users else None,
|
||||
cls.INVITE_USERS if rights.invite_users else None,
|
||||
cls.PIN_MESSAGES if rights.pin_messages else None,
|
||||
cls.MANAGE_ADMINS if rights.add_admins else None,
|
||||
cls.REMAIN_ANONYMOUS if rights.anonymous else None,
|
||||
cls.MANAGE_CALLS if rights.manage_call else None,
|
||||
cls.OTHER if rights.other else None,
|
||||
cls.MANAGE_TOPICS if rights.manage_topics else None,
|
||||
cls.POST_STORIES if rights.post_stories else None,
|
||||
cls.EDIT_STORIES if rights.edit_stories else None,
|
||||
cls.DELETE_STORIES if rights.delete_stories else None,
|
||||
)
|
||||
return set(filter(None, iter(all_rights)))
|
||||
|
||||
@classmethod
|
||||
def _chat_rights(cls) -> Set[AdminRight]:
|
||||
return {
|
||||
cls.CHANGE_INFO,
|
||||
cls.POST_MESSAGES,
|
||||
cls.EDIT_MESSAGES,
|
||||
cls.DELETE_MESSAGES,
|
||||
cls.BAN_USERS,
|
||||
cls.INVITE_USERS,
|
||||
cls.PIN_MESSAGES,
|
||||
cls.MANAGE_ADMINS,
|
||||
cls.REMAIN_ANONYMOUS,
|
||||
cls.MANAGE_CALLS,
|
||||
cls.OTHER,
|
||||
cls.MANAGE_TOPICS,
|
||||
cls.POST_STORIES,
|
||||
cls.EDIT_STORIES,
|
||||
cls.DELETE_STORIES,
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
from typing import Dict, Self, Union
|
||||
from typing import Dict, Optional, Self, Set, Union
|
||||
|
||||
from ...tl import abcs, types
|
||||
from .chat import Chat
|
||||
from .admin_right import AdminRight
|
||||
from .chat import Chat, User, peer_id
|
||||
from .meta import NoPublicConstructor
|
||||
|
||||
|
||||
|
@ -66,3 +67,98 @@ class Participant(metaclass=NoPublicConstructor):
|
|||
return cls._create(participant, chat_map)
|
||||
else:
|
||||
raise RuntimeError("unexpected case")
|
||||
|
||||
def _peer_id(self) -> int:
|
||||
if isinstance(
|
||||
self._raw,
|
||||
(
|
||||
types.ChannelParticipant,
|
||||
types.ChannelParticipantSelf,
|
||||
types.ChannelParticipantCreator,
|
||||
types.ChannelParticipantAdmin,
|
||||
types.ChatParticipant,
|
||||
types.ChatParticipantCreator,
|
||||
types.ChatParticipantAdmin,
|
||||
),
|
||||
):
|
||||
return self._raw.user_id
|
||||
elif isinstance(
|
||||
self._raw, (types.ChannelParticipantBanned, types.ChannelParticipantLeft)
|
||||
):
|
||||
return peer_id(self._raw.peer)
|
||||
else:
|
||||
raise RuntimeError("unexpected case")
|
||||
|
||||
@property
|
||||
def user(self) -> Optional[User]:
|
||||
"""
|
||||
The user participant that is currently present in the chat.
|
||||
|
||||
This will be :data:`None` if the participant was instead :attr:`banned` or has :attr:`left`.
|
||||
"""
|
||||
if isinstance(
|
||||
self._raw,
|
||||
(
|
||||
types.ChannelParticipant,
|
||||
types.ChannelParticipantSelf,
|
||||
types.ChannelParticipantCreator,
|
||||
types.ChannelParticipantAdmin,
|
||||
types.ChatParticipant,
|
||||
types.ChatParticipantCreator,
|
||||
types.ChatParticipantAdmin,
|
||||
),
|
||||
):
|
||||
user = self._chat_map[self._raw.user_id]
|
||||
assert isinstance(user, User)
|
||||
return user
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def banned(self) -> Optional[Chat]:
|
||||
"""
|
||||
The banned participant.
|
||||
|
||||
This will usually be a :class:`User`.
|
||||
"""
|
||||
if isinstance(self._raw, types.ChannelParticipantBanned):
|
||||
return self._chat_map[peer_id(self._raw.peer)]
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def left(self) -> Optional[Chat]:
|
||||
"""
|
||||
The participant that has left the group.
|
||||
|
||||
This will usually be a :class:`User`.
|
||||
"""
|
||||
if isinstance(self._raw, types.ChannelParticipantLeft):
|
||||
return self._chat_map[peer_id(self._raw.peer)]
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def creator(self) -> bool:
|
||||
"""
|
||||
:data:`True` if the participant is the creator of the chat.
|
||||
"""
|
||||
return isinstance(
|
||||
self._raw, (types.ChannelParticipantCreator, types.ChatParticipantCreator)
|
||||
)
|
||||
|
||||
@property
|
||||
def admin_rights(self) -> Optional[Set[AdminRight]]:
|
||||
"""
|
||||
The set of administrator rights this participant has been granted, if they are an administrator.
|
||||
"""
|
||||
if isinstance(
|
||||
self._raw, (types.ChannelParticipantCreator, types.ChannelParticipantAdmin)
|
||||
):
|
||||
return AdminRight._from_raw(self._raw.admin_rights)
|
||||
elif isinstance(
|
||||
self._raw, (types.ChatParticipantCreator, types.ChatParticipantAdmin)
|
||||
):
|
||||
return AdminRight._chat_rights()
|
||||
else:
|
||||
return None
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
Classes for the various objects the library returns.
|
||||
"""
|
||||
from .._impl.client.types import (
|
||||
AdminRight,
|
||||
AsyncList,
|
||||
CallbackAnswer,
|
||||
Channel,
|
||||
|
@ -22,6 +23,7 @@ from .._impl.client.types.buttons import Button, InlineButton
|
|||
from .._impl.session import PackedChat, PackedType
|
||||
|
||||
__all__ = [
|
||||
"AdminRight",
|
||||
"AsyncList",
|
||||
"CallbackAnswer",
|
||||
"Channel",
|
||||
|
|
14
client/tests/types_test.py
Normal file
14
client/tests/types_test.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from pytest import mark
|
||||
from telethon._impl.client.types import AdminRight
|
||||
from telethon._impl.tl import types
|
||||
|
||||
|
||||
@mark.parametrize("slot", types.ChatAdminRights.__slots__)
|
||||
def test_admin_right_covers_all(slot: str) -> None:
|
||||
kwargs = {slot: False for slot in types.ChatAdminRights.__slots__}
|
||||
kwargs[slot] = True
|
||||
|
||||
rights = types.ChatAdminRights(**kwargs)
|
||||
rights_set = AdminRight._from_raw(rights)
|
||||
assert len(rights_set) == 1
|
||||
assert next(iter(rights_set)).value == slot
|
Loading…
Reference in New Issue
Block a user