twapi_v2/api/
get_2_dm_events.rs

1use crate::fields::{
2    dm_event_fields::DmEventFields, media_fields::MediaFields, tweet_fields::TweetFields,
3    user_fields::UserFields,
4};
5use crate::responses::{dm_events::DmEvents, errors::Errors, includes::Includes, meta::Meta};
6use crate::{
7    api::{apply_options, execute_twitter, make_url, Authentication, TwapiOptions},
8    error::Error,
9    headers::Headers,
10};
11use itertools::Itertools;
12use reqwest::RequestBuilder;
13use serde::{Deserialize, Serialize};
14use std::collections::HashSet;
15
16const URL: &str = "/2/dm_events";
17
18#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Clone)]
19pub enum EventTypes {
20    #[serde(rename = "MessageCreate")]
21    Messagecreate,
22    #[serde(rename = "ParticipantsJoin")]
23    Participantsjoin,
24    #[serde(rename = "ParticipantsLeave")]
25    Participantsleave,
26}
27
28impl std::fmt::Display for EventTypes {
29    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
30        match self {
31            Self::Messagecreate => write!(f, "MessageCreate"),
32            Self::Participantsjoin => write!(f, "ParticipantsJoin"),
33            Self::Participantsleave => write!(f, "ParticipantsLeave"),
34        }
35    }
36}
37
38impl Default for EventTypes {
39    fn default() -> Self {
40        Self::Messagecreate
41    }
42}
43
44#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Clone)]
45pub enum Expansions {
46    #[serde(rename = "attachments.media_keys")]
47    AttachmentsMediaKeys,
48    #[serde(rename = "referenced_tweets.id")]
49    ReferencedTweetsId,
50    #[serde(rename = "sender_id")]
51    SenderId,
52    #[serde(rename = "participant_ids")]
53    ParticipantIds,
54}
55
56impl Expansions {
57    pub fn all() -> HashSet<Self> {
58        let mut result = HashSet::new();
59        result.insert(Self::AttachmentsMediaKeys);
60        result.insert(Self::ReferencedTweetsId);
61        result.insert(Self::SenderId);
62        result.insert(Self::ParticipantIds);
63        result
64    }
65}
66
67impl std::fmt::Display for Expansions {
68    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
69        match self {
70            Self::AttachmentsMediaKeys => write!(f, "attachments.media_keys"),
71            Self::ReferencedTweetsId => write!(f, "referenced_tweets.id"),
72            Self::SenderId => write!(f, "sender_id"),
73            Self::ParticipantIds => write!(f, "participant_ids"),
74        }
75    }
76}
77
78impl Default for Expansions {
79    fn default() -> Self {
80        Self::AttachmentsMediaKeys
81    }
82}
83
84#[derive(Debug, Clone, Default)]
85pub struct Api {
86    dm_event_fields: Option<HashSet<DmEventFields>>,
87    event_types: Option<EventTypes>,
88    expansions: Option<HashSet<Expansions>>,
89    max_results: Option<usize>,
90    media_fields: Option<HashSet<MediaFields>>,
91    pagination_token: Option<String>,
92    tweet_fields: Option<HashSet<TweetFields>>,
93    user_fields: Option<HashSet<UserFields>>,
94    twapi_options: Option<TwapiOptions>,
95}
96
97impl Api {
98    pub fn new() -> Self {
99        Self {
100            ..Default::default()
101        }
102    }
103
104    pub fn all() -> Self {
105        Self {
106            dm_event_fields: Some(DmEventFields::all()),
107            expansions: Some(Expansions::all()),
108            media_fields: Some(MediaFields::all()),
109            tweet_fields: Some(TweetFields::organic()),
110            user_fields: Some(UserFields::all()),
111            max_results: Some(100),
112            ..Default::default()
113        }
114    }
115
116    pub fn open() -> Self {
117        Self {
118            dm_event_fields: Some(DmEventFields::all()),
119            expansions: Some(Expansions::all()),
120            media_fields: Some(MediaFields::open()),
121            tweet_fields: Some(TweetFields::open()),
122            user_fields: Some(UserFields::all()),
123            max_results: Some(100),
124            ..Default::default()
125        }
126    }
127
128    pub fn dm_event_fields(mut self, value: HashSet<DmEventFields>) -> Self {
129        self.dm_event_fields = Some(value);
130        self
131    }
132
133    pub fn event_types(mut self, value: EventTypes) -> Self {
134        self.event_types = Some(value);
135        self
136    }
137
138    pub fn expansions(mut self, value: HashSet<Expansions>) -> Self {
139        self.expansions = Some(value);
140        self
141    }
142
143    pub fn max_results(mut self, value: usize) -> Self {
144        self.max_results = Some(value);
145        self
146    }
147
148    pub fn media_fields(mut self, value: HashSet<MediaFields>) -> Self {
149        self.media_fields = Some(value);
150        self
151    }
152
153    pub fn pagination_token(mut self, value: &str) -> Self {
154        self.pagination_token = Some(value.to_owned());
155        self
156    }
157
158    pub fn tweet_fields(mut self, value: HashSet<TweetFields>) -> Self {
159        self.tweet_fields = Some(value);
160        self
161    }
162
163    pub fn user_fields(mut self, value: HashSet<UserFields>) -> Self {
164        self.user_fields = Some(value);
165        self
166    }
167
168    pub fn twapi_options(mut self, value: TwapiOptions) -> Self {
169        self.twapi_options = Some(value);
170        self
171    }
172
173    pub fn build(self, authentication: &impl Authentication) -> RequestBuilder {
174        let mut query_parameters = vec![];
175        if let Some(dm_event_fields) = self.dm_event_fields {
176            query_parameters.push(("dm_event.fields", dm_event_fields.iter().join(",")));
177        }
178        if let Some(event_types) = self.event_types {
179            query_parameters.push(("event_types", event_types.to_string()));
180        }
181        if let Some(expansions) = self.expansions {
182            query_parameters.push(("expansions", expansions.iter().join(",")));
183        }
184        if let Some(max_results) = self.max_results {
185            query_parameters.push(("max_results", max_results.to_string()));
186        }
187        if let Some(media_fields) = self.media_fields {
188            query_parameters.push(("media.fields", media_fields.iter().join(",")));
189        }
190        if let Some(pagination_token) = self.pagination_token {
191            query_parameters.push(("pagination_token", pagination_token));
192        }
193        if let Some(tweet_fields) = self.tweet_fields {
194            query_parameters.push(("tweet.fields", tweet_fields.iter().join(",")));
195        }
196        if let Some(user_fields) = self.user_fields {
197            query_parameters.push(("user.fields", user_fields.iter().join(",")));
198        }
199        let client = reqwest::Client::new();
200        let url = make_url(&self.twapi_options, URL);
201        let builder = client.get(&url).query(&query_parameters);
202        authentication.execute(
203            apply_options(builder, &self.twapi_options),
204            "GET",
205            &url,
206            &query_parameters
207                .iter()
208                .map(|it| (it.0, it.1.as_str()))
209                .collect::<Vec<_>>(),
210        )
211    }
212
213    pub async fn execute(
214        self,
215        authentication: &impl Authentication,
216    ) -> Result<(Response, Headers), Error> {
217        execute_twitter(self.build(authentication)).await
218    }
219}
220
221#[derive(Serialize, Deserialize, Debug, Clone, Default)]
222pub struct Response {
223    #[serde(skip_serializing_if = "Option::is_none")]
224    pub data: Option<Vec<DmEvents>>,
225    #[serde(skip_serializing_if = "Option::is_none")]
226    pub errors: Option<Vec<Errors>>,
227    #[serde(skip_serializing_if = "Option::is_none")]
228    pub includes: Option<Includes>,
229    #[serde(skip_serializing_if = "Option::is_none")]
230    pub meta: Option<Meta>,
231    #[serde(flatten)]
232    pub extra: std::collections::HashMap<String, serde_json::Value>,
233}
234
235impl Response {
236    pub fn is_empty_extra(&self) -> bool {
237        let res = self.extra.is_empty()
238            && self
239                .data
240                .as_ref()
241                .map(|it| it.iter().all(|item| item.is_empty_extra()))
242                .unwrap_or(true)
243            && self
244                .errors
245                .as_ref()
246                .map(|it| it.iter().all(|item| item.is_empty_extra()))
247                .unwrap_or(true)
248            && self
249                .includes
250                .as_ref()
251                .map(|it| it.is_empty_extra())
252                .unwrap_or(true)
253            && self
254                .meta
255                .as_ref()
256                .map(|it| it.is_empty_extra())
257                .unwrap_or(true);
258        if !res {
259            println!("Response {:?}", self.extra);
260        }
261        res
262    }
263}