Files
MusicServer/internal/server/statistics_handler.go
T
Sansan 080bacae80
CI / integration (push) Successful in 18s
CI / test (push) Successful in 22s
CI / publish (push) Skipped
CI / docker (push) Successful in 41s
Add GET /api/v1/statistics/soundtracks with every soundtrack and its songs
The other soundtrack statistics are capped at 100, so a client that shows every soundtrack (the MusicPlayer statistics tab) had no way to get them all. This one has no limit and is sorted by name.
2026-10-06 23:14:49 +02:00

77 lines
3.3 KiB
Go

package server
import (
"context"
"net/http"
"music-server/internal/backend"
"github.com/danielgtaylor/huma/v2"
)
const maxStatsLimit = 100
type limitInput struct {
Limit int `query:"limit" default:"10" minimum:"1" doc:"Number of results. Values above 100 are capped to 100."`
}
func (in *limitInput) capped() int32 {
return int32(min(in.Limit, maxStatsLimit))
}
func (s *Server) registerStatistics(a apis) {
st := s.stats
op := func(id, path, summary, description string) route {
return route{op: huma.Operation{
OperationID: id,
Method: http.MethodGet,
Path: "/statistics" + path,
Summary: summary,
Description: description,
Tags: []string{"statistics"},
}}
}
soundtracks := func(id, path, summary, description string,
query func(context.Context, int32) ([]backend.SoundtrackWithSongs, error)) {
register(s, a, op(id, path, summary, description),
func(ctx context.Context, in *limitInput) (*jsonBody[[]backend.SoundtrackWithSongs], error) {
return ok(query(ctx, in.capped()))
})
}
songs := func(id, path, summary, description string,
query func(context.Context, int32) ([]backend.SongInfoForStats, error)) {
register(s, a, op(id, path, summary, description),
func(ctx context.Context, in *limitInput) (*jsonBody[[]backend.SongInfoForStats], error) {
return ok(query(ctx, in.capped()))
})
}
soundtracks("get-most-played-soundtracks", "/soundtracks/most-played", "Most played soundtracks",
"Returns the most played soundtracks with their songs.", st.MostPlayedSoundtracks)
soundtracks("get-least-played-soundtracks", "/soundtracks/least-played", "Least played soundtracks",
"Returns the least played soundtracks with their songs.", st.LeastPlayedSoundtracks)
soundtracks("get-last-played-soundtracks", "/soundtracks/last-played", "Recently played soundtracks",
"Returns the most recently played soundtracks with their songs.", st.LastPlayedSoundtracks)
soundtracks("get-oldest-played-soundtracks", "/soundtracks/oldest-played", "Least recently played soundtracks",
"Returns the soundtracks played longest ago (played at least once) with their songs.", st.OldestPlayedSoundtracks)
songs("get-most-played-songs", "/songs/most-played", "Most played songs",
"Returns the most played songs with their soundtrack.", st.MostPlayedSongs)
songs("get-least-played-songs", "/songs/least-played", "Least played songs",
"Returns the least played songs with their soundtrack.", st.LeastPlayedSongs)
register(s, a, op("get-all-soundtrack-statistics", "/soundtracks", "All soundtracks with statistics",
"Returns every soundtrack with its songs and play counts, sorted by name."),
func(ctx context.Context, _ *struct{}) (*jsonBody[[]backend.SoundtrackWithSongs], error) {
return ok(st.AllSoundtracks(ctx))
})
register(s, a, op("get-never-played-soundtracks", "/soundtracks/never-played", "Never played soundtracks",
"Returns all soundtracks that have never been played, with their songs."),
func(ctx context.Context, _ *struct{}) (*jsonBody[[]backend.SoundtrackWithSongs], error) {
return ok(st.NeverPlayedSoundtracks(ctx))
})
register(s, a, op("get-statistics-summary", "/summary", "Statistics summary", "Returns overall play statistics."),
func(ctx context.Context, _ *struct{}) (*jsonBody[backend.StatisticsSummary], error) {
return ok(st.Summary(ctx))
})
}