spotify_cli/spotify/
track.rs1use anyhow::{Context, bail};
2use reqwest::Method;
3use reqwest::blocking::Client as HttpClient;
4
5use crate::error::Result;
6use crate::spotify::auth::AuthService;
7use crate::spotify::base::api_base;
8use crate::spotify::error::format_api_error;
9
10#[derive(Debug, Clone)]
12pub struct TrackClient {
13 http: HttpClient,
14 auth: AuthService,
15}
16
17impl TrackClient {
18 pub fn new(http: HttpClient, auth: AuthService) -> Self {
19 Self { http, auth }
20 }
21
22 pub fn like(&self, track_id: &str) -> Result<()> {
23 let path = format!("/me/tracks?ids={}", track_id);
24 self.send(Method::PUT, &path)
25 }
26
27 pub fn unlike(&self, track_id: &str) -> Result<()> {
28 let path = format!("/me/tracks?ids={}", track_id);
29 self.send(Method::DELETE, &path)
30 }
31
32 fn send(&self, method: Method, path: &str) -> Result<()> {
33 let token = self.auth.token()?;
34 let url = format!("{}{}", api_base(), path);
35
36 let response = self
37 .http
38 .request(method, url)
39 .bearer_auth(token.access_token)
40 .body(Vec::new())
41 .send()
42 .context("spotify request failed")?;
43
44 if response.status().is_success() {
45 return Ok(());
46 }
47
48 let status = response.status();
49 let body = response.text().unwrap_or_else(|_| "<no body>".to_string());
50 bail!(format_api_error("spotify request failed", status, &body))
51 }
52}