agent_twitter_client/api/
requests.rs

1use crate::error::Result;
2use reqwest::multipart::Form;
3use reqwest::{Client, header::HeaderMap, Method};
4use serde::de::DeserializeOwned;
5
6pub async fn request_api<T>(
7    client: &Client,
8    url: &str,
9    headers: HeaderMap,
10    method: Method,
11    body: Option<serde_json::Value>,
12) -> Result<(T, HeaderMap)>
13where
14    T: DeserializeOwned,
15{
16    let mut request = client
17        .request(method, url)
18        .headers(headers);
19
20    if let Some(json_body) = body {
21        request = request.json(&json_body);
22    }
23
24    let response = request.send().await?;
25
26    if response.status().is_success() {
27        let headers = response.headers().clone();
28        let text = response.text().await?;
29        let parsed: T = serde_json::from_str(&text)?;
30        Ok((parsed, headers))
31    } else {
32        Err(crate::error::TwitterError::Api(format!(
33            "Request failed with status: {}",
34            response.status()
35        )))
36    }
37}
38
39pub async fn get_guest_token(client: &Client, bearer_token: &str) -> Result<String> {
40    let mut headers = HeaderMap::new();
41    headers.insert(
42        "Authorization",
43        format!("Bearer {}", bearer_token).parse().unwrap(),
44    );
45
46    let (response, _) = request_api::<serde_json::Value>(
47        client,
48        "https://api.twitter.com/1.1/guest/activate.json",
49        headers,
50        Method::POST,
51        None,
52    )
53    .await?;
54
55    response
56        .get("guest_token")
57        .and_then(|token| token.as_str())
58        .map(String::from)
59        .ok_or_else(|| crate::error::TwitterError::Auth("Failed to get guest token".into()))
60}
61
62pub async fn request_multipart_api<T>(
63    client: &Client,
64    url: &str,
65    headers: HeaderMap,
66    form: Form,
67) -> Result<(T, HeaderMap)>
68where
69    T: DeserializeOwned,
70{
71    let request = client
72        .request(Method::POST, url)
73        .headers(headers)
74        .multipart(form);
75
76    let response = request.send().await?;
77
78    if response.status().is_success() {
79        let headers = response.headers().clone();
80        let text = response.text().await?;
81        let parsed: T = serde_json::from_str(&text)?;
82        Ok((parsed, headers))
83    } else {
84        Err(crate::error::TwitterError::Api(format!(
85            "Request failed with status: {}",
86            response.status()
87        )))
88    }
89}
90
91pub async fn request_form_api<T>(
92    client: &Client,
93    url: &str,
94    headers: HeaderMap,
95    form_data: Vec<(String, String)>,
96) -> Result<(T, HeaderMap)>
97where
98    T: DeserializeOwned,
99{
100    let request = client
101        .request(Method::POST, url)
102        .headers(headers)
103        .form(&form_data);
104
105    let response = request.send().await?;
106
107    if response.status().is_success() {
108        let headers = response.headers().clone();
109        let text = response.text().await?;
110        let parsed: T = serde_json::from_str(&text)?;
111        Ok((parsed, headers))
112    } else {
113        Err(crate::error::TwitterError::Api(format!(
114            "Request failed with status: {}",
115            response.status()
116        )))
117    }
118}