1use std::convert::TryFrom;
6
7use super::*;
8
9use crate::common::RateLimit;
10use crate::cursor::{CursorIter, ListCursor, UserCursor};
11use crate::error::{Error::TwitterError, Result};
12use crate::user::{TwitterUser, UserID};
13use crate::{auth, links, tweet};
14
15pub fn memberships<T: Into<UserID>>(user: T, token: &auth::Token) -> CursorIter<ListCursor> {
20 let params = ParamList::new().add_user_param(user.into());
21 CursorIter::new(links::lists::MEMBERSHIPS, token, Some(params), Some(20))
22}
23
24pub async fn list<'id, T: Into<UserID>>(
36 user: T,
37 owned_first: bool,
38 token: &auth::Token,
39) -> Result<Response<Vec<List>>> {
40 let params = ParamList::new()
41 .add_user_param(user.into())
42 .add_param("reverse", owned_first.to_string());
43
44 let req = get(links::lists::LIST, token, Some(¶ms));
45
46 request_with_json_response(req).await
47}
48
49pub fn subscriptions<T: Into<UserID>>(user: T, token: &auth::Token) -> CursorIter<ListCursor> {
54 let params = ParamList::new().add_user_param(user.into());
55 CursorIter::new(links::lists::SUBSCRIPTIONS, token, Some(params), Some(20))
56}
57
58pub fn ownerships<T: Into<UserID>>(user: T, token: &auth::Token) -> CursorIter<ListCursor> {
63 let params = ParamList::new().add_user_param(user.into());
64 CursorIter::new(links::lists::OWNERSHIPS, token, Some(params), Some(20))
65}
66
67pub async fn show(list: ListID, token: &auth::Token) -> Result<Response<List>> {
69 let params = ParamList::new().add_list_param(list);
70
71 let req = get(links::lists::SHOW, token, Some(¶ms));
72
73 request_with_json_response(req).await
74}
75
76pub fn members(list: ListID, token: &auth::Token) -> CursorIter<UserCursor> {
81 let params = ParamList::new().add_list_param(list);
82
83 CursorIter::new(links::lists::MEMBERS, token, Some(params), Some(20))
84}
85
86pub fn subscribers(list: ListID, token: &auth::Token) -> CursorIter<UserCursor> {
91 let params = ParamList::new().add_list_param(list);
92
93 CursorIter::new(links::lists::SUBSCRIBERS, token, Some(params), Some(20))
94}
95
96pub async fn is_subscribed<'id, T: Into<UserID>>(
98 user: T,
99 list: ListID,
100 token: &auth::Token,
101) -> Result<Response<bool>> {
102 let params = ParamList::new()
103 .add_list_param(list)
104 .add_user_param(user.into());
105
106 let req = get(links::lists::IS_SUBSCRIBER, token, Some(¶ms));
107
108 let out = request_with_json_response::<TwitterUser>(req).await;
109
110 match out {
111 Ok(user) => Ok(Response::map(user, |_| true)),
112 Err(TwitterError(headers, terrs)) => {
113 if terrs.errors.iter().any(|e| e.code == 109) {
114 Ok(Response::new(RateLimit::try_from(&headers)?, false))
119 } else {
120 Err(TwitterError(headers, terrs))
121 }
122 }
123 Err(err) => Err(err),
124 }
125}
126
127pub async fn is_member<'id, T: Into<UserID>>(
129 user: T,
130 list: ListID,
131 token: &auth::Token,
132) -> Result<Response<bool>> {
133 let params = ParamList::new()
134 .add_list_param(list)
135 .add_user_param(user.into());
136
137 let req = get(links::lists::IS_MEMBER, token, Some(¶ms));
138 let out = request_with_json_response::<TwitterUser>(req).await;
139
140 match out {
141 Ok(resp) => Ok(Response::map(resp, |_| true)),
142 Err(TwitterError(headers, errors)) => {
143 if errors.errors.iter().any(|e| e.code == 109) {
144 Ok(Response::new(RateLimit::try_from(&headers)?, false))
149 } else {
150 Err(TwitterError(headers, errors))
151 }
152 }
153 Err(err) => Err(err),
154 }
155}
156
157pub fn statuses(list: ListID, with_rts: bool, token: &auth::Token) -> tweet::Timeline {
164 let params = ParamList::new()
165 .add_list_param(list)
166 .add_param("include_rts", with_rts.to_string());
167
168 tweet::Timeline::new(links::lists::STATUSES, Some(params), token)
169}
170
171pub async fn add_member<'id, T: Into<UserID>>(
177 list: ListID,
178 user: T,
179 token: &auth::Token,
180) -> Result<Response<List>> {
181 let params = ParamList::new()
182 .add_list_param(list)
183 .add_user_param(user.into());
184
185 let req = post(links::lists::ADD, token, Some(¶ms));
186
187 request_with_json_response(req).await
188}
189
190pub async fn add_member_list<'id, T, I>(
204 members: I,
205 list: ListID,
206 token: &auth::Token,
207) -> Result<Response<List>>
208where
209 T: Into<UserID>,
210 I: IntoIterator<Item = T>,
211{
212 let (id_param, name_param) = multiple_names_param(members);
213 let params = ParamList::new()
214 .add_list_param(list)
215 .add_opt_param(
216 "user_id",
217 if !id_param.is_empty() {
218 Some(id_param)
219 } else {
220 None
221 },
222 )
223 .add_opt_param(
224 "screen_name",
225 if !name_param.is_empty() {
226 Some(name_param)
227 } else {
228 None
229 },
230 );
231
232 let req = post(links::lists::ADD_LIST, token, Some(¶ms));
233
234 request_with_json_response(req).await
235}
236
237pub async fn remove_member<'id, T: Into<UserID>>(
239 list: ListID,
240 user: T,
241 token: &auth::Token,
242) -> Result<Response<List>> {
243 let params = ParamList::new()
244 .add_list_param(list)
245 .add_user_param(user.into());
246
247 let req = post(links::lists::REMOVE_MEMBER, token, Some(¶ms));
248
249 request_with_json_response(req).await
250}
251
252pub async fn remove_member_list<T, I>(
265 members: I,
266 list: ListID,
267 token: &auth::Token,
268) -> Result<Response<List>>
269where
270 T: Into<UserID>,
271 I: IntoIterator<Item = T>,
272{
273 let (id_param, name_param) = multiple_names_param(members);
274 let params = ParamList::new()
275 .add_list_param(list)
276 .add_opt_param(
277 "user_id",
278 if !id_param.is_empty() {
279 Some(id_param)
280 } else {
281 None
282 },
283 )
284 .add_opt_param(
285 "screen_name",
286 if !name_param.is_empty() {
287 Some(name_param)
288 } else {
289 None
290 },
291 );
292
293 let req = post(links::lists::REMOVE_LIST, token, Some(¶ms));
294
295 request_with_json_response(req).await
296}
297
298pub async fn create(
304 name: String,
305 public: bool,
306 desc: Option<String>,
307 token: &auth::Token,
308) -> Result<Response<List>> {
309 let params = ParamList::new()
310 .add_param("name", name)
311 .add_param("mode", if public { "public" } else { "private" })
312 .add_opt_param("description", desc);
313
314 let req = post(links::lists::CREATE, token, Some(¶ms));
315
316 request_with_json_response(req).await
317}
318
319pub async fn delete(list: ListID, token: &auth::Token) -> Result<Response<List>> {
323 let params = ParamList::new().add_list_param(list);
324
325 let req = post(links::lists::DELETE, token, Some(¶ms));
326
327 request_with_json_response(req).await
328}
329
330pub async fn subscribe(list: ListID, token: &auth::Token) -> Result<Response<List>> {
335 let params = ParamList::new().add_list_param(list);
336
337 let req = post(links::lists::SUBSCRIBE, token, Some(¶ms));
338
339 request_with_json_response(req).await
340}
341
342pub async fn unsubscribe(list: ListID, token: &auth::Token) -> Result<Response<List>> {
344 let params = ParamList::new().add_list_param(list);
345
346 let req = post(links::lists::UNSUBSCRIBE, token, Some(¶ms));
347
348 request_with_json_response(req).await
349}
350
351pub fn update(list: ListID) -> ListUpdate {
357 ListUpdate {
358 list,
359 name: None,
360 public: None,
361 desc: None,
362 }
363}