mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-03-12 23:48:02 +03:00
Replace pysocks with python-proxy
This commit is contained in:
parent
9752f66eab
commit
ad7e62baf3
|
@ -1,4 +1,4 @@
|
||||||
cryptg
|
cryptg
|
||||||
pysocks
|
pproxy
|
||||||
hachoir3
|
hachoir3
|
||||||
pillow
|
pillow
|
||||||
|
|
|
@ -107,7 +107,7 @@ Signing In behind a Proxy
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
If you need to use a proxy to access Telegram,
|
If you need to use a proxy to access Telegram,
|
||||||
you will need to `install PySocks`__ and then change:
|
you will need to `install python-proxy`__ and then change:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -117,12 +117,20 @@ with
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
TelegramClient('anon', api_id, api_hash, proxy=(socks.SOCKS5, '127.0.0.1', 4444))
|
TelegramClient('anon', api_id, api_hash, proxy='socks5://127.0.0.1:4444')
|
||||||
|
|
||||||
|
# You can also use a ``dict`` (it will be translated to the same URI as above)
|
||||||
|
TelegramClient('anon', api_id, api_hash, proxy={
|
||||||
|
'scheme': 'socks5',
|
||||||
|
'hostname': '127.0.0.1',
|
||||||
|
'port': 4444
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
(of course, replacing the IP and port with the IP and port of the proxy).
|
(of course, replacing the IP and port with the IP and port of the proxy).
|
||||||
|
|
||||||
The ``proxy=`` argument should be a tuple, a list or a dict,
|
The ``proxy=`` argument should be a tuple, a list or a dict,
|
||||||
consisting of parameters described `in PySocks usage`__.
|
consisting of parameters described `in python-proxy usage`__.
|
||||||
|
|
||||||
.. __: https://github.com/Anorov/PySocks#installation
|
.. __: https://github.com/qwj/python-proxy#quickstart
|
||||||
.. __: https://github.com/Anorov/PySocks#usage-1
|
.. __: https://github.com/qwj/python-proxy#uri-syntax
|
||||||
|
|
|
@ -67,12 +67,11 @@ class TelegramBaseClient(abc.ABC):
|
||||||
By default this is ``False`` as IPv6 support is not
|
By default this is ``False`` as IPv6 support is not
|
||||||
too widespread yet.
|
too widespread yet.
|
||||||
|
|
||||||
proxy (`tuple` | `list` | `dict`, optional):
|
proxy (`str` | `dict`, optional):
|
||||||
An iterable consisting of the proxy info. If `connection` is
|
The URI with all the required proxy information, or a dictionary
|
||||||
one of `MTProxy`, then it should contain MTProxy credentials:
|
with the fields to use (like ``schemepython``, ``hostname``, etc.).
|
||||||
``('hostname', port, 'secret')``. Otherwise, it's meant to store
|
|
||||||
function parameters for PySocks, like ``(type, 'hostname', port)``.
|
See https://github.com/qwj/python-proxy#uri-syntax for details.
|
||||||
See https://github.com/Anorov/PySocks#usage-1 for more.
|
|
||||||
|
|
||||||
timeout (`int` | `float`, optional):
|
timeout (`int` | `float`, optional):
|
||||||
The timeout in seconds to be used when connecting.
|
The timeout in seconds to be used when connecting.
|
||||||
|
@ -171,7 +170,7 @@ class TelegramBaseClient(abc.ABC):
|
||||||
*,
|
*,
|
||||||
connection: 'typing.Type[Connection]' = ConnectionTcpFull,
|
connection: 'typing.Type[Connection]' = ConnectionTcpFull,
|
||||||
use_ipv6: bool = False,
|
use_ipv6: bool = False,
|
||||||
proxy: typing.Union[tuple, dict] = None,
|
proxy: typing.Union[str, dict] = None,
|
||||||
timeout: int = 10,
|
timeout: int = 10,
|
||||||
request_retries: int = 5,
|
request_retries: int = 5,
|
||||||
connection_retries: int =5,
|
connection_retries: int =5,
|
||||||
|
@ -254,14 +253,14 @@ class TelegramBaseClient(abc.ABC):
|
||||||
self._request_retries = request_retries
|
self._request_retries = request_retries
|
||||||
self._connection_retries = connection_retries
|
self._connection_retries = connection_retries
|
||||||
self._retry_delay = retry_delay or 0
|
self._retry_delay = retry_delay or 0
|
||||||
self._proxy = proxy
|
self._proxy = helpers._get_proxy_uri(proxy)
|
||||||
self._timeout = timeout
|
self._timeout = timeout
|
||||||
self._auto_reconnect = auto_reconnect
|
self._auto_reconnect = auto_reconnect
|
||||||
|
|
||||||
assert isinstance(connection, type)
|
assert isinstance(connection, type)
|
||||||
self._connection = connection
|
self._connection = connection
|
||||||
init_proxy = None if not issubclass(connection, TcpMTProxy) else \
|
init_proxy = None if not issubclass(connection, TcpMTProxy) else \
|
||||||
types.InputClientProxy(*connection.address_info(proxy))
|
types.InputClientProxy(*connection.address_info(self._proxy))
|
||||||
|
|
||||||
# Used on connection. Capture the variables in a lambda since
|
# Used on connection. Capture the variables in a lambda since
|
||||||
# exporting clients need to create this InvokeWithLayerRequest.
|
# exporting clients need to create this InvokeWithLayerRequest.
|
||||||
|
|
|
@ -131,6 +131,43 @@ def _sync_exit(self, *args):
|
||||||
return loop.run_until_complete(self.__aexit__(*args))
|
return loop.run_until_complete(self.__aexit__(*args))
|
||||||
|
|
||||||
|
|
||||||
|
def _get_proxy_uri(proxy):
|
||||||
|
if not proxy:
|
||||||
|
return None
|
||||||
|
elif isinstance(proxy, str):
|
||||||
|
return proxy
|
||||||
|
elif isinstance(proxy, dict):
|
||||||
|
fmt = {
|
||||||
|
'scheme': 'socks5',
|
||||||
|
'cipher': '',
|
||||||
|
'netloc': '',
|
||||||
|
'localbind': '',
|
||||||
|
'plugins': '',
|
||||||
|
'rules': '',
|
||||||
|
'auth': ''
|
||||||
|
}
|
||||||
|
fmt.update(proxy)
|
||||||
|
if 'hostname' in fmt:
|
||||||
|
fmt['netloc'] = '{}:{}'.format(fmt.pop('hostname'), fmt.pop('port'))
|
||||||
|
if 'username' in fmt:
|
||||||
|
fmt['auth'] = '{}:{}'.format(fmt.pop('username'), fmt.pop('password'))
|
||||||
|
|
||||||
|
fix = {
|
||||||
|
'cipher': '{}@',
|
||||||
|
'localbind': '@{}',
|
||||||
|
'plugins': ',{}',
|
||||||
|
'rules': '?{}',
|
||||||
|
'auth': '#{}'
|
||||||
|
}
|
||||||
|
for k, v in fix.items():
|
||||||
|
if fmt[k]:
|
||||||
|
fmt[k] = v.format(fmt[k])
|
||||||
|
|
||||||
|
return '{scheme}://{cipher}{netloc}/{localbind}{plugins}{rules}{auth}'.format(**fmt)
|
||||||
|
else:
|
||||||
|
raise TypeError('{!r} is not a valid proxy (must be str URI or dict)'.format(proxy))
|
||||||
|
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Cryptographic related utils
|
# region Cryptographic related utils
|
||||||
|
|
|
@ -43,43 +43,19 @@ class Connection(abc.ABC):
|
||||||
|
|
||||||
async def _connect(self, timeout=None, ssl=None):
|
async def _connect(self, timeout=None, ssl=None):
|
||||||
if not self._proxy:
|
if not self._proxy:
|
||||||
|
connect_coroutine = asyncio.open_connection(
|
||||||
|
self._ip, self._port, loop=self._loop, ssl=ssl)
|
||||||
|
else:
|
||||||
|
import pproxy
|
||||||
|
|
||||||
|
# FIXME https://github.com/qwj/python-proxy/issues/41
|
||||||
|
connect_coroutine = pproxy.Connection(
|
||||||
|
self._proxy).tcp_connect(self._ip, self._port)
|
||||||
|
|
||||||
self._reader, self._writer = await asyncio.wait_for(
|
self._reader, self._writer = await asyncio.wait_for(
|
||||||
asyncio.open_connection(
|
connect_coroutine,
|
||||||
self._ip, self._port, loop=self._loop, ssl=ssl),
|
|
||||||
loop=self._loop, timeout=timeout
|
loop=self._loop, timeout=timeout
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
import socks
|
|
||||||
if ':' in self._ip:
|
|
||||||
mode, address = socket.AF_INET6, (self._ip, self._port, 0, 0)
|
|
||||||
else:
|
|
||||||
mode, address = socket.AF_INET, (self._ip, self._port)
|
|
||||||
|
|
||||||
s = socks.socksocket(mode, socket.SOCK_STREAM)
|
|
||||||
if isinstance(self._proxy, dict):
|
|
||||||
s.set_proxy(**self._proxy)
|
|
||||||
else:
|
|
||||||
s.set_proxy(*self._proxy)
|
|
||||||
|
|
||||||
s.setblocking(False)
|
|
||||||
await asyncio.wait_for(
|
|
||||||
self._loop.sock_connect(s, address),
|
|
||||||
timeout=timeout,
|
|
||||||
loop=self._loop
|
|
||||||
)
|
|
||||||
if ssl:
|
|
||||||
s.settimeout(timeout)
|
|
||||||
s = ssl_mod.wrap_socket(
|
|
||||||
s,
|
|
||||||
do_handshake_on_connect=True,
|
|
||||||
ssl_version=ssl_mod.PROTOCOL_SSLv23,
|
|
||||||
ciphers='ADH-AES256-SHA'
|
|
||||||
)
|
|
||||||
s.setblocking(False)
|
|
||||||
|
|
||||||
self._reader, self._writer = \
|
|
||||||
await asyncio.open_connection(sock=s, loop=self._loop)
|
|
||||||
|
|
||||||
self._codec = self.packet_codec(self)
|
self._codec = self.packet_codec(self)
|
||||||
self._init_conn()
|
self._init_conn()
|
||||||
await self._writer.drain()
|
await self._writer.drain()
|
||||||
|
|
|
@ -126,6 +126,7 @@ class TcpMTProxy(ObfuscatedConnection):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def address_info(proxy_info):
|
def address_info(proxy_info):
|
||||||
|
raise NotImplementedError('New proxy format is not implemented')
|
||||||
if proxy_info is None:
|
if proxy_info is None:
|
||||||
raise ValueError("No proxy info specified for MTProxy connection")
|
raise ValueError("No proxy info specified for MTProxy connection")
|
||||||
return proxy_info[:2]
|
return proxy_info[:2]
|
||||||
|
|
|
@ -116,9 +116,8 @@ class InteractiveTelegramClient(TelegramClient):
|
||||||
try:
|
try:
|
||||||
loop.run_until_complete(self.connect())
|
loop.run_until_complete(self.connect())
|
||||||
except IOError:
|
except IOError:
|
||||||
# We handle IOError and not ConnectionError because
|
# To avoid issues in the future, we except the most
|
||||||
# PySocks' errors do not subclass ConnectionError
|
# generic IOError as possible (instead of ConnectionError)
|
||||||
# (so this will work with and without proxies).
|
|
||||||
print('Initial connection failed. Retrying...')
|
print('Initial connection failed. Retrying...')
|
||||||
loop.run_until_complete(self.connect())
|
loop.run_until_complete(self.connect())
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ def get_env(name, message, cast=str):
|
||||||
session = os.environ.get('TG_SESSION', 'printer')
|
session = os.environ.get('TG_SESSION', 'printer')
|
||||||
api_id = get_env('TG_API_ID', 'Enter your API ID: ', int)
|
api_id = get_env('TG_API_ID', 'Enter your API ID: ', int)
|
||||||
api_hash = get_env('TG_API_HASH', 'Enter your API hash: ')
|
api_hash = get_env('TG_API_HASH', 'Enter your API hash: ')
|
||||||
proxy = None # https://github.com/Anorov/PySocks
|
proxy = None # https://github.com/qwj/python-proxy#uri-syntax
|
||||||
|
|
||||||
# Create and start the client so we can make requests (we don't here)
|
# Create and start the client so we can make requests (we don't here)
|
||||||
client = TelegramClient(session, api_id, api_hash, proxy=proxy).start()
|
client = TelegramClient(session, api_id, api_hash, proxy=proxy).start()
|
||||||
|
|
|
@ -27,7 +27,7 @@ def get_env(name, message, cast=str):
|
||||||
session = os.environ.get('TG_SESSION', 'printer')
|
session = os.environ.get('TG_SESSION', 'printer')
|
||||||
api_id = get_env('TG_API_ID', 'Enter your API ID: ', int)
|
api_id = get_env('TG_API_ID', 'Enter your API ID: ', int)
|
||||||
api_hash = get_env('TG_API_HASH', 'Enter your API hash: ')
|
api_hash = get_env('TG_API_HASH', 'Enter your API hash: ')
|
||||||
proxy = None # https://github.com/Anorov/PySocks
|
proxy = None # https://github.com/qwj/python-proxy#uri-syntax
|
||||||
|
|
||||||
|
|
||||||
# This is our update handler. It is called when a new update arrives.
|
# This is our update handler. It is called when a new update arrives.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user