1use crate::device::device::{
2 AiOptions, CallControl, Connector, Endpoint, RecordOptions, TagType, TranscribeOptions,
3};
4use crate::device::utils::{get_caller_id, get_listen, get_transcribe};
5use crate::{ConnectState, FlowState, NumberFormat, VoiceServer, format_number};
6use cal_jambonz::dial::TranscribeDial;
7use cal_jambonz::listen::Listen;
8use cal_jambonz::shared::shared::SIPStatus;
9use serde::{Deserialize, Serialize};
10
11#[derive(Serialize, Deserialize, Clone)]
12#[serde(rename_all = "camelCase")]
13pub struct Teams {
14 pub to: String,
15 #[serde(default = "crate::device::device::build_present")]
16 pub present: String,
17 #[serde(default = "crate::device::device::build_country_code")]
18 pub country_code: String,
19 #[serde(default = "crate::device::device::build_connect_to")]
20 pub on_complete: String,
21 #[serde(default = "crate::device::device::build_connect_to")]
22 pub on_busy: String,
23 #[serde(default = "crate::device::device::build_connect_to")]
24 pub on_fail: String,
25 #[serde(default = "crate::device::device::build_connect_to")]
26 pub on_no_answer: String,
27 #[serde(default = "crate::device::device::build_ring_time")]
28 pub ring_time: u8,
29 #[serde(default = "crate::device::device::build_call_time")]
30 pub max_call_time: u16,
31 #[serde(default)]
32 pub transcribe_options: TranscribeOptions,
33 #[serde(default)]
34 pub record_options: RecordOptions,
35 #[serde(default)]
36 pub ai_options: AiOptions,
37 #[serde(default)]
38 pub call_control: CallControl,
39}
40
41impl Connector for Teams {
42 fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
43 match &state.get_dial_status() {
44 Some(status) => match status {
45 SIPStatus::Ok => ConnectState::complete(self.on_complete.as_str()),
46 SIPStatus::RequestTerminated => ConnectState::no_answer(self.on_no_answer.as_str()),
47 SIPStatus::BusyHere | SIPStatus::BusyEverywhere => {
48 ConnectState::busy(self.on_busy.as_str())
49 }
50 _ => ConnectState::fail(self.on_fail.as_str()),
51 },
52 None => ConnectState::dialling(),
53 }
54 }
55}
56
57impl Endpoint for Teams {
58 fn get_caller_id(&self, state: &FlowState) -> String {
59 if self.present == "pass-through" {
60 get_caller_id(&NumberFormat::E164Plus, state)
61 } else {
62 format_number(
63 &self.present,
64 state.get_country_code(),
65 NumberFormat::E164Plus.clone(),
66 )
67 }
68 }
69
70 fn get_called_id(&self, state: &FlowState) -> String {
71 let mut destination = self.to.clone();
72 for (key, value) in state.data.clone() {
73 if value.tag_type == TagType::Session {
74 let formatted = format_number(
75 value.value.clone().as_str(),
76 state.get_country_code(),
77 NumberFormat::E164Plus,
78 );
79 let replace = format!("[request.{}]", key);
80 destination = destination.replace(replace.as_str(), formatted.as_str());
81 }
82 }
83 destination.clone()
84 }
85
86 fn get_listen(&self, state: &FlowState) -> Option<Listen> {
87 get_listen(&self.record_options, self.ai_options.clone(), state)
88 }
89
90 fn get_proxy(&self, state: &FlowState) -> Option<VoiceServer> {
91 let mut voice_server: Option<VoiceServer> = None;
92 if state.account.teams.domain != "" {
93 for region in state.regions.iter() {
94 for vs in ®ion.voice_servers {
95 if vs.public_ip == state.account.cluster_settings.server_a {
96 voice_server = Some(vs.clone());
97 }
98 }
99 }
100 }
101 voice_server
102 }
103
104 fn get_transcribe(&self, _state: &FlowState) -> Option<TranscribeDial> {
105 get_transcribe(self.transcribe_options.clone())
106 }
107}