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, p.current))
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((r.items, r.pagination.pages, r.pagination.current))
271 })
272 .await
273 }
274
275 pub async fn list_page_raw(
282 &self,
283 page: i32,
284 per_page: Option<i32>,
285 filter: &CallReportFilter,
286 ) -> Result<Page<serde_json::Value>, ManagerError> {
287 let cfg = self.cfg.get().await?;
288 let cfg = cfg.as_ref();
289 let (r#type, to_number, agent_id, state, finish_reason) = filter.to_params()?;
292 use crate::gen::manager::apis::urlencode as enc;
293 let mut q = vec![format!("page={page}")];
294 if let Some(max) = per_page {
295 q.push(format!("max={max}"));
296 }
297 if let Some(v) = &filter.from_number {
298 q.push(format!("fromNumber={}", enc(v)));
299 }
300 if let Some(v) = filter.time_start {
301 q.push(format!("time.start={v}"));
302 }
303 if let Some(v) = filter.time_end {
304 q.push(format!("time.end={v}"));
305 }
306 if let Some(v) = &filter.q {
307 q.push(format!("q={}", enc(v)));
308 }
309 if let Some(v) = &to_number {
310 let s = serde_json::to_string(v).unwrap_or_default();
311 q.push(format!("toNumber={}", enc(&s)));
312 }
313 if let Some(v) = &agent_id {
314 let s = serde_json::to_string(v).unwrap_or_default();
315 q.push(format!("agentId={}", enc(&s)));
316 }
317 if let Some(v) = &state {
318 let s = serde_json::to_string(v).unwrap_or_default();
319 q.push(format!("state={}", enc(&s)));
320 }
321 if let Some(v) = &r#type {
322 let s = serde_json::to_string(v).unwrap_or_default();
323 q.push(format!("type={}", enc(&s)));
324 }
325 if let Some(v) = &finish_reason {
326 let s = serde_json::to_string(v).unwrap_or_default();
327 q.push(format!("finishReason={}", enc(&s)));
328 }
329 let path = format!("/api/v2/calls/reporting?{}", q.join("&"));
330 fetch_page(
331 &self.retry,
332 |e| e,
333 || async {
334 let v = get_json(cfg, &path).await?;
335 Ok(page_parts(v, page))
336 },
337 )
338 .await
339 }
340
341 pub async fn simple_page_raw(
344 &self,
345 page: i32,
346 per_page: Option<i32>,
347 ) -> Result<Page<serde_json::Value>, ManagerError> {
348 let cfg = self.cfg.get().await?;
349 let cfg = cfg.as_ref();
350 let mut q = vec![format!("page={page}")];
351 if let Some(max) = per_page {
352 q.push(format!("max={max}"));
353 }
354 let path = format!("/api/v2/calls/reporting/simple?{}", q.join("&"));
355 fetch_page(
356 &self.retry,
357 |e| e,
358 || async {
359 let v = get_json(cfg, &path).await?;
360 Ok(page_parts(v, page))
361 },
362 )
363 .await
364 }
365
366 pub async fn list_page(
368 &self,
369 page: i32,
370 per_page: Option<i32>,
371 filter: &CallReportFilter,
372 ) -> Result<Page<models::Call>, ManagerError> {
373 let cfg = self.cfg.get().await?;
374 let cfg = cfg.as_ref();
375 let (r#type, to_number, agent_id, state, finish_reason) = filter.to_params()?;
376 fetch_page(&self.retry, map_manager_err, || {
377 let (r#type, to_number, agent_id, state, finish_reason) = (
378 r#type.clone(),
379 to_number.clone(),
380 agent_id.clone(),
381 state.clone(),
382 finish_reason.clone(),
383 );
384 async move {
385 let r = call_api::list_reporting_calls(
386 cfg,
387 Some(page),
388 per_page,
389 None,
390 None,
391 None,
392 None,
393 r#type,
394 None,
395 filter.from_number.as_deref(),
396 None,
397 to_number,
398 filter.time_start,
399 filter.time_end,
400 agent_id,
401 filter.q.as_deref(),
402 state,
403 None,
404 None,
405 finish_reason,
406 None,
407 None,
408 None,
409 None,
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 )
426 .await?;
427 Ok((
428 r.items,
429 r.pagination.pages,
430 r.pagination.current,
431 Some(r.pagination.total),
432 ))
433 }
434 })
435 .await
436 }
437
438 pub async fn simple_page(
440 &self,
441 page: i32,
442 per_page: Option<i32>,
443 ) -> Result<Page<models::ReportingCall>, ManagerError> {
444 let cfg = self.cfg.get().await?;
445 let cfg = cfg.as_ref();
446 fetch_page(&self.retry, map_manager_err, || async move {
447 let r = reporting_call_api::list_all_simple_reporting_calls(
448 cfg,
449 Some(page),
450 per_page,
451 None,
452 None,
453 None,
454 None,
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 )
483 .await?;
484 Ok((
485 r.items,
486 r.pagination.pages,
487 r.pagination.current,
488 Some(r.pagination.total),
489 ))
490 })
491 .await
492 }
493
494 pub async fn simple_all(&self) -> Result<Vec<models::ReportingCall>, ManagerError> {
496 let cfg = self.cfg.get().await?;
497 let cfg = cfg.as_ref();
498 collect_all(&self.retry, map_manager_err, |page| async move {
499 let r = reporting_call_api::list_all_simple_reporting_calls(
500 cfg,
501 Some(page),
502 None,
503 None,
504 None,
505 None,
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 )
535 .await?;
536 Ok((r.items, r.pagination.pages, r.pagination.current))
537 })
538 .await
539 }
540
541 pub async fn inbound_simple_all(&self) -> Result<Vec<models::ReportingCall>, ManagerError> {
543 let cfg = self.cfg.get().await?;
544 let cfg = cfg.as_ref();
545 collect_all(&self.retry, map_manager_err, |page| async move {
546 let r = reporting_call_api::list_inbound_simple_reporting_calls(cfg, Some(page), None)
547 .await?;
548 Ok((r.items, r.pagination.pages, r.pagination.current))
549 })
550 .await
551 }
552}