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