use serde::{Deserialize, Deserializer, Serialize, de};
use crate::ids::{Aid, Bvid, Mid};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserCardProfile {
pub card: UserCardSummary,
pub following: bool,
#[serde(default)]
pub archive_count: u64,
#[serde(default)]
pub article_count: u64,
#[serde(default)]
pub follower: u64,
#[serde(default)]
pub like_num: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserCardSummary {
#[serde(deserialize_with = "deserialize_mid_from_string_or_number")]
pub mid: Mid,
pub name: String,
#[serde(default)]
pub sex: Option<String>,
pub face: String,
#[serde(default)]
pub sign: String,
#[serde(default)]
pub fans: u64,
#[serde(default)]
pub attention: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserBatchCard {
pub mid: Mid,
pub name: String,
pub face: String,
#[serde(default)]
pub sign: String,
#[serde(default)]
pub rank: i32,
#[serde(default)]
pub level: i32,
#[serde(default)]
pub silence: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserBatchInfo {
pub mid: Mid,
pub name: String,
#[serde(default)]
pub sign: String,
#[serde(default)]
pub rank: i32,
#[serde(default)]
pub level: i32,
#[serde(default)]
pub silence: i32,
#[serde(default, deserialize_with = "deserialize_optional_string")]
pub sex: Option<String>,
pub face: String,
#[serde(default)]
pub vip: Option<UserBatchVip>,
#[serde(default)]
pub official: Option<UserOfficialSummary>,
#[serde(default)]
pub is_fake_account: Option<u32>,
#[serde(default)]
pub expert_info: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserBatchVip {
#[serde(default, rename = "type")]
pub kind: i32,
#[serde(default)]
pub status: i32,
#[serde(default)]
pub due_date: i64,
#[serde(default)]
pub vip_pay_type: i32,
#[serde(default)]
pub theme_type: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserSpaceProfile {
pub mid: Mid,
pub name: String,
#[serde(default, deserialize_with = "deserialize_optional_string")]
pub sex: Option<String>,
pub face: String,
#[serde(default)]
pub sign: String,
pub level: u8,
pub silence: u8,
#[serde(default)]
pub coins: f64,
#[serde(default)]
pub fans_badge: bool,
#[serde(default)]
pub is_followed: bool,
#[serde(default, deserialize_with = "deserialize_optional_string")]
pub top_photo: Option<String>,
#[serde(default)]
pub official: Option<UserOfficialSummary>,
#[serde(default)]
pub vip: Option<UserVipSummary>,
#[serde(default)]
pub live_room: Option<UserSpaceLiveRoom>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserOfficialSummary {
#[serde(default)]
pub role: i32,
#[serde(default)]
pub title: String,
#[serde(default)]
pub desc: String,
#[serde(default, rename = "type")]
pub kind: i32,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserVipSummary {
#[serde(default, rename = "type")]
pub kind: i32,
#[serde(default)]
pub status: i32,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserSpaceLiveRoom {
#[serde(default, rename = "roomStatus")]
pub room_status: u8,
#[serde(default, rename = "liveStatus")]
pub live_status: u8,
#[serde(default)]
pub url: String,
#[serde(default)]
pub title: String,
#[serde(default, rename = "roomid")]
pub room_id: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(transparent)]
pub struct UserSpaceNotice {
pub content: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserBangumiFollowList {
#[serde(default, rename = "list")]
pub items: Vec<UserBangumiFollow>,
#[serde(default, rename = "pn")]
pub page: u32,
#[serde(default, rename = "ps")]
pub page_size: u32,
#[serde(default)]
pub total: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserBangumiFollow {
pub season_id: i64,
pub media_id: i64,
#[serde(default)]
pub season_type: i64,
#[serde(default)]
pub season_type_name: String,
#[serde(default)]
pub title: String,
#[serde(default)]
pub cover: String,
#[serde(default)]
pub total_count: i64,
#[serde(default)]
pub is_finish: i64,
#[serde(default)]
pub is_started: i64,
#[serde(default)]
pub is_play: i64,
#[serde(default)]
pub badge: String,
#[serde(default)]
pub badge_type: i64,
#[serde(default, rename = "new_ep")]
pub latest_episode: UserBangumiLatestEpisode,
#[serde(default)]
pub rating: Option<UserBangumiRating>,
#[serde(default)]
pub url: String,
#[serde(default)]
pub short_url: String,
#[serde(default)]
pub summary: String,
#[serde(default)]
pub styles: Vec<String>,
#[serde(default)]
pub follow_status: i64,
#[serde(default)]
pub progress: String,
#[serde(default)]
pub both_follow: bool,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserBangumiLatestEpisode {
#[serde(default)]
pub id: i64,
#[serde(default)]
pub index_show: String,
#[serde(default)]
pub cover: String,
#[serde(default)]
pub title: String,
#[serde(default)]
pub long_title: Option<String>,
#[serde(default)]
pub pub_time: String,
#[serde(default)]
pub duration: i64,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct UserBangumiRating {
#[serde(default)]
pub score: f64,
#[serde(default)]
pub count: i64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserRelationStat {
pub mid: Mid,
pub following: u64,
#[serde(default)]
pub whisper: u64,
#[serde(default)]
pub black: u64,
pub follower: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserFollowings {
#[serde(default)]
pub list: Vec<UserFollowing>,
#[serde(default)]
pub re_version: u32,
#[serde(default)]
pub total: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserFollowing {
pub mid: Mid,
#[serde(default)]
pub attribute: u8,
#[serde(default)]
pub mtime: u64,
#[serde(default)]
pub tag: Option<Vec<u64>>,
#[serde(default)]
pub special: u8,
#[serde(default, rename = "uname")]
pub name: String,
#[serde(default)]
pub face: String,
#[serde(default)]
pub sign: String,
#[serde(default)]
pub face_nft: u8,
#[serde(default)]
pub official_verify: Option<UserRelationOfficialVerify>,
#[serde(default)]
pub vip: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserFollowers {
#[serde(default)]
pub list: Vec<UserFollower>,
#[serde(default)]
pub offset: String,
#[serde(default)]
pub re_version: u32,
#[serde(default)]
pub total: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserFollower {
pub mid: Mid,
#[serde(default)]
pub attribute: u8,
#[serde(default)]
pub mtime: Option<u64>,
#[serde(default)]
pub tag: Option<Vec<u64>>,
#[serde(default)]
pub special: u8,
#[serde(default)]
pub contract_info: Option<serde_json::Value>,
#[serde(default, rename = "uname")]
pub name: String,
#[serde(default)]
pub face: String,
#[serde(default)]
pub sign: String,
#[serde(default)]
pub face_nft: u8,
#[serde(default)]
pub official_verify: Option<UserRelationOfficialVerify>,
#[serde(default)]
pub vip: Option<serde_json::Value>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserFollowTag {
#[serde(rename = "tagid")]
pub id: i64,
pub name: String,
#[serde(default)]
pub count: i64,
#[serde(default)]
pub tip: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserMedalWall {
#[serde(default)]
pub list: Vec<UserMedalWallItem>,
#[serde(default)]
pub count: u32,
#[serde(default)]
pub close_space_medal: u32,
#[serde(default)]
pub only_show_wearing: u32,
#[serde(default)]
pub name: String,
#[serde(default)]
pub icon: String,
pub uid: Mid,
#[serde(default)]
pub level: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserMedalWallItem {
pub medal_info: UserMedalInfo,
#[serde(default)]
pub target_name: String,
#[serde(default)]
pub target_icon: String,
#[serde(default)]
pub link: String,
#[serde(default)]
pub live_status: u32,
#[serde(default, rename = "offical")]
pub official: Option<u32>,
#[serde(default)]
pub uinfo_medal: Option<UserMedalOwnerInfo>,
}
impl UserMedalWallItem {
pub fn target_id(&self) -> Mid {
self.medal_info.target_id
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserMedalInfo {
pub target_id: Mid,
#[serde(default)]
pub level: u32,
#[serde(default, rename = "medal_name")]
pub name: String,
#[serde(default)]
pub medal_color_start: u32,
#[serde(default)]
pub medal_color_end: u32,
#[serde(default)]
pub medal_color_border: u32,
#[serde(default)]
pub guard_level: u32,
#[serde(default)]
pub wearing_status: u32,
#[serde(default)]
pub medal_id: u64,
#[serde(default)]
pub intimacy: u64,
#[serde(default)]
pub next_intimacy: u64,
#[serde(default)]
pub today_feed: u64,
#[serde(default)]
pub day_limit: u64,
#[serde(default)]
pub guard_icon: Option<String>,
#[serde(default)]
pub honor_icon: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserMedalOwnerInfo {
#[serde(default)]
pub name: String,
#[serde(default)]
pub level: u32,
#[serde(default)]
pub color_start: u32,
#[serde(default)]
pub color_end: u32,
#[serde(default)]
pub color_border: u32,
#[serde(default)]
pub color: u32,
#[serde(default)]
pub id: u64,
#[serde(default)]
pub typ: u32,
#[serde(default)]
pub is_light: u32,
pub ruid: Mid,
#[serde(default)]
pub guard_level: u32,
#[serde(default)]
pub score: u64,
#[serde(default)]
pub guard_icon: Option<String>,
#[serde(default)]
pub honor_icon: Option<String>,
#[serde(default)]
pub v2_medal_color_start: Option<String>,
#[serde(default)]
pub v2_medal_color_end: Option<String>,
#[serde(default)]
pub v2_medal_color_border: Option<String>,
#[serde(default)]
pub v2_medal_color_text: Option<String>,
#[serde(default)]
pub v2_medal_color_level: Option<String>,
#[serde(default)]
pub user_receive_count: Option<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserRelationOfficialVerify {
#[serde(default, rename = "type")]
pub kind: i8,
#[serde(default)]
pub desc: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserUpStat {
pub archive: UserUpStatArchive,
pub article: UserUpStatArticle,
pub likes: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserUpStatArchive {
#[serde(default)]
pub view: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserUpStatArticle {
#[serde(default)]
pub view: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserNavStat {
#[serde(default)]
pub video: u64,
#[serde(default)]
pub bangumi: u64,
#[serde(default)]
pub cinema: u64,
#[serde(default)]
pub channel: UserNavStatPair,
#[serde(default)]
pub favourite: UserNavStatPair,
#[serde(default)]
pub tag: u64,
#[serde(default)]
pub article: u64,
#[serde(default)]
pub playlist: u64,
#[serde(default)]
pub album: u64,
#[serde(default)]
pub audio: u64,
#[serde(default)]
pub pugv: u64,
#[serde(default)]
pub opus: u64,
#[serde(default, rename = "season_num")]
pub season_count: u64,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserNavStatPair {
#[serde(default)]
pub master: u64,
#[serde(default)]
pub guest: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserAlbumCount {
#[serde(default)]
pub all_count: u64,
#[serde(default)]
pub draw_count: u64,
#[serde(default)]
pub photo_count: u64,
#[serde(default)]
pub daily_count: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserNameToUid {
#[serde(default)]
pub uid_list: Vec<UserNameToUidItem>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserNameToUidItem {
pub name: String,
#[serde(
rename = "uid",
deserialize_with = "deserialize_mid_from_string_or_number"
)]
pub mid: Mid,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserUploadedVideos {
pub list: UserUploadedVideoList,
pub page: UserUploadedVideosPage,
#[serde(default)]
pub episodic_button: Option<UserUploadedVideosButton>,
#[serde(default)]
pub is_risk: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserUploadedVideoList {
#[serde(default)]
pub tlist: serde_json::Value,
#[serde(default, rename = "vlist")]
pub videos: Vec<UserUploadedVideo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserUploadedVideo {
pub aid: Aid,
pub bvid: Bvid,
pub mid: Mid,
pub title: String,
#[serde(default)]
pub author: String,
#[serde(default)]
pub pic: String,
#[serde(default)]
pub length: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub created: u64,
#[serde(default)]
pub play: u64,
#[serde(default)]
pub comment: u64,
#[serde(default)]
pub typeid: u64,
#[serde(default)]
pub video_review: u64,
#[serde(default)]
pub hide_click: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserUploadedVideosPage {
#[serde(default)]
pub count: u64,
#[serde(default)]
pub pn: u32,
#[serde(default)]
pub ps: u32,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UserUploadedVideosButton {
#[serde(default)]
pub text: String,
#[serde(default)]
pub uri: String,
}
fn deserialize_mid_from_string_or_number<'de, D>(deserializer: D) -> Result<Mid, D::Error>
where
D: Deserializer<'de>,
{
let value = serde_json::Value::deserialize(deserializer)?;
match value {
serde_json::Value::Number(number) => {
let mid = number
.as_u64()
.ok_or_else(|| de::Error::custom("mid must be a non-negative integer"))?;
Mid::new(mid).map_err(de::Error::custom)
}
serde_json::Value::String(text) => text.parse::<Mid>().map_err(de::Error::custom),
_ => Err(de::Error::custom("mid must be a string or number")),
}
}
fn deserialize_optional_string<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
Ok(Option::<String>::deserialize(deserializer)?
.and_then(|value| (!value.trim().is_empty()).then_some(value)))
}