diff options
Diffstat (limited to 'src/spotify.rs')
-rw-r--r-- | src/spotify.rs | 95 |
1 files changed, 64 insertions, 31 deletions
diff --git a/src/spotify.rs b/src/spotify.rs index 0e18c43..ea05b14 100644 --- a/src/spotify.rs +++ b/src/spotify.rs @@ -1,19 +1,16 @@ use crate::database; use crate::errors::Error; use lazy_static::lazy_static; -use rspotify::client::{ApiError, Spotify}; -use rspotify::model::page::Page; +use rand::{Rng, RngCore}; +use rspotify::client::{ClientError, Spotify}; +use rspotify::model::enums::TimeRange; use rspotify::model::playlist::*; use rspotify::model::track::*; -use rspotify::oauth2::{SpotifyClientCredentials, SpotifyOAuth}; -use rspotify::senum::TimeRange; -use rspotify::util::process_token; use std::collections::HashMap; use std::sync::{Arc, Mutex}; lazy_static! { - static ref CACHE: Arc<Mutex<HashMap<String, SpotifyOAuth>>> = - Arc::new(Mutex::new(HashMap::new())); + static ref CACHE: Arc<Mutex<HashMap<String, Spotify>>> = Arc::new(Mutex::new(HashMap::new())); } static CHUNK_SIZE: u32 = 50; @@ -23,8 +20,7 @@ macro_rules! get_items { $index = 0; let mut result: Vec<$t> = Vec::new(); loop { - let res: Result<Page<$t>, failure::Error> = $spotify_call.await; - match res { + match $spotify_call.await { Ok(mut page) => { $index += CHUNK_SIZE; if page.items.is_empty() { @@ -32,8 +28,8 @@ macro_rules! get_items { } result.append(&mut page.items); } - Err(e) => match e.downcast::<ApiError>() { - Ok(ApiError::RateLimited(x)) => { + Err(e) => match e { + ClientError::RateLimited(x) => { std::thread::sleep(std::time::Duration::from_secs(x.unwrap_or(5) as u64)) } @@ -66,22 +62,23 @@ pub async fn load_profile(db_uid: i32, spotify_uid: &str, spotify: Spotify) -> R spotify.current_user_top_tracks(CHUNK_SIZE, index, TimeRange::MediumTerm) ); for track in library { - if let Err(e) = database::insert_track(db_uid, track.track, 5) { + if let Err(e) = database::insert_track(db_uid, track.track, 5).await { println!("failed to load track to db: {:?}", e) }; } for (pos, track) in top_tracks.iter().enumerate() { let weight = ((50.0 - pos as f64) / 50.0 * 10.0).floor() as i32; - if let Err(e) = database::insert_track(db_uid, track.clone(), 5 + weight) { + if let Err(e) = database::insert_track(db_uid, track.clone(), 5 + weight).await { println!("failed to load track to db: {:?}", e) }; } + let playlists = playlists.iter().map(|x| x.clone()); for playlist in playlists { let tracks = get_items!( - PlaylistTrack, + PlaylistItem, index, - spotify.user_playlist_tracks( - spotify_uid.as_ref(), + spotify.playlist_tracks( + //spotify_uid.as_ref(), &playlist.id, None, CHUNK_SIZE, @@ -89,8 +86,9 @@ pub async fn load_profile(db_uid: i32, spotify_uid: &str, spotify: Spotify) -> R None, ) ); - for track in tracks.iter().map(|x| x.track.clone()).flatten() { - if let Err(e) = database::insert_track(db_uid, track, 1) { + let tracks: Vec<FullTrack> = tracks.iter().map(|x| x.track.clone()).flatten().collect(); + for track in tracks { + if let Err(e) = database::insert_track(db_uid, track, 1).await { println!("failed to load track to db: {:?}", e) }; } @@ -98,21 +96,37 @@ pub async fn load_profile(db_uid: i32, spotify_uid: &str, spotify: Spotify) -> R Ok(()) } -pub async fn auth_user(name: &str, url: String) -> Result<(String, Spotify), Error> { - let mut oauth = { - let mut guard = CACHE.lock()?; +use rspotify::client::SpotifyBuilder; +use rspotify::oauth2::{CredentialsBuilder, OAuthBuilder}; + +/// Generate `length` random chars +fn generate_random_uuid(length: usize) -> String { + let alphanum: &[u8] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".as_bytes(); + let mut buf = vec![0u8; length]; + rand::thread_rng().fill_bytes(buf.as_mut_slice()); + let range = alphanum.len(); + + buf.iter() + .map(|byte| alphanum[*byte as usize % range] as char) + .collect() +} + +pub async fn auth_user(name: &str, code: &str) -> Result<(String, Spotify), Error> { + let mut spotify = { + let mut guard = (*CACHE).lock()?; guard.remove(name)? }; - println!("auth: {:?} url: {}", oauth, url); - let mut token_string = format!("?code={}", url); - let token_info = process_token(&mut oauth, &mut token_string); - let client_credential = SpotifyClientCredentials::default() + println!("auth: {:?} url: {}", name, code); + spotify.request_user_token(code).await?; + //let token_info = process_token(&mut oauth, &mut token_string); + /*let client_credential = SpotifyClientCredentials::default() .token_info(token_info.await?) .build(); let spotify = Spotify::default() - .client_credentials_manager(client_credential) - .build(); + .client_credentials_manager(client_credential) + .build();*/ let user_id = spotify .current_user() .await @@ -122,13 +136,32 @@ pub async fn auth_user(name: &str, url: String) -> Result<(String, Spotify), Err } pub fn token(name: String) -> Result<String, Error> { - let state = rspotify::util::generate_random_string(16); + let scope = "playlist-read-private playlist-read-collaborative user-read-private user-follow-read user-library-read"; + + let oauth = OAuthBuilder::from_env() + .scope(scope.split_whitespace().map(|x| x.to_owned()).collect()) + .build() + .unwrap(); + let creds = CredentialsBuilder::from_env().build().unwrap(); + + let spotify = SpotifyBuilder::default() + .credentials(creds) + .oauth(oauth) + .build() + .unwrap(); + + let auth_url = spotify.get_authorize_url(false).unwrap(); + + //let token = spotify.token.as_ref().unwrap(); + + /*let state = rspotify::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); + */ + //let auth_url = oauth.get_authorize_url(Some(&state), None); + let mut guard = (*CACHE).lock()?; + guard.insert(name, spotify); Ok(auth_url) } |