cal_core/device/
remote.rs

1use crate::device::device::{
2    AiOptions, CallControl, Connector, Endpoint, RecordOptions, TagType, TranscribeOptions,
3};
4use crate::device::utils::{get_caller_id, get_listen, get_proxy, get_transcribe};
5use crate::{ConnectState, FlowState, NumberFormat, VoiceServer, format_number};
6use cal_jambonz::dial::TranscribeDial;
7use cal_jambonz::listen::Listen;
8use cal_jambonz::shared::shared::SIPStatus;
9use serde::{Deserialize, Serialize};
10
11#[derive(Serialize, Deserialize, Clone)]
12#[serde(rename_all = "camelCase")]
13pub struct Remote {
14    #[serde(default = "crate::device::device::build_destination")]
15    pub destination: String,
16    #[serde(default)]
17    pub proxies: Vec<String>,
18    #[serde(default = "crate::device::device::build_present")]
19    pub present: String,
20    #[serde(default = "crate::device::device::build_format")]
21    pub format: NumberFormat,
22    #[serde(default = "crate::device::device::build_country_code")]
23    pub country_code: String,
24    #[serde(default = "crate::device::device::build_connect_to")]
25    pub on_complete: String,
26    #[serde(default = "crate::device::device::build_connect_to")]
27    pub on_busy: String,
28    #[serde(default = "crate::device::device::build_connect_to")]
29    pub on_fail: String,
30    #[serde(default = "crate::device::device::build_connect_to")]
31    pub on_no_answer: String,
32    #[serde(default = "crate::device::device::build_ring_time")]
33    pub ring_time: u8,
34    #[serde(default = "crate::device::device::build_call_time")]
35    pub max_call_time: u16,
36    #[serde(default)]
37    pub transcribe_options: TranscribeOptions,
38    #[serde(default)]
39    pub record_options: RecordOptions,
40    #[serde(default)]
41    pub ai_options: AiOptions,
42    #[serde(default)]
43    pub call_control: CallControl,
44}
45
46impl Connector for Remote {
47    fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
48        match &state.get_dial_status() {
49            Some(status) => match status {
50                SIPStatus::Ok => ConnectState::complete(self.on_complete.as_str()),
51                SIPStatus::RequestTerminated => ConnectState::no_answer(self.on_no_answer.as_str()),
52                SIPStatus::BusyHere | SIPStatus::BusyEverywhere => {
53                    ConnectState::busy(self.on_busy.as_str())
54                }
55                _ => ConnectState::fail(self.on_fail.as_str()),
56            },
57            None => ConnectState::dialling(),
58        }
59    }
60}
61
62impl Endpoint for Remote {
63    fn get_caller_id(&self, state: &FlowState) -> String {
64        if self.present == "pass-through" {
65            get_caller_id(&self.format, state)
66        } else {
67            format_number(
68                &self.present,
69                state.get_country_code().as_str(),
70                self.format.clone(),
71            )
72        }
73    }
74
75    fn get_called_id(&self, state: &FlowState) -> String {
76        let mut destination = self.destination.clone();
77        for (key, value) in state.data.clone() {
78            if value.tag_type == TagType::Session {
79                let formatted = format_number(
80                    value.value.clone().as_str(),
81                    state.get_country_code().clone().as_str(),
82                    self.format.clone(),
83                );
84                let replace = format!("[request.{}]", key);
85                destination = destination.replace(replace.as_str(), formatted.as_str());
86            }
87        }
88        destination.clone()
89    }
90
91    fn get_listen(&self, state: &FlowState) -> Option<Listen> {
92        get_listen(&self.record_options, self.ai_options.clone(), state)
93    }
94
95    fn get_proxy(&self, state: &FlowState) -> Option<VoiceServer> {
96        get_proxy(self.proxies.clone(), state)
97    }
98
99    fn get_transcribe(&self, _state: &FlowState) -> Option<TranscribeDial> {
100        get_transcribe(self.transcribe_options.clone())
101    }
102}
103
104#[test]
105fn test_remote_destination() {
106    let value = format_number("01234567890", "gb", NumberFormat::E164Plus);
107
108    let destination = "sip:[request.to]@1.1.1.1:5060";
109    let replace = format!("[request.{}]", "to");
110    let result = destination.replace(replace.as_str(), value.as_str());
111    assert_eq!(result, "sip:+441234567890@1.1.1.1:5060");
112
113    let destination = "[request.to]";
114    let replace = format!("[request.{}]", "to");
115    let result = destination.replace(replace.as_str(), value.as_str());
116    assert_eq!(result, "+441234567890");
117}