1use crate::common::{NotetakerId, RecordingId};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct Notetaker {
9 pub id: NotetakerId,
11
12 pub grant_id: String,
14
15 pub active: bool,
17
18 pub provider_settings: ProviderSettings,
20
21 pub transcription_settings: Option<TranscriptionSettings>,
23
24 pub summary_settings: Option<SummarySettings>,
26
27 pub webhook_url: Option<String>,
29
30 pub created_at: i64,
32
33 pub updated_at: i64,
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
39#[serde(tag = "provider", rename_all = "lowercase")]
40pub enum ProviderSettings {
41 #[serde(rename = "google-meet")]
43 GoogleMeet {
44 auto_join: bool,
46 quality: RecordingQuality,
48 },
49
50 #[serde(rename = "microsoft-teams")]
52 MicrosoftTeams {
53 auto_join: bool,
55 quality: RecordingQuality,
57 },
58
59 Zoom {
61 auto_join: bool,
63 quality: RecordingQuality,
65 cloud_recording: bool,
67 },
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
72#[serde(rename_all = "lowercase")]
73pub enum RecordingQuality {
74 Standard,
76 Hd,
78}
79
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
82pub struct TranscriptionSettings {
83 pub enabled: bool,
85
86 pub language: Option<String>,
88
89 pub speaker_identification: bool,
91
92 pub profanity_filter: Option<bool>,
94}
95
96#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
98pub struct SummarySettings {
99 pub enabled: bool,
101
102 pub extract_action_items: bool,
104
105 pub extract_topics: bool,
107
108 pub extract_decisions: bool,
110
111 pub summary_length: SummaryLength,
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
117#[serde(rename_all = "lowercase")]
118pub enum SummaryLength {
119 Brief,
121 Medium,
123 Detailed,
125}
126
127#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
129pub struct Recording {
130 pub id: RecordingId,
132
133 pub notetaker_id: NotetakerId,
135
136 pub title: String,
138
139 pub start_time: i64,
141
142 pub end_time: Option<i64>,
144
145 pub duration: Option<i64>,
147
148 pub status: RecordingStatus,
150
151 pub recording_url: Option<String>,
153
154 pub transcription: Option<Transcription>,
156
157 pub summary: Option<Summary>,
159
160 pub participants: Vec<MeetingParticipant>,
162
163 pub created_at: i64,
165
166 pub updated_at: i64,
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
172#[serde(rename_all = "lowercase")]
173pub enum RecordingStatus {
174 Recording,
176 Processing,
178 Completed,
180 Failed,
182}
183
184#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
186pub struct Transcription {
187 pub text: String,
189
190 pub segments: Vec<TranscriptSegment>,
192
193 pub language: String,
195
196 pub confidence: f64,
198}
199
200#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
202pub struct TranscriptSegment {
203 pub text: String,
205
206 pub speaker: Option<String>,
208
209 pub start_time: f64,
211
212 pub end_time: f64,
214
215 pub confidence: f64,
217}
218
219#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
221pub struct Summary {
222 pub summary: String,
224
225 pub action_items: Vec<ActionItem>,
227
228 pub topics: Vec<String>,
230
231 pub decisions: Vec<String>,
233
234 pub next_steps: Vec<String>,
236}
237
238#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
240pub struct ActionItem {
241 pub description: String,
243
244 pub assignee: Option<String>,
246
247 pub due_date: Option<i64>,
249
250 pub priority: Option<Priority>,
252}
253
254#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
256#[serde(rename_all = "lowercase")]
257pub enum Priority {
258 High,
260 Medium,
262 Low,
264}
265
266#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
268pub struct MeetingParticipant {
269 pub name: String,
271
272 pub email: Option<String>,
274
275 pub joined_at: i64,
277
278 pub left_at: Option<i64>,
280
281 pub speaking_time: Option<i64>,
283}
284
285#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
287pub struct CreateNotetakerRequest {
288 pub provider_settings: ProviderSettings,
290
291 #[serde(skip_serializing_if = "Option::is_none")]
293 pub transcription_settings: Option<TranscriptionSettings>,
294
295 #[serde(skip_serializing_if = "Option::is_none")]
297 pub summary_settings: Option<SummarySettings>,
298
299 #[serde(skip_serializing_if = "Option::is_none")]
301 pub webhook_url: Option<String>,
302
303 #[serde(skip_serializing_if = "Option::is_none")]
305 pub active: Option<bool>,
306}
307
308impl CreateNotetakerRequest {
309 pub fn builder(provider_settings: ProviderSettings) -> CreateNotetakerRequestBuilder {
311 CreateNotetakerRequestBuilder::new(provider_settings)
312 }
313}
314
315#[derive(Debug)]
317pub struct CreateNotetakerRequestBuilder {
318 request: CreateNotetakerRequest,
319}
320
321impl CreateNotetakerRequestBuilder {
322 pub fn new(provider_settings: ProviderSettings) -> Self {
324 Self {
325 request: CreateNotetakerRequest {
326 provider_settings,
327 transcription_settings: None,
328 summary_settings: None,
329 webhook_url: None,
330 active: None,
331 },
332 }
333 }
334
335 pub fn transcription_settings(mut self, settings: TranscriptionSettings) -> Self {
337 self.request.transcription_settings = Some(settings);
338 self
339 }
340
341 pub fn summary_settings(mut self, settings: SummarySettings) -> Self {
343 self.request.summary_settings = Some(settings);
344 self
345 }
346
347 pub fn webhook_url(mut self, url: impl Into<String>) -> Self {
349 self.request.webhook_url = Some(url.into());
350 self
351 }
352
353 pub fn active(mut self, active: bool) -> Self {
355 self.request.active = Some(active);
356 self
357 }
358
359 pub fn build(self) -> CreateNotetakerRequest {
361 self.request
362 }
363}
364
365#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
367pub struct UpdateNotetakerRequest {
368 #[serde(skip_serializing_if = "Option::is_none")]
370 pub provider_settings: Option<ProviderSettings>,
371
372 #[serde(skip_serializing_if = "Option::is_none")]
374 pub transcription_settings: Option<TranscriptionSettings>,
375
376 #[serde(skip_serializing_if = "Option::is_none")]
378 pub summary_settings: Option<SummarySettings>,
379
380 #[serde(skip_serializing_if = "Option::is_none")]
382 pub webhook_url: Option<String>,
383
384 #[serde(skip_serializing_if = "Option::is_none")]
386 pub active: Option<bool>,
387}
388
389impl UpdateNotetakerRequest {
390 pub fn builder() -> UpdateNotetakerRequestBuilder {
392 UpdateNotetakerRequestBuilder::default()
393 }
394}
395
396#[derive(Debug, Default)]
398pub struct UpdateNotetakerRequestBuilder {
399 request: UpdateNotetakerRequest,
400}
401
402impl UpdateNotetakerRequestBuilder {
403 pub fn provider_settings(mut self, settings: ProviderSettings) -> Self {
405 self.request.provider_settings = Some(settings);
406 self
407 }
408
409 pub fn transcription_settings(mut self, settings: TranscriptionSettings) -> Self {
411 self.request.transcription_settings = Some(settings);
412 self
413 }
414
415 pub fn summary_settings(mut self, settings: SummarySettings) -> Self {
417 self.request.summary_settings = Some(settings);
418 self
419 }
420
421 pub fn webhook_url(mut self, url: impl Into<String>) -> Self {
423 self.request.webhook_url = Some(url.into());
424 self
425 }
426
427 pub fn active(mut self, active: bool) -> Self {
429 self.request.active = Some(active);
430 self
431 }
432
433 pub fn build(self) -> UpdateNotetakerRequest {
435 self.request
436 }
437}
438
439#[cfg(test)]
440mod tests {
441 use super::*;
442
443 #[test]
444 fn test_notetaker_id_creation() {
445 let id = NotetakerId::new("notetaker_123");
446 assert_eq!(id.as_str(), "notetaker_123");
447 }
448
449 #[test]
450 fn test_recording_id_creation() {
451 let id = RecordingId::new("rec_456");
452 assert_eq!(id.as_str(), "rec_456");
453 }
454
455 #[test]
456 fn test_create_notetaker_request_builder() {
457 let provider = ProviderSettings::GoogleMeet {
458 auto_join: true,
459 quality: RecordingQuality::Hd,
460 };
461
462 let transcription = TranscriptionSettings {
463 enabled: true,
464 language: Some("en-US".to_string()),
465 speaker_identification: true,
466 profanity_filter: Some(false),
467 };
468
469 let request = CreateNotetakerRequest::builder(provider)
470 .transcription_settings(transcription)
471 .active(true)
472 .build();
473
474 assert!(request.active.unwrap());
475 assert!(request.transcription_settings.is_some());
476 }
477
478 #[test]
479 fn test_update_notetaker_request_builder() {
480 let request = UpdateNotetakerRequest::builder()
481 .active(false)
482 .webhook_url("https://example.com/webhook")
483 .build();
484
485 assert_eq!(request.active, Some(false));
486 assert_eq!(
487 request.webhook_url,
488 Some("https://example.com/webhook".to_string())
489 );
490 }
491
492 #[test]
493 fn test_recording_status_serialization() {
494 let status = RecordingStatus::Processing;
495 let json = serde_json::to_string(&status).unwrap();
496 assert_eq!(json, "\"processing\"");
497 }
498
499 #[test]
500 fn test_summary_length_serialization() {
501 let length = SummaryLength::Brief;
502 let json = serde_json::to_string(&length).unwrap();
503 assert_eq!(json, "\"brief\"");
504 }
505}