mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-07-10 16:12:22 +03:00
Change Chat and Sender Getter interface to match new description
This commit is contained in:
parent
9bfe4cddf5
commit
f0654a0833
|
@ -6,138 +6,65 @@ from ... import errors, _tl
|
||||||
|
|
||||||
class ChatGetter(abc.ABC):
|
class ChatGetter(abc.ABC):
|
||||||
"""
|
"""
|
||||||
Helper base class that introduces the `chat`, `input_chat`
|
Helper base class that introduces the chat-related properties and methods.
|
||||||
and `chat_id` properties and `get_chat` and `get_input_chat`
|
|
||||||
methods.
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, chat_peer=None, *, input_chat=None, chat=None, broadcast=None):
|
def __init__(self, chat, client):
|
||||||
self._chat_peer = chat_peer
|
|
||||||
self._input_chat = input_chat
|
|
||||||
self._chat = chat
|
self._chat = chat
|
||||||
self._broadcast = broadcast
|
self._client = client
|
||||||
self._client = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def chat(self):
|
def chat(self):
|
||||||
"""
|
"""
|
||||||
Returns the :tl:`User`, :tl:`Chat` or :tl:`Channel` where this object
|
Returns the `User` or `Chat` who sent this object, or `None` if there is no chat.
|
||||||
belongs to. It may be `None` if Telegram didn't send the chat.
|
|
||||||
|
|
||||||
If you only need the ID, use `chat_id` instead.
|
The chat of an event is only guaranteed to include the ``id``.
|
||||||
|
If you need the chat to at least have basic information, use `get_chat` instead.
|
||||||
|
|
||||||
If you need to call a method which needs
|
Chats obtained through friendly methods (not events) will always have complete
|
||||||
this chat, use `input_chat` instead.
|
information (so there is no need to use `get_chat` or ``chat.fetch()``).
|
||||||
|
|
||||||
If you're using `telethon.events`, use `get_chat()` instead.
|
|
||||||
"""
|
"""
|
||||||
return self._chat
|
return self._chat
|
||||||
|
|
||||||
async def get_chat(self):
|
async def get_chat(self):
|
||||||
"""
|
"""
|
||||||
Returns `chat`, but will make an API call to find the
|
Returns `chat`, but will make an API call to find the chat unless it's already cached.
|
||||||
chat unless it's already cached.
|
|
||||||
|
|
||||||
If you only need the ID, use `chat_id` instead.
|
If you only need the ID, use `chat_id` instead.
|
||||||
|
|
||||||
If you need to call a method which needs
|
If you need to call a method which needs this chat, prefer `chat` instead.
|
||||||
this chat, use `get_input_chat()` instead.
|
|
||||||
"""
|
|
||||||
# See `get_sender` for information about 'min'.
|
|
||||||
if (self._chat is None or getattr(self._chat, 'min', None))\
|
|
||||||
and await self.get_input_chat():
|
|
||||||
try:
|
|
||||||
self._chat =\
|
|
||||||
await self._client.get_entity(self._input_chat)
|
|
||||||
except ValueError:
|
|
||||||
await self._refetch_chat()
|
|
||||||
return self._chat
|
|
||||||
|
|
||||||
@property
|
Telegram may send a "minimal" version of the chat to save on bandwidth when using events.
|
||||||
def input_chat(self):
|
If you need all the information about the chat upfront, you can use ``chat.fetch()``.
|
||||||
"""
|
|
||||||
This :tl:`InputPeer` is the input version of the chat where the
|
|
||||||
message was sent. Similarly to `input_sender
|
|
||||||
<telethon.tl.custom.sendergetter.SenderGetter.input_sender>`, this
|
|
||||||
doesn't have things like username or similar, but still useful in
|
|
||||||
some cases.
|
|
||||||
|
|
||||||
Note that this might not be available if the library doesn't
|
.. code-block:: python
|
||||||
have enough information available.
|
|
||||||
"""
|
|
||||||
return self._input_chat
|
|
||||||
|
|
||||||
async def get_input_chat(self):
|
@client.on(events.NewMessage)
|
||||||
"""
|
async def handler(event):
|
||||||
Returns `input_chat`, but will make an API call to find the
|
# I only need the ID -> use chat_id
|
||||||
input chat unless it's already cached.
|
chat_id = event.chat_id
|
||||||
"""
|
|
||||||
if self.input_chat is None and self.chat_id and self._client:
|
|
||||||
try:
|
|
||||||
# The chat may be recent, look in dialogs
|
|
||||||
target = self.chat_id
|
|
||||||
async for d in self._client.get_dialogs(100):
|
|
||||||
if d.id == target:
|
|
||||||
self._chat = d.entity
|
|
||||||
self._input_chat = d.input_entity
|
|
||||||
break
|
|
||||||
except errors.RpcError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return self._input_chat
|
# I'm going to use the chat in a method -> use chat
|
||||||
|
await client.send_message(event.chat, 'Hi!')
|
||||||
|
|
||||||
|
# I need the chat's title -> use get_chat
|
||||||
|
chat = await event.get_chat()
|
||||||
|
print(chat.title)
|
||||||
|
|
||||||
|
# I want to see all the information about the chat -> use fetch
|
||||||
|
chat = await event.chat.fetch()
|
||||||
|
print(chat.stringify())
|
||||||
|
|
||||||
|
# ...
|
||||||
|
|
||||||
|
async for message in client.get_messages(chat):
|
||||||
|
# Here there's no need to fetch the chat - get_messages already did
|
||||||
|
print(message.chat.stringify())
|
||||||
|
"""
|
||||||
|
raise RuntimeError('TODO')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def chat_id(self):
|
def chat_id(self):
|
||||||
"""
|
"""
|
||||||
Returns the marked chat integer ID. Note that this value **will
|
Alias for ``self.chat.id``, but checking if ``chat is not None`` first.
|
||||||
be different** from ``peer_id`` for incoming private messages, since
|
|
||||||
the chat *to* which the messages go is to your own person, but
|
|
||||||
the *chat* itself is with the one who sent the message.
|
|
||||||
|
|
||||||
TL;DR; this gets the ID that you expect.
|
|
||||||
|
|
||||||
If there is a chat in the object, `chat_id` will *always* be set,
|
|
||||||
which is why you should use it instead of `chat.id <chat>`.
|
|
||||||
"""
|
|
||||||
return utils.get_peer_id(self._chat_peer) if self._chat_peer else None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_private(self):
|
|
||||||
"""
|
|
||||||
`True` if the message was sent as a private message.
|
|
||||||
|
|
||||||
Returns `None` if there isn't enough information
|
|
||||||
(e.g. on `events.MessageDeleted <telethon.events.messagedeleted.MessageDeleted>`).
|
|
||||||
"""
|
|
||||||
return isinstance(self._chat_peer, _tl.PeerUser) if self._chat_peer else None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_group(self):
|
|
||||||
"""
|
|
||||||
True if the message was sent on a group or megagroup.
|
|
||||||
|
|
||||||
Returns `None` if there isn't enough information
|
|
||||||
(e.g. on `events.MessageDeleted <telethon.events.messagedeleted.MessageDeleted>`).
|
|
||||||
"""
|
|
||||||
# TODO Cache could tell us more in the future
|
|
||||||
if self._broadcast is None and hasattr(self.chat, 'broadcast'):
|
|
||||||
self._broadcast = bool(self.chat.broadcast)
|
|
||||||
|
|
||||||
if isinstance(self._chat_peer, _tl.PeerChannel):
|
|
||||||
if self._broadcast is None:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
return not self._broadcast
|
|
||||||
|
|
||||||
return isinstance(self._chat_peer, _tl.PeerChat)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_channel(self):
|
|
||||||
"""`True` if the message was sent on a megagroup or channel."""
|
|
||||||
# The only case where chat peer could be none is in MessageDeleted,
|
|
||||||
# however those always have the peer in channels.
|
|
||||||
return isinstance(self._chat_peer, _tl.PeerChannel)
|
|
||||||
|
|
||||||
async def _refetch_chat(self):
|
|
||||||
"""
|
|
||||||
Re-fetches chat information through other means.
|
|
||||||
"""
|
"""
|
||||||
|
return self._chat.id if self._chat else None
|
||||||
|
|
|
@ -3,89 +3,65 @@ import abc
|
||||||
|
|
||||||
class SenderGetter(abc.ABC):
|
class SenderGetter(abc.ABC):
|
||||||
"""
|
"""
|
||||||
Helper base class that introduces the `sender`, `input_sender`
|
Helper base class that introduces the sender-related properties and methods.
|
||||||
and `sender_id` properties and `get_sender` and `get_input_sender`
|
|
||||||
methods.
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, sender_id=None, *, sender=None, input_sender=None):
|
def __init__(self, sender, client):
|
||||||
self._sender_id = sender_id
|
|
||||||
self._sender = sender
|
self._sender = sender
|
||||||
self._input_sender = input_sender
|
self._client = client
|
||||||
self._client = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sender(self):
|
def sender(self):
|
||||||
"""
|
"""
|
||||||
Returns the :tl:`User` or :tl:`Channel` that sent this object.
|
Returns the `User` or `Chat` who sent this object, or `None` if there is no sender.
|
||||||
It may be `None` if Telegram didn't send the sender.
|
|
||||||
|
|
||||||
If you only need the ID, use `sender_id` instead.
|
The sender of an event is only guaranteed to include the ``id``.
|
||||||
|
If you need the sender to at least have basic information, use `get_sender` instead.
|
||||||
|
|
||||||
If you need to call a method which needs
|
Senders obtained through friendly methods (not events) will always have complete
|
||||||
this chat, use `input_sender` instead.
|
information (so there is no need to use `get_sender` or ``sender.fetch()``).
|
||||||
|
|
||||||
If you're using `telethon.events`, use `get_sender()` instead.
|
|
||||||
"""
|
"""
|
||||||
return self._sender
|
return self._sender
|
||||||
|
|
||||||
async def get_sender(self):
|
async def get_sender(self):
|
||||||
"""
|
"""
|
||||||
Returns `sender`, but will make an API call to find the
|
Returns `sender`, but will make an API call to find the sender unless it's already cached.
|
||||||
sender unless it's already cached.
|
|
||||||
|
|
||||||
If you only need the ID, use `sender_id` instead.
|
If you only need the ID, use `sender_id` instead.
|
||||||
|
|
||||||
If you need to call a method which needs
|
If you need to call a method which needs this sender, prefer `sender` instead.
|
||||||
this sender, use `get_input_sender()` instead.
|
|
||||||
"""
|
|
||||||
# ``sender.min`` is present both in :tl:`User` and :tl:`Channel`.
|
|
||||||
# It's a flag that will be set if only minimal information is
|
|
||||||
# available (such as display name, but username may be missing),
|
|
||||||
# in which case we want to force fetch the entire thing because
|
|
||||||
# the user explicitly called a method. If the user is okay with
|
|
||||||
# cached information, they may use the property instead.
|
|
||||||
if (self._sender is None or getattr(self._sender, 'min', None)) \
|
|
||||||
and await self.get_input_sender():
|
|
||||||
try:
|
|
||||||
self._sender =\
|
|
||||||
await self._client.get_entity(self._input_sender)
|
|
||||||
except ValueError:
|
|
||||||
await self._refetch_sender()
|
|
||||||
return self._sender
|
|
||||||
|
|
||||||
@property
|
Telegram may send a "minimal" version of the sender to save on bandwidth when using events.
|
||||||
def input_sender(self):
|
If you need all the information about the sender upfront, you can use ``sender.fetch()``.
|
||||||
"""
|
|
||||||
This :tl:`InputPeer` is the input version of the user/channel who
|
|
||||||
sent the message. Similarly to `input_chat
|
|
||||||
<telethon.tl.custom.chatgetter.ChatGetter.input_chat>`, this doesn't
|
|
||||||
have things like username or similar, but still useful in some cases.
|
|
||||||
|
|
||||||
Note that this might not be available if the library can't
|
.. code-block:: python
|
||||||
find the input chat, or if the message a broadcast on a channel.
|
|
||||||
"""
|
|
||||||
return self._input_sender
|
|
||||||
|
|
||||||
async def get_input_sender(self):
|
@client.on(events.NewMessage)
|
||||||
|
async def handler(event):
|
||||||
|
# I only need the ID -> use sender_id
|
||||||
|
sender_id = event.sender_id
|
||||||
|
|
||||||
|
# I'm going to use the sender in a method -> use sender
|
||||||
|
await client.send_message(event.sender, 'Hi!')
|
||||||
|
|
||||||
|
# I need the sender's first name -> use get_sender
|
||||||
|
sender = await event.get_sender()
|
||||||
|
print(sender.first_name)
|
||||||
|
|
||||||
|
# I want to see all the information about the sender -> use fetch
|
||||||
|
sender = await event.sender.fetch()
|
||||||
|
print(sender.stringify())
|
||||||
|
|
||||||
|
# ...
|
||||||
|
|
||||||
|
async for message in client.get_messages(chat):
|
||||||
|
# Here there's no need to fetch the sender - get_messages already did
|
||||||
|
print(message.sender.stringify())
|
||||||
"""
|
"""
|
||||||
Returns `input_sender`, but will make an API call to find the
|
raise RuntimeError('TODO')
|
||||||
input sender unless it's already cached.
|
|
||||||
"""
|
|
||||||
if self.input_sender is None and self._sender_id and self._client:
|
|
||||||
await self._refetch_sender()
|
|
||||||
return self._input_sender
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sender_id(self):
|
def sender_id(self):
|
||||||
"""
|
"""
|
||||||
Returns the marked sender integer ID, if present.
|
Alias for ``self.sender.id``, but checking if ``sender is not None`` first.
|
||||||
|
|
||||||
If there is a sender in the object, `sender_id` will *always* be set,
|
|
||||||
which is why you should use it instead of `sender.id <sender>`.
|
|
||||||
"""
|
|
||||||
return self._sender_id
|
|
||||||
|
|
||||||
async def _refetch_sender(self):
|
|
||||||
"""
|
|
||||||
Re-fetches sender information through other means.
|
|
||||||
"""
|
"""
|
||||||
|
return self._sender.id if sender else None
|
||||||
|
|
Loading…
Reference in New Issue
Block a user