mirror of
https://git.sr.ht/~joren/streamrip-go
synced 2026-06-17 15:05:39 +02:00
add CLI parity flags and expand provider support
This brings the Go CLI closer to upstream behavior with global flag handling and clearer resolve failures, while adding Tidal video downloads plus initial Deezer and SoundCloud no-account flows for broader end-to-end coverage.
This commit is contained in:
@@ -51,22 +51,35 @@ type fakePlaylistProvider struct {
|
||||
url string
|
||||
}
|
||||
|
||||
type fakeVideoProvider struct {
|
||||
url string
|
||||
}
|
||||
|
||||
type fakeFailProvider struct{}
|
||||
|
||||
func (f *fakeAlbumProvider) Source() string { return "qobuz" }
|
||||
func (f *fakePlaylistProvider) Source() string { return "qobuz" }
|
||||
func (f *fakeVideoProvider) Source() string { return "tidal" }
|
||||
func (f *fakeAlbumProvider) Login(context.Context) error { return nil }
|
||||
func (f *fakePlaylistProvider) Login(context.Context) error {
|
||||
return nil
|
||||
}
|
||||
func (f *fakeAlbumProvider) LoggedIn() bool { return true }
|
||||
func (f *fakePlaylistProvider) LoggedIn() bool { return true }
|
||||
func (f *fakeAlbumProvider) Close() error { return nil }
|
||||
func (f *fakePlaylistProvider) Close() error { return nil }
|
||||
func (f *fakeVideoProvider) Login(context.Context) error { return nil }
|
||||
func (f *fakeAlbumProvider) LoggedIn() bool { return true }
|
||||
func (f *fakePlaylistProvider) LoggedIn() bool { return true }
|
||||
func (f *fakeVideoProvider) LoggedIn() bool { return true }
|
||||
func (f *fakeAlbumProvider) Close() error { return nil }
|
||||
func (f *fakePlaylistProvider) Close() error { return nil }
|
||||
func (f *fakeVideoProvider) Close() error { return nil }
|
||||
func (f *fakeAlbumProvider) Search(context.Context, string, string, int) ([]map[string]any, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakePlaylistProvider) Search(context.Context, string, string, int) ([]map[string]any, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakeVideoProvider) Search(context.Context, string, string, int) ([]map[string]any, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakeAlbumProvider) GetMetadata(_ context.Context, id string, mediaType string) (map[string]any, error) {
|
||||
if mediaType == "album" {
|
||||
return map[string]any{
|
||||
@@ -133,6 +146,12 @@ func (f *fakePlaylistProvider) GetMetadata(_ context.Context, id string, mediaTy
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
func (f *fakeVideoProvider) GetMetadata(_ context.Context, id string, mediaType string) (map[string]any, error) {
|
||||
if mediaType == "video" {
|
||||
return map[string]any{"title": "Live Clip"}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakeProvider) GetDownloadable(context.Context, string, int) (*provider.Downloadable, error) {
|
||||
return &provider.Downloadable{URL: f.url, Extension: "flac", Source: "qobuz"}, nil
|
||||
}
|
||||
@@ -142,6 +161,25 @@ func (f *fakeAlbumProvider) GetDownloadable(context.Context, string, int) (*prov
|
||||
func (f *fakePlaylistProvider) GetDownloadable(context.Context, string, int) (*provider.Downloadable, error) {
|
||||
return &provider.Downloadable{URL: f.url, Extension: "flac", Source: "qobuz"}, nil
|
||||
}
|
||||
func (f *fakeVideoProvider) GetDownloadable(context.Context, string, int) (*provider.Downloadable, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakeVideoProvider) GetVideoDownloadable(context.Context, string) (*provider.Downloadable, error) {
|
||||
return &provider.Downloadable{URL: f.url, Extension: "mp4", Source: "tidal"}, nil
|
||||
}
|
||||
func (f *fakeFailProvider) Source() string { return "qobuz" }
|
||||
func (f *fakeFailProvider) Login(context.Context) error { return nil }
|
||||
func (f *fakeFailProvider) LoggedIn() bool { return true }
|
||||
func (f *fakeFailProvider) Close() error { return nil }
|
||||
func (f *fakeFailProvider) Search(context.Context, string, string, int) ([]map[string]any, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakeFailProvider) GetMetadata(context.Context, string, string) (map[string]any, error) {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
func (f *fakeFailProvider) GetDownloadable(context.Context, string, int) (*provider.Downloadable, error) {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
func TestTrackRipPipeline(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
@@ -248,6 +286,88 @@ func TestAlbumRipPipeline(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestVideoRipPipeline(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
_, _ = w.Write([]byte("video-bytes"))
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
d := config.DefaultConfigData()
|
||||
d.Downloads.Folder = tmp
|
||||
d.Downloads.SourceSubdirectories = false
|
||||
cfg := &config.Config{File: d, Session: d}
|
||||
|
||||
sqlite, err := store.NewSQLite(filepath.Join(tmp, "db.sqlite"))
|
||||
if err != nil {
|
||||
t.Fatalf("NewSQLite() error = %v", err)
|
||||
}
|
||||
defer func() { _ = sqlite.Close() }()
|
||||
|
||||
m := &Main{
|
||||
Config: cfg,
|
||||
Providers: map[string]provider.Client{
|
||||
"tidal": &fakeVideoProvider{url: ts.URL},
|
||||
},
|
||||
Store: sqlite,
|
||||
DL: download.New(),
|
||||
Tagger: noopTagger{},
|
||||
Pending: nil,
|
||||
Media: nil,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
if err = m.AddByID(ctx, "tidal", "video", "v1"); err != nil {
|
||||
t.Fatalf("AddByID() error = %v", err)
|
||||
}
|
||||
if err = m.Resolve(ctx); err != nil {
|
||||
t.Fatalf("Resolve() error = %v", err)
|
||||
}
|
||||
if err = m.Rip(ctx); err != nil {
|
||||
t.Fatalf("Rip() error = %v", err)
|
||||
}
|
||||
|
||||
if _, err = os.Stat(filepath.Join(tmp, "Live Clip.mp4")); err != nil {
|
||||
t.Fatalf("expected downloaded video file: %v", err)
|
||||
}
|
||||
|
||||
ok, err := sqlite.IsDownloaded(ctx, "tidal", "v1")
|
||||
if err != nil {
|
||||
t.Fatalf("IsDownloaded() error = %v", err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatalf("expected video marked downloaded")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveAllFailedReturnsError(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
d := config.DefaultConfigData()
|
||||
d.Downloads.Folder = tmp
|
||||
cfg := &config.Config{File: d, Session: d}
|
||||
|
||||
m := &Main{
|
||||
Config: cfg,
|
||||
Providers: map[string]provider.Client{
|
||||
"qobuz": &fakeFailProvider{},
|
||||
},
|
||||
Store: store.NewDummy(),
|
||||
DL: download.New(),
|
||||
Tagger: noopTagger{},
|
||||
Pending: nil,
|
||||
Media: nil,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
if err := m.AddByID(ctx, "qobuz", "track", "x"); err != nil {
|
||||
t.Fatalf("AddByID() error = %v", err)
|
||||
}
|
||||
if err := m.Resolve(ctx); err == nil {
|
||||
t.Fatalf("expected Resolve() to return error when all items fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaylistRipPipeline(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user