Files

136 lines
6.3 KiB
Python
Executable File

#!/usr/bin/env python3
"""LobeHub Proxy — CLI-based, 601 accounts, rotation"""
import json, time, random, threading, subprocess, os
from http.server import HTTPServer, BaseHTTPRequestHandler
from pathlib import Path
from datetime import datetime
BASE_URL = "http://[REDACTED-IP]:3210"
ACCOUNTS_FILE = Path(r"C:\Users\User\lobehub_accounts.json")
CLI = r"C:\Users\User\AppData\Roaming\npm\node_modules\@lobehub\cli\dist\index.js"
PORT = 20140
MODELS = [
"openai/gpt-5.5","openai/gpt-5.4","openai/gpt-5.4-mini","openai/gpt-5.3-codex-spark",
"anthropic/claude-opus-4.8","anthropic/claude-opus-4.7","anthropic/claude-opus-4.6","anthropic/claude-opus-4.5",
"anthropic/claude-sonnet-5","anthropic/claude-sonnet-4.6","anthropic/claude-sonnet-4.5","anthropic/claude-haiku-4.5",
"deepseek/deepseek-v4-pro","deepseek/deepseek-v4-flash",
"z-ai/glm-5.2","z-ai/glm-5.1",
"moonshotai/kimi-k2.7-code","moonshotai/kimi-k2.6",
"qwen/qwen3.7-plus","qwen/qwen3.7-max",
]
pool_lock = threading.Lock()
accounts = []
account_index = 0
stats = {"total_requests": 0, "errors": 0, "started": datetime.now().isoformat()}
def load_accounts():
global accounts
with open(ACCOUNTS_FILE) as f:
raw = json.load(f)
with pool_lock:
accounts = [{"email": a["email"], "password": a["password"], "token": a.get("token",""),
"valid": bool(a.get("token","")), "last_used": None, "request_count": 0, "errors": 0} for a in raw]
print(f"[Pool] {len(accounts)} accounts, {sum(1 for a in accounts if a['valid'])} with tokens")
def generate_text(model, messages, max_tokens, token):
"""LobeHub CLI subprocess"""
prompt = messages[-1]["content"] if messages else ""
system = next((m["content"] for m in messages if m["role"] == "system"), "")
env = os.environ.copy()
env["LOBEHUB_JWT"] = token
env["LOBEHUB_SERVER"] = BASE_URL
env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0"
args = ["node", CLI, "generate", "text", prompt, "--model", model, "--max-tokens", str(max_tokens), "--stream"]
if system: args.extend(["--system", system])
try:
proc = subprocess.run(args, capture_output=True, text=True, timeout=120, env=env)
output = proc.stdout or proc.stderr or ""
result = ""
for line in output.split("\n"):
line = line.strip()
if not line: continue
if line.startswith("in_progress"): result += line[len("in_progress"):]
elif line.startswith("data: "): result += line[6:]
elif line in ("message_stop","end_turn","message_start","text_delta"): pass
elif line.startswith(("error_","id:","[","message_","end_")): pass
elif line == "undefined": pass
else: result += line
result = result.strip()
for a in ["message_stop","end_turn","message_start","text_delta"]: result = result.replace(a,"")
if result: return {"content": result.strip(), "success": True}
return {"error": output[:100], "success": False}
except subprocess.TimeoutExpired: return {"error": "Timeout", "success": False}
except Exception as e: return {"error": str(e), "success": False}
def get_next_account():
global account_index
with pool_lock:
valid = [a for a in accounts if a["valid"]]
if not valid: return None
for _ in range(min(20, len(accounts))):
account_index = (account_index + 1) % len(accounts)
if accounts[account_index]["valid"]:
accounts[account_index]["last_used"] = datetime.now().isoformat()
accounts[account_index]["request_count"] += 1
return accounts[account_index]
acc = random.choice(valid)
acc["last_used"] = datetime.now().isoformat()
acc["request_count"] += 1
return acc
class Proxy(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):
return self.headers.get("Authorization","") in ("Bearer local","local")
def do_GET(self):
if self.path == "/health":
with pool_lock: valid = sum(1 for a in accounts if a["valid"])
self._json({"status":"ok","accounts":{"total":len(accounts),"valid":valid},"models":len(MODELS),"backend":"lobehub-cli","stats":stats})
elif self.path == "/v1/models":
self._json({"object":"list","data":[{"id":m,"object":"model"} for m in MODELS]})
else: self._json({"error":"not found"},404)
def do_POST(self):
if self.path != "/v1/chat/completions": self._json({"error":"not found"},404); return
if not self._auth(): self._json({"error":"Unauthorized"},401); return
stats["total_requests"] += 1
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","openai/gpt-5.5")
messages = body.get("messages",[])
if not messages: self._json({"error":"messages required"},400); return
acc = get_next_account()
if not acc: self._json({"error":"No valid accounts"},503); return
result = generate_text(model, messages, body.get("max_tokens",4096), acc["token"])
if result["success"]:
self._json({
"id":f"lobehub-{int(time.time())}","object":"chat.completion","created":int(time.time()),
"model":model,"choices":[{"index":0,"message":{"role":"assistant","content":result["content"]},"finish_reason":"stop"}],
"usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0},
"_pool":{"account":acc["email"][:3]+"***","engine":"lobehub-cli"}
})
else:
stats["errors"] += 1; acc["errors"] += 1
self._json({"error":result.get("error","Generation failed")},500)
def log_message(self,f,*a): pass
# === START ===
load_accounts()
print(f"[LobeHub CLI Proxy] :{PORT} | {len(accounts)} accounts | Ready")
while True:
try: HTTPServer(("127.0.0.1",PORT), Proxy).serve_forever()
except Exception as e: print(f"[Crash] {e}"); time.sleep(3)