From d5e4398acecbb95f6171967353c695f3207bf1e8 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Thu, 1 Oct 2020 12:22:55 +0200 Subject: [PATCH] Adapt the rest of the library to layer 119 --- telethon/client/dialogs.py | 2 +- telethon/client/messageparse.py | 4 +- telethon/client/messages.py | 60 ++++++-------------- telethon/entitycache.py | 4 +- telethon/events/album.py | 8 +-- telethon/events/chataction.py | 12 ++-- telethon/events/newmessage.py | 29 +++++----- telethon/statecache.py | 6 +- telethon/tl/custom/chatgetter.py | 2 +- telethon/tl/custom/conversation.py | 4 +- telethon/tl/custom/forward.py | 25 ++++---- telethon/tl/custom/message.py | 16 +++--- telethon_examples/replier.py | 2 +- telethon_generator/parsers/tlobject/tlarg.py | 2 +- 14 files changed, 78 insertions(+), 98 deletions(-) diff --git a/telethon/client/dialogs.py b/telethon/client/dialogs.py index adb23851..bced1cd7 100644 --- a/telethon/client/dialogs.py +++ b/telethon/client/dialogs.py @@ -60,7 +60,7 @@ class _DialogsIter(RequestIter): messages = {} for m in r.messages: m._finish_init(self.client, entities, None) - messages[_dialog_message_key(m.to_id, m.id)] = m + messages[_dialog_message_key(m.peer_id, m.id)] = m for d in r.dialogs: # We check the offset date here because Telegram may ignore it diff --git a/telethon/client/messageparse.py b/telethon/client/messageparse.py index 67860a4a..3a0fc268 100644 --- a/telethon/client/messageparse.py +++ b/telethon/client/messageparse.py @@ -157,7 +157,7 @@ class MessageParseMethods: elif (isinstance(update, types.UpdateEditChannelMessage) and utils.get_peer_id(request.peer) == - utils.get_peer_id(update.message.to_id)): + utils.get_peer_id(update.message.peer_id)): if request.id == update.message.id: update.message._finish_init(self, entities, input_chat) return update.message @@ -170,7 +170,7 @@ class MessageParseMethods: if request.media.poll.id == update.poll_id: m = types.Message( id=request.id, - to_id=utils.get_peer(request.peer), + peer_id=utils.get_peer(request.peer), media=types.MessageMediaPoll( poll=update.poll, results=update.results diff --git a/telethon/client/messages.py b/telethon/client/messages.py index 8237c380..dac8d621 100644 --- a/telethon/client/messages.py +++ b/telethon/client/messages.py @@ -1,6 +1,7 @@ import inspect import itertools import typing +import warnings from .. import helpers, utils, errors, hints from ..requestiter import RequestIter @@ -62,7 +63,7 @@ class _MessagesIter(RequestIter): from_user = None # Ignore from_user unless it's a user if from_user: - self.from_id = await self.client.get_peer_id(from_user) + self.from_id = utils.get_peer(from_user) else: self.from_id = None @@ -76,7 +77,9 @@ class _MessagesIter(RequestIter): if not self.entity: self.request = functions.messages.SearchGlobalRequest( q=search or '', - offset_rate=offset_date, + min_date=None, + max_date=offset_date, + offset_rate=None, offset_peer=types.InputPeerEmpty(), offset_id=offset_id, limit=1 @@ -270,7 +273,7 @@ class _IDsIter(RequestIter): else: r = await self.client(functions.messages.GetMessagesRequest(ids)) if self._entity: - from_id = await self.client.get_peer_id(self._entity) + from_id = utils.get_peer(self._entity) if isinstance(r, types.messages.MessagesNotModified): self.buffer.extend(None for _ in ids) @@ -289,7 +292,7 @@ class _IDsIter(RequestIter): # arbitrary chats. Validate these unless ``from_id is None``. for message in r.messages: if isinstance(message, types.MessageEmpty) or ( - from_id and message.chat_id != from_id): + from_id and message.peer_id != from_id): self.buffer.append(None) else: message._finish_init(self.client, entities, self._entity) @@ -753,7 +756,7 @@ class MessageMethods: if isinstance(result, types.UpdateShortSentMessage): message = types.Message( id=result.id, - to_id=utils.get_peer(entity), + peer_id=utils.get_peer(entity), message=message, date=result.date, out=result.out, @@ -805,15 +808,7 @@ class MessageMethods: this behaviour. as_album (`bool`, optional): - Whether several image messages should be forwarded as an - album (grouped) or not. The default behaviour is to treat - albums specially and send outgoing requests with - ``as_album=True`` only for the albums if message objects - are used. If IDs are used it will group by default. - - In short, the default should do what you expect, - `True` will group always (even converting separate - images into albums), and `False` will never group. + This flag no longer has any effect. schedule (`hints.DateLike`, optional): If set, the message(s) won't forward immediately, and @@ -846,6 +841,9 @@ class MessageMethods: # Forwarding as a copy await client.send_message(chat, message) """ + if as_album is not None: + warnings.warn('the as_album argument is deprecated and no longer has any effect') + single = not utils.is_list_like(messages) if single: messages = (messages,) @@ -858,44 +856,24 @@ class MessageMethods: else: from_peer_id = None - def _get_key(m): + def get_key(m): if isinstance(m, int): if from_peer_id is not None: - return from_peer_id, None + return from_peer_id raise ValueError('from_peer must be given if integer IDs are used') elif isinstance(m, types.Message): - return m.chat_id, m.grouped_id + return m.chat_id else: raise TypeError('Cannot forward messages of type {}'.format(type(m))) - # We want to group outgoing chunks differently if we are "smart" - # about sending as album. - # - # Why? We need separate requests for ``as_album=True/False``, so - # if we want that behaviour, when we group messages to create the - # chunks, we need to consider the grouped ID too. But if we don't - # care about that, we don't need to consider it for creating the - # chunks, so we can make less requests. - if as_album is None: - get_key = _get_key - else: - def get_key(m): - return _get_key(m)[0] # Ignore grouped_id - sent = [] - for chat_id, chunk in itertools.groupby(messages, key=get_key): + for _chat_id, chunk in itertools.groupby(messages, key=get_key): chunk = list(chunk) if isinstance(chunk[0], int): chat = from_peer - grouped = True if as_album is None else as_album else: chat = await chunk[0].get_input_chat() - if as_album is None: - grouped = any(m.grouped_id is not None for m in chunk) - else: - grouped = as_album - chunk = [m.id for m in chunk] req = functions.messages.ForwardMessagesRequest( @@ -903,10 +881,6 @@ class MessageMethods: id=chunk, to_peer=entity, silent=silent, - # Trying to send a single message as grouped will cause - # GROUPED_MEDIA_INVALID. If more than one message is forwarded - # (even without media...), this error goes away. - grouped=len(chunk) > 1 and grouped, schedule_date=schedule ) result = await self(req) @@ -1018,7 +992,7 @@ class MessageMethods: elif isinstance(entity, types.Message): text = message # Shift the parameters to the right message = entity - entity = entity.to_id + entity = entity.peer_id text, msg_entities = await self._parse_message_text(text, parse_mode) file_handle, media, image = await self._file_to_media(file, diff --git a/telethon/entitycache.py b/telethon/entitycache.py index db047107..84e17c3c 100644 --- a/telethon/entitycache.py +++ b/telethon/entitycache.py @@ -127,12 +127,12 @@ class EntityCache: if cid in has_message: x = update.message - y = getattr(x, 'to_id', None) # handle MessageEmpty + y = getattr(x, 'peer_id', None) # handle MessageEmpty if y and utils.get_peer_id(y) not in dct: return False y = getattr(x, 'from_id', None) - if y and y not in dct: + if y and utils.get_peer_id(y) not in dct: return False # We don't quite worry about entities anywhere else. diff --git a/telethon/events/album.py b/telethon/events/album.py index 473542bd..d415d51d 100644 --- a/telethon/events/album.py +++ b/telethon/events/album.py @@ -150,12 +150,12 @@ class Album(EventBuilder): """ def __init__(self, messages): message = messages[0] - if not message.out and isinstance(message.to_id, types.PeerUser): - # Incoming message (e.g. from a bot) has to_id=us, and + if not message.out and isinstance(message.peer_id, types.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 = types.PeerUser(message.from_id) + chat_peer = message.from_id else: - chat_peer = message.to_id + chat_peer = message.peer_id super().__init__(chat_peer=chat_peer, msg_id=message.id, broadcast=bool(message.post)) diff --git a/telethon/events/chataction.py b/telethon/events/chataction.py index b7143d4f..9a336e38 100644 --- a/telethon/events/chataction.py +++ b/telethon/events/chataction.py @@ -78,7 +78,7 @@ class ChatAction(EventBuilder): users=msg.from_id) elif isinstance(action, types.MessageActionChatAddUser): # If a user adds itself, it means they joined - added_by = ([msg.from_id] == action.users) or msg.from_id + added_by = ([utils.get_peer_id(msg.from_id)] == action.users) or msg.from_id return cls.Event(msg, added_by=added_by, users=action.users) @@ -108,12 +108,12 @@ class ChatAction(EventBuilder): return cls.Event(msg, users=msg.from_id, new_photo=True) - elif isinstance(action, types.MessageActionPinMessage) and msg.reply_to_msg_id: + elif isinstance(action, types.MessageActionPinMessage) and msg.reply_to: # Seems to not be reliable on unpins, but when pinning # we prefer this because we know who caused it. return cls.Event(msg, users=msg.from_id, - new_pin=msg.reply_to_msg_id) + new_pin=msg.reply_to.reply_to_msg_id) class Event(EventCommon): """ @@ -158,7 +158,7 @@ class ChatAction(EventBuilder): users=None, new_title=None, unpin=None): if isinstance(where, types.MessageService): self.action_message = where - where = where.to_id + where = where.peer_id else: self.action_message = None @@ -193,9 +193,9 @@ class ChatAction(EventBuilder): self.created = bool(created) if isinstance(users, list): - self._user_ids = users + self._user_ids = [utils.get_peer_id(u) for u in users] elif users: - self._user_ids = [users] + self._user_ids = [utils.get_peer_id(users)] else: self._user_ids = [] diff --git a/telethon/events/newmessage.py b/telethon/events/newmessage.py index b30a63c8..4629204e 100644 --- a/telethon/events/newmessage.py +++ b/telethon/events/newmessage.py @@ -1,6 +1,7 @@ import re from .common import EventBuilder, EventCommon, name_inner_event, _into_id_set +from .. import utils from ..tl import types @@ -106,15 +107,15 @@ class NewMessage(EventBuilder): media_unread=update.media_unread, silent=update.silent, id=update.id, - # Note that to_id/from_id complement each other in private + # Note that peer_id/from_id complement each other in private # messages, depending on whether the message was outgoing. - to_id=types.PeerUser(update.user_id if update.out else self_id), - from_id=self_id if update.out else update.user_id, + peer_id=types.PeerUser(update.user_id if update.out else self_id), + from_id=types.PeerUser(self_id if update.out else update.user_id), message=update.message, date=update.date, fwd_from=update.fwd_from, via_bot_id=update.via_bot_id, - reply_to_msg_id=update.reply_to_msg_id, + reply_to=update.reply_to, entities=update.entities )) elif isinstance(update, types.UpdateShortChatMessage): @@ -124,13 +125,13 @@ class NewMessage(EventBuilder): media_unread=update.media_unread, silent=update.silent, id=update.id, - from_id=update.from_id, - to_id=types.PeerChat(update.chat_id), + from_id=types.PeerUser(update.from_id), + peer_id=types.PeerChat(update.chat_id), message=update.message, date=update.date, fwd_from=update.fwd_from, via_bot_id=update.via_bot_id, - reply_to_msg_id=update.reply_to_msg_id, + reply_to=update.reply_to, entities=update.entities )) else: @@ -139,8 +140,8 @@ class NewMessage(EventBuilder): # Make messages sent to ourselves outgoing unless they're forwarded. # This makes it consistent with official client's appearance. ori = event.message - if isinstance(ori.to_id, types.PeerUser): - if ori.from_id == ori.to_id.user_id and not ori.fwd_from: + if isinstance(ori.peer_id, types.PeerUser): + if ori.from_id == ori.peer_id and not ori.fwd_from: event.message.out = True return event @@ -158,7 +159,7 @@ class NewMessage(EventBuilder): return if self.from_users is not None: - if event.message.from_id not in self.from_users: + if utils.get_peer_id(event.message.from_id) not in self.from_users: return if self.pattern: @@ -204,12 +205,12 @@ class NewMessage(EventBuilder): """ def __init__(self, message): self.__dict__['_init'] = False - if not message.out and isinstance(message.to_id, types.PeerUser): - # Incoming message (e.g. from a bot) has to_id=us, and + if not message.out and isinstance(message.peer_id, types.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 = types.PeerUser(message.from_id) + chat_peer = message.from_id else: - chat_peer = message.to_id + chat_peer = message.peer_id super().__init__(chat_peer=chat_peer, msg_id=message.id, broadcast=bool(message.post)) diff --git a/telethon/statecache.py b/telethon/statecache.py index fbb505fa..268a2bca 100644 --- a/telethon/statecache.py +++ b/telethon/statecache.py @@ -134,10 +134,10 @@ class StateCache: if cid in has_channel_id: return update.channel_id elif cid in has_message: - if update.message.to_id is None: - self._logger.info('Update has None to_id %s', update) + if update.message.peer_id is None: + self._logger.info('Update has None peer_id %s', update) else: - return update.message.to_id.channel_id + return update.message.peer_id.channel_id return None diff --git a/telethon/tl/custom/chatgetter.py b/telethon/tl/custom/chatgetter.py index ebf051d6..60f5c79e 100644 --- a/telethon/tl/custom/chatgetter.py +++ b/telethon/tl/custom/chatgetter.py @@ -95,7 +95,7 @@ class ChatGetter(abc.ABC): 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 + 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. diff --git a/telethon/tl/custom/conversation.py b/telethon/tl/custom/conversation.py index 79675b65..9bccb382 100644 --- a/telethon/tl/custom/conversation.py +++ b/telethon/tl/custom/conversation.py @@ -165,7 +165,7 @@ class Conversation(ChatGetter): """ return self._get_message( message, self._reply_indices, self._pending_replies, timeout, - lambda x, y: x.reply_to_msg_id == y + lambda x, y: x.reply_to and x.reply_to.reply_to_msg_id == y ) def _get_message( @@ -374,7 +374,7 @@ class Conversation(ChatGetter): del self._pending_responses[msg_id] for msg_id, future in list(self._pending_replies.items()): - if msg_id == response.reply_to_msg_id: + if response.reply_to and msg_id == response.reply_to.reply_to_msg_id: self._reply_indices[msg_id] = len(self._incoming) future.set_result(response) del self._pending_replies[msg_id] diff --git a/telethon/tl/custom/forward.py b/telethon/tl/custom/forward.py index 548f4e0b..c808de1d 100644 --- a/telethon/tl/custom/forward.py +++ b/telethon/tl/custom/forward.py @@ -1,6 +1,6 @@ from .chatgetter import ChatGetter from .sendergetter import SenderGetter -from ... import utils +from ... import utils, helpers from ...tl import types @@ -30,19 +30,24 @@ class Forward(ChatGetter, SenderGetter): self.__dict__.update(original.__dict__) self.original_fwd = original - sender, input_sender = utils._get_entity_pair( - original.from_id, entities, client._entity_cache) - - if not original.channel_id: - peer = chat = input_chat = None + sender_id = sender = input_sender = peer = chat = input_chat = None + if not original.from_id: + pass else: - peer = types.PeerChannel(original.channel_id) - chat, input_chat = utils._get_entity_pair( - utils.get_peer_id(peer), entities, client._entity_cache) + ty = helpers._entity_type(original.from_id) + if ty == helpers._EntityType.USER: + sender_id = utils.get_peer_id(original.from_id) + sender, input_sender = utils._get_entity_pair( + sender_id, entities, client._entity_cache) + + elif ty in (helpers._EntityType.CHAT, helpers._EntityType.CHANNEL): + peer = original.from_id + chat, input_chat = utils._get_entity_pair( + utils.get_peer_id(peer), entities, client._entity_cache) # This call resets the client ChatGetter.__init__(self, peer, chat=chat, input_chat=input_chat) - SenderGetter.__init__(self, original.from_id, sender=sender, input_sender=input_sender) + SenderGetter.__init__(self, sender_id, sender=sender, input_sender=input_sender) self._client = client # TODO We could reload the message diff --git a/telethon/tl/custom/message.py b/telethon/tl/custom/message.py index 76de7cf7..f4dcf39b 100644 --- a/telethon/tl/custom/message.py +++ b/telethon/tl/custom/message.py @@ -85,7 +85,7 @@ class Message(ChatGetter, SenderGetter, TLObject, abc.ABC): The peer who sent this message, which is either :tl:`PeerUser`, :tl:`PeerChat` or :tl:`PeerChannel`. - reply_to (`int`): + reply_to (:tl:`MessageReplyHeader`): The original reply header if this message is replying to another. fwd_from (:tl:`MessageFwdHeader`): @@ -210,15 +210,15 @@ class Message(ChatGetter, SenderGetter, TLObject, abc.ABC): self._action_entities = None if not out and isinstance(peer_id, types.PeerUser): - chat_peer = types.PeerUser(from_id) - if from_id == peer_id.user_id: + chat_peer = from_id + if from_id == peer_id: self.out = not self.fwd_from # Patch out in our chat else: chat_peer = peer_id # Note that these calls would reset the client ChatGetter.__init__(self, chat_peer, broadcast=post) - SenderGetter.__init__(self, from_id) + SenderGetter.__init__(self, utils.get_peer_id(from_id) if from_id else None) if post and not from_id and chat_peer: # If the message comes from a Channel, let the sender be it @@ -329,10 +329,10 @@ class Message(ChatGetter, SenderGetter, TLObject, abc.ABC): `True` if the message is a reply to some other message. Remember that you can access the ID of the message - this one is replying to through `reply_to_msg_id`, + this one is replying to through `reply_to.reply_to_msg_id`, and the `Message` object with `get_reply_message()`. """ - return bool(self.reply_to_msg_id) + return self.reply_to is not None @property def forward(self): @@ -647,7 +647,7 @@ class Message(ChatGetter, SenderGetter, TLObject, abc.ABC): The result will be cached after its first use. """ if self._reply_message is None and self._client: - if not self.reply_to_msg_id: + if not self.reply_to: return None # Bots cannot access other bots' messages by their ID. @@ -663,7 +663,7 @@ class Message(ChatGetter, SenderGetter, TLObject, abc.ABC): # directly by its ID. self._reply_message = await self._client.get_messages( self._input_chat if self.is_channel else None, - ids=self.reply_to_msg_id + ids=self.reply_to.reply_to_msg_id ) return self._reply_message diff --git a/telethon_examples/replier.py b/telethon_examples/replier.py index f11c39b4..e498bad9 100755 --- a/telethon_examples/replier.py +++ b/telethon_examples/replier.py @@ -76,7 +76,7 @@ async def handler(event): # If we sent the message, we are replying to someone, # and we said "save pic" in the message - if event.out and event.reply_to_msg_id and 'save pic' in event.raw_text: + if event.out and event.is_reply and 'save pic' in event.raw_text: reply_msg = await event.get_reply_message() replied_to_user = await reply_msg.get_input_sender() diff --git a/telethon_generator/parsers/tlobject/tlarg.py b/telethon_generator/parsers/tlobject/tlarg.py index b510f075..4a86fca9 100644 --- a/telethon_generator/parsers/tlobject/tlarg.py +++ b/telethon_generator/parsers/tlobject/tlarg.py @@ -156,7 +156,7 @@ class TLArg: # treated as a "date" object. Note that this is not a valid # Telegram object, but it's easier to work with if self.type == 'int' and ( - re.search(r'(\b|_)([dr]ate|until|since)(\b|_)', name) or + re.search(r'(\b|_)(date|until|since)(\b|_)', name) or name in ('expires', 'expires_at', 'was_online')): self.type = 'date'