twapi_v2/api/
get_2_tweets_count_recent.rs1use 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}