mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-06-28 17:33:08 +03:00
Make custom.Message functional
This commit is contained in:
parent
499fc9f603
commit
334a847de7
|
@ -119,6 +119,32 @@ The following modules have been moved inside ``_misc``:
|
||||||
// TODO review telethon/__init__.py isn't exposing more than it should
|
// TODO review telethon/__init__.py isn't exposing more than it should
|
||||||
|
|
||||||
|
|
||||||
|
The custom.Message class and the way it is used has changed
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
It no longer inherits ``TLObject``, and rather than trying to mimick Telegram's ``Message``
|
||||||
|
constructor, it now takes two parameters: a ``TelegramClient`` instance and a ``_tl.Message``.
|
||||||
|
As a benefit, you can now more easily reconstruct instances of this type from a previously-stored
|
||||||
|
``_tl.Message`` instance.
|
||||||
|
|
||||||
|
There are no public attributes. Instead, they are now properties which forward the values into and
|
||||||
|
from the private ``_message`` field. As a benefit, the documentation will now be easier to follow.
|
||||||
|
However, you can no longer use ``del`` on these.
|
||||||
|
|
||||||
|
The ``_tl.Message.media`` attribute will no longer be ``None`` when using raw API if the media was
|
||||||
|
``messageMediaEmpty``. As a benefit, you can now actually distinguish between no media and empty
|
||||||
|
media. The ``Message.media`` property as returned by friendly methods will still be ``None`` on
|
||||||
|
empty media.
|
||||||
|
|
||||||
|
The ``telethon.tl.patched`` hack has been removed.
|
||||||
|
|
||||||
|
In order to avoid breaking more code than strictly necessary, ``.raw_text`` will remain a synonym
|
||||||
|
of ``.message``, and ``.text`` will still be the text formatted through the ``client.parse_mode``.
|
||||||
|
However, you're encouraged to change uses of ``.raw_text`` with ``.message``, and ``.text`` with
|
||||||
|
either ``.md_text`` or ``.html_text`` as needed. This is because both ``.text`` and ``.raw_text``
|
||||||
|
may disappear in future versions, and their behaviour is not immediately obvious.
|
||||||
|
|
||||||
|
|
||||||
The Conversation API has been removed
|
The Conversation API has been removed
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -291,16 +291,16 @@ class _AdminLogIter(requestiter.RequestIter):
|
||||||
for ev in r.events:
|
for ev in r.events:
|
||||||
if isinstance(ev.action,
|
if isinstance(ev.action,
|
||||||
_tl.ChannelAdminLogEventActionEditMessage):
|
_tl.ChannelAdminLogEventActionEditMessage):
|
||||||
ev.action.prev_message._finish_init(
|
ev.action.prev_message = _custom.Message._new(
|
||||||
self.client, entities, self.entity)
|
self.client, ev.action.prev_message, entities, self.entity)
|
||||||
|
|
||||||
ev.action.new_message._finish_init(
|
ev.action.new_message = _custom.Message._new(
|
||||||
self.client, entities, self.entity)
|
self.client, ev.action.new_message, entities, self.entity)
|
||||||
|
|
||||||
elif isinstance(ev.action,
|
elif isinstance(ev.action,
|
||||||
_tl.ChannelAdminLogEventActionDeleteMessage):
|
_tl.ChannelAdminLogEventActionDeleteMessage):
|
||||||
ev.action.message._finish_init(
|
ev.action.message = _custom.Message._new(
|
||||||
self.client, entities, self.entity)
|
self.client, ev.action.message, entities, self.entity)
|
||||||
|
|
||||||
self.buffer.append(_custom.AdminLogEvent(ev, entities))
|
self.buffer.append(_custom.AdminLogEvent(ev, entities))
|
||||||
|
|
||||||
|
|
|
@ -58,10 +58,10 @@ class _DialogsIter(requestiter.RequestIter):
|
||||||
for x in itertools.chain(r.users, r.chats)
|
for x in itertools.chain(r.users, r.chats)
|
||||||
if not isinstance(x, (_tl.UserEmpty, _tl.ChatEmpty))}
|
if not isinstance(x, (_tl.UserEmpty, _tl.ChatEmpty))}
|
||||||
|
|
||||||
messages = {}
|
messages = {
|
||||||
for m in r.messages:
|
_dialog_message_key(m.peer_id, m.id): _custom.Message._new(self.client, m, entities, None)
|
||||||
m._finish_init(self.client, entities, None)
|
for m in r.messages
|
||||||
messages[_dialog_message_key(m.peer_id, m.id)] = m
|
}
|
||||||
|
|
||||||
for d in r.dialogs:
|
for d in r.dialogs:
|
||||||
# We check the offset date here because Telegram may ignore it
|
# We check the offset date here because Telegram may ignore it
|
||||||
|
|
|
@ -3,6 +3,7 @@ import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from .. import helpers, utils, _tl
|
from .. import helpers, utils, _tl
|
||||||
|
from ..types import _custom
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from .telegramclient import TelegramClient
|
from .telegramclient import TelegramClient
|
||||||
|
@ -94,7 +95,7 @@ def _get_response_message(self: 'TelegramClient', request, result, input_chat):
|
||||||
|
|
||||||
elif isinstance(update, (
|
elif isinstance(update, (
|
||||||
_tl.UpdateNewChannelMessage, _tl.UpdateNewMessage)):
|
_tl.UpdateNewChannelMessage, _tl.UpdateNewMessage)):
|
||||||
update.message._finish_init(self, entities, input_chat)
|
update.message = _custom.Message._new(self, update.message, entities, input_chat)
|
||||||
|
|
||||||
# Pinning a message with `updatePinnedMessage` seems to
|
# Pinning a message with `updatePinnedMessage` seems to
|
||||||
# always produce a service message we can't map so return
|
# always produce a service message we can't map so return
|
||||||
|
@ -110,7 +111,7 @@ def _get_response_message(self: 'TelegramClient', request, result, input_chat):
|
||||||
|
|
||||||
elif (isinstance(update, _tl.UpdateEditMessage)
|
elif (isinstance(update, _tl.UpdateEditMessage)
|
||||||
and helpers._entity_type(request.peer) != helpers._EntityType.CHANNEL):
|
and helpers._entity_type(request.peer) != helpers._EntityType.CHANNEL):
|
||||||
update.message._finish_init(self, entities, input_chat)
|
update.message = _custom.Message._new(self, update.message, entities, input_chat)
|
||||||
|
|
||||||
# Live locations use `sendMedia` but Telegram responds with
|
# Live locations use `sendMedia` but Telegram responds with
|
||||||
# `updateEditMessage`, which means we won't have `id` field.
|
# `updateEditMessage`, which means we won't have `id` field.
|
||||||
|
@ -123,28 +124,24 @@ def _get_response_message(self: 'TelegramClient', request, result, input_chat):
|
||||||
and utils.get_peer_id(request.peer) ==
|
and utils.get_peer_id(request.peer) ==
|
||||||
utils.get_peer_id(update.message.peer_id)):
|
utils.get_peer_id(update.message.peer_id)):
|
||||||
if request.id == update.message.id:
|
if request.id == update.message.id:
|
||||||
update.message._finish_init(self, entities, input_chat)
|
return _custom.Message._new(self, update.message, entities, input_chat)
|
||||||
return update.message
|
|
||||||
|
|
||||||
elif isinstance(update, _tl.UpdateNewScheduledMessage):
|
elif isinstance(update, _tl.UpdateNewScheduledMessage):
|
||||||
update.message._finish_init(self, entities, input_chat)
|
|
||||||
# Scheduled IDs may collide with normal IDs. However, for a
|
# Scheduled IDs may collide with normal IDs. However, for a
|
||||||
# single request there *shouldn't* be a mix between "some
|
# single request there *shouldn't* be a mix between "some
|
||||||
# scheduled and some not".
|
# scheduled and some not".
|
||||||
id_to_message[update.message.id] = update.message
|
id_to_message[update.message.id] = _custom.Message._new(self, update.message, entities, input_chat)
|
||||||
|
|
||||||
elif isinstance(update, _tl.UpdateMessagePoll):
|
elif isinstance(update, _tl.UpdateMessagePoll):
|
||||||
if request.media.poll.id == update.poll_id:
|
if request.media.poll.id == update.poll_id:
|
||||||
m = _tl.Message(
|
return _custom.Message._new(self, _tl.Message(
|
||||||
id=request.id,
|
id=request.id,
|
||||||
peer_id=utils.get_peer(request.peer),
|
peer_id=utils.get_peer(request.peer),
|
||||||
media=_tl.MessageMediaPoll(
|
media=_tl.MessageMediaPoll(
|
||||||
poll=update.poll,
|
poll=update.poll,
|
||||||
results=update.results
|
results=update.results
|
||||||
)
|
)
|
||||||
)
|
), entities, input_chat)
|
||||||
m._finish_init(self, entities, input_chat)
|
|
||||||
return m
|
|
||||||
|
|
||||||
if request is None:
|
if request is None:
|
||||||
return id_to_message
|
return id_to_message
|
||||||
|
|
|
@ -5,6 +5,7 @@ import warnings
|
||||||
|
|
||||||
from .. import errors, hints, _tl
|
from .. import errors, hints, _tl
|
||||||
from .._misc import helpers, utils, requestiter
|
from .._misc import helpers, utils, requestiter
|
||||||
|
from ..types import _custom
|
||||||
|
|
||||||
_MAX_CHUNK_SIZE = 100
|
_MAX_CHUNK_SIZE = 100
|
||||||
|
|
||||||
|
@ -200,8 +201,7 @@ class _MessagesIter(requestiter.RequestIter):
|
||||||
# is an attempt to avoid these duplicates, since the message
|
# is an attempt to avoid these duplicates, since the message
|
||||||
# IDs are returned in descending order (or asc if reverse).
|
# IDs are returned in descending order (or asc if reverse).
|
||||||
self.last_id = message.id
|
self.last_id = message.id
|
||||||
message._finish_init(self.client, entities, self.entity)
|
self.buffer.append(_custom.Message._new(self.client, message, entities, self.entity))
|
||||||
self.buffer.append(message)
|
|
||||||
|
|
||||||
if len(r.messages) < self.request.limit:
|
if len(r.messages) < self.request.limit:
|
||||||
return True
|
return True
|
||||||
|
@ -315,8 +315,7 @@ class _IDsIter(requestiter.RequestIter):
|
||||||
from_id and message.peer_id != from_id):
|
from_id and message.peer_id != from_id):
|
||||||
self.buffer.append(None)
|
self.buffer.append(None)
|
||||||
else:
|
else:
|
||||||
message._finish_init(self.client, entities, self._entity)
|
self.buffer.append(_custom.Message._new(self.client, message, entities, self._entity))
|
||||||
self.buffer.append(message)
|
|
||||||
|
|
||||||
|
|
||||||
def iter_messages(
|
def iter_messages(
|
||||||
|
@ -498,7 +497,7 @@ async def send_message(
|
||||||
|
|
||||||
result = await self(request)
|
result = await self(request)
|
||||||
if isinstance(result, _tl.UpdateShortSentMessage):
|
if isinstance(result, _tl.UpdateShortSentMessage):
|
||||||
message = _tl.Message(
|
return _custom.Message._new(self, _tl.Message(
|
||||||
id=result.id,
|
id=result.id,
|
||||||
peer_id=await self._get_peer(entity),
|
peer_id=await self._get_peer(entity),
|
||||||
message=message,
|
message=message,
|
||||||
|
@ -508,9 +507,7 @@ async def send_message(
|
||||||
entities=result.entities,
|
entities=result.entities,
|
||||||
reply_markup=request.reply_markup,
|
reply_markup=request.reply_markup,
|
||||||
ttl_period=result.ttl_period
|
ttl_period=result.ttl_period
|
||||||
)
|
), {}, entity)
|
||||||
message._finish_init(self, {}, entity)
|
|
||||||
return message
|
|
||||||
|
|
||||||
return self._get_response_message(request, result, entity)
|
return self._get_response_message(request, result, entity)
|
||||||
|
|
||||||
|
|
|
@ -3783,6 +3783,9 @@ class TelegramClient:
|
||||||
async def _handle_auto_reconnect(self: 'TelegramClient'):
|
async def _handle_auto_reconnect(self: 'TelegramClient'):
|
||||||
return await updates._handle_auto_reconnect(**locals())
|
return await updates._handle_auto_reconnect(**locals())
|
||||||
|
|
||||||
|
def _self_id(self: 'TelegramClient') -> typing.Optional[int]:
|
||||||
|
return users._self_id(**locals())
|
||||||
|
|
||||||
# endregion Private
|
# endregion Private
|
||||||
|
|
||||||
# TODO re-patch everything to remove the intermediate calls
|
# TODO re-patch everything to remove the intermediate calls
|
||||||
|
|
|
@ -168,8 +168,10 @@ class Album(EventBuilder):
|
||||||
self._sender, self._input_sender = utils._get_entity_pair(
|
self._sender, self._input_sender = utils._get_entity_pair(
|
||||||
self.sender_id, self._entities, client._entity_cache)
|
self.sender_id, self._entities, client._entity_cache)
|
||||||
|
|
||||||
for msg in self.messages:
|
self.messages = [
|
||||||
msg._finish_init(client, self._entities, None)
|
_custom.Message._new(client, m, self._entities, None)
|
||||||
|
for m in self.messages
|
||||||
|
]
|
||||||
|
|
||||||
if len(self.messages) == 1:
|
if len(self.messages) == 1:
|
||||||
# This will require hacks to be a proper album event
|
# This will require hacks to be a proper album event
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from .common import EventBuilder, EventCommon, name_inner_event
|
from .common import EventBuilder, EventCommon, name_inner_event
|
||||||
from .._misc import utils
|
from .._misc import utils
|
||||||
from .. import _tl
|
from .. import _tl
|
||||||
|
from ..types import _custom
|
||||||
|
|
||||||
|
|
||||||
@name_inner_event
|
@name_inner_event
|
||||||
|
|
|
@ -3,6 +3,7 @@ import re
|
||||||
from .common import EventBuilder, EventCommon, name_inner_event, _into_id_set
|
from .common import EventBuilder, EventCommon, name_inner_event, _into_id_set
|
||||||
from .._misc import utils
|
from .._misc import utils
|
||||||
from .. import _tl
|
from .. import _tl
|
||||||
|
from ..types import _custom
|
||||||
|
|
||||||
|
|
||||||
@name_inner_event
|
@name_inner_event
|
||||||
|
|
|
@ -9,9 +9,22 @@ from ..._misc import utils, tlobject
|
||||||
from ... import errors, _tl
|
from ... import errors, _tl
|
||||||
|
|
||||||
|
|
||||||
|
def _fwd(field, doc):
|
||||||
|
def fget(self):
|
||||||
|
try:
|
||||||
|
return self._message.__dict__[field]
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def fset(self, value):
|
||||||
|
self._message.__dict__[field] = value
|
||||||
|
|
||||||
|
return property(fget, fset, None, doc)
|
||||||
|
|
||||||
|
|
||||||
# TODO Figure out a way to have the code generator error on missing fields
|
# TODO Figure out a way to have the code generator error on missing fields
|
||||||
# Maybe parsing the init function alone if that's possible.
|
# Maybe parsing the init function alone if that's possible.
|
||||||
class Message(ChatGetter, SenderGetter, tlobject.TLObject):
|
class Message(ChatGetter, SenderGetter):
|
||||||
"""
|
"""
|
||||||
This custom class aggregates both :tl:`Message` and
|
This custom class aggregates both :tl:`Message` and
|
||||||
:tl:`MessageService` to ease accessing their members.
|
:tl:`MessageService` to ease accessing their members.
|
||||||
|
@ -20,9 +33,11 @@ class Message(ChatGetter, SenderGetter, tlobject.TLObject):
|
||||||
<telethon.tl.custom.chatgetter.ChatGetter>` and `SenderGetter
|
<telethon.tl.custom.chatgetter.ChatGetter>` and `SenderGetter
|
||||||
<telethon.tl.custom.sendergetter.SenderGetter>` which means you
|
<telethon.tl.custom.sendergetter.SenderGetter>` which means you
|
||||||
have access to all their sender and chat properties and methods.
|
have access to all their sender and chat properties and methods.
|
||||||
|
"""
|
||||||
|
|
||||||
Members:
|
# region Forwarded properties
|
||||||
out (`bool`):
|
|
||||||
|
out = _fwd('out', """
|
||||||
Whether the message is outgoing (i.e. you sent it from
|
Whether the message is outgoing (i.e. you sent it from
|
||||||
another session) or incoming (i.e. someone else sent it).
|
another session) or incoming (i.e. someone else sent it).
|
||||||
|
|
||||||
|
@ -31,76 +46,95 @@ class Message(ChatGetter, SenderGetter, tlobject.TLObject):
|
||||||
to your own chat. Messages you forward to your chat are
|
to your own chat. Messages you forward to your chat are
|
||||||
*not* considered outgoing, just like official clients
|
*not* considered outgoing, just like official clients
|
||||||
display them.
|
display them.
|
||||||
|
""")
|
||||||
|
|
||||||
mentioned (`bool`):
|
mentioned = _fwd('mentioned', """
|
||||||
Whether you were mentioned in this message or not.
|
Whether you were mentioned in this message or not.
|
||||||
Note that replies to your own messages also count
|
Note that replies to your own messages also count
|
||||||
as mentions.
|
as mentions.
|
||||||
|
""")
|
||||||
|
|
||||||
media_unread (`bool`):
|
media_unread = _fwd('media_unread', """
|
||||||
Whether you have read the media in this message
|
Whether you have read the media in this message
|
||||||
or not, e.g. listened to the voice note media.
|
or not, e.g. listened to the voice note media.
|
||||||
|
""")
|
||||||
|
|
||||||
silent (`bool`):
|
silent = _fwd('silent', """
|
||||||
Whether the message should notify people with sound or not.
|
Whether the message should notify people with sound or not.
|
||||||
Previously used in channels, but since 9 August 2019, it can
|
Previously used in channels, but since 9 August 2019, it can
|
||||||
also be `used in private chats
|
also be `used in private chats
|
||||||
<https://telegram.org/blog/silent-messages-slow-mode>`_.
|
<https://telegram.org/blog/silent-messages-slow-mode>`_.
|
||||||
|
""")
|
||||||
|
|
||||||
post (`bool`):
|
post = _fwd('post', """
|
||||||
Whether this message is a post in a broadcast
|
Whether this message is a post in a broadcast
|
||||||
channel or not.
|
channel or not.
|
||||||
|
""")
|
||||||
|
|
||||||
from_scheduled (`bool`):
|
from_scheduled = _fwd('from_scheduled', """
|
||||||
Whether this message was originated from a previously-scheduled
|
Whether this message was originated from a previously-scheduled
|
||||||
message or not.
|
message or not.
|
||||||
|
""")
|
||||||
|
|
||||||
legacy (`bool`):
|
legacy = _fwd('legacy', """
|
||||||
Whether this is a legacy message or not.
|
Whether this is a legacy message or not.
|
||||||
|
""")
|
||||||
|
|
||||||
edit_hide (`bool`):
|
edit_hide = _fwd('edit_hide', """
|
||||||
Whether the edited mark of this message is edited
|
Whether the edited mark of this message is edited
|
||||||
should be hidden (e.g. in GUI clients) or shown.
|
should be hidden (e.g. in GUI clients) or shown.
|
||||||
|
""")
|
||||||
|
|
||||||
pinned (`bool`):
|
pinned = _fwd('pinned', """
|
||||||
Whether this message is currently pinned or not.
|
Whether this message is currently pinned or not.
|
||||||
|
""")
|
||||||
|
|
||||||
id (`int`):
|
id = _fwd('id', """
|
||||||
The ID of this message. This field is *always* present.
|
The ID of this message. This field is *always* present.
|
||||||
Any other member is optional and may be `None`.
|
Any other member is optional and may be `None`.
|
||||||
|
""")
|
||||||
|
|
||||||
from_id (:tl:`Peer`):
|
from_id = _fwd('from_id', """
|
||||||
The peer who sent this message, which is either
|
The peer who sent this message, which is either
|
||||||
:tl:`PeerUser`, :tl:`PeerChat` or :tl:`PeerChannel`.
|
:tl:`PeerUser`, :tl:`PeerChat` or :tl:`PeerChannel`.
|
||||||
This value will be `None` for anonymous messages.
|
This value will be `None` for anonymous messages.
|
||||||
|
""")
|
||||||
|
|
||||||
peer_id (:tl:`Peer`):
|
peer_id = _fwd('peer_id', """
|
||||||
The peer to which this message was sent, which is either
|
The peer to which this message was sent, which is either
|
||||||
:tl:`PeerUser`, :tl:`PeerChat` or :tl:`PeerChannel`. This
|
:tl:`PeerUser`, :tl:`PeerChat` or :tl:`PeerChannel`. This
|
||||||
will always be present except for empty messages.
|
will always be present except for empty messages.
|
||||||
|
""")
|
||||||
|
|
||||||
fwd_from (:tl:`MessageFwdHeader`):
|
fwd_from = _fwd('fwd_from', """
|
||||||
The original forward header if this message is a forward.
|
The original forward header if this message is a forward.
|
||||||
You should probably use the `forward` property instead.
|
You should probably use the `forward` property instead.
|
||||||
|
""")
|
||||||
|
|
||||||
via_bot_id (`int`):
|
via_bot_id = _fwd('via_bot_id', """
|
||||||
The ID of the bot used to send this message
|
The ID of the bot used to send this message
|
||||||
through its inline mode (e.g. "via @like").
|
through its inline mode (e.g. "via @like").
|
||||||
|
""")
|
||||||
|
|
||||||
reply_to (:tl:`MessageReplyHeader`):
|
reply_to = _fwd('reply_to', """
|
||||||
The original reply header if this message is replying to another.
|
The original reply header if this message is replying to another.
|
||||||
|
""")
|
||||||
|
|
||||||
date (`datetime`):
|
date = _fwd('date', """
|
||||||
The UTC+0 `datetime` object indicating when this message
|
The UTC+0 `datetime` object indicating when this message
|
||||||
was sent. This will always be present except for empty
|
was sent. This will always be present except for empty
|
||||||
messages.
|
messages.
|
||||||
|
""")
|
||||||
|
|
||||||
message (`str`):
|
message = _fwd('message', """
|
||||||
The string text of the message for `Message
|
The string text of the message for `Message
|
||||||
<telethon.tl.custom.message.Message>` instances,
|
<telethon.tl.custom.message.Message>` instances,
|
||||||
which will be `None` for other types of messages.
|
which will be `None` for other types of messages.
|
||||||
|
""")
|
||||||
|
|
||||||
media (:tl:`MessageMedia`):
|
@property
|
||||||
|
def media(self):
|
||||||
|
"""
|
||||||
The media sent with this message if any (such as
|
The media sent with this message if any (such as
|
||||||
photos, videos, documents, gifs, stickers, etc.).
|
photos, videos, documents, gifs, stickers, etc.).
|
||||||
|
|
||||||
|
@ -109,34 +143,52 @@ class Message(ChatGetter, SenderGetter, tlobject.TLObject):
|
||||||
|
|
||||||
If the media was not present or it was :tl:`MessageMediaEmpty`,
|
If the media was not present or it was :tl:`MessageMediaEmpty`,
|
||||||
this member will instead be `None` for convenience.
|
this member will instead be `None` for convenience.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
media = self._message.media
|
||||||
|
except AttributeError:
|
||||||
|
return None
|
||||||
|
|
||||||
reply_markup (:tl:`ReplyMarkup`):
|
return None if media.CONSTRUCTOR_ID == 0x3ded6320 else media
|
||||||
|
|
||||||
|
@media.setter
|
||||||
|
def media(self, value):
|
||||||
|
self._message.media = value
|
||||||
|
|
||||||
|
reply_markup = _fwd('reply_markup', """
|
||||||
The reply markup for this message (which was sent
|
The reply markup for this message (which was sent
|
||||||
either via a bot or by a bot). You probably want
|
either via a bot or by a bot). You probably want
|
||||||
to access `buttons` instead.
|
to access `buttons` instead.
|
||||||
|
""")
|
||||||
|
|
||||||
entities (List[:tl:`MessageEntity`]):
|
entities = _fwd('entities', """
|
||||||
The list of markup entities in this message,
|
The list of markup entities in this message,
|
||||||
such as bold, italics, code, hyperlinks, etc.
|
such as bold, italics, code, hyperlinks, etc.
|
||||||
|
""")
|
||||||
|
|
||||||
views (`int`):
|
views = _fwd('views', """
|
||||||
The number of views this message from a broadcast
|
The number of views this message from a broadcast
|
||||||
channel has. This is also present in forwards.
|
channel has. This is also present in forwards.
|
||||||
|
""")
|
||||||
|
|
||||||
forwards (`int`):
|
forwards = _fwd('forwards', """
|
||||||
The number of times this message has been forwarded.
|
The number of times this message has been forwarded.
|
||||||
|
""")
|
||||||
|
|
||||||
replies (`int`):
|
replies = _fwd('replies', """
|
||||||
The number of times another message has replied to this message.
|
The number of times another message has replied to this message.
|
||||||
|
""")
|
||||||
|
|
||||||
edit_date (`datetime`):
|
edit_date = _fwd('edit_date', """
|
||||||
The date when this message was last edited.
|
The date when this message was last edited.
|
||||||
|
""")
|
||||||
|
|
||||||
post_author (`str`):
|
post_author = _fwd('post_author', """
|
||||||
The display name of the message sender to
|
The display name of the message sender to
|
||||||
show in messages sent to broadcast channels.
|
show in messages sent to broadcast channels.
|
||||||
|
""")
|
||||||
|
|
||||||
grouped_id (`int`):
|
grouped_id = _fwd('grouped_id', """
|
||||||
If this message belongs to a group of messages
|
If this message belongs to a group of messages
|
||||||
(photo albums or video albums), all of them will
|
(photo albums or video albums), all of them will
|
||||||
have the same value here.
|
have the same value here.
|
||||||
|
@ -144,95 +196,29 @@ class Message(ChatGetter, SenderGetter, tlobject.TLObject):
|
||||||
restriction_reason (List[:tl:`RestrictionReason`])
|
restriction_reason (List[:tl:`RestrictionReason`])
|
||||||
An optional list of reasons why this message was restricted.
|
An optional list of reasons why this message was restricted.
|
||||||
If the list is `None`, this message has not been restricted.
|
If the list is `None`, this message has not been restricted.
|
||||||
|
""")
|
||||||
|
|
||||||
ttl_period (`int`):
|
ttl_period = _fwd('ttl_period', """
|
||||||
The Time To Live period configured for this message.
|
The Time To Live period configured for this message.
|
||||||
The message should be erased from wherever it's stored (memory, a
|
The message should be erased from wherever it's stored (memory, a
|
||||||
local database, etc.) when
|
local database, etc.) when
|
||||||
``datetime.now() > message.date + timedelta(seconds=message.ttl_period)``.
|
``datetime.now() > message.date + timedelta(seconds=message.ttl_period)``.
|
||||||
|
""")
|
||||||
|
|
||||||
action (:tl:`MessageAction`):
|
action = _fwd('action', """
|
||||||
The message action object of the message for :tl:`MessageService`
|
The message action object of the message for :tl:`MessageService`
|
||||||
instances, which will be `None` for other types of messages.
|
instances, which will be `None` for other types of messages.
|
||||||
"""
|
""")
|
||||||
|
|
||||||
|
# endregion
|
||||||
|
|
||||||
# region Initialization
|
# region Initialization
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, client, message):
|
||||||
# Common to all
|
self._client = client
|
||||||
self, id: int,
|
self._message = message
|
||||||
|
|
||||||
# Common to Message and MessageService (mandatory)
|
|
||||||
peer_id: _tl.TypePeer = None,
|
|
||||||
date: Optional[datetime] = None,
|
|
||||||
|
|
||||||
# Common to Message and MessageService (flags)
|
|
||||||
out: Optional[bool] = None,
|
|
||||||
mentioned: Optional[bool] = None,
|
|
||||||
media_unread: Optional[bool] = None,
|
|
||||||
silent: Optional[bool] = None,
|
|
||||||
post: Optional[bool] = None,
|
|
||||||
from_id: Optional[_tl.TypePeer] = None,
|
|
||||||
reply_to: Optional[_tl.TypeMessageReplyHeader] = None,
|
|
||||||
ttl_period: Optional[int] = None,
|
|
||||||
|
|
||||||
# For Message (mandatory)
|
|
||||||
message: Optional[str] = None,
|
|
||||||
|
|
||||||
# For Message (flags)
|
|
||||||
fwd_from: Optional[_tl.TypeMessageFwdHeader] = None,
|
|
||||||
via_bot_id: Optional[int] = None,
|
|
||||||
media: Optional[_tl.TypeMessageMedia] = None,
|
|
||||||
reply_markup: Optional[_tl.TypeReplyMarkup] = None,
|
|
||||||
entities: Optional[List[_tl.TypeMessageEntity]] = None,
|
|
||||||
views: Optional[int] = None,
|
|
||||||
edit_date: Optional[datetime] = None,
|
|
||||||
post_author: Optional[str] = None,
|
|
||||||
grouped_id: Optional[int] = None,
|
|
||||||
from_scheduled: Optional[bool] = None,
|
|
||||||
legacy: Optional[bool] = None,
|
|
||||||
edit_hide: Optional[bool] = None,
|
|
||||||
pinned: Optional[bool] = None,
|
|
||||||
restriction_reason: Optional[_tl.TypeRestrictionReason] = None,
|
|
||||||
forwards: Optional[int] = None,
|
|
||||||
replies: Optional[_tl.TypeMessageReplies] = None,
|
|
||||||
|
|
||||||
# For MessageAction (mandatory)
|
|
||||||
action: Optional[_tl.TypeMessageAction] = None
|
|
||||||
):
|
|
||||||
# Common properties to messages, then to service (in the order they're defined in the `.tl`)
|
|
||||||
self.out = bool(out)
|
|
||||||
self.mentioned = mentioned
|
|
||||||
self.media_unread = media_unread
|
|
||||||
self.silent = silent
|
|
||||||
self.post = post
|
|
||||||
self.from_scheduled = from_scheduled
|
|
||||||
self.legacy = legacy
|
|
||||||
self.edit_hide = edit_hide
|
|
||||||
self.id = id
|
|
||||||
self.from_id = from_id
|
|
||||||
self.peer_id = peer_id
|
|
||||||
self.fwd_from = fwd_from
|
|
||||||
self.via_bot_id = via_bot_id
|
|
||||||
self.reply_to = reply_to
|
|
||||||
self.date = date
|
|
||||||
self.message = message
|
|
||||||
self.media = None if isinstance(media, _tl.MessageMediaEmpty) else media
|
|
||||||
self.reply_markup = reply_markup
|
|
||||||
self.entities = entities
|
|
||||||
self.views = views
|
|
||||||
self.forwards = forwards
|
|
||||||
self.replies = replies
|
|
||||||
self.edit_date = edit_date
|
|
||||||
self.pinned = pinned
|
|
||||||
self.post_author = post_author
|
|
||||||
self.grouped_id = grouped_id
|
|
||||||
self.restriction_reason = restriction_reason
|
|
||||||
self.ttl_period = ttl_period
|
|
||||||
self.action = action
|
|
||||||
|
|
||||||
# Convenient storage for custom functions
|
# Convenient storage for custom functions
|
||||||
# TODO This is becoming a bit of bloat
|
|
||||||
self._client = None
|
self._client = None
|
||||||
self._text = None
|
self._text = None
|
||||||
self._file = None
|
self._file = None
|
||||||
|
@ -246,28 +232,25 @@ class Message(ChatGetter, SenderGetter, tlobject.TLObject):
|
||||||
self._linked_chat = None
|
self._linked_chat = None
|
||||||
|
|
||||||
sender_id = None
|
sender_id = None
|
||||||
if from_id is not None:
|
if self.from_id is not None:
|
||||||
sender_id = utils.get_peer_id(from_id)
|
sender_id = utils.get_peer_id(self.from_id)
|
||||||
elif peer_id:
|
elif self.peer_id:
|
||||||
# If the message comes from a Channel, let the sender be it
|
# If the message comes from a Channel, let the sender be it
|
||||||
# ...or...
|
# ...or...
|
||||||
# incoming messages in private conversations no longer have from_id
|
# incoming messages in private conversations no longer have from_id
|
||||||
# (layer 119+), but the sender can only be the chat we're in.
|
# (layer 119+), but the sender can only be the chat we're in.
|
||||||
if post or (not out and isinstance(peer_id, _tl.PeerUser)):
|
if self.post or (not self.out and isinstance(self.peer_id, _tl.PeerUser)):
|
||||||
sender_id = utils.get_peer_id(peer_id)
|
sender_id = utils.get_peer_id(self.peer_id)
|
||||||
|
|
||||||
# Note that these calls would reset the client
|
# Note that these calls would reset the client
|
||||||
ChatGetter.__init__(self, peer_id, broadcast=post)
|
ChatGetter.__init__(self, self.peer_id, broadcast=self.post)
|
||||||
SenderGetter.__init__(self, sender_id)
|
SenderGetter.__init__(self, sender_id)
|
||||||
|
|
||||||
self._forward = None
|
self._forward = None
|
||||||
|
|
||||||
def _finish_init(self, client, entities, input_chat):
|
@classmethod
|
||||||
"""
|
def _new(cls, client, message, entities, input_chat):
|
||||||
Finishes the initialization of this message by setting
|
self = cls(client, message)
|
||||||
the client that sent the message and making use of the
|
|
||||||
known entities.
|
|
||||||
"""
|
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
||||||
# Make messages sent to ourselves outgoing unless they're forwarded.
|
# Make messages sent to ourselves outgoing unless they're forwarded.
|
||||||
|
@ -314,6 +297,7 @@ class Message(ChatGetter, SenderGetter, tlobject.TLObject):
|
||||||
self._linked_chat = entities.get(utils.get_peer_id(
|
self._linked_chat = entities.get(utils.get_peer_id(
|
||||||
_tl.PeerChannel(self.replies.channel_id)))
|
_tl.PeerChannel(self.replies.channel_id)))
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
# endregion Initialization
|
# endregion Initialization
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user