A decentralized music tracking and discovery platform built on AT Protocol 馃幍
rocksky.app
spotify
atproto
lastfm
musicbrainz
scrobbling
listenbrainz
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}