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