use std::sync::{Arc, Mutex};
use reqwest::Url;
use rouille::{Response, Server};
use spotify_rs::{model::user::TimeRange, AuthCodeClient, RedirectUrl};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenvy::from_path("spotify-rs/examples/.env")?;
let client_id = dotenvy::var("CLIENT_ID")?;
let client_secret = dotenvy::var("CLIENT_SECRET")?;
let redirect_uri = dotenvy::var("REDIRECT_URI")?;
let redirect_url = Url::parse(&redirect_uri).unwrap();
let redirect_url_host = format!(
"{}:{}",
redirect_url.host_str().unwrap(),
redirect_url.port().unwrap()
);
let scopes = vec!["user-top-read", "user-follow-read"];
let (tx, rx) = std::sync::mpsc::sync_channel(1);
tokio::spawn(async move {
let sent = Arc::new(Mutex::new(false));
let sent2 = sent.clone();
let server = Server::new(redirect_url_host, move |request| {
let url = Url::parse(&format!("http://{}", request.raw_url())).unwrap();
let mut queries: Vec<_> = url.query_pairs().into_owned().collect();
let auth_code = queries.remove(0).1;
let csrf_state = queries.remove(0).1;
tx.send((auth_code, csrf_state)).unwrap();
*sent2.lock().unwrap() = true;
Response::html("<h1>You may close this page</h1><script>window.close()</script>")
})
.unwrap();
while !*sent.lock().unwrap() {
server.poll();
}
});
let auto_refresh = false;
let (client, url) = AuthCodeClient::new(
client_id,
client_secret,
scopes,
RedirectUrl::new(redirect_uri)?,
auto_refresh,
);
println!("Navigate to {url} to complete the OAuth process.");
let (auth_code, csrf_state) = rx.recv().unwrap();
let spotify = client.authenticate(auth_code, csrf_state).await?;
let top_tracks = spotify_rs::current_user_top_tracks()
.limit(5)
.time_range(TimeRange::ShortTerm)
.get(&spotify)
.await?;
let tracks = top_tracks.items;
for (i, track) in tracks.iter().enumerate() {
if let Some(t) = track {
println!("Top track #{}: {}", i + 1, t.name)
}
}
let followed_artists = spotify_rs::followed_artists()
.limit(10)
.get(&spotify)
.await?;
let artists = followed_artists
.filtered_items()
.into_iter()
.map(|a| a.name)
.collect::<Vec<_>>()
.join(", ");
println!("Followed artists: {artists}");
Ok(())
}