use log::warn;
use reqwest::{Method, StatusCode};
use super::{request_builder::RequestBuilder, API_USER_PROFILE_ENDPOINT};
#[cfg(feature = "async")]
use crate::client::request_builder::AsyncResponseHandler;
#[cfg(feature = "sync")]
use crate::client::request_builder::SyncResponseHandler;
use crate::{
client::{
object,
request_builder::{BaseRequestBuilderContainer, CatalogItemRequestBuilder, SearchBuilder},
API_SEARCH_ENDPOINT, API_TRACKS_ENDPOINT,
},
error::Error,
model::{
id::{Id, IdTrait, TrackId, UserId},
track::FullTrack,
user::PublicUser,
},
};
pub trait UnscopedClient
where
Self: crate::private::Sealed + Clone + Sized,
{
fn track<'a>(&'a self, track: Id<'a, TrackId>) -> CatalogItemRequestBuilder<Self, FullTrack> {
let mut builder = CatalogItemRequestBuilder::new(
Method::GET,
format!("{}/{}", API_TRACKS_ENDPOINT, track.as_str()),
self.clone(),
);
#[cfg(feature = "async")]
{
builder = builder.with_async_response_handler(track_response_handler_async_fn(track.as_owned()));
}
#[cfg(feature = "sync")]
{
builder = builder.with_sync_response_handler(track_response_handler_sync_fn(track.as_owned()));
}
builder
}
fn tracks<'a, I>(&'a self, tracks: I) -> CatalogItemRequestBuilder<Self, object::TracksResponse, Vec<FullTrack>>
where
I: IntoIterator<Item = Id<'a, TrackId>>,
{
CatalogItemRequestBuilder::new(Method::GET, API_TRACKS_ENDPOINT, self.clone()).append_query(
object::TRACKS_IDS_QUERY,
tracks
.into_iter()
.map(|id| id.as_str().to_owned())
.collect::<Vec<_>>()
.join(","),
)
}
fn search<S>(&self, query: S) -> SearchBuilder<Self>
where
S: Into<String>,
{
SearchBuilder::new(Method::GET, API_SEARCH_ENDPOINT, self.clone()).query(query.into())
}
fn user_profile<'a>(&'a self, user_id: Id<'a, UserId>) -> RequestBuilder<Self, PublicUser> {
RequestBuilder::new(
Method::GET,
format!("{API_USER_PROFILE_ENDPOINT}/{}", user_id.as_str()),
self.clone(),
)
}
}
#[cfg(feature = "async")]
fn track_response_handler_async_fn(track_id: Id<'static, TrackId>) -> AsyncResponseHandler {
Box::new(move |response| {
Box::pin(async move {
match response.status() {
StatusCode::OK => Ok(response),
StatusCode::NOT_FOUND => {
warn!("Got 404 Not Found to track call");
Err(Error::NonexistentTrack(track_id))
}
other => Err(Error::UnhandledSpotifyResponseStatusCode(other.as_u16())),
}
})
})
}
#[cfg(feature = "sync")]
fn track_response_handler_sync_fn(track_id: Id<'static, TrackId>) -> SyncResponseHandler {
Box::new(move |response| match response.status() {
StatusCode::OK => Ok(response),
StatusCode::NOT_FOUND => {
warn!("Got 404 Not Found to track call");
Err(Error::NonexistentTrack(track_id))
}
other => Err(Error::UnhandledSpotifyResponseStatusCode(other.as_u16())),
})
}