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}