Skip to main content

htb_cli/models/
user.rs

1use serde::{Deserialize, Serialize};
2
3use super::deserialize_bool_or_null;
4
5#[derive(Debug, Deserialize)]
6pub struct UserInfoResponse {
7    pub info: UserInfo,
8}
9
10#[derive(Debug, Deserialize, Serialize)]
11#[serde(rename_all = "camelCase")]
12pub struct UserInfo {
13    pub id: u64,
14    pub name: String,
15    #[serde(default)]
16    pub email: Option<String>,
17    #[serde(default)]
18    pub timezone: Option<String>,
19    #[serde(default, deserialize_with = "deserialize_bool_or_null")]
20    pub is_vip: bool,
21    #[serde(default, deserialize_with = "deserialize_bool_or_null")]
22    pub is_moderator: bool,
23    #[serde(
24        default,
25        rename = "canAccessVIP",
26        deserialize_with = "deserialize_bool_or_null"
27    )]
28    pub can_access_vip: bool,
29    #[serde(default)]
30    pub server_id: Option<u32>,
31    #[serde(default)]
32    pub rank_id: u32,
33    #[serde(default, deserialize_with = "deserialize_bool_or_null")]
34    pub verified: bool,
35    #[serde(default)]
36    pub subscription_type: Option<String>,
37}
38
39#[derive(Debug, Deserialize)]
40pub struct UserProfileResponse {
41    pub profile: UserProfile,
42}
43
44#[derive(Debug, Deserialize, Serialize)]
45pub struct UserProfile {
46    pub id: u64,
47    pub name: String,
48    #[serde(default)]
49    pub system_owns: u32,
50    #[serde(default)]
51    pub user_owns: u32,
52    #[serde(default)]
53    pub user_bloods: u32,
54    #[serde(default)]
55    pub system_bloods: u32,
56    #[serde(default)]
57    pub rank: Option<String>,
58    #[serde(default)]
59    pub rank_id: u32,
60    #[serde(default)]
61    pub ranking: Option<u32>,
62    #[serde(default)]
63    pub points: u32,
64    #[serde(default)]
65    pub country_name: Option<String>,
66    #[serde(default)]
67    pub country_code: Option<String>,
68    #[serde(default)]
69    pub joined_date: Option<String>,
70    #[serde(default)]
71    pub server: Option<String>,
72    #[serde(
73        default,
74        rename = "isVip",
75        deserialize_with = "deserialize_bool_or_null"
76    )]
77    pub is_vip: bool,
78    #[serde(
79        default,
80        rename = "isDedicatedVip",
81        deserialize_with = "deserialize_bool_or_null"
82    )]
83    pub is_dedicated_vip: bool,
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn deserialize_user_info() {
92        let json = include_str!("../../tests/fixtures/user-info.json");
93        let resp: UserInfoResponse = serde_json::from_str(json).unwrap();
94        assert_eq!(resp.info.name, "TestUser");
95        assert!(!resp.info.is_vip);
96        assert_eq!(resp.info.id, 1234567);
97    }
98
99    #[test]
100    fn deserialize_user_info_vip_fields() {
101        let json = r#"{"info":{"id":1,"name":"VipUser","canAccessVIP":true,"isVip":true}}"#;
102        let resp: UserInfoResponse = serde_json::from_str(json).unwrap();
103        assert!(resp.info.can_access_vip);
104        assert!(resp.info.is_vip);
105    }
106
107    #[test]
108    fn deserialize_user_profile() {
109        let json = include_str!("../../tests/fixtures/user-profile-basic.json");
110        let resp: UserProfileResponse = serde_json::from_str(json).unwrap();
111        assert_eq!(resp.profile.name, "TestUser");
112        assert_eq!(resp.profile.system_owns, 10);
113        assert_eq!(resp.profile.user_owns, 10);
114        assert_eq!(resp.profile.rank.as_deref(), Some("Script Kiddie"));
115        assert_eq!(resp.profile.country_name.as_deref(), Some("Denmark"));
116    }
117}