Files
any-auto-register/api/integrations.py
2026-04-07 13:25:56 +08:00

169 lines
5.9 KiB
Python

from __future__ import annotations
from typing import Optional
from fastapi import APIRouter
from pydantic import BaseModel, Field
from sqlmodel import Session, select
from core.base_platform import Account, AccountStatus
from core.db import AccountModel, engine
from services.external_apps import install, list_status, start, start_all, stop, stop_all, uninstall
from services.chatgpt_sync import backfill_chatgpt_account_to_cpa, get_cliproxy_sync_state
router = APIRouter(prefix="/integrations", tags=["integrations"])
class BackfillRequest(BaseModel):
platforms: list[str] = Field(default_factory=lambda: ["grok", "kiro"])
account_ids: list[int] = Field(default_factory=list)
pending_only: bool = False
status: Optional[str] = None
email: Optional[str] = None
def _to_account(model: AccountModel) -> Account:
return Account(
platform=model.platform,
email=model.email,
password=model.password,
user_id=model.user_id,
region=model.region,
token=model.token,
status=AccountStatus(model.status),
extra=model.get_extra(),
)
@router.get("/services")
def get_services():
return {"items": list_status()}
@router.post("/services/start-all")
def start_all_services():
return {"items": start_all()}
@router.post("/services/stop-all")
def stop_all_services():
return {"items": stop_all()}
@router.post("/services/{name}/start")
def start_service(name: str):
return start(name)
@router.post("/services/{name}/install")
def install_service(name: str):
return install(name)
@router.post("/services/{name}/uninstall")
def uninstall_service(name: str):
return uninstall(name)
@router.post("/services/{name}/stop")
def stop_service(name: str):
return stop(name)
@router.post("/backfill")
def backfill_integrations(body: BackfillRequest):
summary = {"total": 0, "success": 0, "failed": 0, "skipped": 0, "items": []}
targets = set(body.platforms or [])
with Session(engine) as s:
q = select(AccountModel)
if body.account_ids:
q = q.where(AccountModel.id.in_(body.account_ids))
if targets:
q = q.where(AccountModel.platform.in_(targets))
elif targets:
q = q.where(AccountModel.platform.in_(targets))
else:
return summary
if body.status:
q = q.where(AccountModel.status == body.status)
if body.email:
q = q.where(AccountModel.email.contains(body.email))
rows = s.exec(q).all()
if body.pending_only:
rows = [
row for row in rows
if row.platform != "chatgpt"
or str(get_cliproxy_sync_state(row).get("remote_state") or "").strip().lower() == "not_found"
]
if any(row.platform == "grok" for row in rows):
from services.grok2api_runtime import ensure_grok2api_ready
ok, msg = ensure_grok2api_ready()
if not ok:
return {
"total": 0,
"success": 0,
"failed": 0,
"items": [{"platform": "grok", "email": "", "results": [{"name": "grok2api", "ok": False, "msg": msg}]}],
}
for row in rows:
item = {"platform": row.platform, "email": row.email, "results": []}
try:
results = []
if row.platform == "chatgpt":
outcome = backfill_chatgpt_account_to_cpa(row, session=s, commit=True)
ok = bool(outcome.get("ok"))
skipped = bool(outcome.get("skipped"))
results.extend(outcome.get("results") or [])
if not results:
results.append({"name": "CLIProxyAPI", "ok": ok, "msg": outcome.get("message", "")})
if skipped:
summary["skipped"] += 1
elif ok:
summary["success"] += 1
else:
summary["failed"] += 1
elif row.platform == "grok":
from core.config_store import config_store
from platforms.grok.grok2api_upload import upload_to_grok2api
account = _to_account(row)
api_url = str(config_store.get("grok2api_url", "") or "").strip() or "http://127.0.0.1:8011"
app_key = str(config_store.get("grok2api_app_key", "") or "").strip() or "grok2api"
ok, msg = upload_to_grok2api(account, api_url=api_url, app_key=app_key)
results.append({"name": "grok2api", "ok": ok, "msg": msg})
elif row.platform == "kiro":
from core.config_store import config_store
from platforms.kiro.account_manager_upload import upload_to_kiro_manager
account = _to_account(row)
configured_path = str(config_store.get("kiro_manager_path", "") or "").strip() or None
ok, msg = upload_to_kiro_manager(account, path=configured_path)
results.append({"name": "Kiro Manager", "ok": ok, "msg": msg})
if not results:
item["results"].append({"name": "skip", "ok": False, "msg": "未配置对应导入目标"})
summary["failed"] += 1
else:
item["results"] = results
if row.platform != "chatgpt":
if all(r.get("ok") for r in results):
summary["success"] += 1
else:
summary["failed"] += 1
except Exception as e:
s.rollback()
item["results"].append({"name": "error", "ok": False, "msg": str(e)})
summary["failed"] += 1
summary["items"].append(item)
summary["total"] += 1
return summary