import sys sys.dont_write_bytecode = True import argparse import os import re import requests sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from keycheck_common import ( append_jsonl, classify_common_http_status, combined_provider_routing_hint, commit_status_transaction, default_input_file, default_proxy_file, ensure_output_files, iter_findings, keycheck_input_mode, load_checked_statuses, load_known_keys, load_proxies, mask_secret, provider_routing_database_failed, recover_status_transaction, request_error_message, record_validation_result, require_provider_authority, service_output_dir, should_skip_key, write_keycheck_event, ) from keycheckers.provider_resolution import resolve_provider_key SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) PARENT_DIR = os.path.dirname(SCRIPT_DIR) SERVICE = "deepseek" OUTPUT_DIR = os.getenv("KEYCHECK_OUTPUT_DIR") or service_output_dir(SERVICE) INPUT_FILE = os.getenv("KEYCHECK_INPUT_FILE") or default_input_file() PROXY_FILE = os.getenv("KEYCHECK_PROXY_FILE") or default_proxy_file() CHECKED_FILE = os.path.join(OUTPUT_DIR, "deepseekChecked.txt") RESULTS_FILE = os.path.join(OUTPUT_DIR, "deepseekResults.jsonl") STATUS_FILES = { "VALID": os.path.join(OUTPUT_DIR, "deepseekAlive.txt"), "NO_BALANCE": os.path.join(OUTPUT_DIR, "deepseekNoBalance.txt"), "DEAD": os.path.join(OUTPUT_DIR, "deepseekDead.txt"), "LIMITED": os.path.join(OUTPUT_DIR, "deepseekLimited.txt"), "NETWORK": os.path.join(OUTPUT_DIR, "deepseekNetwork.txt"), "NO_CONTEXT": os.path.join(OUTPUT_DIR, "deepseekNoContext.txt"), "UNKNOWN": os.path.join(OUTPUT_DIR, "deepseekUnknown.txt"), } DEEPSEEK_REGEX = re.compile(r"sk-[a-z0-9]{32}") DEEPSEEK_DETECTOR_NAMES = {"deepseek", "deepseekapikey", "deepseek_api_key"} DEEPSEEK_EXPLICIT_DETECTOR_NAMES = {"deepseekapikey", "deepseek_api_key"} QWEN_EXPLICIT_DETECTOR_NAMES = {"qwendashscope", "qwen_dashscope"} KIMI_EXPLICIT_DETECTOR_NAMES = {"kimimoonshot", "moonshotai"} QWEN_CONTEXT_REGEX = re.compile( r"(?:DASHSCOPE_API_KEY|QWEN_API_KEY|dashscope|qwen|model[_-]?studio|bailian)", re.IGNORECASE, ) DEEPSEEK_CONTEXT_REGEX = re.compile(r"(?:DEEPSEEK_API_KEY|deepseek|api\.deepseek\.com)", re.IGNORECASE) KIMI_CONTEXT_REGEX = re.compile( r"(?:MOONSHOT_API_KEY|KIMI_API_KEY|api\.moonshot\.(?:ai|cn)|platform\.kimi\.(?:ai|com))", re.IGNORECASE, ) AMBIGUOUS_PROVIDER_HINT = "ambiguous_qwen_deepseek" AMBIGUOUS_GENERIC_SK_HINT = "ambiguous_generic_sk" GENERIC_SK_PROVIDERS = {"qwen", "deepseek", "kimi", "zai"} EXPLICIT_ASSIGNMENT_HINT_SOURCE = "explicit_assignment" def ensure_files(): ensure_output_files([CHECKED_FILE, RESULTS_FILE, *STATUS_FILES.values()]) recover_status_transaction(CHECKED_FILE, STATUS_FILES) def iter_candidate_decisions(input_file, plain_files): detector_names = ["DeepSeek", "DeepSeekApiKey", "DeepSeek_API_Key", "CustomRegex"] for item in iter_findings(input_file, detector_names): finding = item.get("finding") or {} if not finding_has_deepseek_detector(finding): continue key = item.get("credential_secret_text") or item["raw"] if key and DEEPSEEK_REGEX.fullmatch(key): hint = combined_provider_routing_hint(key, finding_provider_routing_hint(finding)) if provider_routing_database_failed(): raise RuntimeError("provider routing evidence lookup failed closed") yield key, item["source"], finding, hint def extract_candidates(input_file, plain_files): for key, source, finding, hint in iter_candidate_decisions(input_file, plain_files): if hint == "deepseek": yield key, source, finding def route_rejection_result(hint): normalized = str(hint or "missing").strip().lower() return { "status": "NO_CONTEXT", "routing_hint": normalized, "message": f"candidate is not safely attributable to DeepSeek; routing_hint={normalized}", } def finding_detector_names(finding): if not isinstance(finding, dict): return set() extra = finding.get("ExtraData") if isinstance(finding.get("ExtraData"), dict) else {} names = { str(finding.get("DetectorName") or finding.get("detector") or "").strip().lower(), str(extra.get("name") or "").strip().lower(), } return {name for name in names if name} def finding_has_deepseek_detector(finding): return bool(finding_detector_names(finding) & DEEPSEEK_DETECTOR_NAMES) def finding_has_explicit_detector(finding, detector_names): return bool(finding_detector_names(finding) & set(detector_names)) def finding_provider_routing_hint(finding): if not isinstance(finding, dict): return "" context = finding.get("ScannerContext") if isinstance(finding.get("ScannerContext"), dict) else {} persisted_hint = context.get("provider_hint") if ( context.get("provider_hint_source") == EXPLICIT_ASSIGNMENT_HINT_SOURCE and persisted_hint in (*GENERIC_SK_PROVIDERS, AMBIGUOUS_PROVIDER_HINT, AMBIGUOUS_GENERIC_SK_HINT) ): return persisted_hint parts = [] for key in ("nearby", "file"): if context.get(key): parts.append(str(context.get(key))) metadata = finding.get("SourceMetadata") if isinstance(finding.get("SourceMetadata"), dict) else {} data = metadata.get("Data") if isinstance(metadata.get("Data"), dict) else {} for details in data.values(): if not isinstance(details, dict): continue for key in ("file", "repository", "repo", "link", "image"): if details.get(key): parts.append(str(details.get(key))) text = "\n".join(parts) evidence = set() if QWEN_CONTEXT_REGEX.search(text) or finding_has_explicit_detector(finding, QWEN_EXPLICIT_DETECTOR_NAMES): evidence.add("qwen") if DEEPSEEK_CONTEXT_REGEX.search(text) or finding_has_explicit_detector(finding, DEEPSEEK_EXPLICIT_DETECTOR_NAMES): evidence.add("deepseek") if KIMI_CONTEXT_REGEX.search(text) or finding_has_explicit_detector(finding, KIMI_EXPLICIT_DETECTOR_NAMES): evidence.add("kimi") if persisted_hint == AMBIGUOUS_PROVIDER_HINT: evidence.update(("qwen", "deepseek")) elif persisted_hint == AMBIGUOUS_GENERIC_SK_HINT: evidence.update(GENERIC_SK_PROVIDERS) elif persisted_hint in GENERIC_SK_PROVIDERS: evidence.add(persisted_hint) if len(evidence) > 1: return AMBIGUOUS_PROVIDER_HINT if evidence == {"qwen", "deepseek"} else AMBIGUOUS_GENERIC_SK_HINT return next(iter(evidence)) if evidence else "" def finding_has_ambiguous_provider_hint(finding): return finding_provider_routing_hint(finding) in (AMBIGUOUS_PROVIDER_HINT, AMBIGUOUS_GENERIC_SK_HINT) def finding_looks_like_qwen_context(finding): return finding_provider_routing_hint(finding) == "qwen" def check_key(key, proxy, timeout): url = "https://api.deepseek.com/user/balance" headers = {"Authorization": f"Bearer {key}"} try: response = requests.get(url, headers=headers, proxies=proxy, timeout=timeout) except requests.RequestException as exc: return {"status": "NETWORK", "message": str(exc)} if response.status_code == 200: data = response.json() balance_infos = data.get("balance_infos", []) total_usd = 0.0 for balance in balance_infos: amount = float(balance.get("total_balance", "0") or 0) currency = balance.get("currency", "USD") if currency == "CNY": amount *= 0.14 total_usd += amount available = bool(data.get("is_available", False)) status = "VALID" if available and total_usd > 0 else "NO_BALANCE" return { "status": status, "authenticated": True, "available": available, "balance_usd": round(total_usd, 4), "message": f"available={available}; balance=${total_usd:.4f}", } status = classify_common_http_status(response.status_code) return {"status": status, "http_status": response.status_code, "message": request_error_message(response)} def write_result(key, result, source, finding): write_keycheck_event(SERVICE, RESULTS_FILE, key, result, source, finding, "DeepSeek") commit_status_transaction( CHECKED_FILE, STATUS_FILES, key, result["status"], result.get("message", ""), source, ) record_validation_result(SERVICE, key, result, source, finding, "DeepSeek") def parse_args(): parser = argparse.ArgumentParser(description="DeepSeek key checker") parser.add_argument("--input", default=INPUT_FILE) parser.add_argument("--plain", action="append", default=[]) parser.add_argument("--proxy-file", default=PROXY_FILE) parser.add_argument("--timeout", type=int, default=20) parser.add_argument("--max-keys", type=int, default=0) parser.add_argument("--retry-network", action="store_true") parser.add_argument("--retry-limited", action="store_true") parser.add_argument("--retry-unknown", action="store_true") parser.add_argument("--retry-no-balance", action="store_true") parser.add_argument("--retry-valid", action="store_true") parser.add_argument("--recheck-all", action="store_true") return parser.parse_args() def main(): require_provider_authority(SERVICE) args = parse_args() ensure_files() proxy_cycler = load_proxies(args.proxy_file) checked = load_checked_statuses(CHECKED_FILE) known = load_known_keys(CHECKED_FILE, STATUS_FILES) retry_statuses = set() if args.retry_network: retry_statuses.add("NETWORK") if args.retry_limited: retry_statuses.add("LIMITED") if args.retry_unknown: retry_statuses.update({"UNKNOWN", "NO_CONTEXT"}) if args.retry_no_balance: retry_statuses.add("NO_BALANCE") if args.retry_valid: retry_statuses.add("VALID") processed = 0 skipped = 0 postgres_mode = keycheck_input_mode() == "postgres" for key, source, finding, routing_hint in iter_candidate_decisions(args.input, args.plain): route_rejected = routing_hint != "deepseek" ambiguous_route = routing_hint in (AMBIGUOUS_PROVIDER_HINT, AMBIGUOUS_GENERIC_SK_HINT) if route_rejected and not postgres_mode: skipped += 1 continue if not route_rejected and should_skip_key(key, checked, known, args, retry_statuses, service=SERVICE, source=source, finding=finding, detector="DeepSeek"): skipped += 1 continue if args.max_keys and processed >= args.max_keys: break processed += 1 print(f"\n[{processed}] DeepSeek candidate {mask_secret(key)} from {source}") if route_rejected and ambiguous_route: proxy = next(proxy_cycler) if proxy_cycler else None result = resolve_provider_key( key, finding, proxy, args.timeout, hint=routing_hint, origin_service=SERVICE, ) elif route_rejected: result = route_rejection_result(routing_hint) else: proxy = next(proxy_cycler) if proxy_cycler else None result = check_key(key, proxy, args.timeout) print(f" STATUS: {result['status']} | {result.get('message', '')[:200]}") write_result(key, result, source, finding) known.add(key) checked[key] = result["status"] print(f"\nDone. Processed={processed}, skipped={skipped}, results={RESULTS_FILE}") if __name__ == "__main__": main()