mirror of
https://git.sr.ht/~joren/streamrip-go
synced 2026-06-17 15:05:39 +02:00
fix deezer track pagination and decryption track id resolution
This commit is contained in:
@@ -99,6 +99,118 @@ func TestGetMetadataArtistPaginatesAlbums(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMetadataAlbumPaginatesTracks(t *testing.T) {
|
||||
callCount := 0
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/album/46514392":
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"id": 46514392, "title": "Clouseau30", "tracks": map[string]any{"data": []any{}}})
|
||||
case "/album/46514392/tracks":
|
||||
callCount++
|
||||
index := r.URL.Query().Get("index")
|
||||
limit := r.URL.Query().Get("limit")
|
||||
if limit != "100" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
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": "T"})
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"data": items, "total": 105})
|
||||
case "100":
|
||||
items := make([]any, 0, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
items = append(items, map[string]any{"id": 101 + i, "title": "T"})
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"data": items, "total": 105})
|
||||
default:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
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(), "46514392", "album")
|
||||
if err != nil {
|
||||
t.Fatalf("GetMetadata() error = %v", err)
|
||||
}
|
||||
tracksObj, _ := meta["tracks"].(map[string]any)
|
||||
items, _ := tracksObj["items"].([]any)
|
||||
if len(items) != 105 {
|
||||
t.Fatalf("tracks len = %d, want 105", len(items))
|
||||
}
|
||||
if callCount != 2 {
|
||||
t.Fatalf("track page call count = %d, want 2", callCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMetadataPlaylistPaginatesTracks(t *testing.T) {
|
||||
callCount := 0
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/playlist/123":
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"id": 123, "title": "Mix", "tracks": map[string]any{"data": []any{}}})
|
||||
case "/playlist/123/tracks":
|
||||
callCount++
|
||||
index := r.URL.Query().Get("index")
|
||||
limit := r.URL.Query().Get("limit")
|
||||
if limit != "100" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
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": "T"})
|
||||
}
|
||||
_ = 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": "T"}}, "total": 101})
|
||||
default:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
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(), "123", "playlist")
|
||||
if err != nil {
|
||||
t.Fatalf("GetMetadata() error = %v", err)
|
||||
}
|
||||
tracksObj, _ := meta["tracks"].(map[string]any)
|
||||
items, _ := tracksObj["items"].([]any)
|
||||
if len(items) != 101 {
|
||||
t.Fatalf("tracks len = %d, want 101", len(items))
|
||||
}
|
||||
if callCount != 2 {
|
||||
t.Fatalf("track page 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 {
|
||||
@@ -161,6 +273,58 @@ func TestGetDownloadableNativeCipher(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDownloadablePrefersNoneCipherWhenAvailable(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/track/42":
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"id": 42, "title": "X", "track_token": "tt"})
|
||||
case "/media":
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"data": []any{map[string]any{"errors": []any{}, "media": []any{
|
||||
map[string]any{"cipher": map[string]any{"type": "BF_CBC_STRIPE"}, "format": "FLAC", "sources": []any{map[string]any{"url": "https://cdn.example/bf"}}},
|
||||
map[string]any{"cipher": map[string]any{"type": "NONE"}, "format": "FLAC", "sources": []any{map[string]any{"url": "https://cdn.example/plain"}}},
|
||||
}}}})
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
cfgData := config.DefaultConfigData()
|
||||
cfgData.Deezer.ARL = "arl"
|
||||
c := New(&config.Config{File: cfgData, Session: cfgData})
|
||||
c.loggedIn = true
|
||||
c.arl = "arl"
|
||||
c.license = "license"
|
||||
c.jwt = "jwt"
|
||||
|
||||
origBase := baseURL
|
||||
origMedia := mediaURL
|
||||
origPipe := pipeURL
|
||||
baseURL = ts.URL
|
||||
mediaURL = ts.URL + "/media"
|
||||
pipeURL = ts.URL + "/pipe"
|
||||
defer func() {
|
||||
baseURL = origBase
|
||||
mediaURL = origMedia
|
||||
pipeURL = origPipe
|
||||
}()
|
||||
|
||||
d, err := c.GetDownloadable(context.Background(), "42", 2)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDownloadable() error = %v", err)
|
||||
}
|
||||
if d.Cipher != "NONE" || d.URL != "https://cdn.example/plain" {
|
||||
t.Fatalf("expected NONE cipher source, got %+v", d)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractTrackIDFromMediaURL(t *testing.T) {
|
||||
url := "https://f-cdnt-stream.dzcdn.net/media/1/9/6/4/8/2552667002/64821d6a2007e90768fa0300b508fcf4.flac?hdnea=x"
|
||||
if got := extractTrackIDFromMediaURL(url); got != "2552667002" {
|
||||
t.Fatalf("extractTrackIDFromMediaURL() = %q, want 2552667002", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoginPrefersARLFlowOverRefreshShortcut(t *testing.T) {
|
||||
mobileToken := testMobileToken(t)
|
||||
refreshCalled := false
|
||||
@@ -298,13 +462,16 @@ func TestGetTrackTokenPrefersPipeToken(t *testing.T) {
|
||||
pipeURL = origPipe
|
||||
}()
|
||||
|
||||
token, err := c.getTrackToken(context.Background(), "42")
|
||||
token, mediaID, err := c.getTrackToken(context.Background(), "42")
|
||||
if err != nil {
|
||||
t.Fatalf("getTrackToken() error = %v", err)
|
||||
}
|
||||
if token != "pipe-track-token" {
|
||||
t.Fatalf("token = %q, want pipe-track-token", token)
|
||||
}
|
||||
if mediaID != "" {
|
||||
t.Fatalf("mediaID = %q, want empty when pipe media id missing", mediaID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDownloadableUsesPipeTrackToken(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user