1use std::{fmt::{
2 Display,
3 Debug
4}, sync::Arc};
5
6use log::{error, info};
7use reqwest::{StatusCode, IntoUrl, header::CONTENT_TYPE};
8use serde::{Serialize, Deserialize};
9use async_lock::RwLock;
10
11use crate::api::{
12 result::{
13 BotXApiError,
14 ExpressResult,
15 BotXApiResult,
16 },
17 context::BotXApiContext, v2::token::api::token, models::FileResponse
18};
19
20#[derive(Debug)]
21pub struct MultipartPartData {
22 pub name: String,
23 pub file_name: Option<String>,
24 pub content: MultipartPartDataContent,
25 pub mime_type: Option<String>,
26}
27
28#[derive(Debug)]
29pub enum MultipartPartDataContent {
30 Bytes(Vec<u8>),
31 Text(String)
32}
33
34pub struct RequestManager {}
35
36impl RequestManager {
37 pub const JSON_CONTENT_TYPE: &str = "application/json";
38 pub const MULTIPART_CONTENT_TYPE: &str = "multipart/form-data";
39
40 pub async fn post<TRequest, TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, request: &TRequest, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
41 where
42 TRequest: Serialize,
43 for<'a> TResponse: Deserialize<'a> + Debug,
44 for<'a> TError: Deserialize<'a> + Debug,
45 {
46 log::info!("{request_name} request url [{url:?}]");
47 log::debug!("{request_name} request data [{}]", serde_json::to_string(request).unwrap());
48
49 let context_read_lock = context.read().await;
50
51 let raw_response = if context_read_lock.auth_token.is_some() {
52 let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
53
54 let raw_response = context_read_lock.client.post(url)
55 .bearer_auth(auth_token)
56 .header(reqwest::header::CONTENT_TYPE, content_type.into())
57 .json(request)
58 .send()
59 .await
60 .map_err::<BotXApiError<TError>, _>(|e| {
61 log::error!("{request_name} request error:[{e:#?}]");
62 e.into()
63 })?;
64
65 drop(context_read_lock);
66
67 raw_response
68 } else {
69 info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
70
71 drop(context_read_lock);
72
73 let mut context_write_lock = context.write().await;
74
75 let token_response = token(&mut *context_write_lock).await;
76
77 let Ok(token_result) = token_response else {
78 error!("Не удалось повторить запрос с пере авторизацией");
79 return Err(BotXApiError::Unauthorized);
80 };
81
82 context_write_lock.auth_token = Some(token_result.token.clone());
83
84 let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
85
86 let auth_token = token_result.token;
87
88 let raw_response = context_read_lock.client.post(url)
89 .bearer_auth(auth_token)
90 .header(reqwest::header::CONTENT_TYPE, content_type.into())
91 .json(request)
92 .send()
93 .await
94 .map_err::<BotXApiError<TError>, _>(|e| {
95 log::error!("{request_name} request error:[{e:#?}]");
96 e.into()
97 })?;
98
99 drop(context_read_lock);
100
101 raw_response
102 };
103
104 let status_code = raw_response.status();
105 let response_body = raw_response.text()
106 .await
107 .map_err::<BotXApiError<TError>, _>(|e| {
108 log::error!("{request_name} read response error:[{e:#?}]");
109 e.into()
110 })?;
111
112 if status_code == StatusCode::UNAUTHORIZED {
113 log::debug!("{request_name} request Unauthorized {response_body}");
114 return Err(BotXApiError::Unauthorized);
115 }
116
117 let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
118 .map_err(|e| {
119 log::error!("{request_name} response body deserialization error: [{response_body}]");
120 BotXApiError::SerdeError(e)
121 })?;
122
123 if !response.is_ok() {
124 log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
125 } else {
126 log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
127 }
128
129 response.into()
130 }
131
132 pub async fn put<TRequest, TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, request: &TRequest, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
133 where
134 TRequest: Serialize,
135 for<'a> TResponse: Deserialize<'a> + Debug,
136 for<'a> TError: Deserialize<'a> + Debug,
137 {
138 log::info!("{request_name} request url [{url:?}]");
139 log::debug!("{request_name} request data [{}]", serde_json::to_string(request).unwrap());
140
141 let context_read_lock = context.read().await;
142
143 let raw_response = if context_read_lock.auth_token.is_some() {
144 let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
145
146 let raw_response = context_read_lock.client.put(url)
147 .bearer_auth(auth_token)
148 .header(reqwest::header::CONTENT_TYPE, content_type.into())
149 .json(request)
150 .send()
151 .await
152 .map_err::<BotXApiError<TError>, _>(|e| {
153 log::error!("{request_name} request error:[{e:#?}]");
154 e.into()
155 })?;
156
157 drop(context_read_lock);
158
159 raw_response
160 } else {
161 info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
162
163 drop(context_read_lock);
164
165 let mut context_write_lock = context.write().await;
166
167 let token_response = token(&mut *context_write_lock).await;
168
169 let Ok(token_result) = token_response else {
170 error!("Не удалось повторить запрос с пере авторизацией");
171 return Err(BotXApiError::Unauthorized);
172 };
173
174 context_write_lock.auth_token = Some(token_result.token.clone());
175
176 let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
177
178 let auth_token = token_result.token;
179
180 let raw_response = context_read_lock.client.put(url)
181 .bearer_auth(auth_token)
182 .header(reqwest::header::CONTENT_TYPE, content_type.into())
183 .json(request)
184 .send()
185 .await
186 .map_err::<BotXApiError<TError>, _>(|e| {
187 log::error!("{request_name} request error:[{e:#?}]");
188 e.into()
189 })?;
190
191 drop(context_read_lock);
192
193 raw_response
194 };
195
196 let status_code = raw_response.status();
197 let response_body = raw_response.text()
198 .await
199 .map_err::<BotXApiError<TError>, _>(|e| {
200 log::error!("{request_name} read response error:[{e:#?}]");
201 e.into()
202 })?;
203
204 if status_code == StatusCode::UNAUTHORIZED {
205 log::debug!("{request_name} request Unauthorized {response_body}");
206 return Err(BotXApiError::Unauthorized);
207 }
208
209 let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
210 .map_err(|e| {
211 log::error!("{request_name} response body deserialization error: [{response_body}]");
212 BotXApiError::SerdeError(e)
213 })?;
214
215 if !response.is_ok() {
216 log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
217 } else {
218 log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
219 }
220
221 response.into()
222 }
223
224 pub async fn get<TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
225 where
226 for<'a> TResponse: Deserialize<'a> + Debug,
227 for<'a> TError: Deserialize<'a> + Debug,
228 {
229 log::info!("{request_name} request url [{url:?}]");
230
231 let context_read_lock = context.read().await;
232
233 let raw_response = if context_read_lock.auth_token.is_some() {
234 let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
235
236 let raw_response = context_read_lock.client.get(url)
237 .bearer_auth(auth_token)
238 .header(reqwest::header::CONTENT_TYPE, content_type.into())
239 .send()
240 .await
241 .map_err::<BotXApiError<TError>, _>(|e| {
242 log::error!("{request_name} request error:[{e:#?}]");
243 e.into()
244 })?;
245
246 drop(context_read_lock);
247
248 raw_response
249 } else {
250 info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
251
252 drop(context_read_lock);
253
254 let mut context_write_lock = context.write().await;
255
256 let token_response = token(&mut *context_write_lock).await;
257
258 let Ok(token_result) = token_response else {
259 error!("Не удалось повторить запрос с пере авторизацией");
260 return Err(BotXApiError::Unauthorized);
261 };
262
263 context_write_lock.auth_token = Some(token_result.token.clone());
264
265 let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
266
267 let auth_token = token_result.token;
268
269 let raw_response = context_read_lock.client.get(url)
270 .bearer_auth(auth_token)
271 .header(reqwest::header::CONTENT_TYPE, content_type.into())
272 .send()
273 .await
274 .map_err::<BotXApiError<TError>, _>(|e| {
275 log::error!("{request_name} request error:[{e:#?}]");
276 e.into()
277 })?;
278
279 drop(context_read_lock);
280
281 raw_response
282 };
283
284 let status_code = raw_response.status();
285 let response_body = raw_response.text()
286 .await
287 .map_err::<BotXApiError<TError>, _>(|e| {
288 log::error!("{request_name} read response error:[{e:#?}]");
289 e.into()
290 })?;
291
292 if status_code == StatusCode::UNAUTHORIZED {
293 log::debug!("{request_name} request Unauthorized {response_body}");
294 return Err(BotXApiError::Unauthorized);
295 }
296
297 let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
298 .map_err(|e| {
299 log::error!("{request_name} response body deserialization error: [{response_body}]");
300 BotXApiError::SerdeError(e)
301 })?;
302
303 if !response.is_ok() {
304 log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
305 } else {
306 log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
307 }
308
309 response.into()
310 }
311
312 pub async fn get_file<TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<FileResponse, TError>
313 where
314 for<'a> TError: Deserialize<'a> + Debug,
315 {
316 log::info!("{request_name} request url [{url:?}]");
317
318 let context_read_lock = context.read().await;
319
320 let raw_response = if context_read_lock.auth_token.is_some() {
321 let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
322
323 let raw_response = context_read_lock.client.get(url)
324 .bearer_auth(auth_token)
325 .header(reqwest::header::CONTENT_TYPE, content_type.into())
326 .send()
327 .await
328 .map_err::<BotXApiError<TError>, _>(|e| {
329 log::error!("{request_name} request error:[{e:#?}]");
330 e.into()
331 })?;
332
333 drop(context_read_lock);
334
335 raw_response
336 } else {
337 info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
338
339 drop(context_read_lock);
340
341 let mut context_write_lock = context.write().await;
342
343 let token_response = token(&mut *context_write_lock).await;
344
345 let Ok(token_result) = token_response else {
346 error!("Не удалось повторить запрос с пере авторизацией");
347 return Err(BotXApiError::Unauthorized);
348 };
349
350 context_write_lock.auth_token = Some(token_result.token.clone());
351
352 let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
353
354 let auth_token = token_result.token;
355
356 let raw_response = context_read_lock.client.get(url)
357 .bearer_auth(auth_token)
358 .header(reqwest::header::CONTENT_TYPE, content_type.into())
359 .send()
360 .await
361 .map_err::<BotXApiError<TError>, _>(|e| {
362 log::error!("{request_name} request error:[{e:#?}]");
363 e.into()
364 })?;
365
366 drop(context_read_lock);
367
368 raw_response
369 };
370
371 let status_code = raw_response.status();
372
373 let result = if [200u16, 201u16].contains(&raw_response.status().as_u16()) {
375 let content_type = raw_response.headers()
376 .get(CONTENT_TYPE)
377 .map(|x| x.to_str()
378 .unwrap()
379 .to_string())
380 .unwrap_or("text/plain".to_string());
381
382 let data = raw_response.bytes()
383 .await
384 .map_err::<BotXApiError<TError>, _>(|e| {
385 log::error!("{request_name} read response error:[{e:#?}]");
386 e.into()
387 })?
388 .to_vec();
389
390 ExpressResult::Ok(FileResponse { content_type: serde_json::from_str(&*format!("\"{content_type}\"")).unwrap(), data })
391 } else {
392 let response_body = raw_response.text()
393 .await
394 .map_err::<BotXApiError<TError>, _>(|e| {
395 log::error!("{request_name} read response error:[{e:#?}]");
396 e.into()
397 })?;
398
399 if status_code == StatusCode::UNAUTHORIZED {
400 log::debug!("{request_name} request Unauthorized {response_body}");
401 return Err(BotXApiError::Unauthorized);
402 }
403
404 let response_error = serde_json::from_str::<TError>(&*response_body).map_err(|e| {
405 log::error!("{request_name} response body deserialization error: [{response_body}]");
406 BotXApiError::SerdeError(e)
407 })?;
408
409 log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response_error:#?}]");
410
411 ExpressResult::Err(response_error)
412 };
413
414 result.into()
415 }
416
417 pub async fn get_csv<TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<Vec<TResponse>, TError>
418 where
419 for<'a> TResponse: Deserialize<'a> + Debug,
420 for<'a> TError: Deserialize<'a> + Debug,
421 {
422 log::info!("{request_name} request url [{url:?}]");
423
424 let context_read_lock = context.read().await;
425
426 let raw_response = if context_read_lock.auth_token.is_some() {
427 let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
428
429 let raw_response = context_read_lock.client.get(url)
430 .bearer_auth(auth_token)
431 .header(reqwest::header::CONTENT_TYPE, content_type.into())
432 .send()
433 .await
434 .map_err::<BotXApiError<TError>, _>(|e| {
435 log::error!("{request_name} request error:[{e:#?}]");
436 e.into()
437 })?;
438
439 drop(context_read_lock);
440
441 raw_response
442 } else {
443 info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
444
445 drop(context_read_lock);
446
447 let mut context_write_lock = context.write().await;
448
449 let token_response = token(&mut *context_write_lock).await;
450
451 let Ok(token_result) = token_response else {
452 error!("Не удалось повторить запрос с пере авторизацией");
453 return Err(BotXApiError::Unauthorized);
454 };
455
456 context_write_lock.auth_token = Some(token_result.token.clone());
457
458 let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
459
460 let auth_token = token_result.token;
461
462 let raw_response = context_read_lock.client.get(url)
463 .bearer_auth(auth_token)
464 .header(reqwest::header::CONTENT_TYPE, content_type.into())
465 .send()
466 .await
467 .map_err::<BotXApiError<TError>, _>(|e| {
468 log::error!("{request_name} request error:[{e:#?}]");
469 e.into()
470 })?;
471
472 drop(context_read_lock);
473
474 raw_response
475 };
476
477 let status_code = raw_response.status();
478 let response_body = raw_response.text()
479 .await
480 .map_err::<BotXApiError<TError>, _>(|e| {
481 log::error!("{request_name} read response error:[{e:#?}]");
482 e.into()
483 })?;
484
485 if status_code == StatusCode::UNAUTHORIZED {
486 log::debug!("{request_name} request Unauthorized {response_body}");
487 return Err(BotXApiError::Unauthorized);
488 }
489
490 if status_code.is_success() {
491 let mut reader = csv::Reader::from_reader(response_body.as_bytes());
492
493 let mut rows = vec![];
494 for record in reader.deserialize() {
495 let record: Result::<TResponse, _> = record;
496 match record {
497 Ok(row) => rows.push(row),
498 Err(err) => log::error!("Invalid data format, skip row:[{:?}]", err),
499 }
500 }
501
502 return ExpressResult::<Vec::<TResponse>, TError>::Ok(rows).into();
503 }
504
505 let response = serde_json::from_str::<ExpressResult<Vec<TResponse>, TError>>(&*response_body)
506 .map_err(|e| {
507 log::error!("{request_name} response body deserialization error: [{response_body}]");
508 BotXApiError::SerdeError(e)
509 })?;
510
511 if !response.is_ok() {
512 log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
513 } else {
514 log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
515 }
516
517 response.into()
518 }
519
520 pub async fn delete<TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
521 where
522 for<'a> TResponse: Deserialize<'a> + Debug,
523 for<'a> TError: Deserialize<'a> + Debug,
524 {
525 log::info!("{request_name} request url [{url:?}]");
526
527 let context_read_lock = context.read().await;
528
529 let raw_response = if context_read_lock.auth_token.is_some() {
530 let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
531
532 let raw_response = context_read_lock.client.delete(url)
533 .bearer_auth(auth_token)
534 .header(reqwest::header::CONTENT_TYPE, content_type.into())
535 .send()
536 .await
537 .map_err::<BotXApiError<TError>, _>(|e| {
538 log::error!("{request_name} request error:[{e:#?}]");
539 e.into()
540 })?;
541
542 drop(context_read_lock);
543
544 raw_response
545 } else {
546 info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
547
548 drop(context_read_lock);
549
550 let mut context_write_lock = context.write().await;
551
552 let token_response = token(&mut *context_write_lock).await;
553
554 let Ok(token_result) = token_response else {
555 error!("Не удалось повторить запрос с пере авторизацией");
556 return Err(BotXApiError::Unauthorized);
557 };
558
559 context_write_lock.auth_token = Some(token_result.token.clone());
560
561 let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
562
563 let auth_token = token_result.token;
564
565 let raw_response = context_read_lock.client.delete(url)
566 .bearer_auth(auth_token)
567 .header(reqwest::header::CONTENT_TYPE, content_type.into())
568 .send()
569 .await
570 .map_err::<BotXApiError<TError>, _>(|e| {
571 log::error!("{request_name} request error:[{e:#?}]");
572 e.into()
573 })?;
574
575 drop(context_read_lock);
576
577 raw_response
578 };
579
580 let status_code = raw_response.status();
581 let response_body = raw_response.text()
582 .await
583 .map_err::<BotXApiError<TError>, _>(|e| {
584 log::error!("{request_name} read response error:[{e:#?}]");
585 e.into()
586 })?;
587
588 if status_code == StatusCode::UNAUTHORIZED {
589 log::debug!("{request_name} request Unauthorized {response_body}");
590 return Err(BotXApiError::Unauthorized);
591 }
592
593 let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
594 .map_err(|e| {
595 log::error!("{request_name} response body deserialization error: [{response_body}]");
596 BotXApiError::SerdeError(e)
597 })?;
598
599 if !response.is_ok() {
600 log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
601 } else {
602 log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
603 }
604
605 response.into()
606 }
607
608 pub async fn post_multipart<TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, data: Vec<MultipartPartData>, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
609 where
610 for<'a> TResponse: Deserialize<'a> + Debug,
611 for<'a> TError: Deserialize<'a> + Debug,
612 {
613 log::info!("{request_name} request url [{url:?}]");
614 log::debug!("{request_name} request data [{:#?}]", data);
615
616 let mut form = reqwest::multipart::Form::new();
617
618 for data in data.into_iter() {
619 let part = match data.content {
620 MultipartPartDataContent::Bytes(bytes) => reqwest::multipart::Part::bytes(bytes),
621 MultipartPartDataContent::Text(text) => reqwest::multipart::Part::text(text),
622 };
623
624 let part = if let Some(file_name) = data.file_name {
625 part.file_name(file_name)
626 } else {
627 part
628 };
629
630 let part = if let Some(content_type) = data.mime_type {
631 part.mime_str(&*content_type).unwrap()
632 } else {
633 part
634 };
635
636 form = form.part(data.name, part);
637 }
638
639 log::debug!("{:#?}", form);
640
641 let context_read_lock = context.read().await;
642
643 let raw_response = if context_read_lock.auth_token.is_some() {
644 let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
645
646 let raw_response = context_read_lock.client.post(url)
647 .bearer_auth(auth_token)
648 .multipart(form)
649 .send()
650 .await
651 .map_err::<BotXApiError<TError>, _>(|e| {
652 log::error!("{request_name} request error:[{e:#?}]");
653 e.into()
654 })?;
655
656 drop(context_read_lock);
657
658 raw_response
659 } else {
660 info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
661
662 drop(context_read_lock);
663
664 let mut context_write_lock = context.write().await;
665
666 let token_response = token(&mut *context_write_lock).await;
667
668 let Ok(token_result) = token_response else {
669 error!("Не удалось повторить запрос с пере авторизацией");
670 return Err(BotXApiError::Unauthorized);
671 };
672
673 context_write_lock.auth_token = Some(token_result.token.clone());
674
675 let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
676
677 let auth_token = token_result.token;
678
679 let raw_response = context_read_lock.client.post(url)
680 .bearer_auth(auth_token)
681 .multipart(form)
682 .send()
683 .await
684 .map_err::<BotXApiError<TError>, _>(|e| {
685 log::error!("{request_name} request error:[{e:#?}]");
686 e.into()
687 })?;
688
689 drop(context_read_lock);
690
691 raw_response
692 };
693
694 let status_code = raw_response.status();
695 let response_body = raw_response.text()
696 .await
697 .map_err::<BotXApiError<TError>, _>(|e| {
698 log::error!("{request_name} read response error:[{e:#?}]");
699 e.into()
700 })?;
701
702 if status_code == StatusCode::UNAUTHORIZED {
703 log::debug!("{request_name} request Unauthorized {response_body}");
704 return Err(BotXApiError::Unauthorized);
705 }
706
707 let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
708 .map_err(|e| {
709 log::error!("{request_name} response body deserialization error: [{response_body}]");
710 BotXApiError::SerdeError(e)
711 })?;
712
713 if !response.is_ok() {
714 log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
715 } else {
716 log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
717 }
718
719 response.into()
720 }
721}