1use std::sync::Arc;
2
3use crate::error::{map_manager_err, ManagerError};
4use crate::gen::manager::apis::configuration::Configuration;
5use crate::gen::manager::apis::{call_api, manager_api, queue_api, reporting_call_api};
6use crate::gen::manager::models;
7use crate::http::{collect_all, fetch_page, Page};
8use crate::resources::raw::{get_json, page_parts, post_json};
9use crate::retry::{with_retry, RetryPolicy};
10
11#[derive(Debug, Clone, Default)]
15pub struct CallReportFilter {
16 pub from_number: Option<String>,
18 pub to_number: Option<String>,
20 pub time_start: Option<i32>,
22 pub time_end: Option<i32>,
24 pub agent_id: Option<String>,
26 pub state: Option<String>,
28 pub r#type: Option<String>,
30 pub finish_reason: Option<String>,
32 pub q: Option<String>,
34}
35
36fn parse_enum<T: serde::de::DeserializeOwned>(field: &str, value: &str) -> Result<T, ManagerError> {
39 serde_json::from_value(serde_json::Value::String(value.to_string()))
40 .map_err(|_| ManagerError::InvalidArgument(format!("{field}: unknown value '{value}'")))
41}
42
43impl CallReportFilter {
44 #[allow(clippy::type_complexity)]
45 fn to_params(
46 &self,
47 ) -> Result<
48 (
49 Option<models::ListReportingCallsTypeParameter>,
50 Option<models::ListReportingCallsToParameter>,
51 Option<models::ListReportingCallsIdParameter>,
52 Option<models::ListReportingCallsStateParameter>,
53 Option<models::ListReportingCallsFinishReasonParameter>,
54 ),
55 ManagerError,
56 > {
57 let r#type = self
58 .r#type
59 .as_deref()
60 .map(|v| parse_enum::<models::CallType>("type", v))
61 .transpose()?
62 .map(models::ListReportingCallsTypeParameter::CallType);
63 let to_number = self
64 .to_number
65 .clone()
66 .map(models::ListReportingCallsToParameter::ReportingNumberFilter);
67 let agent_id = self
68 .agent_id
69 .as_deref()
70 .map(|v| {
71 uuid::Uuid::parse_str(v)
72 .map_err(|e| ManagerError::InvalidArgument(format!("agent_id: {e}")))
73 })
74 .transpose()?
75 .map(models::ListReportingCallsIdParameter::ObjectUuid);
76 let state = self
77 .state
78 .as_deref()
79 .map(|v| parse_enum::<models::CallState>("state", v))
80 .transpose()?
81 .map(models::ListReportingCallsStateParameter::CallState);
82 let finish_reason = self
83 .finish_reason
84 .as_deref()
85 .map(|v| parse_enum::<models::CallFinishReason>("finish_reason", v))
86 .transpose()?
87 .map(models::ListReportingCallsFinishReasonParameter::CallFinishReason);
88 Ok((r#type, to_number, agent_id, state, finish_reason))
89 }
90}
91
92pub struct CallsResource {
94 pub(crate) cfg: Arc<Configuration>,
95 pub(crate) retry: RetryPolicy,
96 pub reporting: ReportingResource,
98}
99
100impl CallsResource {
101 pub async fn get_raw(&self, id: &str) -> Result<serde_json::Value, ManagerError> {
105 let path = format!("/api/v2/calls/{}", crate::gen::manager::apis::urlencode(id));
106 with_retry(&self.retry, true, || get_json(self.cfg.as_ref(), &path)).await
107 }
108
109 pub async fn get(&self, id: &str) -> Result<models::CallItemResponse, ManagerError> {
111 with_retry(&self.retry, true, || {
112 call_api::get_call(self.cfg.as_ref(), id)
113 })
114 .await
115 .map_err(map_manager_err)
116 }
117
118 pub async fn hangup(&self, id: &str) -> Result<models::CallItemResponse, ManagerError> {
120 with_retry(&self.retry, false, || {
121 manager_api::hangup_call(self.cfg.as_ref(), id)
122 })
123 .await
124 .map_err(map_manager_err)
125 }
126
127 pub async fn hangup_raw(&self, id: &str) -> Result<serde_json::Value, ManagerError> {
132 let path = format!(
133 "/api/v2/calls/{}/hangup",
134 crate::gen::manager::apis::urlencode(id)
135 );
136 with_retry(&self.retry, false, || post_json(self.cfg.as_ref(), &path)).await
138 }
139
140 pub async fn create_test_call(
142 &self,
143 body: models::CreateTestCallRequest,
144 ) -> Result<models::CallItemResponse, ManagerError> {
145 with_retry(&self.retry, false, || {
146 call_api::create_inbound_test_call(self.cfg.as_ref(), body.clone())
147 })
148 .await
149 .map_err(map_manager_err)
150 }
151
152 pub async fn set_session_variables(
154 &self,
155 id: &str,
156 variables: models::SetCallSessionVariablesRequest,
157 ) -> Result<models::SetCallSessionVariablesResponse, ManagerError> {
158 with_retry(&self.retry, false, || {
159 manager_api::set_call_session_variables(self.cfg.as_ref(), id, Some(variables.clone()))
160 })
161 .await
162 .map_err(map_manager_err)
163 }
164
165 pub async fn cancel(&self, id: &str) -> Result<models::CallItemResponse, ManagerError> {
167 with_retry(&self.retry, false, || {
168 manager_api::cancel_call(self.cfg.as_ref(), id)
169 })
170 .await
171 .map_err(map_manager_err)
172 }
173
174 pub async fn list_queued(
176 &self,
177 queue_id: &str,
178 ) -> Result<Vec<models::QueuedCall>, ManagerError> {
179 collect_all(&self.retry, map_manager_err, |page| async move {
180 let r =
181 queue_api::list_queued_calls(self.cfg.as_ref(), queue_id, Some(page), None).await?;
182 let (pages, current) = r
183 .pagination
184 .as_ref()
185 .map(|p| (p.pages, p.current))
186 .unwrap_or((1, 1));
187 Ok((r.items, pages, current))
188 })
189 .await
190 }
191
192 pub async fn queue_callback(
194 &self,
195 queue_id: &str,
196 body: models::QueueCallbackRequest,
197 ) -> Result<models::QueueCallbackResponse, ManagerError> {
198 with_retry(&self.retry, false, || {
199 queue_api::queue_callback(self.cfg.as_ref(), queue_id, body.clone())
200 })
201 .await
202 .map_err(map_manager_err)
203 }
204}
205
206pub struct ReportingResource {
208 pub(crate) cfg: Arc<Configuration>,
209 pub(crate) retry: RetryPolicy,
210}
211
212impl ReportingResource {
213 pub async fn list_all(&self) -> Result<Vec<models::Call>, ManagerError> {
215 collect_all(&self.retry, map_manager_err, |page| async move {
216 let r = call_api::list_reporting_calls(
217 self.cfg.as_ref(),
218 Some(page),
219 None,
220 None,
221 None,
222 None,
223 None,
224 None,
225 None,
226 None,
227 None,
228 None,
229 None,
230 None,
231 None,
232 None,
233 None,
234 None,
235 None,
236 None,
237 None,
238 None,
239 None,
240 None,
241 None,
242 None,
243 None,
244 None,
245 None,
246 None,
247 None,
248 None,
249 None,
250 None,
251 None,
252 None,
253 None,
254 None,
255 None,
256 )
257 .await?;
258 Ok((r.items, r.pagination.pages, r.pagination.current))
259 })
260 .await
261 }
262
263 pub async fn list_page_raw(
270 &self,
271 page: i32,
272 per_page: Option<i32>,
273 filter: &CallReportFilter,
274 ) -> Result<Page<serde_json::Value>, ManagerError> {
275 let (r#type, to_number, agent_id, state, finish_reason) = filter.to_params()?;
278 use crate::gen::manager::apis::urlencode as enc;
279 let mut q = vec![format!("page={page}")];
280 if let Some(max) = per_page {
281 q.push(format!("max={max}"));
282 }
283 if let Some(v) = &filter.from_number {
284 q.push(format!("fromNumber={}", enc(v)));
285 }
286 if let Some(v) = filter.time_start {
287 q.push(format!("time.start={v}"));
288 }
289 if let Some(v) = filter.time_end {
290 q.push(format!("time.end={v}"));
291 }
292 if let Some(v) = &filter.q {
293 q.push(format!("q={}", enc(v)));
294 }
295 if let Some(v) = &to_number {
296 let s = serde_json::to_string(v).unwrap_or_default();
297 q.push(format!("toNumber={}", enc(&s)));
298 }
299 if let Some(v) = &agent_id {
300 let s = serde_json::to_string(v).unwrap_or_default();
301 q.push(format!("agentId={}", enc(&s)));
302 }
303 if let Some(v) = &state {
304 let s = serde_json::to_string(v).unwrap_or_default();
305 q.push(format!("state={}", enc(&s)));
306 }
307 if let Some(v) = &r#type {
308 let s = serde_json::to_string(v).unwrap_or_default();
309 q.push(format!("type={}", enc(&s)));
310 }
311 if let Some(v) = &finish_reason {
312 let s = serde_json::to_string(v).unwrap_or_default();
313 q.push(format!("finishReason={}", enc(&s)));
314 }
315 let path = format!("/api/v2/calls/reporting?{}", q.join("&"));
316 fetch_page(
317 &self.retry,
318 |e| e,
319 || async {
320 let v = get_json(self.cfg.as_ref(), &path).await?;
321 Ok(page_parts(v, page))
322 },
323 )
324 .await
325 }
326
327 pub async fn simple_page_raw(
330 &self,
331 page: i32,
332 per_page: Option<i32>,
333 ) -> Result<Page<serde_json::Value>, ManagerError> {
334 let mut q = vec![format!("page={page}")];
335 if let Some(max) = per_page {
336 q.push(format!("max={max}"));
337 }
338 let path = format!("/api/v2/calls/reporting/simple?{}", q.join("&"));
339 fetch_page(
340 &self.retry,
341 |e| e,
342 || async {
343 let v = get_json(self.cfg.as_ref(), &path).await?;
344 Ok(page_parts(v, page))
345 },
346 )
347 .await
348 }
349
350 pub async fn list_page(
352 &self,
353 page: i32,
354 per_page: Option<i32>,
355 filter: &CallReportFilter,
356 ) -> Result<Page<models::Call>, ManagerError> {
357 let (r#type, to_number, agent_id, state, finish_reason) = filter.to_params()?;
358 fetch_page(&self.retry, map_manager_err, || {
359 let (r#type, to_number, agent_id, state, finish_reason) = (
360 r#type.clone(),
361 to_number.clone(),
362 agent_id.clone(),
363 state.clone(),
364 finish_reason.clone(),
365 );
366 async move {
367 let r = call_api::list_reporting_calls(
368 self.cfg.as_ref(),
369 Some(page),
370 per_page,
371 None,
372 None,
373 None,
374 None,
375 r#type,
376 None,
377 filter.from_number.as_deref(),
378 None,
379 to_number,
380 filter.time_start,
381 filter.time_end,
382 agent_id,
383 filter.q.as_deref(),
384 state,
385 None,
386 None,
387 finish_reason,
388 None,
389 None,
390 None,
391 None,
392 None,
393 None,
394 None,
395 None,
396 None,
397 None,
398 None,
399 None,
400 None,
401 None,
402 None,
403 None,
404 None,
405 None,
406 None,
407 )
408 .await?;
409 Ok((
410 r.items,
411 r.pagination.pages,
412 r.pagination.current,
413 Some(r.pagination.total),
414 ))
415 }
416 })
417 .await
418 }
419
420 pub async fn simple_page(
422 &self,
423 page: i32,
424 per_page: Option<i32>,
425 ) -> Result<Page<models::ReportingCall>, ManagerError> {
426 fetch_page(&self.retry, map_manager_err, || async move {
427 let r = reporting_call_api::list_all_simple_reporting_calls(
428 self.cfg.as_ref(),
429 Some(page),
430 per_page,
431 None,
432 None,
433 None,
434 None,
435 None,
436 None,
437 None,
438 None,
439 None,
440 None,
441 None,
442 None,
443 None,
444 None,
445 None,
446 None,
447 None,
448 None,
449 None,
450 None,
451 None,
452 None,
453 None,
454 None,
455 None,
456 None,
457 None,
458 None,
459 None,
460 None,
461 None,
462 )
463 .await?;
464 Ok((
465 r.items,
466 r.pagination.pages,
467 r.pagination.current,
468 Some(r.pagination.total),
469 ))
470 })
471 .await
472 }
473
474 pub async fn simple_all(&self) -> Result<Vec<models::ReportingCall>, ManagerError> {
476 collect_all(&self.retry, map_manager_err, |page| async move {
477 let r = reporting_call_api::list_all_simple_reporting_calls(
478 self.cfg.as_ref(),
479 Some(page),
480 None,
481 None,
482 None,
483 None,
484 None,
485 None,
486 None,
487 None,
488 None,
489 None,
490 None,
491 None,
492 None,
493 None,
494 None,
495 None,
496 None,
497 None,
498 None,
499 None,
500 None,
501 None,
502 None,
503 None,
504 None,
505 None,
506 None,
507 None,
508 None,
509 None,
510 None,
511 None,
512 )
513 .await?;
514 Ok((r.items, r.pagination.pages, r.pagination.current))
515 })
516 .await
517 }
518
519 pub async fn inbound_simple_all(&self) -> Result<Vec<models::ReportingCall>, ManagerError> {
521 collect_all(&self.retry, map_manager_err, |page| async move {
522 let r = reporting_call_api::list_inbound_simple_reporting_calls(
523 self.cfg.as_ref(),
524 Some(page),
525 None,
526 )
527 .await?;
528 Ok((r.items, r.pagination.pages, r.pagination.current))
529 })
530 .await
531 }
532}