diff --git a/telethon/telegram_bare_client.py b/telethon/telegram_bare_client.py index 9684a034..ba6ae374 100644 --- a/telethon/telegram_bare_client.py +++ b/telethon/telegram_bare_client.py @@ -7,7 +7,7 @@ from signal import signal, SIGINT, SIGTERM, SIGABRT from threading import Lock from time import sleep -from . import version +from . import version, utils from .crypto import rsa from .errors import ( RPCError, BrokenAuthKeyError, ServerError, FloodWaitError, @@ -420,6 +420,9 @@ class TelegramBareClient: if self._background_error: raise self._background_error + for request in requests: + request.resolve(self, utils) + # For logging purposes if len(requests) == 1: which = type(requests[0]).__name__ diff --git a/telethon/tl/tlobject.py b/telethon/tl/tlobject.py index ad930f9c..7c86a24a 100644 --- a/telethon/tl/tlobject.py +++ b/telethon/tl/tlobject.py @@ -144,6 +144,9 @@ class TLObject: raise TypeError('Cannot interpret "{}" as a date.'.format(dt)) # These should be overrode + def resolve(self, client, utils): + pass + def to_dict(self, recursive=True): return {} diff --git a/telethon_generator/tl_generator.py b/telethon_generator/tl_generator.py index 3116003a..39bad15f 100644 --- a/telethon_generator/tl_generator.py +++ b/telethon_generator/tl_generator.py @@ -10,6 +10,15 @@ AUTO_GEN_NOTICE = \ '"""File generated by TLObjects\' generator. All changes will be ERASED"""' +AUTO_CASTS = { + 'InputPeer': 'utils.get_input_peer(client.get_input_entity({}))', + 'InputChannel': 'utils.get_input_channel(client.get_input_entity({}))', + 'InputUser': 'utils.get_input_user(client.get_input_entity({}))', + 'InputMedia': 'utils.get_input_media({})', + 'InputPhoto': 'utils.get_input_photo({})' +} + + class TLGenerator: def __init__(self, output_dir): self.output_dir = output_dir @@ -257,10 +266,45 @@ class TLGenerator: builder.writeln() for arg in args: - TLGenerator._write_self_assigns(builder, tlobject, arg, args) + if not arg.can_be_inferred: + builder.writeln('self.{0} = {0}'.format(arg.name)) + continue + + # Currently the only argument that can be + # inferred are those called 'random_id' + if arg.name == 'random_id': + # Endianness doesn't really matter, and 'big' is shorter + code = "int.from_bytes(os.urandom({}), 'big', signed=True)" \ + .format(8 if arg.type == 'long' else 4) + + if arg.is_vector: + # Currently for the case of "messages.forwardMessages" + # Ensure we can infer the length from id:Vector<> + if not next( + a for a in args if a.name == 'id').is_vector: + raise ValueError( + 'Cannot infer list of random ids for ', tlobject + ) + code = '[{} for _ in range(len(id))]'.format(code) + + builder.writeln( + "self.random_id = random_id if random_id " + "is not None else {}".format(code) + ) + else: + raise ValueError('Cannot infer a value for ', arg) builder.end_block() + # Write the resolve(self, client, utils) method + if any(arg.type in AUTO_CASTS for arg in args): + builder.writeln('def resolve(self, client, utils):') + for arg in args: + ac = AUTO_CASTS.get(arg.type, None) + if ac: + TLGenerator._write_self_assign(builder, arg, ac) + builder.end_block() + # Write the to_dict(self) method builder.writeln('def to_dict(self, recursive=True):') if args: @@ -370,59 +414,17 @@ class TLGenerator: # builder.end_block() # No need to end the last block @staticmethod - def _write_self_assigns(builder, tlobject, arg, args): - if arg.can_be_inferred: - # Currently the only argument that can be - # inferred are those called 'random_id' - if arg.name == 'random_id': - # Endianness doesn't really matter, and 'big' is shorter - code = "int.from_bytes(os.urandom({}), 'big', signed=True)"\ - .format(8 if arg.type == 'long' else 4) - - if arg.is_vector: - # Currently for the case of "messages.forwardMessages" - # Ensure we can infer the length from id:Vector<> - if not next(a for a in args if a.name == 'id').is_vector: - raise ValueError( - 'Cannot infer list of random ids for ', tlobject - ) - code = '[{} for _ in range(len(id))]'.format(code) - - builder.writeln( - "self.random_id = random_id if random_id " - "is not None else {}".format(code) - ) - else: - raise ValueError('Cannot infer a value for ', arg) - - # Well-known cases, auto-cast it to the right type - elif arg.type == 'InputPeer' and tlobject.is_function: - TLGenerator.write_get_input(builder, arg, 'get_input_peer') - elif arg.type == 'InputChannel' and tlobject.is_function: - TLGenerator.write_get_input(builder, arg, 'get_input_channel') - elif arg.type == 'InputUser' and tlobject.is_function: - TLGenerator.write_get_input(builder, arg, 'get_input_user') - elif arg.type == 'InputMedia' and tlobject.is_function: - TLGenerator.write_get_input(builder, arg, 'get_input_media') - elif arg.type == 'InputPhoto' and tlobject.is_function: - TLGenerator.write_get_input(builder, arg, 'get_input_photo') - - else: - builder.writeln('self.{0} = {0}'.format(arg.name)) - - @staticmethod - def write_get_input(builder, arg, get_input_code): - """Returns "True" if the get_input_* code was written when assigning - a parameter upon creating the request. Returns False otherwise - """ + def _write_self_assign(builder, arg, get_input_code): + """Writes self.arg = input.format(self.arg), considering vectors""" if arg.is_vector: - builder.write('self.{0} = [{1}(_x) for _x in {0}]' - .format(arg.name, get_input_code)) + builder.write('self.{0} = [{1} for _x in self.{0}]' + .format(arg.name, get_input_code.format('_x'))) else: - builder.write('self.{0} = {1}({0})' - .format(arg.name, get_input_code)) + builder.write('self.{} = {}'.format( + arg.name, get_input_code.format('self.' + arg.name))) + builder.writeln( - ' if {} else None'.format(arg.name) if arg.is_flag else '' + ' if self.{} else None'.format(arg.name) if arg.is_flag else '' ) @staticmethod