forked from
rocksky.app/rocksky
A decentralized music tracking and discovery platform built on AT Protocol 馃幍
1use super::types::{Album, Artist, SearchResponse};
2use anyhow::Error;
3
4pub const BASE_URL: &str = "https://api.spotify.com/v1";
5
6pub struct SpotifyClient {
7 token: String,
8}
9
10impl SpotifyClient {
11 pub fn new(token: &str) -> Self {
12 SpotifyClient {
13 token: token.to_string(),
14 }
15 }
16
17 pub async fn search(&self, query: &str) -> Result<SearchResponse, Error> {
18 let url = format!("{}/search", BASE_URL);
19 let client = reqwest::Client::new();
20 let response = client
21 .get(&url)
22 .bearer_auth(&self.token)
23 .query(&[("type", "track"), ("q", query)])
24 .send()
25 .await?;
26 let result = response.json().await?;
27 Ok(result)
28 }
29
30 pub async fn get_album(&self, id: &str) -> Result<Option<Album>, Error> {
31 let url = format!("{}/albums/{}", BASE_URL, id);
32 let client = reqwest::Client::new();
33 let response = client.get(&url).bearer_auth(&self.token).send().await?;
34
35 let headers = response.headers().clone();
36 let data = response.text().await?;
37
38 if data == "Too many requests" {
39 tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_album");
40 return Ok(None);
41 }
42
43 Ok(Some(serde_json::from_str(&data)?))
44 }
45
46 pub async fn get_artist(&self, id: &str) -> Result<Option<Artist>, Error> {
47 let url = format!("{}/artists/{}", BASE_URL, id);
48 let client = reqwest::Client::new();
49 let response = client.get(&url).bearer_auth(&self.token).send().await?;
50
51 let headers = response.headers().clone();
52 let data = response.text().await?;
53
54 if data == "Too many requests" {
55 tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_artist");
56 return Ok(None);
57 }
58
59 Ok(Some(serde_json::from_str(&data)?))
60 }
61}