twitter_v2/api/
base.rs

1use crate::api_result::{ApiPayload, ApiResponse, ApiResponseExt, ApiResult};
2use crate::authorization::Authorization;
3use crate::error::Result;
4use crate::utils::JsonStream;
5use futures::prelude::*;
6use reqwest::header::AUTHORIZATION;
7use reqwest::{Client, IntoUrl, Method, Url};
8use serde::de::DeserializeOwned;
9use std::sync::Arc;
10
11#[derive(Debug)]
12pub struct TwitterApi<A> {
13    client: Client,
14    base_url: Url,
15    auth: Arc<A>,
16}
17
18impl<A> TwitterApi<A>
19where
20    A: Authorization,
21{
22    pub fn new(auth: A) -> Self {
23        Self {
24            client: Client::builder().pool_max_idle_per_host(0).build().unwrap(),
25            base_url: Url::parse("https://api.twitter.com/2/").unwrap(),
26            auth: Arc::new(auth),
27        }
28    }
29
30    pub fn auth(&self) -> &A {
31        &self.auth
32    }
33
34    pub(crate) fn url(&self, url: impl AsRef<str>) -> Result<Url> {
35        Ok(self.base_url.join(url.as_ref())?)
36    }
37
38    pub(crate) fn request(&self, method: Method, url: impl IntoUrl) -> reqwest::RequestBuilder {
39        self.client.request(method, url)
40    }
41
42    pub(crate) async fn send<T: DeserializeOwned, M: DeserializeOwned>(
43        &self,
44        req: reqwest::RequestBuilder,
45    ) -> ApiResult<A, T, M> {
46        let mut req = req.build()?;
47        let authorization = self.auth.header(&req).await?;
48        let _ = req.headers_mut().insert(AUTHORIZATION, authorization);
49        let url = req.url().clone();
50        let response = self
51            .client
52            .execute(req)
53            .await?
54            .api_error_for_status()
55            .await?
56            .json()
57            .await?;
58        Ok(ApiResponse::new(self, url, response))
59    }
60
61    pub(crate) async fn stream<T: DeserializeOwned, M: DeserializeOwned>(
62        &self,
63        req: reqwest::RequestBuilder,
64    ) -> Result<impl Stream<Item = Result<ApiPayload<T, M>>>> {
65        let mut req = req.build()?;
66        let authorization = self.auth.header(&req).await?;
67        let _ = req.headers_mut().insert(AUTHORIZATION, authorization);
68        Ok(JsonStream::new(
69            self.client
70                .execute(req)
71                .await?
72                .api_error_for_status()
73                .await?
74                .bytes_stream(),
75        ))
76    }
77}
78
79impl<A> Clone for TwitterApi<A> {
80    fn clone(&self) -> Self {
81        Self {
82            client: self.client.clone(),
83            base_url: self.base_url.clone(),
84            auth: self.auth.clone(),
85        }
86    }
87}