mirror of
https://git.sr.ht/~joren/streamrip-go
synced 2026-06-17 15:05:39 +02:00
feat yandex desktop downloads
This commit is contained in:
174
internal/provider/yandex/client_test.go
Normal file
174
internal/provider/yandex/client_test.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package yandex
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"streamrip-go/internal/config"
|
||||
"streamrip-go/internal/jsonutil"
|
||||
)
|
||||
|
||||
func TestYandexDownloadSignMatchesCapturedFormat(t *testing.T) {
|
||||
sign, ts := yandexDownloadSign("32038184", "lossless", []string{"flac", "aac", "he-aac", "mp3", "flac-mp4", "aac-mp4", "he-aac-mp4"}, "raw")
|
||||
if ts <= 0 {
|
||||
t.Fatalf("timestamp = %d", ts)
|
||||
}
|
||||
if strings.TrimSpace(sign) == "" {
|
||||
t.Fatalf("decoded sign is empty")
|
||||
}
|
||||
if strings.Contains(sign, "=") {
|
||||
t.Fatalf("sign unexpectedly contains base64 padding: %q", sign)
|
||||
}
|
||||
if strings.Contains(sign, " ") {
|
||||
t.Fatalf("sign unexpectedly contains space: %q", sign)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDownloadableUsesModernGetFileInfo(t *testing.T) {
|
||||
var gotPath string
|
||||
var gotQuery url.Values
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gotPath = r.URL.Path
|
||||
gotQuery = r.URL.Query()
|
||||
if r.URL.Path == "/account/about" {
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"result": map[string]any{"uid": "123"}})
|
||||
return
|
||||
}
|
||||
if r.URL.Path != "/get-file-info" {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"result": map[string]any{
|
||||
"downloadInfo": map[string]any{
|
||||
"trackId": "32038184",
|
||||
"quality": "lossless",
|
||||
"codec": "flac-mp4",
|
||||
"transport": "encraw",
|
||||
"key": "00112233445566778899aabbccddeeff",
|
||||
"bitrate": 0,
|
||||
"url": "https://strm.example/music-v2/crypt/x/flac-mp4",
|
||||
},
|
||||
},
|
||||
})
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
d := config.DefaultConfigData()
|
||||
d.Downloads.RequestsPerMinute = 0
|
||||
d.Yandex.AccessToken = "token"
|
||||
c := New(&config.Config{File: d, Session: d})
|
||||
c.baseURL = ts.URL
|
||||
c.loggedIn = true
|
||||
|
||||
dl, err := c.GetDownloadable(context.Background(), "32038184:1683700", 2)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDownloadable() error = %v", err)
|
||||
}
|
||||
if gotPath != "/get-file-info" {
|
||||
t.Fatalf("path = %q, want /get-file-info", gotPath)
|
||||
}
|
||||
if gotQuery.Get("trackId") != "32038184" {
|
||||
t.Fatalf("trackId = %q, want 32038184", gotQuery.Get("trackId"))
|
||||
}
|
||||
if gotQuery.Get("quality") != "lossless" {
|
||||
t.Fatalf("quality = %q, want lossless", gotQuery.Get("quality"))
|
||||
}
|
||||
if gotQuery.Get("transports") != "encraw" {
|
||||
t.Fatalf("transports = %q, want encraw", gotQuery.Get("transports"))
|
||||
}
|
||||
if dl.Extension != "m4a" {
|
||||
t.Fatalf("extension = %q, want m4a", dl.Extension)
|
||||
}
|
||||
if dl.Audio.Codec != "FLAC" || dl.Audio.Quality != "LOSSLESS" {
|
||||
t.Fatalf("unexpected audio profile: %+v", dl.Audio)
|
||||
}
|
||||
if dl.TrackID != "32038184" {
|
||||
t.Fatalf("track id = %q, want 32038184", dl.TrackID)
|
||||
}
|
||||
if dl.Cipher != "AES_CTR" || dl.Key == "" {
|
||||
t.Fatalf("expected yandex cipher metadata, got cipher=%q key=%q", dl.Cipher, dl.Key)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMetadataTrackUsesModernTracksEndpoint(t *testing.T) {
|
||||
var gotMethod string
|
||||
var gotPath string
|
||||
var gotBody string
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gotMethod = r.Method
|
||||
gotPath = r.URL.Path
|
||||
if r.URL.Path != "/tracks" {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
gotBody = string(body)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"result": []map[string]any{{
|
||||
"id": "9442712",
|
||||
"realId": "9442712",
|
||||
"title": "Nightcall",
|
||||
"artists": []map[string]any{{"id": "1433871", "name": "Kavinsky"}},
|
||||
"albums": []map[string]any{{
|
||||
"id": "1000856",
|
||||
"title": "OutRun",
|
||||
"releaseDate": "2013-02-25T00:00:00+04:00",
|
||||
"trackCount": 13,
|
||||
"artists": []map[string]any{{"id": "1433871", "name": "Kavinsky"}},
|
||||
"trackPosition": map[string]any{
|
||||
"index": 0,
|
||||
"volume": 1,
|
||||
},
|
||||
}},
|
||||
}},
|
||||
})
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
d := config.DefaultConfigData()
|
||||
d.Downloads.RequestsPerMinute = 0
|
||||
d.Yandex.AccessToken = "token"
|
||||
c := New(&config.Config{File: d, Session: d})
|
||||
c.baseURL = ts.URL
|
||||
c.loggedIn = true
|
||||
|
||||
meta, err := c.GetMetadata(context.Background(), "9442712:1000856", "track")
|
||||
if err != nil {
|
||||
t.Fatalf("GetMetadata() error = %v", err)
|
||||
}
|
||||
if gotMethod != http.MethodPost || gotPath != "/tracks" {
|
||||
t.Fatalf("unexpected request: %s %s", gotMethod, gotPath)
|
||||
}
|
||||
if !strings.Contains(gotBody, "trackIds=9442712%3A1000856") {
|
||||
t.Fatalf("body = %q", gotBody)
|
||||
}
|
||||
if meta["id"] != "9442712:1000856" {
|
||||
t.Fatalf("id = %v", meta["id"])
|
||||
}
|
||||
if album, _ := meta["album"].(map[string]any); jsonutil.StringFromAny(album["title"]) != "OutRun" {
|
||||
t.Fatalf("unexpected album: %+v", album)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLegacyDirectURLBuildsPlayableMP3URL(t *testing.T) {
|
||||
url, err := legacyDirectURL(&legacyDownloadInfoXML{
|
||||
Host: "example.test",
|
||||
Path: "/abc123",
|
||||
TS: "1234567890",
|
||||
S: "tailxyz",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("legacyDirectURL() error = %v", err)
|
||||
}
|
||||
want := "https://example.test/get-mp3/248c1c6ff5daf481560d3bd9f24e8058/1234567890/abc123"
|
||||
if url != want {
|
||||
t.Fatalf("legacyDirectURL() = %q, want %q", url, want)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user