mirror of
https://git.sr.ht/~joren/streamrip-go
synced 2026-06-17 23:25:30 +02:00
175 lines
4.9 KiB
Go
175 lines
4.9 KiB
Go
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)
|
|
}
|
|
}
|