1pub mod account;
2pub mod agent;
3pub mod auth;
4pub mod client;
5pub mod config;
6pub mod credential;
7pub mod friend;
8pub mod profile;
9
10use std::ops::Deref;
11
12use reqwest::RequestBuilder;
13use serde::{de::DeserializeOwned, Deserialize};
14use thiserror::Error;
15
16#[derive(Debug, Error)]
17#[error(transparent)]
18#[non_exhaustive]
19pub enum RequestError {
20 Reqwest(#[from] reqwest::Error),
21 Json(#[from] serde_json::Error),
22 Url(#[from] url::ParseError),
23}
24
25pub type RequestResult<T> = Result<T, RequestError>;
26
27#[derive(Debug, Error)]
28pub enum ApiError {
29 #[error(transparent)]
30 Request(RequestError),
31
32 #[error("api responded with error. status: {0}")]
33 Status(i32),
34}
35
36impl<T: Into<RequestError>> From<T> for ApiError {
37 fn from(value: T) -> Self {
38 Self::Request(value.into())
39 }
40}
41
42pub type ApiResult<T> = Result<T, ApiError>;
43
44pub(crate) async fn read_response(request: RequestBuilder) -> ApiResult<impl Deref<Target = [u8]>> {
45 #[derive(Debug, Clone, Copy, Deserialize)]
46 struct ApiStatus {
47 pub status: i32,
48 }
49
50 let data = request.send().await?.bytes().await?;
51
52 match serde_json::from_slice::<ApiStatus>(&data)?.status {
53 0 => Ok(data),
54 status => Err(ApiError::Status(status)),
55 }
56}
57
58pub(crate) async fn read_structured_response<T: DeserializeOwned>(
59 request: RequestBuilder,
60) -> ApiResult<T> {
61 Ok(serde_json::from_slice(&read_response(request).await?)?)
62}