91 lines
3.3 KiB
Python
91 lines
3.3 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
BOSS 账号 API(需要登录):
|
||
- POST /api/accounts -> 前台添加账号时绑定到指定电脑
|
||
- POST /api/accounts/check -> 提交环境名称,自动派发 check_login 任务
|
||
- GET /api/accounts -> 查询所有账号登录状态
|
||
- GET /api/accounts/{worker_id} -> 查询指定 Worker 的账号状态
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from typing import Optional
|
||
|
||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||
|
||
from common.protocol import TaskStatus, TaskType
|
||
from server.models import AccountBindRequest, CheckLoginRequest, TaskCreate
|
||
from server.core.worker_manager import worker_manager
|
||
from server.core.task_dispatcher import task_dispatcher
|
||
from server import db
|
||
from server.api.deps import require_auth, parse_body
|
||
|
||
router = APIRouter(prefix="/api/accounts", tags=["accounts"], dependencies=[Depends(require_auth)])
|
||
|
||
|
||
@router.post("", status_code=201)
|
||
async def bind_account(request: Request):
|
||
"""前台添加账号:保存账号环境与电脑绑定关系。"""
|
||
req = AccountBindRequest(**(await parse_body(request)))
|
||
db.bind_account_to_worker(worker_id=req.worker_id, browser_name=req.browser_name)
|
||
return {"message": f"账号绑定已保存: {req.browser_name} -> {req.worker_id}"}
|
||
|
||
|
||
@router.post("/check", status_code=201)
|
||
async def check_login(request: Request):
|
||
"""
|
||
前端提交 browser_name(可选 worker_id)→ 自动派发 check_login 任务。
|
||
"""
|
||
req = CheckLoginRequest(**(await parse_body(request)))
|
||
worker_id = req.worker_id
|
||
if not worker_id:
|
||
bind = db.get_account_by_name(req.browser_name)
|
||
if not bind:
|
||
raise HTTPException(
|
||
status_code=400,
|
||
detail=f"未找到账号绑定关系,请先调用 POST /api/accounts 绑定: {req.browser_name}",
|
||
)
|
||
worker_id = bind.get("worker_id")
|
||
|
||
if not worker_manager.is_online(worker_id):
|
||
raise HTTPException(status_code=503, detail=f"Worker {worker_id} 不在线")
|
||
|
||
task_req = TaskCreate(
|
||
task_type=TaskType.CHECK_LOGIN,
|
||
worker_id=worker_id,
|
||
account_name=req.browser_name,
|
||
params={"account_name": req.browser_name},
|
||
)
|
||
task = task_dispatcher.create_task(task_req)
|
||
|
||
ws = worker_manager.get_ws(worker_id)
|
||
if not ws:
|
||
task.status = TaskStatus.FAILED
|
||
task.error = "Worker WebSocket 连接不存在"
|
||
raise HTTPException(status_code=503, detail="Worker WebSocket 连接不存在")
|
||
|
||
success = await task_dispatcher.dispatch(task, ws.send_json)
|
||
if not success:
|
||
raise HTTPException(status_code=503, detail=f"任务派发失败: {task.error}")
|
||
|
||
worker_manager.set_current_task(worker_id, task.task_id)
|
||
|
||
return {
|
||
"message": f"检测任务已派发,环境: {req.browser_name},目标: {worker_id}",
|
||
"task_id": task.task_id,
|
||
"worker_id": worker_id,
|
||
}
|
||
|
||
|
||
@router.get("")
|
||
async def list_accounts(worker_id: Optional[str] = None):
|
||
"""查询 BOSS 账号登录状态列表。"""
|
||
if worker_id:
|
||
return db.get_accounts_by_worker(worker_id)
|
||
return db.get_all_accounts()
|
||
|
||
|
||
@router.get("/{worker_id}")
|
||
async def get_worker_accounts(worker_id: str):
|
||
"""查询指定 Worker 的所有账号状态。"""
|
||
return db.get_accounts_by_worker(worker_id)
|