Files
autoreg-skills-max/skills/lobehub-pool/scripts/gateway.py

141 lines
5.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""LobeHub API Gateway — 601 ключей, 20 моделей, closerouter backend"""
import json, time, httpx, secrets
from http.server import HTTPServer, BaseHTTPRequestHandler
from pathlib import Path
BASE_URL = "http://[REDACTED-IP]:3210"
BACKEND = "https://api.closerouter.dev/v1"
BACKEND_KEY = "closerouter_G7GChTmljnOmIlJaD92YKaIzLHeMjErvbrKEBRxhsCY"
PORT = 20141
KEYS_FILE = Path(r"C:\Users\User\lobehub_api_keys.json")
TOKEN_CACHE = {} # email → token cache
MODELS = [
"claude-opus-4.8","claude-opus-4.7","claude-opus-4.6","claude-opus-4.5",
"claude-sonnet-5","claude-sonnet-4.6","claude-sonnet-4.5","claude-haiku-4.5",
"gpt-5.5","gpt-5.4","gpt-5.4-mini","gpt-5.3-codex-spark",
"deepseek-v4-pro","deepseek-v4-flash",
"glm-5.2","glm-5.1","kimi-k2.7-code","kimi-k2.6",
"qwen-3.7-plus","qwen-3.7-max",
]
MODEL_PREFIX = {
"claude": "anthropic/", "gpt": "openai/", "deepseek": "deepseek/",
"glm": "z-ai/", "kimi": "moonshotai/", "qwen": "qwen/",
}
with open(KEYS_FILE) as f:
KEY_DATA = json.load(f)
KEYS = {k['api_key']: k for k in KEY_DATA['keys']}
print(f"[Gateway] {len(KEYS)} keys | {len(MODELS)} models | closerouter backend")
def resolve_model(model):
for prefix, provider in MODEL_PREFIX.items():
if model.startswith(prefix):
return f"{provider}{model}"
return model
def get_token(email, pw):
cache_key = f"{email}:{pw}"
if cache_key in TOKEN_CACHE:
cached = TOKEN_CACHE[cache_key]
if cached['expires'] > time.time():
return cached['token']
try:
r = httpx.post(f"{BASE_URL}/api/auth/sign-in/email",
json={"email": email, "password": pw},
headers={"Origin": BASE_URL, "Referer": f"{BASE_URL}/signin"},
timeout=10)
if r.status_code == 200 and "token" in r.json():
token = [REDACTED])["token"]
TOKEN_CACHE[cache_key] = {"token": token, "expires": time.time() + 3600}
return token
except:
pass
return None
class Gateway(BaseHTTPRequestHandler):
def _json(self, data, status=200):
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
self.wfile.write(json.dumps(data, ensure_ascii=False).encode())
def _auth(self):
auth = self.headers.get("Authorization", "")
if not auth.startswith("Bearer "):
return None
key = auth[7:]
if key == "local":
return {"email": "local", "password": "local"}
if key in KEYS:
return KEYS[key]
if ":" in key and "@" in key:
e, p = key.split(":", 1)
return {"email": e, "password": p}
return None
def do_GET(self):
if self.path == "/health":
self._json({"status": "ok", "keys": len(KEYS), "models": len(MODELS), "backend": "closerouter"})
elif self.path == "/v1/models":
self._json({"object": "list", "data": [{"id": m, "object": "model"} for m in MODELS]})
elif self.path == "/keys/stats":
self._json({"total": len(KEYS), "cached_tokens": len(TOKEN_CACHE)})
else:
self._json({"error": "not found"}, 404)
def do_POST(self):
if self.path == "/v1/chat/completions":
self._chat()
elif self.path == "/v1/embeddings":
self._json({"error": "embeddings not supported"}, 400)
else:
self._json({"error": "not found"}, 404)
def _chat(self):
account = self._auth()
if not account:
self._json({"error": "Unauthorized. Use Bearer <api_key> or Bearer local"}, 401)
return
try:
body = json.loads(self.rfile.read(int(self.headers.get("Content-Length", 0))))
except:
self._json({"error": "Invalid JSON"}, 400); return
model = body.get("model", "deepseek-v4-pro")
messages = body.get("messages", [])
if not messages:
self._json({"error": "messages required"}, 400); return
backend_model = resolve_model(model)
try:
r = httpx.post(f"{BACKEND}/chat/completions",
headers={"Authorization": f"Bearer {BACKEND_KEY}", "Content-Type": "application/json"},
json={
"model": backend_model,
"messages": messages,
"max_tokens": body.get("max_tokens", 4096),
"stream": False,
},
timeout=180)
if r.status_code == 200:
self._json(r.json())
else:
self._json({"error": f"Backend {r.status_code}: {r.text[:300]}"}, 500)
except Exception as e:
self._json({"error": str(e)}, 500)
def log_message(self, f, *a):
pass
print(f"[Gateway] :{PORT} | {len(KEYS)} keys | 20 models | closerouter")
while True:
try:
HTTPServer(("127.0.0.1", PORT), Gateway).serve_forever()
except Exception as e:
print(f"[Gateway] Restart: {e}")
time.sleep(3)