// SPDX-License-Identifier: AGPL-3.0-only
use std::collections::HashMap;
use std::sync::Arc;
use serde::{Deserialize, Deserializer, de};
use serde_json::Value;
fn str_num<'de, D, T>(d: D) -> Result<T, D::Error> where D: Deserializer<'de>, T: From<u64> {
struct Visitor;
impl<'v> de::Visitor<'v> for Visitor {
type Value = u64;
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "a value which can be interpreted as a uint")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: de::Error
{
v.parse().map_err(|_| de::Error::invalid_value(de::Unexpected::Str(v), &"a string which can be parsed as a uint"))
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where E: de::Error
{
Ok(v)
}
}
d.deserialize_any(Visitor).map(Into::into)
}
fn str_bool<'de, D, T>(d: D) -> Result<T, D::Error> where D: Deserializer<'de>, T: From<bool>{
struct Visitor;
impl<'v> de::Visitor<'v> for Visitor {
type Value = bool;
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "a value which can be interpreted as a uint")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: de::Error
{
match v.to_ascii_lowercase().as_str() {
"true" | "1" => Ok(true),
"false" | "0" => Ok(false),
_ => Err(de::Error::invalid_value(de::Unexpected::Str(v), &"a string which can be parsed as a bool"))
}
}
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where E: de::Error
{
Ok(v)
}
}
d.deserialize_any(Visitor).map(Into::into)
}
#[derive(Deserialize, Debug)]
pub struct TimeStamp {
#[serde(alias = "unixtime")]
#[serde(alias = "uts")]
#[serde(deserialize_with = "str_num")]
pub unix_timestamp: u64,
#[serde(rename = "#text")]
pub text: Value
}
#[derive(Deserialize, Debug)]
pub struct Artist {
#[serde(alias = "#text")]
pub name: Arc<str>,
#[serde(default)]
pub url: Option<Arc<str>>
}
#[derive(Deserialize, Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
#[serde(rename_all = "lowercase")]
#[repr(u8)]
pub enum ImageSize {
Small,
Medium,
Large,
ExtraLarge
}
#[derive(Deserialize, Debug)]
pub struct Image {
pub size: ImageSize,
#[serde(alias = "#text")]
pub url: Arc<str>,
}
#[derive(Deserialize, Debug)]
pub struct Album {
pub mbid: Option<Arc<str>>,
#[serde(alias = "#text")]
pub title: Arc<str>,
#[serde(default)]
#[serde(alias = "image")]
pub images: Vec<Image>,
}
#[derive(Deserialize, Debug)]
pub struct Track {
pub artist: Artist,
#[serde(alias = "image")]
#[serde(default)]
pub images: Vec<Image>,
pub mbid: Option<Arc<str>>,
pub album: Option<Album>,
pub name: Arc<str>,
pub url: Arc<str>,
#[serde(deserialize_with = "str_num")]
pub duration: u64,
#[serde(deserialize_with = "str_num")]
pub listeners: u64,
#[serde(deserialize_with = "str_num")]
pub playcount: u64,
#[serde(default)]
#[serde(rename = "userloved")]
#[serde(deserialize_with = "str_bool")]
pub loved: Option<bool>,
#[serde(deserialize_with = "str_num")]
pub userplaycount: u64,
}
#[derive(Deserialize, Debug)]
pub struct GetTrackInfo {
pub track: Track
}
#[derive(Default, Deserialize, Debug)]
pub struct TrackAttr {
#[serde(default)]
#[serde(deserialize_with = "str_bool")]
pub nowplaying: bool,
#[serde(flatten)]
pub rest: HashMap<Arc<str>, Value>,
}
#[derive(Deserialize, Debug)]
pub struct ArtistStub {
#[serde(alias = "#text")]
pub name: Arc<str>
}
#[derive(Deserialize, Debug)]
pub struct TrackStub {
pub name: Arc<str>,
pub artist: ArtistStub,
#[serde(default)]
pub date: Option<TimeStamp>,
#[serde(rename = "@attr")]
#[serde(default)]
pub attr: TrackAttr,
#[serde(default)]
#[serde(alias = "image")]
pub images: Vec<Image>,
#[serde(default)]
pub album: Option<Album>
}
#[derive(Deserialize, Debug)]
pub struct RecentTracks {
pub track: Vec<TrackStub>
}
#[derive(Deserialize, Debug)]
pub struct GetRecentTracks {
pub recenttracks: RecentTracks
}
#[derive(Deserialize, Debug)]
pub struct User {
pub name: Arc<str>,
pub realname: Arc<str>,
#[serde(deserialize_with = "str_num")]
pub playcount: u64,
#[serde(deserialize_with = "str_num")]
pub artist_count: u64,
#[serde(deserialize_with = "str_num")]
pub playlists: u64,
#[serde(deserialize_with = "str_num")]
pub track_count: u64,
#[serde(deserialize_with = "str_num")]
pub album_count: u64,
#[serde(alias = "image")]
pub images: Vec<Image>,
pub registered: TimeStamp,
pub url: Arc<str>
}
#[derive(Deserialize, Debug)]
pub struct GetUserInfo {
pub user: User
}