use crate::error::Error;
use crate::request::builder::MusicRequestBuilder;
use crate::request::context::ContextContainer;
use crate::request::paginated::paginate;
use crate::request::try_resource_response;
use crate::resource::relationship::Relationship;
use crate::resource::{Resource, ResourceHeader};
use crate::ApiClient;
use am_api_proc_macro::{Context, ResourceProperty};
use futures::Stream;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use time::OffsetDateTime;
#[derive(Context, Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
#[serde(rename_all = "camelCase")]
pub struct PersonalRecommendation {
#[context(skip)]
#[serde(flatten)]
pub header: ResourceHeader,
#[context(skip)]
#[serde(default)]
pub attributes: Option<PersonalRecommendationAttributes>,
#[serde(default)]
pub relationships: PersonalRecommendationRelationships,
}
impl PersonalRecommendation {
pub fn get<'a>() -> PersonalRecommendationGetRequestBuilder<'a> {
PersonalRecommendationGetRequestBuilder::default()
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
#[serde(rename_all = "camelCase")]
pub struct PersonalRecommendationAttributes {
pub kind: PersonalRecommendationKind,
#[serde(with = "time::serde::iso8601")]
pub next_update_date: OffsetDateTime,
#[serde(default)]
pub reason: Option<PersonalRecommendationReason>,
pub resource_types: Vec<String>,
#[serde(default)]
pub title: Option<PersonalRecommendationTitle>,
}
#[derive(
Context, ResourceProperty, Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq, Hash,
)]
#[serde(rename_all = "camelCase", default)]
#[resource_property(
PersonalRecommendationRelationshipType,
object = "recommendations",
relationship
)]
pub struct PersonalRecommendationRelationships {
pub contents: Option<Relationship<Resource>>,
}
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq, Hash)]
pub enum PersonalRecommendationKind {
#[serde(rename = "music-recommendations")]
#[default]
MusicRecommendations,
#[serde(rename = "recently-played")]
RecentlyPlayed,
#[serde(rename = "unknown")]
Generic,
}
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq, Hash)]
#[serde(rename_all = "camelCase", default)]
pub struct PersonalRecommendationReason {
pub string_for_display: String,
}
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq, Hash)]
#[serde(rename_all = "camelCase", default)]
pub struct PersonalRecommendationTitle {
pub string_for_display: String,
}
pub struct PersonalRecommendationRequestBuilder;
pub type PersonalRecommendationGetRequestBuilder<'a> =
MusicRequestBuilder<'a, PersonalRecommendationRequestBuilder>;
impl<'a> PersonalRecommendationGetRequestBuilder<'a> {
pub async fn one(
mut self,
client: &ApiClient,
id: &str,
) -> Result<Option<PersonalRecommendation>, Error> {
let request_context = Arc::new(self.get_request_context_drain(client));
let response = client
.get(&format!("/v1/me/recommendations/{id}"))
.query(&request_context.query)
.send()
.await?;
let mut response = try_resource_response(response).await?;
response.data.set_context(request_context);
Ok(response.data.into_iter().next())
}
pub async fn many(
mut self,
client: &ApiClient,
ids: &[&str],
) -> Result<Vec<PersonalRecommendation>, Error> {
let mut request_context = self.get_request_context_drain(client);
request_context
.query
.push((String::from("ids"), ids.to_vec().join(",")));
let request_context = Arc::new(request_context);
let response = client
.get("/v1/me/recommendations")
.query(&request_context.query)
.send()
.await?;
let mut response = try_resource_response(response).await?;
response.data.set_context(request_context);
Ok(response.data)
}
pub async fn default_recommendations(
mut self,
client: &ApiClient,
limit: usize,
offset: usize,
) -> impl Stream<Item = Result<PersonalRecommendation, Error>> {
let mut request_context = self.get_request_context_drain(client);
request_context
.query
.push((String::from("limit"), limit.to_string()));
paginate(
client.clone(),
String::from("/v1/me/recommendations"),
request_context,
offset,
)
}
}