mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-02-13 18:11:06 +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):
|
class InlineResults(metaclass=NoPublicConstructor):
|
||||||
"""
|
|
||||||
:final:
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Optional
|
from typing import TYPE_CHECKING, Optional, Set
|
||||||
|
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
from ..types import AsyncList, ChatLike, File, Participant, RecentAction, build_chat_map
|
from ..types import AsyncList, ChatLike, File, Participant, RecentAction, build_chat_map
|
||||||
|
@ -21,6 +21,7 @@ class ParticipantList(AsyncList[Participant]):
|
||||||
self._chat = chat
|
self._chat = chat
|
||||||
self._peer: Optional[abcs.InputPeer] = None
|
self._peer: Optional[abcs.InputPeer] = None
|
||||||
self._offset = 0
|
self._offset = 0
|
||||||
|
self._seen: Set[int] = set()
|
||||||
|
|
||||||
async def _fetch_next(self) -> None:
|
async def _fetch_next(self) -> None:
|
||||||
if self._peer is None:
|
if self._peer is None:
|
||||||
|
@ -45,10 +46,17 @@ class ParticipantList(AsyncList[Participant]):
|
||||||
|
|
||||||
chat_map = build_chat_map(result.users, result.chats)
|
chat_map = build_chat_map(result.users, result.chats)
|
||||||
|
|
||||||
self._buffer.extend(
|
seen_count = len(self._seen)
|
||||||
Participant._from_raw_channel(p, chat_map) for p in result.participants
|
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._total = result.count
|
||||||
|
self._offset += len(result.participants)
|
||||||
|
self._done = len(self._seen) == seen_count
|
||||||
|
|
||||||
elif isinstance(self._peer, types.InputPeerChat):
|
elif isinstance(self._peer, types.InputPeerChat):
|
||||||
result = await self._client(
|
result = await self._client(
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from .admin_right import AdminRight
|
||||||
from .async_list import AsyncList
|
from .async_list import AsyncList
|
||||||
from .callback_answer import CallbackAnswer
|
from .callback_answer import CallbackAnswer
|
||||||
from .chat import (
|
from .chat import (
|
||||||
|
@ -22,6 +23,7 @@ from .password_token import PasswordToken
|
||||||
from .recent_action import RecentAction
|
from .recent_action import RecentAction
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"AdminRight",
|
||||||
"AsyncList",
|
"AsyncList",
|
||||||
"CallbackAnswer",
|
"CallbackAnswer",
|
||||||
"Channel",
|
"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 ...tl import abcs, types
|
||||||
from .chat import Chat
|
from .admin_right import AdminRight
|
||||||
|
from .chat import Chat, User, peer_id
|
||||||
from .meta import NoPublicConstructor
|
from .meta import NoPublicConstructor
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,3 +67,98 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
return cls._create(participant, chat_map)
|
return cls._create(participant, chat_map)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("unexpected case")
|
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.
|
Classes for the various objects the library returns.
|
||||||
"""
|
"""
|
||||||
from .._impl.client.types import (
|
from .._impl.client.types import (
|
||||||
|
AdminRight,
|
||||||
AsyncList,
|
AsyncList,
|
||||||
CallbackAnswer,
|
CallbackAnswer,
|
||||||
Channel,
|
Channel,
|
||||||
|
@ -22,6 +23,7 @@ from .._impl.client.types.buttons import Button, InlineButton
|
||||||
from .._impl.session import PackedChat, PackedType
|
from .._impl.session import PackedChat, PackedType
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"AdminRight",
|
||||||
"AsyncList",
|
"AsyncList",
|
||||||
"CallbackAnswer",
|
"CallbackAnswer",
|
||||||
"Channel",
|
"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