mod bundle;
mod comment;
mod post;
mod showcase;
mod subscription_level;
mod target;
mod user;
use crate::auth_provider::AuthProvider;
use crate::error::{ApiError, ResultApi, ResultAuth};
use reqwest::header::{ACCEPT, CACHE_CONTROL, HeaderMap, HeaderValue, USER_AGENT};
use reqwest::{Client, Response, multipart};
const DEFAULT_PAGE_SIZE: usize = 20;
#[derive(Debug, Clone)]
pub struct ApiClient {
base_url: String,
client: Client,
headers: HeaderMap,
auth_provider: AuthProvider,
}
impl ApiClient {
pub fn new(client: Client, base_url: impl Into<String> + Clone) -> Self {
let base_url = base_url.into();
let headers = Self::prepare_headers();
let auth_provider = AuthProvider::new(client.clone(), base_url.clone());
Self {
base_url,
client,
headers,
auth_provider,
}
}
fn prepare_headers() -> HeaderMap {
let mut headers = HeaderMap::new();
headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
headers.insert(
USER_AGENT,
HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"),
);
headers.insert(CACHE_CONTROL, HeaderValue::from_static("no-cache"));
headers.insert("DNT", HeaderValue::from_static("1"));
headers
}
pub async fn set_bearer_token(&self, access_token: &str) -> ResultAuth<()> {
self.auth_provider
.set_access_token_only(access_token.to_string())
.await
}
pub async fn set_refresh_token_and_device_id(
&self,
refresh_token: &str,
device_id: &str,
) -> ResultAuth<()> {
self.auth_provider
.set_refresh_token_and_device_id(refresh_token.to_string(), device_id.to_string())
.await
}
pub async fn clear_refresh_and_device_id(&self) {
self.auth_provider.clear_refresh_and_device_id().await
}
pub async fn clear_access_token(&self) {
self.auth_provider.clear_access_token().await
}
pub fn headers_as_map(&self) -> std::collections::HashMap<String, String> {
self.headers
.iter()
.filter_map(|(k, v)| {
v.to_str()
.ok()
.map(|value| (k.to_string(), value.to_string()))
})
.collect()
}
async fn get_request(&self, path: &str) -> ResultApi<Response> {
let mut headers = self.headers.clone();
self.auth_provider.apply_auth_header(&mut headers).await?;
let url = format!("{}/v1/{}", self.base_url, path);
self.client
.get(&url)
.headers(headers)
.send()
.await
.map_err(ApiError::HttpRequest)
}
async fn post_request<T: serde::Serialize + ?Sized>(
&self,
path: &str,
body: &T,
as_form: bool,
) -> ResultApi<Response> {
let mut headers = self.headers.clone();
self.auth_provider.apply_auth_header(&mut headers).await?;
let url = format!("{}/v1/{}", self.base_url, path);
let builder = self.client.post(&url).headers(headers);
let request = if as_form {
builder.form(body)
} else {
builder.json(body)
};
request.send().await.map_err(ApiError::HttpRequest)
}
async fn post_multipart(&self, path: &str, form: multipart::Form) -> ResultApi<Response> {
let mut headers = self.headers.clone();
self.auth_provider.apply_auth_header(&mut headers).await?;
headers.remove("Content-Type");
let url = format!("{}/v1/{}", self.base_url, path);
let request = self.client.post(&url).headers(headers).multipart(form);
request.send().await.map_err(ApiError::HttpRequest)
}
async fn delete_request(&self, path: &str) -> ResultApi<Response> {
let mut headers = self.headers.clone();
self.auth_provider.apply_auth_header(&mut headers).await?;
let url = format!("{}/v1/{}", self.base_url, path);
self.client
.delete(&url)
.headers(headers)
.send()
.await
.map_err(ApiError::HttpRequest)
}
async fn put_request<T: serde::Serialize + ?Sized>(
&self,
path: &str,
body: &T,
as_form: bool,
) -> ResultApi<Response> {
let mut headers = self.headers.clone();
self.auth_provider.apply_auth_header(&mut headers).await?;
let url = format!("{}/v1/{}", self.base_url, path);
let builder = self.client.put(&url).headers(headers);
let request = if as_form {
builder.form(body)
} else {
builder.json(body)
};
request.send().await.map_err(ApiError::HttpRequest)
}
}