mirror of
https://git.sr.ht/~joren/streamrip-go
synced 2026-06-17 15:05:39 +02:00
163 lines
5.0 KiB
Go
163 lines
5.0 KiB
Go
package tidal
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"streamrip-go/internal/config"
|
|
)
|
|
|
|
func TestLoginMissingToken(t *testing.T) {
|
|
cfgData := config.DefaultConfigData()
|
|
cfgData.Tidal.AccessToken = ""
|
|
c := New(&config.Config{File: cfgData, Session: cfgData})
|
|
err := c.Login(context.Background())
|
|
if err == nil {
|
|
t.Fatalf("expected error")
|
|
}
|
|
}
|
|
|
|
func TestSearch(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch r.URL.Path {
|
|
case "/v1/sessions":
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"countryCode": "US", "userId": 123})
|
|
case "/v1/search/albums":
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"items": []any{map[string]any{"id": 1, "title": "x"}}})
|
|
default:
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
cfgData := config.DefaultConfigData()
|
|
cfgData.Tidal.AccessToken = "token"
|
|
cfgData.Tidal.CountryCode = "US"
|
|
c := New(&config.Config{File: cfgData, Session: cfgData})
|
|
c.baseURL = ts.URL + "/v1"
|
|
|
|
if err := c.Login(context.Background()); err != nil {
|
|
t.Fatalf("login err = %v", err)
|
|
}
|
|
pages, err := c.Search(context.Background(), "album", "x", 10)
|
|
if err != nil {
|
|
t.Fatalf("search err = %v", err)
|
|
}
|
|
if len(pages) != 1 {
|
|
t.Fatalf("pages = %d", len(pages))
|
|
}
|
|
}
|
|
|
|
func TestGetVideoDownloadable(t *testing.T) {
|
|
var server *httptest.Server
|
|
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch r.URL.Path {
|
|
case "/v1/sessions":
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"countryCode": "US", "userId": 123})
|
|
case "/v1/videos/42/playbackinfopostpaywall":
|
|
manifest := map[string]any{"urls": []string{server.URL + "/master.m3u8"}}
|
|
b, _ := json.Marshal(manifest)
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"manifest": base64.StdEncoding.EncodeToString(b)})
|
|
case "/master.m3u8":
|
|
_, _ = w.Write([]byte("#EXTM3U\n#EXT-X-STREAM-INF:BANDWIDTH=1000,CODECS=\"avc1.42E01E,mp4a.40.2\",RESOLUTION=640x360\nlow/stream.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=2000,CODECS=\"avc1.4D401F,mp4a.40.2\",RESOLUTION=1280x720\nhi/stream.m3u8\n"))
|
|
default:
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
cfgData := config.DefaultConfigData()
|
|
cfgData.Tidal.AccessToken = "token"
|
|
cfgData.Tidal.CountryCode = "US"
|
|
c := New(&config.Config{File: cfgData, Session: cfgData})
|
|
c.baseURL = server.URL + "/v1"
|
|
|
|
if err := c.Login(context.Background()); err != nil {
|
|
t.Fatalf("login err = %v", err)
|
|
}
|
|
d, err := c.GetVideoDownloadable(context.Background(), "42")
|
|
if err != nil {
|
|
t.Fatalf("GetVideoDownloadable() err = %v", err)
|
|
}
|
|
if d.Extension != "mp4" {
|
|
t.Fatalf("extension = %q, want mp4", d.Extension)
|
|
}
|
|
if d.URL != server.URL+"/hi/stream.m3u8" {
|
|
t.Fatalf("url = %q, want %q", d.URL, server.URL+"/hi/stream.m3u8")
|
|
}
|
|
}
|
|
|
|
func TestBestHLSVariantURLFallsBackToMaster(t *testing.T) {
|
|
master := "https://example.com/master.m3u8"
|
|
got := bestHLSVariantURL(master, "#EXTM3U\n#comment")
|
|
if got != master {
|
|
t.Fatalf("url = %q, want %q", got, master)
|
|
}
|
|
}
|
|
|
|
func TestGetMetadataArtistPaginatesAlbums(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch r.URL.Path {
|
|
case "/v1/sessions":
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"countryCode": "US", "userId": 123})
|
|
case "/v1/artists/9":
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"id": 9, "name": "Artist X"})
|
|
case "/v1/artists/9/albums":
|
|
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
|
|
filter := r.URL.Query().Get("filter")
|
|
if filter == "" {
|
|
if offset == 0 {
|
|
items := make([]any, 0, 100)
|
|
for i := 0; i < 100; i++ {
|
|
items = append(items, map[string]any{"id": i + 1})
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"items": items})
|
|
return
|
|
}
|
|
if offset == 100 {
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"items": []any{map[string]any{"id": 101}}})
|
|
return
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"items": []any{}})
|
|
return
|
|
}
|
|
if filter == "EPSANDSINGLES" {
|
|
if offset == 0 {
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"items": []any{map[string]any{"id": 101}, map[string]any{"id": 102}}})
|
|
return
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"items": []any{}})
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
default:
|
|
w.WriteHeader(http.StatusNotFound)
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
cfgData := config.DefaultConfigData()
|
|
cfgData.Tidal.AccessToken = "token"
|
|
cfgData.Tidal.CountryCode = "US"
|
|
c := New(&config.Config{File: cfgData, Session: cfgData})
|
|
c.baseURL = ts.URL + "/v1"
|
|
|
|
if err := c.Login(context.Background()); err != nil {
|
|
t.Fatalf("login err = %v", err)
|
|
}
|
|
meta, err := c.GetMetadata(context.Background(), "9", "artist")
|
|
if err != nil {
|
|
t.Fatalf("GetMetadata() err = %v", err)
|
|
}
|
|
albumsObj, _ := meta["albums"].(map[string]any)
|
|
items, _ := albumsObj["items"].([]map[string]any)
|
|
if len(items) != 102 {
|
|
t.Fatalf("albums len = %d, want 102", len(items))
|
|
}
|
|
}
|