mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-02-03 05:04:33 +03:00
Add new method to .resolve() parameters instead on init
TLObject's __init__ used to call utils.get_input_* methods and similar to auto-cast things like User into InputPeerUser as required. Now there's a custom .resolve() method for this purpose with several advantages: - Old behaviour still works, autocasts work like usual. - A request can be constructed and later modified, before the autocast only occured on the constructor but now while invoking. - This allows us to not only use the utils module but also the client, so it's even possible to use usernames or phone numbers for things that require an InputPeer. This actually assumes the TelegramClient subclass is being used and not the bare version which would fail when calling .get_input_peer().
This commit is contained in:
parent
7c55d42287
commit
1c9fa76ede
|
@ -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__
|
||||
|
|
|
@ -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 {}
|
||||
|
||||
|
|
|
@ -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,8 +266,43 @@ 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
|
||||
|
@ -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)
|
||||
|
||||
def _write_self_assign(builder, arg, get_input_code):
|
||||
"""Writes self.arg = input.format(self.arg), considering vectors"""
|
||||
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.write('self.{0} = [{1} for _x in self.{0}]'
|
||||
.format(arg.name, get_input_code.format('_x')))
|
||||
else:
|
||||
builder.write('self.{} = {}'.format(
|
||||
arg.name, get_input_code.format('self.' + arg.name)))
|
||||
|
||||
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
|
||||
"""
|
||||
if arg.is_vector:
|
||||
builder.write('self.{0} = [{1}(_x) for _x in {0}]'
|
||||
.format(arg.name, get_input_code))
|
||||
else:
|
||||
builder.write('self.{0} = {1}({0})'
|
||||
.format(arg.name, get_input_code))
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue
Block a user