pub mod album_download;
pub mod albums;
pub mod artist_download;
pub mod artists;
pub mod catalog;
pub mod download_io;
pub mod playlist_download;
pub mod playlists;
pub mod tracks;
use std::{
future::Future,
sync::atomic::{AtomicBool, Ordering::Relaxed},
};
use serde::de::DeserializeOwned;
use crate::{
api::{
requests::{self, RequestAuth},
service::QobuzApiService,
},
errors::QobuzApiError::{self, Canceled},
};
pub fn check_cancel(cancel: Option<&AtomicBool>) -> Result<(), QobuzApiError> {
if cancel.is_some_and(|c| c.load(Relaxed)) {
return Err(Canceled);
}
Ok(())
}
pub async fn fetch_with_cancel<T, F, Fut>(
cancel: Option<&AtomicBool>,
f: F,
) -> Result<T, QobuzApiError>
where
F: FnOnce() -> Fut,
Fut: Future<Output = Result<T, QobuzApiError>>,
{
check_cancel(cancel)?;
let result = f().await?;
check_cancel(cancel)?;
Ok(result)
}
pub fn push_pagination_params(
params: &mut Vec<(String, String)>,
limit: Option<i32>,
offset: Option<i32>,
) {
if let Some(l) = limit {
params.push(("limit".to_string(), l.to_string()));
}
if let Some(o) = offset {
params.push(("offset".to_string(), o.to_string()));
}
}
async fn do_signed_get<T: DeserializeOwned>(
service: &QobuzApiService,
endpoint: &str,
params: &mut Vec<(String, String)>,
) -> Result<T, QobuzApiError> {
let token = service.require_auth_token()?;
requests::signed_get(
service.http_client(),
service.base_url(),
endpoint,
params,
&RequestAuth {
app_id: &service.app_id,
app_secret: service.app_secret(),
user_auth_token: token,
},
)
.await
}
pub async fn search<T: DeserializeOwned>(
service: &QobuzApiService,
endpoint: &str,
query: &str,
limit: Option<i32>,
offset: Option<i32>,
) -> Result<T, QobuzApiError> {
let mut params = vec![("query".to_string(), query.to_string())];
push_pagination_params(&mut params, limit, offset);
do_signed_get(service, endpoint, &mut params).await
}
pub async fn get_by_id<T: DeserializeOwned, I: ToString>(
service: &QobuzApiService,
endpoint: &str,
id_field: &str,
id: I,
extra: Option<&str>,
) -> Result<T, QobuzApiError> {
let mut params = vec![(id_field.to_string(), id.to_string())];
if let Some(e) = extra {
params.push(("extra".to_string(), e.to_string()));
}
do_signed_get(service, endpoint, &mut params).await
}
pub async fn paginated<T: DeserializeOwned, I: ToString>(
service: &QobuzApiService,
endpoint: &str,
id_field: &str,
id: I,
limit: Option<i32>,
offset: Option<i32>,
) -> Result<T, QobuzApiError> {
let mut params = vec![(id_field.to_string(), id.to_string())];
push_pagination_params(&mut params, limit, offset);
do_signed_get(service, endpoint, &mut params).await
}