universal-autoreg: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609a1a863cbgp
2026-10-20 02:16:17 +03:00
commit 888c07b949
32 changed files with 6363 additions and 0 deletions

104
lib/captcha.py Normal file
View File

@@ -0,0 +1,104 @@
"""captcha.py — клиент captcha-инфраструктуры.
Два бэкенда:
1. Локальный sidecar (waguriagentic/captcha-solver, http://127.0.0.1:8877) — БЕСПЛАТНО:
turnstile / recaptcha v2-v3 / hcaptcha / arkose(funcaptcha) / aliyun / geetest и др. (11 типов).
Запуск sidecar: см. docs/SETUP.md. Для новых версий нужен SOLVER_ALLOW_UNAUTHENTICATED=1.
2. 2captcha fallback (платный) — когда sidecar не справляется (нативный Turnstile под
siteverify-проверкой, DataDome, press&hold PerimeterX).
Все ключи — из config.json (НЕ хардкодить).
"""
import json, os, time, urllib.request, urllib.parse
CFG_FILE = os.environ.get("UA_CONFIG", os.path.join(os.path.dirname(__file__), "..", "config.json"))
SIDECAR = os.environ.get("UA_SIDECAR", "http://127.0.0.1:8877")
def _cfg():
if os.path.exists(CFG_FILE):
return json.load(open(CFG_FILE, encoding="utf-8"))
return {}
def _post_json(url, payload, timeout=300):
req = urllib.request.Request(url, data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=timeout) as r:
return json.loads(r.read().decode())
def sidecar_health():
try:
with urllib.request.urlopen(SIDECAR + "/health", timeout=5) as r:
return json.loads(r.read().decode())
except Exception as e:
return {"ok": False, "error": str(e)}
def solve_sidecar(captcha_type: str, sitekey: str, pageurl: str, **kw):
"""Решить капчу локальным sidecar'ом (бесплатно).
captcha_type: turnstile | recaptcha_v2 | recaptcha_v3 | hcaptcha | funcaptcha | ...
Для recaptcha v3 обязательны: page_action (action сайта, напр. 'signup').
Для turnstile рекомендуется real_page режим у sidecar'а (REAL_PAGE=1).
"""
payload = {"type": captcha_type, "sitekey": sitekey, "pageurl": pageurl}
payload.update(kw)
return _post_json(SIDECAR + "/solve", payload)
def solve_2captcha(captcha_type: str, sitekey: str, pageurl: str, **kw):
"""2captcha fallback. ВАЖНО: submit СТРОГО на in.php (res.php = ERROR_EMPTY_METHOD),
баланс СТРОГО POST api.2captcha.com/res.php (GET = ложный ERROR_WRONG_USER_KEY)."""
key = _cfg().get("twocaptcha_key")
if not key:
raise RuntimeError("twocaptcha_key not set in config.json")
method = {"turnstile": "turnstile", "recaptcha_v2": "userrecaptcha",
"recaptcha_v3": "recaptcha", "hcaptcha": "hcaptcha",
"funcaptcha": "funcaptcha"}.get(captcha_type, captcha_type)
params = {"key": key, "method": method, "googlekey" if method == "userrecaptcha" else "sitekey": sitekey,
"pageurl": pageurl, "json": 1}
params.update(kw)
data = urllib.parse.urlencode(params).encode()
with urllib.request.urlopen("https://api.2captcha.com/in.php", data=data, timeout=30) as r:
resp = json.loads(r.read().decode())
if resp.get("status") != 1:
raise RuntimeError(f"2captcha submit failed: {resp}")
cid = resp["request"]
for _ in range(60):
time.sleep(5)
q = urllib.parse.urlencode({"key": key, "action": "get", "id": cid, "json": 1}).encode()
with urllib.request.urlopen("https://api.2captcha.com/res.php", data=q, timeout=30) as r:
resp = json.loads(r.read().decode())
if resp.get("status") == 1:
return {"token": resp["request"]}
if resp.get("request") != "CAPCHA_NOT_READY":
raise RuntimeError(f"2captcha: {resp}")
raise TimeoutError("2captcha timeout 300s")
def solve(captcha_type: str, sitekey: str, pageurl: str, prefer="sidecar", **kw):
"""Умный решатель: sidecar → при ошибке 2captcha (если включён fallback)."""
if prefer == "sidecar":
try:
return solve_sidecar(captcha_type, sitekey, pageurl, **kw)
except Exception:
if _cfg().get("twocaptcha_fallback", True):
return solve_2captcha(captcha_type, sitekey, pageurl, **kw)
raise
return solve_2captcha(captcha_type, sitekey, pageurl, **kw)
def balance_2captcha():
key = _cfg().get("twocaptcha_key")
if not key:
return None
data = urllib.parse.urlencode({"key": key, "action": "getbalance"}).encode()
with urllib.request.urlopen("https://api.2captcha.com/res.php", data=data, timeout=15) as r:
return json.loads(r.read().decode())
if __name__ == "__main__":
print("sidecar health:", sidecar_health())
print("2captcha balance:", balance_2captcha())