Skip to main content

fishpi_sdk/model/
misc.rs

1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use serde_json::Value;
3
4use crate::utils::error::Error;
5
6fn to_md5(input: &str) -> String {
7    let hash = md5::compute(input);
8    format!("{:x}", hash)
9}
10
11/// 登录账户信息
12#[derive(Clone, Debug, Default, Serialize, Deserialize)]
13pub struct LoginData {
14    #[serde(rename = "nameOrEmail")]
15    pub username: String,
16    #[serde(rename = "userPassword")]
17    pub password: String,
18    #[serde(rename = "mfaCode")]
19    pub mfa_code: Option<String>,
20}
21
22impl LoginData {
23    pub fn new(username: &str, password: &str, mfa_code: Option<String>) -> Self {
24        LoginData {
25            username: username.to_string(),
26            password: to_md5(password),
27            mfa_code,
28        }
29    }
30
31    pub fn from_value(value: &Value) -> Result<Self, Error> {
32        serde_json::from_value(value.clone())
33            .map_err(|e| Error::Parse(format!("Failed to parse LoginData: {}", e)))
34    }
35
36    pub fn to_value(&self) -> Result<Value, Error> {
37        serde_json::to_value(self)
38            .map_err(|e| Error::Parse(format!("Failed to serialize LoginData: {}", e)))
39    }
40}
41
42/// 预注册账户信息
43#[derive(Clone, Debug, Serialize, Deserialize)]
44#[allow(non_snake_case)]
45#[derive(Default)]
46pub struct PreRegisterInfo {
47    /// 用户名
48    #[serde(rename = "userName")]
49    pub username: String,
50    /// 手机号
51    #[serde(rename = "userPhone")]
52    pub phone: String,
53    /// 邀请码
54    pub invitecode: Option<String>,
55    /// 验证码
56    pub captcha: String,
57}
58
59impl PreRegisterInfo {
60    pub fn from_value(data: &Value) -> Result<Self, Error> {
61        serde_json::from_value(data.clone())
62            .map_err(|e| Error::Parse(format!("Failed to parse PreRegisterInfo: {}", e)))
63    }
64
65    pub fn to_value(&self) -> Result<Value, Error> {
66        serde_json::to_value(self)
67            .map_err(|e| Error::Parse(format!("Failed to serialize PreRegisterInfo: {}", e)))
68    }
69}
70
71/// 注册账户信息
72#[derive(Clone, Debug, Serialize, Deserialize)]
73#[allow(non_snake_case)]
74pub struct RegisterInfo {
75    /// 用户角色
76    #[serde(rename = "userAppRole")]
77    pub role: String,
78    /// 用户密码
79    #[serde(rename = "userPassword", serialize_with = "serialize_md5")]
80    pub passwd: String,
81    /// 用户 Id
82    #[serde(rename = "userId")]
83    pub user_id: String,
84    /// 邀请人用户名
85    pub r: Option<String>,
86}
87
88impl RegisterInfo {
89    pub fn from_value(data: &Value) -> Result<Self, Error> {
90        serde_json::from_value(data.clone())
91            .map_err(|e| Error::Parse(format!("Failed to parse RegisterInfo: {}", e)))
92    }
93}
94
95impl Default for RegisterInfo {
96    fn default() -> Self {
97        Self {
98            role: "0".to_string(),
99            passwd: String::new(),
100            user_id: String::new(),
101            r: None,
102        }
103    }
104}
105
106/// 计算 MD5
107fn serialize_md5<S>(passwd: &str, serializer: S) -> Result<S::Ok, S::Error>
108where
109    S: Serializer,
110{
111    let hash = md5::compute(passwd.as_bytes());
112    serializer.serialize_str(&format!("{:x}", hash))
113}
114
115/// 上传文件信息
116#[derive(Clone, Debug, Serialize, Deserialize, Default)]
117pub struct FileInfo {
118    /// 文件名
119    pub filename: String,
120    /// 文件地址
121    pub url: String,
122}
123
124impl FileInfo {
125    pub fn from_value(data: &Value) -> Result<Self, Error> {
126        serde_json::from_value(data.clone())
127            .map_err(|e| Error::Parse(format!("Failed to parse FileInfo: {}", e)))
128    }
129}
130
131impl std::fmt::Display for FileInfo {
132    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133        write!(
134            f,
135            "FileInfo{{filename={}, url={}}}",
136            self.filename, self.url
137        )
138    }
139}
140
141/// 上传结果
142#[derive(Clone, Debug, Default)]
143pub struct UploadResult {
144    /// 上传失败文件
145    pub errs: Vec<String>,
146    /// 上传成功文件
147    pub success: Vec<FileInfo>,
148}
149
150impl UploadResult {
151    pub fn from_value(data: &Value) -> Result<Self, Error> {
152        let errs = data["errFiles"]
153            .as_array()
154            .unwrap_or(&vec![])
155            .iter()
156            .filter_map(|v| v.as_str().map(|s| s.to_string()))
157            .collect();
158
159        let success = if let Some(succ_map) = data["succMap"].as_object() {
160            succ_map
161                .iter()
162                .map(|(filename, url)| FileInfo {
163                    filename: filename.clone(),
164                    url: url.as_str().unwrap_or("").to_string(),
165                })
166                .collect()
167        } else {
168            vec![]
169        };
170
171        Ok(UploadResult { errs, success })
172    }
173}
174
175impl Serialize for UploadResult {
176    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
177    where
178        S: Serializer,
179    {
180        use serde::ser::SerializeMap;
181
182        let mut map = serializer.serialize_map(Some(2))?;
183        map.serialize_entry("errFiles", &self.errs)?;
184        let succ_map: std::collections::HashMap<String, String> = self
185            .success
186            .iter()
187            .map(|f| (f.filename.clone(), f.url.clone()))
188            .collect();
189        map.serialize_entry("succMap", &succ_map)?;
190        map.end()
191    }
192}
193
194impl<'de> Deserialize<'de> for UploadResult {
195    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
196    where
197        D: Deserializer<'de>,
198    {
199        #[derive(Deserialize)]
200        struct UploadResultHelper {
201            #[serde(rename = "errFiles")]
202            errs: Vec<String>,
203            #[serde(rename = "succMap")]
204            succ_map: std::collections::HashMap<String, String>,
205        }
206
207        let helper = UploadResultHelper::deserialize(deserializer)?;
208        let success = helper
209            .succ_map
210            .into_iter()
211            .map(|(filename, url)| FileInfo { filename, url })
212            .collect();
213
214        Ok(UploadResult {
215            errs: helper.errs,
216            success,
217        })
218    }
219}
220
221impl std::fmt::Display for UploadResult {
222    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223        let errs_str = self.errs.join(",");
224        write!(
225            f,
226            "UploadResult{{ errFiles={}, succFiles={:?} }}",
227            errs_str, self.success
228        )
229    }
230}
231
232/// 最近注册用户信息
233#[derive(Clone, Debug, Serialize, Deserialize)]
234#[allow(non_snake_case)]
235#[derive(Default)]
236pub struct UserLite {
237    /// 用户昵称
238    #[serde(rename = "userNickname")]
239    pub user_nickname: String,
240    /// 用户名
241    #[serde(rename = "userName")]
242    pub user_name: String,
243}
244
245impl UserLite {
246    pub fn from_value(data: &Value) -> Result<Self, Error> {
247        serde_json::from_value(data.clone())
248            .map_err(|e| Error::Parse(format!("Failed to parse UserLite: {}", e)))
249    }
250}
251
252impl std::fmt::Display for UserLite {
253    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254        write!(
255            f,
256            "UserLite{{userNickname: {}, userName: {}}}",
257            self.user_nickname, self.user_name
258        )
259    }
260}
261
262use chrono::{DateTime, Utc};
263
264/// 用户 VIP 信息
265#[derive(Clone, Debug, Serialize, Deserialize)]
266#[allow(non_snake_case)]
267#[derive(Default)]
268pub struct UserVipInfo {
269    pub joint_vip: bool,
270    pub color: String,
271    pub underline: bool,
272    pub metal: bool,
273    pub auto_checkin: u32,
274    pub bold: bool,
275    pub o_id: String,
276    pub state: bool,
277    pub user_id: String,
278    pub lv_code: String,
279    pub expires_at: u64,
280    pub created_at: u64,
281    pub updated_at: u64,
282}
283
284impl UserVipInfo {
285    /// 是否为 VIP
286    pub fn is_vip(&self) -> bool {
287        self.state
288    }
289
290    /// 过期日期
291    pub fn expires_date(&self) -> DateTime<Utc> {
292        DateTime::from_timestamp_millis(self.expires_at as i64).unwrap_or_default()
293    }
294
295    /// 创建日期
296    pub fn created_date(&self) -> DateTime<Utc> {
297        DateTime::from_timestamp_millis(self.created_at as i64).unwrap_or_default()
298    }
299
300    /// 更新日期
301    pub fn updated_date(&self) -> DateTime<Utc> {
302        DateTime::from_timestamp_millis(self.updated_at as i64).unwrap_or_default()
303    }
304
305    /// VIP 名称
306    pub fn vip_name(&self) -> String {
307        self.lv_code
308            .replace("_YEAR", "(包年)")
309            .replace("_MONTH", "(包月)")
310    }
311
312    pub fn from_value(data: &Value) -> Result<Self, Error> {
313        let joint_vip = data["jointVip"].as_bool().unwrap_or(false);
314        let color = data["color"].as_str().unwrap_or("").to_string();
315        let underline = data["underline"].as_bool().unwrap_or(false);
316        let metal = data["metal"].as_bool().unwrap_or(false);
317        let auto_checkin = data["autoCheckin"].as_u64().unwrap_or(0) as u32;
318        let bold = data["bold"].as_bool().unwrap_or(false);
319        let o_id = data["oId"].as_str().unwrap_or("").to_string();
320        let state = data["state"].as_i64().unwrap_or(0) == 1;
321        let user_id = data["userId"].as_str().unwrap_or("").to_string();
322        let lv_code = data["lvCode"].as_str().unwrap_or("").to_string();
323        let expires_at = data["expiresAt"].as_u64().unwrap_or(0);
324        let created_at = data["createdAt"].as_u64().unwrap_or(0);
325        let updated_at = data["updatedAt"].as_u64().unwrap_or(0);
326
327        Ok(UserVipInfo {
328            joint_vip,
329            color,
330            underline,
331            metal,
332            auto_checkin,
333            bold,
334            o_id,
335            state,
336            user_id,
337            lv_code,
338            expires_at,
339            created_at,
340            updated_at,
341        })
342    }
343}
344
345/// 举报数据类型
346#[derive(Clone, Debug, Serialize, Deserialize)]
347pub enum ReportDataType {
348    /// 文章
349    Article,
350    /// 评论
351    Comment,
352    /// 用户
353    User,
354    /// 聊天消息
355    Chatroom,
356}
357
358impl From<u8> for ReportDataType {
359    fn from(value: u8) -> Self {
360        match value {
361            0 => Self::Article,
362            1 => Self::Comment,
363            2 => Self::User,
364            _ => Self::Chatroom,
365        }
366    }
367}
368
369/// 举报类型
370#[derive(Clone, Debug, Serialize, Deserialize)]
371pub enum ReportType {
372    /// 垃圾广告
373    Advertise,
374    /// 色情
375    Porn,
376    /// 违规
377    Violate,
378    /// 侵权
379    Infringement,
380    /// 人身攻击
381    Attacks,
382    /// 冒充他人账号
383    Impersonate,
384    /// 垃圾广告账号
385    AdvertisingAccount,
386    /// 违规泄露个人信息
387    LeakPrivacy,
388    /// 其它
389    Other,
390}
391
392impl From<u8> for ReportType {
393    fn from(value: u8) -> Self {
394        match value {
395            0 => Self::Advertise,
396            1 => Self::Porn,
397            2 => Self::Violate,
398            3 => Self::Infringement,
399            4 => Self::Attacks,
400            5 => Self::Impersonate,
401            6 => Self::AdvertisingAccount,
402            7 => Self::LeakPrivacy,
403            _ => Self::Other,
404        }
405    }
406}
407
408/// 举报数据
409#[derive(Clone, Debug, Serialize, Deserialize)]
410#[allow(non_snake_case)]
411pub struct Report {
412    /// 举报对象的 oId
413    #[serde(rename = "reportDataId")]
414    pub report_data_id: String,
415    /// 举报数据的类型
416    #[serde(rename = "reportDataType")]
417    pub report_data_type: ReportDataType,
418    /// 举报的类型
419    #[serde(rename = "reportType")]
420    pub report_type: ReportType,
421    /// 举报的理由
422    #[serde(rename = "reportMemo")]
423    pub report_memo: String,
424}
425
426impl Report {
427    pub fn from_value(data: &Value) -> Result<Self, Error> {
428        let report_data_id = data["reportDataId"].as_str().unwrap_or("").to_string();
429        let report_data_type =
430            ReportDataType::from(data["reportDataType"].as_u64().unwrap_or(3) as u8);
431        let report_type = ReportType::from(data["reportType"].as_u64().unwrap_or(0) as u8);
432        let report_memo = data["reportMemo"].as_str().unwrap_or("").to_string();
433
434        Ok(Report {
435            report_data_id,
436            report_data_type,
437            report_type,
438            report_memo,
439        })
440    }
441}
442
443impl Default for Report {
444    fn default() -> Self {
445        Self {
446            report_data_id: String::new(),
447            report_data_type: ReportDataType::Chatroom,
448            report_type: ReportType::Advertise,
449            report_memo: String::new(),
450        }
451    }
452}
453
454/// 服务器日志
455#[derive(Clone, Debug, Serialize, Deserialize)]
456#[allow(non_snake_case)]
457#[derive(Default)]
458pub struct Log {
459    /// 操作时间
460    pub key1: String,
461    /// IP
462    pub key2: String,
463    /// 内容
464    pub data: String,
465    /// 是否公开
466    #[serde(rename = "public")]
467    pub is_public: bool,
468    /// 操作类型
469    pub key3: String,
470    /// 唯一标识
471    pub o_id: String,
472    /// 类型
473    #[serde(rename = "type")]
474    pub type_: String,
475}
476
477impl Log {
478    pub fn from_value(data: &Value) -> Result<Self, Error> {
479        serde_json::from_value(data.clone())
480            .map_err(|e| Error::Parse(format!("Failed to parse Log: {}", e)))
481    }
482}