finance_query/models/transcript/
mod.rs1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct Transcript {
11 pub transcript_content: TranscriptContent,
13 pub transcript_metadata: TranscriptMetadata,
15}
16
17impl Transcript {
18 pub fn text(&self) -> &str {
20 self.transcript_content
21 .transcript
22 .as_ref()
23 .map(|t| t.text.as_str())
24 .unwrap_or("")
25 }
26
27 pub fn quarter(&self) -> &str {
29 &self.transcript_metadata.fiscal_period
30 }
31
32 pub fn year(&self) -> i32 {
34 self.transcript_metadata.fiscal_year
35 }
36
37 pub fn speaker_name(&self, speaker_id: i32) -> Option<&str> {
39 self.transcript_content
40 .speaker_mapping
41 .iter()
42 .find(|s| s.speaker == speaker_id)
43 .map(|s| s.speaker_data.name.as_str())
44 }
45
46 pub fn paragraphs_with_speakers(&self) -> Vec<(&Paragraph, Option<&str>)> {
48 self.transcript_content
49 .transcript
50 .as_ref()
51 .map(|t| {
52 t.paragraphs
53 .iter()
54 .map(|p| (p, self.speaker_name(p.speaker)))
55 .collect()
56 })
57 .unwrap_or_default()
58 }
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct TranscriptContent {
64 pub company_id: i64,
66 pub event_id: i64,
68 #[serde(default)]
70 pub version: Option<String>,
71 #[serde(default)]
73 pub speaker_mapping: Vec<SpeakerMapping>,
74 #[serde(default)]
76 pub transcript: Option<TranscriptData>,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct SpeakerMapping {
82 pub speaker: i32,
84 pub speaker_data: SpeakerData,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct SpeakerData {
91 #[serde(default)]
93 pub company: Option<String>,
94 #[serde(default)]
96 pub name: String,
97 #[serde(default)]
99 pub role: Option<String>,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct TranscriptData {
105 #[serde(default)]
107 pub number_of_speakers: i32,
108 #[serde(default)]
110 pub text: String,
111 #[serde(default)]
113 pub paragraphs: Vec<Paragraph>,
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct Paragraph {
119 #[serde(default)]
121 pub speaker: i32,
122 #[serde(default)]
124 pub start: f64,
125 #[serde(default)]
127 pub end: f64,
128 #[serde(default)]
130 pub text: String,
131 #[serde(default)]
133 pub sentences: Vec<Sentence>,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct Sentence {
139 #[serde(default)]
141 pub start: f64,
142 #[serde(default)]
144 pub end: f64,
145 #[serde(default)]
147 pub text: String,
148 #[serde(default)]
150 pub words: Vec<Word>,
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct Word {
156 #[serde(default)]
158 pub word: String,
159 #[serde(default)]
161 pub punctuated_word: String,
162 #[serde(default)]
164 pub start: f64,
165 #[serde(default)]
167 pub end: f64,
168 #[serde(default)]
170 pub confidence: f64,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
175#[serde(rename_all = "camelCase")]
176pub struct TranscriptMetadata {
177 #[serde(default)]
179 pub date: i64,
180 #[serde(default)]
182 pub event_id: i64,
183 #[serde(default)]
185 pub event_type: String,
186 #[serde(default)]
188 pub fiscal_period: String,
189 #[serde(default)]
191 pub fiscal_year: i32,
192 #[serde(default)]
194 pub is_latest: bool,
195 #[serde(default)]
197 pub s3_url: String,
198 #[serde(default)]
200 pub title: String,
201 #[serde(default)]
203 pub transcript_id: i64,
204 #[serde(default, rename = "type")]
206 pub transcript_type: String,
207 #[serde(default)]
209 pub updated: i64,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
216#[serde(rename_all = "camelCase")]
217pub struct TranscriptWithMeta {
218 pub event_id: String,
220 pub quarter: Option<String>,
222 pub year: Option<i32>,
224 pub title: String,
226 pub url: String,
228 pub transcript: Transcript,
230}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235
236 #[test]
237 fn test_deserialize_transcript() {
238 let json = r#"{
239 "transcriptContent": {
240 "company_id": 4742,
241 "event_id": 369370,
242 "version": "1.0.0",
243 "speaker_mapping": [
244 {
245 "speaker": 0,
246 "speaker_data": {
247 "company": "Apple",
248 "name": "Tim Cook",
249 "role": "CEO"
250 }
251 }
252 ],
253 "transcript": {
254 "number_of_speakers": 15,
255 "text": "Hello everyone...",
256 "paragraphs": []
257 }
258 },
259 "transcriptMetadata": {
260 "date": 1761858000,
261 "eventId": 369370,
262 "eventType": "Earnings Call",
263 "fiscalPeriod": "Q4",
264 "fiscalYear": 2025,
265 "isLatest": true,
266 "title": "Q4 2025"
267 }
268 }"#;
269
270 let transcript: Transcript = serde_json::from_str(json).unwrap();
271 assert_eq!(transcript.transcript_content.company_id, 4742);
272 assert_eq!(transcript.quarter(), "Q4");
273 assert_eq!(transcript.year(), 2025);
274 assert_eq!(transcript.speaker_name(0), Some("Tim Cook"));
275 }
276}