1use crate::{
2 media::{recorder::RecorderOption, track::media_pass::MediaPassOption, vad::VADOption},
3 synthesis::SynthesisOption,
4 transcription::TranscriptionOption,
5};
6use anyhow::Result;
7use rsipstack::dialog::{authenticate::Credential, invitation::InviteOption};
8use serde::{Deserialize, Serialize};
9use serde_with::skip_serializing_none;
10use std::collections::HashMap;
11
12pub mod event;
13pub mod media;
14pub mod net_tool;
15pub mod synthesis;
16pub mod transcription;
17
18#[derive(Default, Debug, Serialize, Deserialize, Clone)]
19pub struct IceServer {
20 pub urls: Vec<String>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub username: Option<String>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub credential: Option<String>,
25}
26
27#[derive(Debug, Deserialize, Serialize, Default, Clone)]
28#[serde(default)]
29pub struct SipOption {
30 pub username: Option<String>,
31 pub password: Option<String>,
32 pub realm: Option<String>,
33 pub headers: Option<HashMap<String, String>>,
34}
35
36#[skip_serializing_none]
37#[derive(Debug, Deserialize, Serialize, Clone)]
38#[serde(rename_all = "camelCase")]
39pub struct CallOption {
40 pub denoise: Option<bool>,
41 pub offer: Option<String>,
42 pub callee: Option<String>,
43 pub caller: Option<String>,
44 pub recorder: Option<RecorderOption>,
45 pub vad: Option<VADOption>,
46 pub asr: Option<TranscriptionOption>,
47 pub tts: Option<SynthesisOption>,
48 pub media_pass: Option<MediaPassOption>,
49 pub handshake_timeout: Option<String>,
50 pub enable_ipv6: Option<bool>,
51 pub sip: Option<SipOption>,
52 pub extra: Option<HashMap<String, String>>,
53 pub codec: Option<String>, pub eou: Option<EouOption>,
55}
56
57impl Default for CallOption {
58 fn default() -> Self {
59 Self {
60 denoise: None,
61 offer: None,
62 callee: None,
63 caller: None,
64 recorder: None,
65 asr: None,
66 vad: None,
67 tts: None,
68 media_pass: None,
69 handshake_timeout: None,
70 enable_ipv6: None,
71 sip: None,
72 extra: None,
73 codec: None,
74 eou: None,
75 }
76 }
77}
78
79impl CallOption {
80 pub fn check_default(&mut self) {
81 if let Some(tts) = &mut self.tts {
82 tts.check_default();
83 }
84 if let Some(asr) = &mut self.asr {
85 asr.check_default();
86 }
87 }
88
89 pub fn build_invite_option(&self) -> Result<InviteOption> {
90 let mut invite_option = InviteOption::default();
91 if let Some(offer) = &self.offer {
92 invite_option.offer = Some(offer.clone().into());
93 }
94 if let Some(callee) = &self.callee {
95 invite_option.callee = callee.clone().try_into()?;
96 }
97 if let Some(caller) = &self.caller {
98 invite_option.caller = caller.clone().try_into()?;
99 invite_option.contact = invite_option.caller.clone();
100 }
101
102 if let Some(sip) = &self.sip {
103 invite_option.credential = Some(Credential {
104 username: sip.username.clone().unwrap_or_default(),
105 password: sip.password.clone().unwrap_or_default(),
106 realm: sip.realm.clone(),
107 });
108 invite_option.headers = sip.headers.as_ref().map(|h| {
109 h.iter()
110 .map(|(k, v)| rsip::Header::Other(k.clone(), v.clone()))
111 .collect::<Vec<_>>()
112 });
113 }
114 Ok(invite_option)
115 }
116}
117
118#[skip_serializing_none]
119#[derive(Debug, Deserialize, Serialize, Clone)]
120#[serde(rename_all = "camelCase")]
121pub struct ReferOption {
122 pub denoise: Option<bool>,
123 pub timeout: Option<u32>,
124 pub moh: Option<String>,
125 pub asr: Option<TranscriptionOption>,
126 pub auto_hangup: Option<bool>,
128 pub sip: Option<SipOption>,
129}
130
131#[skip_serializing_none]
132#[derive(Clone, Debug, Deserialize, Serialize)]
133#[serde(rename_all = "camelCase")]
134pub struct EouOption {
135 pub r#type: Option<String>,
136 pub endpoint: Option<String>,
137 pub secret_key: Option<String>,
138 pub secret_id: Option<String>,
139 pub timeout: Option<u32>,
141 pub extra: Option<HashMap<String, String>>,
142}