A decentralized music tracking and discovery platform built on AT Protocol 馃幍 rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz
at main 61 lines 1.9 kB view raw
1use anyhow::Error; 2use reqwest::Client; 3 4use crate::types::{self, token::AccessToken}; 5 6pub async fn refresh_token( 7 token: &str, 8 client_id: &str, 9 client_secret: &str, 10) -> Result<AccessToken, Error> { 11 let client = Client::new(); 12 13 let response = client 14 .post("https://accounts.spotify.com/api/token") 15 .basic_auth(&client_id, Some(client_secret)) 16 .form(&[ 17 ("grant_type", "refresh_token"), 18 ("refresh_token", token), 19 ("client_id", &client_id), 20 ]) 21 .send() 22 .await?; 23 let token = response.json::<AccessToken>().await?; 24 Ok(token) 25} 26 27pub async fn get_user_playlists( 28 token: String, 29 client_id: String, 30 client_secret: String, 31) -> Result<Vec<types::playlist::Playlist>, Error> { 32 let token = refresh_token(&token, &client_id, &client_secret).await?; 33 let client = Client::new(); 34 let response = client 35 .get("https://api.spotify.com/v1/me/playlists") 36 .header("Authorization", format!("Bearer {}", token.access_token)) 37 .send() 38 .await?; 39 let playlists = response.json::<types::playlist::SpotifyResponse>().await?; 40 let mut all_playlists = vec![]; 41 42 for playlist in playlists.items { 43 all_playlists.push(get_playlist(&playlist.id, &token.access_token).await?); 44 // wait for 1 second to avoid rate limiting 45 tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; 46 } 47 48 Ok(all_playlists) 49} 50 51pub async fn get_playlist(id: &str, token: &str) -> Result<types::playlist::Playlist, Error> { 52 let client = Client::new(); 53 let response = client 54 .get(format!("https://api.spotify.com/v1/playlists/{}", id)) 55 .header("Authorization", format!("Bearer {}", token)) 56 .send() 57 .await?; 58 59 let playlist = response.json::<types::playlist::Playlist>().await?; 60 Ok(playlist) 61}