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#[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#[derive(Clone, Debug, Serialize, Deserialize)]
44#[allow(non_snake_case)]
45#[derive(Default)]
46pub struct PreRegisterInfo {
47 #[serde(rename = "userName")]
49 pub username: String,
50 #[serde(rename = "userPhone")]
52 pub phone: String,
53 pub invitecode: Option<String>,
55 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#[derive(Clone, Debug, Serialize, Deserialize)]
73#[allow(non_snake_case)]
74pub struct RegisterInfo {
75 #[serde(rename = "userAppRole")]
77 pub role: String,
78 #[serde(rename = "userPassword", serialize_with = "serialize_md5")]
80 pub passwd: String,
81 #[serde(rename = "userId")]
83 pub user_id: String,
84 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
106fn 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#[derive(Clone, Debug, Serialize, Deserialize, Default)]
117pub struct FileInfo {
118 pub filename: String,
120 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#[derive(Clone, Debug, Default)]
143pub struct UploadResult {
144 pub errs: Vec<String>,
146 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#[derive(Clone, Debug, Serialize, Deserialize)]
234#[allow(non_snake_case)]
235#[derive(Default)]
236pub struct UserLite {
237 #[serde(rename = "userNickname")]
239 pub user_nickname: String,
240 #[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#[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 pub fn is_vip(&self) -> bool {
287 self.state
288 }
289
290 pub fn expires_date(&self) -> DateTime<Utc> {
292 DateTime::from_timestamp_millis(self.expires_at as i64).unwrap_or_default()
293 }
294
295 pub fn created_date(&self) -> DateTime<Utc> {
297 DateTime::from_timestamp_millis(self.created_at as i64).unwrap_or_default()
298 }
299
300 pub fn updated_date(&self) -> DateTime<Utc> {
302 DateTime::from_timestamp_millis(self.updated_at as i64).unwrap_or_default()
303 }
304
305 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#[derive(Clone, Debug, Serialize, Deserialize)]
347pub enum ReportDataType {
348 Article,
350 Comment,
352 User,
354 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#[derive(Clone, Debug, Serialize, Deserialize)]
371pub enum ReportType {
372 Advertise,
374 Porn,
376 Violate,
378 Infringement,
380 Attacks,
382 Impersonate,
384 AdvertisingAccount,
386 LeakPrivacy,
388 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#[derive(Clone, Debug, Serialize, Deserialize)]
410#[allow(non_snake_case)]
411pub struct Report {
412 #[serde(rename = "reportDataId")]
414 pub report_data_id: String,
415 #[serde(rename = "reportDataType")]
417 pub report_data_type: ReportDataType,
418 #[serde(rename = "reportType")]
420 pub report_type: ReportType,
421 #[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#[derive(Clone, Debug, Serialize, Deserialize)]
456#[allow(non_snake_case)]
457#[derive(Default)]
458pub struct Log {
459 pub key1: String,
461 pub key2: String,
463 pub data: String,
465 #[serde(rename = "public")]
467 pub is_public: bool,
468 pub key3: String,
470 pub o_id: String,
472 #[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}