Compare commits
5 commits
2ce0e9ba4e
...
fd43a6165a
| Author | SHA1 | Date | |
|---|---|---|---|
| fd43a6165a | |||
|
|
2a433a41e9 | ||
|
|
8560884bbd | ||
|
|
51e906c41f | ||
|
|
12f01a17a9 |
4 changed files with 1410 additions and 496 deletions
37
app/main.py
37
app/main.py
|
|
@ -189,6 +189,21 @@ async def update_source(source_id: UUID, payload: dict):
|
||||||
@app.get("/api/events", response_model=list[EventOut])
|
@app.get("/api/events", response_model=list[EventOut])
|
||||||
async def list_events(
|
async def list_events(
|
||||||
source_type: SourceType | None = Query(None),
|
source_type: SourceType | None = Query(None),
|
||||||
|
bbox: str | None = Query(
|
||||||
|
None,
|
||||||
|
description="Comma-separated 'minlon,minlat,maxlon,maxlat' to bound the "
|
||||||
|
"result set by event coordinates. Omit for all stored events.",
|
||||||
|
),
|
||||||
|
since: datetime | None = Query(
|
||||||
|
None,
|
||||||
|
description="Only events ingested at/after this UTC instant "
|
||||||
|
"(ISO 8601, e.g. '2026-08-24T12:00:00Z').",
|
||||||
|
),
|
||||||
|
has_coords: bool = Query(
|
||||||
|
False,
|
||||||
|
description="Only events that carry a location (location_lat/lon set). "
|
||||||
|
"Used by the map's event-blips layer.",
|
||||||
|
),
|
||||||
limit: int = Query(50, ge=1, le=500),
|
limit: int = Query(50, ge=1, le=500),
|
||||||
offset: int = Query(0, ge=0),
|
offset: int = Query(0, ge=0),
|
||||||
):
|
):
|
||||||
|
|
@ -197,6 +212,28 @@ async def list_events(
|
||||||
stmt = select(events).order_by(events.c.ingested_at.desc())
|
stmt = select(events).order_by(events.c.ingested_at.desc())
|
||||||
if source_type:
|
if source_type:
|
||||||
stmt = stmt.where(events.c.source_type == source_type.value)
|
stmt = stmt.where(events.c.source_type == source_type.value)
|
||||||
|
if since:
|
||||||
|
stmt = stmt.where(events.c.ingested_at >= since)
|
||||||
|
if has_coords:
|
||||||
|
stmt = stmt.where(events.c.location_lat.isnot(None))
|
||||||
|
if bbox:
|
||||||
|
parts = [p.strip() for p in bbox.split(",")]
|
||||||
|
if len(parts) != 4:
|
||||||
|
raise HTTPException(
|
||||||
|
422, "bbox must be 'minlon,minlat,maxlon,maxlat' (4 comma-separated values)"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
minlon, minlat, maxlon, maxlat = (float(p) for p in parts)
|
||||||
|
except ValueError:
|
||||||
|
raise HTTPException(
|
||||||
|
422, "bbox values must be floats: 'minlon,minlat,maxlon,maxlat'"
|
||||||
|
)
|
||||||
|
stmt = stmt.where(
|
||||||
|
and_(
|
||||||
|
events.c.location_lon >= minlon, events.c.location_lon <= maxlon,
|
||||||
|
events.c.location_lat >= minlat, events.c.location_lat <= maxlat,
|
||||||
|
)
|
||||||
|
)
|
||||||
stmt = stmt.limit(limit).offset(offset)
|
stmt = stmt.limit(limit).offset(offset)
|
||||||
rows = (await session.execute(stmt)).mappings().all()
|
rows = (await session.execute(stmt)).mappings().all()
|
||||||
return [event_to_out(r) for r in rows]
|
return [event_to_out(r) for r in rows]
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ events = Table(
|
||||||
Column("id", UUID(as_uuid=True), primary_key=True, default=uuid4),
|
Column("id", UUID(as_uuid=True), primary_key=True, default=uuid4),
|
||||||
Column("source_type", Enum(
|
Column("source_type", Enum(
|
||||||
"rss", "gdel-t2", "social", "earthquake", "disaster",
|
"rss", "gdel-t2", "social", "earthquake", "disaster",
|
||||||
"weather", "fire", "satellite", name="event_source_type"
|
"weather", "fire", "satellite", "camera", name="event_source_type"
|
||||||
), nullable=False, index=True),
|
), nullable=False, index=True),
|
||||||
Column("source_id", UUID(as_uuid=True)),
|
Column("source_id", UUID(as_uuid=True)),
|
||||||
Column("title", Text),
|
Column("title", Text),
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ class SourceType(str, Enum):
|
||||||
weather = "weather"
|
weather = "weather"
|
||||||
fire = "fire"
|
fire = "fire"
|
||||||
satellite = "satellite"
|
satellite = "satellite"
|
||||||
|
camera = "camera"
|
||||||
|
|
||||||
|
|
||||||
class EntityKind(str, Enum):
|
class EntityKind(str, Enum):
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue