babelforce-manager-sdk 0.46.0

Rust SDK for the babelforce manager APIs — auth, user & agent management, call reporting, metrics, and task automations.
Documentation
use crate::error::{map_manager_err, ManagerError};
use crate::gen::manager::apis::configuration::Configuration;
use crate::gen::manager::apis::{call_api, dialer_api, outbound_api as api, reporting_call_api};
use crate::gen::manager::models;
use crate::http::collect_all;
use crate::retry::{with_retry, RetryPolicy};
use crate::token::SharedCfg;

/// Outbound lists & leads — `/api/v2/outbound/lists`.
pub struct OutboundResource {
    pub(crate) cfg: SharedCfg<Configuration>,
    pub(crate) retry: RetryPolicy,
}

impl OutboundResource {
    /// List the outbound lists.
    pub async fn lists(&self) -> Result<Vec<models::OutboundList>, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        let resp = with_retry(&self.retry, true, || api::list_outbound_lists(cfg))
            .await
            .map_err(map_manager_err)?;
        Ok(resp.items)
    }

    /// Create an outbound list.
    pub async fn create_list(
        &self,
        body: models::CreateOutboundListRequest,
    ) -> Result<models::OutboundListItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::create_outbound_list(cfg, Some(body.clone()))
        })
        .await
        .map_err(map_manager_err)
    }

    /// Clear all leads from an outbound list; returns the updated list.
    pub async fn clear_list(
        &self,
        id: &str,
    ) -> Result<models::OutboundListItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || api::clear_outbound_list(cfg, id))
            .await
            .map_err(map_manager_err)
    }

    /// Add a lead to an outbound list.
    pub async fn add_lead(
        &self,
        list_id: &str,
        body: models::AddOutboundLeadRequest,
    ) -> Result<models::OutboundLeadItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::add_outbound_lead(cfg, list_id, Some(body.clone()))
        })
        .await
        .map_err(map_manager_err)
    }

    /// Update a lead on an outbound list.
    pub async fn update_lead(
        &self,
        list_id: &str,
        lead_id: &str,
        body: models::AddOutboundLeadRequest,
    ) -> Result<models::OutboundLeadItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            dialer_api::update_outbound_lead(cfg, list_id, lead_id, Some(body.clone()))
        })
        .await
        .map_err(map_manager_err)
    }

    /// Delete a lead from an outbound list.
    pub async fn delete_lead(&self, list_id: &str, lead_id: &str) -> Result<(), ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            dialer_api::delete_outbound_lead(cfg, list_id, lead_id)
        })
        .await
        .map_err(map_manager_err)?;
        Ok(())
    }

    /// Place an outbound call on behalf of an agent.
    pub async fn create_agent_call(
        &self,
        id: &str,
        body: models::AgentOutboundCallRequest,
    ) -> Result<models::CallItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            call_api::create_agent_outbound_call(cfg, id, body.clone())
        })
        .await
        .map_err(map_manager_err)
    }

    /// The simple outbound call report, collecting every call across pages.
    pub async fn simple_reporting(&self) -> Result<Vec<models::ReportingCall>, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        collect_all(&self.retry, map_manager_err, |page| async move {
            let r = reporting_call_api::list_outbound_simple_reporting_calls(cfg, Some(page), None)
                .await?;
            Ok((
                r.items,
                r.pagination.pages.unwrap_or(1),
                r.pagination.current.unwrap_or(1),
            ))
        })
        .await
    }

    /// List outbound dial attempts, collecting every attempt across pages.
    pub async fn attempts(&self) -> Result<Vec<models::CallAttempt>, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        collect_all(&self.retry, map_manager_err, |page| async move {
            let r =
                api::list_outbound_attempts(cfg, Some(page), None, None, None, None, None).await?;
            Ok((
                r.items,
                r.pagination.pages.unwrap_or(1),
                r.pagination.current.unwrap_or(1),
            ))
        })
        .await
    }

    /// List outbound leads, collecting every lead across pages.
    pub async fn leads(&self) -> Result<Vec<models::Lead>, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        collect_all(&self.retry, map_manager_err, |page| async move {
            let r = api::list_outbound_leads(cfg, Some(page), None, None, None).await?;
            Ok((
                r.items,
                r.pagination.pages.unwrap_or(1),
                r.pagination.current.unwrap_or(1),
            ))
        })
        .await
    }

    /// List processed outbound leads, collecting every lead across pages.
    pub async fn processed_leads(&self) -> Result<Vec<models::Lead>, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        collect_all(&self.retry, map_manager_err, |page| async move {
            let r = api::list_processed_outbound_leads(cfg, Some(page), None).await?;
            Ok((
                r.items,
                r.pagination.pages.unwrap_or(1),
                r.pagination.current.unwrap_or(1),
            ))
        })
        .await
    }

    /// Get a single outbound list.
    pub async fn get_list(&self, id: &str) -> Result<models::LeadListItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, true, || api::get_outbound_list(cfg, id))
            .await
            .map_err(map_manager_err)
    }

    /// Update an outbound list.
    pub async fn update_list(
        &self,
        id: &str,
        body: models::CreateListRequest,
    ) -> Result<models::LeadListItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::update_outbound_list(cfg, id, body.clone())
        })
        .await
        .map_err(map_manager_err)
    }

    /// Delete an outbound list.
    pub async fn delete_list(&self, id: &str) -> Result<(), ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || api::delete_outbound_list(cfg, id))
            .await
            .map_err(map_manager_err)?;
        Ok(())
    }

    /// Bulk-delete leads from an outbound list.
    pub async fn bulk_delete_leads(
        &self,
        id: &str,
        body: models::LeadBulkDeleteRequest,
    ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::bulk_delete_outbound_leads(cfg, id, body.clone())
        })
        .await
        .map_err(map_manager_err)
    }

    /// Bulk-delete leads from an outbound list (alternate endpoint).
    pub async fn bulk_delete_leads_alt(
        &self,
        id: &str,
        body: models::LeadBulkDeleteRequest,
    ) -> Result<models::DefaultV2MessageResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::bulk_delete_outbound_leads_alt(cfg, id, body.clone())
        })
        .await
        .map_err(map_manager_err)
    }

    /// Get a single lead from an outbound list.
    pub async fn get_lead(
        &self,
        list_id: &str,
        lead_id: &str,
    ) -> Result<models::LeadItemResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, true, || {
            api::get_lead_in_list(cfg, list_id, lead_id)
        })
        .await
        .map_err(map_manager_err)
    }

    /// List the leads in an outbound list, optionally filtered by dial status and format.
    pub async fn list_leads(
        &self,
        list_id: &str,
        status: Option<models::DialStatus>,
        format: Option<&str>,
    ) -> Result<models::PaginatedLeadResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, true, || {
            api::list_leads_in_list(cfg, list_id, status, format)
        })
        .await
        .map_err(map_manager_err)
    }

    /// Upload leads to an outbound list from a CSV file.
    pub async fn upload_leads(
        &self,
        id: &str,
        file: std::path::PathBuf,
        mapping: Option<&str>,
        separator: Option<&str>,
        clear: Option<bool>,
    ) -> Result<models::LeadUploadResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        with_retry(&self.retry, false, || {
            api::upload_outbound_leads(cfg, id, file.clone(), mapping, separator, clear)
        })
        .await
        .map_err(map_manager_err)
    }

    /// Upload leads to an outbound list from in-memory CSV bytes — the same multipart request as
    /// [`upload_leads`](Self::upload_leads) without a file on disk (lead CSVs carry PII; callers
    /// holding the content in memory shouldn't have to write it out to upload it).
    pub async fn upload_leads_bytes(
        &self,
        id: &str,
        file_name: &str,
        csv: Vec<u8>,
        mapping: Option<&str>,
        separator: Option<&str>,
        clear: Option<bool>,
    ) -> Result<models::LeadUploadResponse, ManagerError> {
        let cfg = self.cfg.get().await?;
        let cfg = cfg.as_ref();
        let uri = format!(
            "{}/api/v2/outbound/lists/{id}/leads/upload",
            cfg.base_path,
            id = crate::gen::manager::apis::urlencode(id)
        );
        with_retry(&self.retry, false, || {
            let uri = uri.clone();
            let csv = csv.clone();
            async move {
                let mut req = cfg.client.request(reqwest::Method::POST, &uri);
                if let Some(ref user_agent) = cfg.user_agent {
                    req = req.header(reqwest::header::USER_AGENT, user_agent.clone());
                }
                if let Some(ref token) = cfg.oauth_access_token {
                    req = req.bearer_auth(token.to_owned());
                }
                let mut form = reqwest::multipart::Form::new().part(
                    "file",
                    reqwest::multipart::Part::bytes(csv).file_name(file_name.to_string()),
                );
                if let Some(v) = mapping {
                    form = form.text("mapping", v.to_string());
                }
                if let Some(v) = separator {
                    form = form.text("separator", v.to_string());
                }
                if let Some(v) = clear {
                    form = form.text("clear", v.to_string());
                }
                let resp = req
                    .multipart(form)
                    .send()
                    .await
                    .map_err(|e| ManagerError::Network(e.to_string()))?;
                let status = resp.status();
                let body = resp
                    .text()
                    .await
                    .map_err(|e| ManagerError::Network(e.to_string()))?;
                if !status.is_success() {
                    return Err(ManagerError::from_response(status.as_u16(), body));
                }
                serde_json::from_str(&body).map_err(|e| ManagerError::Decode(e.to_string()))
            }
        })
        .await
    }
}