Skip to main content

twapi_v2/api/
post_2_tweets_search_stream_rules.rs

1use crate::responses::{errors::Errors, streams::Streams, summary::Summary};
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/search/stream/rules";
12
13#[derive(Serialize, Deserialize, Debug, Default, Clone)]
14pub struct Add {
15    pub value: String,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub tag: Option<String>,
18}
19
20#[derive(Serialize, Deserialize, Debug, Default, Clone)]
21pub struct Delete {
22    pub ids: Vec<String>,
23}
24
25#[derive(Serialize, Deserialize, Debug, Default, Clone)]
26pub struct Body {
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub add: Option<Vec<Add>>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub delete: Option<Delete>,
31}
32
33#[derive(Debug, Clone, Default)]
34pub struct Api {
35    dry_run: Option<bool>,
36    body: Body,
37    twapi_options: Option<TwapiOptions>,
38}
39
40impl Api {
41    pub fn new(body: Body) -> Self {
42        Self {
43            body,
44            ..Default::default()
45        }
46    }
47
48    pub fn dry_run(mut self, value: bool) -> Self {
49        self.dry_run = Some(value);
50        self
51    }
52
53    pub fn twapi_options(mut self, value: TwapiOptions) -> Self {
54        self.twapi_options = Some(value);
55        self
56    }
57
58    pub fn build(&self, authentication: &impl Authentication) -> RequestBuilder {
59        let mut query_parameters = vec![];
60        if let Some(dry_run) = self.dry_run.as_ref() {
61            query_parameters.push(("dry_run", dry_run.to_string()));
62        }
63        let client = reqwest::Client::new();
64        let url = make_url(&self.twapi_options, URL);
65        let builder = client.post(&url).query(&query_parameters).json(&self.body);
66        authentication.execute(
67            builder,
68            "POST",
69            &url,
70            &query_parameters
71                .iter()
72                .map(|it| (it.0, it.1.as_str()))
73                .collect::<Vec<_>>(),
74        )
75    }
76
77    pub async fn execute(
78        &self,
79        authentication: &impl Authentication,
80    ) -> Result<(Response, Headers), Error> {
81        execute_twitter(|| self.build(authentication), &self.twapi_options).await
82    }
83}
84
85#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
86pub struct Response {
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub data: Option<Vec<Streams>>,
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub errors: Option<Vec<Errors>>,
91    pub meta: Meta,
92    #[serde(flatten)]
93    pub extra: std::collections::HashMap<String, serde_json::Value>,
94}
95
96impl Response {
97    pub fn is_empty_extra(&self) -> bool {
98        let res = self.extra.is_empty()
99            && self
100                .data
101                .as_ref()
102                .map(|it| it.iter().all(|item| item.is_empty_extra()))
103                .unwrap_or(true)
104            && self
105                .errors
106                .as_ref()
107                .map(|it| it.iter().all(|item| item.is_empty_extra()))
108                .unwrap_or(true)
109            && self.meta.is_empty_extra();
110        if !res {
111            println!("Response {:?}", self.extra);
112        }
113        res
114    }
115}
116
117#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
118pub struct Meta {
119    pub sent: DateTime<Utc>,
120    pub summary: Summary,
121    #[serde(flatten)]
122    pub extra: std::collections::HashMap<String, serde_json::Value>,
123}
124
125impl Meta {
126    pub fn is_empty_extra(&self) -> bool {
127        let res = self.extra.is_empty() && self.summary.is_empty_extra();
128        if !res {
129            println!("Meta {:?}", self.extra);
130        }
131        res
132    }
133}