From 51bc62b4346446dab84e02aa4533d4a4340b7485 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Tue, 3 Mar 2020 17:58:44 +0100 Subject: Macro foo --- src/spotify.rs | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 src/spotify.rs (limited to 'src/spotify.rs') diff --git a/src/spotify.rs b/src/spotify.rs new file mode 100644 index 0000000..b9a1147 --- /dev/null +++ b/src/spotify.rs @@ -0,0 +1,172 @@ +use crate::database; +use crate::errors::Error; +use lazy_static::lazy_static; +use rspotify::spotify::client::{ApiError, Spotify}; +use rspotify::spotify::model::playlist::FullPlaylist; +use rspotify::spotify::oauth2::{SpotifyClientCredentials, SpotifyOAuth}; +use rspotify::spotify::util::process_token; +use std::collections::HashMap; +use std::sync::{Arc, Mutex}; + +lazy_static! { + static ref CACHE: Arc>> = + Arc::new(Mutex::new(HashMap::new())); +} + +static CHUNK_SIZE: i32 = 50; + +macro_rules! get_items { + ($func_name:ident, $spotify_call:stmt, $t: ty) => { + fn $func_name(spotify_uid: &str, spotify: &mut Spotify) -> Result, Error> { + let mut index = 0; + let mut result = Vec::new(); + loop { + match $spotify_call { + Ok(items) => { + index += CHUNK_SIZE; + if items.items.is_empty() { + break; + } + result.append(items.items); + } + Err(e) => match e.downcast::() { + Ok(ApiError::RateLimited(x)) => std::thread::sleep( + std::time::Duration::from_secs(x.unwrap_or(5) as u64), + ), + + cause => { + println!("Error: {:?}", cause); + break; + } + }, + } + } + Ok((result)) + } + }; +} + +get_items!( + playlists, + spotify.user_playlists(spotify_uid.as_ref(), Some(CHUNK_SIZE), Some(playlist_index)), + FullPlaylist +); +fn load_playlist(spotify_uid: &str, spotify: &mut Spotify) -> Result, Error> { + let mut playlist_index = 0; + loop { + match spotify.user_playlists(spotify_uid.as_ref(), Some(CHUNK_SIZE), Some(playlist_index)) { + Ok(playlists) => { + playlist_index += chunk_size; + if playlists.items.is_empty() { + break; + } + for playlist in playlists.items {} + } + Err(e) => match e.downcast::() { + Ok(ApiError::RateLimited(x)) => { + std::thread::sleep(std::time::Duration::from_secs(x.unwrap_or(5) as u64)) + } + + cause => { + println!("Error: {:?}", cause); + break; + } + }, + } + } + Ok(()) +} + +pub fn load_profile(db_uid: i32, spotify_uid: &str, spotify: Spotify) -> Result<(), Error> { + let mut playlist_index = 0; + loop { + match spotify.user_playlists(spotify_uid.as_ref(), Some(chunk_size), Some(playlist_index)) { + Ok(playlists) => { + playlist_index += chunk_size; + if playlists.items.is_empty() { + break; + } + for playlist in playlists.items { + println!("playlist: {:?}", playlist.name); + let mut track_index = 0; + + loop { + match spotify.user_playlist_tracks( + spotify_uid.as_ref(), + &playlist.id, + None, + Some(chunk_size), + Some(track_index), + None, + ) { + Ok(tracks) => { + track_index += chunk_size; + if tracks.items.is_empty() { + break; + } + for track in tracks.items { + if let Err(e) = insert_track(uid, track.track) { + println!("failed to load track to db: {:?}", e) + }; + } + } + Err(e) => match e.downcast::() { + Ok(ApiError::RateLimited(x)) => std::thread::sleep( + std::time::Duration::from_secs(x.unwrap_or(5) as u64), + ), + + cause => { + println!("Error: {:?}", cause); + break; + } + }, + } + } + } + } + Err(e) => match e.downcast::() { + Ok(ApiError::RateLimited(x)) => { + std::thread::sleep(std::time::Duration::from_secs(x.unwrap_or(5) as u64)) + } + + cause => { + println!("Error: {:?}", cause); + break; + } + }, + } + } + Ok(()) +} + +pub fn auth_user(name: &str, url: String) -> Result<(String, Spotify), Error> { + let mut guard = CACHE.lock()?; + let mut oauth = guard.remove(name)?; + println!("auth: {:?} url: {}", oauth, url); + let token_info = process_token(&mut oauth, &mut ("?code=".to_owned() + url.as_ref())); + let client_credential = SpotifyClientCredentials::default() + .token_info(token_info?) + .build(); + + let spotify = Spotify::default() + .client_credentials_manager(client_credential) + .build(); + let user_id = spotify + .current_user() + .map_err(|e| format!("failed to load currentuser {:?}", e))? + .id; + Ok((user_id, spotify)) +} + +#[get("/token/")] +pub fn token(name: String) -> Result { + let state = rspotify::spotify::util::generate_random_string(16); + let oauth = SpotifyOAuth::default(); + let oauth = oauth + .scope("playlist-read-private, playlist-read-collaborative, user-read-private, user-follow-read, user-library-read") + .build(); + let auth_url = oauth.get_authorize_url(Some(&state), None); + let mut guard = CACHE.lock()?; + guard.insert(name, oauth); + Ok(auth_url) +} -- cgit v1.2.3-70-g09d2