1use 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 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}
124impl TweetyClient {
128 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 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 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 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 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}