Add GET /api/v1/statistics/soundtracks with every soundtrack and its songs
CI / integration (push) Successful in 18s
CI / test (push) Successful in 22s
CI / publish (push) Skipped
CI / docker (push) Successful in 41s

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.
This commit is contained in:
Sansan committed 2026-10-06 23:14:49 +02:00
1 parent fc7d787014
commit 080bacae80
9 files changed
+147 -1

No files matched your search

+27
View File
@@ -180,3 +180,30 @@ SELECT
COALESCE(MIN(times_played), 0)::bigint as min_soundtrack_plays
FROM soundtrack
WHERE deleted IS NULL;
-- Every soundtrack with its songs, by name
-- name: GetAllSoundtracksWithSongs :many
SELECT
g.id as soundtrack_id,
g.uuid as soundtrack_uuid,
g.soundtrack_name,
g.times_played as soundtrack_played,
g.last_played as soundtrack_last_played,
COALESCE(
json_agg(
json_build_object(
'song_uuid', s.uuid,
'soundtrack_uuid', g.uuid,
'song_name', s.song_name,
'path', s.path,
'times_played', s.times_played,
'file_name', s.file_name
)
) FILTER (WHERE s.uuid IS NOT NULL),
'[]'
)::json as songs
FROM soundtrack g
LEFT JOIN song s ON g.id = s.soundtrack_id
WHERE g.deleted IS NULL
GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played
ORDER BY g.soundtrack_name;
+2
View File
@@ -31,6 +31,8 @@ type Querier interface {
FindSongsFromSoundtrack(ctx context.Context, soundtrackID int32) ([]Song, error)
GetActiveSongByUUID(ctx context.Context, argUuid uuid.UUID) (GetActiveSongByUUIDRow, error)
GetAllSoundtracksIncludingDeleted(ctx context.Context) ([]Soundtrack, error)
// Every soundtrack with its songs, by name
GetAllSoundtracksWithSongs(ctx context.Context) ([]GetAllSoundtracksWithSongsRow, error)
GetIdBySoundtrackName(ctx context.Context, soundtrackName string) (int32, error)
// Last played soundtracks (most recently played)
GetLastPlayedSoundtracks(ctx context.Context, limit int32) ([]GetLastPlayedSoundtracksRow, error)
+64
View File
@@ -12,6 +12,70 @@ import (
"github.com/google/uuid"
)
const getAllSoundtracksWithSongs = `-- name: GetAllSoundtracksWithSongs :many
SELECT
g.id as soundtrack_id,
g.uuid as soundtrack_uuid,
g.soundtrack_name,
g.times_played as soundtrack_played,
g.last_played as soundtrack_last_played,
COALESCE(
json_agg(
json_build_object(
'song_uuid', s.uuid,
'soundtrack_uuid', g.uuid,
'song_name', s.song_name,
'path', s.path,
'times_played', s.times_played,
'file_name', s.file_name
)
) FILTER (WHERE s.uuid IS NOT NULL),
'[]'
)::json as songs
FROM soundtrack g
LEFT JOIN song s ON g.id = s.soundtrack_id
WHERE g.deleted IS NULL
GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played
ORDER BY g.soundtrack_name
`
type GetAllSoundtracksWithSongsRow struct {
SoundtrackID int32 `json:"soundtrack_id"`
SoundtrackUuid uuid.UUID `json:"soundtrack_uuid"`
SoundtrackName string `json:"soundtrack_name"`
SoundtrackPlayed int32 `json:"soundtrack_played"`
SoundtrackLastPlayed *time.Time `json:"soundtrack_last_played"`
Songs []byte `json:"songs"`
}
// Every soundtrack with its songs, by name
func (q *Queries) GetAllSoundtracksWithSongs(ctx context.Context) ([]GetAllSoundtracksWithSongsRow, error) {
rows, err := q.db.Query(ctx, getAllSoundtracksWithSongs)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetAllSoundtracksWithSongsRow
for rows.Next() {
var i GetAllSoundtracksWithSongsRow
if err := rows.Scan(
&i.SoundtrackID,
&i.SoundtrackUuid,
&i.SoundtrackName,
&i.SoundtrackPlayed,
&i.SoundtrackLastPlayed,
&i.Songs,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getLastPlayedSoundtracks = `-- name: GetLastPlayedSoundtracks :many
SELECT
g.id as soundtrack_id,