tweety_rs/api/
user.rs

1//! User Interaction API's
2//!
3//!
4//!
5//!
6//!
7//!
8
9use crate::api::client::TweetyClient;
10use crate::api::error::TweetyError;
11use crate::types::types::ResponseWithHeaders;
12use crate::types::user::UserResponse;
13use reqwest::Method;
14use serde::{Deserialize, Serialize};
15
16#[derive(Debug, Deserialize, Serialize)]
17pub struct UserInfo {
18    pub data: UserResponse,
19}
20
21#[derive(Debug, Deserialize, Serialize)]
22#[serde(rename_all = "snake_case")]
23pub enum Expansions {
24    PinnedTweetId,
25}
26
27#[derive(Debug, Deserialize, Serialize)]
28#[serde(rename_all = "snake_case")]
29pub enum TweetFields {
30    Attachments,
31    AuthorId,
32    ContextAnnotations,
33    ConversationId,
34    CreatedAt,
35    EditControls,
36    Entities,
37    Geo,
38    Id,
39    InReplyToUserId,
40    Lang,
41    NonPublicMetrics,
42    PublicMetrics,
43    OrganicMetrics,
44    PromotedMetrics,
45    PossiblySensitive,
46    ReferencedTweets,
47    ReplySettings,
48    Source,
49    Text,
50    Withheld,
51}
52
53#[derive(Debug, Deserialize, Serialize)]
54#[serde(rename_all = "snake_case")]
55pub enum UserFields {
56    CreatedAt,
57    Description,
58    Entities,
59    Id,
60    Location,
61    MostRecentTweetId,
62    Name,
63    PinnedTweetId,
64    ProfileImageUrl,
65    Protected,
66    PublicMetrics,
67    Url,
68    Username,
69    Verified,
70    VerifiedType,
71    Withheld,
72}
73
74#[derive(Debug, Serialize, Deserialize)]
75pub struct UserQueryParams {
76    pub expansions: Option<Expansions>,
77    pub tweet_fields: Option<Vec<TweetFields>>,
78    pub user_fields: Option<Vec<UserFields>>,
79}
80
81impl UserQueryParams {
82    /// Construct querys params from the provided optional parameters
83    pub fn construct_query_string(&self) -> String {
84        let mut query = vec![];
85
86        if let Some(expansion) = &self.expansions {
87            let serialized_expansion = serde_json::to_string(expansion)
88                .unwrap()
89                .trim_matches('"')
90                .to_string();
91            query.push(format!("expansions={}", serialized_expansion));
92        }
93
94        if let Some(tweet_fields) = &self.tweet_fields {
95            let fields = tweet_fields
96                .iter()
97                .map(|f| {
98                    serde_json::to_string(f)
99                        .unwrap()
100                        .trim_matches('"')
101                        .to_string()
102                })
103                .collect::<Vec<_>>()
104                .join(",");
105            query.push(format!("tweet.fields={}", fields));
106        }
107
108        if let Some(user_fields) = &self.user_fields {
109            let fields = user_fields
110                .iter()
111                .map(|f| {
112                    serde_json::to_string(f)
113                        .unwrap()
114                        .trim_matches('"')
115                        .to_string()
116                })
117                .collect::<Vec<_>>()
118                .join(",");
119            query.push(format!("user.fields={}", fields));
120        }
121        query.join("&")
122    }
123}
124/// Users lookup
125/// API reference index
126
127impl TweetyClient {
128    /// Fetches detailed information about a user specified by their ID.
129    ///
130    /// # Arguments
131    ///
132    /// * `user_id` - The ID of the user to retrieve information about.
133    /// * `params` - Additional query parameters to include in the request, such as expansions or specific fields.
134    ///
135    /// # Returns
136    ///
137    /// A `Result` containing a `Response` with the user data if successful, or a `TweetyError` if an error occurs.
138    ///
139    /// # Examples
140    ///
141    /// ```rust
142    /// use tweety_rs::api::client::TweetyClient;
143    /// use tweety_rs::api::error::TweetyError;
144    /// use tweety_rs::api::user::UserQueryParams;
145    ///
146    /// async fn example() -> Result<(), TweetyError> {
147    ///     let client = TweetyClient::new("your_consumer_key","your_access_token","your_consumer_key_secret","your_access_token_secret");
148    ///     let user_id = "12345";
149    ///     let params = None;
150    ///
151    ///     let response = client.get_user_by_id(user_id, params).await?;
152    ///     println!("{:?}", response);
153    ///     Ok(())
154    /// }
155    /// ```
156    pub async fn get_user_by_id(
157        &self,
158        user_id: &str,
159        params: Option<UserQueryParams>,
160    ) -> Result<ResponseWithHeaders, TweetyError> {
161        let query_string = if let Some(params) = params {
162            params.construct_query_string()
163        } else {
164            String::new()
165        };
166        let url = format!("https://api.x.com/2/users/{}?{}", user_id, query_string);
167        self.send_request::<()>(&url, Method::GET, None).await
168    }
169
170    /// <https://developer.x.com/en/docs/x-api/users/lookup/api-reference/get-users#tab1>
171    /// Endpoint URL: https://api.x.com/2/users
172    /// Fetches detailed information about one or more users specified by their IDs.
173    pub async fn get_users(
174        &self,
175        ids: Vec<String>,
176        params: Option<UserQueryParams>,
177    ) -> Result<ResponseWithHeaders, TweetyError> {
178        let ids_string = ids.join(",");
179        let query_string = if let Some(params) = params {
180            params.construct_query_string()
181        } else {
182            String::new()
183        };
184
185        let url = format!(
186            "https://api.x.com/2/users?ids={}&{}",
187            ids_string, query_string
188        );
189        self.send_request::<()>(&url, Method::GET, None).await
190    }
191    ///  Returns a variety of information about one or more users specified by their usernames.
192    ///  Required 	string	A comma separated list of user IDs. Up to 100 are allowed in a single request.
193    /// Make sure to not include a space between commas and fields.
194    pub async fn get_users_by_username(
195        &self,
196        username: &[&str],
197    ) -> Result<ResponseWithHeaders, TweetyError> {
198        let url = format!(
199            "https://api.x.com/2/users/by/username/{}",
200            username.join(",")
201        );
202        self.send_request::<()>(&url, Method::GET, None).await
203    }
204    /// GET /2/users/by
205    /// Returns a variety of information about one or more users specified by their usernames.
206    /// usernames
207    ///  Required 	string A comma separated list of Twitter usernames (handles).
208    /// Up to 100 are allowed in a single request. Make sure to not include a space between commas and fields.
209    pub async fn get_users_by_usernames(
210        &self,
211        user_names: &[&str],
212        params: Option<UserQueryParams>,
213    ) -> Result<ResponseWithHeaders, TweetyError> {
214        let query_string = if let Some(params) = params {
215            params.construct_query_string()
216        } else {
217            String::new()
218        };
219
220        let url = format!(
221            "https://api.x.com/2/users/by/?username={}&{}",
222            user_names.join(","),
223            query_string
224        );
225
226        self.send_request::<()>(&url, Method::GET, None).await
227    }
228    /// Returns information about an authorized user.
229    /// <https://developer.x.com/en/docs/x-api/users/lookup/api-reference/get-users-me#>
230    pub async fn get_user_me(
231        &self,
232        params: Option<UserQueryParams>,
233    ) -> Result<ResponseWithHeaders, TweetyError> {
234        let query_string = if let Some(params) = params {
235            params.construct_query_string()
236        } else {
237            String::new()
238        };
239        let url = format!("https://api.x.com/2/users/me?{}", query_string);
240
241        self.send_request::<()>(&url, Method::GET, None).await
242    }
243}