added count option and sorting for artists

This commit is contained in:
Ebbe Baß
2026-09-09 14:18:05 +02:00
parent 5d56df1af8
commit 594c101a07
6 changed files with 92 additions and 8 deletions
+30 -6
View File
@@ -16,15 +16,27 @@ from fastapi import FastAPI, HTTPException, Query
from fastapi.responses import PlainTextResponse
from calendar_feed import build_ics
from datasource import EventStore, iter_artist_names, parse_event_date, sort_date_strings, sort_events
from datasource import (
EventStore,
iter_artist_names,
parse_event_date,
sort_artist_schedules,
sort_date_strings,
sort_events,
)
from models import ArtistSchedule, Event, EventList
from rate_limit import Cooldown
from scrape_schedule import discover_cron_expr, get_schedule_info
SortOrder = Literal["asc", "desc", "az", "za"]
_SORT_DESCRIPTION = (
_EVENT_SORT_DESCRIPTION = (
"Sort order: asc/desc by event date, az/za alphabetically by event name"
)
_ARTIST_SORT_DESCRIPTION = (
"Sort order: asc/desc by each artist's latest date, "
"az/za alphabetically by artist name"
)
_COUNT_DESCRIPTION = "Limit the number of results returned"
app = FastAPI(
title="Fundi Scraper API",
@@ -124,7 +136,8 @@ def list_events(
artist: Optional[str] = Query(None, description="Case-insensitive substring match on any artist name"),
date: Optional[str] = Query(None, description="Exact match on the raw event date (dd.mm.yy)"),
upcoming: Optional[bool] = Query(None, description="true = today or later, false = past events"),
sort: Optional[SortOrder] = Query(None, description=_SORT_DESCRIPTION),
sort: Optional[SortOrder] = Query(None, description=_EVENT_SORT_DESCRIPTION),
count: Optional[int] = Query(None, ge=1, description=_COUNT_DESCRIPTION),
):
today = datetime.date.today()
events = [
@@ -133,11 +146,16 @@ def list_events(
if _matches(e, free, name, artist, date, upcoming, today)
]
events = sort_events(events, sort)
if count is not None:
events = events[:count]
return EventList(count=len(events), events=events)
@app.get("/artists", response_model=List[ArtistSchedule])
def list_artists():
def list_artists(
sort: Optional[SortOrder] = Query(None, description=_ARTIST_SORT_DESCRIPTION),
count: Optional[int] = Query(None, ge=1, description=_COUNT_DESCRIPTION),
):
"""Deduplicated, sorted list of all artists, each with every date
(past or upcoming) they appear in the line-up.
"""
@@ -145,9 +163,12 @@ def list_artists():
for event in store.all():
for artist_name in iter_artist_names(event):
appearances[artist_name].add(event.event_date)
ordered = sort_artist_schedules(appearances.items(), sort)
if count is not None:
ordered = ordered[:count]
return [
ArtistSchedule(artist_name=artist_name, dates=sort_date_strings(dates))
for artist_name, dates in sorted(appearances.items(), key=lambda kv: kv[0].lower())
for artist_name, dates in ordered
]
@@ -157,7 +178,8 @@ def list_archive_events(
name: Optional[str] = Query(None, description="Case-insensitive substring match on event name"),
artist: Optional[str] = Query(None, description="Case-insensitive substring match on any artist name"),
date: Optional[str] = Query(None, description="Exact match on the raw event date (dd.mm.yy)"),
sort: Optional[SortOrder] = Query(None, description=_SORT_DESCRIPTION),
sort: Optional[SortOrder] = Query(None, description=_EVENT_SORT_DESCRIPTION),
count: Optional[int] = Query(None, ge=1, description=_COUNT_DESCRIPTION),
):
"""Past events only - shorthand for ``/events?upcoming=false``."""
today = datetime.date.today()
@@ -167,6 +189,8 @@ def list_archive_events(
if _matches(e, free, name, artist, date, upcoming=False, today=today)
]
events = sort_events(events, sort)
if count is not None:
events = events[:count]
return EventList(count=len(events), events=events)