twapi_v2/api/
post_2_users_id_following.rs1use crate::responses::errors::Errors;
2use crate::{
3 api::{Authentication, TwapiOptions, execute_twitter, make_url},
4 error::Error,
5 headers::Headers,
6};
7use reqwest::RequestBuilder;
8use serde::{Deserialize, Serialize};
9
10const URL: &str = "/2/users/:id/following";
11
12#[derive(Serialize, Deserialize, Debug, Default, Clone)]
13pub struct Body {
14 pub target_user_id: String,
15}
16
17#[derive(Debug, Clone, Default)]
18pub struct Api {
19 id: String,
20 body: Body,
21 twapi_options: Option<TwapiOptions>,
22}
23
24impl Api {
25 pub fn new(id: &str, body: Body) -> Self {
26 Self {
27 id: id.to_owned(),
28 body,
29 ..Default::default()
30 }
31 }
32
33 pub fn twapi_options(mut self, value: TwapiOptions) -> Self {
34 self.twapi_options = Some(value);
35 self
36 }
37
38 pub fn build(&self, authentication: &impl Authentication) -> RequestBuilder {
39 let client = reqwest::Client::new();
40 let url = make_url(&self.twapi_options, &URL.replace(":id", &self.id));
41 let builder = client.post(&url).json(&self.body);
42 authentication.execute(builder, "POST", &url, &[])
43 }
44
45 pub async fn execute(
46 &self,
47 authentication: &impl Authentication,
48 ) -> Result<(Response, Headers), Error> {
49 execute_twitter(|| self.build(authentication), &self.twapi_options).await
50 }
51}
52
53#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
54pub struct Response {
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub data: Option<Data>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub errors: Option<Vec<Errors>>,
59 #[serde(flatten)]
60 pub extra: std::collections::HashMap<String, serde_json::Value>,
61}
62
63impl Response {
64 pub fn is_empty_extra(&self) -> bool {
65 let res = self.extra.is_empty()
66 && self
67 .data
68 .as_ref()
69 .map(|it| it.is_empty_extra())
70 .unwrap_or(true)
71 && self
72 .errors
73 .as_ref()
74 .map(|it| it.iter().all(|item| item.is_empty_extra()))
75 .unwrap_or(true);
76 if !res {
77 println!("Response {:?}", self.extra);
78 }
79 res
80 }
81}
82
83#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
84pub struct Data {
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub following: Option<bool>,
87 #[serde(skip_serializing_if = "Option::is_none")]
88 pub pending_follow: Option<bool>,
89 #[serde(flatten)]
90 pub extra: std::collections::HashMap<String, serde_json::Value>,
91}
92
93impl Data {
94 pub fn is_empty_extra(&self) -> bool {
95 let res = self.extra.is_empty();
96 if !res {
97 println!("Data {:?}", self.extra);
98 }
99 res
100 }
101}