1#![doc = include_str!("../README.md")]
2
3mod authentication;
4mod bots;
5mod channels;
6mod customisation;
7mod invites;
8mod miscellaneous;
9mod platform_administration;
10mod revolt;
11mod servers;
12mod users;
13
14use rive_models::{authentication::Authentication, ApiError};
15
16type Result<T> = std::result::Result<T, Error>;
17
18pub(crate) mod prelude {
19 pub(crate) use crate::{ep, Client, RequestBuilderExt, ResponseExt, Result};
20}
21
22pub const BASE_URL: &str = "https://api.revolt.chat";
24
25#[derive(Debug, thiserror::Error)]
27pub enum Error {
28 #[error("Serde JSON serialization/deserialization error: {0}")]
30 Serialization(#[from] serde_json::Error),
31
32 #[error("Error while processing an HTTP request: {0}")]
34 HttpRequest(#[from] reqwest::Error),
35
36 #[error("Error returned from API: {0:#?}")]
38 Api(ApiError),
39}
40
41macro_rules! ep {
42 ($self:ident, $ep:literal, $($args:tt)*) => {
43 format!(concat!("{}", $ep), $self.base_url, $($args)*)
44 };
45
46 ($self:ident, $ep:literal) => {
47 format!(concat!("{}", $ep), $self.base_url)
48 };
49
50 (api_root = $api_root:expr, $ep:literal $($args:tt)*) => {
51 format!(concat!("{}", $ep), $api_root, $($args)*)
52 };
53}
54pub(crate) use ep;
55
56trait RequestBuilderExt {
57 fn auth(self, authentication: &Authentication) -> Self;
58}
59
60impl RequestBuilderExt for reqwest::RequestBuilder {
61 fn auth(self, authentication: &Authentication) -> Self {
62 self.header(authentication.header_key(), authentication.value())
63 }
64}
65
66#[async_trait::async_trait]
67trait ResponseExt {
68 async fn process_error(self) -> Result<Self>
69 where
70 Self: Sized;
71}
72
73#[async_trait::async_trait]
74impl ResponseExt for reqwest::Response {
75 async fn process_error(self) -> Result<Self>
76 where
77 Self: Sized,
78 {
79 match self.status().as_u16() {
80 200..=299 => Ok(self),
81 401 => Err(Error::Api(ApiError::Unauthenticated)),
84 _ => Err(Error::Api(self.json().await?)),
85 }
86 }
87}
88
89#[derive(Debug, Clone)]
90pub struct Client {
91 base_url: String,
92 client: reqwest::Client,
93 authentication: Authentication,
94}
95
96impl Client {
97 pub fn new(authentication: Authentication) -> Self {
99 Client::new_base_url(authentication, BASE_URL)
100 }
101
102 pub fn new_base_url(authentication: Authentication, base_url: impl Into<String>) -> Self {
104 Client {
105 base_url: base_url.into(),
106 client: reqwest::Client::new(),
107 authentication,
108 }
109 }
110}