pub use albums::*;
pub use artists::*;
pub use browse::*;
pub use follow::*;
use isocountry::CountryCode;
pub use library::*;
pub use personalization::*;
pub use player::*;
pub use playlists::*;
pub use search::*;
pub use tracks::*;
pub use users_profile::*;
macro_rules! request {
(
$token:expr,
$method:ident $path:expr
$(, path_params = [$($path_param:expr),*])?
$(, header_params = {$($header_param_name:literal: $header_param_value:expr),*})?
$(, query_params = {$($query_param_name:literal: $query_param_value:expr),*})?
$(, optional_query_params = {$($optional_query_param_name:literal: $optional_query_param_value:expr),*})?
$(, additional_query_params = $additional_query_params:expr)?
$(, body = $body:expr)?
$(, ret = $type:ty)?
$(, or_else = $else:expr)?
) => {{
#[allow(unused_mut)]
let mut request = crate::CLIENT.request(
reqwest::Method::$method,
&format!(concat!("https://api.spotify.com", $path)$($(, $path_param)*)?)
)
$($(.header($header_param_name, $header_param_value))*)?
$(.query(&[$(($query_param_name, $query_param_value)),*]))?
$(.body($body))?
.bearer_auth(&$token.token);
$(
$(
if let Some(optional_query_param) = $optional_query_param_value {
request = request.query(&[($optional_query_param_name, optional_query_param)]);
}
)*
)?
$(
for (name, value) in $additional_query_params.into_iter() {
request = request.query(&[(name, value)]);
}
)?
let response = loop {
let response = request.try_clone().unwrap().send().await?;
if response.status() != 429 {
break response;
}
let wait = response.headers().get("Retry-After").and_then(|val| val.to_str().ok()).and_then(|secs| secs.parse::<u64>().ok());
let wait = wait.unwrap_or(2);
tokio::time::delay_for(std::time::Duration::from_secs(wait)).await;
};
let status = response.status();
let text = response.text().await?;
if cfg!(test) {
println!("Request is {:?}", request);
$(println!("Request body is {}", $body);)?
println!("Response status is {}", status);
println!("Response body is '{}'", text);
}
$(
if text.is_empty() {
return Ok($else);
}
)?
if !status.is_success() {
return Err(EndpointError::SpotifyError(serde_json::from_str(&text)?));
}
$(
serde_json::from_str::<$type>(&text)?
)?
}};
}
pub mod albums;
pub mod artists;
pub mod browse;
pub mod follow;
pub mod library;
pub mod personalization;
pub mod player;
pub mod playlists;
pub mod search;
pub mod tracks;
pub mod users_profile;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Market {
Country(CountryCode),
FromToken,
}
impl Market {
fn as_str(self) -> &'static str {
match self {
Market::Country(code) => code.alpha2(),
Market::FromToken => "from_token",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TimeRange {
LongTerm,
MediumTerm,
ShortTerm,
}
impl TimeRange {
fn as_str(self) -> &'static str {
match self {
Self::LongTerm => "long_term",
Self::MediumTerm => "medium_term",
Self::ShortTerm => "short_term",
}
}
}
#[cfg(test)]
async fn token() -> crate::AccessToken {
dotenv::dotenv().unwrap();
crate::AuthCodeFlow::from_refresh(
&crate::ClientCredentials::from_env().unwrap(),
std::fs::read_to_string(".refresh_token").unwrap(),
)
.send()
.await
.unwrap()
}