Add Gmail+Email Worker hybrid mail path and private runtime config

Prefer Cloudflare Worker KV for verification codes with optional short IMAP
fallback disabled for private deploy; track config.json/.env for private repo.
Also add worker project, protocol mint backoff, and fail-fast Turnstile/mail
timeouts from batch runs.
This commit is contained in:
chaos committed 2026-07-11 23:21:23 +08:00
1 parent 187792d6be
commit 55f56d27c9
19 files changed
+1225 -85

No files matched your search

+64 -32
View File
@@ -2,6 +2,9 @@
from __future__ import annotations
import threading
import time
from pathlib import Path
from typing import Any, Callable
@@ -14,6 +17,11 @@ from .writer import write_cpa_xai_auth
LogFn = Callable[[str], None]
# Serialize/spacing protocol mints to reduce accounts.x.ai rate_limited.
_PROTOCOL_MINT_LOCK = threading.Lock()
_PROTOCOL_LAST_OK_AT = 0.0
_PROTOCOL_MIN_INTERVAL_SEC = 1.5
def _noop(_: str) -> None:
return None
@@ -51,6 +59,7 @@ def mint_and_export(
Returns dict with keys: ok, path, email, probe, error?, mint_method?
"""
log = log or _noop
global _PROTOCOL_LAST_OK_AT
email = (email or "").strip()
if not email or not password:
# Protocol can work with sso alone; password only required for browser fallback
@@ -71,38 +80,61 @@ def mint_and_export(
if prefer_protocol and sso_val:
log("mint try protocol (SSO HTTP device flow)")
try:
tokens = mint_with_sso_protocol(
sso_cookie=sso_val,
email=email,
proxy=resolved or None,
poll_timeout_sec=protocol_poll_timeout_sec,
log=log,
cancel=cancel,
)
log("mint protocol SUCCESS")
except ProtocolMintError as e:
protocol_err = str(e)
log(f"mint protocol failed: {e}")
if protocol_only:
return {
"ok": False,
"email": email,
"error": f"protocol_only: {e}",
"mint_method": "protocol",
}
log("mint fallback → browser")
except Exception as e: # noqa: BLE001
protocol_err = str(e)
log(f"mint protocol exception: {e}")
if protocol_only:
return {
"ok": False,
"email": email,
"error": f"protocol_only: {e}",
"mint_method": "protocol",
}
log("mint fallback → browser")
max_protocol_attempts = 3
for attempt in range(1, max_protocol_attempts + 1):
if cancel and cancel():
return {"ok": False, "email": email, "error": "cancelled", "mint_method": "protocol"}
# Throttle protocol calls across mint workers
with _PROTOCOL_MINT_LOCK:
gap = time.time() - _PROTOCOL_LAST_OK_AT
if _PROTOCOL_LAST_OK_AT > 0 and gap < _PROTOCOL_MIN_INTERVAL_SEC:
wait = _PROTOCOL_MIN_INTERVAL_SEC - gap
log(f"protocol throttle sleep {wait:.1f}s")
time.sleep(wait)
try:
tokens = mint_with_sso_protocol(
sso_cookie=sso_val,
email=email,
proxy=resolved or None,
poll_timeout_sec=protocol_poll_timeout_sec,
log=log,
cancel=cancel,
)
with _PROTOCOL_MINT_LOCK:
_PROTOCOL_LAST_OK_AT = time.time()
log("mint protocol SUCCESS")
protocol_err = None
break
except ProtocolMintError as e:
protocol_err = str(e)
log(f"mint protocol failed (try {attempt}/{max_protocol_attempts}): {e}")
rate_limited = "rate_limited" in protocol_err.lower()
if rate_limited and attempt < max_protocol_attempts:
backoff = 5.0 * attempt
log(f"protocol rate_limited → backoff {backoff:.0f}s then retry")
time.sleep(backoff)
continue
if protocol_only:
return {
"ok": False,
"email": email,
"error": f"protocol_only: {e}",
"mint_method": "protocol",
}
log("mint fallback → browser")
break
except Exception as e: # noqa: BLE001
protocol_err = str(e)
log(f"mint protocol exception (try {attempt}/{max_protocol_attempts}): {e}")
if protocol_only:
return {
"ok": False,
"email": email,
"error": f"protocol_only: {e}",
"mint_method": "protocol",
}
log("mint fallback → browser")
break
elif prefer_protocol and not sso_val:
log("mint protocol skipped (no sso cookie) → browser")
if protocol_only: