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((r.items, r.pagination.pages, r.pagination.current))
116 },
117 )
118 .await
119 }
120
121 pub async fn list_all(&self) -> Result<Vec<models::Agent>, ManagerError> {
123 self.list(ListAgentsQuery::default()).await
124 }
125
126 pub async fn list_page(
128 &self,
129 page: i32,
130 per_page: Option<i32>,
131 query: ListAgentsQuery,
132 ) -> Result<Page<models::Agent>, ManagerError> {
133 let cfg = self.cfg.get().await?;
134 let cfg = cfg.as_ref();
135 let query = &query;
136 fetch_page(
137 &self.retry,
138 |e| e,
139 || async move {
140 let v = get_json(cfg, &query.to_path(page, per_page)).await?;
141 let r: models::PaginatedAgentResponse =
142 serde_json::from_value(v).map_err(|e| ManagerError::Decode(e.to_string()))?;
143 Ok((
144 r.items,
145 r.pagination.pages,
146 r.pagination.current,
147 Some(r.pagination.total),
148 ))
149 },
150 )
151 .await
152 }
153
154 pub async fn create(
156 &self,
157 body: models::RestCreateAgent,
158 ) -> Result<models::AgentItemResponse, ManagerError> {
159 let cfg = self.cfg.get().await?;
160 let cfg = cfg.as_ref();
161 with_retry(&self.retry, false, || {
162 agent_api::create_agent(cfg, body.clone())
163 })
164 .await
165 .map_err(map_manager_err)
166 }
167
168 pub async fn get(&self, id: &str) -> Result<models::AgentItemResponse, ManagerError> {
170 let cfg = self.cfg.get().await?;
171 let cfg = cfg.as_ref();
172 with_retry(&self.retry, true, || agent_api::get_agent(cfg, id))
173 .await
174 .map_err(map_manager_err)
175 }
176
177 pub async fn update(
179 &self,
180 id: &str,
181 body: models::RestUpdateAgent,
182 ) -> Result<models::AgentItemResponse, ManagerError> {
183 let cfg = self.cfg.get().await?;
184 let cfg = cfg.as_ref();
185 with_retry(&self.retry, false, || {
186 agent_api::update_agent(cfg, id, body.clone())
187 })
188 .await
189 .map_err(map_manager_err)
190 }
191
192 pub async fn delete(&self, id: &str) -> Result<(), ManagerError> {
194 let cfg = self.cfg.get().await?;
195 let cfg = cfg.as_ref();
196 with_retry(&self.retry, false, || agent_api::delete_agent(cfg, id))
197 .await
198 .map_err(map_manager_err)?;
199 Ok(())
200 }
201
202 pub async fn update_status(
204 &self,
205 id: &str,
206 status: models::UpdateAgentStatusRequest,
207 ) -> Result<models::AgentStatus, ManagerError> {
208 let cfg = self.cfg.get().await?;
209 let cfg = cfg.as_ref();
210 with_retry(&self.retry, false, || {
211 manager_api::update_agent_status(cfg, id, Some(status.clone()))
212 })
213 .await
214 .map_err(map_manager_err)
215 }
216
217 pub async fn presences(&self) -> Result<models::AgentPresenceListResponse, ManagerError> {
219 let cfg = self.cfg.get().await?;
220 let cfg = cfg.as_ref();
221 with_retry(&self.retry, true, || agent_api::list_agent_presences(cfg))
222 .await
223 .map_err(map_manager_err)
224 }
225
226 pub async fn get_presence(
228 &self,
229 name: &str,
230 ) -> Result<models::AgentPresenceItemResponse, ManagerError> {
231 let cfg = self.cfg.get().await?;
232 let cfg = cfg.as_ref();
233 with_retry(&self.retry, true, || {
234 agent_api::get_agent_presence(cfg, name)
235 })
236 .await
237 .map_err(map_manager_err)
238 }
239
240 pub async fn create_presence(
242 &self,
243 body: models::AgentPresenceWriteBody,
244 ) -> Result<models::AgentPresenceItemResponse, ManagerError> {
245 let cfg = self.cfg.get().await?;
246 let cfg = cfg.as_ref();
247 with_retry(&self.retry, false, || {
248 agent_api::create_agent_presence(cfg, body.clone())
249 })
250 .await
251 .map_err(map_manager_err)
252 }
253
254 pub async fn update_presence(
256 &self,
257 name: &str,
258 body: models::AgentPresenceWriteBody,
259 ) -> Result<models::AgentPresenceItemResponse, ManagerError> {
260 let cfg = self.cfg.get().await?;
261 let cfg = cfg.as_ref();
262 with_retry(&self.retry, false, || {
263 agent_api::update_agent_presence(cfg, name, body.clone())
264 })
265 .await
266 .map_err(map_manager_err)
267 }
268
269 pub async fn delete_presence(
271 &self,
272 name: &str,
273 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
274 let cfg = self.cfg.get().await?;
275 let cfg = cfg.as_ref();
276 with_retry(&self.retry, false, || {
277 agent_api::delete_agent_presence(cfg, name)
278 })
279 .await
280 .map_err(map_manager_err)
281 }
282
283 pub async fn get_status(
285 &self,
286 id: &str,
287 ) -> Result<models::AgentTotalStatusResponse, ManagerError> {
288 let cfg = self.cfg.get().await?;
289 let cfg = cfg.as_ref();
290 with_retry(&self.retry, true, || agent_api::get_agent_status(cfg, id))
291 .await
292 .map_err(map_manager_err)
293 }
294
295 pub async fn available_statuses(
297 &self,
298 ) -> Result<models::AgentAvailabilityListResponse, ManagerError> {
299 let cfg = self.cfg.get().await?;
300 let cfg = cfg.as_ref();
301 with_retry(&self.retry, true, || {
302 agent_api::list_available_agent_statuses(cfg)
303 })
304 .await
305 .map_err(map_manager_err)
306 }
307
308 pub async fn enable(&self, id: &str) -> Result<models::DefaultV2MessageResponse, ManagerError> {
310 let cfg = self.cfg.get().await?;
311 let cfg = cfg.as_ref();
312 with_retry(&self.retry, false, || agent_api::enable_agent(cfg, id))
313 .await
314 .map_err(map_manager_err)
315 }
316
317 pub async fn disable(
319 &self,
320 id: &str,
321 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
322 let cfg = self.cfg.get().await?;
323 let cfg = cfg.as_ref();
324 with_retry(&self.retry, false, || agent_api::disable_agent(cfg, id))
325 .await
326 .map_err(map_manager_err)
327 }
328
329 pub async fn hangup_call(
331 &self,
332 id: &str,
333 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
334 let cfg = self.cfg.get().await?;
335 let cfg = cfg.as_ref();
336 with_retry(&self.retry, false, || agent_api::hangup_agent_call(cfg, id))
337 .await
338 .map_err(map_manager_err)
339 }
340
341 pub async fn bulk_action(
343 &self,
344 action: &str,
345 body: models::AgentBulkRequest,
346 ) -> Result<models::AgentBulkResponse, ManagerError> {
347 let cfg = self.cfg.get().await?;
348 let cfg = cfg.as_ref();
349 with_retry(&self.retry, false, || {
350 agent_api::bulk_agent_action(cfg, action, body.clone())
351 })
352 .await
353 .map_err(map_manager_err)
354 }
355
356 pub async fn export(&self, format: &str) -> Result<String, ManagerError> {
358 let cfg = self.cfg.get().await?;
359 let cfg = cfg.as_ref();
360 with_retry(&self.retry, true, || agent_api::export_agents(cfg, format))
361 .await
362 .map_err(map_manager_err)
363 }
364
365 #[allow(clippy::too_many_arguments)]
367 pub async fn import_agents(
368 &self,
369 format: &str,
370 file: std::path::PathBuf,
371 r#async: Option<bool>,
372 create_only: Option<bool>,
373 update_only: Option<bool>,
374 delete_unlisted: Option<bool>,
375 ) -> Result<models::AgentImportValidationResults, ManagerError> {
376 let cfg = self.cfg.get().await?;
377 let cfg = cfg.as_ref();
378 with_retry(&self.retry, false, || {
379 agent_api::import_agents(
380 cfg,
381 format,
382 file.clone(),
383 r#async,
384 create_only,
385 update_only,
386 delete_unlisted,
387 )
388 })
389 .await
390 .map_err(map_manager_err)
391 }
392
393 pub async fn validate_import(
395 &self,
396 file: std::path::PathBuf,
397 ) -> Result<models::AgentImportValidationResults, ManagerError> {
398 let cfg = self.cfg.get().await?;
399 let cfg = cfg.as_ref();
400 with_retry(&self.retry, false, || {
401 agent_api::validate_agent_import(cfg, file.clone())
402 })
403 .await
404 .map_err(map_manager_err)
405 }
406
407 pub async fn get_import_job(
409 &self,
410 id: &str,
411 ) -> Result<models::AgentImportJobItemResponse, ManagerError> {
412 let cfg = self.cfg.get().await?;
413 let cfg = cfg.as_ref();
414 with_retry(&self.retry, true, || {
415 agent_api::get_agent_import_job(cfg, id)
416 })
417 .await
418 .map_err(map_manager_err)
419 }
420
421 pub async fn logs(
423 &self,
424 id: &str,
425 from: Option<i32>,
426 to: Option<i32>,
427 ) -> Result<Vec<models::AgentLogEntry>, ManagerError> {
428 let cfg = self.cfg.get().await?;
429 let cfg = cfg.as_ref();
430 collect_all(&self.retry, map_manager_err, |page| async move {
431 let r = agent_api::list_agent_logs(cfg, id, Some(page), None, from, to).await?;
432 let (pages, current) = r
433 .pagination
434 .as_ref()
435 .map(|p| (p.pages, p.current))
436 .unwrap_or((1, 1));
437 Ok((r.items, pages, current))
438 })
439 .await
440 }
441
442 pub async fn all_logs(&self) -> Result<Vec<models::AgentLogEntry>, ManagerError> {
444 let cfg = self.cfg.get().await?;
445 let cfg = cfg.as_ref();
446 collect_all(&self.retry, map_manager_err, |page| async move {
447 let r = agent_api::list_all_agent_logs(cfg, Some(page), None).await?;
448 let (pages, current) = r
449 .pagination
450 .as_ref()
451 .map(|p| (p.pages, p.current))
452 .unwrap_or((1, 1));
453 Ok((r.items, pages, current))
454 })
455 .await
456 }
457
458 pub async fn push(
460 &self,
461 body: models::AgentPushRequest,
462 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
463 let cfg = self.cfg.get().await?;
464 let cfg = cfg.as_ref();
465 with_retry(&self.retry, false, || {
466 agent_api::push_to_agent(cfg, body.clone())
467 })
468 .await
469 .map_err(map_manager_err)
470 }
471
472 pub async fn update_password(
474 &self,
475 id: &str,
476 body: models::AgentPasswordUpdateRequest,
477 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
478 let cfg = self.cfg.get().await?;
479 let cfg = cfg.as_ref();
480 with_retry(&self.retry, false, || {
481 agent_api::update_agent_password(cfg, id, body.clone())
482 })
483 .await
484 .map_err(map_manager_err)
485 }
486}
487
488pub struct AgentGroupsResource {
490 pub(crate) cfg: SharedCfg<Configuration>,
491 pub(crate) retry: RetryPolicy,
492}
493
494impl AgentGroupsResource {
495 pub async fn list_all(&self) -> Result<Vec<models::AgentGroup>, ManagerError> {
497 let cfg = self.cfg.get().await?;
498 let cfg = cfg.as_ref();
499 collect_all(&self.retry, map_manager_err, |page| async move {
500 let r = agent_group_api::list_agent_groups(cfg, Some(page), None).await?;
501 Ok((r.items, r.pagination.pages, r.pagination.current))
502 })
503 .await
504 }
505
506 pub async fn create(
508 &self,
509 body: models::RestCreateAgentGroup,
510 ) -> Result<models::AgentGroupItemResponse, ManagerError> {
511 let cfg = self.cfg.get().await?;
512 let cfg = cfg.as_ref();
513 with_retry(&self.retry, false, || {
514 agent_group_api::create_agent_group(cfg, body.clone())
515 })
516 .await
517 .map_err(map_manager_err)
518 }
519
520 pub async fn get(&self, id: &str) -> Result<models::AgentGroupItemResponse, ManagerError> {
522 let cfg = self.cfg.get().await?;
523 let cfg = cfg.as_ref();
524 with_retry(&self.retry, true, || {
525 agent_group_api::get_agent_group(cfg, id)
526 })
527 .await
528 .map_err(map_manager_err)
529 }
530
531 pub async fn update(
533 &self,
534 id: &str,
535 body: models::RestUpdateAgentGroup,
536 ) -> Result<models::AgentGroupItemResponse, ManagerError> {
537 let cfg = self.cfg.get().await?;
538 let cfg = cfg.as_ref();
539 with_retry(&self.retry, false, || {
540 agent_group_api::update_agent_group(cfg, id, body.clone())
541 })
542 .await
543 .map_err(map_manager_err)
544 }
545
546 pub async fn delete(&self, id: &str) -> Result<(), ManagerError> {
548 let cfg = self.cfg.get().await?;
549 let cfg = cfg.as_ref();
550 with_retry(&self.retry, false, || {
551 agent_group_api::delete_agent_group(cfg, id)
552 })
553 .await
554 .map_err(map_manager_err)?;
555 Ok(())
556 }
557
558 pub async fn add_agent(
560 &self,
561 group_id: &str,
562 agent_id: &str,
563 ) -> Result<models::AgentGroupAdditionResponse, ManagerError> {
564 let cfg = self.cfg.get().await?;
565 let cfg = cfg.as_ref();
566 let id = uuid::Uuid::parse_str(agent_id)
567 .map_err(|e| ManagerError::InvalidArgument(format!("agent_id: {e}")))?;
568 let body = models::AddAgentToGroupRequest { id };
569 with_retry(&self.retry, false, || {
570 manager_api::add_agent_to_group(cfg, group_id, Some(body.clone()))
571 })
572 .await
573 .map_err(map_manager_err)
574 }
575
576 pub async fn remove_agent(
578 &self,
579 group_id: &str,
580 agent_id: &str,
581 ) -> Result<models::AgentGroupItemResponse, ManagerError> {
582 let cfg = self.cfg.get().await?;
583 let cfg = cfg.as_ref();
584 with_retry(&self.retry, false, || {
585 agent_group_api::remove_agent_from_group(cfg, group_id, agent_id)
586 })
587 .await
588 .map_err(map_manager_err)
589 }
590
591 pub async fn list_agents(&self, group_id: &str) -> Result<Vec<models::Agent>, ManagerError> {
593 let cfg = self.cfg.get().await?;
594 let cfg = cfg.as_ref();
595 collect_all(&self.retry, map_manager_err, |page| async move {
596 let r = agent_group_api::list_agents_in_group(cfg, group_id, Some(page), None).await?;
597 Ok((r.items, r.pagination.pages, r.pagination.current))
598 })
599 .await
600 }
601
602 pub async fn bulk_delete(
604 &self,
605 ids: Vec<String>,
606 ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
607 let cfg = self.cfg.get().await?;
608 let cfg = cfg.as_ref();
609 let ids = ids
610 .iter()
611 .map(|id| {
612 uuid::Uuid::parse_str(id)
613 .map_err(|e| ManagerError::InvalidArgument(format!("ids: {e}")))
614 })
615 .collect::<Result<Vec<_>, _>>()?;
616 let body = models::BulkIdsRequest { ids };
617 with_retry(&self.retry, false, || {
618 agent_group_api::bulk_delete_agent_groups(cfg, body.clone())
619 })
620 .await
621 .map_err(map_manager_err)
622 }
623}