//! Deezer client. use std::fmt::Debug; use hyper::client::{Client, HttpConnector}; use hyper::Uri; use serde::Deserialize; use crate::auth::AccessToken; use crate::errors::client::DeezerClientError; use crate::playlist::Playlist; use crate::user::{User, UserPlaylist, UserPlaylists}; /// Deezer API error. #[derive(Debug, Deserialize)] pub struct DeezerError { /// Error type. #[serde(rename = "type")] pub err_type: String, /// Error message. pub message: String, /// Error code. pub code: u32, } #[derive(Debug, Deserialize)] struct ErrorResponseBody { error: DeezerError, } /// Deezer client. pub struct DeezerClient { client: Client, api_url: &'static str, access_token: AccessToken, } impl DeezerClient { /// Creates a new Deezer client. #[must_use] pub fn new(access_token: AccessToken) -> Self { Self { client: Client::new(), api_url: "api.deezer.com", access_token, } } /// Returns the authenticated user. /// /// # Errors /// Will return Err if either sending the request or parsing the response fails. pub async fn get_me(&self) -> Result { let response = self .client .get(self.build_endpoint_uri(&"user/me".to_string())?) .await?; let body_buf = &*hyper::body::to_bytes(response).await?; let err_body_result: Result = serde_json::from_slice(body_buf); if let Ok(err_body) = err_body_result { return Err(DeezerClientError::ReceivedErrorResponse(err_body.error)); } serde_json::from_slice(body_buf).map_err(DeezerClientError::ParseResponseFailed) } /// Returns the playlists of a user. /// /// # Errors /// Will return Err if either sending the request or parsing the response fails. pub async fn get_user_playlists( &self, user_id: u64, ) -> Result, DeezerClientError> { let response = self .client .get(self.build_endpoint_uri(&format!("user/{}/playlists", user_id))?) .await?; let body_buf = &*hyper::body::to_bytes(response).await?; let err_body_result: Result = serde_json::from_slice(body_buf); if let Ok(err_body) = err_body_result { return Err(DeezerClientError::ReceivedErrorResponse(err_body.error)); } let user_playlists: UserPlaylists = serde_json::from_slice(body_buf) .map_err(DeezerClientError::ParseResponseFailed)?; Ok(user_playlists.data) } /// Returns a playlist. /// /// # Errors /// Will return Err if either sending the request or parsing the response fails. pub async fn get_playlist( &self, playlist_id: u64, ) -> Result { let response = self .client .get(self.build_endpoint_uri(&format!("playlist/{}", playlist_id))?) .await?; let body_buf = &*hyper::body::to_bytes(response).await?; let err_body_result: Result = serde_json::from_slice(body_buf); if let Ok(err_body) = err_body_result { return Err(DeezerClientError::ReceivedErrorResponse(err_body.error)); } serde_json::from_slice(body_buf).map_err(DeezerClientError::ParseResponseFailed) } fn build_endpoint_uri(&self, endpoint: &String) -> Result { Uri::builder() .scheme("http") .authority(self.api_url) .path_and_query(format!( "/{}?access_token={}", endpoint, self.access_token.access_token )) .build() .map_err(|_| DeezerClientError::BuildAPIEndpointURIFailed) } }