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)]
14#[derive(Default)]
15pub enum Granularity {
16 #[serde(rename = "minute")]
17 #[default]
18 Minute,
19 #[serde(rename = "hour")]
20 Hour,
21 #[serde(rename = "day")]
22 Day,
23}
24
25impl std::fmt::Display for Granularity {
26 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
27 match self {
28 Self::Minute => write!(f, "minute"),
29 Self::Hour => write!(f, "hour"),
30 Self::Day => write!(f, "day"),
31 }
32 }
33}
34
35
36#[derive(Debug, Clone, Default)]
37pub struct Api {
38 query: String,
39 end_time: Option<DateTime<Utc>>,
40 granularity: Option<Granularity>,
41 since_id: Option<String>,
42 start_time: Option<DateTime<Utc>>,
43 until_id: Option<String>,
44 twapi_options: Option<TwapiOptions>,
45}
46
47impl Api {
48 pub fn new(query: &str) -> Self {
49 Self {
50 query: query.to_owned(),
51 ..Default::default()
52 }
53 }
54
55 pub fn end_time(mut self, value: DateTime<Utc>) -> Self {
56 self.end_time = Some(value);
57 self
58 }
59
60 pub fn granularity(mut self, value: Granularity) -> Self {
61 self.granularity = Some(value);
62 self
63 }
64
65 pub fn since_id(mut self, value: &str) -> Self {
66 self.since_id = Some(value.to_owned());
67 self
68 }
69
70 pub fn start_time(mut self, value: DateTime<Utc>) -> Self {
71 self.start_time = Some(value);
72 self
73 }
74
75 pub fn until_id(mut self, value: &str) -> Self {
76 self.until_id = Some(value.to_owned());
77 self
78 }
79
80 pub fn twapi_options(mut self, value: TwapiOptions) -> Self {
81 self.twapi_options = Some(value);
82 self
83 }
84
85 pub fn build(&self, authentication: &impl Authentication) -> RequestBuilder {
86 let mut query_parameters = vec![];
87 query_parameters.push(("query", self.query.to_string()));
88 if let Some(end_time) = self.end_time.as_ref() {
89 query_parameters.push((
90 "end_time",
91 end_time.format("%Y-%m-%dT%H:%M:%SZ").to_string(),
92 ));
93 }
94 if let Some(granularity) = self.granularity.as_ref() {
95 query_parameters.push(("granularity", granularity.to_string()));
96 }
97 if let Some(since_id) = self.since_id.as_ref() {
98 query_parameters.push(("since_id", since_id.to_string()));
99 }
100 if let Some(start_time) = self.start_time.as_ref() {
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.as_ref() {
107 query_parameters.push(("until_id", until_id.to_string()));
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 builder,
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), &self.twapi_options).await
128 }
129}
130
131#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
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}