""" BantayCam — Integrated License Plate & Face Recognition for Philippine CCTV FastAPI Application Entry Point """ from contextlib import asynccontextmanager import logging from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from pathlib import Path from app.core.config import settings from app.core.database import init_db from app.services.vehicle_detector import vehicle_detector from app.services.face_service import face_service from app.services.stream_manager import StreamManager from app.api import cameras, vehicles, persons logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s" ) logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): """Startup and shutdown events.""" logger.info("🚀 BantayCam starting up...") # Init database await init_db() logger.info("✅ Database initialized") # Load AI models logger.info("Loading AI models (this may take a moment)...") vehicle_detector.load() face_service.load() logger.info("✅ AI models loaded") # Ensure snapshot storage exists Path(settings.STORAGE_PATH).mkdir(parents=True, exist_ok=True) yield # Shutdown logger.info("Shutting down streams...") await StreamManager.get().stop_all() logger.info("👋 BantayCam shut down") app = FastAPI( title="BantayCam", description="Integrated License Plate & Face Recognition for Philippine CCTV Infrastructure", version=settings.APP_VERSION, lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=["*"], # Tighten in production allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # API routes app.include_router(cameras.router, prefix="/api/v1") app.include_router(vehicles.router, prefix="/api/v1") app.include_router(persons.router, prefix="/api/v1") # Serve snapshots as static files snapshot_dir = Path(settings.STORAGE_PATH) snapshot_dir.mkdir(parents=True, exist_ok=True) app.mount("/snapshots", StaticFiles(directory=str(snapshot_dir)), name="snapshots") @app.get("/") async def root(): return { "app": settings.APP_NAME, "version": settings.APP_VERSION, "status": "running", "docs": "/docs", } @app.get("/health") async def health(): return {"status": "ok"}