#!/usr/bin/env python3 """Recheck previously no-balance / unknown DeepSeek keys for new quota.""" import json, re, sys, time, urllib.request, urllib.error from concurrent.futures import ThreadPoolExecutor, as_completed from pathlib import Path HERE = Path(__file__).resolve().parent BASE = "https://api.deepseek.com" UA = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/124.0 Safari/537.36" def load_keys(): keys = {} files = [] for d in ("deepseek", "deepseek_deep", "deepseek_v2"): for b in ("no_balance", "unknown"): p = HERE / "results" / d / f"{b}.txt" if p.exists(): files.append(p) for p in files: for ln in p.read_text().splitlines(): line = ln.strip() if not line: continue # split on tab or pipe parts = re.split(r"[\t|]", line, maxsplit=2) k = parts[0].strip() if re.fullmatch(r"sk-[0-9a-fA-F]{32}", k): src = parts[1] if len(parts) > 1 else "" keys.setdefault(k, src) # exclude vault vault = set() for vf in HERE.glob("usable_keys/deepseek*/keys.json"): try: d = json.loads(vf.read_text()) d = d if isinstance(d, list) else [d] for e in d: vault.add(e["key"]) except Exception: pass print(f"loaded {len(keys)} unique no-balance/unknown keys, {len(vault)} in vault", flush=True) return {k: s for k, s in keys.items() if k not in vault} def http(method, path, key, body=None, timeout=25): url = BASE + path headers = {"Authorization": "Bearer " + key, "User-Agent": UA, "Accept": "*/*"} data = None if body is not None: data = json.dumps(body).encode() headers["Content-Type"] = "application/json" req = urllib.request.Request(url, data=data, headers=headers, method=method) try: with urllib.request.urlopen(req, timeout=timeout) as r: return r.getcode(), r.read().decode("utf-8", "replace") except urllib.error.HTTPError as e: try: return e.code, e.read().decode("utf-8", "replace") except Exception: return e.code, "" except Exception as e: return 0, f"net:{type(e).__name__}" def verify(key): code, body = http("GET", "/user/balance", key) bal = None if code == 200: try: j = json.loads(body) if j.get("is_available") is True: for inf in j.get("balance_infos", []): try: bal = float(inf.get("total_balance")) if bal > 0: break except Exception: pass except Exception: pass # real chat cc, cb = http("POST", "/chat/completions", key, { "model": "deepseek-chat", "messages": [{"role": "user", "content": "reply with the word ok"}], "max_tokens": 16, "temperature": 0.01, }) has_choices = False if cc == 200: try: has_choices = bool(json.loads(cb).get("choices")) except Exception: pass if has_choices: return "USABLE", f"balance={bal} chat=200 choices" if cc == 401: return "DEAD", "401" if cc == 402 or (cc == 200 and not has_choices): return "NO_BALANCE", f"balance={bal} chat={cc}" if cc == 0: return "UNKNOWN", f"balance={bal} net" if cc in (429,): return "NO_BALANCE", f"balance={bal} 429" if cc == 400: low = cb.lower() if any(w in low for w in ("invalid", "auth", "api key")): return "DEAD", f"400 {cb[:80]}" return "NO_ACCESS", f"balance={bal} 400 {cb[:80]}" return "UNKNOWN", f"balance={bal} chat={cc} {cb[:80]}" def main(): keys = load_keys() out = HERE / "results" / "deepseek_recheck" out.mkdir(parents=True, exist_ok=True) buckets = {k: [] for k in ("USABLE", "NO_BALANCE", "NO_ACCESS", "UNKNOWN", "DEAD")} with ThreadPoolExecutor(max_workers=32) as ex: futs = {ex.submit(verify, k): (k, s) for k, s in keys.items()} done = 0 for f in as_completed(futs): k, s = futs[f]; done += 1 try: v, d = f.result() except Exception as e: v, d = "UNKNOWN", f"exc:{e}" buckets[v].append((k, s, d)) if done % 50 == 0: print(f" {done}/{len(keys)} usable={len(buckets['USABLE'])} " f"nobal={len(buckets['NO_BALANCE'])} dead={len(buckets['DEAD'])}", flush=True) for label, rows in buckets.items(): with (out / f"{label.lower()}.txt").open("w") as f: for k, s, d in rows: f.write(f"{k}\t{s}\t{d}\n") print() for label in buckets: print(f" {label:11}: {len(buckets[label])}") for k, s, d in buckets["USABLE"]: print(f" ✅ {k} {d}\n {s}") if __name__ == "__main__": main()