Skip to main content

twapi_v2/api/
get_2_users_id_muting.rs

1use crate::fields::{tweet_fields::TweetFields, user_fields::UserFields};
2use crate::responses::{errors::Errors, includes::Includes, meta::Meta, users::Users};
3use crate::{
4    api::{Authentication, TwapiOptions, execute_twitter, make_url},
5    error::Error,
6    headers::Headers,
7};
8use itertools::Itertools;
9use reqwest::RequestBuilder;
10use serde::{Deserialize, Serialize};
11use std::collections::HashSet;
12
13const URL: &str = "/2/users/:id/muting";
14
15#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Clone)]
16#[derive(Default)]
17pub enum Expansions {
18    #[serde(rename = "affiliation.user_id")]
19    #[default]
20    AffiliationUserId,
21    #[serde(rename = "most_recent_tweet_id")]
22    MostRecentTweetId,
23    #[serde(rename = "pinned_tweet_id")]
24    PinnedTweetId,
25}
26
27impl Expansions {
28    pub fn all() -> HashSet<Self> {
29        let mut result = HashSet::new();
30        result.insert(Self::AffiliationUserId);
31        result.insert(Self::MostRecentTweetId);
32        result.insert(Self::PinnedTweetId);
33        result
34    }
35}
36
37impl std::fmt::Display for Expansions {
38    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
39        match self {
40            Self::AffiliationUserId => write!(f, "affiliation.user_id"),
41            Self::MostRecentTweetId => write!(f, "most_recent_tweet_id"),
42            Self::PinnedTweetId => write!(f, "pinned_tweet_id"),
43        }
44    }
45}
46
47
48#[derive(Debug, Clone, Default)]
49pub struct Api {
50    id: String,
51    expansions: Option<HashSet<Expansions>>,
52    max_results: Option<usize>,
53    pagination_token: Option<String>,
54    tweet_fields: Option<HashSet<TweetFields>>,
55    user_fields: Option<HashSet<UserFields>>,
56    twapi_options: Option<TwapiOptions>,
57}
58
59impl Api {
60    pub fn new(id: &str) -> Self {
61        Self {
62            id: id.to_owned(),
63            ..Default::default()
64        }
65    }
66
67    pub fn all(id: &str) -> Self {
68        Self {
69            id: id.to_owned(),
70            expansions: Some(Expansions::all()),
71            tweet_fields: Some(TweetFields::organic()),
72            user_fields: Some(UserFields::all()),
73            max_results: Some(1000),
74            ..Default::default()
75        }
76    }
77
78    pub fn open(id: &str) -> Self {
79        Self {
80            id: id.to_owned(),
81            expansions: Some(Expansions::all()),
82            tweet_fields: Some(TweetFields::open()),
83            user_fields: Some(UserFields::all()),
84            max_results: Some(1000),
85            ..Default::default()
86        }
87    }
88
89    pub fn expansions(mut self, value: HashSet<Expansions>) -> Self {
90        self.expansions = Some(value);
91        self
92    }
93
94    pub fn max_results(mut self, value: usize) -> Self {
95        self.max_results = Some(value);
96        self
97    }
98
99    pub fn pagination_token(mut self, value: &str) -> Self {
100        self.pagination_token = Some(value.to_owned());
101        self
102    }
103
104    pub fn tweet_fields(mut self, value: HashSet<TweetFields>) -> Self {
105        self.tweet_fields = Some(value);
106        self
107    }
108
109    pub fn user_fields(mut self, value: HashSet<UserFields>) -> Self {
110        self.user_fields = Some(value);
111        self
112    }
113
114    pub fn twapi_options(mut self, value: TwapiOptions) -> Self {
115        self.twapi_options = Some(value);
116        self
117    }
118
119    pub fn build(&self, authentication: &impl Authentication) -> RequestBuilder {
120        let mut query_parameters = vec![];
121        if let Some(expansions) = self.expansions.as_ref() {
122            query_parameters.push(("expansions", expansions.iter().join(",")));
123        }
124        if let Some(max_results) = self.max_results.as_ref() {
125            query_parameters.push(("max_results", max_results.to_string()));
126        }
127        if let Some(pagination_token) = self.pagination_token.as_ref() {
128            query_parameters.push(("pagination_token", pagination_token.to_string()));
129        }
130        if let Some(tweet_fields) = self.tweet_fields.as_ref() {
131            query_parameters.push(("tweet.fields", tweet_fields.iter().join(",")));
132        }
133        if let Some(user_fields) = self.user_fields.as_ref() {
134            query_parameters.push(("user.fields", user_fields.iter().join(",")));
135        }
136        let client = reqwest::Client::new();
137        let url = make_url(&self.twapi_options, &URL.replace(":id", &self.id));
138        let builder = client.get(&url).query(&query_parameters);
139        authentication.execute(
140            builder,
141            "GET",
142            &url,
143            &query_parameters
144                .iter()
145                .map(|it| (it.0, it.1.as_str()))
146                .collect::<Vec<_>>(),
147        )
148    }
149
150    pub async fn execute(
151        &self,
152        authentication: &impl Authentication,
153    ) -> Result<(Response, Headers), Error> {
154        execute_twitter(|| self.build(authentication), &self.twapi_options).await
155    }
156}
157
158#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
159pub struct Response {
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub data: Option<Vec<Users>>,
162    #[serde(skip_serializing_if = "Option::is_none")]
163    pub errors: Option<Vec<Errors>>,
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub includes: Option<Includes>,
166    #[serde(skip_serializing_if = "Option::is_none")]
167    pub meta: Option<Meta>,
168    #[serde(flatten)]
169    pub extra: std::collections::HashMap<String, serde_json::Value>,
170}
171
172impl Response {
173    pub fn is_empty_extra(&self) -> bool {
174        let res = self.extra.is_empty()
175            && self
176                .data
177                .as_ref()
178                .map(|it| it.iter().all(|item| item.is_empty_extra()))
179                .unwrap_or(true)
180            && self
181                .errors
182                .as_ref()
183                .map(|it| it.iter().all(|item| item.is_empty_extra()))
184                .unwrap_or(true)
185            && self
186                .includes
187                .as_ref()
188                .map(|it| it.is_empty_extra())
189                .unwrap_or(true)
190            && self
191                .meta
192                .as_ref()
193                .map(|it| it.is_empty_extra())
194                .unwrap_or(true);
195        if !res {
196            println!("Response {:?}", self.extra);
197        }
198        res
199    }
200}