cal_core/
core.rs

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