From 90b4560a2dbac159e72746b50987d12196af3e78 Mon Sep 17 00:00:00 2001 From: Henrik Friedrichsen Date: Sat, 22 Jul 2023 13:39:04 +0200 Subject: [PATCH] Gracefully handle tracks without IDs As reported in #1231: Local files in playlists have no IDs. When trying to delete them ncspot crashes as it tries to extract a track ID. --- src/model/playable.rs | 16 +++++++++------- src/spotify_api.rs | 17 ++++++++++++----- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/model/playable.rs b/src/model/playable.rs index 0966a6f..6b5e3dc 100644 --- a/src/model/playable.rs +++ b/src/model/playable.rs @@ -139,15 +139,17 @@ impl From<&PlayableItem> for Playable { } } -impl From<&Playable> for rspotify::prelude::PlayableId<'_> { +impl From<&Playable> for Option> { fn from(p: &Playable) -> Self { match p { - Playable::Track(t) => rspotify::prelude::PlayableId::Track( - rspotify::model::TrackId::from_id(t.id.clone().unwrap()).unwrap(), - ), - Playable::Episode(e) => rspotify::prelude::PlayableId::Episode( - rspotify::model::EpisodeId::from_id(e.id.clone()).unwrap(), - ), + Playable::Track(t) => { + t.id.clone() + .and_then(|id| rspotify::model::TrackId::from_id(id).ok()) + .map(rspotify::prelude::PlayableId::Track) + } + Playable::Episode(e) => rspotify::model::EpisodeId::from_id(e.id.clone()) + .map(rspotify::prelude::PlayableId::Episode) + .ok(), } } } diff --git a/src/spotify_api.rs b/src/spotify_api.rs index b94abf0..f3ef229 100644 --- a/src/spotify_api.rs +++ b/src/spotify_api.rs @@ -155,7 +155,10 @@ impl WebApi { position: Option, ) -> bool { self.api_with_retry(|api| { - let trackids: Vec = tracks.iter().map(|playable| playable.into()).collect(); + let trackids: Vec = tracks + .iter() + .filter_map(|playable| playable.into()) + .collect(); api.playlist_add_items( PlaylistId::from_id(playlist_id).unwrap(), trackids.iter().map(|id| id.as_ref()), @@ -172,8 +175,10 @@ impl WebApi { playables: &[Playable], ) -> bool { self.api_with_retry(move |api| { - let playable_ids: Vec = - playables.iter().map(|playable| playable.into()).collect(); + let playable_ids: Vec = playables + .iter() + .filter_map(|playable| playable.into()) + .collect(); let positions = playables .iter() .map(|playable| [playable.list_index() as u32]) @@ -207,8 +212,10 @@ impl WebApi { }; if let Some(()) = self.api_with_retry(|api| { - let playable_ids: Vec = - tracks.iter().map(|playable| playable.into()).collect(); + let playable_ids: Vec = tracks + .iter() + .filter_map(|playable| playable.into()) + .collect(); api.playlist_replace_items( PlaylistId::from_id(id).unwrap(), playable_ids.iter().map(|p| p.as_ref()),