Files

163 lines
5.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import shutil
from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException
from app.core.auth import verify_app_key
from app.core.config import config
from app.core.logger import logger, LOG_DIR
from app.services.grok.services.model import ModelService
from app.services.token import get_token_manager
from app.core.storage import (
get_storage as get_storage_backend,
LocalStorage,
RedisStorage,
SQLStorage,
)
from app.services.cf_refresh.scheduler import refresh_once
router = APIRouter()
def _clear_log_dir() -> dict:
"""清空日志目录内容,保留目录本身。"""
log_dir = Path(LOG_DIR)
log_dir.mkdir(parents=True, exist_ok=True)
deleted_files = 0
deleted_dirs = 0
released_bytes = 0
for child in log_dir.iterdir():
try:
if child.is_file() or child.is_symlink():
try:
released_bytes += child.stat().st_size
except OSError:
pass
child.unlink(missing_ok=True)
deleted_files += 1
continue
if child.is_dir():
for nested in child.rglob("*"):
if nested.is_file():
try:
released_bytes += nested.stat().st_size
except OSError:
pass
shutil.rmtree(child, ignore_errors=False)
deleted_dirs += 1
except FileNotFoundError:
continue
return {
"log_dir": str(log_dir),
"deleted_files": deleted_files,
"deleted_dirs": deleted_dirs,
"released_bytes": released_bytes,
}
@router.get("/verify", dependencies=[Depends(verify_app_key)])
async def admin_verify():
"""验证后台访问密钥(app_key)"""
return {"status": "success"}
@router.get("/config", dependencies=[Depends(verify_app_key)])
async def get_config():
"""获取当前配置"""
# 暴露原始配置字典
return config._config
@router.post("/config", dependencies=[Depends(verify_app_key)])
async def update_config(data: dict):
"""更新配置"""
try:
await config.update(data)
return {"status": "success", "message": "配置已更新"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/config/cf-refresh", dependencies=[Depends(verify_app_key)])
async def refresh_cf_clearance():
"""手动刷新 cf_clearance。"""
try:
success = await refresh_once()
if not success:
raise HTTPException(status_code=500, detail="刷新失败,请检查 FlareSolverr、代理和网络配置")
proxy_conf = (config._config or {}).get("proxy", {}) if isinstance(config._config, dict) else {}
return {
"status": "success",
"message": "CF Clearance 已刷新",
"data": {
"browser": proxy_conf.get("browser") or "",
"user_agent": proxy_conf.get("user_agent") or "",
"has_cf_clearance": bool(proxy_conf.get("cf_clearance")),
},
}
except HTTPException:
raise
except Exception as e:
logger.error(f"Manual cf_clearance refresh failed: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/config/clear-logs", dependencies=[Depends(verify_app_key)])
async def clear_logs():
"""清空日志目录。"""
try:
result = _clear_log_dir()
return {
"status": "success",
"message": "日志文件夹已清空",
"data": result,
}
except Exception as e:
logger.error(f"Clear log directory failed: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/model-routing/meta", dependencies=[Depends(verify_app_key)])
async def get_model_routing_meta():
"""获取模型池路由界面所需的模型与池元数据。"""
token_mgr = await get_token_manager()
pool_names = set(token_mgr.pools.keys())
pool_names.update({"ssoBasic", "ssoSuper"})
models = [
{
"id": item.model_id,
"display_name": item.display_name,
}
for item in ModelService.list()
]
return {
"models": models,
"pools": sorted(pool_names),
}
@router.get("/storage", dependencies=[Depends(verify_app_key)])
async def admin_get_storage():
"""获取当前存储模式"""
storage_type = os.getenv("SERVER_STORAGE_TYPE", "").lower()
if not storage_type:
storage = get_storage_backend()
if isinstance(storage, LocalStorage):
storage_type = "local"
elif isinstance(storage, RedisStorage):
storage_type = "redis"
elif isinstance(storage, SQLStorage):
storage_type = {
"mysql": "mysql",
"mariadb": "mysql",
"postgres": "pgsql",
"postgresql": "pgsql",
"pgsql": "pgsql",
}.get(storage.dialect, storage.dialect)
return {"type": storage_type or "local"}