From 6ae7c43414583fa4ee9f3702dbf835656c21a106 Mon Sep 17 00:00:00 2001 From: Tsiry Sandratraina Date: Sun, 28 Sep 2025 14:18:48 +0300 Subject: [PATCH] fix: improve artist matching logic in scrobble functions to prevent mismatches --- crates/scrobbler/src/scrobbler.rs | 78 ++++++++++++++++------------ crates/webscrobbler/src/scrobbler.rs | 33 ++++++------ 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/crates/scrobbler/src/scrobbler.rs b/crates/scrobbler/src/scrobbler.rs index d28d967f..e18851b4 100644 --- a/crates/scrobbler/src/scrobbler.rs +++ b/crates/scrobbler/src/scrobbler.rs @@ -378,24 +378,38 @@ pub async fn scrobble_v1( .await?; if let Some(track) = result.tracks.items.first() { - tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Spotify (track)"); - scrobble.album = Some(track.album.name.clone()); - let mut track = track.clone(); + let artists = track + .artists + .iter() + .map(|a| a.name.to_lowercase().clone()) + .collect::>() + .join(", ") + .to_lowercase(); - if let Some(album) = spotify_client.get_album(&track.album.id).await? { - track.album = album; - } + // check if artists don't contain the scrobble artist (to avoid wrong matches) + if !artists.contains(&scrobble.artist.to_lowercase()) { + tracing::warn!(artist = %artist, track = ?track, "Artist mismatch, skipping"); + return Ok(()); + } else { + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Spotify (track)"); + scrobble.album = Some(track.album.name.clone()); + let mut track = track.clone(); - if let Some(artist) = spotify_client - .get_artist(&track.album.artists[0].id) - .await? - { - track.album.artists[0] = artist; - } + if let Some(album) = spotify_client.get_album(&track.album.id).await? { + track.album = album; + } - rocksky::scrobble(cache, &did, track.into(), scrobble.timestamp).await?; - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - return Ok(()); + if let Some(artist) = spotify_client + .get_artist(&track.album.artists[0].id) + .await? + { + track.album.artists[0] = artist; + } + + rocksky::scrobble(cache, &did, track.into(), scrobble.timestamp).await?; + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + return Ok(()); + } } let query = format!( @@ -616,7 +630,7 @@ pub async fn scrobble_listenbrainz( let artists = track .artists .iter() - .map(|a| a.name.clone()) + .map(|a| a.name.to_lowercase().clone()) .collect::>() .join(", ") .to_lowercase(); @@ -625,26 +639,26 @@ pub async fn scrobble_listenbrainz( if !artists.contains(&scrobble.artist.to_lowercase()) { tracing::warn!(artist = %artist, track = ?track, "Artist mismatch, skipping"); return Ok(()); - } + } else { + tracing::info!("Spotify (track)"); + scrobble.album = Some(track.album.name.clone()); + let mut track = track.clone(); - tracing::info!("Spotify (track)"); - scrobble.album = Some(track.album.name.clone()); - let mut track = track.clone(); + if let Some(album) = spotify_client.get_album(&track.album.id).await? { + track.album = album; + } - if let Some(album) = spotify_client.get_album(&track.album.id).await? { - track.album = album; - } + if let Some(artist) = spotify_client + .get_artist(&track.album.artists[0].id) + .await? + { + track.album.artists[0] = artist; + } - if let Some(artist) = spotify_client - .get_artist(&track.album.artists[0].id) - .await? - { - track.album.artists[0] = artist; + rocksky::scrobble(cache, &did, track.into(), scrobble.timestamp).await?; + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + return Ok(()); } - - rocksky::scrobble(cache, &did, track.into(), scrobble.timestamp).await?; - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - return Ok(()); } let query = format!( diff --git a/crates/webscrobbler/src/scrobbler.rs b/crates/webscrobbler/src/scrobbler.rs index 3075381a..b8beb9db 100644 --- a/crates/webscrobbler/src/scrobbler.rs +++ b/crates/webscrobbler/src/scrobbler.rs @@ -131,7 +131,7 @@ pub async fn scrobble( let artists = track .artists .iter() - .map(|a| a.name.clone()) + .map(|a| a.name.to_lowercase().clone()) .collect::>() .join(", ") .to_lowercase(); @@ -139,26 +139,25 @@ pub async fn scrobble( // check if artists don't contain the scrobble artist (to avoid wrong matches) if !artists.contains(&scrobble.data.song.parsed.artist.trim().to_lowercase()) { tracing::warn!(artist = %artist, track = ?track, "Artist mismatch, skipping"); - return Ok(()); - } + } else { + tracing::info!("Spotify (track)"); + let mut track = track.clone(); - tracing::info!("Spotify (track)"); - let mut track = track.clone(); + if let Some(album) = spotify_client.get_album(&track.album.id).await? { + track.album = album; + } - if let Some(album) = spotify_client.get_album(&track.album.id).await? { - track.album = album; - } + if let Some(artist) = spotify_client + .get_artist(&track.album.artists[0].id) + .await? + { + track.album.artists[0] = artist; + } - if let Some(artist) = spotify_client - .get_artist(&track.album.artists[0].id) - .await? - { - track.album.artists[0] = artist; + rocksky::scrobble(cache, &did, track.into(), scrobble.time).await?; + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + return Ok(()); } - - rocksky::scrobble(cache, &did, track.into(), scrobble.time).await?; - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - return Ok(()); } let query = format!( -- 2.51.2