"""FastAPI application factory.""" from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates import logging import config import os from core.logging import setup_logger def create_app() -> FastAPI: """Create and configure FastAPI application.""" # Setup logging logger = setup_logger() logger.info("Creating FastAPI application") # Create app app = FastAPI( title="Syllabus", description="Media downloader for Dropout, YouTube, and more", version="1.0.0" ) # Mount static files app.mount("/data", StaticFiles(directory=str(config.DATA_DIR)), name="data") # Setup templates app.templates = Jinja2Templates(directory=str(config.TEMPLATES_DIR)) # Setup startup event to load series data @app.on_event("startup") async def startup_event(): """Load series data from cache on startup.""" logger.info("Running startup initialization") # Load existing dropout.json if it exists if os.path.exists(config.DROPOUT_JSON): try: from core.cache import series_cache series_cache.load_from_file(str(config.DROPOUT_JSON)) logger.info("Series data loaded from cache") except Exception as e: logger.error(f"Failed to load series cache: {e}") else: logger.info("dropout.json not found - users must manually trigger /api/dropout/update or use HTML upload") # Setup middleware @app.middleware("http") async def log_requests(request, call_next): """Log all incoming HTTP requests.""" try: response = await call_next(request) except Exception as e: logger.exception(f"EXCEPTION: {request.method} {request.url} - {str(e)}") from fastapi.responses import JSONResponse return JSONResponse( status_code=500, content={"detail": "Internal Server Error"}, ) logger.info( f"request_client={request.client.host}:{request.client.port}, " f"request_method={request.method}, request_url={request.url}, " f"status_code={response.status_code}" ) return response return app