talk_api_internal/
lib.rs

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}