Add set_proxy() to change proxy, without reestablishing client.

Current client implementation does not allow to
change proxy without recreating whole `TelegramClient` object.

Instead of creating a new `TelegramClient` each time we need to
change proxy, user can use this method.
This commit is contained in:
Serhii Dylda 2020-11-13 03:18:04 +01:00
parent ab9035acd2
commit 56c5e19184

View File

@ -355,18 +355,17 @@ class TelegramBaseClient(abc.ABC):
else:
default_device_model = system.machine
default_system_version = re.sub(r'-.+','',system.release)
self._init_with = lambda x: functions.InvokeWithLayerRequest(
LAYER, functions.InitConnectionRequest(
api_id=self.api_id,
device_model=device_model or default_device_model or 'Unknown',
system_version=system_version or default_system_version or '1.0',
app_version=app_version or self.__version__,
lang_code=lang_code,
system_lang_code=system_lang_code,
lang_pack='', # "langPacks are for official apps only"
query=x,
proxy=init_proxy
)
self._init_request = functions.InitConnectionRequest(
api_id=self.api_id,
device_model=device_model or default_device_model or 'Unknown',
system_version=system_version or default_system_version or '1.0',
app_version=app_version or self.__version__,
lang_code=lang_code,
system_lang_code=system_lang_code,
lang_pack='', # "langPacks are for official apps only"
query=functions.help.GetConfigRequest(),
proxy=init_proxy
)
self._sender = MTProtoSender(
@ -527,8 +526,9 @@ class TelegramBaseClient(abc.ABC):
self.session.auth_key = self._sender.auth_key
self.session.save()
await self._sender.send(self._init_with(
functions.help.GetConfigRequest()))
await self._sender.send(functions.InvokeWithLayerRequest(
LAYER, self._init_request
))
self._updates_handle = self._loop.create_task(self._update_loop())
@ -574,6 +574,35 @@ class TelegramBaseClient(abc.ABC):
# However, it doesn't really make a lot of sense.
pass
def set_proxy(self: 'TelegramClient', proxy: typing.Union[tuple, dict]):
"""
Changes the proxy which will be used on next (re)connection.
Method has no immediate effects if the client is currently connected.
The new proxy will take it's effect on the next reconnection attempt:
- on a call `await client.connect()` (after complete disconnect)
- on auto-reconnect attempt (e.g, after previous connection was lost)
"""
init_proxy = None if not issubclass(self._connection, TcpMTProxy) else \
types.InputClientProxy(*self._connection.address_info(proxy))
self._init_request.proxy = init_proxy
self._proxy = proxy
# While `await client.connect()` passes new proxy on each new call,
# auto-reconnect attempts use already set up `_connection` inside
# the `_sender`, so the only way to change proxy between those
# is to directly inject parameters.
connection = getattr(self._sender, "_connection", None)
if connection:
if isinstance(connection, TcpMTProxy):
setattr(connection, "_ip", proxy[0])
setattr(connection, "_port", proxy[1])
else:
setattr(connection, "_proxy", proxy)
async def _disconnect_coro(self: 'TelegramClient'):
await self._disconnect()