Files
sora2api/src/main.py
TheSmallHanCat 01523360bb sora2api
2025-11-08 12:47:08 +08:00

123 lines
3.6 KiB
Python

"""Main application entry point"""
import uvicorn
from fastapi import FastAPI
from fastapi.responses import FileResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from pathlib import Path
# Import modules
from .core.config import config
from .core.database import Database
from .services.token_manager import TokenManager
from .services.proxy_manager import ProxyManager
from .services.load_balancer import LoadBalancer
from .services.sora_client import SoraClient
from .services.generation_handler import GenerationHandler
from .api import routes as api_routes
from .api import admin as admin_routes
# Initialize FastAPI app
app = FastAPI(
title="Sora2API",
description="OpenAI compatible API for Sora",
version="1.0.0"
)
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Initialize components
db = Database()
token_manager = TokenManager(db)
proxy_manager = ProxyManager(db)
load_balancer = LoadBalancer(token_manager)
sora_client = SoraClient(proxy_manager)
generation_handler = GenerationHandler(sora_client, token_manager, load_balancer, db, proxy_manager)
# Set dependencies for route modules
api_routes.set_generation_handler(generation_handler)
admin_routes.set_dependencies(token_manager, proxy_manager, db, generation_handler)
# Include routers
app.include_router(api_routes.router)
app.include_router(admin_routes.router)
# Static files
static_dir = Path(__file__).parent.parent / "static"
static_dir.mkdir(exist_ok=True)
app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")
# Cache files (tmp directory)
tmp_dir = Path(__file__).parent.parent / "tmp"
tmp_dir.mkdir(exist_ok=True)
app.mount("/tmp", StaticFiles(directory=str(tmp_dir)), name="tmp")
# Frontend routes
@app.get("/", response_class=HTMLResponse)
async def root():
"""Redirect to login page"""
return """
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; url=/login">
</head>
<body>
<p>Redirecting to login...</p>
</body>
</html>
"""
@app.get("/login", response_class=FileResponse)
async def login_page():
"""Serve login page"""
return FileResponse(str(static_dir / "login.html"))
@app.get("/manage", response_class=FileResponse)
async def manage_page():
"""Serve management page"""
return FileResponse(str(static_dir / "manage.html"))
@app.on_event("startup")
async def startup_event():
"""Initialize database on startup"""
# Check if database exists
is_first_startup = not db.db_exists()
# Initialize database tables
await db.init_db()
# If first startup, initialize config from setting.toml
if is_first_startup:
print("First startup detected. Initializing configuration from setting.toml...")
config_dict = config.get_raw_config()
await db.init_config_from_toml(config_dict)
print("Configuration initialized successfully.")
# Start file cache cleanup task
await generation_handler.file_cache.start_cleanup_task()
print(f"Sora2API started on http://{config.server_host}:{config.server_port}")
print(f"API Key: {config.api_key}")
print(f"Admin: {config.admin_username} / {config.admin_password}")
print(f"Cache timeout: {config.cache_timeout}s")
@app.on_event("shutdown")
async def shutdown_event():
"""Cleanup on shutdown"""
await generation_handler.file_cache.stop_cleanup_task()
if __name__ == "__main__":
uvicorn.run(
"src.main:app",
host=config.server_host,
port=config.server_port,
reload=False
)