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