mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-02-09 16:10:51 +03:00
Improve setting of chat participants rights
This commit is contained in:
parent
48bf78a855
commit
95e1f5115c
|
@ -244,14 +244,17 @@ The simplest approach could be using a global ``states`` dictionary storing the
|
||||||
This is not a thing in Telegram.
|
This is not a thing in Telegram.
|
||||||
It was implemented by restricting and then removing the restriction.
|
It was implemented by restricting and then removing the restriction.
|
||||||
|
|
||||||
The old ``client.edit_permissions()`` was renamed to :meth:`Client.set_banned_rights`.
|
The old ``client.edit_permissions()`` was renamed to :meth:`Client.set_participant_restrictions`.
|
||||||
This defines the rights a restricted participant has (bans them from doing other things).
|
This defines the restrictions a banned participant has applied (bans them from doing those things).
|
||||||
Revoking the right to view messages will kick them.
|
Revoking the right to view messages will kick them.
|
||||||
This rename should avoid confusion, as it is now clear this is not to promote users to admin status.
|
This rename should avoid confusion, as it is now clear this is not to promote users to admin status.
|
||||||
|
|
||||||
For administrators, ``client.edit_admin`` was renamed to :meth:`Client.set_admin_rights` for consistency.
|
For administrators, ``client.edit_admin`` was renamed to :meth:`Client.set_participant_admin_rights` for consistency.
|
||||||
|
|
||||||
Note that a new method, :meth:`Client.set_default_rights`, must now be used to set a chat's default rights.
|
You can also use the aliases on the :class:`~types.Participant`, :meth:`types.Participant.set_restrictions` and :meth:`types.Participant.set_admin_rights`.
|
||||||
|
|
||||||
|
Note that a new method, :meth:`Client.set_chat_default_restrictions`, must now be used to set a chat's default rights.
|
||||||
|
You can also use the alias on the :class:`~types.Group`, :meth:`types.Group.set_default_restrictions`.
|
||||||
|
|
||||||
.. rubric:: No ``client.download_profile_photo()`` method.
|
.. rubric:: No ``client.download_profile_photo()`` method.
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,20 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Optional, Set
|
import datetime
|
||||||
|
from typing import TYPE_CHECKING, Optional, Sequence, Set
|
||||||
|
|
||||||
|
from ...session import PackedChat
|
||||||
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 (
|
||||||
|
AdminRight,
|
||||||
|
AsyncList,
|
||||||
|
ChatLike,
|
||||||
|
ChatRestriction,
|
||||||
|
File,
|
||||||
|
Participant,
|
||||||
|
RecentAction,
|
||||||
|
build_chat_map,
|
||||||
|
)
|
||||||
from .messages import SearchList
|
from .messages import SearchList
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
@ -19,65 +30,65 @@ class ParticipantList(AsyncList[Participant]):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._client = client
|
self._client = client
|
||||||
self._chat = chat
|
self._chat = chat
|
||||||
self._peer: Optional[abcs.InputPeer] = None
|
self._packed: Optional[PackedChat] = None
|
||||||
self._offset = 0
|
self._offset = 0
|
||||||
self._seen: Set[int] = set()
|
self._seen: Set[int] = set()
|
||||||
|
|
||||||
async def _fetch_next(self) -> None:
|
async def _fetch_next(self) -> None:
|
||||||
if self._peer is None:
|
if self._packed is None:
|
||||||
self._peer = (
|
self._packed = await self._client._resolve_to_packed(self._chat)
|
||||||
await self._client._resolve_to_packed(self._chat)
|
|
||||||
)._to_input_peer()
|
|
||||||
|
|
||||||
if isinstance(self._peer, types.InputPeerChannel):
|
if self._packed.is_channel():
|
||||||
result = await self._client(
|
chanp = await self._client(
|
||||||
functions.channels.get_participants(
|
functions.channels.get_participants(
|
||||||
channel=types.InputChannel(
|
channel=self._packed._to_input_channel(),
|
||||||
channel_id=self._peer.channel_id,
|
|
||||||
access_hash=self._peer.access_hash,
|
|
||||||
),
|
|
||||||
filter=types.ChannelParticipantsRecent(),
|
filter=types.ChannelParticipantsRecent(),
|
||||||
offset=self._offset,
|
offset=self._offset,
|
||||||
limit=200,
|
limit=200,
|
||||||
hash=0,
|
hash=0,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert isinstance(result, types.channels.ChannelParticipants)
|
assert isinstance(chanp, types.channels.ChannelParticipants)
|
||||||
|
|
||||||
chat_map = build_chat_map(result.users, result.chats)
|
chat_map = build_chat_map(self._client, chanp.users, chanp.chats)
|
||||||
|
|
||||||
seen_count = len(self._seen)
|
seen_count = len(self._seen)
|
||||||
for p in result.participants:
|
for p in chanp.participants:
|
||||||
part = Participant._from_raw_channel(p, chat_map)
|
part = Participant._from_raw_channel(
|
||||||
|
self._client, self._packed, p, chat_map
|
||||||
|
)
|
||||||
pid = part._peer_id()
|
pid = part._peer_id()
|
||||||
if pid not in self._seen:
|
if pid not in self._seen:
|
||||||
self._seen.add(pid)
|
self._seen.add(pid)
|
||||||
self._buffer.append(part)
|
self._buffer.append(part)
|
||||||
|
|
||||||
self._total = result.count
|
self._total = chanp.count
|
||||||
self._offset += len(result.participants)
|
self._offset += len(chanp.participants)
|
||||||
self._done = len(self._seen) == seen_count
|
self._done = len(self._seen) == seen_count
|
||||||
|
|
||||||
elif isinstance(self._peer, types.InputPeerChat):
|
elif self._packed.is_chat():
|
||||||
result = await self._client(
|
chatp = await self._client(
|
||||||
functions.messages.get_full_chat(chat_id=self._peer.chat_id) # type: ignore [arg-type]
|
functions.messages.get_full_chat(chat_id=self._packed.id)
|
||||||
)
|
)
|
||||||
assert isinstance(result, types.messages.ChatFull)
|
assert isinstance(chatp, types.messages.ChatFull)
|
||||||
assert isinstance(result.full_chat, types.ChatFull)
|
assert isinstance(chatp.full_chat, types.ChatFull)
|
||||||
|
|
||||||
chat_map = build_chat_map(result.users, result.chats)
|
chat_map = build_chat_map(self._client, chatp.users, chatp.chats)
|
||||||
|
|
||||||
participants = result.full_chat.participants
|
participants = chatp.full_chat.participants
|
||||||
if isinstance(participants, types.ChatParticipantsForbidden):
|
if isinstance(participants, types.ChatParticipantsForbidden):
|
||||||
if participants.self_participant:
|
if participants.self_participant:
|
||||||
self._buffer.append(
|
self._buffer.append(
|
||||||
Participant._from_raw_chat(
|
Participant._from_raw_chat(
|
||||||
participants.self_participant, chat_map
|
self._client,
|
||||||
|
self._packed,
|
||||||
|
participants.self_participant,
|
||||||
|
chat_map,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif isinstance(participants, types.ChatParticipants):
|
elif isinstance(participants, types.ChatParticipants):
|
||||||
self._buffer.extend(
|
self._buffer.extend(
|
||||||
Participant._from_raw_chat(p, chat_map)
|
Participant._from_raw_chat(self._client, self._packed, p, chat_map)
|
||||||
for p in participants.participants
|
for p in participants.participants
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -122,7 +133,7 @@ class RecentActionList(AsyncList[RecentAction]):
|
||||||
)
|
)
|
||||||
assert isinstance(result, types.channels.AdminLogResults)
|
assert isinstance(result, types.channels.AdminLogResults)
|
||||||
|
|
||||||
chat_map = build_chat_map(result.users, result.chats)
|
chat_map = build_chat_map(self._client, result.users, result.chats)
|
||||||
self._buffer.extend(RecentAction._create(e, chat_map) for e in result.events)
|
self._buffer.extend(RecentAction._create(e, chat_map) for e in result.events)
|
||||||
self._total += len(self._buffer)
|
self._total += len(self._buffer)
|
||||||
|
|
||||||
|
@ -184,13 +195,82 @@ def get_profile_photos(self: Client, chat: ChatLike) -> AsyncList[File]:
|
||||||
return ProfilePhotoList(self, chat)
|
return ProfilePhotoList(self, chat)
|
||||||
|
|
||||||
|
|
||||||
def set_banned_rights(self: Client, chat: ChatLike, user: ChatLike) -> None:
|
async def set_participant_admin_rights(
|
||||||
pass
|
self: Client, chat: ChatLike, user: ChatLike, rights: Sequence[AdminRight]
|
||||||
|
) -> None:
|
||||||
|
packed = await self._resolve_to_packed(chat)
|
||||||
|
participant = await self._resolve_to_packed(user)
|
||||||
|
|
||||||
|
if packed.is_channel():
|
||||||
|
admin_rights = AdminRight._set_to_raw(set(rights))
|
||||||
|
await self(
|
||||||
|
functions.channels.edit_admin(
|
||||||
|
channel=packed._to_input_channel(),
|
||||||
|
user_id=participant._to_input_user(),
|
||||||
|
admin_rights=admin_rights,
|
||||||
|
rank="",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif packed.is_chat():
|
||||||
|
await self(
|
||||||
|
functions.messages.edit_chat_admin(
|
||||||
|
chat_id=packed.id,
|
||||||
|
user_id=participant._to_input_user(),
|
||||||
|
is_admin=bool(rights),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise TypeError(f"Cannot set admin rights in {packed.ty}")
|
||||||
|
|
||||||
|
|
||||||
def set_admin_rights(self: Client, chat: ChatLike, user: ChatLike) -> None:
|
async def set_participant_restrictions(
|
||||||
pass
|
self: Client,
|
||||||
|
chat: ChatLike,
|
||||||
|
user: ChatLike,
|
||||||
|
restrictions: Sequence[ChatRestriction],
|
||||||
|
*,
|
||||||
|
until: Optional[datetime.datetime] = None,
|
||||||
|
) -> None:
|
||||||
|
packed = await self._resolve_to_packed(chat)
|
||||||
|
participant = await self._resolve_to_packed(user)
|
||||||
|
if packed.is_channel():
|
||||||
|
banned_rights = ChatRestriction._set_to_raw(
|
||||||
|
set(restrictions),
|
||||||
|
until_date=int(until.timestamp()) if until else 0x7FFFFFFF,
|
||||||
|
)
|
||||||
|
await self(
|
||||||
|
functions.channels.edit_banned(
|
||||||
|
channel=packed._to_input_channel(),
|
||||||
|
participant=participant._to_input_peer(),
|
||||||
|
banned_rights=banned_rights,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif packed.is_chat():
|
||||||
|
if restrictions:
|
||||||
|
await self(
|
||||||
|
functions.messages.delete_chat_user(
|
||||||
|
revoke_history=ChatRestriction.VIEW_MESSAGES in restrictions,
|
||||||
|
chat_id=packed.id,
|
||||||
|
user_id=participant._to_input_user(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise TypeError(f"Cannot set banned rights in {packed.ty}")
|
||||||
|
|
||||||
|
|
||||||
def set_default_rights(self: Client, chat: ChatLike, user: ChatLike) -> None:
|
async def set_chat_default_restrictions(
|
||||||
pass
|
self: Client,
|
||||||
|
chat: ChatLike,
|
||||||
|
restrictions: Sequence[ChatRestriction],
|
||||||
|
*,
|
||||||
|
until: Optional[datetime.datetime] = None,
|
||||||
|
) -> None:
|
||||||
|
peer = (await self._resolve_to_packed(chat))._to_input_peer()
|
||||||
|
banned_rights = ChatRestriction._set_to_raw(
|
||||||
|
set(restrictions), int(until.timestamp()) if until else 0x7FFFFFFF
|
||||||
|
)
|
||||||
|
await self(
|
||||||
|
functions.messages.edit_chat_default_banned_rights(
|
||||||
|
peer=peer, banned_rights=banned_rights
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -13,6 +13,7 @@ from typing import (
|
||||||
Literal,
|
Literal,
|
||||||
Optional,
|
Optional,
|
||||||
Self,
|
Self,
|
||||||
|
Sequence,
|
||||||
Tuple,
|
Tuple,
|
||||||
Type,
|
Type,
|
||||||
TypeVar,
|
TypeVar,
|
||||||
|
@ -35,9 +36,11 @@ from ...tl import Request, abcs
|
||||||
from ..events import Event
|
from ..events import Event
|
||||||
from ..events.filters import Filter
|
from ..events.filters import Filter
|
||||||
from ..types import (
|
from ..types import (
|
||||||
|
AdminRight,
|
||||||
AsyncList,
|
AsyncList,
|
||||||
Chat,
|
Chat,
|
||||||
ChatLike,
|
ChatLike,
|
||||||
|
ChatRestriction,
|
||||||
Dialog,
|
Dialog,
|
||||||
Draft,
|
Draft,
|
||||||
File,
|
File,
|
||||||
|
@ -66,9 +69,9 @@ from .chats import (
|
||||||
get_admin_log,
|
get_admin_log,
|
||||||
get_participants,
|
get_participants,
|
||||||
get_profile_photos,
|
get_profile_photos,
|
||||||
set_admin_rights,
|
set_chat_default_restrictions,
|
||||||
set_banned_rights,
|
set_participant_admin_rights,
|
||||||
set_default_rights,
|
set_participant_restrictions,
|
||||||
)
|
)
|
||||||
from .dialogs import delete_dialog, edit_draft, get_dialogs, get_drafts
|
from .dialogs import delete_dialog, edit_draft, get_dialogs, get_drafts
|
||||||
from .files import (
|
from .files import (
|
||||||
|
@ -1700,14 +1703,46 @@ class Client:
|
||||||
caption_html=caption_html,
|
caption_html=caption_html,
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_admin_rights(self, chat: ChatLike, user: ChatLike) -> None:
|
async def set_chat_default_restrictions(
|
||||||
set_admin_rights(self, chat, user)
|
self,
|
||||||
|
chat: ChatLike,
|
||||||
|
restrictions: Sequence[ChatRestriction],
|
||||||
|
*,
|
||||||
|
until: Optional[datetime.datetime] = None,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Set the default restrictions to apply to all participant in a chat.
|
||||||
|
|
||||||
def set_banned_rights(self, chat: ChatLike, user: ChatLike) -> None:
|
:param chat:
|
||||||
set_banned_rights(self, chat, user)
|
The :term:`chat` where the restrictions will be applied.
|
||||||
|
|
||||||
def set_default_rights(self, chat: ChatLike, user: ChatLike) -> None:
|
:param restrictions:
|
||||||
set_default_rights(self, chat, user)
|
The sequence of restrictions to apply.
|
||||||
|
|
||||||
|
:param until:
|
||||||
|
Date until which the restrictions should be applied.
|
||||||
|
By default, restrictions apply for as long as possible.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from telethon.types import ChatRestriction
|
||||||
|
|
||||||
|
# Don't allow anyone except administrators to send stickers for a day
|
||||||
|
await client.set_chat_default_restrictions(
|
||||||
|
chat, user, [ChatRestriction.SEND_STICKERS],
|
||||||
|
until=datetime.now() + timedelta(days=1))
|
||||||
|
|
||||||
|
# Remove all default restrictions from the chat
|
||||||
|
await client.set_chat_default_restrictions(chat, user, [])
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`telethon.types.Group.set_default_restrictions`
|
||||||
|
"""
|
||||||
|
await set_chat_default_restrictions(self, chat, restrictions, until=until)
|
||||||
|
|
||||||
def set_handler_filter(
|
def set_handler_filter(
|
||||||
self,
|
self,
|
||||||
|
@ -1737,6 +1772,102 @@ class Client:
|
||||||
"""
|
"""
|
||||||
set_handler_filter(self, handler, filter)
|
set_handler_filter(self, handler, filter)
|
||||||
|
|
||||||
|
async def set_participant_admin_rights(
|
||||||
|
self, chat: ChatLike, user: ChatLike, rights: Sequence[AdminRight]
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Set the administrator rights granted to the participant in the chat.
|
||||||
|
|
||||||
|
If an empty sequence of rights is given, the user will be demoted and stop being an administrator.
|
||||||
|
|
||||||
|
In small group chats, there are no separate administrator rights.
|
||||||
|
In this case, granting any right will make the user an administrator with all rights.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the rights will be granted.
|
||||||
|
|
||||||
|
:param participant:
|
||||||
|
The participant to promote to administrator, usually a :class:`types.User`.
|
||||||
|
|
||||||
|
:param rights:
|
||||||
|
The sequence of rights to grant.
|
||||||
|
Can be empty to revoke the administrator status from the participant.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from telethon.types import AdminRight
|
||||||
|
|
||||||
|
# Make user an administrator allowed to pin messages
|
||||||
|
await client.set_participant_admin_rights(
|
||||||
|
chat, user, [AdminRight.PIN_MESSAGES])
|
||||||
|
|
||||||
|
# Demote an administrator
|
||||||
|
await client.set_participant_admin_rights(chat, user, [])
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`telethon.types.Participant.set_admin_rights`
|
||||||
|
"""
|
||||||
|
await set_participant_admin_rights(self, chat, user, rights)
|
||||||
|
|
||||||
|
async def set_participant_restrictions(
|
||||||
|
self,
|
||||||
|
chat: ChatLike,
|
||||||
|
user: ChatLike,
|
||||||
|
restrictions: Sequence[ChatRestriction],
|
||||||
|
*,
|
||||||
|
until: Optional[datetime.datetime] = None,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Set the restrictions to apply to a participant in the chat.
|
||||||
|
|
||||||
|
Restricting the participant to :attr:`~types.ChatRestriction.VIEW_MESSAGES` will kick them out of the chat.
|
||||||
|
|
||||||
|
In small group chats, there are no separate restrictions.
|
||||||
|
In this case, any restriction will kick the participant.
|
||||||
|
The participant's history will be revoked if the restriction to :attr:`~types.ChatRestriction.VIEW_MESSAGES` is applied.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the restrictions will be applied.
|
||||||
|
|
||||||
|
:param participant:
|
||||||
|
The participant to restrict or ban, usually a :class:`types.User`.
|
||||||
|
|
||||||
|
:param restrictions:
|
||||||
|
The sequence of restrictions to apply.
|
||||||
|
Can be empty to remove all restrictions from the participant and unban them.
|
||||||
|
|
||||||
|
:param until:
|
||||||
|
Date until which the restrictions should be applied.
|
||||||
|
By default, restrictions apply for as long as possible.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from telethon.types import ChatRestriction
|
||||||
|
|
||||||
|
# Kick the user out of the chat
|
||||||
|
await client.set_participant_restrictions(
|
||||||
|
chat, user, [ChatRestriction.VIEW_MESSAGES])
|
||||||
|
|
||||||
|
# Don't allow the user to send media for 5 minutes
|
||||||
|
await client.set_participant_restrictions(
|
||||||
|
chat, user, [ChatRestriction.SEND_MEDIA],
|
||||||
|
until=datetime.now() + timedelta(minutes=5))
|
||||||
|
|
||||||
|
# Unban the user
|
||||||
|
await client.set_participant_restrictions(chat, user, [])
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`telethon.types.Participant.set_restrictions`
|
||||||
|
"""
|
||||||
|
await set_participant_restrictions(self, chat, user, restrictions, until=until)
|
||||||
|
|
||||||
async def sign_in(self, token: LoginToken, code: str) -> Union[User, PasswordToken]:
|
async def sign_in(self, token: LoginToken, code: str) -> Union[User, PasswordToken]:
|
||||||
"""
|
"""
|
||||||
Sign in to a user account.
|
Sign in to a user account.
|
||||||
|
|
|
@ -40,7 +40,7 @@ class DialogList(AsyncList[Dialog]):
|
||||||
|
|
||||||
assert isinstance(result, (types.messages.Dialogs, types.messages.DialogsSlice))
|
assert isinstance(result, (types.messages.Dialogs, types.messages.DialogsSlice))
|
||||||
|
|
||||||
chat_map = build_chat_map(result.users, result.chats)
|
chat_map = build_chat_map(self._client, result.users, result.chats)
|
||||||
msg_map = build_msg_map(self._client, result.messages, chat_map)
|
msg_map = build_msg_map(self._client, result.messages, chat_map)
|
||||||
|
|
||||||
self._buffer.extend(
|
self._buffer.extend(
|
||||||
|
@ -94,7 +94,7 @@ class DraftList(AsyncList[Draft]):
|
||||||
result = await self._client(functions.messages.get_all_drafts())
|
result = await self._client(functions.messages.get_all_drafts())
|
||||||
assert isinstance(result, types.Updates)
|
assert isinstance(result, types.Updates)
|
||||||
|
|
||||||
chat_map = build_chat_map(result.users, result.chats)
|
chat_map = build_chat_map(self._client, result.users, result.chats)
|
||||||
|
|
||||||
self._buffer.extend(
|
self._buffer.extend(
|
||||||
Draft._from_raw_update(self._client, u, chat_map)
|
Draft._from_raw_update(self._client, u, chat_map)
|
||||||
|
|
|
@ -271,7 +271,7 @@ class MessageList(AsyncList[Message]):
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("unexpected case")
|
raise RuntimeError("unexpected case")
|
||||||
|
|
||||||
chat_map = build_chat_map(messages.users, messages.chats)
|
chat_map = build_chat_map(client, messages.users, messages.chats)
|
||||||
self._buffer.extend(
|
self._buffer.extend(
|
||||||
Message._from_raw(client, m, chat_map)
|
Message._from_raw(client, m, chat_map)
|
||||||
for m in (
|
for m in (
|
||||||
|
@ -650,7 +650,7 @@ def build_message_map(
|
||||||
) -> MessageMap:
|
) -> MessageMap:
|
||||||
if isinstance(result, (types.Updates, types.UpdatesCombined)):
|
if isinstance(result, (types.Updates, types.UpdatesCombined)):
|
||||||
updates = result.updates
|
updates = result.updates
|
||||||
chat_map = build_chat_map(result.users, result.chats)
|
chat_map = build_chat_map(client, result.users, result.chats)
|
||||||
elif isinstance(result, types.UpdateShort):
|
elif isinstance(result, types.UpdateShort):
|
||||||
updates = [result.update]
|
updates = [result.update]
|
||||||
chat_map = {}
|
chat_map = {}
|
||||||
|
|
|
@ -106,7 +106,7 @@ def extend_update_queue(
|
||||||
users: List[abcs.User],
|
users: List[abcs.User],
|
||||||
chats: List[abcs.Chat],
|
chats: List[abcs.Chat],
|
||||||
) -> None:
|
) -> None:
|
||||||
chat_map = build_chat_map(users, chats)
|
chat_map = build_chat_map(client, users, chats)
|
||||||
|
|
||||||
for update in updates:
|
for update in updates:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -51,10 +51,10 @@ def get_contacts(self: Client) -> AsyncList[User]:
|
||||||
return ContactList(self)
|
return ContactList(self)
|
||||||
|
|
||||||
|
|
||||||
def resolved_peer_to_chat(resolved: abcs.contacts.ResolvedPeer) -> Chat:
|
def resolved_peer_to_chat(client: Client, resolved: abcs.contacts.ResolvedPeer) -> Chat:
|
||||||
assert isinstance(resolved, types.contacts.ResolvedPeer)
|
assert isinstance(resolved, types.contacts.ResolvedPeer)
|
||||||
|
|
||||||
map = build_chat_map(resolved.users, resolved.chats)
|
map = build_chat_map(client, resolved.users, resolved.chats)
|
||||||
if chat := map.get(peer_id(resolved.peer)):
|
if chat := map.get(peer_id(resolved.peer)):
|
||||||
return chat
|
return chat
|
||||||
else:
|
else:
|
||||||
|
@ -63,13 +63,13 @@ def resolved_peer_to_chat(resolved: abcs.contacts.ResolvedPeer) -> Chat:
|
||||||
|
|
||||||
async def resolve_phone(client: Client, phone: str) -> Chat:
|
async def resolve_phone(client: Client, phone: str) -> Chat:
|
||||||
return resolved_peer_to_chat(
|
return resolved_peer_to_chat(
|
||||||
await client(functions.contacts.resolve_phone(phone=phone))
|
client, await client(functions.contacts.resolve_phone(phone=phone))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def resolve_username(self: Client, username: str) -> Chat:
|
async def resolve_username(self: Client, username: str) -> Chat:
|
||||||
return resolved_peer_to_chat(
|
return resolved_peer_to_chat(
|
||||||
await self(functions.contacts.resolve_username(username=username))
|
self, await self(functions.contacts.resolve_username(username=username))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ from .chat import (
|
||||||
expand_peer,
|
expand_peer,
|
||||||
peer_id,
|
peer_id,
|
||||||
)
|
)
|
||||||
|
from .chat_restriction import ChatRestriction
|
||||||
from .dialog import Dialog
|
from .dialog import Dialog
|
||||||
from .draft import Draft
|
from .draft import Draft
|
||||||
from .file import File, InFileLike, OutFileLike, OutWrapper, expand_stripped_size
|
from .file import File, InFileLike, OutFileLike, OutWrapper, expand_stripped_size
|
||||||
|
@ -25,6 +26,7 @@ from .recent_action import RecentAction
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"AdminRight",
|
"AdminRight",
|
||||||
"AsyncList",
|
"AsyncList",
|
||||||
|
"ChatRestriction",
|
||||||
"CallbackAnswer",
|
"CallbackAnswer",
|
||||||
"Channel",
|
"Channel",
|
||||||
"Chat",
|
"Chat",
|
||||||
|
|
|
@ -102,3 +102,23 @@ class AdminRight(Enum):
|
||||||
cls.EDIT_STORIES,
|
cls.EDIT_STORIES,
|
||||||
cls.DELETE_STORIES,
|
cls.DELETE_STORIES,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _set_to_raw(cls, all_rights: Set[AdminRight]) -> types.ChatAdminRights:
|
||||||
|
return types.ChatAdminRights(
|
||||||
|
change_info=cls.CHANGE_INFO in all_rights,
|
||||||
|
post_messages=cls.POST_MESSAGES in all_rights,
|
||||||
|
edit_messages=cls.EDIT_MESSAGES in all_rights,
|
||||||
|
delete_messages=cls.DELETE_MESSAGES in all_rights,
|
||||||
|
ban_users=cls.BAN_USERS in all_rights,
|
||||||
|
invite_users=cls.INVITE_USERS in all_rights,
|
||||||
|
pin_messages=cls.PIN_MESSAGES in all_rights,
|
||||||
|
add_admins=cls.MANAGE_ADMINS in all_rights,
|
||||||
|
anonymous=cls.REMAIN_ANONYMOUS in all_rights,
|
||||||
|
manage_call=cls.MANAGE_CALLS in all_rights,
|
||||||
|
other=cls.OTHER in all_rights,
|
||||||
|
manage_topics=cls.MANAGE_TOPICS in all_rights,
|
||||||
|
post_stories=cls.POST_STORIES in all_rights,
|
||||||
|
edit_stories=cls.EDIT_STORIES in all_rights,
|
||||||
|
delete_stories=cls.DELETE_STORIES in all_rights,
|
||||||
|
)
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import itertools
|
import itertools
|
||||||
import sys
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import DefaultDict, Dict, List, Optional, Union
|
from typing import TYPE_CHECKING, DefaultDict, Dict, List, Optional, Union
|
||||||
|
|
||||||
from ....session import PackedChat
|
from ....session import PackedChat
|
||||||
from ....tl import abcs, types
|
from ....tl import abcs, types
|
||||||
|
@ -10,15 +12,20 @@ from .chat import Chat
|
||||||
from .group import Group
|
from .group import Group
|
||||||
from .user import User
|
from .user import User
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ...client.client import Client
|
||||||
|
|
||||||
ChatLike = Union[Chat, PackedChat, int, str]
|
ChatLike = Union[Chat, PackedChat, int, str]
|
||||||
|
|
||||||
|
|
||||||
def build_chat_map(users: List[abcs.User], chats: List[abcs.Chat]) -> Dict[int, Chat]:
|
def build_chat_map(
|
||||||
|
client: Client, users: List[abcs.User], chats: List[abcs.Chat]
|
||||||
|
) -> Dict[int, Chat]:
|
||||||
users_iter = (User._from_raw(u) for u in users)
|
users_iter = (User._from_raw(u) for u in users)
|
||||||
chats_iter = (
|
chats_iter = (
|
||||||
Channel._from_raw(c)
|
Channel._from_raw(c)
|
||||||
if isinstance(c, (types.Channel, types.ChannelForbidden)) and c.broadcast
|
if isinstance(c, (types.Channel, types.ChannelForbidden)) and c.broadcast
|
||||||
else Group._from_raw(c)
|
else Group._from_raw(client, c)
|
||||||
for c in chats
|
for c in chats
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,11 +64,11 @@ def peer_id(peer: abcs.Peer) -> int:
|
||||||
raise RuntimeError("unexpected case")
|
raise RuntimeError("unexpected case")
|
||||||
|
|
||||||
|
|
||||||
def expand_peer(peer: abcs.Peer, *, broadcast: Optional[bool]) -> Chat:
|
def expand_peer(client: Client, peer: abcs.Peer, *, broadcast: Optional[bool]) -> Chat:
|
||||||
if isinstance(peer, types.PeerUser):
|
if isinstance(peer, types.PeerUser):
|
||||||
return User._from_raw(types.UserEmpty(id=peer.user_id))
|
return User._from_raw(types.UserEmpty(id=peer.user_id))
|
||||||
elif isinstance(peer, types.PeerChat):
|
elif isinstance(peer, types.PeerChat):
|
||||||
return Group._from_raw(types.ChatEmpty(id=peer.chat_id))
|
return Group._from_raw(client, types.ChatEmpty(id=peer.chat_id))
|
||||||
elif isinstance(peer, types.PeerChannel):
|
elif isinstance(peer, types.PeerChannel):
|
||||||
if broadcast is None:
|
if broadcast is None:
|
||||||
broadcast = True # assume broadcast by default (Channel type is more accurate than Group)
|
broadcast = True # assume broadcast by default (Channel type is more accurate than Group)
|
||||||
|
@ -75,7 +82,11 @@ def expand_peer(peer: abcs.Peer, *, broadcast: Optional[bool]) -> Chat:
|
||||||
until_date=None,
|
until_date=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
return Channel._from_raw(channel) if broadcast else Group._from_raw(channel)
|
return (
|
||||||
|
Channel._from_raw(channel)
|
||||||
|
if broadcast
|
||||||
|
else Group._from_raw(client, channel)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("unexpected case")
|
raise RuntimeError("unexpected case")
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
from typing import Optional, Self, Union
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from typing import TYPE_CHECKING, Optional, Self, Sequence, Union
|
||||||
|
|
||||||
from ....session import PackedChat, PackedType
|
from ....session import PackedChat, PackedType
|
||||||
from ....tl import abcs, types
|
from ....tl import abcs, types
|
||||||
|
from ..chat_restriction import ChatRestriction
|
||||||
from ..meta import NoPublicConstructor
|
from ..meta import NoPublicConstructor
|
||||||
from .chat import Chat
|
from .chat import Chat
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ...client.client import Client
|
||||||
|
|
||||||
|
|
||||||
class Group(Chat, metaclass=NoPublicConstructor):
|
class Group(Chat, metaclass=NoPublicConstructor):
|
||||||
"""
|
"""
|
||||||
|
@ -18,7 +25,8 @@ class Group(Chat, metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
raw: Union[
|
client: Client,
|
||||||
|
chat: Union[
|
||||||
types.ChatEmpty,
|
types.ChatEmpty,
|
||||||
types.Chat,
|
types.Chat,
|
||||||
types.ChatForbidden,
|
types.ChatForbidden,
|
||||||
|
@ -26,16 +34,17 @@ class Group(Chat, metaclass=NoPublicConstructor):
|
||||||
types.ChannelForbidden,
|
types.ChannelForbidden,
|
||||||
],
|
],
|
||||||
) -> None:
|
) -> None:
|
||||||
self._raw = raw
|
self._client = client
|
||||||
|
self._raw = chat
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_raw(cls, chat: abcs.Chat) -> Self:
|
def _from_raw(cls, client: Client, chat: abcs.Chat) -> Self:
|
||||||
if isinstance(chat, (types.ChatEmpty, types.Chat, types.ChatForbidden)):
|
if isinstance(chat, (types.ChatEmpty, types.Chat, types.ChatForbidden)):
|
||||||
return cls._create(chat)
|
return cls._create(client, chat)
|
||||||
elif isinstance(chat, (types.Channel, types.ChannelForbidden)):
|
elif isinstance(chat, (types.Channel, types.ChannelForbidden)):
|
||||||
if chat.broadcast:
|
if chat.broadcast:
|
||||||
raise RuntimeError("cannot create group from broadcast channel")
|
raise RuntimeError("cannot create group from broadcast channel")
|
||||||
return cls._create(chat)
|
return cls._create(client, chat)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("unexpected case")
|
raise RuntimeError("unexpected case")
|
||||||
|
|
||||||
|
@ -80,3 +89,16 @@ class Group(Chat, metaclass=NoPublicConstructor):
|
||||||
These are known as "megagroups" in Telegram's API, and are different from "gigagroups".
|
These are known as "megagroups" in Telegram's API, and are different from "gigagroups".
|
||||||
"""
|
"""
|
||||||
return isinstance(self._raw, (types.Channel, types.ChannelForbidden))
|
return isinstance(self._raw, (types.Channel, types.ChannelForbidden))
|
||||||
|
|
||||||
|
async def set_default_restrictions(
|
||||||
|
self,
|
||||||
|
restrictions: Sequence[ChatRestriction],
|
||||||
|
*,
|
||||||
|
until: Optional[datetime.datetime] = None,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Alias for :meth:`telethon.Client.set_chat_default_restrictions`.
|
||||||
|
"""
|
||||||
|
await self._client.set_chat_default_restrictions(
|
||||||
|
self, restrictions, until=until
|
||||||
|
)
|
||||||
|
|
140
client/src/telethon/_impl/client/types/chat_restriction.py
Normal file
140
client/src/telethon/_impl/client/types/chat_restriction.py
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Set
|
||||||
|
|
||||||
|
from ...tl import abcs, types
|
||||||
|
|
||||||
|
|
||||||
|
class ChatRestriction(Enum):
|
||||||
|
"""
|
||||||
|
A restriction that may be applied to a banned chat's participant.
|
||||||
|
|
||||||
|
A banned participant is completley banned from a chat if they are forbidden to :attr:`VIEW_MESSAGES`.
|
||||||
|
|
||||||
|
A banned participant that can :attr:`VIEW_MESSAGES` is restricted, but can still be part of the chat,
|
||||||
|
|
||||||
|
.. 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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
VIEW_MESSAGES = "view_messages"
|
||||||
|
"""
|
||||||
|
Prevents being in the chat and fetching the message history.
|
||||||
|
|
||||||
|
Applying this restriction will kick the participant out of the group.
|
||||||
|
"""
|
||||||
|
|
||||||
|
SEND_MESSAGES = "send_messages"
|
||||||
|
"""Prevents sending messages to the chat."""
|
||||||
|
|
||||||
|
SEND_MEDIA = "send_media"
|
||||||
|
"""Prevents sending messages with media such as photos or documents to the chat."""
|
||||||
|
|
||||||
|
SEND_STICKERS = "send_stickers"
|
||||||
|
"""Prevents sending sticker media to the chat."""
|
||||||
|
|
||||||
|
SEND_GIFS = "send_gifs"
|
||||||
|
"""Prevents sending muted looping video media ("GIFs") to the chat."""
|
||||||
|
|
||||||
|
SEND_GAMES = "send_games"
|
||||||
|
"""Prevents sending *@bot inline* games to the chat."""
|
||||||
|
|
||||||
|
SEND_INLINE = "send_inline"
|
||||||
|
"""Prevents sending messages via *@bot inline* to the chat."""
|
||||||
|
|
||||||
|
EMBED_LINKS = "embed_links"
|
||||||
|
"""Prevents sending messages that include links to external URLs to the chat."""
|
||||||
|
|
||||||
|
SEND_POLLS = "send_polls"
|
||||||
|
"""Prevents sending poll media to the chat."""
|
||||||
|
|
||||||
|
CHANGE_INFO = "change_info"
|
||||||
|
"""Prevents changing the description of the chat."""
|
||||||
|
|
||||||
|
INVITE_USERS = "invite_users"
|
||||||
|
"""Prevents inviting users to the chat."""
|
||||||
|
|
||||||
|
PIN_MESSAGES = "pin_messages"
|
||||||
|
"""Prevents pinning messages to the chat."""
|
||||||
|
|
||||||
|
MANAGE_TOPICS = "manage_topics"
|
||||||
|
"""Prevents managing the topics of the chat."""
|
||||||
|
|
||||||
|
SEND_PHOTOS = "send_photos"
|
||||||
|
"""Prevents sending photo media files to the chat."""
|
||||||
|
|
||||||
|
SEND_VIDEOS = "send_videos"
|
||||||
|
"""Prevents sending video media files to the chat."""
|
||||||
|
|
||||||
|
SEND_ROUND_VIDEOS = "send_roundvideos"
|
||||||
|
"""Prevents sending round video media files to the chat."""
|
||||||
|
|
||||||
|
SEND_AUDIOS = "send_audios"
|
||||||
|
"""Prevents sending audio media files to the chat."""
|
||||||
|
|
||||||
|
SEND_VOICE_NOTES = "send_voices"
|
||||||
|
"""Prevents sending voice note audio media files to the chat."""
|
||||||
|
|
||||||
|
SEND_DOCUMENTS = "send_docs"
|
||||||
|
"""Prevents sending document media files to the chat."""
|
||||||
|
|
||||||
|
SEND_PLAIN_MESSAGES = "send_plain"
|
||||||
|
"""Prevents sending plain text messages with no media to the chat."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _from_raw(cls, rights: abcs.ChatBannedRights) -> Set[ChatRestriction]:
|
||||||
|
assert isinstance(rights, types.ChatBannedRights)
|
||||||
|
restrictions = (
|
||||||
|
cls.VIEW_MESSAGES if rights.view_messages else None,
|
||||||
|
cls.SEND_MESSAGES if rights.send_messages else None,
|
||||||
|
cls.SEND_MEDIA if rights.send_media else None,
|
||||||
|
cls.SEND_STICKERS if rights.send_stickers else None,
|
||||||
|
cls.SEND_GIFS if rights.send_gifs else None,
|
||||||
|
cls.SEND_GAMES if rights.send_games else None,
|
||||||
|
cls.SEND_INLINE if rights.send_inline else None,
|
||||||
|
cls.EMBED_LINKS if rights.embed_links else None,
|
||||||
|
cls.SEND_POLLS if rights.send_polls else None,
|
||||||
|
cls.CHANGE_INFO if rights.change_info else None,
|
||||||
|
cls.INVITE_USERS if rights.invite_users else None,
|
||||||
|
cls.PIN_MESSAGES if rights.pin_messages else None,
|
||||||
|
cls.MANAGE_TOPICS if rights.manage_topics else None,
|
||||||
|
cls.SEND_PHOTOS if rights.send_photos else None,
|
||||||
|
cls.SEND_VIDEOS if rights.send_videos else None,
|
||||||
|
cls.SEND_ROUND_VIDEOS if rights.send_roundvideos else None,
|
||||||
|
cls.SEND_AUDIOS if rights.send_audios else None,
|
||||||
|
cls.SEND_VOICE_NOTES if rights.send_voices else None,
|
||||||
|
cls.SEND_DOCUMENTS if rights.send_docs else None,
|
||||||
|
cls.SEND_PLAIN_MESSAGES if rights.send_plain else None,
|
||||||
|
)
|
||||||
|
return set(filter(None, iter(restrictions)))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _set_to_raw(
|
||||||
|
cls, restrictions: Set[ChatRestriction], until_date: int
|
||||||
|
) -> types.ChatBannedRights:
|
||||||
|
return types.ChatBannedRights(
|
||||||
|
view_messages=cls.VIEW_MESSAGES in restrictions,
|
||||||
|
send_messages=cls.SEND_MESSAGES in restrictions,
|
||||||
|
send_media=cls.SEND_MEDIA in restrictions,
|
||||||
|
send_stickers=cls.SEND_STICKERS in restrictions,
|
||||||
|
send_gifs=cls.SEND_GIFS in restrictions,
|
||||||
|
send_games=cls.SEND_GAMES in restrictions,
|
||||||
|
send_inline=cls.SEND_INLINE in restrictions,
|
||||||
|
embed_links=cls.EMBED_LINKS in restrictions,
|
||||||
|
send_polls=cls.SEND_POLLS in restrictions,
|
||||||
|
change_info=cls.CHANGE_INFO in restrictions,
|
||||||
|
invite_users=cls.INVITE_USERS in restrictions,
|
||||||
|
pin_messages=cls.PIN_MESSAGES in restrictions,
|
||||||
|
manage_topics=cls.MANAGE_TOPICS in restrictions,
|
||||||
|
send_photos=cls.SEND_PHOTOS in restrictions,
|
||||||
|
send_videos=cls.SEND_VIDEOS in restrictions,
|
||||||
|
send_roundvideos=cls.SEND_ROUND_VIDEOS in restrictions,
|
||||||
|
send_audios=cls.SEND_AUDIOS in restrictions,
|
||||||
|
send_voices=cls.SEND_VOICE_NOTES in restrictions,
|
||||||
|
send_docs=cls.SEND_DOCUMENTS in restrictions,
|
||||||
|
send_plain=cls.SEND_PLAIN_MESSAGES in restrictions,
|
||||||
|
until_date=until_date,
|
||||||
|
)
|
|
@ -61,7 +61,7 @@ class Draft(metaclass=NoPublicConstructor):
|
||||||
This is also the chat where the message will be sent to by :meth:`send`.
|
This is also the chat where the message will be sent to by :meth:`send`.
|
||||||
"""
|
"""
|
||||||
return self._chat_map.get(peer_id(self._peer)) or expand_peer(
|
return self._chat_map.get(peer_id(self._peer)) or expand_peer(
|
||||||
self._peer, broadcast=None
|
self._client, self._peer, broadcast=None
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -179,7 +179,7 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
pid = peer_id(peer)
|
pid = peer_id(peer)
|
||||||
if pid not in self._chat_map:
|
if pid not in self._chat_map:
|
||||||
self._chat_map[pid] = expand_peer(
|
self._chat_map[pid] = expand_peer(
|
||||||
peer, broadcast=getattr(self._raw, "post", None)
|
self._client, peer, broadcast=getattr(self._raw, "post", None)
|
||||||
)
|
)
|
||||||
return self._chat_map[pid]
|
return self._chat_map[pid]
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
"""
|
"""
|
||||||
if (from_ := getattr(self._raw, "from_id", None)) is not None:
|
if (from_ := getattr(self._raw, "from_id", None)) is not None:
|
||||||
return self._chat_map.get(peer_id(from_)) or expand_peer(
|
return self._chat_map.get(peer_id(from_)) or expand_peer(
|
||||||
from_, broadcast=getattr(self._raw, "post", None)
|
self._client, from_, broadcast=getattr(self._raw, "post", None)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
from typing import Dict, Optional, Self, Set, Union
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from typing import TYPE_CHECKING, Dict, Optional, Self, Sequence, Set, Union
|
||||||
|
|
||||||
|
from ...session import PackedChat
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
from .admin_right import AdminRight
|
from .admin_right import AdminRight
|
||||||
from .chat import Chat, User, peer_id
|
from .chat import Chat, User, peer_id
|
||||||
|
from .chat_restriction import ChatRestriction
|
||||||
from .meta import NoPublicConstructor
|
from .meta import NoPublicConstructor
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ..client.client import Client
|
||||||
|
|
||||||
|
|
||||||
class Participant(metaclass=NoPublicConstructor):
|
class Participant(metaclass=NoPublicConstructor):
|
||||||
"""
|
"""
|
||||||
|
@ -13,10 +21,10 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
You can obtain participants with methods such as :meth:`telethon.Client.get_participants`.
|
You can obtain participants with methods such as :meth:`telethon.Client.get_participants`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ("_raw", "_chat_map")
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
client: Client,
|
||||||
|
chat: PackedChat,
|
||||||
participant: Union[
|
participant: Union[
|
||||||
types.ChannelParticipant,
|
types.ChannelParticipant,
|
||||||
types.ChannelParticipantSelf,
|
types.ChannelParticipantSelf,
|
||||||
|
@ -30,12 +38,18 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
],
|
],
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: Dict[int, Chat],
|
||||||
) -> None:
|
) -> None:
|
||||||
|
self._client = client
|
||||||
|
self._chat = chat
|
||||||
self._raw = participant
|
self._raw = participant
|
||||||
self._chat_map = chat_map
|
self._chat_map = chat_map
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_raw_channel(
|
def _from_raw_channel(
|
||||||
cls, participant: abcs.ChannelParticipant, chat_map: Dict[int, Chat]
|
cls,
|
||||||
|
client: Client,
|
||||||
|
chat: PackedChat,
|
||||||
|
participant: abcs.ChannelParticipant,
|
||||||
|
chat_map: Dict[int, Chat],
|
||||||
) -> Self:
|
) -> Self:
|
||||||
if isinstance(
|
if isinstance(
|
||||||
participant,
|
participant,
|
||||||
|
@ -48,13 +62,17 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
types.ChannelParticipantLeft,
|
types.ChannelParticipantLeft,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
return cls._create(participant, chat_map)
|
return cls._create(client, chat, participant, chat_map)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("unexpected case")
|
raise RuntimeError("unexpected case")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_raw_chat(
|
def _from_raw_chat(
|
||||||
cls, participant: abcs.ChatParticipant, chat_map: Dict[int, Chat]
|
cls,
|
||||||
|
client: Client,
|
||||||
|
chat: PackedChat,
|
||||||
|
participant: abcs.ChatParticipant,
|
||||||
|
chat_map: Dict[int, Chat],
|
||||||
) -> Self:
|
) -> Self:
|
||||||
if isinstance(
|
if isinstance(
|
||||||
participant,
|
participant,
|
||||||
|
@ -64,7 +82,7 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
types.ChatParticipantAdmin,
|
types.ChatParticipantAdmin,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
return cls._create(participant, chat_map)
|
return cls._create(client, chat, participant, chat_map)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("unexpected case")
|
raise RuntimeError("unexpected case")
|
||||||
|
|
||||||
|
@ -162,3 +180,36 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
return AdminRight._chat_rights()
|
return AdminRight._chat_rights()
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def restrictions(self) -> Optional[Set[ChatRestriction]]:
|
||||||
|
"""
|
||||||
|
The set of restrictions applied to this participant, if they are banned.
|
||||||
|
"""
|
||||||
|
if isinstance(self._raw, types.ChannelParticipantBanned):
|
||||||
|
return ChatRestriction._from_raw(self._raw.banned_rights)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def set_admin_rights(self, rights: Sequence[AdminRight]) -> None:
|
||||||
|
"""
|
||||||
|
Alias for :meth:`telethon.Client.set_participant_admin_rights`.
|
||||||
|
"""
|
||||||
|
participant = self.user or self.banned or self.left
|
||||||
|
assert participant
|
||||||
|
await self._client.set_participant_admin_rights(self._chat, participant, rights)
|
||||||
|
|
||||||
|
async def set_restrictions(
|
||||||
|
self,
|
||||||
|
restrictions: Sequence[ChatRestriction],
|
||||||
|
*,
|
||||||
|
until: Optional[datetime.datetime] = None,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Alias for :meth:`telethon.Client.set_participant_restrictions`.
|
||||||
|
"""
|
||||||
|
participant = self.user or self.banned or self.left
|
||||||
|
assert participant
|
||||||
|
await self._client.set_participant_restrictions(
|
||||||
|
self._chat, participant, restrictions, until=until
|
||||||
|
)
|
||||||
|
|
|
@ -7,6 +7,7 @@ from .._impl.client.types import (
|
||||||
CallbackAnswer,
|
CallbackAnswer,
|
||||||
Channel,
|
Channel,
|
||||||
Chat,
|
Chat,
|
||||||
|
ChatRestriction,
|
||||||
Dialog,
|
Dialog,
|
||||||
Draft,
|
Draft,
|
||||||
File,
|
File,
|
||||||
|
@ -28,6 +29,7 @@ __all__ = [
|
||||||
"CallbackAnswer",
|
"CallbackAnswer",
|
||||||
"Channel",
|
"Channel",
|
||||||
"Chat",
|
"Chat",
|
||||||
|
"ChatRestriction",
|
||||||
"Dialog",
|
"Dialog",
|
||||||
"Draft",
|
"Draft",
|
||||||
"File",
|
"File",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user