From 2ba7383f8182b3c44b6d83e15ef51672e110c3bb Mon Sep 17 00:00:00 2001 From: disqualifier Date: Wed, 24 Jun 2026 21:16:46 -0400 Subject: [PATCH] init: proxy parsing, formatting & source management Signed-off-by: disqualifier --- .gitignore | 16 ++++++++ README.md | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 .gitignore create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6ff830 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# claude +CLAUDE.md + +# python +__pycache__/ +*.py[cod] +*.egg-info/ +dist/ +build/ +.eggs/ + +# env +.venv/ +venv/ +.env +.pytest_cache/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ff2e63 --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ +# 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.