diff --git a/src/main.rs b/src/main.rs index 6a45cb8..c10e223 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,10 @@ use rspotify::{ - prelude::*, - scopes, AuthCodeSpotify, Credentials, OAuth, + model::{PlaylistId, TimeRange, UserId}, + prelude::*, scopes, AuthCodeSpotify, ClientError, Credentials, OAuth }; +use futures_util::TryStreamExt; + #[tokio::main] async fn main() -> Result<(), Box> { dotenvy::dotenv()?; @@ -28,7 +30,7 @@ async fn main() -> Result<(), Box> { let oauth = OAuth { redirect_uri, - scopes: scopes!(), + scopes: scopes!("playlist-read-private playlist-modify-private user-top-read"), ..Default::default() }; @@ -38,5 +40,35 @@ async fn main() -> Result<(), Box> { let url = spotify.get_authorize_url(false)?; spotify.prompt_for_token(&url).await?; + let mut top_tracks = spotify.current_user_top_tracks(Some(TimeRange::ShortTerm)); + let mut top_track_ids = Vec::new(); + + while let Some(top_track) = top_tracks.try_next().await? && top_track_ids.len() < track_limit { + if let Some(track_id) = top_track.id { + top_track_ids.push(track_id); + } else { + println!("Warning: Track ID not available (probably a local track), ignoring"); + } + } + + println!("Adding top tracks to playlist: {}", playlist_name); + let playlist_id = find_or_create_playlist(&spotify, &playlist_name, spotify.me().await?.id).await?; + spotify.playlist_replace_items(playlist_id, top_track_ids.into_iter().map(|track| PlayableId::Track(track))).await?; Ok(()) } + +async fn find_or_create_playlist<'a>(spotify: &AuthCodeSpotify, + playlist_name: &str, user_id: UserId<'_>) -> Result, ClientError> { + + let mut playlists = spotify.current_user_playlists(); + + while let Some(playlist) = playlists.try_next().await? { + if playlist.name == playlist_name { + return Ok(playlist.id); + } + } + + let playlist = spotify.user_playlist_create(user_id, playlist_name, Some(false), Some(false), Some("")).await?; + + Ok(playlist.id) +}