- 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)
86 lines
3.3 KiB
Python
86 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Test NewAPI channels and report results.
|
|
|
|
Tests channels concurrently for speed (default: 8 workers).
|
|
By default tests all channels with ID >= 6 (the ones we manage).
|
|
|
|
Filtering options:
|
|
--ids 1,2,3 Test only the given channel IDs
|
|
--name keyword Test only channels whose name contains keyword
|
|
--list Just list matching channels, don't test
|
|
"""
|
|
|
|
import argparse
|
|
|
|
from newapi_client import list_channels, test_channels_concurrent
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Test NewAPI channels")
|
|
parser.add_argument("--min-id", type=int, default=6,
|
|
help="Minimum channel ID to test (default: 6)")
|
|
parser.add_argument("--workers", type=int, default=8,
|
|
help="Concurrent test workers (default: 8)")
|
|
parser.add_argument("--ids", type=str, default=None,
|
|
help="Comma-separated channel IDs to test (overrides --min-id)")
|
|
parser.add_argument("--name", type=str, default=None,
|
|
help="Only test channels whose name contains this substring")
|
|
parser.add_argument("--list", action="store_true",
|
|
help="List matching channels without testing")
|
|
args = parser.parse_args()
|
|
|
|
channels = list_channels()
|
|
|
|
# ── Filter ──────────────────────────────────────────────────
|
|
if args.ids:
|
|
wanted = {int(x.strip()) for x in args.ids.split(",") if x.strip()}
|
|
to_test = [ch for ch in channels if ch["id"] in wanted]
|
|
else:
|
|
to_test = [ch for ch in channels if ch["id"] >= args.min_id]
|
|
|
|
if args.name:
|
|
needle = args.name.lower()
|
|
to_test = [ch for ch in to_test if needle in ch.get("name", "").lower()]
|
|
|
|
# ── List-only mode ──────────────────────────────────────────
|
|
if args.list:
|
|
print(f"Found {len(to_test)} channel(s):\n")
|
|
for ch in to_test:
|
|
first_model = ch.get("models", "").split(",")[0]
|
|
print(f" [ID={ch['id']:2d}] {ch.get('name','?'):30s} (model: {first_model})")
|
|
return
|
|
|
|
print(f"Testing {len(to_test)} channels (workers={args.workers})...\n")
|
|
|
|
# Build a quick lookup for names/models
|
|
ch_map = {ch["id"]: ch for ch in to_test}
|
|
test_ids = [ch["id"] for ch in to_test]
|
|
|
|
results = test_channels_concurrent(test_ids, max_workers=args.workers)
|
|
|
|
# Print results
|
|
for cid, success, msg, _ in results:
|
|
ch = ch_map.get(cid, {})
|
|
name = ch.get("name", "?")
|
|
first_model = ch.get("models", "").split(",")[0]
|
|
status = "✅" if success else "❌"
|
|
print(f" [ID={cid:2d}] {name:30s} (model: {first_model}) {status} {msg[:80]}")
|
|
|
|
# Summary
|
|
ok = sum(1 for _, s, _, _ in results if s)
|
|
fail = sum(1 for _, s, _, _ in results if not s)
|
|
print(f"\n=== Summary ===")
|
|
print(f" ✅ Working: {ok}")
|
|
print(f" ❌ Failed: {fail}")
|
|
|
|
if fail > 0:
|
|
print("\n=== Failed channels ===")
|
|
for cid, success, msg, _ in results:
|
|
if not success:
|
|
name = ch_map.get(cid, {}).get("name", "?")
|
|
print(f" ID={cid:2d} {name:30s} {msg[:100]}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|