cal_core/
account.rs

1use crate::accounting::Address;
2use crate::core::*;
3use crate::device::device::{Connector, Device, DeviceStruct};
4use crate::utils::*;
5use crate::RecordReference;
6use bson::DateTime;
7use phonenumber::country;
8use phonenumber::country::Id;
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11use std::fmt::{Debug, Formatter};
12
13#[derive(Serialize, Deserialize, Clone)]
14#[serde(rename_all = "camelCase")]
15pub struct AccountLite {
16    #[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
17    pub id: String,
18    pub name: String,
19    pub mbn: String,
20    pub domain: String,
21    #[serde(default = "crate::shared::build_timestamp")]
22    pub created: DateTime,
23    pub organisation: RecordReference,
24    #[serde(default)]
25    pub teams: TeamsAccount,
26    #[serde(default)]
27    pub environment: Environment,
28    #[serde(default)]
29    pub spend_cap: SpendCap,
30    #[serde(default)]
31    pub concurrency: Concurrency,
32    #[serde(default)]
33    pub class_of_service: ClassOfService,
34    pub cluster_settings: Cluster,
35}
36
37
38
39impl AccountLite {
40    pub fn country_code(&self) -> &str {
41        self.environment.country_code.as_str()
42    }
43
44    pub fn country_code_parsed(&self) -> Id {
45        self.environment.country_code_parsed()
46    }
47
48    pub fn clean_str(&self, str: &str) -> String {
49        clean_str(self.environment.country_code_parsed(), str)
50    }
51}
52
53#[derive(Serialize, Deserialize, Clone)]
54#[serde(rename_all = "camelCase")]
55pub struct Account {
56    #[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
57    pub id: String,
58    pub name: String,
59    pub mbn: String,
60    pub domain: String,
61    #[serde(default = "crate::shared::build_timestamp")]
62    pub created: DateTime,
63    pub organisation: RecordReference,
64    #[serde(default)]
65    pub ddis: Vec<DDI>,
66    #[serde(default)]
67    pub trunks: Vec<Trunk>,
68    #[serde(default)]
69    #[serde(rename = "callbackURLS")]
70    pub hooks: Vec<Hook>,
71    #[serde(default)]
72    pub devices: Vec<DeviceStruct>,
73    #[serde(default)]
74    pub assets: Vec<Asset>,
75    #[serde(default)]
76    pub address: Address,
77    #[serde(default)]
78    pub addresses: Vec<Address>,
79    #[serde(default)]
80    pub teams: TeamsAccount,
81    #[serde(default)]
82    pub environment: Environment,
83    #[serde(default)]
84    pub spend_cap: SpendCap,
85    #[serde(default)]
86    pub concurrency: Concurrency,
87    #[serde(default)]
88    pub class_of_service: ClassOfService,
89    pub cluster_settings: Cluster,
90    #[serde(default)]
91    pub api_keys: APIKeys,
92}
93
94impl From<Account> for AccountLite {
95    fn from(account: Account) -> Self {
96        AccountLite {
97            id: account.id,
98            name: account.name,
99            mbn: account.mbn,
100            domain: account.domain,
101            created: account.created,
102            organisation: account.organisation,
103            teams: account.teams,
104            environment: account.environment,
105            spend_cap: account.spend_cap,
106            concurrency: account.concurrency,
107            class_of_service: account.class_of_service,
108            cluster_settings: account.cluster_settings,
109        }
110    }
111}
112
113// Implement From for references too, which is often useful
114impl From<&Account> for AccountLite {
115    fn from(account: &Account) -> Self {
116        AccountLite {
117            id: account.id.clone(),
118            name: account.name.clone(),
119            mbn: account.mbn.clone(),
120            domain: account.domain.clone(),
121            created: account.created.clone(),
122            organisation: account.organisation.clone(),
123            teams: account.teams.clone(),
124            environment: account.environment.clone(),
125            spend_cap: account.spend_cap.clone(),
126            concurrency: account.concurrency.clone(),
127            class_of_service: account.class_of_service.clone(),
128            cluster_settings: account.cluster_settings.clone(),
129        }
130    }
131}
132
133#[derive(Serialize, Deserialize, Clone)]
134#[serde(rename_all = "camelCase")]
135pub struct Cluster {
136    #[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
137    pub id: String,
138    pub name: String,
139    pub server_a: String,
140}
141
142#[derive(Serialize, Deserialize, Clone)]
143#[serde(rename_all = "camelCase")]
144pub struct APIKeys {
145    #[serde(default)]
146    keys: Vec<APIKey>,
147}
148
149impl Default for APIKeys {
150    fn default() -> Self {
151        Self { keys: Vec::new() }
152    }
153}
154
155#[derive(Serialize, Deserialize, Clone)]
156#[serde(rename_all = "camelCase")]
157pub struct APIKey {
158    key: String,
159}
160
161#[derive(Serialize, Deserialize, Clone)]
162#[serde(rename_all = "camelCase")]
163pub struct Environment {
164    #[serde(default = "build_logger")]
165    pub logger: LoggerLevel,
166    #[serde(rename = "dialTimeLimit")]
167    #[serde(default = "build_call_time")]
168    pub max_call_time: u16,
169    #[serde(rename = "dialTimeout")]
170    #[serde(default = "build_ring_time")]
171    pub ring_time: u8,
172    #[serde(default = "build_tts_vendor")]
173    pub tts_vendor: String,
174    #[serde(default = "build_tts_language")]
175    #[serde(rename = "ttsLanguageV2")]
176    pub tts_language: String,
177    #[serde(default = "build_tts_voice")]
178    pub tts_voice: String,
179    #[serde(default = "build_asr_vendor")]
180    pub asr_vendor: AsrVendor,
181    #[serde(default = "build_asr_language")]
182    pub asr_language: String,
183    #[serde(default = "build_default_timezone")]
184    pub time_zone: String,
185    #[serde(default = "build_country_code")]
186    pub country_code: String,
187    #[serde(default = "build_record_retention")]
188    pub recording_retention: String,
189    pub ingress_script: Option<String>,
190}
191
192impl Environment {
193    pub fn country_code_parsed(&self) -> Id {
194        self.country_code.parse().unwrap_or_else(|_| country::GB)
195    }
196}
197impl Default for Environment {
198    fn default() -> Self {
199        Self {
200            logger: LoggerLevel::Warn,
201            max_call_time: DEFAULT_CALL_TIME,
202            ring_time: DEFAULT_RING_TIME,
203            tts_vendor: DEFAULT_TTS_VENDOR.to_string(),
204            tts_language: DEFAULT_TTS_LANGUAGE.to_string(),
205            tts_voice: DEFAULT_TTS_VOICE.to_string(),
206            asr_vendor: AsrVendor::Google,
207            asr_language: DEFAULT_ASR_LANGUAGE.to_string(),
208            time_zone: DEFAULT_TIMEZONE.to_string(),
209            country_code: DEFAULT_COUNTRY_CODE.to_string(),
210            recording_retention: DEFAULT_RECORDING_RETENTION.to_string(),
211            ingress_script: None,
212        }
213    }
214}
215
216#[derive(Serialize, Deserialize, Clone)]
217#[serde(rename_all = "camelCase")]
218pub struct SpendCap {
219    #[serde(default = "build_spend_cap_value")]
220    value: u16,
221    #[serde(default = "build_spend_cap_level")]
222    warn: u8,
223    #[serde(default = "build_spend_cap_action")]
224    action: RouteAction,
225    #[serde(default)]
226    email_recipients: Vec<String>,
227}
228
229impl Default for SpendCap {
230    fn default() -> Self {
231        Self {
232            value: 100,
233            warn: 80,
234            action: RouteAction::Warn,
235            email_recipients: Vec::new(),
236        }
237    }
238}
239
240#[derive(Serialize, Deserialize, Clone)]
241#[serde(rename_all = "camelCase")]
242pub struct Concurrency {
243    #[serde(rename = "type")]
244    #[serde(default = "build_license")]
245    license: Licence,
246    #[serde(default = "build_concurrency_action")]
247    action: RouteAction,
248    #[serde(default)]
249    email_recipients: Vec<String>,
250}
251
252impl Default for Concurrency {
253    fn default() -> Self {
254        Concurrency {
255            license: Licence::Standard,
256            action: RouteAction::Warn,
257            email_recipients: vec![],
258        }
259    }
260}
261
262#[derive(Serialize, Deserialize, Clone)]
263#[serde(rename_all = "camelCase")]
264pub struct ClassOfService {
265    #[serde(rename = "type")]
266    #[serde(default = "build_cos_action")]
267    license: COSAction,
268    #[serde(default)]
269    countries: Vec<String>,
270    #[serde(default)]
271    prefix_exceptions: String,
272    #[serde(rename = "maxPPM")]
273    #[serde(default = "build_cos_ppm")]
274    max_ppm: f32,
275    #[serde(rename = "maxPPC")]
276    #[serde(default = "build_cos_ppc")]
277    max_ppc: f32,
278}
279
280impl Default for ClassOfService {
281    fn default() -> Self {
282        Self {
283            license: COSAction::Allow,
284            countries: Vec::new(),
285            prefix_exceptions: String::from(""),
286            max_ppc: 10.00,
287            max_ppm: 10.00,
288        }
289    }
290}
291
292#[derive(Serialize, Deserialize, Clone)]
293#[serde(rename_all = "camelCase")]
294pub enum LoggerLevel {
295    Debug,
296    Info,
297    Warn,
298    Error,
299}
300
301#[derive(Serialize, Deserialize, Clone)]
302#[serde(rename_all = "camelCase")]
303pub enum Licence {
304    Standard,
305    Professional,
306    Enterprise,
307}
308
309#[derive(Serialize, Deserialize, Clone)]
310pub enum COSAction {
311    #[serde(alias = "DENY")]
312    #[serde(rename = "deny")]
313    Deny,
314    #[serde(alias = "ALLOW")]
315    #[serde(rename = "allow")]
316    Allow,
317    #[serde(alias = "WARN")]
318    #[serde(rename = "warn")]
319    Warn,
320}
321
322#[derive(Serialize, Deserialize, Clone)]
323pub enum RouteAction {
324    #[serde(rename = "warn")]
325    Warn,
326    #[serde(rename = "restrict")]
327    Restrict,
328    #[serde(rename = "deny")]
329    Deny,
330}
331
332#[derive(Serialize, Deserialize, Clone)]
333#[serde(rename_all = "camelCase")]
334pub struct TeamsAccount {
335    #[serde(rename = "type")]
336    pub domain_type: TeamsDomainType,
337    #[serde(default)]
338    pub domain: String,
339    pub txt: Option<String>,
340    // #[serde(rename = "serverA")]
341    // pub server_a: String,
342    // #[serde(rename = "serverB")]
343    // pub server_b: String,
344}
345
346#[derive(Serialize, Deserialize, Clone)]
347#[serde(rename_all = "camelCase")]
348pub enum TeamsDomainType {
349    Callable,
350    Legacy,
351}
352
353impl Default for TeamsAccount {
354    fn default() -> Self {
355        Self {
356            domain_type: TeamsDomainType::Callable,
357            domain: String::from(""),
358            txt: None,
359        }
360    }
361}
362
363
364#[derive(Serialize, Deserialize, Clone)]
365#[serde(rename_all = "camelCase")]
366pub struct Asset {
367    #[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
368    pub id: String,
369    pub bucket: String,
370    pub key: String,
371    pub filename: String,
372    pub name: String,
373    pub mime_type: String,
374    pub size: u32,
375    #[serde(default = "crate::shared::build_timestamp")]
376    pub created: DateTime,
377    #[serde(default)]
378    pub meta: HashMap<String, String>,
379}
380
381#[derive(Serialize, Deserialize, Clone)]
382#[serde(rename_all = "camelCase")]
383pub struct Setting {
384    #[serde(default)]
385    #[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
386    pub id: String,
387    pub key: String,
388    #[serde(rename = "type")]
389    pub setting_type: String,
390    pub value: String,
391}
392
393#[derive(Serialize, Deserialize, Debug, Clone)]
394#[serde(rename_all = "camelCase")]
395pub struct DDI {
396    #[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
397    pub id: String,
398    pub name: String,
399    #[serde(default)]
400    pub meta: HashMap<String, String>,
401}
402
403#[derive(Serialize, Deserialize, Clone)]
404#[serde(rename_all = "camelCase")]
405pub struct Trunk {
406    #[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
407    pub id: String,
408    pub ip: String,
409    #[serde(default = "build_trunk_description")]
410    pub description: String,
411    #[serde(deserialize_with = "crate::shared::from_str", default = "build_trunk_port")]
412    pub port: u16,
413}
414
415
416
417#[derive(Serialize, Deserialize, Clone)]
418#[serde(rename_all = "camelCase")]
419pub struct Hook {
420    #[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
421    pub id: String,
422    pub app: String,
423    pub url: String,
424    #[serde(default = "AuthType::default_method")]
425    pub auth_type: AuthType,
426    #[serde(default = "HookMethod::default_method")]
427    pub method: HookMethod,
428    #[serde(default)]
429    pub meta: HashMap<String, String>,
430    #[serde(default)]
431    pub api_key_name: String,
432    #[serde(default)]
433    pub api_key_value: String,
434    #[serde(default)]
435    pub api_secret_name: String,
436    #[serde(default)]
437    pub api_secret_value: String,
438}
439
440#[derive(Serialize, Deserialize, Clone)]
441pub enum HookMethod {
442    #[serde(rename = "POST")]
443    Post,
444    #[serde(rename = "GET")]
445    Get,
446}
447
448impl Debug for HookMethod {
449    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
450        match self {
451            HookMethod::Post => write!(f, "HookMethod::Post"),
452            HookMethod::Get => write!(f, "HookMethod::Get"),
453        }
454    }
455}
456
457
458impl HookMethod {
459    fn default_method() -> Self {
460        HookMethod::Post
461    }
462}
463
464#[derive(Serialize, Deserialize, Clone)]
465pub enum AuthType {
466    #[serde(rename = "DISABLED")]
467    Disabled,
468    #[serde(rename = "KEY")]
469    Key,
470    #[serde(rename = "KEY_SECRET")]
471    KeySecret,
472    #[serde(rename = "BASIC_AUTH")]
473    BasicAuth,
474    #[serde(rename = "OAUTH")]
475    OAuth,
476}
477
478impl AuthType {
479    fn default_method() -> Self {
480        AuthType::Disabled
481    }
482}
483
484impl Connector for Device {
485    fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
486        match self {
487            Device::InboundFlow(value) => value.get_connect_to(state),
488            Device::OutboundFlow(value) => value.get_connect_to(state),
489            Device::AppFlow(value) => value.get_connect_to(state),
490            Device::WhatsAppFlow(value) => value.get_connect_to(state),
491            Device::AniRouter(value) => value.get_connect_to(state),
492            Device::DnisRouter(value) => value.get_connect_to(state),
493            Device::DigitRouter(value) => value.get_connect_to(state),
494            Device::TimeRangeRouter(value) => value.get_connect_to(state),
495            Device::DayOfWeekRouter(value) => value.get_connect_to(state),
496            Device::DateRangeRouter(value) => value.get_connect_to(state),
497            Device::Play(value) => value.get_connect_to(state),
498            Device::Say(value) => value.get_connect_to(state),
499            Device::Voicemail(value) => value.get_connect_to(state),
500            Device::Script(value) => value.get_connect_to(state),
501            Device::Queue(value) => value.get_connect_to(state),
502            Device::Sms(value) => value.get_connect_to(state),
503            Device::Email(value) => value.get_connect_to(state),
504            Device::Tag(value) => value.get_connect_to(state),
505            Device::TagRouter(value) => value.get_connect_to(state),
506            Device::Service(value) => value.get_connect_to(state),
507            Device::Client(value) => value.get_connect_to(state),
508            Device::Teams(value) => value.get_connect_to(state),
509            Device::Remote(value) => value.get_connect_to(state),
510            Device::HuntGroup(value) => value.get_connect_to(state),
511            Device::SipGateway(value) => value.get_connect_to(state),
512            Device::SipExtension(value) => value.get_connect_to(state),
513            _ => ConnectState::device_error(HANG_UP_CONNECT),
514        }
515    }
516}
517
518#[derive(Serialize, Deserialize, Clone)]
519#[serde(rename_all = "camelCase")]
520pub enum AsrVendor {
521    Deepgram,
522    Google,
523    Aws,
524    Ibm,
525    Microsoft,
526    Nuance,
527    Nvidia,
528    Soniox,
529}
530
531#[derive(Serialize, Deserialize, Clone)]
532pub struct Contact {
533    #[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
534    id: String,
535    primary: String,
536    secondary: Option<String>,
537    tertiary: Option<String>,
538    name: Option<String>,
539    nickname: Option<String>,
540    email: Option<String>,
541}
542
543fn build_asr_vendor() -> AsrVendor {
544    AsrVendor::Google
545}
546
547fn build_asr_language() -> String {
548    String::from(DEFAULT_ASR_LANGUAGE)
549}
550
551fn build_tts_vendor() -> String {
552    String::from(DEFAULT_TTS_VENDOR)
553}
554
555fn build_tts_language() -> String {
556    String::from(DEFAULT_TTS_LANGUAGE)
557}
558
559fn build_tts_voice() -> String {
560    String::from(DEFAULT_TTS_VOICE)
561}
562
563fn build_default_timezone() -> String {
564    String::from(DEFAULT_TIMEZONE)
565}
566
567fn build_trunk_description() -> String {
568    String::from(DEFAULT_TRUNK_DESCRIPTION)
569}
570
571fn build_trunk_port() -> u16 {
572    DEFAULT_TRUNK_PORT
573}
574
575fn build_country_code() -> String {
576    String::from(DEFAULT_COUNTRY_CODE)
577}
578
579fn build_logger() -> LoggerLevel {
580    LoggerLevel::Warn
581}
582
583fn build_call_time() -> u16 {
584    DEFAULT_CALL_TIME
585}
586
587fn build_ring_time() -> u8 {
588    DEFAULT_RING_TIME
589}
590
591fn build_spend_cap_value() -> u16 {
592    100
593}
594
595fn build_spend_cap_level() -> u8 {
596    80
597}
598
599fn build_spend_cap_action() -> RouteAction {
600    RouteAction::Warn
601}
602
603fn build_concurrency_action() -> RouteAction {
604    RouteAction::Warn
605}
606
607fn build_cos_action() -> COSAction {
608    COSAction::Allow
609}
610
611fn build_cos_ppm() -> f32 {
612    15.00
613}
614
615fn build_cos_ppc() -> f32 {
616    15.00
617}
618
619fn build_license() -> Licence {
620    Licence::Standard
621}
622
623fn build_record_retention() -> String {
624    String::from(DEFAULT_RECORDING_RETENTION)
625}
626
627
628
629