1use super::*;
5
6const CLIPS_PATH: &str = "/clips";
7const PRESENTERS_PATH: &str = "/presenters";
8const DRIVERS_PATH: &str = "/drivers";
9
10#[derive(Serialize, Deserialize, Debug)]
11pub struct GetPresentersResponse {
12 presenters: Vec<Presenter>,
13}
14
15#[derive(Serialize, Deserialize, Debug)]
16pub struct Presenter {
17 presenter_id: String,
18 driver_id: String,
19 gender: String,
20 owner_id: String,
21 preview_url: String,
22 modified_at: String,
23 }
25
26pub async fn get_presenters() -> Result<GetPresentersResponse> {
27 let c = ClientBuilder::new()?
28 .method(GET)?
29 .path(&format!("{}{}", CLIPS_PATH, PRESENTERS_PATH))?
30 .header(CONTENT_TYPE, APPLICATION_JSON)?
31 .build()?;
32
33 let resp = c.send_request(Empty::<Bytes>::new()).await?;
34
35 let presenters = serde_json::from_slice::<GetPresentersResponse>(&resp.as_ref())?;
36
37 Ok(presenters)
38}
39
40pub async fn get_presenter(id: &str) -> Result<Presenter> {
41 let c = ClientBuilder::new()?
42 .method(GET)?
43 .path(&format!("{}{}/{}", CLIPS_PATH, PRESENTERS_PATH, id))?
44 .header(CONTENT_TYPE, APPLICATION_JSON)?
45 .build()?;
46
47 let resp = c.send_request(Empty::<Bytes>::new()).await?;
48
49 let presenter = serde_json::from_slice::<Presenter>(&resp.as_ref())?;
50
51 Ok(presenter)
52}
53
54
55#[derive(Serialize, Deserialize, Debug)]
56pub struct ClipRequestBody {
57 presenter_id: String,
58 script: Script,
59 #[serde(skip_serializing_if = "String::is_empty")]
60 driver_id: String,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 config: Option<Config>,
63 #[serde(skip_serializing_if = "String::is_empty")]
64 created_by: String,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 presenter_config: Option<PresenterConfig>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 background: Option<Background>,
69 #[serde(skip_serializing_if = "String::is_empty")]
70 user_data: String,
71 #[serde(skip_serializing_if = "String::is_empty")]
72 name: String,
73 #[serde(skip_serializing_if = "String::is_empty")]
74 webhook: String,
75 #[serde(skip_serializing_if = "String::is_empty")]
76 result_url: String,
77 #[serde(skip_serializing_if = "String::is_empty")]
78 raw_result_url: String,
79 #[serde(skip_serializing_if = "Option::is_none")]
80 persist: Option<bool>
81}
82
83#[derive(Serialize, Deserialize, Debug)]
84pub struct PresenterConfig{
85 crop: Crop,
86}
87
88#[derive(Serialize, Deserialize, Debug)]
89pub struct Crop {
90 r#type: String,
91 rectangle: Rectangle,
92}
93
94#[derive(Serialize, Deserialize, Debug)]
95pub struct Rectangle {
96 bottom: i64,
97 left: i64,
98 right: i64,
99 top: i64,
100}
101
102#[derive(Serialize, Deserialize, Debug)]
103pub struct Background {
104 color: String,
105}
106
107impl ClipRequestBody {
108 pub async fn create(&self) -> Result<CreateClipResponse> {
109 let c = ClientBuilder::new()?
110 .method(POST)?
111 .path(CLIPS_PATH)?
112 .header(CONTENT_TYPE, APPLICATION_JSON)?
113 .header(ACCEPT, APPLICATION_JSON)?
114 .build()?;
115
116 let resp = c.send_request(Full::<Bytes>::new(serde_json::to_string(&self)?.into())).await?;
117
118 let clip_resp = serde_json::from_slice::<CreateClipResponse>(&resp.as_ref())?;
119
120 Ok(clip_resp)
121 }
122}
123
124#[derive(Serialize, Deserialize, Debug)]
125pub struct ClipRequestBodyBuilder {
126 presenter_id: Option<String>,
127 driver_id: Option<String>,
128 script: Option<Script>,
129 config: Option<Config>,
130 created_by: Option<String>,
131 presenter_config: Option<PresenterConfig>,
132 background: Option<Background>,
133 user_data: Option<String>,
134 name: Option<String>,
135 webhook: Option<String>,
136 result_url: Option<String>,
137 raw_result_url: Option<String>,
138 persist: Option<bool>,
139}
140
141
142impl ClipRequestBodyBuilder {
143 pub fn new() -> Self {
144 Self {
145 presenter_id: None,
146 driver_id: None,
147 script: None,
148 config: None,
149 created_by: None,
150 presenter_config: None,
151 background: None,
152 user_data: None,
153 name: None,
154 webhook: None,
155 result_url: None,
156 raw_result_url: None,
157 persist: None,
158 }
159 }
160
161 pub fn with_text_script(presenter_id: &str) -> Self {
162 let script = Script::Text {
163 r#type: "text".to_string(),
164 subtitles: false,
165 provider: Some(TTSProvider::MicrosoftTTS {
166 r#type: "microsoft".to_string(),
167 voice_id: "en-US-JennyNeural".to_string(),
168 }),
169 input: "".to_string(),
170 ssml: false,
171 };
172
173 Self {
174 presenter_id: Some(presenter_id.to_string()),
175 driver_id: None,
176 script: Some(script),
177 config: None,
178 created_by: None,
179 presenter_config: None,
180 background: None,
181 user_data: None,
182 name: None,
183 webhook: None,
184 result_url: None,
185 raw_result_url: None,
186 persist: None,
187 }
188 }
189
190 pub fn with_audio_script(presenter_id: &str) -> Self {
191 let script = Script::Audio {
192 r#type: "audio".to_string(),
193 subtitles: false,
194 audio_url: "".to_string(),
195 reduce_noise: false,
196 };
197
198 Self {
199 presenter_id: Some(presenter_id.to_string()),
200 script: Some(script),
201 config: None,
202 created_by: None,
203 presenter_config: None,
204 background: None,
205 user_data: None,
206 name: None,
207 webhook: None,
208 result_url: None,
209 persist: None,
210 driver_id: None,
211 raw_result_url: None,
212 }
213 }
214
215 pub fn presenter_id(mut self, presenter_id: &str) -> Self {
216 self.presenter_id = Some(presenter_id.to_string());
217 self
218 }
219
220 pub fn driver_id(mut self, driver_id: &str) -> Self {
221 self.driver_id = Some(driver_id.to_string());
222 self
223 }
224
225 pub fn script(mut self, script: Script) -> Self {
226 self.script = Some(script);
227 self
228 }
229
230 pub fn config(mut self, config: Config) -> Self {
231 self.config = Some(config);
232 self
233 }
234
235 pub fn created_by(mut self, created_by: &str) -> Self {
236 self.created_by = Some(created_by.to_string());
237 self
238 }
239
240 pub fn presenter_config(mut self, presenter_config: PresenterConfig) -> Self {
241 self.presenter_config = Some(presenter_config);
242 self
243 }
244
245 pub fn background(mut self, background: Background) -> Self {
246 self.background = Some(background);
247 self
248 }
249
250 pub fn user_data(mut self, user_data: &str) -> Self {
251 self.user_data = Some(user_data.to_string());
252 self
253 }
254
255 pub fn name(mut self, name: &str) -> Self {
256 self.name = Some(name.to_string());
257 self
258 }
259
260 pub fn webhook(mut self, webhook: &str) -> Self {
261 self.webhook = Some(webhook.to_string());
262 self
263 }
264
265 pub fn result_url(mut self, result_url: &str) -> Self {
266 self.result_url = Some(result_url.to_string());
267 self
268 }
269
270 pub fn raw_result_url(mut self, raw_result_url: &str) -> Self {
271 self.raw_result_url = Some(raw_result_url.to_string());
272 self
273 }
274
275 pub fn persist(mut self, persist: bool) -> Self {
276 self.persist = Some(persist);
277 self
278 }
279
280 pub fn audio_url(mut self, audio_url: &str) -> Result<Self> {
281 if let Some(Script::Audio { audio_url: a, .. }) = self.script.as_mut() {
282 *a = audio_url.to_string();
283 }
284 Ok(self)
285 }
286
287 pub fn input(mut self, input: &str) -> Self {
288 if let Some(Script::Text { input: i, .. }) = self.script.as_mut() {
289 *i = input.to_string();
290 }
291 self
292 }
293
294 pub fn ssml(mut self, ssml: bool) -> Result<Self> {
295 if let Some(Script::Text { ssml: s, .. }) = self.script.as_mut() {
296 *s = ssml;
297 }
298 Ok(self)
299 }
300
301 pub fn subtitles(mut self, subtitles: bool) -> Result<Self> {
302 if let Some(Script::Text { subtitles: s, .. }) = self.script.as_mut() {
303 *s = subtitles;
304 }
305 Ok(self)
306 }
307
308 pub fn provider(mut self, provider: TTSProvider) -> Result<Self> {
309 if let Some(Script::Text { provider: p, .. }) = self.script.as_mut() {
310 *p = Some(provider);
311 }
312 Ok(self)
313 }
314
315 pub fn reduce_noise(mut self, reduce_noise: bool) -> Result<Self> {
316 if let Some(Script::Audio { reduce_noise: r, .. }) = self.script.as_mut() {
317 *r = reduce_noise;
318 }
319 Ok(self)
320 }
321
322 pub fn build(self) -> Result<ClipRequestBody> {
323 let presenter_id = self.presenter_id.ok_or(RequestBodyBuildError::PresenterIdNotSet)?;
324 let script = self.script.ok_or(RequestBodyBuildError::ScriptNotSet)?;
325
326 Ok(ClipRequestBody {
327 presenter_id,
328 script,
329 driver_id: self.driver_id.unwrap_or_default(),
330 config: self.config,
331 created_by: self.created_by.unwrap_or_default(),
332 presenter_config: self.presenter_config,
333 background: self.background,
334 user_data: self.user_data.unwrap_or_default(),
335 name: self.name.unwrap_or_default(),
336 webhook: self.webhook.unwrap_or_default(),
337 result_url: self.result_url.unwrap_or_default(),
338 raw_result_url: self.raw_result_url.unwrap_or_default(),
339 persist: self.persist,
340 })
341 }
342}
343
344#[derive(Serialize, Deserialize, Debug)]
345pub struct CreateClipResponse {
346 id: String,
347 object: String,
348 created_at: String,
349 status: String,
350}
351
352pub async fn get_clips() -> Result<GetClipsResponse> {
353 let c = ClientBuilder::new()?
354 .method(GET)?
355 .path(CLIPS_PATH)?
356 .header(CONTENT_TYPE, APPLICATION_JSON)?
357 .build()?;
358
359 let resp = c.send_request(Empty::<Bytes>::new()).await?;
360
361 let clips = serde_json::from_slice::<GetClipsResponse>(&resp.as_ref())?;
362
363 Ok(clips)
364}
365
366#[derive(Serialize, Deserialize, Debug)]
367pub struct GetClipsResponse {
368 clips: Vec<Clip>,
369}
370
371#[derive(Serialize, Deserialize, Debug)]
372pub struct Clip {
373 id: String,
374 owner_id: String,
375 audio_url: String,
376 created_at: String,
377 created_by: String,
378 modified_at: String,
379 started_at: String,
380 completed_at: String,
381 status: String,
382 presenter_id: String,
383 driver_id: String,
384 config: Config,
385 name: String,
386 webhook: String,
387 result_url: String,
388 }
390
391pub async fn get_clip(id: &str) -> Result<Clip> {
392 let c = ClientBuilder::new()?
393 .method(GET)?
394 .path(&format!("{}/{}", CLIPS_PATH, id))?
395 .header(CONTENT_TYPE, APPLICATION_JSON)?
396 .build()?;
397
398 let resp = c.send_request(Empty::<Bytes>::new()).await?;
399
400 let clip = serde_json::from_slice::<Clip>(&resp.as_ref())?;
401
402 Ok(clip)
403}
404
405pub async fn delete_clip(id: &str) -> Result<()> {
406 let c = ClientBuilder::new()?
407 .method(DELETE)?
408 .path(&format!("{}/{}", CLIPS_PATH, id))?
409 .header(CONTENT_TYPE, APPLICATION_JSON)?
410 .build()?;
411
412 let _resp = c.send_request(Empty::<Bytes>::new()).await?;
413
414 Ok(())
415}
416
417pub async fn get_presenter_drivers(presenter_id: &str) -> Result<GetPresenterDriversResponse> {
418 let c = ClientBuilder::new()?
419 .method(GET)?
420 .path(&format!("{}{}/{}{}", CLIPS_PATH, PRESENTERS_PATH, presenter_id, DRIVERS_PATH))?
421 .header(CONTENT_TYPE, APPLICATION_JSON)?
422 .build()?;
423
424 let resp = c.send_request(Empty::<Bytes>::new()).await?;
425
426 let drivers = serde_json::from_slice::<GetPresenterDriversResponse>(&resp.as_ref())?;
427
428 Ok(drivers)
429}
430
431#[derive(Serialize, Deserialize, Debug)]
432pub struct GetPresenterDriversResponse {
433 clips_drivers: Vec<ClipDriver>,
434}
435
436#[derive(Serialize, Deserialize, Debug)]
437pub struct ClipDriver {
438 created_at: String,
439 driver_id: String,
440 driver_image_url: String,
441 gender: String,
442 modified_at: String,
443 name: String,
444 presenter_id: String,
445 preview_url: String,
446 thumbnail_url: String,
447 video_url: String,
448}
449