1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4#[serde(rename_all = "camelCase")]
5pub struct GetLoginQrCodeRequest<'a> {
6 #[serde(rename = "appId")]
8 pub app_id: &'a str,
9 pub r#type: &'a str,
11 pub region_id: &'a str,
13 #[serde(skip_serializing_if = "Option::is_none")]
15 pub proxy_ip: Option<&'a str>,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub ttuid: Option<&'a str>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub aid: Option<&'a str>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize, Default)]
23#[serde(rename_all = "camelCase")]
24pub struct GetLoginQrCodeResponse {
25 pub qr_data: String,
26 pub qr_img_base64: String,
27 pub uuid: String,
28 pub app_id: String,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct CheckLoginRequest<'a> {
34 #[serde(rename = "appId")]
35 pub app_id: &'a str,
36 pub uuid: &'a str,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub proxy_ip: Option<&'a str>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub captch_code: Option<&'a str>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub auto_sliding: Option<bool>,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize, Default)]
46#[serde(rename_all = "camelCase")]
47pub struct CheckLoginResponse {
48 pub uuid: String,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub head_img_url: Option<String>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub nick_name: Option<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub expired_time: Option<i64>,
55 pub status: i32,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub login_info: Option<LoginInfo>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize, Default)]
61#[serde(rename_all = "camelCase")]
62pub struct LoginInfo {
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub uin: Option<i64>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub wxid: Option<String>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 pub nick_name: Option<String>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub mobile: Option<String>,
71 #[serde(skip_serializing_if = "Option::is_none")]
72 pub alias: Option<String>,
73}
74
75#[derive(Debug, Clone, Serialize)]
76#[serde(rename_all = "camelCase")]
77pub struct DialogLoginRequest<'a> {
78 #[serde(rename = "appId")]
79 pub app_id: &'a str,
80 #[serde(rename = "regionId")]
81 pub region_id: &'a str,
82 #[serde(rename = "proxyIp", skip_serializing_if = "Option::is_none")]
83 pub proxy_ip: Option<&'a str>,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub aid: Option<&'a str>,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize, Default)]
89#[serde(rename_all = "camelCase")]
90pub struct DialogLoginResponse {
91 #[serde(rename = "appId")]
92 pub app_id: String,
93 pub uuid: String,
94}
95
96#[derive(Debug, Clone, Serialize)]
97#[serde(rename_all = "camelCase")]
98pub struct LoginByAccountRequest<'a> {
99 #[serde(rename = "appId")]
100 pub app_id: &'a str,
101 #[serde(rename = "proxyIp")]
102 pub proxy_ip: &'a str,
103 #[serde(rename = "regionId")]
104 pub region_id: &'a str,
105 pub account: &'a str,
106 pub password: &'a str,
107 pub step: i32,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize, Default)]
111#[serde(rename_all = "camelCase")]
112pub struct LoginByAccountResponse {
113 #[serde(rename = "appId", skip_serializing_if = "Option::is_none")]
114 pub app_id: Option<String>,
115 #[serde(rename = "base64Img", skip_serializing_if = "Option::is_none")]
116 pub base64_img: Option<String>,
117 #[serde(skip_serializing_if = "Option::is_none")]
118 pub uuid: Option<String>,
119 #[serde(rename = "headImgUrl", skip_serializing_if = "Option::is_none")]
120 pub head_img_url: Option<String>,
121 #[serde(rename = "nickName", skip_serializing_if = "Option::is_none")]
122 pub nick_name: Option<String>,
123 #[serde(rename = "expiredTime", skip_serializing_if = "Option::is_none")]
124 pub expired_time: Option<i64>,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub status: Option<i32>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub login_info: Option<LoginInfo>,
129}
130
131#[derive(Debug, Clone, Serialize)]
132#[serde(rename_all = "camelCase")]
133pub struct SetCallbackRequest<'a> {
134 pub token: &'a str,
135 #[serde(rename = "callbackUrl")]
136 pub callback_url: &'a str,
137}
138
139#[derive(Debug, Clone, Serialize)]
140#[serde(rename_all = "camelCase")]
141pub struct ChangeMacToIpadRequest<'a> {
142 #[serde(rename = "appId")]
143 pub app_id: &'a str,
144}
145
146#[derive(Debug, Clone, Serialize)]
147#[serde(rename_all = "camelCase")]
148pub struct CheckOnlineRequest<'a> {
149 #[serde(rename = "appId")]
150 pub app_id: &'a str,
151}
152
153pub type CheckOnlineResponse = bool;
154
155#[derive(Debug, Clone, Serialize)]
156#[serde(rename_all = "camelCase")]
157pub struct ReconnectionRequest<'a> {
158 #[serde(rename = "appId")]
159 pub app_id: &'a str,
160}
161
162#[derive(Debug, Clone, Serialize, Deserialize, Default)]
163#[serde(rename_all = "camelCase")]
164pub struct ReconnectionResponse {
165 pub uuid: String,
166 #[serde(rename = "headImgUrl", skip_serializing_if = "Option::is_none")]
167 pub head_img_url: Option<String>,
168 #[serde(rename = "nickName", skip_serializing_if = "Option::is_none")]
169 pub nick_name: Option<String>,
170 #[serde(rename = "expiredTime", skip_serializing_if = "Option::is_none")]
171 pub expired_time: Option<i64>,
172 pub status: i32,
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub login_info: Option<LoginInfo>,
175}
176
177#[derive(Debug, Clone, Serialize)]
178#[serde(rename_all = "camelCase")]
179pub struct LogoutRequest<'a> {
180 #[serde(rename = "appId")]
181 pub app_id: &'a str,
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187
188 #[test]
189 fn test_get_login_qr_code_response_default() {
190 let resp = GetLoginQrCodeResponse::default();
191 assert_eq!(resp.qr_data, "");
192 assert_eq!(resp.qr_img_base64, "");
193 assert_eq!(resp.uuid, "");
194 assert_eq!(resp.app_id, "");
195 }
196
197 #[test]
198 fn test_get_login_qr_code_response_deserialization() {
199 let json = r#"{
200 "qrData": "test_qr_data",
201 "qrImgBase64": "base64_image",
202 "uuid": "test_uuid",
203 "appId": "test_app_id"
204 }"#;
205 let resp: GetLoginQrCodeResponse = serde_json::from_str(json).unwrap();
206 assert_eq!(resp.qr_data, "test_qr_data");
207 assert_eq!(resp.qr_img_base64, "base64_image");
208 assert_eq!(resp.uuid, "test_uuid");
209 assert_eq!(resp.app_id, "test_app_id");
210 }
211
212 #[test]
213 fn test_check_login_response_default() {
214 let resp = CheckLoginResponse::default();
215 assert_eq!(resp.uuid, "");
216 assert_eq!(resp.status, 0);
217 assert_eq!(resp.head_img_url, None);
218 assert_eq!(resp.nick_name, None);
219 }
220
221 #[test]
222 fn test_check_login_response_with_login_info() {
223 let json = r#"{
224 "uuid": "test_uuid",
225 "status": 1,
226 "headImgUrl": "http://example.com/avatar.jpg",
227 "nickName": "TestUser",
228 "expiredTime": 1234567890,
229 "loginInfo": {
230 "uin": 123456,
231 "wxid": "test_wxid",
232 "nickName": "TestUser",
233 "mobile": "1234567890",
234 "alias": "test_alias"
235 }
236 }"#;
237 let resp: CheckLoginResponse = serde_json::from_str(json).unwrap();
238 assert_eq!(resp.uuid, "test_uuid");
239 assert_eq!(resp.status, 1);
240 assert_eq!(
241 resp.head_img_url,
242 Some("http://example.com/avatar.jpg".to_string())
243 );
244 assert_eq!(resp.nick_name, Some("TestUser".to_string()));
245 assert_eq!(resp.expired_time, Some(1234567890));
246 assert!(resp.login_info.is_some());
247
248 let login_info = resp.login_info.unwrap();
249 assert_eq!(login_info.uin, Some(123456));
250 assert_eq!(login_info.wxid, Some("test_wxid".to_string()));
251 assert_eq!(login_info.nick_name, Some("TestUser".to_string()));
252 assert_eq!(login_info.mobile, Some("1234567890".to_string()));
253 assert_eq!(login_info.alias, Some("test_alias".to_string()));
254 }
255
256 #[test]
257 fn test_login_info_default() {
258 let info = LoginInfo::default();
259 assert_eq!(info.uin, None);
260 assert_eq!(info.wxid, None);
261 assert_eq!(info.nick_name, None);
262 assert_eq!(info.mobile, None);
263 assert_eq!(info.alias, None);
264 }
265
266 #[test]
267 fn test_dialog_login_response_default() {
268 let resp = DialogLoginResponse::default();
269 assert_eq!(resp.app_id, "");
270 assert_eq!(resp.uuid, "");
271 }
272
273 #[test]
274 fn test_dialog_login_response_deserialization() {
275 let json = r#"{
276 "appId": "test_app",
277 "uuid": "test_uuid"
278 }"#;
279 let resp: DialogLoginResponse = serde_json::from_str(json).unwrap();
280 assert_eq!(resp.app_id, "test_app");
281 assert_eq!(resp.uuid, "test_uuid");
282 }
283
284 #[test]
285 fn test_login_by_account_response_default() {
286 let resp = LoginByAccountResponse::default();
287 assert_eq!(resp.app_id, None);
288 assert_eq!(resp.base64_img, None);
289 assert_eq!(resp.uuid, None);
290 assert_eq!(resp.status, None);
291 }
292
293 #[test]
294 fn test_login_by_account_response_deserialization() {
295 let json = r#"{
296 "appId": "test_app",
297 "base64Img": "base64_data",
298 "uuid": "test_uuid",
299 "headImgUrl": "http://example.com/avatar.jpg",
300 "nickName": "TestUser",
301 "expiredTime": 1234567890,
302 "status": 1
303 }"#;
304 let resp: LoginByAccountResponse = serde_json::from_str(json).unwrap();
305 assert_eq!(resp.app_id, Some("test_app".to_string()));
306 assert_eq!(resp.base64_img, Some("base64_data".to_string()));
307 assert_eq!(resp.uuid, Some("test_uuid".to_string()));
308 assert_eq!(
309 resp.head_img_url,
310 Some("http://example.com/avatar.jpg".to_string())
311 );
312 assert_eq!(resp.nick_name, Some("TestUser".to_string()));
313 assert_eq!(resp.expired_time, Some(1234567890));
314 assert_eq!(resp.status, Some(1));
315 }
316
317 #[test]
318 fn test_reconnection_response_default() {
319 let resp = ReconnectionResponse::default();
320 assert_eq!(resp.uuid, "");
321 assert_eq!(resp.status, 0);
322 assert_eq!(resp.head_img_url, None);
323 }
324
325 #[test]
326 fn test_reconnection_response_deserialization() {
327 let json = r#"{
328 "uuid": "test_uuid",
329 "status": 1,
330 "headImgUrl": "http://example.com/avatar.jpg",
331 "nickName": "TestUser",
332 "expiredTime": 1234567890
333 }"#;
334 let resp: ReconnectionResponse = serde_json::from_str(json).unwrap();
335 assert_eq!(resp.uuid, "test_uuid");
336 assert_eq!(resp.status, 1);
337 assert_eq!(
338 resp.head_img_url,
339 Some("http://example.com/avatar.jpg".to_string())
340 );
341 assert_eq!(resp.nick_name, Some("TestUser".to_string()));
342 assert_eq!(resp.expired_time, Some(1234567890));
343 }
344
345 #[test]
346 fn test_get_login_qr_code_request_serialization() {
347 let req = GetLoginQrCodeRequest {
348 app_id: "test_app",
349 r#type: "ipad",
350 region_id: "cn",
351 proxy_ip: Some("127.0.0.1"),
352 ttuid: None,
353 aid: None,
354 };
355 let json = serde_json::to_string(&req).unwrap();
356 assert!(json.contains("test_app"));
357 assert!(json.contains("ipad"));
358 assert!(json.contains("cn"));
359 assert!(json.contains("127.0.0.1"));
360 }
361
362 #[test]
363 fn test_check_login_request_serialization() {
364 let req = CheckLoginRequest {
365 app_id: "test_app",
366 uuid: "test_uuid",
367 proxy_ip: None,
368 captch_code: None,
369 auto_sliding: Some(true),
370 };
371 let json = serde_json::to_string(&req).unwrap();
372 assert!(json.contains("test_app"));
373 assert!(json.contains("test_uuid"));
374 assert!(json.contains("true"));
375 }
376
377 #[test]
378 fn test_dialog_login_request_serialization() {
379 let req = DialogLoginRequest {
380 app_id: "test_app",
381 region_id: "cn",
382 proxy_ip: Some("127.0.0.1"),
383 aid: None,
384 };
385 let json = serde_json::to_string(&req).unwrap();
386 assert!(json.contains("test_app"));
387 assert!(json.contains("cn"));
388 assert!(json.contains("127.0.0.1"));
389 }
390
391 #[test]
392 fn test_login_by_account_request_serialization() {
393 let req = LoginByAccountRequest {
394 app_id: "test_app",
395 proxy_ip: "127.0.0.1",
396 region_id: "cn",
397 account: "test_account",
398 password: "test_password",
399 step: 1,
400 };
401 let json = serde_json::to_string(&req).unwrap();
402 assert!(json.contains("test_app"));
403 assert!(json.contains("127.0.0.1"));
404 assert!(json.contains("test_account"));
405 assert!(json.contains("test_password"));
406 }
407
408 #[test]
409 fn test_set_callback_request_serialization() {
410 let req = SetCallbackRequest {
411 token: "test_token",
412 callback_url: "http://example.com/callback",
413 };
414 let json = serde_json::to_string(&req).unwrap();
415 assert!(json.contains("test_token"));
416 assert!(json.contains("http://example.com/callback"));
417 }
418
419 #[test]
420 fn test_change_mac_to_ipad_request_serialization() {
421 let req = ChangeMacToIpadRequest { app_id: "test_app" };
422 let json = serde_json::to_string(&req).unwrap();
423 assert!(json.contains("test_app"));
424 }
425
426 #[test]
427 fn test_check_online_request_serialization() {
428 let req = CheckOnlineRequest { app_id: "test_app" };
429 let json = serde_json::to_string(&req).unwrap();
430 assert!(json.contains("test_app"));
431 }
432
433 #[test]
434 fn test_reconnection_request_serialization() {
435 let req = ReconnectionRequest { app_id: "test_app" };
436 let json = serde_json::to_string(&req).unwrap();
437 assert!(json.contains("test_app"));
438 }
439
440 #[test]
441 fn test_logout_request_serialization() {
442 let req = LogoutRequest { app_id: "test_app" };
443 let json = serde_json::to_string(&req).unwrap();
444 assert!(json.contains("test_app"));
445 }
446}