1use crate::core::*;
2use crate::device::client::{Client, ClientProfile};
3use crate::device::hunt_group::HuntGroup;
4use crate::device::remote::Remote;
5use crate::device::sip_extension::SipExtension;
6use crate::sip_gateway::SipGateway;
7use crate::teams::Teams;
8use crate::{AsrVendor, ConnectState, FlowState, NumberFormat, QueueItemType, VoiceServer};
9use bson::DateTime;
10use cal_jambonz::dial::TranscribeDial;
11use cal_jambonz::listen::{Listen, MixType, SampleRate};
12use cal_jambonz::recognizer::Recognizer;
13use cal_jambonz::shared::shared::SIPStatus;
14use chrono::{Datelike, Local, Utc};
15use serde::{Deserialize, Deserializer, Serialize};
16use serde_json::Value;
17
18pub trait Connector {
19 fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState;
20}
21
22pub trait BaseDevice {
23 fn get_id(&mut self) -> String;
24 fn get_name(&mut self) -> String;
25 fn get_extension(&mut self) -> u16;
26}
27
28#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
29pub enum DeviceType {
30 #[serde(rename = "ROUTE_START")]
31 InboundFlow,
32 #[serde(rename = "MATCH_START")]
33 OutboundFlow,
34 #[serde(rename = "WHATSAPP_START")]
35 WhatsAppFlow,
36 #[serde(rename = "APP_START")]
37 AppFlow,
38 #[serde(rename = "ANI_ROUTER")]
39 AniRouter,
40 #[serde(rename = "DNIS_ROUTER")]
41 DnisRouter,
42 #[serde(rename = "NUMBER_PLAN")]
43 DigitRouter,
44 #[serde(rename = "TIME_RANGE_ROUTER")]
45 TimeRangeRouter,
46 #[serde(rename = "DAY_OF_WEEK_ROUTER")]
47 DayOfWeekRouter,
48 #[serde(rename = "DATE_RANGE_ROUTER")]
49 DateRangeRouter,
50 #[serde(rename = "HUNT_GROUP")]
51 HuntGroup,
52 #[serde(rename = "CLIENT")]
53 Client,
54 #[serde(rename = "TEAMS")]
55 Teams,
56 #[serde(rename = "SIP")]
57 SipExtension,
58 #[serde(rename = "SIP_GATEWAY")]
59 SipGateway,
60 #[serde(rename = "REMOTE")]
61 Remote,
62 #[serde(rename = "PLUGIN")]
63 Plugin,
64 #[serde(rename = "PLAY")]
65 Play,
66 #[serde(rename = "SAY")]
67 Say,
68 #[serde(rename = "VOICEMAIL")]
69 Voicemail,
70 #[serde(rename = "SCRIPT")]
71 Script,
72 #[serde(rename = "QUEUE")]
73 Queue,
74 #[serde(rename = "SMS")]
75 Sms,
76 #[serde(rename = "EMAIL")]
77 Email,
78 #[serde(rename = "TAG")]
79 Tag,
80 #[serde(rename = "TAG_ROUTER")]
81 TagRouter,
82 #[serde(rename = "MESSAGE_PLUGIN")]
83 MessagePlugin,
84 #[serde(rename = "MESSAGE_TEXT")]
85 MessageText,
86 #[serde(rename = "MESSAGE_BUTTONS")]
87 MessageButtons,
88 #[serde(rename = "MESSAGE_TEMPLATE")]
89 MessageTemplate,
90 #[serde(rename = "MESSAGE_ANI_ROUTER")]
91 MessageAniRouter,
92 #[serde(rename = "SERVICE")]
93 Service,
94 }
96
97#[derive(Serialize, Deserialize, Clone)]
98#[serde(untagged)]
99pub enum Device {
100 InboundFlow(InboundFlow),
101 OutboundFlow(OutboundFlow),
102 WhatsAppFlow(WhatsAppFlow),
103 AppFlow(AppFlow),
104 AniRouter(ANIRouter),
105 DnisRouter(DNISRouter),
106 DigitRouter(DigitRouter),
107 TimeRangeRouter(TimeRangeRouter),
108 DayOfWeekRouter(DayOfWeekRouter),
109 DateRangeRouter(DateRangeRouter),
110 HuntGroup(HuntGroup),
111 Client(Client),
112 Teams(Teams),
113 SipExtension(SipExtension),
114 SipGateway(SipGateway),
115 Remote(Remote),
116 Plugin(Plugin),
117 Play(Play),
118 Say(Say),
119 Voicemail(VoiceMail),
120 Script(Script),
121 Queue(Queue),
122 Sms(Sms),
123 Email(Email),
124 Tag(Tag),
125 TagRouter(TagRouter),
126 MessagePlugin(MessagePlugin),
127 MessageButtons(MessageButtons),
128 MessageText(MessageText),
129 MessageTemplate(MessageTemplate),
130 MessageAniRouter(MessageAniRouter),
131 Service(Service),
132}
133
134#[derive(Serialize, Deserialize, Clone)]
135#[serde(rename_all = "camelCase")]
136pub struct DeviceStruct {
137 #[serde(rename = "_id")]
138 pub id: String,
139
140 #[serde(rename = "type")]
141 pub device_type: DeviceType,
142
143 pub name: String,
144
145 #[serde(deserialize_with = "from_str")]
146 pub extension: u16,
147
148 #[serde(default)]
149 pub tags: Vec<DeviceTag>,
150
151 #[serde(rename = "startRoute")]
152 #[serde(skip_serializing_if = "Option::is_none")]
153 pub start_route: Option<InboundFlow>,
154
155 #[serde(rename = "regexRoute")]
156 #[serde(skip_serializing_if = "Option::is_none")]
157 pub regex_route: Option<OutboundFlow>,
158
159 #[serde(rename = "appRoute")]
160 #[serde(skip_serializing_if = "Option::is_none")]
161 pub app_route: Option<AppFlow>,
162
163 #[serde(rename = "numberPlan")]
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub number_plan: Option<DigitRouter>,
166
167 #[serde(rename = "aniRouter")]
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub ani_router: Option<ANIRouter>,
170
171 #[serde(rename = "dnisRouter")]
172 #[serde(skip_serializing_if = "Option::is_none")]
173 pub dnis_router: Option<DNISRouter>,
174
175 #[serde(rename = "zoneRouter")]
176 #[serde(skip_serializing_if = "Option::is_none")]
177 pub zone_router: Option<ZoneRouter>,
178
179 #[serde(rename = "tagRouter")]
180 #[serde(skip_serializing_if = "Option::is_none")]
181 pub tag_router: Option<TagRouter>,
182
183 #[serde(rename = "timeRangeRoute")]
184 #[serde(skip_serializing_if = "Option::is_none")]
185 pub time_range_router: Option<TimeRangeRouter>,
186
187 #[serde(rename = "dayOfWeekRoute")]
188 #[serde(skip_serializing_if = "Option::is_none")]
189 pub day_of_week_router: Option<DayOfWeekRouter>,
190
191 #[serde(rename = "dateRangeRoute")]
192 #[serde(skip_serializing_if = "Option::is_none")]
193 pub date_range_router: Option<DateRangeRouter>,
194
195 #[serde(rename = "huntGroup")]
196 #[serde(skip_serializing_if = "Option::is_none")]
197 pub hunt_group: Option<HuntGroup>,
198
199 #[serde(rename = "client")]
200 #[serde(skip_serializing_if = "Option::is_none")]
201 pub client: Option<Client>,
202
203 #[serde(rename = "teams")]
204 #[serde(skip_serializing_if = "Option::is_none")]
205 pub teams: Option<Teams>,
206
207 #[serde(rename = "sipExtension")]
208 #[serde(skip_serializing_if = "Option::is_none")]
209 pub sip_extension: Option<SipExtension>,
210
211 #[serde(rename = "sipGateway")]
212 #[serde(skip_serializing_if = "Option::is_none")]
213 pub sip_gateway: Option<SipGateway>,
214
215 #[serde(rename = "remote")]
216 #[serde(skip_serializing_if = "Option::is_none")]
217 pub remote: Option<Remote>,
218
219 #[serde(rename = "voicemail")]
220 #[serde(skip_serializing_if = "Option::is_none")]
221 pub voice_mail: Option<VoiceMail>,
222
223 #[serde(rename = "queue")]
224 #[serde(skip_serializing_if = "Option::is_none")]
225 pub queue: Option<Queue>,
226
227 #[serde(rename = "plugin")]
228 #[serde(skip_serializing_if = "Option::is_none")]
229 pub plugin: Option<Plugin>,
230
231 #[serde(rename = "service")]
232 #[serde(skip_serializing_if = "Option::is_none")]
233 pub service: Option<Service>,
234
235 #[serde(rename = "play")]
236 #[serde(skip_serializing_if = "Option::is_none")]
237 pub play: Option<Play>,
238
239 #[serde(rename = "say")]
240 #[serde(skip_serializing_if = "Option::is_none")]
241 pub say: Option<Say>,
242
243 #[serde(rename = "script")]
244 #[serde(skip_serializing_if = "Option::is_none")]
245 pub script: Option<Script>,
246
247 #[serde(rename = "email")]
248 #[serde(skip_serializing_if = "Option::is_none")]
249 pub email: Option<Email>,
250
251 #[serde(rename = "sms")]
252 #[serde(skip_serializing_if = "Option::is_none")]
253 pub sms: Option<Sms>,
254
255 #[serde(rename = "tag")]
256 #[serde(skip_serializing_if = "Option::is_none")]
257 pub tag: Option<Tag>,
258
259 #[serde(rename = "event")]
260 #[serde(skip_serializing_if = "Option::is_none")]
261 pub event: Option<Event>,
262
263 #[serde(rename = "whatsAppRoute")]
264 #[serde(skip_serializing_if = "Option::is_none")]
265 pub whats_app_flow: Option<WhatsAppFlow>,
266
267 #[serde(rename = "messagePlugin")]
268 #[serde(skip_serializing_if = "Option::is_none")]
269 pub message_plugin: Option<MessagePlugin>,
270
271 #[serde(rename = "messageText")]
272 #[serde(skip_serializing_if = "Option::is_none")]
273 pub message_text: Option<MessageText>,
274
275 #[serde(rename = "messageButtons")]
276 #[serde(skip_serializing_if = "Option::is_none")]
277 pub message_buttons: Option<MessageButtons>,
278
279 #[serde(rename = "messageTemplate")]
280 #[serde(skip_serializing_if = "Option::is_none")]
281 pub message_template: Option<MessageTemplate>,
282
283 #[serde(rename = "messageANIRouter")]
284 #[serde(skip_serializing_if = "Option::is_none")]
285 pub message_ani_router: Option<MessageAniRouter>,
286
287 #[serde(rename = "messageDNISRouter")]
288 #[serde(skip_serializing_if = "Option::is_none")]
289 pub message_dnis_router: Option<MessageDnisRouter>,
290}
291
292fn from_str<'de, D>(deserializer: D) -> Result<u16, D::Error>
293where
294 D: Deserializer<'de>,
295{
296 let value = Value::deserialize(deserializer)?;
297 if value.is_string() {
298 Ok(value.as_str().unwrap().parse().unwrap())
299 } else if value.is_u64() {
300 Ok(value.as_u64().unwrap() as u16)
301 } else if value.is_i64() {
302 Ok(value.as_i64().unwrap() as u16)
303 } else {
304 Err(serde::de::Error::custom("Cannot map extension to u16"))
305 }
306}
307
308impl DeviceStruct {
309 pub fn value(&self) -> Device {
310 match &self.device_type {
311 DeviceType::InboundFlow => Device::InboundFlow(self.clone().start_route.unwrap()),
312 DeviceType::OutboundFlow => Device::OutboundFlow(self.clone().regex_route.unwrap()),
313 DeviceType::WhatsAppFlow => Device::WhatsAppFlow(self.clone().whats_app_flow.unwrap()),
314 DeviceType::AppFlow => Device::AppFlow(self.clone().app_route.unwrap()),
315 DeviceType::AniRouter => Device::AniRouter(self.clone().ani_router.unwrap()),
316 DeviceType::DnisRouter => Device::DnisRouter(self.clone().dnis_router.unwrap()),
317 DeviceType::DigitRouter => Device::DigitRouter(self.clone().number_plan.unwrap()),
318 DeviceType::TimeRangeRouter => {
319 Device::TimeRangeRouter(self.clone().time_range_router.unwrap())
320 }
321 DeviceType::DayOfWeekRouter => {
322 Device::DayOfWeekRouter(self.clone().day_of_week_router.unwrap())
323 }
324 DeviceType::DateRangeRouter => {
325 Device::DateRangeRouter(self.clone().date_range_router.unwrap())
326 }
327 DeviceType::HuntGroup => Device::HuntGroup(self.clone().hunt_group.unwrap()),
328 DeviceType::Client => Device::Client(self.clone().client.unwrap()),
329 DeviceType::Teams => Device::Teams(self.clone().teams.unwrap()),
330 DeviceType::SipExtension => Device::SipExtension(self.clone().sip_extension.unwrap()),
331 DeviceType::SipGateway => Device::SipGateway(self.clone().sip_gateway.unwrap()),
332 DeviceType::Remote => Device::Remote(self.clone().remote.unwrap()),
333 DeviceType::Plugin => Device::Plugin(self.clone().plugin.unwrap()),
334 DeviceType::Play => Device::Play(self.clone().play.unwrap()),
335 DeviceType::Say => Device::Say(self.clone().say.unwrap()),
336 DeviceType::Voicemail => Device::Voicemail(self.clone().voice_mail.unwrap()),
337 DeviceType::Script => Device::Script(self.clone().script.unwrap()),
338 DeviceType::Queue => Device::Queue(self.clone().queue.unwrap()),
339 DeviceType::Sms => Device::Sms(self.clone().sms.unwrap()),
340 DeviceType::Email => Device::Email(self.clone().email.unwrap()),
341 DeviceType::Tag => Device::Tag(self.clone().tag.unwrap()),
342 DeviceType::TagRouter => Device::TagRouter(self.clone().tag_router.unwrap()),
343 DeviceType::MessagePlugin => {
344 Device::MessagePlugin(self.clone().message_plugin.unwrap())
345 }
346 DeviceType::MessageText => Device::MessageText(self.clone().message_text.unwrap()),
347 DeviceType::MessageButtons => {
348 Device::MessageButtons(self.clone().message_buttons.unwrap())
349 }
350 DeviceType::MessageTemplate => {
351 Device::MessageTemplate(self.clone().message_template.unwrap())
352 }
353 DeviceType::MessageAniRouter => {
354 Device::MessageAniRouter(self.clone().message_ani_router.unwrap())
355 }
356 DeviceType::Service => Device::Service(self.clone().service.unwrap()),
357 }
358 }
359
360 pub fn record_options(&self) -> Option<RecordOptions> {
361 match &self.device_type {
362 DeviceType::HuntGroup => Some(self.clone().hunt_group.unwrap().record_options),
363 DeviceType::Client => Some(self.clone().client.unwrap().record_options),
364 DeviceType::Teams => Some(self.clone().teams.unwrap().record_options),
365 DeviceType::SipExtension => Some(self.clone().sip_extension.unwrap().record_options),
366 DeviceType::SipGateway => Some(self.clone().sip_gateway.unwrap().record_options),
367 DeviceType::Remote => Some(self.clone().remote.unwrap().record_options),
368 DeviceType::Plugin => Some(self.clone().plugin.unwrap().record_options),
369 DeviceType::Voicemail => Some(self.clone().voice_mail.unwrap().record_options),
370 _ => None,
371 }
372 }
373
374 pub fn transcribe_options(&self) -> Option<TranscribeOptions> {
375 match &self.device_type {
376 DeviceType::HuntGroup => Some(self.clone().hunt_group.unwrap().transcribe_options),
377 DeviceType::Client => Some(self.clone().client.unwrap().transcribe_options),
378 DeviceType::Teams => Some(self.clone().teams.unwrap().transcribe_options),
379 DeviceType::SipExtension => {
380 Some(self.clone().sip_extension.unwrap().transcribe_options)
381 }
382 DeviceType::SipGateway => Some(self.clone().sip_gateway.unwrap().transcribe_options),
383 DeviceType::Remote => Some(self.clone().remote.unwrap().transcribe_options),
384 DeviceType::Plugin => Some(self.clone().plugin.unwrap().transcribe_options),
385 DeviceType::Voicemail => Some(self.clone().voice_mail.unwrap().transcribe_options),
386 _ => None,
387 }
388 }
389
390 pub fn is_id(&self, _id: &str) -> bool {
391 self.id == _id
392 }
393
394 pub fn is_device_type(&self, device_type: DeviceType) -> bool {
395 self.device_type == device_type
396 }
397
398 pub fn match_device(&self, str: &str) -> bool {
399 let matched = match &self.value() {
400 Device::InboundFlow(v) => v.ddis.contains(&str.to_string()),
401 Device::Client(v) => v.username.eq(&str),
402 Device::SipGateway(v) => v.trunks.contains(&str.to_string()),
403 _ => false,
404 };
405 matched || self.id.eq(&str) || self.extension.to_string().eq(&str)
406 }
407
408 pub fn match_outbound_flow(&self) -> bool {
409 match &self.value() {
410 Device::OutboundFlow(_value) => true,
411 _ => false,
412 }
413 }
414
415 pub fn is_connector(&self) -> bool {
416 vec![
417 DeviceType::InboundFlow,
418 DeviceType::OutboundFlow,
419 DeviceType::AppFlow,
420 DeviceType::WhatsAppFlow,
421 DeviceType::AniRouter,
422 DeviceType::DnisRouter,
423 DeviceType::DigitRouter,
424 DeviceType::TimeRangeRouter,
425 DeviceType::DayOfWeekRouter,
426 DeviceType::DateRangeRouter,
427 DeviceType::Play,
428 DeviceType::Say,
429 DeviceType::Voicemail,
430 DeviceType::Script,
431 DeviceType::Queue,
432 DeviceType::Sms,
433 DeviceType::Email,
434 DeviceType::Tag,
435 DeviceType::TagRouter,
436 DeviceType::Service,
437 ]
438 .contains(&self.device_type)
439 }
440
441 pub fn is_call_handler(&self) -> bool {
442 vec![
443 DeviceType::HuntGroup,
444 DeviceType::Client,
445 DeviceType::Teams,
446 DeviceType::SipExtension,
447 DeviceType::SipGateway,
448 DeviceType::Remote,
449 DeviceType::Plugin,
450 ]
451 .contains(&self.device_type)
452 }
453}
454
455#[derive(Serialize, Deserialize, Clone)]
456#[serde(rename_all = "camelCase")]
457pub struct DeviceTag {
458 #[serde(rename = "type")]
459 pub tag_type: TagType,
460 pub name: String,
461 pub value: String,
462}
463
464#[derive(Serialize, Deserialize, Eq, PartialEq, Clone)]
465#[serde(rename_all = "camelCase")]
466pub enum TagType {
467 Session,
468 Global,
469}
470
471#[derive(Serialize, Deserialize, Clone)]
472#[serde(rename_all = "camelCase")]
473pub struct InboundFlow {
474 #[serde(default)]
475 pub ddis: Vec<String>,
476 #[serde(default = "build_connect_to")]
477 pub connect_to: String,
478}
479
480impl Connector for InboundFlow {
481 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
482 ConnectState::default(&self.connect_to, None)
483 }
484}
485
486#[derive(Serialize, Deserialize, Clone)]
487#[serde(rename_all = "camelCase")]
488pub struct OutboundFlow {
489 pub reg_exp: String,
490 #[serde(default = "build_connect_to")]
491 pub connect_to: String,
492}
493
494impl Connector for OutboundFlow {
495 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
496 ConnectState::default(&self.connect_to, None)
497 }
498}
499
500#[derive(Serialize, Deserialize, Clone)]
501#[serde(rename_all = "camelCase")]
502pub struct WhatsAppFlow {
503 #[serde(default)]
504 pub ddis: Vec<String>,
505 #[serde(default = "build_connect_to")]
506 pub connect_to: String,
507}
508
509impl Connector for WhatsAppFlow {
510 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
511 ConnectState::default(&self.connect_to, None)
512 }
513}
514
515#[derive(Serialize, Deserialize, Clone)]
516#[serde(rename_all = "camelCase")]
517pub struct AppFlow {
518 #[serde(default = "build_connect_to")]
519 pub connect_to: String,
520}
521
522impl Connector for AppFlow {
523 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
524 ConnectState::default(&self.connect_to, None)
525 }
526}
527
528#[derive(Serialize, Deserialize, Clone)]
529#[serde(rename_all = "camelCase")]
530pub struct ANIRouter {
531 #[serde(default)]
532 pub options: Vec<RouterOption>,
533 #[serde(default = "build_connect_to")]
534 pub connect_to: String,
535}
536
537impl ANIRouter {
538 fn get_opts(&mut self) -> Vec<RouterOption> {
539 let opts = &mut self.options.clone();
540 opts.sort_by_key(|o| o.option.chars().count());
541 opts.reverse();
542 opts.clone()
543 }
544}
545
546impl Connector for ANIRouter {
547 fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
548 let str = state.get_paid_or_from();
549 self.get_opts()
550 .iter()
551 .find(|o| o.option.starts_with(str.as_str()))
552 .map(|o| {
553 ConnectState::matched(
554 o.connect_to.as_str(),
555 Some(str.to_string()),
556 Some(o.option.clone()),
557 )
558 })
559 .unwrap_or_else(|| {
560 ConnectState::default(self.connect_to.as_str(), Some(str.to_string()))
561 })
562 }
563}
564
565#[derive(Serialize, Deserialize, Clone)]
566#[serde(rename_all = "camelCase")]
567pub struct DNISRouter {
568 #[serde(default)]
569 pub options: Vec<RouterOption>,
570 #[serde(default = "build_connect_to")]
571 pub connect_to: String,
572}
573
574#[derive(Serialize, Deserialize, Clone)]
575#[serde(rename_all = "camelCase")]
576pub struct ZoneRouter {
577 #[serde(default)]
578 pub options: Vec<RouterOption>,
579 #[serde(default = "build_connect_to")]
580 pub connect_to: String,
581}
582
583impl DNISRouter {
584 fn get_opts(&mut self) -> Vec<RouterOption> {
585 let opts = &mut self.options.clone();
586 opts.sort_by_key(|o| o.option.chars().count());
587 opts.reverse();
588 opts.clone()
589 }
590}
591impl Connector for DNISRouter {
592 fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
593 let str = state.get_to();
594 self.get_opts()
595 .iter()
596 .find(|o| o.option.starts_with(str.as_str()))
597 .map(|o| {
598 ConnectState::matched(
599 o.connect_to.as_str(),
600 Some(str.to_string()),
601 Some(o.option.clone()),
602 )
603 })
604 .unwrap_or_else(|| {
605 ConnectState::default(self.connect_to.as_str(), Some(str.to_string()))
606 })
607 }
608}
609
610#[derive(Serialize, Deserialize, Clone)]
611#[serde(rename_all = "camelCase")]
612pub struct DigitRouter {
613 pub text: String,
614 #[serde(rename = "ttsLanguage")]
615 #[serde(default = "build_tts_voice")]
616 pub tts_voice: String,
617 #[serde(default = "build_finish_key")]
618 pub finish_on_key: String,
619 #[serde(default = "build_connect_to")]
620 pub connect_to: String,
621 #[serde(default)]
622 pub options: Vec<RouterOption>,
623 #[serde(default = "build_digit_timeout")]
624 pub timeout: u8,
625 #[serde(default = "build_max_digits")]
626 pub max_digits: u8,
627}
628
629impl DigitRouter {
630 fn get_opts(&mut self) -> Vec<RouterOption> {
631 let opts = &mut self.options.clone();
632 opts.sort_by_key(|o| o.option.chars().count());
633 opts.reverse();
634 opts.clone()
635 }
636}
637impl Connector for DigitRouter {
638 fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
639 match &state.get_digits() {
640 Some(d) => self
641 .get_opts()
642 .iter()
643 .find(|o| o.option.eq(d.as_str()))
644 .map(|o| {
645 ConnectState::matched(
646 &o.connect_to.to_string(),
647 Some(d.to_string()),
648 Some(o.option.clone()),
649 )
650 })
651 .unwrap_or_else(|| {
652 ConnectState::default(&self.connect_to.to_string(), Some(d.to_string()))
653 }),
654 None => ConnectState::default(
655 &self.connect_to.to_string(),
656 Some(self.connect_to.to_string()),
657 ),
658 }
659 }
660}
661
662pub trait Endpoint {
663 fn get_caller_id(&self, state: &FlowState) -> String {
664 state.initial_request.from.clone()
665 }
666 fn get_called_id(&self, state: &FlowState) -> String {
667 state.initial_request.to.clone()
668 }
669 fn get_listen(&self, state: &FlowState) -> Option<Listen>;
670 fn get_proxy(&self, _state: &FlowState) -> Option<VoiceServer> {
671 None
672 }
673 fn get_transcribe(&self, _state: &FlowState) -> Option<TranscribeDial> {
674 None
675 }
676}
677
678#[derive(Serialize, Deserialize, Clone)]
679#[serde(rename_all = "camelCase")]
680pub struct Plugin {
681 pub plugin: String,
683 pub data: String,
684 #[serde(default = "build_present")]
685 pub present: String,
686 #[serde(default = "build_country_code")]
687 pub country_code: String,
688 #[serde(default = "build_ring_time")]
689 pub ring_time: u8,
690 #[serde(default = "build_call_time")]
691 pub max_call_time: u16,
692 #[serde(default = "build_connect_to")]
693 pub on_transfer: String,
694 #[serde(default = "build_connect_to")]
695 pub on_error: String,
696 #[serde(default = "build_connect_to")]
697 pub on_complete: String,
698 #[serde(default = "build_connect_to")]
699 pub on_busy: String,
700 #[serde(default = "build_connect_to")]
701 pub on_fail: String,
702 #[serde(default = "build_connect_to")]
703 pub on_no_answer: String,
704 #[serde(default)]
705 pub record_options: RecordOptions,
706 #[serde(default)]
707 pub transcribe_options: TranscribeOptions,
708 #[serde(default)]
709 pub ai_options: AiOptions,
710 #[serde(default)]
711 pub call_control: CallControl,
712}
713
714impl Connector for Plugin {
715 fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
716 match &state.get_dial_status() {
717 Some(status) => match status {
718 SIPStatus::Ok => ConnectState::complete(self.on_complete.as_str()),
719 SIPStatus::RequestTerminated => ConnectState::no_answer(self.on_no_answer.as_str()),
720 SIPStatus::BusyHere | SIPStatus::BusyEverywhere => {
721 ConnectState::busy(self.on_busy.as_str())
722 }
723 _ => ConnectState::fail(self.on_fail.as_str()),
724 },
725 None => ConnectState::dialling(),
726 }
727 }
728}
729
730#[derive(Serialize, Deserialize, Clone)]
731#[serde(rename_all = "camelCase")]
732pub struct Play {
733 pub url: String,
734 pub connect_to: String,
735}
736
737impl Connector for Play {
738 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
739 ConnectState::default(&self.connect_to, None)
740 }
741}
742
743#[derive(Serialize, Deserialize, Clone)]
744#[serde(rename_all = "camelCase")]
745pub struct Say {
746 pub text: String,
747 #[serde(rename = "ttsLanguage")]
748 #[serde(default = "build_tts_voice")]
749 pub tts_voice: String,
750 #[serde(default = "build_connect_to")]
751 pub connect_to: String,
752}
753
754impl Connector for Say {
755 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
756 ConnectState::default(&self.connect_to, None)
757 }
758}
759
760#[derive(Serialize, Deserialize, Clone)]
761#[serde(rename_all = "camelCase")]
762pub struct VoiceMail {
763 pub text: String,
764 #[serde(rename = "ttsLanguage")]
765 #[serde(default = "build_tts_voice")]
766 pub tts_voice: String,
767 #[serde(default = "build_vm_finish_key")]
768 pub finish_on_key: String,
769 #[serde(default)]
770 pub email_recipients: Vec<String>,
771 #[serde(default = "build_vm_timeout")]
772 pub timeout: u8,
773 #[serde(default = "build_vm_max_length")]
774 pub max_length: u8,
775 #[serde(default)]
776 pub transcribe_options: TranscribeOptions,
777 #[serde(default)]
778 pub record_options: RecordOptions,
779 #[serde(default)]
780 pub play_beep: bool,
781 #[serde(default = "build_connect_to")]
782 pub connect_to: String,
783}
784
785impl Connector for VoiceMail {
786 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
787 ConnectState::default(&self.connect_to, None)
788 }
789}
790
791#[derive(Serialize, Deserialize, Clone)]
792#[serde(rename_all = "camelCase")]
793pub struct TimeRangeRouter {
794 start: DateTime,
795 end: DateTime,
796 #[serde(default = "build_default_timezone")]
797 pub timezone: String,
798 #[serde(default = "build_connect_to")]
799 pub on_match: String,
800 #[serde(default = "build_connect_to")]
801 pub connect_to: String,
802}
803
804impl Connector for TimeRangeRouter {
805 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
806 let now = Local::now().naive_utc().time();
807 let start = self.start.to_chrono().naive_utc().time();
808 let end = self.end.to_chrono().naive_utc().time();
809 let within = now < end && now > start;
810 if within {
811 ConnectState::matched(self.on_match.as_str(), Some(now.to_string()), None)
812 } else {
813 ConnectState::default(self.on_match.as_str(), Some(now.to_string()))
814 }
815 }
816}
817
818#[derive(Serialize, Deserialize, Clone)]
819#[serde(rename_all = "camelCase")]
820pub struct DayOfWeekRouter {
821 #[serde(default)]
822 pub days: Vec<u32>,
823 #[serde(default = "build_default_timezone")]
824 pub timezone: String,
825 #[serde(default = "build_connect_to")]
826 pub on_match: String,
827 #[serde(default = "build_connect_to")]
828 pub connect_to: String,
829}
830
831impl Connector for DayOfWeekRouter {
832 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
833 let now = Local::now().naive_local();
834 let within = self.days.contains(&now.day());
835 if within {
836 ConnectState::matched(self.on_match.as_str(), Some(now.to_string()), None)
837 } else {
838 ConnectState::default(self.connect_to.as_str(), Some(now.to_string()))
839 }
840 }
841}
842
843#[derive(Serialize, Deserialize, Clone)]
844#[serde(rename_all = "camelCase")]
845pub struct DateRangeRouter {
846 start: DateTime,
847 end: DateTime,
848 #[serde(default = "build_default_timezone")]
849 pub timezone: String,
850 #[serde(default = "build_connect_to")]
851 pub on_match: String,
852 #[serde(default = "build_connect_to")]
853 pub connect_to: String,
854}
855
856impl Connector for DateRangeRouter {
857 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
858 let now = Utc::now().naive_utc();
859 let start = self.start.to_chrono().naive_utc();
860 let end = self.end.to_chrono().naive_utc();
861 let within = now < end && now > start;
862 if within {
863 ConnectState::matched(self.on_match.as_str(), Some(now.to_string()), None)
864 } else {
865 ConnectState::default(self.connect_to.as_str(), Some(now.to_string()))
866 }
867 }
868}
869
870#[derive(Serialize, Deserialize, Clone)]
871#[serde(rename_all = "camelCase")]
872pub struct Script {
873 pub code: String,
874 #[serde(default = "build_connect_to")]
875 pub connect_to: String,
876}
877
878impl Connector for Script {
879 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
880 ConnectState::default(&self.connect_to, None)
881 }
882}
883
884#[derive(Serialize, Deserialize, Clone)]
885#[serde(rename_all = "camelCase")]
886pub struct Queue {
887 #[serde(default = "build_connect_to")]
888 pub connect_to: String,
889 }
898
899impl Connector for Queue {
901 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
902 ConnectState::default(&self.connect_to, None)
903 }
904}
905
906#[derive(Serialize, Deserialize, Clone)]
907#[serde(rename_all = "camelCase")]
908pub struct QueueItem {
909 pub text: String,
910 #[serde(rename = "type")]
911 pub item_type: QueueItemType,
912}
913
914#[derive(Serialize, Deserialize, Clone)]
915#[serde(rename_all = "camelCase")]
916pub struct Email {
917 #[serde(default = "build_connect_to")]
918 pub connect_to: String,
919}
920
921impl Connector for Email {
922 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
923 ConnectState::default(&self.connect_to, None)
924 }
925}
926
927#[derive(Serialize, Deserialize, Clone)]
928#[serde(rename_all = "camelCase")]
929pub struct Sms {
930 #[serde(default = "build_connect_to")]
931 pub connect_to: String,
932}
933
934impl Connector for Sms {
935 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
936 ConnectState::default(&self.connect_to, None)
937 }
938}
939
940#[derive(Serialize, Deserialize, Clone)]
941#[serde(rename_all = "camelCase")]
942pub struct Tag {
943 #[serde(default = "build_connect_to")]
944 pub connect_to: String,
945}
946
947impl Connector for Tag {
948 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
949 ConnectState::default(&self.connect_to, None)
950 }
951}
952
953#[derive(Serialize, Deserialize, Clone)]
954#[serde(rename_all = "camelCase")]
955pub struct TagRouter {
956 #[serde(default = "build_connect_to")]
957 pub connect_to: String,
958}
959
960impl Connector for TagRouter {
961 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
962 ConnectState::default(&self.connect_to, None)
963 }
964}
965
966#[derive(Serialize, Deserialize, Clone)]
967#[serde(rename_all = "camelCase")]
968pub struct Service {
969 #[serde(default = "build_connect_to")]
970 pub connect_to: String,
971}
972
973impl Connector for Service {
974 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
975 ConnectState::default(&self.connect_to, None)
976 }
977}
978
979#[derive(Serialize, Deserialize, Clone)]
980#[serde(rename_all = "camelCase")]
981pub struct MessagePlugin {
982 #[serde(default = "build_connect_to")]
983 pub connect_to: String,
984}
985
986impl Connector for MessagePlugin {
987 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
988 ConnectState::default(&self.connect_to, None)
989 }
990}
991
992#[derive(Serialize, Deserialize, Clone)]
993#[serde(rename_all = "camelCase")]
994pub struct MessageText {
995 #[serde(default = "build_connect_to")]
996 pub connect_to: String,
997}
998
999#[derive(Serialize, Deserialize, Clone)]
1000#[serde(rename_all = "camelCase")]
1001pub struct MessageButtons {
1002 #[serde(default = "build_connect_to")]
1003 pub connect_to: String,
1004}
1005
1006#[derive(Serialize, Deserialize, Clone)]
1007#[serde(rename_all = "camelCase")]
1008pub struct MessageTemplate {
1009 #[serde(default = "build_connect_to")]
1010 pub connect_to: String,
1011}
1012
1013#[derive(Serialize, Deserialize, Clone)]
1014#[serde(rename_all = "camelCase")]
1015pub struct MessageAniRouter {
1016 #[serde(default = "build_connect_to")]
1017 pub connect_to: String,
1018}
1019
1020#[derive(Serialize, Deserialize, Clone)]
1021#[serde(rename_all = "camelCase")]
1022pub struct MessageDnisRouter {
1023 #[serde(default = "build_connect_to")]
1024 pub connect_to: String,
1025}
1026
1027impl Connector for MessageText {
1028 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
1029 ConnectState::default(&self.connect_to, None)
1030 }
1031}
1032#[derive(Serialize, Deserialize, Clone)]
1033#[serde(rename_all = "camelCase")]
1034pub struct Event {
1035 #[serde(default = "build_connect_to")]
1036 pub connect_to: String,
1037}
1038impl Connector for Event {
1039 fn get_connect_to(&mut self, _state: &mut FlowState) -> ConnectState {
1040 ConnectState::default(&self.connect_to, None)
1041 }
1042}
1043
1044#[derive(Serialize, Deserialize, Clone)]
1045#[serde(rename_all = "camelCase")]
1046pub struct MapBox {
1047 #[serde(default)]
1048 pub bounds: MapBoxBoundary,
1049 #[serde(default)]
1050 pub features: Vec<MapBoxFeature>,
1051}
1052
1053#[derive(Serialize, Deserialize, Clone)]
1054#[serde(rename_all = "camelCase")]
1055pub struct MapBoxBoundary {
1056 pub xmin: f32,
1057 pub ymin: f32,
1058 pub xmax: f32,
1059 pub ymax: f32,
1060}
1061
1062impl Default for MapBoxBoundary {
1063 fn default() -> Self {
1064 Self {
1065 xmin: 0.00,
1066 ymin: 1.00,
1067 xmax: 0.01,
1068 ymax: 1.01,
1069 }
1070 }
1071}
1072
1073#[derive(Serialize, Deserialize, Clone)]
1074#[serde(rename_all = "camelCase")]
1075pub struct MapBoxFeature {
1076 pub id: String,
1077 #[serde(rename = "type")]
1078 pub feature_type: String,
1079 pub geometry: MapBoxGeometry,
1080}
1081
1082#[derive(Serialize, Deserialize, Clone)]
1083#[serde(rename_all = "camelCase")]
1084pub struct MapBoxGeometry {
1085 #[serde(rename = "type")]
1086 pub geometry_type: String,
1087 pub coordinates: Vec<Vec<(f32, f32)>>,
1088}
1089
1090#[derive(Serialize, Deserialize, Clone)]
1091#[serde(rename_all = "camelCase")]
1092pub struct RouterOption {
1093 pub option: String,
1094 #[serde(default = "build_connect_to")]
1095 pub connect_to: String,
1096}
1097
1098#[derive(Serialize, Deserialize, Clone)]
1099pub struct TranscribeOptions {
1100 pub enabled: bool,
1101 pub language: AsrVendor,
1102}
1103
1104impl Default for TranscribeOptions {
1105 fn default() -> Self {
1106 Self {
1107 enabled: false,
1108 language: AsrVendor::Google,
1109 }
1110 }
1111}
1112
1113#[derive(Serialize, Deserialize, Clone)]
1114#[serde(rename_all = "camelCase")]
1115pub struct RecordOptions {
1116 #[serde(default = "build_record")]
1117 pub enabled: bool,
1118 #[serde(default = "build_record_retention")]
1119 pub retention: String,
1120 #[serde(default = "build_mix_type")]
1121 pub mix_type: MixType,
1122 #[serde(default = "build_sample_rate")]
1123 pub sample_rate: SampleRate,
1124}
1125
1126impl Default for RecordOptions {
1127 fn default() -> Self {
1128 Self {
1129 enabled: false,
1130 retention: String::from(DEFAULT_RECORDING_RETENTION),
1131 mix_type: MixType::Stereo,
1132 sample_rate: SampleRate::SR8000,
1133 }
1134 }
1135}
1136
1137#[derive(Serialize, Deserialize, Clone)]
1138pub struct AiOptions {
1139 pub transcribe: bool,
1140 pub summary: bool,
1141 pub recognizer: Option<Recognizer>,
1142}
1143
1144impl Default for AiOptions {
1145 fn default() -> Self {
1146 Self {
1147 transcribe: false,
1148 summary: false,
1149 recognizer: None,
1150 }
1151 }
1152}
1153
1154#[derive(Serialize, Deserialize, Clone)]
1155pub struct CallControl {
1156 enabled: bool,
1157 channels: u8,
1158 stats: bool,
1159 action: CacAction,
1160}
1161
1162impl Default for CallControl {
1163 fn default() -> Self {
1164 CallControl {
1165 enabled: false,
1166 channels: 0,
1167 stats: false,
1168 action: CacAction::Warn,
1169 }
1170 }
1171}
1172
1173#[derive(Serialize, Deserialize, Clone)]
1174#[serde(rename_all = "camelCase")]
1175pub enum CacAction {
1176 Warn,
1177 Deny,
1178}
1179pub fn build_record() -> bool {
1180 false
1181}
1182
1183pub fn build_record_retention() -> String {
1184 String::from(DEFAULT_RECORDING_RETENTION)
1185}
1186
1187pub fn build_mix_type() -> MixType {
1188 MixType::Stereo
1189}
1190
1191pub fn build_sample_rate() -> SampleRate {
1192 SampleRate::SR8000
1193}
1194
1195pub fn build_connect_to() -> String {
1196 String::from(HANG_UP_CONNECT)
1197}
1198
1199pub fn build_tts_voice() -> String {
1200 String::from(DEFAULT_TTS_VOICE)
1201}
1202
1203pub fn build_vm_finish_key() -> String {
1204 String::from(DEFAULT_VM_FINISH_KEY)
1205}
1206
1207pub fn build_default_timezone() -> String {
1208 String::from(DEFAULT_TIMEZONE)
1209}
1210
1211pub fn build_vm_timeout() -> u8 {
1212 DEFAULT_VM_TIMEOUT
1213}
1214
1215pub fn build_vm_max_length() -> u8 {
1216 DEFAULT_VM_MAX_LENGTH
1217}
1218
1219pub fn build_present() -> String {
1220 String::from(DEFAULT_ENDPOINT_PRESENT)
1221}
1222
1223pub fn build_destination() -> String {
1224 String::from(DEFAULT_REMOTE_DESTINATION)
1225}
1226
1227pub fn build_format() -> NumberFormat {
1228 NumberFormat::National
1229}
1230
1231pub fn build_client_profile() -> ClientProfile {
1232 ClientProfile::GenericE164Plus
1233}
1234
1235pub fn build_country_code() -> String {
1236 String::from(DEFAULT_COUNTRY_CODE)
1237}
1238
1239pub fn build_finish_key() -> String {
1240 String::from(DEFAULT_DIGITS_FINISH_KEY)
1241}
1242
1243pub fn build_call_time() -> u16 {
1244 DEFAULT_CALL_TIME
1245}
1246
1247pub fn build_ring_time() -> u8 {
1248 DEFAULT_RING_TIME
1249}
1250
1251pub fn build_digit_timeout() -> u8 {
1252 DEFAULT_DIGIT_TIMEOUT
1253}
1254
1255pub fn build_max_digits() -> u8 {
1256 DEFAULT_MAX_DIGITS
1257}