twapi_v2/api/
get_2_tweets_count_recent.rs

1use crate::responses::{counts::Counts, errors::Errors, meta_count::MetaCount};
2use crate::{
3    api::{apply_options, execute_twitter, make_url, Authentication, TwapiOptions},
4    error::Error,
5    headers::Headers,
6};
7use chrono::prelude::*;
8use reqwest::RequestBuilder;
9use serde::{Deserialize, Serialize};
10
11const URL: &str = "/2/tweets/counts/recent";
12
13#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Clone)]
14pub enum Granularity {
15    #[serde(rename = "minute")]
16    Minute,
17    #[serde(rename = "hour")]
18    Hour,
19    #[serde(rename = "day")]
20    Day,
21}
22
23impl std::fmt::Display for Granularity {
24    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
25        match self {
26            Self::Minute => write!(f, "minute"),
27            Self::Hour => write!(f, "hour"),
28            Self::Day => write!(f, "day"),
29        }
30    }
31}
32
33impl Default for Granularity {
34    fn default() -> Self {
35        Self::Minute
36    }
37}
38
39#[derive(Debug, Clone, Default)]
40pub struct Api {
41    query: String,
42    end_time: Option<DateTime<Utc>>,
43    granularity: Option<Granularity>,
44    since_id: Option<String>,
45    start_time: Option<DateTime<Utc>>,
46    until_id: Option<String>,
47    twapi_options: Option<TwapiOptions>,
48}
49
50impl Api {
51    pub fn new(query: &str) -> Self {
52        Self {
53            query: query.to_owned(),
54            ..Default::default()
55        }
56    }
57
58    pub fn end_time(mut self, value: DateTime<Utc>) -> Self {
59        self.end_time = Some(value);
60        self
61    }
62
63    pub fn granularity(mut self, value: Granularity) -> Self {
64        self.granularity = Some(value);
65        self
66    }
67
68    pub fn since_id(mut self, value: &str) -> Self {
69        self.since_id = Some(value.to_owned());
70        self
71    }
72
73    pub fn start_time(mut self, value: DateTime<Utc>) -> Self {
74        self.start_time = Some(value);
75        self
76    }
77
78    pub fn until_id(mut self, value: &str) -> Self {
79        self.until_id = Some(value.to_owned());
80        self
81    }
82
83    pub fn twapi_options(mut self, value: TwapiOptions) -> Self {
84        self.twapi_options = Some(value);
85        self
86    }
87
88    pub fn build(self, authentication: &impl Authentication) -> RequestBuilder {
89        let mut query_parameters = vec![];
90        query_parameters.push(("query", self.query));
91        if let Some(end_time) = self.end_time {
92            query_parameters.push(("end_time", end_time.format("%Y-%m-%dT%H%M%SZ").to_string()));
93        }
94        if let Some(granularity) = self.granularity {
95            query_parameters.push(("granularity", granularity.to_string()));
96        }
97        if let Some(since_id) = self.since_id {
98            query_parameters.push(("since_id", since_id));
99        }
100        if let Some(start_time) = self.start_time {
101            query_parameters.push((
102                "start_time",
103                start_time.format("%Y-%m-%dT%H%M%SZ").to_string(),
104            ));
105        }
106        if let Some(until_id) = self.until_id {
107            query_parameters.push(("until_id", until_id));
108        }
109        let client = reqwest::Client::new();
110        let url = make_url(&self.twapi_options, URL);
111        let builder = client.get(&url).query(&query_parameters);
112        authentication.execute(
113            apply_options(builder, &self.twapi_options),
114            "GET",
115            &url,
116            &query_parameters
117                .iter()
118                .map(|it| (it.0, it.1.as_str()))
119                .collect::<Vec<_>>(),
120        )
121    }
122
123    pub async fn execute(
124        self,
125        authentication: &impl Authentication,
126    ) -> Result<(Response, Headers), Error> {
127        execute_twitter(self.build(authentication)).await
128    }
129}
130
131#[derive(Serialize, Deserialize, Debug, Clone, Default)]
132pub struct Response {
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub data: Option<Vec<Counts>>,
135    #[serde(skip_serializing_if = "Option::is_none")]
136    pub errors: Option<Vec<Errors>>,
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub meta: Option<MetaCount>,
139    #[serde(flatten)]
140    pub extra: std::collections::HashMap<String, serde_json::Value>,
141}
142
143impl Response {
144    pub fn is_empty_extra(&self) -> bool {
145        let res = self.extra.is_empty()
146            && self
147                .data
148                .as_ref()
149                .map(|it| it.iter().all(|item| item.is_empty_extra()))
150                .unwrap_or(true)
151            && self
152                .errors
153                .as_ref()
154                .map(|it| it.iter().all(|item| item.is_empty_extra()))
155                .unwrap_or(true)
156            && self
157                .meta
158                .as_ref()
159                .map(|it| it.is_empty_extra())
160                .unwrap_or(true);
161        if !res {
162            println!("Response {:?}", self.extra);
163        }
164        res
165    }
166}