#!/usr/bin/env python3
"""Test an API key against 35+ providers to identify which one it belongs to.

Usage:
    python3 test_apikey.py 'sk-xxxx'

Exit 0 if at least one provider authenticates successfully.
Exit 1 if all providers reject the key.
"""
import urllib.request
import urllib.error
import json
import ssl
import sys

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

key = sys.argv[1] if len(sys.argv) > 1 else ""

if not key:
    print("Usage: python3 test_apikey.py <API_KEY>")
    sys.exit(2)

# fmt: off
endpoints = [
    # Major Western providers
    ("OpenAI",              "https://api.openai.com/v1/models"),
    ("Anthropic",           "https://api.anthropic.com/v1/models"),
    ("OpenRouter",          "https://openrouter.ai/api/v1/models"),
    ("Groq",                "https://api.groq.com/v1/models"),
    ("Together",            "https://api.together.xyz/v1/models"),
    ("Fireworks",           "https://api.fireworks.ai/v1/models"),
    ("XAI/Grok",            "https://api.x.ai/v1/models"),
    ("Perplexity",          "https://api.perplexity.ai/models"),
    ("Mistral",             "https://api.mistral.ai/v1/models"),
    ("Cohere",              "https://api.cohere.ai/v1/models"),
    ("AI21",                "https://api.ai21.com/studio/v1/models"),
    ("DeepInfra",           "https://api.deepinfra.com/v1/models"),
    ("Cerebras",            "https://api.cerebras.ai/v1/models"),
    ("SambaNova",           "https://api.sambanova.ai/v1/models"),
    ("Replicate",           "https://api.replicate.com/v1/models"),
    ("Hyperbolic",          "https://api.hyperbolic.xyz/v1/models"),
    ("AIMLAPI",             "https://api.aimlapi.com/v1/models"),
    ("OctoAI",              "https://text.octoai.run/v1/models"),

    # Chinese providers
    ("DeepSeek",            "https://api.deepseek.com/v1/models"),
    ("SiliconFlow/硅基流动",  "https://api.siliconflow.cn/v1/models"),
    ("Kimi/Moonshot",       "https://api.moonshot.cn/v1/models"),
    ("MiniMax",             "https://api.minimax.chat/v1/models"),
    ("StepFun/阶跃",         "https://api.stepfun.com/v1/models"),
    ("ZhipuAI/智谱",        "https://open.bigmodel.cn/api/paas/v4/models"),
    ("Baichuan/百川",        "https://api.baichuan-ai.com/v1/models"),
    ("DashScope/阿里",       "https://dashscope.aliyuncs.com/compatible-mode/v1/models"),
    ("01.AI/零一",           "https://api.lingyiwanwu.com/v1/models"),
    ("SenseNova/商汤",       "https://api.sensenova.cn/v1/models"),
    ("Xunfei/讯飞",          "https://spark-api-open.xf-yun.com/v1/models"),
    ("Tencent/腾讯混元",      "https://api.hunyuan.cloud.tencent.com/v1/models"),
    ("ByteDance/字节豆包",    "https://ark.cn-beijing.volces.com/api/v3/models"),
    ("Infinite/无问芯穹",     "https://api.infini-ai.com/v1/models"),
    ("Qiniu/七牛云",         "https://api.qnaigc.com/v1/models"),

    # Others
    ("NVIDIA NIM",          "https://integrate.api.nvidia.com/v1/models"),
    ("Voyage AI",           "https://api.voyageai.com/v1/models"),
    ("Cloudflare AI",       "https://api.cloudflare.com/client/v4/accounts/me/ai/models/search"),
]
# fmt: on

found = False

for name, url in endpoints:
    req = urllib.request.Request(url, headers={"Authorization": f"Bearer {key}"})
    try:
        with urllib.request.urlopen(req, timeout=10, context=ctx) as resp:
            data = json.loads(resp.read())

            # Normalize: different providers use different keys
            models = (
                data.get("data")
                or data.get("models")
                or data.get("body")
                or data.get("result")
                or []
            )

            if isinstance(models, list) and len(models) > 0:
                if not found:
                    print(f"\n{'='*60}")
                    print(f"MATCHES FOUND")
                    print(f"{'='*60}")
                found = True
                print(f"\n✅ {name}: 认证成功 ({len(models)} 个模型)")
                for m in sorted([m.get("id", str(m)) for m in models]):
                    print(f"     {m}")
    except urllib.error.HTTPError as e:
        body = e.read().decode(errors="replace")
        # 401/403 are expected for wrong providers — only surface unexpected errors
        if e.code not in (401, 403):
            try:
                err = json.loads(body)
                msg = err.get("error", {}).get("message", str(err))
            except json.JSONDecodeError:
                msg = body[:120]
            print(f"  {name}: HTTP {e.code} - {msg}")
    except Exception:
        pass  # Timeout/connection errors are noise — skip silently

if not found:
    print("❌ 该 API Key 在所有测试的平台上均认证失败")
    print(f"\n已测试 {len(endpoints)} 个平台")
    print("\n可能原因:")
    print("  1. Key 已过期或被撤销")
    print("  2. Key 来自未覆盖的小众平台（可手动添加 endpoint）")
    print("  3. Key 格式不完整（被截断）")
    print("  4. 网络不通（服务器在国内需检查城墙）")
    sys.exit(1)

sys.exit(0)
