package api import ( "net/http" "git.fabledsword.com/bvandeusen/minstrel/internal/apierror" "git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq" ) // genreCount is one row of the genre browse index (#367). // // Genres are the raw ID3 strings, split on [;,] but otherwise untouched — no // case folding and no synonym mapping. So "Rock" and "rock" can both appear, // as can "Rock/Pop" alongside "Rock" and "Pop". That's deliberate for v1: the // alternative is a normalisation table to invent and maintain, and the raw // spread has to be visible before anyone can judge whether it's a problem. type genreCount struct { Genre string `json:"genre"` TrackCount int `json:"track_count"` } // yearCount is one row of the year browse index. type yearCount struct { Year int `json:"year"` AlbumCount int `json:"album_count"` } // handleListGenres implements GET /api/library/genres. // // Unpaged on purpose. Even a messy library yields hundreds of distinct tag // strings, not thousands, and the client needs the whole set at once to render // a browsable index — paging it would mean the UI could only ever show a // prefix of an ordering the user didn't choose. func (h *handlers) handleListGenres(w http.ResponseWriter, r *http.Request) { rows, err := dbq.New(h.pool).ListGenresWithCount(r.Context()) if err != nil { h.logger.Error("api: list genres", "err", err) writeErr(w, apierror.InternalMsg("lookup failed", err)) return } out := make([]genreCount, 0, len(rows)) for _, row := range rows { out = append(out, genreCount{Genre: row.Genre, TrackCount: int(row.TrackCount)}) } writeJSON(w, http.StatusOK, out) } // handleListAlbumYears implements GET /api/library/years. // // Albums with no release_date are absent rather than bucketed under 0 — "year // unknown" isn't a year, and inventing a row for it would put a fake entry at // one end of a chronological list. func (h *handlers) handleListAlbumYears(w http.ResponseWriter, r *http.Request) { rows, err := dbq.New(h.pool).ListAlbumYearsWithCount(r.Context()) if err != nil { h.logger.Error("api: list album years", "err", err) writeErr(w, apierror.InternalMsg("lookup failed", err)) return } out := make([]yearCount, 0, len(rows)) for _, row := range rows { out = append(out, yearCount{Year: int(row.Year), AlbumCount: int(row.AlbumCount)}) } writeJSON(w, http.StatusOK, out) }