use serde::{Deserialize, Serialize};
use super::perf::LichessPerfs;
use super::title::LichessTitle;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LichessLightUser {
pub id: String,
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flair: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub title: Option<LichessTitle>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub patron: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub patron_color: Option<u8>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct LichessProfile {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flag: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub location: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bio: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub real_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fide_rating: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uscf_rating: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ecf_rating: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cfc_rating: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rcf_rating: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub dsb_rating: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub links: Option<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct LichessCount {
pub all: u32,
pub rated: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ai: Option<u32>,
pub draw: u32,
#[serde(rename = "drawH", default, skip_serializing_if = "Option::is_none")]
pub draw_human: Option<u32>,
pub loss: u32,
#[serde(rename = "lossH", default, skip_serializing_if = "Option::is_none")]
pub loss_human: Option<u32>,
pub win: u32,
#[serde(rename = "winH", default, skip_serializing_if = "Option::is_none")]
pub win_human: Option<u32>,
pub bookmark: u32,
pub playing: u32,
pub import: u32,
pub me: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct LichessPlayTime {
pub total: u64,
pub tv: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LichessStreamerChannel {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub channel: Option<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct LichessStreamerInfo {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub twitch: Option<LichessStreamerChannel>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub youtube: Option<LichessStreamerChannel>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct LichessUser {
pub id: String,
pub username: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub perfs: Option<LichessPerfs>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub title: Option<LichessTitle>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flair: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub created_at: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub disabled: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tos_violation: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub profile: Option<LichessProfile>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub seen_at: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub play_time: Option<LichessPlayTime>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub patron: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub patron_color: Option<u8>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub verified: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct LichessUserExtended {
#[serde(flatten)]
pub user: LichessUser,
pub url: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub playing: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub count: Option<LichessCount>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub streaming: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub streamer: Option<LichessStreamerInfo>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub followable: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub following: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub blocking: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fide_id: Option<u32>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_extended_user_with_flattened_core() {
let json = r#"{
"id": "bobby", "username": "Bobby",
"title": "GM", "createdAt": 1290415680000,
"playTime": {"total": 1000, "tv": 20},
"url": "https://lichess.org/@/Bobby",
"count": {"all": 5, "rated": 3, "draw": 1, "loss": 1, "win": 3,
"bookmark": 0, "playing": 0, "import": 0, "me": 0},
"followable": true, "following": false
}"#;
let user: LichessUserExtended = serde_json::from_str(json).unwrap();
assert_eq!(user.user.id, "bobby");
assert_eq!(user.user.title, Some(LichessTitle::Gm));
assert_eq!(user.url, "https://lichess.org/@/Bobby");
assert_eq!(user.count.unwrap().all, 5);
assert_eq!(user.following, Some(false));
}
#[test]
fn count_maps_human_suffixed_fields() {
let json = r#"{"all":1,"rated":1,"draw":0,"drawH":0,"loss":0,"win":1,
"winH":1,"bookmark":0,"playing":0,"import":0,"me":0}"#;
let count: LichessCount = serde_json::from_str(json).unwrap();
assert_eq!(count.win_human, Some(1));
assert_eq!(count.draw_human, Some(0));
}
}