"""FastAPI application entry point.""" 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 .config import settings from .database.engine import init_db from .services.scheduler import start_scheduler, stop_scheduler from .auth.routes import router as auth_router from .api.servers import router as servers_router from .api.trackers import router as trackers_router from .api.templates import router as templates_router from .api.targets import router as targets_router from .api.users import router as users_router from .api.status import router as status_router from .api.sync import router as sync_router from .ai.telegram_webhook import router as telegram_ai_router logging.basicConfig( level=logging.DEBUG if settings.debug else logging.INFO, format="%(asctime)s %(levelname)s [%(name)s] %(message)s", ) _LOGGER = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): """Application lifespan: startup and shutdown.""" # Startup settings.data_dir.mkdir(parents=True, exist_ok=True) await init_db() _LOGGER.info("Database initialized at %s", settings.effective_database_url) await start_scheduler() yield # Shutdown await stop_scheduler() app = FastAPI( title="Immich Watcher", description="Standalone Immich album change notification server", version="0.1.0", lifespan=lifespan, ) # CORS for frontend dev server app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # API routes app.include_router(auth_router) app.include_router(servers_router) app.include_router(trackers_router) app.include_router(templates_router) app.include_router(targets_router) app.include_router(users_router) app.include_router(status_router) app.include_router(sync_router) app.include_router(telegram_ai_router) # Serve frontend static files if available _frontend_dist = Path(__file__).parent / "frontend" if _frontend_dist.is_dir(): app.mount("/", StaticFiles(directory=_frontend_dist, html=True), name="frontend") @app.get("/api/health") async def health(): """Health check endpoint.""" from .ai.service import is_ai_enabled return {"status": "ok", "version": "0.1.0", "ai_enabled": is_ai_enabled()} def run(): """Run the server (entry point for `immich-watcher` CLI command).""" import uvicorn uvicorn.run( "immich_watcher_server.main:app", host=settings.host, port=settings.port, reload=settings.debug, )