diff --git a/src/playlist.rs b/src/playlist.rs index 3b458b5..94d80dc 100644 --- a/src/playlist.rs +++ b/src/playlist.rs @@ -32,35 +32,13 @@ impl Playlist { } fn get_all_tracks(&self, spotify: Spotify) -> Vec { - let mut collected_tracks = Vec::new(); - - let mut tracks_result = spotify.user_playlist_tracks(&self.id, 100, 0); - while let Some(ref tracks) = tracks_result.clone() { - for (index, listtrack) in tracks.items.iter().enumerate() { - if let Some(track) = &listtrack.track { - let mut t: Track = track.into(); - t.list_index = index; - t.added_at = Some(listtrack.added_at); - collected_tracks.push(t); - } - } - debug!("got {} tracks", tracks.items.len()); - - // load next batch if necessary - tracks_result = match tracks.next { - Some(_) => { - debug!("requesting tracks again.."); - spotify.user_playlist_tracks( - &self.id, - 100, - tracks.offset + tracks.items.len() as u32, - ) - } - None => None, - } + let tracks_result = spotify.user_playlist_tracks(&self.id); + while !tracks_result.at_end() { + tracks_result.next(); } - collected_tracks + let tracks = tracks_result.items.read().unwrap(); + tracks.clone() } pub fn has_track(&self, track_id: &str) -> bool { diff --git a/src/spotify.rs b/src/spotify.rs index e83e10c..b100c53 100644 --- a/src/spotify.rs +++ b/src/spotify.rs @@ -14,7 +14,7 @@ use rspotify::blocking::client::Spotify as SpotifyAPI; use rspotify::model::album::{FullAlbum, SavedAlbum}; use rspotify::model::artist::FullArtist; use rspotify::model::page::{CursorBasedPage, Page}; -use rspotify::model::playlist::{FullPlaylist, PlaylistTrack}; +use rspotify::model::playlist::FullPlaylist; use rspotify::model::search::SearchResult; use rspotify::model::track::{FullTrack, SavedTrack, SimplifiedTrack}; use rspotify::model::user::PrivateUser; @@ -550,16 +550,46 @@ impl Spotify { ApiResult::new(MAX_LIMIT, Arc::new(fetch_page)) } - pub fn user_playlist_tracks( - &self, - playlist_id: &str, - limit: u32, - offset: u32, - ) -> Option> { - let user = self.user.as_ref().unwrap(); - self.api_with_retry(|api| { - api.user_playlist_tracks(user, playlist_id, None, limit, offset, self.country) - }) + pub fn user_playlist_tracks(&self, playlist_id: &str) -> ApiResult { + const MAX_LIMIT: u32 = 100; + let spotify = self.clone(); + let playlist_id = playlist_id.to_string(); + let fetch_page = move |offset: u32| { + debug!( + "fetching playlist {} tracks, offset: {}", + playlist_id, offset + ); + spotify.api_with_retry(|api| { + match api.user_playlist_tracks( + spotify.user.as_ref().unwrap(), + &playlist_id, + None, + MAX_LIMIT, + offset, + spotify.country, + ) { + Ok(page) => Ok(ApiPage { + offset: page.offset, + total: page.total, + items: page + .items + .iter() + .enumerate() + .flat_map(|(index, pt)| { + pt.track.as_ref().map(|t| { + let mut track: Track = t.into(); + track.added_at = Some(pt.added_at); + track.list_index = page.offset as usize + index; + track + }) + }) + .collect(), + }), + Err(e) => Err(e), + } + }) + }; + ApiResult::new(MAX_LIMIT, Arc::new(fetch_page)) } pub fn full_album(&self, album_id: &str) -> Option {