"""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 """

Redirecting to login...

""" @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 )