| """FastAPI application initialization""" |
| from fastapi import FastAPI |
| from fastapi.responses import HTMLResponse, FileResponse |
| from fastapi.staticfiles import StaticFiles |
| from fastapi.middleware.cors import CORSMiddleware |
| from contextlib import asynccontextmanager |
| from pathlib import Path |
|
|
| from .core.config import config |
| from .core.database import Database |
| from .services.flow_client import FlowClient |
| from .services.proxy_manager import ProxyManager |
| from .services.token_manager import TokenManager |
| from .services.load_balancer import LoadBalancer |
| from .services.concurrency_manager import ConcurrencyManager |
| from .services.generation_handler import GenerationHandler |
| from .api import routes, admin |
|
|
|
|
| @asynccontextmanager |
| async def lifespan(app: FastAPI): |
| """Application lifespan manager""" |
| |
| print("=" * 60) |
| print("Flow2API Starting...") |
| print("=" * 60) |
|
|
| |
| config_dict = config.get_raw_config() |
|
|
| |
| is_first_startup = not db.db_exists() |
|
|
| |
| await db.init_db() |
|
|
| |
| if is_first_startup: |
| print("🎉 First startup detected. Initializing database and configuration from setting.toml...") |
| await db.init_config_from_toml(config_dict, is_first_startup=True) |
| print("✓ Database and configuration initialized successfully.") |
| else: |
| print("🔄 Existing database detected. Checking for missing tables and columns...") |
| await db.check_and_migrate_db(config_dict) |
| print("✓ Database migration check completed.") |
|
|
| |
| admin_config = await db.get_admin_config() |
| if admin_config: |
| config.set_admin_username_from_db(admin_config.username) |
| config.set_admin_password_from_db(admin_config.password) |
| config.api_key = admin_config.api_key |
|
|
| |
| cache_config = await db.get_cache_config() |
| config.set_cache_enabled(cache_config.cache_enabled) |
| config.set_cache_timeout(cache_config.cache_timeout) |
| config.set_cache_base_url(cache_config.cache_base_url or "") |
|
|
| |
| generation_config = await db.get_generation_config() |
| config.set_image_timeout(generation_config.image_timeout) |
| config.set_video_timeout(generation_config.video_timeout) |
|
|
| |
| tokens = await token_manager.get_all_tokens() |
| await concurrency_manager.initialize(tokens) |
|
|
| |
| await generation_handler.file_cache.start_cleanup_task() |
|
|
| print(f"✓ Database initialized") |
| print(f"✓ Total tokens: {len(tokens)}") |
| print(f"✓ Cache: {'Enabled' if config.cache_enabled else 'Disabled'} (timeout: {config.cache_timeout}s)") |
| print(f"✓ File cache cleanup task started") |
| print(f"✓ Server running on http://{config.server_host}:{config.server_port}") |
| print("=" * 60) |
|
|
| yield |
|
|
| |
| print("Flow2API Shutting down...") |
| |
| await generation_handler.file_cache.stop_cleanup_task() |
| print("✓ File cache cleanup task stopped") |
|
|
|
|
| |
| db = Database() |
| proxy_manager = ProxyManager(db) |
| flow_client = FlowClient(proxy_manager) |
| token_manager = TokenManager(db, flow_client) |
| concurrency_manager = ConcurrencyManager() |
| load_balancer = LoadBalancer(token_manager, concurrency_manager) |
| generation_handler = GenerationHandler( |
| flow_client, |
| token_manager, |
| load_balancer, |
| db, |
| concurrency_manager, |
| proxy_manager |
| ) |
|
|
| |
| routes.set_generation_handler(generation_handler) |
| admin.set_dependencies(token_manager, proxy_manager, db) |
|
|
| |
| app = FastAPI( |
| title="Flow2API", |
| description="OpenAI-compatible API for Google VideoFX (Veo)", |
| version="1.0.0", |
| lifespan=lifespan |
| ) |
|
|
| |
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| |
| app.include_router(routes.router) |
| app.include_router(admin.router) |
|
|
| |
| tmp_dir = Path(__file__).parent.parent / "tmp" |
| tmp_dir.mkdir(exist_ok=True) |
| app.mount("/tmp", StaticFiles(directory=str(tmp_dir)), name="tmp") |
|
|
| |
| static_path = Path(__file__).parent.parent / "static" |
|
|
|
|
| @app.get("/", response_class=HTMLResponse) |
| async def index(): |
| """Redirect to login page""" |
| login_file = static_path / "login.html" |
| if login_file.exists(): |
| return FileResponse(str(login_file)) |
| return HTMLResponse(content="<h1>Flow2API</h1><p>Frontend not found</p>", status_code=404) |
|
|
|
|
| @app.get("/login", response_class=HTMLResponse) |
| async def login_page(): |
| """Login page""" |
| login_file = static_path / "login.html" |
| if login_file.exists(): |
| return FileResponse(str(login_file)) |
| return HTMLResponse(content="<h1>Login Page Not Found</h1>", status_code=404) |
|
|
|
|
| @app.get("/manage", response_class=HTMLResponse) |
| async def manage_page(): |
| """Management console page""" |
| manage_file = static_path / "manage.html" |
| if manage_file.exists(): |
| return FileResponse(str(manage_file)) |
| return HTMLResponse(content="<h1>Management Page Not Found</h1>", status_code=404) |
|
|