async ip address calls

This commit is contained in:
SimplifiedPrivacy 2026-10-22 13:37:27 -04:00
parent af368db8b7
commit 587c72f4c3

View file

@ -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.
""" async def _test(connection_observer: Optional[ConnectionObserver], port: Optional[int] = None) -> Result:
attempt = 0 endpoint_list = list(API_ENDPOINT_FORMATS.keys())[:MAX_ATTEMPTS]
endpoint_index = 0
endpoint_list = list(API_ENDPOINT_FORMATS.keys())
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:
raw_response = _ip_test_client.get(endpoint_url)
try:
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)}")
logger.error(f"We went through {MAX_ATTEMPTS} attempts and could not get a reply.") return Result(valid=False)
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