from __future__ import annotations import json from contextlib import asynccontextmanager from pathlib import Path from fastapi import FastAPI, HTTPException from .config import settings from .models import MenuSnapshot from .scraper import GorichMenuScraper scraper = GorichMenuScraper() output_path = Path(settings.output_path) @asynccontextmanager async def lifespan(_: FastAPI): if settings.scrape_on_startup: await scraper.scrape_and_save() yield app = FastAPI( title="Gorich Menu Scraper", version="1.0.0", lifespan=lifespan, ) def load_snapshot_from_disk() -> MenuSnapshot: if not output_path.exists(): raise HTTPException(status_code=404, detail="Menu snapshot not found") data = json.loads(output_path.read_text(encoding="utf-8")) return MenuSnapshot.model_validate(data) @app.get("/health") async def health() -> dict[str, str]: return {"status": "ok"} @app.post("/scrape", response_model=MenuSnapshot) async def scrape_menu() -> MenuSnapshot: return await scraper.scrape_and_save() @app.get("/items", response_model=MenuSnapshot) async def get_items() -> MenuSnapshot: return load_snapshot_from_disk() @app.get("/items/{item_id}") async def get_item(item_id: str) -> dict[str, object]: snapshot = load_snapshot_from_disk() for item in snapshot.items: if item.item_id == item_id: return item.model_dump(mode="json") raise HTTPException(status_code=404, detail="Menu item not found")