Koito/internal/db/psql/top_tracks.go
2026-01-15 21:08:30 -05:00

154 lines
5.1 KiB
Go

package psql
import (
"context"
"encoding/json"
"fmt"
"github.com/gabehf/koito/internal/db"
"github.com/gabehf/koito/internal/logger"
"github.com/gabehf/koito/internal/models"
"github.com/gabehf/koito/internal/repository"
)
func (d *Psql) GetTopTracksPaginated(ctx context.Context, opts db.GetItemsOpts) (*db.PaginatedResponse[db.RankedItem[*models.Track]], error) {
l := logger.FromContext(ctx)
offset := (opts.Page - 1) * opts.Limit
t1, t2 := db.TimeframeToTimeRange(opts.Timeframe)
if opts.Limit == 0 {
opts.Limit = DefaultItemsPerPage
}
var tracks []db.RankedItem[*models.Track]
var count int64
if opts.AlbumID > 0 {
l.Debug().Msgf("Fetching top %d tracks on page %d from range %v to %v",
opts.Limit, opts.Page, t1.Format("Jan 02, 2006"), t2.Format("Jan 02, 2006"))
rows, err := d.q.GetTopTracksInReleasePaginated(ctx, repository.GetTopTracksInReleasePaginatedParams{
ListenedAt: t1,
ListenedAt_2: t2,
Limit: int32(opts.Limit),
Offset: int32(offset),
ReleaseID: int32(opts.AlbumID),
})
if err != nil {
return nil, fmt.Errorf("GetTopTracksPaginated: GetTopTracksInReleasePaginated: %w", err)
}
tracks = make([]db.RankedItem[*models.Track], len(rows))
for i, row := range rows {
artists := make([]models.SimpleArtist, 0)
err = json.Unmarshal(row.Artists, &artists)
if err != nil {
l.Err(err).Msgf("Error unmarshalling artists for track with id %d", row.ID)
return nil, fmt.Errorf("GetTopTracksPaginated: Unmarshal: %w", err)
}
t := &models.Track{
Title: row.Title,
MbzID: row.MusicBrainzID,
ID: row.ID,
ListenCount: row.ListenCount,
Image: row.Image,
AlbumID: row.ReleaseID,
Artists: artists,
}
tracks[i].Item = t
tracks[i].Rank = row.Rank
}
count, err = d.q.CountTopTracksByRelease(ctx, repository.CountTopTracksByReleaseParams{
ListenedAt: t1,
ListenedAt_2: t2,
ReleaseID: int32(opts.AlbumID),
})
if err != nil {
return nil, err
}
} else if opts.ArtistID > 0 {
l.Debug().Msgf("Fetching top %d tracks on page %d from range %v to %v",
opts.Limit, opts.Page, t1.Format("Jan 02, 2006"), t2.Format("Jan 02, 2006"))
rows, err := d.q.GetTopTracksByArtistPaginated(ctx, repository.GetTopTracksByArtistPaginatedParams{
ListenedAt: t1,
ListenedAt_2: t2,
Limit: int32(opts.Limit),
Offset: int32(offset),
ArtistID: int32(opts.ArtistID),
})
if err != nil {
return nil, fmt.Errorf("GetTopTracksPaginated: GetTopTracksByArtistPaginated: %w", err)
}
tracks = make([]db.RankedItem[*models.Track], len(rows))
for i, row := range rows {
artists := make([]models.SimpleArtist, 0)
err = json.Unmarshal(row.Artists, &artists)
if err != nil {
l.Err(err).Msgf("Error unmarshalling artists for track with id %d", row.ID)
return nil, fmt.Errorf("GetTopTracksPaginated: Unmarshal: %w", err)
}
t := &models.Track{
Title: row.Title,
MbzID: row.MusicBrainzID,
ID: row.ID,
Image: row.Image,
ListenCount: row.ListenCount,
AlbumID: row.ReleaseID,
Artists: artists,
}
tracks[i].Item = t
tracks[i].Rank = row.Rank
}
count, err = d.q.CountTopTracksByArtist(ctx, repository.CountTopTracksByArtistParams{
ListenedAt: t1,
ListenedAt_2: t2,
ArtistID: int32(opts.ArtistID),
})
if err != nil {
return nil, fmt.Errorf("GetTopTracksPaginated: CountTopTracksByArtist: %w", err)
}
} else {
l.Debug().Msgf("Fetching top %d tracks on page %d from range %v to %v",
opts.Limit, opts.Page, t1.Format("Jan 02, 2006"), t2.Format("Jan 02, 2006"))
rows, err := d.q.GetTopTracksPaginated(ctx, repository.GetTopTracksPaginatedParams{
ListenedAt: t1,
ListenedAt_2: t2,
Limit: int32(opts.Limit),
Offset: int32(offset),
})
if err != nil {
return nil, fmt.Errorf("GetTopTracksPaginated: GetTopTracksPaginated: %w", err)
}
tracks = make([]db.RankedItem[*models.Track], len(rows))
for i, row := range rows {
artists := make([]models.SimpleArtist, 0)
err = json.Unmarshal(row.Artists, &artists)
if err != nil {
l.Err(err).Msgf("Error unmarshalling artists for track with id %d", row.ID)
return nil, fmt.Errorf("GetTopTracksPaginated: Unmarshal: %w", err)
}
t := &models.Track{
Title: row.Title,
MbzID: row.MusicBrainzID,
ID: row.ID,
Image: row.Image,
ListenCount: row.ListenCount,
AlbumID: row.ReleaseID,
Artists: artists,
}
tracks[i].Item = t
tracks[i].Rank = row.Rank
}
count, err = d.q.CountTopTracks(ctx, repository.CountTopTracksParams{
ListenedAt: t1,
ListenedAt_2: t2,
})
if err != nil {
return nil, fmt.Errorf("GetTopTracksPaginated: CountTopTracks: %w", err)
}
l.Debug().Msgf("Database responded with %d tracks out of a total %d", len(rows), count)
}
return &db.PaginatedResponse[db.RankedItem[*models.Track]]{
Items: tracks,
TotalCount: count,
ItemsPerPage: int32(opts.Limit),
HasNextPage: int64(offset+len(tracks)) < count,
CurrentPage: int32(opts.Page),
}, nil
}