use chrono::serde::ts_seconds::deserialize as from_ts;
use chrono::{DateTime, Utc};
use serde::Deserialize;
use std::marker::PhantomData;
use crate::{
error::{Error, LastFMError},
model::Image,
Client, RequestBuilder,
};
#[derive(Debug, Deserialize)]
pub struct UserInfo {
pub user: User,
}
#[derive(Debug, Deserialize)]
pub struct User {
#[serde(rename = "playcount")]
pub scrobbles: String,
#[serde(rename = "name")]
pub username: String,
pub url: String,
pub country: String,
#[serde(rename = "image")]
pub images: Vec<Image>,
pub registered: Registered,
#[serde(rename = "realname")]
pub display_name: String,
}
#[derive(Debug, Deserialize)]
pub struct Registered {
#[serde(rename = "unixtime")]
pub unix_timestamp: String,
#[serde(rename = "#text")]
#[serde(deserialize_with = "from_ts")]
pub date: DateTime<Utc>,
}
impl UserInfo {
pub async fn build<'a>(client: &'a mut Client, user: &str) -> RequestBuilder<'a, UserInfo> {
let url = client.build_url(vec![("method", "user.getInfo"), ("user", user)]).await;
RequestBuilder { client, url, phantom: PhantomData }
}
}
impl<'a> RequestBuilder<'a, UserInfo> {
pub async fn send(&'a mut self) -> Result<UserInfo, 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::<UserInfo>(&body) {
Ok(user) => Ok(user),
Err(e) => Err(Error::ParsingError(e)),
},
}
}
Err(err) => Err(Error::HTTPError(err)),
}
}
}
impl<'a> Client {
pub async fn user_info(&'a mut self, user: &str) -> RequestBuilder<'a, UserInfo> { UserInfo::build(self, user).await }
}