mirror of
https://git.sr.ht/~joren/streamrip-go
synced 2026-06-17 15:05:39 +02:00
paginate artist album fetching for deezer and qobuz
This commit is contained in:
@@ -122,6 +122,9 @@ func (c *Client) GetMetadata(ctx context.Context, item, mediaType string) (map[s
|
||||
if mediaType == "label" {
|
||||
return c.getLabel(ctx, item)
|
||||
}
|
||||
if mediaType == "artist" {
|
||||
return c.getArtist(ctx, item)
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("app_id", c.cfg.Session.Qobuz.AppID)
|
||||
@@ -130,8 +133,6 @@ func (c *Client) GetMetadata(ctx context.Context, item, mediaType string) (map[s
|
||||
params.Set("offset", "0")
|
||||
|
||||
switch mediaType {
|
||||
case "artist":
|
||||
params.Set("extra", "albums")
|
||||
case "playlist":
|
||||
params.Set("extra", "tracks")
|
||||
case "label":
|
||||
@@ -358,6 +359,77 @@ func (c *Client) getLabel(ctx context.Context, labelID string) (map[string]any,
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) getArtist(ctx context.Context, artistID string) (map[string]any, error) {
|
||||
pageLimit := 500
|
||||
params := url.Values{}
|
||||
params.Set("app_id", c.cfg.Session.Qobuz.AppID)
|
||||
params.Set("artist_id", artistID)
|
||||
params.Set("limit", strconv.Itoa(pageLimit))
|
||||
params.Set("offset", "0")
|
||||
params.Set("extra", "albums")
|
||||
|
||||
resp, status, err := c.apiRequest(ctx, "artist/get", params, c.authHeaders())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if status != http.StatusOK {
|
||||
return nil, fmt.Errorf("artist/get failed: status=%d", status)
|
||||
}
|
||||
|
||||
albumsObj, ok := mapValue(resp["albums"])
|
||||
if !ok {
|
||||
return resp, nil
|
||||
}
|
||||
items, ok := albumsObj["items"].([]any)
|
||||
if !ok {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
total, _ := intValue(resp["albums_count"])
|
||||
if total <= 0 {
|
||||
total, _ = intValue(albumsObj["total"])
|
||||
}
|
||||
if total <= pageLimit && len(items) < pageLimit {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
for offset := pageLimit; ; offset += pageLimit {
|
||||
if total > 0 && offset >= total {
|
||||
break
|
||||
}
|
||||
pageParams := url.Values{}
|
||||
pageParams.Set("app_id", c.cfg.Session.Qobuz.AppID)
|
||||
pageParams.Set("artist_id", artistID)
|
||||
pageParams.Set("limit", strconv.Itoa(pageLimit))
|
||||
pageParams.Set("offset", strconv.Itoa(offset))
|
||||
pageParams.Set("extra", "albums")
|
||||
|
||||
pageResp, pageStatus, pageErr := c.apiRequest(ctx, "artist/get", pageParams, c.authHeaders())
|
||||
if pageErr != nil {
|
||||
return nil, pageErr
|
||||
}
|
||||
if pageStatus != http.StatusOK {
|
||||
return nil, fmt.Errorf("artist/get pagination failed: status=%d offset=%d", pageStatus, offset)
|
||||
}
|
||||
pageAlbums, ok := mapValue(pageResp["albums"])
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
pageItems, ok := pageAlbums["items"].([]any)
|
||||
if !ok || len(pageItems) == 0 {
|
||||
break
|
||||
}
|
||||
items = append(items, pageItems...)
|
||||
if len(pageItems) < pageLimit {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
albumsObj["items"] = items
|
||||
resp["albums"] = albumsObj
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) authHeaders() map[string]string {
|
||||
headers := map[string]string{"X-App-Id": c.cfg.Session.Qobuz.AppID}
|
||||
if c.uat != "" {
|
||||
|
||||
@@ -157,6 +157,53 @@ func TestGetLabelPagination(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetArtistPagination(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
offset := r.URL.Query().Get("offset")
|
||||
if offset == "" {
|
||||
offset = "0"
|
||||
}
|
||||
|
||||
resp := map[string]any{}
|
||||
switch offset {
|
||||
case "0":
|
||||
resp = map[string]any{
|
||||
"albums_count": 620,
|
||||
"albums": map[string]any{"items": makeItems(0, 500)},
|
||||
}
|
||||
case "500":
|
||||
resp = map[string]any{"albums": map[string]any{"items": makeItems(500, 620)}}
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"message": "not found"})
|
||||
return
|
||||
}
|
||||
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
c := newTestClient(t)
|
||||
c.loggedIn = true
|
||||
c.baseURL = ts.URL
|
||||
|
||||
raw, err := c.GetMetadata(context.Background(), "artist-id", "artist")
|
||||
if err != nil {
|
||||
t.Fatalf("GetMetadata() error = %v", err)
|
||||
}
|
||||
albums, ok := mapValue(raw["albums"])
|
||||
if !ok {
|
||||
t.Fatalf("albums missing")
|
||||
}
|
||||
items, ok := albums["items"].([]any)
|
||||
if !ok {
|
||||
t.Fatalf("items missing")
|
||||
}
|
||||
if len(items) != 620 {
|
||||
t.Fatalf("len(items) = %d, want 620", len(items))
|
||||
}
|
||||
}
|
||||
|
||||
func newTestClient(t *testing.T) *Client {
|
||||
t.Helper()
|
||||
d := config.DefaultConfigData()
|
||||
|
||||
Reference in New Issue
Block a user