Files
beavergram/backend/src/api/routers/watches.py
T
2026-05-30 01:32:35 +02:00

83 lines
2.6 KiB
Python

from typing import Annotated, Any
import asyncpg
from dishka.integrations.fastapi import DishkaRoute, FromDishka
from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel
from utils.read import watches
from utils.read.models import DEFAULT_LIMIT, AlertView, Page, WatchView
router = APIRouter(prefix="/api", tags=["watches"], route_class=DishkaRoute)
class WatchCreate(BaseModel):
account_id: int
kind: str
params: dict[str, Any] = {}
enabled: bool = True
class WatchUpdate(BaseModel):
params: dict[str, Any] = {}
enabled: bool = True
@router.get("/watches")
async def list_watches(
pool: FromDishka[asyncpg.Pool], account_id: Annotated[int, Query()]
) -> list[WatchView]:
return await watches.list_watches(pool, account_id)
@router.post("/watches", status_code=201)
async def create_watch(pool: FromDishka[asyncpg.Pool], body: WatchCreate) -> WatchView:
return await watches.create_watch(
pool, body.account_id, body.kind, body.params, enabled=body.enabled
)
@router.get("/watches/{watch_id}")
async def get_watch(pool: FromDishka[asyncpg.Pool], watch_id: int) -> WatchView:
watch = await watches.get_watch(pool, watch_id)
if watch is None:
raise HTTPException(status_code=404, detail="watch not found")
return watch
@router.put("/watches/{watch_id}")
async def update_watch(
pool: FromDishka[asyncpg.Pool], watch_id: int, body: WatchUpdate
) -> WatchView:
watch = await watches.update_watch(
pool, watch_id, body.params, enabled=body.enabled
)
if watch is None:
raise HTTPException(status_code=404, detail="watch not found")
return watch
@router.delete("/watches/{watch_id}", status_code=204)
async def delete_watch(pool: FromDishka[asyncpg.Pool], watch_id: int) -> None:
if not await watches.delete_watch(pool, watch_id):
raise HTTPException(status_code=404, detail="watch not found")
@router.get("/alerts")
async def list_alerts(
pool: FromDishka[asyncpg.Pool],
account_id: Annotated[int, Query()],
seen: Annotated[bool | None, Query()] = None,
limit: Annotated[int, Query()] = DEFAULT_LIMIT,
offset: Annotated[int, Query()] = 0,
) -> list[AlertView]:
return await watches.list_alerts(
pool, account_id, Page(limit=limit, offset=offset), seen=seen
)
@router.post("/alerts/{alert_id}/seen", status_code=204)
async def mark_alert_seen(pool: FromDishka[asyncpg.Pool], alert_id: int) -> None:
if not await watches.mark_alert_seen(pool, alert_id):
raise HTTPException(status_code=404, detail="alert not found")