Ai_GirlFriend/lover/main.py
2026-02-03 17:13:56 +08:00

125 lines
3.9 KiB
Python

from fastapi import FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
import logging
import dashscope
from pathlib import Path
from contextlib import asynccontextmanager
from lover.routers import config as config_router
from lover.routers import lover as lover_router
from lover.routers import user_basic as user_basic_router
from lover.response import ApiResponse
from lover.routers import outfit as outfit_router
from lover.routers import chat as chat_router
from lover.routers import voice_call as voice_call_router
from lover.routers import dance as dance_router
from lover.routers import dynamic as dynamic_router
from lover.routers import sing as sing_router
from lover.routers import friend as friend_router
from lover.routers import msg as msg_router
from lover.routers import huanxin as huanxin_router
from lover.routers import user as user_router
from lover.routers import music_library as music_library_router
from lover.task_queue import start_sing_workers
from lover.config import settings
# 初始化 DashScope API Key
if settings.DASHSCOPE_API_KEY:
dashscope.api_key = settings.DASHSCOPE_API_KEY
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动时执行
logger = logging.getLogger("main")
logger.info("应用启动中...")
start_sing_workers()
logger.info("应用启动完成")
yield
# 关闭时执行
logger.info("应用关闭")
app = FastAPI(title="LOVER API", lifespan=lifespan)
# 创建 TTS 文件目录
tts_dir = Path("public/tts")
tts_dir.mkdir(parents=True, exist_ok=True)
# 挂载静态文件服务(用于提供 TTS 音频文件)
app.mount("/tts", StaticFiles(directory=str(tts_dir)), name="tts")
app.add_middleware(
CORSMiddleware,
allow_origins=[
"http://localhost",
"http://localhost:5173",
"http://localhost:8080",
"http://127.0.0.1",
"http://127.0.0.1:5173",
"http://127.0.0.1:8080",
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(config_router.router)
app.include_router(lover_router.router)
app.include_router(user_basic_router.router)
app.include_router(outfit_router.router)
app.include_router(chat_router.router)
app.include_router(voice_call_router.router)
app.include_router(dance_router.router)
app.include_router(dynamic_router.router)
app.include_router(sing_router.router)
app.include_router(friend_router.router)
app.include_router(msg_router.router)
app.include_router(huanxin_router.router)
app.include_router(user_router.router)
app.include_router(music_library_router.router)
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
# 统一错误响应结构,便于前端通过 code 判定
detail = exc.detail
msg = detail if isinstance(detail, str) else str(detail)
return JSONResponse(
status_code=exc.status_code,
content={"code": exc.status_code, "msg": msg, "data": None},
)
@app.exception_handler(Exception)
async def generic_exception_handler(request: Request, exc: Exception):
logging.exception("Unhandled error", exc_info=exc)
return JSONResponse(
status_code=500,
content={"code": 500, "msg": "服务器内部错误", "data": None},
)
@app.get("/health", response_model=ApiResponse[dict])
async def health():
return ApiResponse(code=1, msg="ok", data={"status": "ok"})
@app.get("/debug/auth")
async def debug_auth(request: Request):
"""调试认证信息"""
headers = dict(request.headers)
return {
"app_env": settings.APP_ENV,
"debug": settings.DEBUG,
"headers": headers,
"token": headers.get("token"),
"authorization": headers.get("authorization"),
}