From b2ea07c41e48bd8fcdfd21f9005fb65f2cdd09f8 Mon Sep 17 00:00:00 2001 From: zarzet <42882290+zarzet@users.noreply.github.com> Date: Thu, 17 Sep 2026 02:12:10 +0700 Subject: [PATCH] fix: preserve source artist credits when downloading Keep full source artist credits in download responses and embedded tags, falling back to provider credits only when the source is empty. Add regression coverage for new and existing files. --- .../src/backend/download_latency_tests.rs | 48 +++++++++++++++++++ .../extensions/src/backend/downloads.rs | 3 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/rust_backend/crates/extensions/src/backend/download_latency_tests.rs b/rust_backend/crates/extensions/src/backend/download_latency_tests.rs index e07667e6..2d2e9ee2 100644 --- a/rust_backend/crates/extensions/src/backend/download_latency_tests.rs +++ b/rust_backend/crates/extensions/src/backend/download_latency_tests.rs @@ -10,6 +10,54 @@ use std::thread; const RECORDING: &str = r#"{"recordings":[{"tags":[{"name":"rock","count":1}],"releases":[{"title":"Album","artist-credit":[{"name":"Album Artist"}]}]}]}"#; const CATALOG: &str = r#"{"id":7,"album":{"id":9},"genres":{"data":[{"name":"Jazz"}]},"label":"Label","copyright":"Copyright"}"#; +#[test] +fn download_preserves_source_artist_credits_in_response_and_embedded_tags() { + let manifest = ExtensionManifest { + name: "audio-provider".into(), + ..Default::default() + }; + for (source, provided, expected) in [ + ( + "Lead Artist & Guest Artist", + "Lead Artist", + "Lead Artist & Guest Artist", + ), + ( + "", + "Lead Artist & Guest Artist", + "Lead Artist & Guest Artist", + ), + ( + " ", + "Lead Artist & Guest Artist", + "Lead Artist & Guest Artist", + ), + ( + "Lead Artist & Guest Artist", + "", + "Lead Artist & Guest Artist", + ), + ] { + let request = DownloadRequest { + track_name: "Track".into(), + artist_name: source.into(), + ..Default::default() + }; + let result = json!({"artist": provided}); + for exists in [false, true] { + let response = success(&request, &result, "track.flac", exists, &manifest, &|| { + Ok(()) + }) + .unwrap(); + assert_eq!(response["artist"], expected); + assert_eq!( + download_metadata_fields(&request, &response)["ARTIST"], + expected + ); + } + } +} + fn network() -> (Arc, Arc) { let certificate = rcgen::generate_simple_self_signed(vec!["127.0.0.1".into()]).unwrap(); let config = rustls::ServerConfig::builder_with_provider(Arc::new( diff --git a/rust_backend/crates/extensions/src/backend/downloads.rs b/rust_backend/crates/extensions/src/backend/downloads.rs index 33bd310a..9c7c32f8 100644 --- a/rust_backend/crates/extensions/src/backend/downloads.rs +++ b/rust_backend/crates/extensions/src/backend/downloads.rs @@ -1648,7 +1648,8 @@ fn success( "explicit":request.explicit || result["explicit"] == true}); for (key, requested, prefer_request) in [ ("title", request.track_name.trim(), true), - ("artist", request.artist_name.as_str(), false), + // Preserve source credits: an audio provider may list only the lead artist. + ("artist", request.artist_name.trim(), true), ("album", request.album_name.trim(), true), ("album_artist", request.album_artist.as_str(), true), ("release_date", request.release_date.trim(), true),