64 lines
1.5 KiB
Python
64 lines
1.5 KiB
Python
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")
|
|
|