cal_core/
core.rs

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