async ip address calls
This commit is contained in:
parent
af368db8b7
commit
587c72f4c3
1 changed files with 38 additions and 27 deletions
|
|
@ -11,6 +11,7 @@ from essentials.observers.ConnectionObserver import ConnectionObserver
|
||||||
# generic
|
# generic
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
|
import asyncio
|
||||||
import httpx
|
import httpx
|
||||||
from httpx_socks import AsyncProxyTransport
|
from httpx_socks import AsyncProxyTransport
|
||||||
import httpx_socks
|
import httpx_socks
|
||||||
|
|
@ -31,50 +32,63 @@ API_ENDPOINT_FORMATS = {
|
||||||
MAX_ATTEMPTS = 3
|
MAX_ATTEMPTS = 3
|
||||||
|
|
||||||
def test(connection_observer: Optional[ConnectionObserver], port: Optional[int] = None) -> Result:
|
def test(connection_observer: Optional[ConnectionObserver], port: Optional[int] = None) -> Result:
|
||||||
"""
|
return asyncio.run(_test(connection_observer, port))
|
||||||
Cycles through 3 possible endpoints,
|
|
||||||
to attempt to get an IP address for the systemwide connection.
|
|
||||||
"""
|
|
||||||
attempt = 0
|
|
||||||
endpoint_index = 0
|
|
||||||
endpoint_list = list(API_ENDPOINT_FORMATS.keys())
|
|
||||||
|
|
||||||
|
|
||||||
|
async def _test(connection_observer: Optional[ConnectionObserver], port: Optional[int] = None) -> Result:
|
||||||
|
endpoint_list = list(API_ENDPOINT_FORMATS.keys())[:MAX_ATTEMPTS]
|
||||||
|
|
||||||
if port:
|
if port:
|
||||||
transport = httpx_socks.SyncProxyTransport(
|
transport = httpx_socks.AsyncProxyTransport(
|
||||||
proxy_type=ProxyType.SOCKS5,
|
proxy_type=ProxyType.SOCKS5,
|
||||||
proxy_host="127.0.0.1",
|
proxy_host="127.0.0.1",
|
||||||
proxy_port=port,
|
proxy_port=port,
|
||||||
)
|
)
|
||||||
_ip_test_client = httpx.Client(transport=transport, http2=True, timeout=6)
|
client = httpx.AsyncClient(transport=transport, http2=True, timeout=6)
|
||||||
else:
|
else:
|
||||||
_ip_test_client = httpx.Client(http2=True, timeout=6)
|
client = httpx.AsyncClient(http2=True, timeout=6)
|
||||||
|
|
||||||
|
async def attempt_request(url: str, index: int):
|
||||||
while attempt < MAX_ATTEMPTS:
|
logger.info(f"Attempt {index + 1}: Trying {url}")
|
||||||
endpoint_url = endpoint_list[attempt]
|
|
||||||
attempt += 1
|
|
||||||
logger.info(f"Attempt {attempt}: Trying {endpoint_url}")
|
|
||||||
if connection_observer:
|
if connection_observer:
|
||||||
connection_observer.notify("connecting", f"Testing IP. Attempt {attempt}")
|
connection_observer.notify("connecting", f"Testing IP. Attempt {index + 1}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
raw_response = _ip_test_client.get(endpoint_url)
|
raw_response = await client.get(url)
|
||||||
|
|
||||||
filtered_response = classify_response(raw_response)
|
filtered_response = classify_response(raw_response)
|
||||||
|
|
||||||
if filtered_response.valid:
|
if filtered_response.valid:
|
||||||
ip_address = extract_ip_from_response(
|
ip_address = extract_ip_from_response(
|
||||||
response=filtered_response.data,
|
response=filtered_response.data,
|
||||||
api_url=endpoint_url
|
api_url=url
|
||||||
)
|
)
|
||||||
if ip_address is not None:
|
if ip_address is not None:
|
||||||
return Result(valid=True, data=ip_address)
|
return Result(valid=True, data=ip_address)
|
||||||
else:
|
|
||||||
logger.error(f"Skipping {endpoint_url}")
|
logger.error(f"Skipping {url}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"We are NOT error handling this. Skipping {endpoint_url}. Invalid API reply or failed connection {str(e)}")
|
logger.error(f"Skipping {url}. Invalid API reply or failed connection {str(e)}")
|
||||||
|
|
||||||
|
return Result(valid=False)
|
||||||
|
|
||||||
logger.error(f"We went through {MAX_ATTEMPTS} attempts and could not get a reply.")
|
try:
|
||||||
|
# Create tasks for all endpoints to run them concurrently
|
||||||
|
tasks = [asyncio.create_task(attempt_request(url, i)) for i, url in enumerate(endpoint_list)]
|
||||||
|
|
||||||
|
# Process tasks as they complete
|
||||||
|
for future in asyncio.as_completed(tasks):
|
||||||
|
result = await future
|
||||||
|
if result.valid:
|
||||||
|
# Cancel all other pending tasks immediately
|
||||||
|
for t in tasks:
|
||||||
|
if not t.done():
|
||||||
|
t.cancel()
|
||||||
|
return result
|
||||||
|
|
||||||
|
finally:
|
||||||
|
await client.aclose()
|
||||||
|
|
||||||
|
logger.error(f"We went through {len(endpoint_list)} attempts and could not get a reply.")
|
||||||
return Result(valid=False, error_type=ResultError.CONNECTION, message="Could not connect.")
|
return Result(valid=False, error_type=ResultError.CONNECTION, message="Could not connect.")
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -84,9 +98,6 @@ def extract_ip_from_response(response: dict, api_url: str) -> str | bool:
|
||||||
Extract the IP address from the API's response,
|
Extract the IP address from the API's response,
|
||||||
based on which keys that API uses.
|
based on which keys that API uses.
|
||||||
|
|
||||||
Rank:
|
|
||||||
Helper
|
|
||||||
|
|
||||||
On Success:
|
On Success:
|
||||||
Returns String of IP address
|
Returns String of IP address
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue