diff --git a/parser/tlobject.py b/parser/tlobject.py index 970bb1cd..feb8d928 100755 --- a/parser/tlobject.py +++ b/parser/tlobject.py @@ -130,8 +130,8 @@ class TLArg: self.is_generic = False else: self.flag_indicator = False - self.type = type.lstrip('!') # Strip the exclamation mark always to have only the name self.is_generic = type.startswith('!') + self.type = type.lstrip('!') # Strip the exclamation mark always to have only the name # The type may be a flag (flags.IDX?REAL_TYPE) # Note that «flags» is NOT the flags name; this is determined by a previous argument @@ -148,6 +148,12 @@ class TLArg: self.is_vector = True self.type = vector_match.group(1) # Update the type to match the one inside the vector + # The name may contain "date" in it, if this is the case and the type is "int", + # we can safely assume that this should be treated as a "date" object. + # Note that this is not a valid Telegram object, but it's easier to work with + if re.search(r'(\b|_)date\b', name) and self.type == 'int': + self.type = 'date' + self.generic_definition = generic_definition def __str__(self): diff --git a/tl/telegram_client.py b/tl/telegram_client.py index 9088b544..5c2c9f16 100644 --- a/tl/telegram_client.py +++ b/tl/telegram_client.py @@ -148,10 +148,10 @@ class TelegramClient: def get_dialogs(self, count=10, offset_date=None, offset_id=0, offset_peer=InputPeerEmpty()): """Returns a tuple of lists ([dialogs], [displays], [input_peers]) with 'count' items each""" - r = self.invoke(GetDialogsRequest(offset_date=TelegramClient.get_tg_date(offset_date), - offset_id=offset_id, - offset_peer=offset_peer, - limit=count)) + r = self.invoke(GetDialogsRequest(offset_date=offset_date, + offset_id=offset_id, + offset_peer=offset_peer, + limit=count)) return (r.dialogs, [self.find_display_name(d.peer, r.users, r.chats) for d in r.dialogs], @@ -188,7 +188,7 @@ class TelegramClient: """ result = self.invoke(GetHistoryRequest(input_peer, limit=limit, - offset_date=self.get_tg_date(offset_date), + offset_date=offset_date, offset_id=offset_id, max_id=max_id, min_id=min_id, @@ -198,7 +198,7 @@ class TelegramClient: # simply a messages TLObject. In the later case, no "count" attribute is specified: # the total messages count is retrieved by counting all the retrieved messages total_messages = getattr(result, 'count', len(result.messages)) - + return (total_messages, result.messages, [usr # Create a list with the users... @@ -220,11 +220,6 @@ class TelegramClient: # region Utilities - @staticmethod - def get_tg_date(datetime): - """Parses a datetime Python object to Telegram's required integer Unix timestamp""" - return 0 if datetime is None else int(datetime.timestamp()) - @staticmethod def find_display_name(peer, users, chats): """Searches the display name for peer in both users and chats. diff --git a/tl_generator.py b/tl_generator.py index fee29d00..17aa839b 100755 --- a/tl_generator.py +++ b/tl_generator.py @@ -284,6 +284,9 @@ def write_onsend_code(builder, arg, args, name=None): elif 'bytes' == arg.type: builder.writeln('writer.write({})'.format(name)) + elif 'date' == arg.type: # Custom format + builder.writeln('writer.tgwrite_date({})'.format(name)) + else: # Else it may be a custom type builder.writeln('{}.on_send(writer)'.format(name)) @@ -364,6 +367,9 @@ def write_onresponse_code(builder, arg, args, name=None): elif 'bytes' == arg.type: builder.writeln('{} = reader.tgread_bytes()'.format(name)) + elif 'date' == arg.type: # Custom format + builder.writeln('{} = reader.tgread_date()'.format(name)) + else: # Else it may be a custom type builder.writeln('{} = reader.tgread_object()'.format(name)) diff --git a/utils/binary_reader.py b/utils/binary_reader.py index b267dc13..0a5c9383 100755 --- a/utils/binary_reader.py +++ b/utils/binary_reader.py @@ -1,3 +1,4 @@ +from datetime import datetime from io import BytesIO, BufferedReader from tl.all_tlobjects import tlobjects from struct import unpack @@ -95,6 +96,11 @@ class BinaryReader: else: raise ValueError('Invalid boolean code {}'.format(hex(value))) + def tgread_date(self): + """Reads and converts Unix time (used by Telegram) into a Python datetime object""" + value = self.read_int() + return None if value == 0 else datetime.fromtimestamp(value) + def tgread_object(self): """Reads a Telegram object""" constructor_id = self.read_int(signed=False) diff --git a/utils/binary_writer.py b/utils/binary_writer.py index db2aa35c..b448750a 100755 --- a/utils/binary_writer.py +++ b/utils/binary_writer.py @@ -83,12 +83,17 @@ class BinaryWriter: def tgwrite_string(self, string): """Write a string by using Telegram guidelines""" - return self.tgwrite_bytes(string.encode('utf-8')) + self.tgwrite_bytes(string.encode('utf-8')) def tgwrite_bool(self, boolean): """Write a boolean value by using Telegram guidelines""" # boolTrue boolFalse - return self.write_int(0x997275b5 if boolean else 0xbc799737, signed=False) + self.write_int(0x997275b5 if boolean else 0xbc799737, signed=False) + + def tgwrite_date(self, datetime): + """Converts a Python datetime object into Unix time (used by Telegram) and writes it""" + value = 0 if datetime is None else int(datetime.timestamp()) + self.write_int(value) # endregion