"""Daily Briefing Dashboard — FastAPI Application.""" from __future__ import annotations import logging from contextlib import asynccontextmanager from pathlib import Path from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from server.config import settings from server.services import news_service logger = logging.getLogger("daily-briefing") logging.basicConfig( level=logging.DEBUG if settings.debug else logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", ) @asynccontextmanager async def lifespan(app: FastAPI): """Startup / shutdown lifecycle.""" logger.info("Starting Daily Briefing Dashboard...") logger.info( "Unraid servers configured: %d", len(settings.unraid_servers), ) # Initialize database pool try: await news_service.init_pool( host=settings.db_host, port=settings.db_port, dbname=settings.db_name, user=settings.db_user, password=settings.db_password, ) logger.info("Database pool initialized") except Exception: logger.exception("Failed to initialize database pool — news will be unavailable") yield # Shutdown logger.info("Shutting down...") await news_service.close_pool() app = FastAPI( title="Daily Briefing", version="2.0.0", lifespan=lifespan, ) # CORS — allow frontend dev server app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # --- Register Routers --- from server.routers import dashboard, homeassistant, news, servers, tasks, weather # noqa: E402 app.include_router(weather.router) app.include_router(news.router) app.include_router(servers.router) app.include_router(homeassistant.router) app.include_router(tasks.router) app.include_router(dashboard.router) # --- Serve static frontend (production) --- static_dir = Path(__file__).parent.parent / "static" if static_dir.is_dir(): app.mount("/", StaticFiles(directory=str(static_dir), html=True), name="static") logger.info("Serving static frontend from %s", static_dir) else: @app.get("/") async def root(): return { "status": "ok", "message": "Daily Briefing API — Frontend not built yet", "endpoints": ["/api/all", "/api/weather", "/api/news", "/api/servers", "/api/ha", "/api/tasks"], }