diff options
Diffstat (limited to 'src/client.rs')
-rw-r--r-- | src/client.rs | 133 |
1 files changed, 114 insertions, 19 deletions
diff --git a/src/client.rs b/src/client.rs index 5c6858b..0699545 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,50 +1,145 @@ //! Deezer client. -use std::error::Error; +use std::fmt::Debug; +use hyper::client::{Client, HttpConnector}; +use hyper::Uri; use serde::Deserialize; -/// A user. +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 User +pub struct DeezerError { - /// The user ID. - pub id: u32, + /// Error type. + #[serde(rename = "type")] + pub err_type: String, + + /// Error message. + pub message: String, - /// The user name. - pub name: String, + /// Error code. + pub code: u32, +} + +#[derive(Debug, Deserialize)] +struct ErrorResponseBody +{ + error: DeezerError, } /// Deezer client. -#[derive(Default)] pub struct DeezerClient { - client: reqwest::Client, + client: Client<HttpConnector>, api_url: &'static str, + access_token: AccessToken, } impl DeezerClient { /// Creates a new Deezer client. #[must_use] - pub fn new() -> Self + pub fn new(access_token: AccessToken) -> Self { Self { - client: reqwest::Client::new(), - api_url: "https://api.deezer.com", + client: Client::new(), + api_url: "api.deezer.com", + access_token, } } /// Returns the authenticated user. - pub async fn get_me(&self) -> Result<User, Box<dyn Error + Send + Sync>> + /// + /// # Errors + /// Will return Err if either sending the request or parsing the response fails. + pub async fn get_me(&self) -> Result<User, DeezerClientError> + { + 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<ErrorResponseBody, _> = + 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<Vec<UserPlaylist>, 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<ErrorResponseBody, _> = + 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<Playlist, DeezerClientError> { - let user = self + let response = self .client - .get(format!("{}/user/me", self.api_url)) - .send() - .await? - .json::<User>() + .get(self.build_endpoint_uri(&format!("playlist/{}", playlist_id))?) .await?; - Ok(user) + let body_buf = &*hyper::body::to_bytes(response).await?; + + let err_body_result: Result<ErrorResponseBody, _> = + 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, DeezerClientError> + { + 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) } } |