mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-25 10:53:44 +03:00
Reuse code to get chat and sender
This commit is contained in:
parent
531a02a2a1
commit
8eecd9c226
|
@ -53,3 +53,19 @@ telethon\.tl\.custom\.button module
|
|||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
telethon\.tl\.custom\.chatgetter module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: telethon.tl.custom.chatgetter
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
telethon\.tl\.custom\.sendergetter module
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: telethon.tl.custom.sendergetter
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
|
|
@ -3,6 +3,7 @@ import warnings
|
|||
|
||||
from .. import utils
|
||||
from ..tl import TLObject, types
|
||||
from ..tl.custom.chatgetter import ChatGetter
|
||||
|
||||
|
||||
async def _into_id_set(client, chats):
|
||||
|
@ -79,13 +80,16 @@ class EventBuilder(abc.ABC):
|
|||
return event
|
||||
|
||||
|
||||
class EventCommon(abc.ABC):
|
||||
class EventCommon(ChatGetter, abc.ABC):
|
||||
"""
|
||||
Intermediate class with common things to all events.
|
||||
|
||||
All events (except `Raw`) have ``is_private``, ``is_group``
|
||||
and ``is_channel`` boolean properties, as well as an
|
||||
``original_update`` field containing the original :tl:`Update`.
|
||||
Remember that this class implements `ChatGetter
|
||||
<telethon.tl.custom.chatgetter.ChatGetter>` which
|
||||
means you have access to all chat properties and methods.
|
||||
|
||||
In addition, you can access the `original_update`
|
||||
field which contains the original :tl:`Update`.
|
||||
"""
|
||||
_event_name = 'Event'
|
||||
|
||||
|
@ -96,64 +100,27 @@ class EventCommon(abc.ABC):
|
|||
self._message_id = msg_id
|
||||
self._input_chat = None
|
||||
self._chat = None
|
||||
self._broadcast = broadcast
|
||||
self.original_update = None
|
||||
|
||||
self.is_private = isinstance(chat_peer, types.PeerUser)
|
||||
self.is_group = (
|
||||
isinstance(chat_peer, (types.PeerChat, types.PeerChannel))
|
||||
and not broadcast
|
||||
)
|
||||
self.is_channel = isinstance(chat_peer, types.PeerChannel)
|
||||
|
||||
def _set_client(self, client):
|
||||
"""
|
||||
Setter so subclasses can act accordingly when the client is set.
|
||||
"""
|
||||
self._client = client
|
||||
self._chat = self._entities.get(self.chat_id)
|
||||
if not self._chat:
|
||||
return
|
||||
|
||||
@property
|
||||
def input_chat(self):
|
||||
"""
|
||||
This (:tl:`InputPeer`) is the input version of the chat where the
|
||||
event occurred. This doesn't have things like username or similar,
|
||||
but is still useful in some cases.
|
||||
|
||||
Note that this might not be available if the library doesn't have
|
||||
enough information available.
|
||||
"""
|
||||
if self._input_chat is None and self._chat_peer is not None:
|
||||
self._input_chat = utils.get_input_peer(self._chat)
|
||||
if not getattr(self._input_chat, 'access_hash', True):
|
||||
# getattr with True to handle the InputPeerSelf() case
|
||||
try:
|
||||
self._input_chat =\
|
||||
self._client.session.get_input_entity(self._chat_peer)
|
||||
self._input_chat = self._client.session.get_input_entity(
|
||||
self._chat_peer
|
||||
)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return self._input_chat
|
||||
|
||||
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_peer is not None:
|
||||
ch = isinstance(self._chat_peer, types.PeerChannel)
|
||||
if not ch and self._message_id is not None:
|
||||
msg = await self._client.get_messages(
|
||||
None, ids=self._message_id)
|
||||
self._chat = msg._chat
|
||||
self._input_chat = msg._input_chat
|
||||
else:
|
||||
target = utils.get_peer_id(self._chat_peer)
|
||||
async for d in self._client.iter_dialogs(100):
|
||||
if d.id == target:
|
||||
self._chat = d.entity
|
||||
self._input_chat = d.input_entity
|
||||
# TODO Don't break, exhaust the iterator, otherwise
|
||||
# async_generator raises RuntimeError: partially-
|
||||
# exhausted async_generator 'xyz' garbage collected
|
||||
# break
|
||||
|
||||
return self._input_chat
|
||||
self._input_chat = None
|
||||
|
||||
@property
|
||||
def client(self):
|
||||
|
@ -162,44 +129,6 @@ class EventCommon(abc.ABC):
|
|||
"""
|
||||
return self._client
|
||||
|
||||
@property
|
||||
def chat(self):
|
||||
"""
|
||||
The :tl:`User`, :tl:`Chat` or :tl:`Channel` on which
|
||||
the event occurred. This property may make an API call the first time
|
||||
to get the most up to date version of the chat (mostly when the event
|
||||
doesn't belong to a channel), so keep that in mind. You should use
|
||||
`get_chat` instead, unless you want to avoid an API call.
|
||||
"""
|
||||
if not self.input_chat:
|
||||
return None
|
||||
|
||||
if self._chat is None:
|
||||
self._chat = self._entities.get(utils.get_peer_id(self._chat_peer))
|
||||
|
||||
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.
|
||||
"""
|
||||
if self.chat is None and await self.get_input_chat():
|
||||
try:
|
||||
self._chat =\
|
||||
await self._client.get_entity(self._input_chat)
|
||||
except ValueError:
|
||||
pass
|
||||
return self._chat
|
||||
|
||||
@property
|
||||
def chat_id(self):
|
||||
"""
|
||||
Returns the marked integer ID of the chat, if any.
|
||||
"""
|
||||
if self._chat_peer:
|
||||
return utils.get_peer_id(self._chat_peer)
|
||||
|
||||
def __str__(self):
|
||||
return TLObject.pretty_format(self.to_dict())
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ from async_generator import isasyncgenfunction
|
|||
|
||||
from .client.telegramclient import TelegramClient
|
||||
from .tl.custom import Draft, Dialog, MessageButton, Forward, Message
|
||||
from .tl.custom.chatgetter import ChatGetter
|
||||
from .tl.custom.sendergetter import SenderGetter
|
||||
|
||||
|
||||
def _syncify_coro(t, method_name):
|
||||
|
@ -78,4 +80,5 @@ def syncify(*types):
|
|||
_syncify_gen(t, method_name)
|
||||
|
||||
|
||||
syncify(TelegramClient, Draft, Dialog, MessageButton, Forward, Message)
|
||||
syncify(TelegramClient, Draft, Dialog, MessageButton,
|
||||
ChatGetter, SenderGetter, Forward, Message)
|
||||
|
|
114
telethon/tl/custom/chatgetter.py
Normal file
114
telethon/tl/custom/chatgetter.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
import abc
|
||||
|
||||
from ... import errors, utils
|
||||
from ...tl import types
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Subclasses **must** have the following private members: `_chat`,
|
||||
`_input_chat`, `_chat_peer`, `_broadcast` and `_client`. As an end
|
||||
user, you should not worry about this.
|
||||
"""
|
||||
@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.
|
||||
|
||||
If you're using `telethon.events`, use `get_chat` instead.
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
if self._chat is 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
|
||||
def input_chat(self):
|
||||
"""
|
||||
This :tl:`InputPeer` is the input version of the chat where the
|
||||
message was sent. Similarly to `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
|
||||
have enough information available.
|
||||
"""
|
||||
if self._input_chat is None and self._chat_peer:
|
||||
try:
|
||||
self._input_chat =\
|
||||
self._client.session.get_input_entity(self._chat_peer)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return self._input_chat
|
||||
|
||||
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:
|
||||
try:
|
||||
# The chat may be recent, look in dialogs
|
||||
target = self.chat_id
|
||||
async for d in self._client.iter_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
|
||||
|
||||
@property
|
||||
def chat_id(self):
|
||||
"""
|
||||
Returns the marked chat integer ID. Note that this value **will
|
||||
be different** from `to_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.
|
||||
"""
|
||||
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."""
|
||||
return isinstance(self._chat_peer, types.PeerUser)
|
||||
|
||||
@property
|
||||
def is_group(self):
|
||||
"""True if the message was sent on a group or megagroup."""
|
||||
if self._broadcast is None and self.chat:
|
||||
self._broadcast = getattr(self.chat, 'broadcast', None)
|
||||
|
||||
return (
|
||||
isinstance(self._chat_peer, (types.PeerChat, types.PeerChannel))
|
||||
and not self._broadcast
|
||||
)
|
||||
|
||||
@property
|
||||
def is_channel(self):
|
||||
"""True if the message was sent on a megagroup or channel."""
|
||||
return isinstance(self._chat_peer, types.PeerChannel)
|
||||
|
||||
async def _refetch_chat(self):
|
||||
"""
|
||||
Re-fetches chat information through other means.
|
||||
"""
|
|
@ -1,11 +1,19 @@
|
|||
from ...utils import get_input_peer
|
||||
from .chatgetter import ChatGetter
|
||||
from .sendergetter import SenderGetter
|
||||
from ... import utils
|
||||
from ...tl import types
|
||||
|
||||
|
||||
class Forward:
|
||||
class Forward(ChatGetter, SenderGetter):
|
||||
"""
|
||||
Custom class that encapsulates a :tl:`MessageFwdHeader` providing an
|
||||
abstraction to easily access information like the original sender.
|
||||
|
||||
Remember that this class implements `ChatGetter
|
||||
<telethon.tl.custom.chatgetter.ChatGetter>` and `SenderGetter
|
||||
<telethon.tl.custom.sendergetter.SenderGetter>` which means you
|
||||
have access to all their sender and chat properties and methods.
|
||||
|
||||
Attributes:
|
||||
|
||||
original_fwd (:tl:`MessageFwdHeader`):
|
||||
|
@ -19,105 +27,21 @@ class Forward:
|
|||
self.__dict__ = original.__dict__
|
||||
self._client = client
|
||||
self.original_fwd = original
|
||||
|
||||
self._sender_id = original.from_id
|
||||
self._sender = entities.get(original.from_id)
|
||||
self._chat = entities.get(original.channel_id)
|
||||
|
||||
self._input_sender =\
|
||||
get_input_peer(self._sender) if self._sender else None
|
||||
self._input_chat =\
|
||||
get_input_peer(self._chat) if self._chat else None
|
||||
utils.get_input_peer(self._sender) if self._sender else None
|
||||
|
||||
# TODO The pattern to get sender and chat is very similar
|
||||
# and copy pasted in/to several places. Reuse the code.
|
||||
#
|
||||
# It could be an ABC with some ``resolve_sender`` abstract,
|
||||
# so every subclass knew what tricks it can make to get
|
||||
# the sender.
|
||||
self._broadcast = None
|
||||
if original.channel_id:
|
||||
self._chat_peer = types.PeerChannel(original.channel_id)
|
||||
self._chat = entities.get(utils.get_peer_id(self._chat_peer))
|
||||
else:
|
||||
self._chat_peer = None
|
||||
self._chat = None
|
||||
|
||||
@property
|
||||
def sender(self):
|
||||
"""
|
||||
The :tl:`User` that sent the original message. This may be ``None``
|
||||
if it couldn't be found or the message wasn't forwarded from an user
|
||||
but instead was forwarded from e.g. a channel.
|
||||
"""
|
||||
return self._sender
|
||||
self._input_chat = \
|
||||
utils.get_input_peer(self._chat) if self._chat else None
|
||||
|
||||
async def get_sender(self):
|
||||
"""
|
||||
Returns `sender` but will make an API if necessary.
|
||||
"""
|
||||
if not self.sender and self.original_fwd.from_id:
|
||||
try:
|
||||
self._sender = await self._client.get_entity(
|
||||
await self.get_input_sender())
|
||||
except ValueError:
|
||||
# TODO We could reload the message
|
||||
pass
|
||||
|
||||
return self._sender
|
||||
|
||||
@property
|
||||
def input_sender(self):
|
||||
"""
|
||||
Returns the input version of `user`.
|
||||
"""
|
||||
if not self._input_sender and self.original_fwd.from_id:
|
||||
try:
|
||||
self._input_sender = self._client.session.get_input_entity(
|
||||
self.original_fwd.from_id)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return self._input_sender
|
||||
|
||||
async def get_input_sender(self):
|
||||
"""
|
||||
Returns `input_sender` but will make an API call if necessary.
|
||||
"""
|
||||
# TODO We could reload the message
|
||||
return self.input_sender
|
||||
|
||||
@property
|
||||
def chat(self):
|
||||
"""
|
||||
The :tl:`Channel` where the original message was sent. This may be
|
||||
``None`` if it couldn't be found or the message wasn't forwarded
|
||||
from a channel but instead was forwarded from e.g. an user.
|
||||
"""
|
||||
return self._chat
|
||||
|
||||
async def get_chat(self):
|
||||
"""
|
||||
Returns `chat` but will make an API if necessary.
|
||||
"""
|
||||
if not self.chat and self.original_fwd.channel_id:
|
||||
try:
|
||||
self._chat = await self._client.get_entity(
|
||||
await self.get_input_chat())
|
||||
except ValueError:
|
||||
# TODO We could reload the message
|
||||
pass
|
||||
|
||||
return self._chat
|
||||
|
||||
@property
|
||||
def input_chat(self):
|
||||
"""
|
||||
Returns the input version of `chat`.
|
||||
"""
|
||||
if not self._input_chat and self.original_fwd.channel_id:
|
||||
try:
|
||||
self._input_chat = self._client.session.get_input_entity(
|
||||
self.original_fwd.channel_id)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return self._input_chat
|
||||
|
||||
async def get_input_chat(self):
|
||||
"""
|
||||
Returns `input_chat` but will make an API call if necessary.
|
||||
"""
|
||||
# TODO We could reload the message
|
||||
return self.input_chat
|
||||
# TODO We could reload the message
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
from .. import types
|
||||
from ...utils import get_input_peer, get_peer_id, get_inner_text
|
||||
from ...utils import get_input_peer, get_inner_text
|
||||
from .chatgetter import ChatGetter
|
||||
from .sendergetter import SenderGetter
|
||||
from .messagebutton import MessageButton
|
||||
from .forward import Forward
|
||||
|
||||
|
||||
class Message:
|
||||
class Message(ChatGetter, SenderGetter):
|
||||
"""
|
||||
Custom class that encapsulates a message providing an abstraction to
|
||||
easily access some commonly needed features (such as the markdown text
|
||||
or the text for a given message entity).
|
||||
|
||||
Remember that this class implements `ChatGetter
|
||||
<telethon.tl.custom.chatgetter.ChatGetter>` and `SenderGetter
|
||||
<telethon.tl.custom.sendergetter.SenderGetter>` which means you
|
||||
have access to all their sender and chat properties and methods.
|
||||
|
||||
Attributes:
|
||||
|
||||
original_message (:tl:`Message`):
|
||||
|
@ -34,7 +41,8 @@ class Message:
|
|||
self._buttons_flat = None
|
||||
self._buttons_count = None
|
||||
|
||||
self._sender = entities.get(self.original_message.from_id)
|
||||
self._sender_id = self.original_message.from_id
|
||||
self._sender = entities.get(self._sender_id)
|
||||
if self._sender:
|
||||
self._input_sender = get_input_peer(self._sender)
|
||||
if not getattr(self._input_sender, 'access_hash', None):
|
||||
|
@ -46,10 +54,11 @@ class Message:
|
|||
# was sent, not *to which ID* it was sent.
|
||||
if not self.original_message.out \
|
||||
and isinstance(self.original_message.to_id, types.PeerUser):
|
||||
self._chat_peer = types.PeerUser(self.original_message.from_id)
|
||||
self._chat_peer = types.PeerUser(self._sender_id)
|
||||
else:
|
||||
self._chat_peer = self.original_message.to_id
|
||||
|
||||
self._broadcast = bool(self.original_message.post)
|
||||
self._chat = entities.get(self.chat_id)
|
||||
self._input_chat = input_chat
|
||||
if not self._input_chat and self._chat:
|
||||
|
@ -171,158 +180,8 @@ class Message:
|
|||
self._chat = msg._chat
|
||||
self._input_chat = msg._input_chat
|
||||
|
||||
@property
|
||||
def sender(self):
|
||||
"""
|
||||
Returns the :tl:`User` that sent this message. It may be ``None``
|
||||
if the message has no sender or if Telegram didn't send the sender
|
||||
inside message events.
|
||||
|
||||
If you're using `telethon.events`, use `get_sender` instead.
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
if self._sender is None and await self.get_input_sender():
|
||||
try:
|
||||
self._sender =\
|
||||
await self._client.get_entity(self._input_sender)
|
||||
except ValueError:
|
||||
await self._reload_message()
|
||||
return self._sender
|
||||
|
||||
@property
|
||||
def chat(self):
|
||||
"""
|
||||
Returns the :tl:`User`, :tl:`Chat` or :tl:`Channel` where this message
|
||||
was sent. It may be ``None`` if Telegram didn't send the chat inside
|
||||
message events.
|
||||
|
||||
If you're using `telethon.events`, use `get_chat` instead.
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
if self._chat is None and await self.get_input_chat():
|
||||
try:
|
||||
self._chat =\
|
||||
await self._client.get_entity(self._input_chat)
|
||||
except ValueError:
|
||||
await self._reload_message()
|
||||
return self._chat
|
||||
|
||||
@property
|
||||
def input_sender(self):
|
||||
"""
|
||||
This (:tl:`InputPeer`) is the input version of the user who
|
||||
sent the message. Similarly to `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
|
||||
find the input chat, or if the message a broadcast on a channel.
|
||||
"""
|
||||
if self._input_sender is None:
|
||||
if self.is_channel and not self.is_group:
|
||||
return None
|
||||
try:
|
||||
self._input_sender = self._client.session\
|
||||
.get_input_entity(self.original_message.from_id)
|
||||
except ValueError:
|
||||
pass
|
||||
return self._input_sender
|
||||
|
||||
async def get_input_sender(self):
|
||||
"""
|
||||
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 not self.is_channel and not self.is_group:
|
||||
await self._reload_message()
|
||||
return self._input_sender
|
||||
|
||||
@property
|
||||
def input_chat(self):
|
||||
"""
|
||||
This (:tl:`InputPeer`) is the input version of the chat where the
|
||||
message was sent. Similarly to `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 know
|
||||
where the message came from.
|
||||
"""
|
||||
if self._input_chat is None:
|
||||
try:
|
||||
self._input_chat =\
|
||||
self._client.session.get_input_entity(self._chat_peer)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return self._input_chat
|
||||
|
||||
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:
|
||||
# There's a chance that the chat is a recent new dialog.
|
||||
# The input chat cannot rely on ._reload_message() because
|
||||
# said method may need the input chat.
|
||||
target = self.chat_id
|
||||
async for d in self._client.iter_dialogs(100):
|
||||
if d.id == target:
|
||||
self._chat = d.entity
|
||||
self._input_chat = d.input_entity
|
||||
break
|
||||
|
||||
return self._input_chat
|
||||
|
||||
@property
|
||||
def sender_id(self):
|
||||
"""
|
||||
Returns the marked sender integer ID, if present.
|
||||
"""
|
||||
return self.original_message.from_id
|
||||
|
||||
@property
|
||||
def chat_id(self):
|
||||
"""
|
||||
Returns the marked chat integer ID. Note that this value **will
|
||||
be different** from `to_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.
|
||||
"""
|
||||
return get_peer_id(self._chat_peer)
|
||||
|
||||
@property
|
||||
def is_private(self):
|
||||
"""True if the message was sent as a private message."""
|
||||
return isinstance(self.original_message.to_id, types.PeerUser)
|
||||
|
||||
@property
|
||||
def is_group(self):
|
||||
"""True if the message was sent on a group or megagroup."""
|
||||
return (
|
||||
isinstance(self.original_message.to_id, (types.PeerChat,
|
||||
types.PeerChannel))
|
||||
and not self.original_message.post
|
||||
)
|
||||
|
||||
@property
|
||||
def is_channel(self):
|
||||
"""True if the message was sent on a megagroup or channel."""
|
||||
return isinstance(self.original_message.to_id, types.PeerChannel)
|
||||
async def _refetch_sender(self):
|
||||
await self._reload_message()
|
||||
|
||||
@property
|
||||
def is_reply(self):
|
||||
|
@ -602,10 +461,10 @@ class Message:
|
|||
if self.original_message.fwd_from:
|
||||
return None
|
||||
if not self.original_message.out:
|
||||
if not isinstance(self.original_message.to_id, types.PeerUser):
|
||||
if not isinstance(self._chat_peer, types.PeerUser):
|
||||
return None
|
||||
me = await self._client.get_me(input_peer=True)
|
||||
if self.original_message.to_id.user_id != me.user_id:
|
||||
if self._chat_peer.user_id != me.user_id:
|
||||
return None
|
||||
|
||||
return await self._client.edit_message(
|
||||
|
|
74
telethon/tl/custom/sendergetter.py
Normal file
74
telethon/tl/custom/sendergetter.py
Normal file
|
@ -0,0 +1,74 @@
|
|||
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.
|
||||
|
||||
Subclasses **must** have the following private members: `_sender`,
|
||||
`_input_sender`, `_sender_id` and `_client`. As an end user, you
|
||||
should not worry about this.
|
||||
"""
|
||||
@property
|
||||
def sender(self):
|
||||
"""
|
||||
Returns the :tl:`User` that created this object. It may be ``None``
|
||||
if the object has no sender or if Telegram didn't send the sender.
|
||||
|
||||
If you're using `telethon.events`, use `get_sender` instead.
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
if self._sender is None and await self.get_input_sender():
|
||||
try:
|
||||
self._sender =\
|
||||
await self._client.get_entity(self._input_sender)
|
||||
except ValueError:
|
||||
await self._reload_message()
|
||||
return self._sender
|
||||
|
||||
@property
|
||||
def input_sender(self):
|
||||
"""
|
||||
This :tl:`InputPeer` is the input version of the user who
|
||||
sent the message. Similarly to `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
|
||||
find the input chat, or if the message a broadcast on a channel.
|
||||
"""
|
||||
if self._input_sender is None and self._sender_id:
|
||||
try:
|
||||
self._input_sender = self._client.session\
|
||||
.get_input_entity(self._sender_id)
|
||||
except ValueError:
|
||||
pass
|
||||
return self._input_sender
|
||||
|
||||
async def get_input_sender(self):
|
||||
"""
|
||||
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:
|
||||
await self._refetch_sender()
|
||||
return self._input_sender
|
||||
|
||||
@property
|
||||
def sender_id(self):
|
||||
"""
|
||||
Returns the marked sender integer ID, if present.
|
||||
"""
|
||||
return self._sender_id
|
||||
|
||||
async def _refetch_sender(self):
|
||||
"""
|
||||
Re-fetches sender information through other means.
|
||||
"""
|
Loading…
Reference in New Issue
Block a user