1use livekit_protocol as proto;
16use std::collections::HashMap;
17
18use super::{ServiceBase, ServiceResult, LIVEKIT_PACKAGE};
19use crate::{access_token::VideoGrants, get_env_keys, services::twirp_client::TwirpClient};
20
21const SVC: &str = "Connector";
22
23#[derive(Default, Clone, Debug)]
25pub struct DialWhatsAppCallOptions {
26 pub biz_opaque_callback_data: Option<String>,
28 pub room_name: Option<String>,
30 pub agents: Option<Vec<proto::RoomAgentDispatch>>,
32 pub participant_identity: Option<String>,
34 pub participant_name: Option<String>,
36 pub participant_metadata: Option<String>,
38 pub participant_attributes: Option<HashMap<String, String>>,
40 pub destination_country: Option<String>,
42}
43
44#[derive(Default, Clone, Debug)]
46pub struct AcceptWhatsAppCallOptions {
47 pub biz_opaque_callback_data: Option<String>,
49 pub room_name: Option<String>,
51 pub agents: Option<Vec<proto::RoomAgentDispatch>>,
53 pub participant_identity: Option<String>,
55 pub participant_name: Option<String>,
57 pub participant_metadata: Option<String>,
59 pub participant_attributes: Option<HashMap<String, String>>,
61 pub destination_country: Option<String>,
63}
64
65#[derive(Default, Clone, Debug)]
67pub struct ConnectTwilioCallOptions {
68 pub agents: Option<Vec<proto::RoomAgentDispatch>>,
70 pub participant_identity: Option<String>,
72 pub participant_name: Option<String>,
74 pub participant_metadata: Option<String>,
76 pub participant_attributes: Option<HashMap<String, String>>,
78 pub destination_country: Option<String>,
80}
81
82#[derive(Debug)]
83pub struct ConnectorClient {
84 base: ServiceBase,
85 client: TwirpClient,
86}
87
88impl ConnectorClient {
89 pub fn with_api_key(host: &str, api_key: &str, api_secret: &str) -> Self {
90 Self {
91 base: ServiceBase::with_api_key(api_key, api_secret),
92 client: TwirpClient::new(host, LIVEKIT_PACKAGE, None),
93 }
94 }
95
96 pub fn new(host: &str) -> ServiceResult<Self> {
97 let (api_key, api_secret) = get_env_keys()?;
98 Ok(Self::with_api_key(host, &api_key, &api_secret))
99 }
100
101 pub async fn dial_whatsapp_call(
113 &self,
114 phone_number_id: impl Into<String>,
115 to_phone_number: impl Into<String>,
116 api_key: impl Into<String>,
117 cloud_api_version: impl Into<String>,
118 options: DialWhatsAppCallOptions,
119 ) -> ServiceResult<proto::DialWhatsAppCallResponse> {
120 self.client
121 .request(
122 SVC,
123 "DialWhatsAppCall",
124 proto::DialWhatsAppCallRequest {
125 whatsapp_phone_number_id: phone_number_id.into(),
126 whatsapp_to_phone_number: to_phone_number.into(),
127 whatsapp_api_key: api_key.into(),
128 whatsapp_cloud_api_version: cloud_api_version.into(),
129 whatsapp_biz_opaque_callback_data: options
130 .biz_opaque_callback_data
131 .unwrap_or_default(),
132 room_name: options.room_name.unwrap_or_default(),
133 agents: options.agents.unwrap_or_default(),
134 participant_identity: options.participant_identity.unwrap_or_default(),
135 participant_name: options.participant_name.unwrap_or_default(),
136 participant_metadata: options.participant_metadata.unwrap_or_default(),
137 participant_attributes: options.participant_attributes.unwrap_or_default(),
138 destination_country: options.destination_country.unwrap_or_default(),
139 ringing_timeout: Default::default(),
140 },
141 self.base
142 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
143 )
144 .await
145 .map_err(Into::into)
146 }
147
148 pub async fn disconnect_whatsapp_call(
157 &self,
158 call_id: impl Into<String>,
159 api_key: impl Into<String>,
160 ) -> ServiceResult<proto::DisconnectWhatsAppCallResponse> {
161 self.client
162 .request(
163 SVC,
164 "DisconnectWhatsAppCall",
165 proto::DisconnectWhatsAppCallRequest {
166 whatsapp_call_id: call_id.into(),
167 whatsapp_api_key: api_key.into(),
168 ..Default::default()
169 },
170 self.base
171 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
172 )
173 .await
174 .map_err(Into::into)
175 }
176
177 pub async fn connect_whatsapp_call(
186 &self,
187 call_id: impl Into<String>,
188 sdp: proto::SessionDescription,
189 ) -> ServiceResult<proto::ConnectWhatsAppCallResponse> {
190 self.client
191 .request(
192 SVC,
193 "ConnectWhatsAppCall",
194 proto::ConnectWhatsAppCallRequest {
195 whatsapp_call_id: call_id.into(),
196 sdp: Some(sdp),
197 },
198 self.base
199 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
200 )
201 .await
202 .map_err(Into::into)
203 }
204
205 pub async fn accept_whatsapp_call(
218 &self,
219 phone_number_id: impl Into<String>,
220 api_key: impl Into<String>,
221 cloud_api_version: impl Into<String>,
222 call_id: impl Into<String>,
223 sdp: proto::SessionDescription,
224 options: AcceptWhatsAppCallOptions,
225 ) -> ServiceResult<proto::AcceptWhatsAppCallResponse> {
226 self.client
227 .request(
228 SVC,
229 "AcceptWhatsAppCall",
230 proto::AcceptWhatsAppCallRequest {
231 whatsapp_phone_number_id: phone_number_id.into(),
232 whatsapp_api_key: api_key.into(),
233 whatsapp_cloud_api_version: cloud_api_version.into(),
234 whatsapp_call_id: call_id.into(),
235 whatsapp_biz_opaque_callback_data: options
236 .biz_opaque_callback_data
237 .unwrap_or_default(),
238 sdp: Some(sdp),
239 room_name: options.room_name.unwrap_or_default(),
240 agents: options.agents.unwrap_or_default(),
241 participant_identity: options.participant_identity.unwrap_or_default(),
242 participant_name: options.participant_name.unwrap_or_default(),
243 participant_metadata: options.participant_metadata.unwrap_or_default(),
244 participant_attributes: options.participant_attributes.unwrap_or_default(),
245 destination_country: options.destination_country.unwrap_or_default(),
246 ringing_timeout: Default::default(),
247 wait_until_answered: Default::default(),
248 },
249 self.base
250 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
251 )
252 .await
253 .map_err(Into::into)
254 }
255
256 pub async fn connect_twilio_call(
266 &self,
267 direction: proto::connect_twilio_call_request::TwilioCallDirection,
268 room_name: impl Into<String>,
269 options: ConnectTwilioCallOptions,
270 ) -> ServiceResult<proto::ConnectTwilioCallResponse> {
271 self.client
272 .request(
273 SVC,
274 "ConnectTwilioCall",
275 proto::ConnectTwilioCallRequest {
276 twilio_call_direction: direction as i32,
277 room_name: room_name.into(),
278 agents: options.agents.unwrap_or_default(),
279 participant_identity: options.participant_identity.unwrap_or_default(),
280 participant_name: options.participant_name.unwrap_or_default(),
281 participant_metadata: options.participant_metadata.unwrap_or_default(),
282 participant_attributes: options.participant_attributes.unwrap_or_default(),
283 destination_country: options.destination_country.unwrap_or_default(),
284 },
285 self.base
286 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
287 )
288 .await
289 .map_err(Into::into)
290 }
291}