cal_core/
core.rs

1use crate::{clean_str, clean_str_parse_country, AccountLite, Device};
2use cal_jambonz::rest::{InitialRequest, Request};
3use cal_jambonz::shared::shared::SIPStatus;
4use cal_jambonz::TenantType;
5use serde::{Deserialize, Serialize};
6
7pub const HANG_UP_CONNECT: &'static str = "HANGUP";
8pub const DEFAULT_TTS_VOICE: &'static str = "en-GB-Standard-B";
9pub const DEFAULT_TTS_LANGUAGE: &'static str = "en-GB";
10pub const DEFAULT_TTS_VENDOR: &'static str = "google";
11pub const DEFAULT_ASR_LANGUAGE: &'static str = "en-GB";
12pub const DEFAULT_ASR_VENDOR: &'static str = "google";
13pub const DEFAULT_RECORDING_RETENTION: &'static str = "P30D";
14pub const DEFAULT_CLIENT_PROFILE: &'static str = "generic_e164_plus";
15pub const DEFAULT_COUNTRY_CODE: &'static str = "gb";
16pub const DEFAULT_DIGITS_FINISH_KEY: &'static str = "#";
17pub const DEFAULT_ENDPOINT_PRESENT: &'static str = "pass-through";
18pub const DEFAULT_VM_FINISH_KEY: &'static str = "#";
19pub const DEFAULT_ENDPOINT_FORMAT: &'static str = "e164p";
20pub const DEFAULT_TIMEZONE: &'static str = "Europe/London";
21pub const DEFAULT_TRUNK_DESCRIPTION: &'static str = "SIP Trunk";
22pub const DEFAULT_TRUNK_PORT: u16 = 5060;
23pub const DEFAULT_RING_TIME: u8 = 180;
24pub const DEFAULT_DIGIT_TIMEOUT: u8 = 10;
25pub const DEFAULT_MAX_DIGITS: u8 = 1;
26pub const DEFAULT_VM_TIMEOUT: u8 = 30;
27pub const DEFAULT_VM_MAX_LENGTH: u8 = 30;
28pub const DEFAULT_CALL_TIME: u16 = 14400;
29
30#[derive(Serialize, Deserialize, Clone)]
31pub struct FlowState {
32    pub initial_request: InitialRequest,
33    pub current_request: Option<Request>,
34    pub account: AccountLite,
35    pub device: Option<Device>,
36    pub connect: Option<ConnectState>,
37    pub tenant_type: TenantType,
38}
39
40impl FlowState {
41    pub fn new(
42        initial_request: InitialRequest,
43        account: AccountLite,
44        proxies: Vec<&str>,
45    ) -> FlowState {
46        let tenant_type = initial_request.get_tenant_type(proxies);
47        let dialled_number = clean_str(
48            account.environment.country_code_parsed(),
49            &initial_request.to,
50        );
51        let device = match tenant_type {
52            TenantType::PROXY => {
53                account.inbound_flow(&dialled_number)
54            }
55            _ => match account.device(&dialled_number) {
56                Some(device) => Some(device),
57                None => account.outbound_flow(),
58            },
59        };
60
61        FlowState {
62            initial_request,
63            current_request: None,
64            account,
65            device,
66            connect: None,
67            tenant_type
68        }
69    }
70
71    pub fn get_country_code(&self) -> String {
72        self.account.environment.country_code.clone()
73    }
74
75    pub fn get_from(&self) -> String {
76        clean_str_parse_country(
77            self.get_country_code().as_str(),
78            self.initial_request.from.as_str(),
79        )
80    }
81    pub fn get_to(&self) -> String {
82        clean_str_parse_country(
83            self.get_country_code().as_str(),
84            self.initial_request.to.as_str(),
85        )
86    }
87    pub fn get_paid_or_from(&self) -> String {
88        match &self.initial_request.sip.headers.p_asserted_identity {
89            Some(str) => clean_str_parse_country(self.get_country_code().as_str(), str.as_str()),
90            None => self.get_from(),
91        }
92    }
93
94    pub fn get_timezone(&self) -> String {
95        self.account.environment.time_zone.clone()
96    }
97
98    pub fn get_dial_status(&self) -> Option<SIPStatus> {
99        match &self.current_request {
100            Some(request) => match request {
101                Request::Dial(value) => Some(value.sip_status.clone()),
102                _ => None,
103            },
104            _ => None,
105        }
106    }
107
108    pub fn get_digits(&self) -> Option<String> {
109        match &self.current_request {
110            Some(request) => match request {
111                Request::Subsequent(value) => match value.digits.clone() {
112                    Some(d) => Some(d),
113                    None => None,
114                },
115                _ => None,
116            },
117            _ => None,
118        }
119    }
120
121    pub fn add_state(&mut self, state: ConnectState) {
122        let device = self
123            .account
124            .devices
125            .iter()
126            .find(|d| d.match_device(state.connect_to.as_str()))
127            .map(|d| d.clone());
128
129        self.device = device.clone();
130    }
131}
132
133#[derive(Serialize, Deserialize, Clone)]
134pub struct ConnectState {
135    pub status: ConnectStatus,
136    pub value: Option<String>,
137    pub match_value: Option<String>,
138    pub connect_to: String,
139}
140
141impl ConnectState {
142    pub fn complete(connect_to: &str) -> ConnectState {
143        ConnectState {
144            connect_to: connect_to.to_string(),
145            status: ConnectStatus::OnCompleted,
146            match_value: None,
147            value: Some("Call Completed".to_string()),
148        }
149    }
150    pub fn fail(connect_to: &str) -> ConnectState {
151        ConnectState {
152            connect_to: connect_to.to_string(),
153            status: ConnectStatus::OnFail,
154            match_value: None,
155            value: Some("Call Failed".to_string()),
156        }
157    }
158
159    pub fn no_answer(connect_to: &str) -> ConnectState {
160        ConnectState {
161            connect_to: connect_to.to_string(),
162            status: ConnectStatus::OnNoAnswer,
163            match_value: None,
164            value: Some("No Answer".to_string()),
165        }
166    }
167
168    pub fn busy(connect_to: &str) -> ConnectState {
169        ConnectState {
170            connect_to: connect_to.to_string(),
171            status: ConnectStatus::OnBusy,
172            match_value: None,
173            value: Some("Call Busy".to_string()),
174        }
175    }
176
177    pub fn waiting() -> ConnectState {
178        ConnectState {
179            connect_to: "WAITING".to_string(),
180            status: ConnectStatus::OnWaiting,
181            match_value: None,
182            value: None,
183        }
184    }
185
186    pub fn dialling() -> ConnectState {
187        ConnectState {
188            connect_to: "DIALLING".to_string(),
189            status: ConnectStatus::OnDialling,
190            match_value: None,
191            value: None,
192        }
193    }
194
195    pub fn matched(
196        connect_to: &str,
197        value: Option<String>,
198        match_value: Option<String>,
199    ) -> ConnectState {
200        ConnectState {
201            connect_to: connect_to.to_string(),
202            status: ConnectStatus::OnMatch,
203            match_value,
204            value,
205        }
206    }
207
208    pub fn default(connect_to: &str, value: Option<String>) -> ConnectState {
209        ConnectState {
210            connect_to: connect_to.to_string(),
211            status: ConnectStatus::OnDefault,
212            match_value: None,
213            value,
214        }
215    }
216}
217
218#[derive(Serialize, Deserialize, Clone)]
219pub enum ConnectStatus {
220    OnDefault,
221    OnMatch,
222    OnCompleted,
223    OnFail,
224    OnBusy,
225    OnNoAnswer,
226    OnTransfer,
227    OnError,
228    OnWaiting,
229    OnDialling,
230}