# aioproxies Proxy parsing, formatting, and source management. Renders proxies for aiohttp/aioweb, camoufox, and socks5; manages session templates (with caller-supplied fields like country/ttl), rotating lists, or a static proxy. **Credentials are always injected — never hardcoded.** ## Install ``` aioproxies @ git+ssh://git@git.rethinkstudios.io/rethink-public/aioproxies.git@v0.1.0 # network helpers (current_ip / reset) need the extra: aioproxies[net] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aioproxies.git@v0.1.0 ``` The core has no dependencies. The `net` extra adds `aiohttp` for `current_ip` / `reset`. ## Formatting ```python from aioproxies import parse p = parse("1.2.3.4:8080:user:pass") # or "host:port" p.aiohttp() # {"http": "...", "https": "..."} -> aioweb ExtendedSession(proxies=) p.camoufox() # {"server": "...", "username": ..., "password": ...} p.socks5() # {"server": "socks5://...", ...} p.url() # "http://user:pass@host:port" ``` ## Sources Construct with exactly one source: ```python from aioproxies import AioProxies # rotating list (round-robin, shuffled by default) m = AioProxies(proxies=["h1:1:u:p", "h2:2:u:p"]) m.get() # next proxy as an aiohttp dict # session template — {session} is filled with a fresh id each call m = AioProxies(template="gw.example.io:9000:user_X,sess_{session}:pw") # a bare {} also works and is treated as the session slot # static m = AioProxies(static="1.2.3.4:8080:u:p") # from a file (raises FileNotFoundError if missing — never exits the process) m = AioProxies.from_file("proxies.txt") ``` The class is also exported as `ProxyManager` and lowercase `aioproxies` (aliases of `AioProxies`) — use whichever reads best at your call site. ## Location / per-call fields Templates can carry extra named placeholders the caller fills per call; the lib always fills `{session}`. This replaces the old `location_proxy(country, ttl)` / `dynamic_proxy(user)` helpers — one template, fields supplied at call time: ```python m = AioProxies(template="portal.io:1080:user_X,country_{country},ttl_{ttl},sess_{session}:pw") m.next(country="ca", ttl=30) # lib fills {session}; caller fills {country}/{ttl} m.get(country="us", ttl=60) # same, returned as an aiohttp dict ``` Provider-specific values (account, password, the host, country codes, ASN tables, which providers support geo) are **your config** — bake them into the template or pass them as fields. The lib only fills placeholders; it never holds credentials. ### Provider session strings (e.g. mobile rotation) ```python # creds come from your config — placeholders shown here template = ( "portal.anyip.io:1080:" "user_{ACCOUNT},type_mobile,country_{{country}},asn_{{asn}},session_{{session}}:{PASSWORD}" ).format(ACCOUNT=acct, PASSWORD=pw) # double-braced fields survive this .format() m = AioProxies(template=template) # and stay as {country}/{asn}/{session} for the lib m.next(country="us", asn="7922") ``` The credentials are baked in once with `.format()`; the per-call fields and `{session}` are double-braced (`{{country}}`) so they pass through that `.format()` untouched and remain for `next(**fields)` / the lib to fill. ## Network helpers (optional) ```python from aioproxies.net import current_ip, reset ip = await current_ip("1.2.3.4:8080:u:p") # egress ip through the proxy (ipify by default) await reset("https://provider/reset-url") # rotate upstream ip ``` `current_ip` defaults to ipify and is opt-in; pass `test_url=` to point elsewhere. ## Notes - No module-level globals; rotation state is per-instance. - A missing proxy file raises, it does not exit the process. - Country/ASN tables, provider accounts, and reset URLs are project config — inject them; do not hardcode credentials in shared code.