cal_core/device/
remote.rs1use 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}