cal-core 0.2.158

Callable core lib
Documentation
// Filename cal-core/src/device/client.rs

use crate::device::device::{Connector, Endpoint, RecordOptions, TranscribeOptions};
use crate::device::shared::{AiOptions, CallControl};
use crate::device::utils::{get_caller_id, get_listen, get_transcribe};
use crate::{format_number, ConnectState, FlowState, NumberFormat, RecordReference};
use cal_jambonz::dial::TranscribeDial;
use cal_jambonz::listen::Listen;
use cal_jambonz::shared::shared::SIPStatus;
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Formatter};

#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Client {
    pub username: String,
    pub password: String,
    #[serde(default = "crate::device::shared::build_client_profile")]
    pub profile: ClientProfile,
    pub user: Option<RecordReference>,
    #[serde(default = "crate::device::shared::build_format")]
    pub format: NumberFormat,
    #[serde(default = "crate::device::shared::build_present")]
    pub present: String,
    #[serde(default = "crate::device::shared::build_country_code")]
    pub country_code: String,
    #[serde(default = "crate::device::shared::build_connect_to")]
    pub on_complete: String,
    #[serde(default = "crate::device::shared::build_connect_to")]
    pub on_busy: String,
    #[serde(default = "crate::device::shared::build_connect_to")]
    pub on_fail: String,
    #[serde(default = "crate::device::shared::build_connect_to")]
    pub on_no_answer: String,
    #[serde(default = "crate::device::shared::build_ring_time")]
    pub ring_time: u8,
    #[serde(default = "crate::device::shared::build_call_time")]
    pub max_call_time: u16,
    #[serde(default)]
    pub transcribe_options: TranscribeOptions,
    #[serde(default)]
    pub record_options: RecordOptions,
    #[serde(default)]
    pub ai_options: AiOptions,
    #[serde(default)]
    pub call_control: CallControl,
}

impl Endpoint for Client {
    fn get_caller_id(&self, state: &FlowState) -> String {
        get_caller_id(&self.format, state)
    }

    fn get_called_id(&self, state: &FlowState) -> String {
        let country_code = state.account.country_code();
        let mut called_id = match state.data.get("to") {
            Some(dt) => dt.value.clone(),
            None => state.initial_request.to.clone(),
        };
        called_id = format_number(
            called_id.as_str(),
            state.account.country_code(),
            &self.format,
        );
        match self.profile {
            ClientProfile::GenericSoftphone
            | ClientProfile::CallablePhone
            | ClientProfile::Avaya
            | ClientProfile::Generic => called_id,
            ClientProfile::GenericE164Plus => {
                format_number(called_id.as_str(), country_code, &NumberFormat::E164Plus)
            }
            ClientProfile::AvayaE164 => {
                format_number(called_id.as_str(), country_code, &NumberFormat::E164)
            }
        }
    }

    fn get_listen(&self, state: &FlowState) -> Option<Listen> {
        get_listen(&self.record_options, self.ai_options.clone(), state)
    }

    fn get_transcribe(&self, _state: &FlowState) -> Option<TranscribeDial> {
        get_transcribe(self.transcribe_options.clone())
    }
}

impl Connector for Client {
    fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
        match &state.get_dial_status() {
            Some(status) => match status {
                SIPStatus::Ok => ConnectState::complete(self.on_complete.as_str()),
                SIPStatus::RequestTerminated => ConnectState::no_answer(self.on_no_answer.as_str()),
                SIPStatus::BusyHere | SIPStatus::BusyEverywhere => {
                    ConnectState::busy(self.on_busy.as_str())
                }
                _ => ConnectState::fail(self.on_fail.as_str()),
            },
            None => ConnectState::dialling(),
        }
    }
}

#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum ClientProfile {
    Generic,
    GenericE164Plus,
    GenericSoftphone,
    CallablePhone,
    Avaya,
    AvayaE164,
}

// Client Debug Implementation
impl Debug for Client {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
        f.debug_struct("Client")
            .field("username", &self.username)
            .field("password", &"REDACTED")
            .field("profile", &self.profile)
            .field("user", &self.user)
            .field("format", &self.format)
            .field("present", &self.present)
            .field("country_code", &self.country_code)
            .field("on_complete", &self.on_complete)
            .field("on_busy", &self.on_busy)
            .field("on_fail", &self.on_fail)
            .field("on_no_answer", &self.on_no_answer)
            .field("ring_time", &self.ring_time)
            .field("max_call_time", &self.max_call_time)
            .field("transcribe_options", &self.transcribe_options)
            .field("record_options", &self.record_options)
            .field("ai_options", &self.ai_options)
            .field("call_control", &self.call_control)
            .finish()
    }
}

impl Debug for ClientProfile {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
        match self {
            ClientProfile::GenericE164Plus => write!(f, "GenericE164Plus"),
            ClientProfile::CallablePhone => write!(f, "CallablePhone"),
            ClientProfile::Avaya => write!(f, "Avaya"),
            ClientProfile::Generic => write!(f, "Generic"),
            ClientProfile::GenericSoftphone =>  write!(f, "GenericSoftphone"),
            ClientProfile::AvayaE164 =>  write!(f, "AvayaE164"),
        }
    }
}

impl Debug for NumberFormat {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
        match self {
            NumberFormat::National => write!(f, "National"),
            NumberFormat::E164Plus => write!(f, "E164+"),
            NumberFormat::E164 => write!(f, "E164"),
        }
    }
}