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