finance_query/models/search/
news.rs

1//! Search News Model
2//!
3//! Represents news articles from search results
4
5use super::thumbnail::NewsThumbnail;
6use serde::{Deserialize, Serialize};
7use std::ops::Deref;
8
9/// A collection of search news with DataFrame support.
10///
11/// This wrapper allows `search_results.news.to_dataframe()` syntax while still
12/// acting like a `Vec<SearchNews>` for iteration, indexing, etc.
13#[derive(Debug, Clone, Default, Serialize, Deserialize)]
14#[serde(transparent)]
15pub struct SearchNewsList(pub Vec<SearchNews>);
16
17impl Deref for SearchNewsList {
18    type Target = Vec<SearchNews>;
19
20    fn deref(&self) -> &Self::Target {
21        &self.0
22    }
23}
24
25impl IntoIterator for SearchNewsList {
26    type Item = SearchNews;
27    type IntoIter = std::vec::IntoIter<SearchNews>;
28
29    fn into_iter(self) -> Self::IntoIter {
30        self.0.into_iter()
31    }
32}
33
34impl<'a> IntoIterator for &'a SearchNewsList {
35    type Item = &'a SearchNews;
36    type IntoIter = std::slice::Iter<'a, SearchNews>;
37
38    fn into_iter(self) -> Self::IntoIter {
39        self.0.iter()
40    }
41}
42
43#[cfg(feature = "dataframe")]
44impl SearchNewsList {
45    /// Converts the news to a polars DataFrame.
46    pub fn to_dataframe(&self) -> ::polars::prelude::PolarsResult<::polars::prelude::DataFrame> {
47        SearchNews::vec_to_dataframe(&self.0)
48    }
49}
50
51/// A news result from search
52///
53/// When the `dataframe` feature is enabled, scalar fields can be converted
54/// to a DataFrame. Complex fields (thumbnail, related_tickers) are automatically skipped.
55#[derive(Debug, Clone, Serialize, Deserialize)]
56#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
57#[non_exhaustive]
58#[serde(rename_all = "camelCase")]
59pub struct SearchNews {
60    /// Unique news article identifier
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub uuid: Option<String>,
63    /// Article title
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub title: Option<String>,
66    /// Publisher name
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub publisher: Option<String>,
69    /// Article URL
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub link: Option<String>,
72    /// Publication timestamp (Unix epoch seconds)
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub provider_publish_time: Option<i64>,
75    /// Article type (STORY, VIDEO, etc.)
76    #[serde(rename = "type")]
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub news_type: Option<String>,
79    /// Article thumbnail image (excluded from DataFrame)
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub thumbnail: Option<NewsThumbnail>,
82    /// Related stock symbols (excluded from DataFrame)
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub related_tickers: Option<Vec<String>>,
85}