1use crate::error::{map_manager_err, ManagerError};
2use crate::gen::manager::apis::configuration::Configuration;
3use crate::gen::manager::apis::{agent_api, agent_group_api, manager_api};
4use crate::gen::manager::models;
5use crate::http::{collect_all, fetch_page, Page};
6use crate::resources::raw::get_json;
7use crate::retry::{with_retry, RetryPolicy};
8use crate::token::SharedCfg;
9
10#[derive(Debug, Clone, Default)]
13pub struct ListAgentsQuery {
14 pub q: Option<String>,
16 pub enabled: Option<bool>,
18 pub name: Option<String>,
20 pub number: Option<String>,
22 pub source_id: Option<String>,
24 pub state: Option<models::AgentLineStatus>,
26 pub source: Option<String>,
28 pub group_ids: Vec<String>,
31 pub groups: Vec<String>,
33 pub tags: Vec<String>,
35}
36
37impl ListAgentsQuery {
38 fn to_path(&self, page: i32, max: Option<i32>) -> String {
41 let mut ser = url::form_urlencoded::Serializer::new(String::new());
42 ser.append_pair("page", &page.to_string());
43 if let Some(max) = max {
44 ser.append_pair("max", &max.to_string());
45 }
46 if let Some(v) = &self.q {
47 ser.append_pair("q", v);
48 }
49 if let Some(v) = self.enabled {
50 ser.append_pair("enabled", if v { "true" } else { "false" });
51 }
52 if let Some(v) = &self.name {
53 ser.append_pair("name", v);
54 }
55 if let Some(v) = &self.number {
56 ser.append_pair("number", v);
57 }
58 if let Some(v) = &self.source_id {
59 ser.append_pair("sourceId", v);
60 }
61 if let Some(v) = &self.state {
62 ser.append_pair("state", &v.to_string());
63 }
64 if let Some(v) = &self.source {
65 ser.append_pair("source", v);
66 }
67 for id in &self.group_ids {
68 ser.append_pair("groupIds", &normalize_entity_id(id));
69 }
70 for g in &self.groups {
71 ser.append_pair("groups", g);
72 }
73 for t in &self.tags {
74 ser.append_pair("tags", t);
75 }
76 format!("/api/v2/agents?{}", ser.finish())
77 }
78}
79
80fn normalize_entity_id(v: &str) -> String {
83 match uuid::Uuid::parse_str(v) {
84 Ok(u) => u.simple().to_string(),
85 Err(_) => v.to_string(),
86 }
87}
88
89pub struct AgentsResource {
91 pub(crate) cfg: SharedCfg<Configuration>,
92 pub(crate) retry: RetryPolicy,
93 pub groups: AgentGroupsResource,
95}
96
97impl AgentsResource {
98 pub async fn list(&self, query: ListAgentsQuery) -> Result<Vec<models::Agent>, ManagerError> {
105 let cfg = self.cfg.get().await?;
106 let cfg = cfg.as_ref();
107 let query = &query;
108 collect_all(
109 &self.retry,
110 |e| e,
111 |page| async move {
112 let v = get_json(cfg, &query.to_path(page, None)).await?;
113 let r: models::PaginatedAgentResponse =
114 serde_json::from_value(v).map_err(|e| ManagerError::Decode(e.to_string()))?;
115 Ok((
116 r.items,
117 r.pagination.pages.unwrap_or(1),
118 r.pagination.current.unwrap_or(1),
119 ))
120 },
121 )
122 .await
123 }
124
125 pub async fn list_all(&self) -> Result<Vec<models::Agent>, ManagerError> {
127 self.list(ListAgentsQuery::default()).await
128 }
129
130 pub async fn list_page(
132 &self,
133 page: i32,
134 per_page: Option<i32>,
135 query: ListAgentsQuery,
136 ) -> Result<Page<models::Agent>, ManagerError> {
137 let cfg = self.cfg.get().await?;
138 let cfg = cfg.as_ref();
139 let query = &query;
140 fetch_page(
141 &self.retry,
142 |e| e,
143 || async move {
144 let v = get_json(cfg, &query.to_path(page, per_page)).await?;
145 let r: models::PaginatedAgentResponse =
146 serde_json::from_value(v).map_err(|e| ManagerError::Decode(e.to_string()))?;
147 Ok((
148 r.items,
149 r.pagination.pages.unwrap_or(1),
150 r.pagination.current.unwrap_or(1),
151 r.pagination.total,
152 ))
153 },
154 )
155 .await
156 }
157
158 pub async fn create(
160 &self,
161 body: models::RestCreateAgent,
162 ) -> Result<models::AgentItemResponse, ManagerError> {
163 let cfg = self.cfg.get().await?;
164 let cfg = cfg.as_ref();
165 with_retry(&self.retry, false, || {
166 agent_api::create_agent(cfg, body.clone())
167 })
168 .await
169 .map_err(map_manager_err)
170 }
171
172 pub async fn get(&self, id: &str) -> Result<models::AgentItemResponse, ManagerError> {
174 let cfg = self.cfg.get().await?;
175 let cfg = cfg.as_ref();
176 with_retry(&self.retry, true, || agent_api::get_agent(cfg, id))
177 .await
178 .map_err(map_manager_err)
179 }
180
181 pub async fn update(
183 &self,
184 id: &str,
185 body: models::RestUpdateAgent,
186 ) -> Result<models::AgentItemResponse, ManagerError> {
187 let cfg = self.cfg.get().await?;
188 let cfg = cfg.as_ref();
189 with_retry(&self.retry, false, || {
190 agent_api::update_agent(cfg, id, body.clone())
191 })
192 .await
193 .map_err(map_manager_err)
194 }
195
196 pub async fn delete(&self, id: &str) -> Result<(), ManagerError> {
198 let cfg = self.cfg.get().await?;
199 let cfg = cfg.as_ref();
200 with_retry(&self.retry, false, || agent_api::delete_agent(cfg, id))
201 .await
202 .map_err(map_manager_err)?;
203 Ok(())
204 }
205
206 pub async fn update_status(
208 &self,
209 id: &str,
210 status: models::UpdateAgentStatusRequest,
211 ) -> Result<models::AgentStatus, ManagerError> {
212 let cfg = self.cfg.get().await?;
213 let cfg = cfg.as_ref();
214 with_retry(&self.retry, false, || {
215 manager_api::update_agent_status(cfg, id, Some(status.clone()))
216 })
217 .await
218 .map_err(map_manager_err)
219 }
220
221 pub async fn presences(&self) -> Result<models::AgentPresenceListResponse, ManagerError> {
223 let cfg = self.cfg.get().await?;
224 let cfg = cfg.as_ref();
225 with_retry(&self.retry, true, || agent_api::list_agent_presences(cfg))
226 .await
227 .map_err(map_manager_err)
228 }
229
230 pub async fn get_presence(
232 &self,
233 name: &str,
234 ) -> Result<models::AgentPresenceItemResponse, ManagerError> {
235 let cfg = self.cfg.get().await?;
236 let cfg = cfg.as_ref();
237 with_retry(&self.retry, true, || {
238 agent_api::get_agent_presence(cfg, name)
239 })
240 .await
241 .map_err(map_manager_err)
242 }
243
244 pub async fn create_presence(
246 &self,
247 body: models::AgentPresenceWriteBody,
248 ) -> Result<models::AgentPresenceItemResponse, ManagerError> {
249 let cfg = self.cfg.get().await?;
250 let cfg = cfg.as_ref();
251 with_retry(&self.retry, false, || {
252 agent_api::create_agent_presence(cfg, body.clone())
253 })
254 .await
255 .map_err(map_manager_err)
256 }
257
258 pub async fn update_presence(
260 &self,
261 name: &str,
262 body: models::AgentPresenceWriteBody,
263 ) -> Result<models::AgentPresenceItemResponse, ManagerError> {
264 let cfg = self.cfg.get().await?;
265 let cfg = cfg.as_ref();
266 with_retry(&self.retry, false, || {
267 agent_api::update_agent_presence(cfg, name, body.clone())
268 })
269 .await
270 .map_err(map_manager_err)
271 }
272
273 pub async fn delete_presence(
275 &self,
276 name: &str,
277 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
278 let cfg = self.cfg.get().await?;
279 let cfg = cfg.as_ref();
280 with_retry(&self.retry, false, || {
281 agent_api::delete_agent_presence(cfg, name)
282 })
283 .await
284 .map_err(map_manager_err)
285 }
286
287 pub async fn get_status(
289 &self,
290 id: &str,
291 ) -> Result<models::AgentTotalStatusResponse, ManagerError> {
292 let cfg = self.cfg.get().await?;
293 let cfg = cfg.as_ref();
294 with_retry(&self.retry, true, || agent_api::get_agent_status(cfg, id))
295 .await
296 .map_err(map_manager_err)
297 }
298
299 pub async fn available_statuses(
301 &self,
302 ) -> Result<models::AgentAvailabilityListResponse, ManagerError> {
303 let cfg = self.cfg.get().await?;
304 let cfg = cfg.as_ref();
305 with_retry(&self.retry, true, || {
306 agent_api::list_available_agent_statuses(cfg)
307 })
308 .await
309 .map_err(map_manager_err)
310 }
311
312 pub async fn enable(&self, id: &str) -> Result<models::DefaultV2MessageResponse, ManagerError> {
314 let cfg = self.cfg.get().await?;
315 let cfg = cfg.as_ref();
316 with_retry(&self.retry, false, || agent_api::enable_agent(cfg, id))
317 .await
318 .map_err(map_manager_err)
319 }
320
321 pub async fn disable(
323 &self,
324 id: &str,
325 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
326 let cfg = self.cfg.get().await?;
327 let cfg = cfg.as_ref();
328 with_retry(&self.retry, false, || agent_api::disable_agent(cfg, id))
329 .await
330 .map_err(map_manager_err)
331 }
332
333 pub async fn hangup_call(
335 &self,
336 id: &str,
337 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
338 let cfg = self.cfg.get().await?;
339 let cfg = cfg.as_ref();
340 with_retry(&self.retry, false, || agent_api::hangup_agent_call(cfg, id))
341 .await
342 .map_err(map_manager_err)
343 }
344
345 pub async fn bulk_action(
347 &self,
348 action: &str,
349 body: models::AgentBulkRequest,
350 ) -> Result<models::AgentBulkResponse, ManagerError> {
351 let cfg = self.cfg.get().await?;
352 let cfg = cfg.as_ref();
353 with_retry(&self.retry, false, || {
354 agent_api::bulk_agent_action(cfg, action, body.clone())
355 })
356 .await
357 .map_err(map_manager_err)
358 }
359
360 pub async fn export(&self, format: &str) -> Result<String, ManagerError> {
362 let cfg = self.cfg.get().await?;
363 let cfg = cfg.as_ref();
364 with_retry(&self.retry, true, || agent_api::export_agents(cfg, format))
365 .await
366 .map_err(map_manager_err)
367 }
368
369 #[allow(clippy::too_many_arguments)]
371 pub async fn import_agents(
372 &self,
373 format: &str,
374 file: std::path::PathBuf,
375 r#async: Option<bool>,
376 create_only: Option<bool>,
377 update_only: Option<bool>,
378 delete_unlisted: Option<bool>,
379 ) -> Result<models::AgentImportValidationResults, ManagerError> {
380 let cfg = self.cfg.get().await?;
381 let cfg = cfg.as_ref();
382 with_retry(&self.retry, false, || {
383 agent_api::import_agents(
384 cfg,
385 format,
386 file.clone(),
387 r#async,
388 create_only,
389 update_only,
390 delete_unlisted,
391 )
392 })
393 .await
394 .map_err(map_manager_err)
395 }
396
397 pub async fn validate_import(
399 &self,
400 file: std::path::PathBuf,
401 ) -> Result<models::AgentImportValidationResults, ManagerError> {
402 let cfg = self.cfg.get().await?;
403 let cfg = cfg.as_ref();
404 with_retry(&self.retry, false, || {
405 agent_api::validate_agent_import(cfg, file.clone())
406 })
407 .await
408 .map_err(map_manager_err)
409 }
410
411 pub async fn get_import_job(
413 &self,
414 id: &str,
415 ) -> Result<models::AgentImportJobItemResponse, ManagerError> {
416 let cfg = self.cfg.get().await?;
417 let cfg = cfg.as_ref();
418 with_retry(&self.retry, true, || {
419 agent_api::get_agent_import_job(cfg, id)
420 })
421 .await
422 .map_err(map_manager_err)
423 }
424
425 pub async fn logs(
427 &self,
428 id: &str,
429 from: Option<i32>,
430 to: Option<i32>,
431 ) -> Result<Vec<models::AgentLogEntry>, ManagerError> {
432 let cfg = self.cfg.get().await?;
433 let cfg = cfg.as_ref();
434 collect_all(&self.retry, map_manager_err, |page| async move {
435 let r = agent_api::list_agent_logs(cfg, id, Some(page), None, from, to).await?;
436 let (pages, current) = r
437 .pagination
438 .as_ref()
439 .map(|p| (p.pages.unwrap_or(1), p.current.unwrap_or(1)))
440 .unwrap_or((1, 1));
441 Ok((r.items, pages, current))
442 })
443 .await
444 }
445
446 pub async fn all_logs(&self) -> Result<Vec<models::AgentLogEntry>, ManagerError> {
448 let cfg = self.cfg.get().await?;
449 let cfg = cfg.as_ref();
450 collect_all(&self.retry, map_manager_err, |page| async move {
451 let r = agent_api::list_all_agent_logs(cfg, Some(page), None).await?;
452 let (pages, current) = r
453 .pagination
454 .as_ref()
455 .map(|p| (p.pages.unwrap_or(1), p.current.unwrap_or(1)))
456 .unwrap_or((1, 1));
457 Ok((r.items, pages, current))
458 })
459 .await
460 }
461
462 pub async fn push(
464 &self,
465 body: models::AgentPushRequest,
466 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
467 let cfg = self.cfg.get().await?;
468 let cfg = cfg.as_ref();
469 with_retry(&self.retry, false, || {
470 agent_api::push_to_agent(cfg, body.clone())
471 })
472 .await
473 .map_err(map_manager_err)
474 }
475
476 pub async fn update_password(
478 &self,
479 id: &str,
480 body: models::AgentPasswordUpdateRequest,
481 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
482 let cfg = self.cfg.get().await?;
483 let cfg = cfg.as_ref();
484 with_retry(&self.retry, false, || {
485 agent_api::update_agent_password(cfg, id, body.clone())
486 })
487 .await
488 .map_err(map_manager_err)
489 }
490}
491
492pub struct AgentGroupsResource {
494 pub(crate) cfg: SharedCfg<Configuration>,
495 pub(crate) retry: RetryPolicy,
496}
497
498impl AgentGroupsResource {
499 pub async fn list_all(&self) -> Result<Vec<models::AgentGroup>, ManagerError> {
501 let cfg = self.cfg.get().await?;
502 let cfg = cfg.as_ref();
503 collect_all(&self.retry, map_manager_err, |page| async move {
504 let r = agent_group_api::list_agent_groups(cfg, Some(page), None).await?;
505 Ok((
506 r.items,
507 r.pagination.pages.unwrap_or(1),
508 r.pagination.current.unwrap_or(1),
509 ))
510 })
511 .await
512 }
513
514 pub async fn create(
516 &self,
517 body: models::RestCreateAgentGroup,
518 ) -> Result<models::AgentGroupItemResponse, ManagerError> {
519 let cfg = self.cfg.get().await?;
520 let cfg = cfg.as_ref();
521 with_retry(&self.retry, false, || {
522 agent_group_api::create_agent_group(cfg, body.clone())
523 })
524 .await
525 .map_err(map_manager_err)
526 }
527
528 pub async fn get(&self, id: &str) -> Result<models::AgentGroupItemResponse, ManagerError> {
530 let cfg = self.cfg.get().await?;
531 let cfg = cfg.as_ref();
532 with_retry(&self.retry, true, || {
533 agent_group_api::get_agent_group(cfg, id)
534 })
535 .await
536 .map_err(map_manager_err)
537 }
538
539 pub async fn update(
541 &self,
542 id: &str,
543 body: models::RestUpdateAgentGroup,
544 ) -> Result<models::AgentGroupItemResponse, ManagerError> {
545 let cfg = self.cfg.get().await?;
546 let cfg = cfg.as_ref();
547 with_retry(&self.retry, false, || {
548 agent_group_api::update_agent_group(cfg, id, body.clone())
549 })
550 .await
551 .map_err(map_manager_err)
552 }
553
554 pub async fn delete(&self, id: &str) -> Result<(), ManagerError> {
556 let cfg = self.cfg.get().await?;
557 let cfg = cfg.as_ref();
558 with_retry(&self.retry, false, || {
559 agent_group_api::delete_agent_group(cfg, id)
560 })
561 .await
562 .map_err(map_manager_err)?;
563 Ok(())
564 }
565
566 pub async fn add_agent(
568 &self,
569 group_id: &str,
570 agent_id: &str,
571 ) -> Result<models::AgentGroupAdditionResponse, ManagerError> {
572 let cfg = self.cfg.get().await?;
573 let cfg = cfg.as_ref();
574 let id = uuid::Uuid::parse_str(agent_id)
575 .map_err(|e| ManagerError::InvalidArgument(format!("agent_id: {e}")))?;
576 let body = models::AddAgentToGroupRequest { id };
577 with_retry(&self.retry, false, || {
578 manager_api::add_agent_to_group(cfg, group_id, Some(body.clone()))
579 })
580 .await
581 .map_err(map_manager_err)
582 }
583
584 pub async fn remove_agent(
586 &self,
587 group_id: &str,
588 agent_id: &str,
589 ) -> Result<models::AgentGroupItemResponse, ManagerError> {
590 let cfg = self.cfg.get().await?;
591 let cfg = cfg.as_ref();
592 with_retry(&self.retry, false, || {
593 agent_group_api::remove_agent_from_group(cfg, group_id, agent_id)
594 })
595 .await
596 .map_err(map_manager_err)
597 }
598
599 pub async fn list_agents(&self, group_id: &str) -> Result<Vec<models::Agent>, ManagerError> {
601 let cfg = self.cfg.get().await?;
602 let cfg = cfg.as_ref();
603 collect_all(&self.retry, map_manager_err, |page| async move {
604 let r = agent_group_api::list_agents_in_group(cfg, group_id, Some(page), None).await?;
605 Ok((
606 r.items,
607 r.pagination.pages.unwrap_or(1),
608 r.pagination.current.unwrap_or(1),
609 ))
610 })
611 .await
612 }
613
614 pub async fn bulk_delete(
616 &self,
617 ids: Vec<String>,
618 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
619 let cfg = self.cfg.get().await?;
620 let cfg = cfg.as_ref();
621 let ids = ids
622 .iter()
623 .map(|id| {
624 uuid::Uuid::parse_str(id)
625 .map_err(|e| ManagerError::InvalidArgument(format!("ids: {e}")))
626 })
627 .collect::<Result<Vec<_>, _>>()?;
628 let body = models::BulkIdsRequest { ids };
629 with_retry(&self.retry, false, || {
630 agent_group_api::bulk_delete_agent_groups(cfg, body.clone())
631 })
632 .await
633 .map_err(map_manager_err)
634 }
635}