#!/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()