xenon_lib/client/
mod.rs

1use reqwest::{Client, Method};
2use serde::de::DeserializeOwned;
3use serde::Serialize;
4use serde_json::Value;
5
6use crate::wire::{
7    ApiError, BackupCreateFlags, BackupCreateRequestWire, BackupInfoWire, BackupLoadFlags,
8    BackupLoadRequestWire, BackupMetaWire,
9};
10
11#[derive(Clone, Debug)]
12pub struct XenonApiClient {
13    host: String,
14    client: Client,
15}
16
17type ApiResult<T> = Result<T, ApiError>;
18
19impl XenonApiClient {
20    pub fn new(host: String) -> Self {
21        Self {
22            host,
23            client: Client::new(), // use builder
24        }
25    }
26
27    pub async fn request<T: DeserializeOwned, D: Serialize>(
28        &self,
29        method: Method,
30        path: &str,
31        data: &D,
32    ) -> ApiResult<T> {
33        let url = format!("{}{}", self.host, path);
34
35        let resp = self
36            .client
37            .request(method, &url)
38            .json(data)
39            .send()
40            .await
41            .map_err(|e| ApiError::Unexpected {
42                message: "sending api request failed".into(),
43                details: Some(e.to_string().into()),
44            })?
45            .json::<Value>()
46            .await
47            .map_err(|e| ApiError::Unexpected {
48                message: "parsing api response failed".into(),
49                details: Some(e.to_string().into()),
50            })?;
51
52        if let Some(Value::Bool(true)) = resp.get("success") {
53            Ok(serde_json::from_value(resp.get("data").unwrap().clone()).unwrap())
54        } else {
55            Err(serde_json::from_value(resp).unwrap())
56        }
57    }
58
59    pub async fn backup_create(
60        &self,
61        guild_id: u64,
62        flags: BackupCreateFlags,
63        message_count: u32,
64    ) -> ApiResult<BackupMetaWire> {
65        let path = format!("/guilds/{}/backups", guild_id);
66        let data = BackupCreateRequestWire {
67            message_count,
68            flags: flags.bits(),
69        };
70        self.request(Method::POST, &path, &data).await
71    }
72
73    pub async fn backup_delete(&self, backup_id: &str) -> ApiResult<()> {
74        let path = format!("/backups/{}", backup_id);
75        self.request(Method::DELETE, &path, &()).await
76    }
77
78    pub async fn backup_get(&self, backup_id: &str) -> ApiResult<BackupInfoWire> {
79        let path = format!("/backups/{}", backup_id);
80        self.request(Method::GET, &path, &()).await
81    }
82
83    pub async fn backup_list(&self) -> ApiResult<Vec<BackupMetaWire>> {
84        self.request(Method::GET, "/backups", &()).await
85    }
86
87    pub async fn backup_load(
88        &self,
89        guild_id: u64,
90        backup_id: &str,
91        flags: BackupLoadFlags,
92        message_count: u32,
93    ) -> ApiResult<()> {
94        let path = format!("/guilds/{}/backups/{}", guild_id, backup_id);
95        let data = BackupLoadRequestWire {
96            message_count,
97            flags: flags.bits(),
98        };
99        self.request(Method::POST, &path, &data).await
100    }
101}