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