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 },
140 self.base
141 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
142 )
143 .await
144 .map_err(Into::into)
145 }
146
147 pub async fn disconnect_whatsapp_call(
156 &self,
157 call_id: impl Into<String>,
158 api_key: impl Into<String>,
159 ) -> ServiceResult<proto::DisconnectWhatsAppCallResponse> {
160 self.client
161 .request(
162 SVC,
163 "DisconnectWhatsAppCall",
164 proto::DisconnectWhatsAppCallRequest {
165 whatsapp_call_id: call_id.into(),
166 whatsapp_api_key: api_key.into(),
167 ..Default::default()
168 },
169 self.base
170 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
171 )
172 .await
173 .map_err(Into::into)
174 }
175
176 pub async fn connect_whatsapp_call(
185 &self,
186 call_id: impl Into<String>,
187 sdp: proto::SessionDescription,
188 ) -> ServiceResult<proto::ConnectWhatsAppCallResponse> {
189 self.client
190 .request(
191 SVC,
192 "ConnectWhatsAppCall",
193 proto::ConnectWhatsAppCallRequest {
194 whatsapp_call_id: call_id.into(),
195 sdp: Some(sdp),
196 },
197 self.base
198 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
199 )
200 .await
201 .map_err(Into::into)
202 }
203
204 pub async fn accept_whatsapp_call(
217 &self,
218 phone_number_id: impl Into<String>,
219 api_key: impl Into<String>,
220 cloud_api_version: impl Into<String>,
221 call_id: impl Into<String>,
222 sdp: proto::SessionDescription,
223 options: AcceptWhatsAppCallOptions,
224 ) -> ServiceResult<proto::AcceptWhatsAppCallResponse> {
225 self.client
226 .request(
227 SVC,
228 "AcceptWhatsAppCall",
229 proto::AcceptWhatsAppCallRequest {
230 whatsapp_phone_number_id: phone_number_id.into(),
231 whatsapp_api_key: api_key.into(),
232 whatsapp_cloud_api_version: cloud_api_version.into(),
233 whatsapp_call_id: call_id.into(),
234 whatsapp_biz_opaque_callback_data: options
235 .biz_opaque_callback_data
236 .unwrap_or_default(),
237 sdp: Some(sdp),
238 room_name: options.room_name.unwrap_or_default(),
239 agents: options.agents.unwrap_or_default(),
240 participant_identity: options.participant_identity.unwrap_or_default(),
241 participant_name: options.participant_name.unwrap_or_default(),
242 participant_metadata: options.participant_metadata.unwrap_or_default(),
243 participant_attributes: options.participant_attributes.unwrap_or_default(),
244 destination_country: options.destination_country.unwrap_or_default(),
245 },
246 self.base
247 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
248 )
249 .await
250 .map_err(Into::into)
251 }
252
253 pub async fn connect_twilio_call(
263 &self,
264 direction: proto::connect_twilio_call_request::TwilioCallDirection,
265 room_name: impl Into<String>,
266 options: ConnectTwilioCallOptions,
267 ) -> ServiceResult<proto::ConnectTwilioCallResponse> {
268 self.client
269 .request(
270 SVC,
271 "ConnectTwilioCall",
272 proto::ConnectTwilioCallRequest {
273 twilio_call_direction: direction as i32,
274 room_name: room_name.into(),
275 agents: options.agents.unwrap_or_default(),
276 participant_identity: options.participant_identity.unwrap_or_default(),
277 participant_name: options.participant_name.unwrap_or_default(),
278 participant_metadata: options.participant_metadata.unwrap_or_default(),
279 participant_attributes: options.participant_attributes.unwrap_or_default(),
280 destination_country: options.destination_country.unwrap_or_default(),
281 },
282 self.base
283 .auth_header(VideoGrants { room_create: true, ..Default::default() }, None)?,
284 )
285 .await
286 .map_err(Into::into)
287 }
288}