diff --git a/network/mtproto_sender.py b/network/mtproto_sender.py index a9b0d9c3..528c3247 100755 --- a/network/mtproto_sender.py +++ b/network/mtproto_sender.py @@ -36,8 +36,22 @@ class MtProtoSender: def add_update_handler(self, handler): """Adds an update handler (a method with one argument, the received TLObject) that is fired when there are updates available""" + + first_handler = not self.on_update_handlers self.on_update_handlers.append(handler) + # If this is the first added handler, + # we must start the thread to receive updates + if first_handler: + self.set_listen_for_updates(enabled=True) + + def remove_update_handler(self, handler): + self.on_update_handlers.remove(handler) + + # If there are no more update handlers, stop the thread + if not self.on_update_handlers: + self.set_listen_for_updates(False) + def generate_sequence(self, confirmed): """Generates the next sequence number, based on whether it was confirmed yet or not""" diff --git a/network/tcp_client.py b/network/tcp_client.py index 1beda5a5..571163ab 100755 --- a/network/tcp_client.py +++ b/network/tcp_client.py @@ -45,7 +45,12 @@ class TcpClient: self.cancelled = False with BinaryWriter() as writer: - while writer.written_count < buffer_size and not self.cancelled: + while writer.written_count < buffer_size: + # Only do cancel if no data was read yet + # Otherwise, carry on reading and finish + if self.cancelled and writer.written_count == 0: + raise ReadCancelledError() + try: # When receiving from the socket, we may not receive all the data at once # This is why we need to keep checking to make sure that we receive it all @@ -57,20 +62,10 @@ class TcpClient: # There was no data available for us to read. Sleep a bit time.sleep(self.delay) - # If the operation was cancelled *but* data was read, - # this will result on data loss so raise an exception - # TODO this could be solved by using an internal FIFO buffer (first in, first out) - if self.cancelled: - if writer.written_count == 0: - raise ReadCancelledError() - else: - raise NotImplementedError('The read operation was cancelled when some data ' - 'was already read. This has not yet implemented ' - 'an internal buffer, so cannot continue.') - # If everything went fine, return the read bytes return writer.get_bytes() def cancel_read(self): - """Cancels the read operation raising a ReadCancelledError""" + """Cancels the read operation IF it hasn't yet + started, raising a ReadCancelledError""" self.cancelled = True diff --git a/parser/markdown_parser.py b/parser/markdown_parser.py index 8e7b8294..e1e75ff4 100644 --- a/parser/markdown_parser.py +++ b/parser/markdown_parser.py @@ -123,9 +123,8 @@ def parse_message_entities(msg): # Second case, both inside: so*me_th*in_g. # In this case, the current entity length is decreased by one, # and all the subentities offset and length decrease 1 - elif (subentity.offset > entity.offset and - subentity.offset < entity.offset + entity.length and - subentity.offset + subentity.length > entity.offset + entity.length): + elif (entity.offset < subentity.offset < entity.offset + entity.length and + subentity.offset + subentity.length > entity.offset + entity.length): entity.length -= 1 subentity.offset -= 1 subentity.length -= 1 diff --git a/tl/telegram_client.py b/tl/telegram_client.py index 5c2c9f16..55d76a4a 100644 --- a/tl/telegram_client.py +++ b/tl/telegram_client.py @@ -18,9 +18,6 @@ from tl.functions.help import GetConfigRequest from tl.functions.auth import SendCodeRequest, SignInRequest from tl.functions.messages import GetDialogsRequest, GetHistoryRequest, SendMessageRequest -# For working with updates -from tl.types import UpdateShortMessage - class TelegramClient: @@ -59,7 +56,6 @@ class TelegramClient: self.session.save() self.sender = MtProtoSender(self.transport, self.session) - self.sender.add_update_handler(self.on_update) # Now it's time to send an InitConnectionRequest # This must always be invoked with the layer we'll be using @@ -72,10 +68,6 @@ class TelegramClient: result = self.invoke(InvokeWithLayerRequest(layer=self.layer, query=query)) - # Only listen for updates if we're authorized - if self.is_user_authorized(): - self.sender.set_listen_for_updates(True) - # We're only interested in the DC options, # although many other options are available! self.dc_options = result.dc_options @@ -260,21 +252,18 @@ class TelegramClient: return InputPeerChannel(channel.id, channel.access_hash) except StopIteration: - pass - - return None + return None # endregion # region Updates handling - def on_update(self, tlobject): - """This method is fired when there are updates from Telegram. - Add your own implementation below, or simply override it!""" + def add_update_handler(self, handler): + """Adds an update handler (a function which takes a TLObject, + an update, as its parameter) and listens for updates""" + self.sender.add_update_handler(handler) - # Only show incoming messages - if type(tlobject) is UpdateShortMessage: - if not tlobject.out: - print('> User with ID {} said "{}"'.format(tlobject.user_id, tlobject.message)) + def remove_update_handler(self, handler): + self.sender.remove_update_handler(handler) # endregion