mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-04-09 03:34:13 +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):
|
||||
"""
|
||||
Helper base class that introduces the `chat`, `input_chat`
|
||||
and `chat_id` properties and `get_chat` and `get_input_chat`
|
||||
methods.
|
||||
Helper base class that introduces the chat-related properties and methods.
|
||||
"""
|
||||
def __init__(self, chat_peer=None, *, input_chat=None, chat=None, broadcast=None):
|
||||
self._chat_peer = chat_peer
|
||||
self._input_chat = input_chat
|
||||
def __init__(self, chat, client):
|
||||
self._chat = chat
|
||||
self._broadcast = broadcast
|
||||
self._client = None
|
||||
self._client = client
|
||||
|
||||
@property
|
||||
def chat(self):
|
||||
"""
|
||||
Returns the :tl:`User`, :tl:`Chat` or :tl:`Channel` where this object
|
||||
belongs to. It may be `None` if Telegram didn't send the chat.
|
||||
Returns the `User` or `Chat` who sent this object, or `None` if there is no 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
|
||||
this chat, use `input_chat` instead.
|
||||
|
||||
If you're using `telethon.events`, use `get_chat()` instead.
|
||||
Chats obtained through friendly methods (not events) will always have complete
|
||||
information (so there is no need to use `get_chat` or ``chat.fetch()``).
|
||||
"""
|
||||
return self._chat
|
||||
|
||||
async def get_chat(self):
|
||||
"""
|
||||
Returns `chat`, but will make an API call to find the
|
||||
chat unless it's already cached.
|
||||
Returns `chat`, but will make an API call to find the chat unless it's already cached.
|
||||
|
||||
If you only need the ID, use `chat_id` instead.
|
||||
|
||||
If you need to call a method which needs
|
||||
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
|
||||
If you need to call a method which needs this chat, prefer `chat` instead.
|
||||
|
||||
@property
|
||||
def input_chat(self):
|
||||
"""
|
||||
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.
|
||||
Telegram may send a "minimal" version of the chat to save on bandwidth when using events.
|
||||
If you need all the information about the chat upfront, you can use ``chat.fetch()``.
|
||||
|
||||
Note that this might not be available if the library doesn't
|
||||
have enough information available.
|
||||
"""
|
||||
return self._input_chat
|
||||
.. code-block:: python
|
||||
|
||||
async def get_input_chat(self):
|
||||
"""
|
||||
Returns `input_chat`, but will make an API call to find the
|
||||
input chat unless it's already cached.
|
||||
"""
|
||||
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
|
||||
@client.on(events.NewMessage)
|
||||
async def handler(event):
|
||||
# I only need the ID -> use chat_id
|
||||
chat_id = event.chat_id
|
||||
|
||||
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
|
||||
def chat_id(self):
|
||||
"""
|
||||
Returns the marked chat integer ID. Note that this value **will
|
||||
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.
|
||||
Alias for ``self.chat.id``, but checking if ``chat is not None`` first.
|
||||
"""
|
||||
return self._chat.id if self._chat else None
|
||||
|
|
|
@ -3,89 +3,65 @@ import abc
|
|||
|
||||
class SenderGetter(abc.ABC):
|
||||
"""
|
||||
Helper base class that introduces the `sender`, `input_sender`
|
||||
and `sender_id` properties and `get_sender` and `get_input_sender`
|
||||
methods.
|
||||
Helper base class that introduces the sender-related properties and methods.
|
||||
"""
|
||||
def __init__(self, sender_id=None, *, sender=None, input_sender=None):
|
||||
self._sender_id = sender_id
|
||||
def __init__(self, sender, client):
|
||||
self._sender = sender
|
||||
self._input_sender = input_sender
|
||||
self._client = None
|
||||
self._client = client
|
||||
|
||||
@property
|
||||
def sender(self):
|
||||
"""
|
||||
Returns the :tl:`User` or :tl:`Channel` that sent this object.
|
||||
It may be `None` if Telegram didn't send the sender.
|
||||
Returns the `User` or `Chat` who sent this object, or `None` if there is no 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
|
||||
this chat, use `input_sender` instead.
|
||||
|
||||
If you're using `telethon.events`, use `get_sender()` instead.
|
||||
Senders obtained through friendly methods (not events) will always have complete
|
||||
information (so there is no need to use `get_sender` or ``sender.fetch()``).
|
||||
"""
|
||||
return self._sender
|
||||
|
||||
async def get_sender(self):
|
||||
"""
|
||||
Returns `sender`, but will make an API call to find the
|
||||
sender unless it's already cached.
|
||||
Returns `sender`, but will make an API call to find the sender unless it's already cached.
|
||||
|
||||
If you only need the ID, use `sender_id` instead.
|
||||
|
||||
If you need to call a method which needs
|
||||
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
|
||||
If you need to call a method which needs this sender, prefer `sender` instead.
|
||||
|
||||
@property
|
||||
def input_sender(self):
|
||||
"""
|
||||
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.
|
||||
Telegram may send a "minimal" version of the sender to save on bandwidth when using events.
|
||||
If you need all the information about the sender upfront, you can use ``sender.fetch()``.
|
||||
|
||||
Note that this might not be available if the library can't
|
||||
find the input chat, or if the message a broadcast on a channel.
|
||||
"""
|
||||
return self._input_sender
|
||||
.. code-block:: python
|
||||
|
||||
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
|
||||
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
|
||||
raise RuntimeError('TODO')
|
||||
|
||||
@property
|
||||
def sender_id(self):
|
||||
"""
|
||||
Returns the marked sender integer ID, if present.
|
||||
|
||||
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.
|
||||
Alias for ``self.sender.id``, but checking if ``sender is not None`` first.
|
||||
"""
|
||||
return self._sender.id if sender else None
|
||||
|
|
Loading…
Reference in New Issue
Block a user