use serde::Deserialize;
use std::marker::PhantomData;
use crate::{
error::{Error, LastFMError},
model::{Attributes, Image},
user::User,
Client, RequestBuilder,
};
#[derive(Debug, Deserialize)]
pub struct TopArtists {
#[serde(rename = "artist")]
pub artists: Vec<Artist>,
#[serde(rename = "@attr")]
pub attrs: Attributes,
}
#[derive(Debug, Deserialize)]
pub struct Artist {
#[serde(rename = "@attr")]
pub attrs: ArtistAttributes,
pub mbid: String,
#[serde(rename = "playcount")]
pub scrobbles: String,
pub name: String,
pub url: String,
#[serde(rename = "image")]
pub images: Vec<Image>,
}
#[derive(Debug, Deserialize)]
pub struct ArtistAttributes {
pub rank: String,
}
impl TopArtists {
pub async fn build<'a>(client: &'a mut Client, user: &str) -> RequestBuilder<'a, TopArtists> {
let url = client.build_url(vec![("method", "user.getTopArtists"), ("user", user)]).await;
RequestBuilder { client, url, phantom: PhantomData }
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum Period {
SevenDays,
OneMonth,
ThreeMonths,
SixMonths,
TwelveMonths,
OneYear,
Overall,
}
impl ToString for Period {
fn to_string(&self) -> String {
match self {
Self::Overall => String::from("overall"),
Self::SevenDays => String::from("7day"),
Self::OneMonth => String::from("1month"),
Self::ThreeMonths => String::from("3month"),
Self::SixMonths => String::from("6month"),
Self::TwelveMonths | Self::OneYear => String::from("12month"),
}
}
}
impl<'a> RequestBuilder<'a, TopArtists> {
add_param!(with_limit, limit, usize);
add_param!(within_period, period, Period);
add_param!(with_page, page, usize);
pub async fn send(&'a mut self) -> Result<TopArtists, Error> {
match self.client.request(&self.url).await {
Ok(response) => {
let body = response.text().await.unwrap();
match serde_json::from_str::<LastFMError>(&body) {
Ok(lastm_error) => Err(Error::LastFMError(lastm_error.into())),
Err(_) => match serde_json::from_str::<User>(&body) {
Ok(user) => Ok(user.top_artists.unwrap()),
Err(e) => Err(Error::ParsingError(e)),
},
}
}
Err(err) => Err(Error::HTTPError(err)),
}
}
}
impl<'a> Client {
pub async fn top_artists(&'a mut self, user: &str) -> RequestBuilder<'a, TopArtists> { TopArtists::build(self, user).await }
}