use crate::audio::models::{AudioServerStatus, TranscriptionResponse, VoiceRequest}; use reqwest::Client; use reqwest::multipart::Form; use std::path::Path; use thiserror::Error; use url::Url; pub struct AudioClient { client: Client, authorization: Option, base_url: Url, } pub trait AudioClientTrait { fn new(base_url: Url) -> Self; fn from_client(base_url: Url, client: Client) -> Self; fn with_authorization(self, authorization: String) -> Self; fn status(&self) -> impl Future>; fn transcribe( &self, audio_file_path: impl AsRef, ) -> impl Future>; fn tts(&self, voice_request: VoiceRequest) -> impl Future>; } #[derive(Debug, Error)] pub enum AudioError { #[error(transparent)] RequestError(#[from] reqwest::Error), #[error(transparent)] UrlParseError(#[from] url::ParseError), #[error(transparent)] IOError(#[from] std::io::Error), } type AudioResult = Result; impl AudioClient { fn get(&self, url: Url) -> reqwest::RequestBuilder { self.client.get(url).header( "Authorization", self.authorization.clone().unwrap_or(String::new()), ) } } impl AudioClientTrait for AudioClient { fn new(base_url: Url) -> Self { AudioClient { client: Client::new(), authorization: None, base_url, } } fn from_client(base_url: Url, client: Client) -> Self { AudioClient { client, authorization: None, base_url, } } fn with_authorization(mut self, authorization: String) -> Self { self.authorization = Some(authorization); self } async fn status(&self) -> AudioResult { let response = self .get(self.base_url.clone()) .send() .await? .error_for_status()?; Ok(response.json().await?) } async fn transcribe( &self, audio_file_path: impl AsRef, ) -> AudioResult { let form = Form::new().file("audio_file", audio_file_path).await?; let response = self .get(self.base_url.join("transcribe")?) .multipart(form) .send() .await?; Ok(response.json().await?) } async fn tts(&self, voice_request: VoiceRequest) -> AudioResult { let response = self .get(self.base_url.join("tts")?) .json(&voice_request) .send() .await? .error_for_status()?; Ok(response.bytes().await?) } }