implement native Deezer download/decrypt pipeline

Replace Deezer yt-dlp usage with native ARL session + media.get_url resolution, add BF_CBC_STRIPE decryption in downloader, and wire cipher-aware Deezer downloads through the main rip pipeline. Includes validation hardening and metadata/source-id improvements used by tagging flows.
This commit is contained in:
2026-04-21 00:48:07 +02:00
parent 0ba8faa943
commit 26c9d50fac
10 changed files with 569 additions and 260 deletions

View File

@@ -70,6 +70,9 @@ func TestGetPlaylistMetadata(t *testing.T) {
if len(items) != 2 {
t.Fatalf("playlist items len = %d, want 2", len(items))
}
if stringFromAny(meta["id"]) != "https://soundcloud.com/a/sets/road-trip" {
t.Fatalf("playlist id not canonical: %q", stringFromAny(meta["id"]))
}
}
func TestSearchTrack(t *testing.T) {
@@ -95,6 +98,13 @@ func TestSearchTrack(t *testing.T) {
if len(items) != 1 {
t.Fatalf("items len = %d, want 1", len(items))
}
item0, ok := items[0].(map[string]any)
if !ok {
t.Fatalf("expected first item map")
}
if stringFromAny(item0["id"]) != "https://soundcloud.com/a/b" {
t.Fatalf("track search id not canonical: %q", stringFromAny(item0["id"]))
}
}
func TestSearchPlaylist(t *testing.T) {
@@ -133,6 +143,13 @@ func TestSearchPlaylist(t *testing.T) {
if len(items) != 1 {
t.Fatalf("items len = %d, want 1", len(items))
}
item0, ok := items[0].(map[string]any)
if !ok {
t.Fatalf("expected first item map")
}
if stringFromAny(item0["id"]) != "https://soundcloud.com/a/sets/road-trip" {
t.Fatalf("playlist search id not canonical: %q", stringFromAny(item0["id"]))
}
}
func TestLoginShowsYtDlpHint(t *testing.T) {
@@ -169,6 +186,9 @@ func TestTrackMetadataIncludesExplicitAndISRC(t *testing.T) {
if stringFromAny(meta["source_track_id"]) != "9876" {
t.Fatalf("source_track_id = %q, want 9876", stringFromAny(meta["source_track_id"]))
}
if stringFromAny(nestedMap(meta, "album")["title"]) != "T" {
t.Fatalf("album title mismatch: %#v", nestedMap(meta, "album"))
}
}
func TestCanonicalSoundcloudURL(t *testing.T) {