diff --git a/src/subsonic.rs b/src/subsonic.rs index f91cafa..69397eb 100644 --- a/src/subsonic.rs +++ b/src/subsonic.rs @@ -1,5 +1,6 @@ pub mod schema; +use bytes::Bytes; use md5::Digest; use rand::Rng; use tracing::{event, Level}; @@ -146,6 +147,47 @@ impl Client { } } + async fn send_bytes(&self, request: reqwest::RequestBuilder) -> Result { + let (sender, receiver) = async_channel::bounded(1); + + let future = request.send(); + runtime().spawn(async move { + async fn perform( + response: Result, + ) -> Result { + let response = response?.error_for_status()?; + if response.headers()[reqwest::header::CONTENT_TYPE] + .to_str() + .expect("bad content type") + .starts_with("text/json") + { + match response + .json::>() + .await? + .subsonic_response + { + schema::SubsonicResponse::Failed { error } => { + Err(Error::SubsonicError(error)) + } + _ => panic!("unlimited error but no error"), + } + } else { + Ok(response.bytes().await?) + } + } + + sender + .send(perform(future.await).await) + .await + .expect("could not send cover art bytes back to the main loop"); + }); + + receiver + .recv() + .await + .expect("could not receive cover art bytes from tokio") + } + fn url(&self, path: &[&str], query: &[(&str, &str)]) -> url::Url { let mut url = self.base_url.clone(); url.path_segments_mut() @@ -181,27 +223,9 @@ impl Client { self.url(&["rest", "getCoverArt"], &[("id", id)]) } - pub async fn cover_art(&self, id: &str) -> Result { - let (sender, receiver) = async_channel::bounded(1); - - let future = self.client.get(self.cover_art_url(id)).send(); - runtime().spawn(async move { - async fn perform( - response: Result, - ) -> Result { - Ok(response?.error_for_status()?.bytes().await?) - } - - sender - .send(perform(future.await).await) - .await - .expect("could not send cover art bytes back to the main loop"); - }); - - receiver - .recv() + pub async fn cover_art(&self, id: &str) -> Result { + self.send_bytes(self.client.get(self.cover_art_url(id))) .await - .expect("could not receive cover art bytes from tokio") } pub fn stream_url(&self, id: &str) -> url::Url {