From e200acbca8a10a8a5851b502788ceced6dd2b2c1 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Wed, 9 May 2018 09:46:07 +0200 Subject: [PATCH] Allow sending ordered MessageContainer --- telethon/network/mtproto_sender.py | 19 +++++++++++++++---- telethon/telegram_bare_client.py | 12 ++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/telethon/network/mtproto_sender.py b/telethon/network/mtproto_sender.py index c3209de9..b146a4e0 100644 --- a/telethon/network/mtproto_sender.py +++ b/telethon/network/mtproto_sender.py @@ -2,7 +2,6 @@ This module contains the class used to communicate with Telegram's servers encrypting every packet, and relies on a valid AuthKey in the used Session. """ -import gzip import logging from threading import Lock @@ -14,6 +13,7 @@ from ..errors import ( from ..extensions import BinaryReader from ..tl import TLMessage, MessageContainer, GzipPacked from ..tl.all_tlobjects import tlobjects +from ..tl.functions import InvokeAfterMsgRequest from ..tl.functions.auth import LogOutRequest from ..tl.types import ( MsgsAck, Pong, BadServerSalt, BadMsgNotification, FutureSalts, @@ -84,15 +84,26 @@ class MtProtoSender: # region Send and receive - def send(self, *requests): + def send(self, *requests, ordered=False): """ Sends the specified TLObject(s) (which must be requests), and acknowledging any message which needed confirmation. :param requests: the requests to be sent. + :param ordered: whether the requests should be invoked in the + order in which they appear or they can be executed + in arbitrary order in the server. """ - # Finally send our packed request(s) - messages = [TLMessage(self.session, r) for r in requests] + if ordered: + requests = iter(requests) + messages = [TLMessage(self.session, next(requests))] + for r in requests: + messages.append(TLMessage( + self.session, InvokeAfterMsgRequest(messages[-1].msg_id, r) + )) + else: + messages = [TLMessage(self.session, r) for r in requests] + self._pending_receive.update({m.msg_id: m for m in messages}) __log__.debug('Sending requests with IDs: %s', ', '.join( diff --git a/telethon/telegram_bare_client.py b/telethon/telegram_bare_client.py index e753dc06..c343dbe4 100644 --- a/telethon/telegram_bare_client.py +++ b/telethon/telegram_bare_client.py @@ -429,11 +429,15 @@ class TelegramBareClient: # region Invoking Telegram requests - def __call__(self, *requests, retries=5): + def __call__(self, *requests, retries=5, ordered=False): """Invokes (sends) a MTProtoRequest and returns (receives) its result. The invoke will be retried up to 'retries' times before raising RuntimeError(). + + If more than one request is given and ordered is True, then the + requests will be invoked sequentially in the server (useful for + bursts of requests that need to be ordered). """ if not all(isinstance(x, TLObject) and x.content_related for x in requests): @@ -458,7 +462,7 @@ class TelegramBareClient: not self._idling.is_set() or self._reconnect_lock.locked() for retry in range(retries): - result = self._invoke(call_receive, *requests) + result = self._invoke(call_receive, *requests, ordered=ordered) if result is not None: return result @@ -481,7 +485,7 @@ class TelegramBareClient: # Let people use client.invoke(SomeRequest()) instead client(...) invoke = __call__ - def _invoke(self, call_receive, *requests): + def _invoke(self, call_receive, *requests, ordered=False): try: # Ensure that we start with no previous errors (i.e. resending) for x in requests: @@ -506,7 +510,7 @@ class TelegramBareClient: self._wrap_init_connection(GetConfigRequest()) ) - self._sender.send(*requests) + self._sender.send(*requests, ordered=ordered) if not call_receive: # TODO This will be slightly troublesome if we allow