mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-08-10 10:49:39 +00:00
Begin unification of event builders and events
This commit is contained in:
@@ -2,7 +2,7 @@ import asyncio
|
||||
import time
|
||||
import weakref
|
||||
|
||||
from .common import EventBuilder, EventCommon, name_inner_event
|
||||
from .base import EventBuilder
|
||||
from .._misc import utils
|
||||
from .. import _tl
|
||||
from ..types import _custom
|
||||
@@ -64,13 +64,16 @@ class AlbumHack:
|
||||
await asyncio.sleep(diff)
|
||||
|
||||
|
||||
@name_inner_event
|
||||
class Album(EventBuilder):
|
||||
class Album(EventBuilder, _custom.chatgetter.ChatGetter, _custom.sendergetter.SenderGetter):
|
||||
"""
|
||||
Occurs whenever you receive an album. This event only exists
|
||||
to ease dealing with an unknown amount of messages that belong
|
||||
to the same album.
|
||||
|
||||
Members:
|
||||
messages (Sequence[`Message <telethon.tl._custom.message.Message>`]):
|
||||
The list of messages belonging to the same album.
|
||||
|
||||
Example
|
||||
.. code-block:: python
|
||||
|
||||
@@ -91,12 +94,20 @@ class Album(EventBuilder):
|
||||
await event.messages[4].reply('Cool!')
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, chats=None, *, blacklist_chats=False, func=None):
|
||||
super().__init__(chats, blacklist_chats=blacklist_chats, func=func)
|
||||
def __init__(self, messages):
|
||||
message = messages[0]
|
||||
if not message.out and isinstance(message.peer_id, _tl.PeerUser):
|
||||
# Incoming message (e.g. from a bot) has peer_id=us, and
|
||||
# from_id=bot (the actual "chat" from a user's perspective).
|
||||
chat_peer = message.from_id
|
||||
else:
|
||||
chat_peer = message.peer_id
|
||||
|
||||
@classmethod
|
||||
def build(cls, update, others=None, self_id=None, *todo, **todo2):
|
||||
_custom.chatgetter.ChatGetter.__init__(self, chat_peer=chat_peer, broadcast=bool(message.post))
|
||||
_custom.sendergetter.SenderGetter.__init__(self, message.sender_id)
|
||||
self.messages = messages
|
||||
|
||||
def _build(cls, update, others=None, self_id=None, *todo, **todo2):
|
||||
if not others:
|
||||
return # We only care about albums which come inside the same Updates
|
||||
|
||||
@@ -135,216 +146,188 @@ class Album(EventBuilder):
|
||||
and u.message.grouped_id == group)
|
||||
])
|
||||
|
||||
def filter(self, event):
|
||||
# Albums with less than two messages require a few hacks to work.
|
||||
if len(event.messages) > 1:
|
||||
return super().filter(event)
|
||||
def _set_client(self, client):
|
||||
super()._set_client(client)
|
||||
self._sender, self._input_sender = utils._get_entity_pair(self.sender_id, self._entities)
|
||||
|
||||
class Event(EventCommon, _custom.sendergetter.SenderGetter):
|
||||
"""
|
||||
Represents the event of a new album.
|
||||
self.messages = [
|
||||
_custom.Message._new(client, m, self._entities, None)
|
||||
for m in self.messages
|
||||
]
|
||||
|
||||
Members:
|
||||
messages (Sequence[`Message <telethon.tl._custom.message.Message>`]):
|
||||
The list of messages belonging to the same album.
|
||||
"""
|
||||
def __init__(self, messages):
|
||||
message = messages[0]
|
||||
if not message.out and isinstance(message.peer_id, _tl.PeerUser):
|
||||
# Incoming message (e.g. from a bot) has peer_id=us, and
|
||||
# from_id=bot (the actual "chat" from a user's perspective).
|
||||
chat_peer = message.from_id
|
||||
if len(self.messages) == 1:
|
||||
# This will require hacks to be a proper album event
|
||||
hack = client._albums.get(self.grouped_id)
|
||||
if hack is None:
|
||||
client._albums[self.grouped_id] = AlbumHack(client, self)
|
||||
else:
|
||||
chat_peer = message.peer_id
|
||||
hack.extend(self.messages)
|
||||
|
||||
super().__init__(chat_peer=chat_peer,
|
||||
msg_id=message.id, broadcast=bool(message.post))
|
||||
@property
|
||||
def grouped_id(self):
|
||||
"""
|
||||
The shared ``grouped_id`` between all the messages.
|
||||
"""
|
||||
return self.messages[0].grouped_id
|
||||
|
||||
_custom.sendergetter.SenderGetter.__init__(self, message.sender_id)
|
||||
self.messages = messages
|
||||
@property
|
||||
def text(self):
|
||||
"""
|
||||
The message text of the first photo with a caption,
|
||||
formatted using the client's default parse mode.
|
||||
"""
|
||||
return next((m.text for m in self.messages if m.text), '')
|
||||
|
||||
def _set_client(self, client):
|
||||
super()._set_client(client)
|
||||
self._sender, self._input_sender = utils._get_entity_pair(self.sender_id, self._entities)
|
||||
@property
|
||||
def raw_text(self):
|
||||
"""
|
||||
The raw message text of the first photo
|
||||
with a caption, ignoring any formatting.
|
||||
"""
|
||||
return next((m.raw_text for m in self.messages if m.raw_text), '')
|
||||
|
||||
self.messages = [
|
||||
_custom.Message._new(client, m, self._entities, None)
|
||||
for m in self.messages
|
||||
]
|
||||
@property
|
||||
def is_reply(self):
|
||||
"""
|
||||
`True` if the album is a reply to some other message.
|
||||
|
||||
if len(self.messages) == 1:
|
||||
# This will require hacks to be a proper album event
|
||||
hack = client._albums.get(self.grouped_id)
|
||||
if hack is None:
|
||||
client._albums[self.grouped_id] = AlbumHack(client, self)
|
||||
else:
|
||||
hack.extend(self.messages)
|
||||
Remember that you can access the ID of the message
|
||||
this one is replying to through `reply_to_msg_id`,
|
||||
and the `Message` object with `get_reply_message()`.
|
||||
"""
|
||||
# Each individual message in an album all reply to the same message
|
||||
return self.messages[0].is_reply
|
||||
|
||||
@property
|
||||
def grouped_id(self):
|
||||
"""
|
||||
The shared ``grouped_id`` between all the messages.
|
||||
"""
|
||||
return self.messages[0].grouped_id
|
||||
@property
|
||||
def forward(self):
|
||||
"""
|
||||
The `Forward <telethon.tl._custom.forward.Forward>`
|
||||
information for the first message in the album if it was forwarded.
|
||||
"""
|
||||
# Each individual message in an album all reply to the same message
|
||||
return self.messages[0].forward
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
"""
|
||||
The message text of the first photo with a caption,
|
||||
formatted using the client's default parse mode.
|
||||
"""
|
||||
return next((m.text for m in self.messages if m.text), '')
|
||||
# endregion Public Properties
|
||||
|
||||
@property
|
||||
def raw_text(self):
|
||||
"""
|
||||
The raw message text of the first photo
|
||||
with a caption, ignoring any formatting.
|
||||
"""
|
||||
return next((m.raw_text for m in self.messages if m.raw_text), '')
|
||||
# region Public Methods
|
||||
|
||||
@property
|
||||
def is_reply(self):
|
||||
"""
|
||||
`True` if the album is a reply to some other message.
|
||||
async def get_reply_message(self):
|
||||
"""
|
||||
The `Message <telethon.tl._custom.message.Message>`
|
||||
that this album is replying to, or `None`.
|
||||
|
||||
Remember that you can access the ID of the message
|
||||
this one is replying to through `reply_to_msg_id`,
|
||||
and the `Message` object with `get_reply_message()`.
|
||||
"""
|
||||
# Each individual message in an album all reply to the same message
|
||||
return self.messages[0].is_reply
|
||||
The result will be cached after its first use.
|
||||
"""
|
||||
return await self.messages[0].get_reply_message()
|
||||
|
||||
@property
|
||||
def forward(self):
|
||||
"""
|
||||
The `Forward <telethon.tl._custom.forward.Forward>`
|
||||
information for the first message in the album if it was forwarded.
|
||||
"""
|
||||
# Each individual message in an album all reply to the same message
|
||||
return self.messages[0].forward
|
||||
async def respond(self, *args, **kwargs):
|
||||
"""
|
||||
Responds to the album (not as a reply). Shorthand for
|
||||
`telethon.client.messages.MessageMethods.send_message`
|
||||
with ``entity`` already set.
|
||||
"""
|
||||
return await self.messages[0].respond(*args, **kwargs)
|
||||
|
||||
# endregion Public Properties
|
||||
async def reply(self, *args, **kwargs):
|
||||
"""
|
||||
Replies to the first photo in the album (as a reply). Shorthand
|
||||
for `telethon.client.messages.MessageMethods.send_message`
|
||||
with both ``entity`` and ``reply_to`` already set.
|
||||
"""
|
||||
return await self.messages[0].reply(*args, **kwargs)
|
||||
|
||||
# region Public Methods
|
||||
async def forward_to(self, *args, **kwargs):
|
||||
"""
|
||||
Forwards the entire album. Shorthand for
|
||||
`telethon.client.messages.MessageMethods.forward_messages`
|
||||
with both ``messages`` and ``from_peer`` already set.
|
||||
"""
|
||||
if self._client:
|
||||
kwargs['messages'] = self.messages
|
||||
kwargs['from_peer'] = await self.get_input_chat()
|
||||
return await self._client.forward_messages(*args, **kwargs)
|
||||
|
||||
async def get_reply_message(self):
|
||||
"""
|
||||
The `Message <telethon.tl._custom.message.Message>`
|
||||
that this album is replying to, or `None`.
|
||||
async def edit(self, *args, **kwargs):
|
||||
"""
|
||||
Edits the first caption or the message, or the first messages'
|
||||
caption if no caption is set, iff it's outgoing. Shorthand for
|
||||
`telethon.client.messages.MessageMethods.edit_message`
|
||||
with both ``entity`` and ``message`` already set.
|
||||
|
||||
The result will be cached after its first use.
|
||||
"""
|
||||
return await self.messages[0].get_reply_message()
|
||||
Returns `None` if the message was incoming,
|
||||
or the edited `Message` otherwise.
|
||||
|
||||
async def respond(self, *args, **kwargs):
|
||||
"""
|
||||
Responds to the album (not as a reply). Shorthand for
|
||||
`telethon.client.messages.MessageMethods.send_message`
|
||||
with ``entity`` already set.
|
||||
"""
|
||||
return await self.messages[0].respond(*args, **kwargs)
|
||||
.. note::
|
||||
|
||||
async def reply(self, *args, **kwargs):
|
||||
"""
|
||||
Replies to the first photo in the album (as a reply). Shorthand
|
||||
for `telethon.client.messages.MessageMethods.send_message`
|
||||
with both ``entity`` and ``reply_to`` already set.
|
||||
"""
|
||||
return await self.messages[0].reply(*args, **kwargs)
|
||||
This is different from `client.edit_message
|
||||
<telethon.client.messages.MessageMethods.edit_message>`
|
||||
and **will respect** the previous state of the message.
|
||||
For example, if the message didn't have a link preview,
|
||||
the edit won't add one by default, and you should force
|
||||
it by setting it to `True` if you want it.
|
||||
|
||||
async def forward_to(self, *args, **kwargs):
|
||||
"""
|
||||
Forwards the entire album. Shorthand for
|
||||
`telethon.client.messages.MessageMethods.forward_messages`
|
||||
with both ``messages`` and ``from_peer`` already set.
|
||||
"""
|
||||
if self._client:
|
||||
kwargs['messages'] = self.messages
|
||||
kwargs['from_peer'] = await self.get_input_chat()
|
||||
return await self._client.forward_messages(*args, **kwargs)
|
||||
This is generally the most desired and convenient behaviour,
|
||||
and will work for link previews and message buttons.
|
||||
"""
|
||||
for msg in self.messages:
|
||||
if msg.raw_text:
|
||||
return await msg.edit(*args, **kwargs)
|
||||
|
||||
async def edit(self, *args, **kwargs):
|
||||
"""
|
||||
Edits the first caption or the message, or the first messages'
|
||||
caption if no caption is set, iff it's outgoing. Shorthand for
|
||||
`telethon.client.messages.MessageMethods.edit_message`
|
||||
with both ``entity`` and ``message`` already set.
|
||||
return await self.messages[0].edit(*args, **kwargs)
|
||||
|
||||
Returns `None` if the message was incoming,
|
||||
or the edited `Message` otherwise.
|
||||
async def delete(self, *args, **kwargs):
|
||||
"""
|
||||
Deletes the entire album. You're responsible for checking whether
|
||||
you have the permission to do so, or to except the error otherwise.
|
||||
Shorthand for
|
||||
`telethon.client.messages.MessageMethods.delete_messages` with
|
||||
``entity`` and ``message_ids`` already set.
|
||||
"""
|
||||
if self._client:
|
||||
return await self._client.delete_messages(
|
||||
await self.get_input_chat(), self.messages,
|
||||
*args, **kwargs
|
||||
)
|
||||
|
||||
.. note::
|
||||
async def mark_read(self):
|
||||
"""
|
||||
Marks the entire album as read. Shorthand for
|
||||
`client.mark_read()
|
||||
<telethon.client.messages.MessageMethods.mark_read>`
|
||||
with both ``entity`` and ``message`` already set.
|
||||
"""
|
||||
if self._client:
|
||||
await self._client.mark_read(
|
||||
await self.get_input_chat(), max_id=self.messages[-1].id)
|
||||
|
||||
This is different from `client.edit_message
|
||||
<telethon.client.messages.MessageMethods.edit_message>`
|
||||
and **will respect** the previous state of the message.
|
||||
For example, if the message didn't have a link preview,
|
||||
the edit won't add one by default, and you should force
|
||||
it by setting it to `True` if you want it.
|
||||
async def pin(self, *, notify=False):
|
||||
"""
|
||||
Pins the first photo in the album. Shorthand for
|
||||
`telethon.client.messages.MessageMethods.pin_message`
|
||||
with both ``entity`` and ``message`` already set.
|
||||
"""
|
||||
return await self.messages[0].pin(notify=notify)
|
||||
|
||||
This is generally the most desired and convenient behaviour,
|
||||
and will work for link previews and message buttons.
|
||||
"""
|
||||
for msg in self.messages:
|
||||
if msg.raw_text:
|
||||
return await msg.edit(*args, **kwargs)
|
||||
def __len__(self):
|
||||
"""
|
||||
Return the amount of messages in the album.
|
||||
|
||||
return await self.messages[0].edit(*args, **kwargs)
|
||||
Equivalent to ``len(self.messages)``.
|
||||
"""
|
||||
return len(self.messages)
|
||||
|
||||
async def delete(self, *args, **kwargs):
|
||||
"""
|
||||
Deletes the entire album. You're responsible for checking whether
|
||||
you have the permission to do so, or to except the error otherwise.
|
||||
Shorthand for
|
||||
`telethon.client.messages.MessageMethods.delete_messages` with
|
||||
``entity`` and ``message_ids`` already set.
|
||||
"""
|
||||
if self._client:
|
||||
return await self._client.delete_messages(
|
||||
await self.get_input_chat(), self.messages,
|
||||
*args, **kwargs
|
||||
)
|
||||
def __iter__(self):
|
||||
"""
|
||||
Iterate over the messages in the album.
|
||||
|
||||
async def mark_read(self):
|
||||
"""
|
||||
Marks the entire album as read. Shorthand for
|
||||
`client.mark_read()
|
||||
<telethon.client.messages.MessageMethods.mark_read>`
|
||||
with both ``entity`` and ``message`` already set.
|
||||
"""
|
||||
if self._client:
|
||||
await self._client.mark_read(
|
||||
await self.get_input_chat(), max_id=self.messages[-1].id)
|
||||
Equivalent to ``iter(self.messages)``.
|
||||
"""
|
||||
return iter(self.messages)
|
||||
|
||||
async def pin(self, *, notify=False):
|
||||
"""
|
||||
Pins the first photo in the album. Shorthand for
|
||||
`telethon.client.messages.MessageMethods.pin_message`
|
||||
with both ``entity`` and ``message`` already set.
|
||||
"""
|
||||
return await self.messages[0].pin(notify=notify)
|
||||
def __getitem__(self, n):
|
||||
"""
|
||||
Access the n'th message in the album.
|
||||
|
||||
def __len__(self):
|
||||
"""
|
||||
Return the amount of messages in the album.
|
||||
|
||||
Equivalent to ``len(self.messages)``.
|
||||
"""
|
||||
return len(self.messages)
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
Iterate over the messages in the album.
|
||||
|
||||
Equivalent to ``iter(self.messages)``.
|
||||
"""
|
||||
return iter(self.messages)
|
||||
|
||||
def __getitem__(self, n):
|
||||
"""
|
||||
Access the n'th message in the album.
|
||||
|
||||
Equivalent to ``event.messages[n]``.
|
||||
"""
|
||||
return self.messages[n]
|
||||
Equivalent to ``event.messages[n]``.
|
||||
"""
|
||||
return self.messages[n]
|
||||
|
Reference in New Issue
Block a user