paginate artist album fetching for deezer and qobuz

This commit is contained in:
2026-04-21 11:39:04 +02:00
parent 9ebddc8316
commit 4f86751ff4
4 changed files with 203 additions and 3 deletions

View File

@@ -203,7 +203,7 @@ func (c *Client) GetMetadata(ctx context.Context, item, mediaType string) (map[s
resp["tracks"] = map[string]any{"items": items}
return resp, nil
case "artist":
resp, err := c.apiGet(ctx, "/artist/"+item+"/albums", nil)
resp, err := c.getArtistAlbums(ctx, item)
if err != nil {
return nil, err
}
@@ -224,6 +224,35 @@ func (c *Client) GetMetadata(ctx context.Context, item, mediaType string) (map[s
}
}
func (c *Client) getArtistAlbums(ctx context.Context, artistID string) (map[string]any, error) {
const pageSize = 100
index := 0
total := -1
all := make([]any, 0)
for {
params := url.Values{}
params.Set("limit", strconv.Itoa(pageSize))
params.Set("index", strconv.Itoa(index))
resp, err := c.apiGet(ctx, "/artist/"+strings.TrimSpace(artistID)+"/albums", params)
if err != nil {
return nil, err
}
data, _ := resp["data"].([]any)
all = append(all, data...)
if total < 0 {
total = intFromAny(resp["total"])
}
if len(data) < pageSize {
break
}
index += len(data)
if total > 0 && index >= total {
break
}
}
return map[string]any{"data": all, "total": total}, nil
}
func (c *Client) GetDownloadable(ctx context.Context, item string, _ int) (*provider.Downloadable, error) {
if strings.TrimSpace(c.license) == "" {
if strings.TrimSpace(c.arl) != "" {

View File

@@ -39,6 +39,58 @@ func TestSearchTrack(t *testing.T) {
}
}
func TestGetMetadataArtistPaginatesAlbums(t *testing.T) {
callCount := 0
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/artist/9/albums" {
w.WriteHeader(http.StatusNotFound)
return
}
callCount++
index := r.URL.Query().Get("index")
limit := r.URL.Query().Get("limit")
if limit != "100" {
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(map[string]any{"error": map[string]any{"message": "bad limit"}})
return
}
switch index {
case "0":
items := make([]any, 0, 100)
for i := 0; i < 100; i++ {
items = append(items, map[string]any{"id": i + 1, "title": "Album"})
}
_ = json.NewEncoder(w).Encode(map[string]any{"data": items, "total": 101})
case "100":
_ = json.NewEncoder(w).Encode(map[string]any{"data": []any{map[string]any{"id": 101, "title": "Album 101"}}, "total": 101})
default:
w.WriteHeader(http.StatusBadRequest)
}
}))
defer ts.Close()
cfgData := config.DefaultConfigData()
c := New(&config.Config{File: cfgData, Session: cfgData})
c.loggedIn = true
origBase := baseURL
baseURL = ts.URL
defer func() { baseURL = origBase }()
meta, err := c.GetMetadata(context.Background(), "9", "artist")
if err != nil {
t.Fatalf("GetMetadata() error = %v", err)
}
albumsObj, _ := meta["albums"].(map[string]any)
items, _ := albumsObj["items"].([]any)
if len(items) != 101 {
t.Fatalf("albums len = %d, want 101", len(items))
}
if callCount != 2 {
t.Fatalf("call count = %d, want 2", callCount)
}
}
func TestGetDownloadableNativeCipher(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {