1use reqwest::{Response, header::AUTHORIZATION, multipart::Form};
19use serde::Serialize;
20
21pub mod file;
22pub mod site;
23
24pub struct Unauthenticated;
25pub struct Authenticated {
26 token: String,
27}
28
29#[derive(Debug, Clone)]
30pub struct Client<S> {
31 base_url: String,
32 http: reqwest::Client,
33 state: S,
34}
35
36impl Client<Unauthenticated> {
37 pub fn new(user_agent: &str) -> anyhow::Result<Self> {
38 Ok(Self {
39 base_url: "https://nekoweb.org/api".into(),
40 http: reqwest::Client::builder().user_agent(user_agent).build()?,
41 state: Unauthenticated,
42 })
43 }
44
45 pub fn authenticate(self, token: String) -> Client<Authenticated> {
46 Client {
47 state: Authenticated { token },
48 base_url: self.base_url,
49 http: self.http,
50 }
51 }
52
53 async fn get(&self, path: impl Into<String>) -> anyhow::Result<Response> {
54 Ok(self
55 .http
56 .get(format!("{}{}", &self.base_url, path.into()))
57 .send()
58 .await?
59 .error_for_status()?)
60 }
61}
62
63impl Client<Authenticated> {
64 async fn post<T>(&self, path: impl Into<String>, body: &T) -> anyhow::Result<Response>
65 where
66 T: Serialize,
67 {
68 Ok(self
69 .http
70 .post(format!("{}{}", &self.base_url, path.into()))
71 .header(AUTHORIZATION, &self.state.token)
72 .form(body)
73 .send()
74 .await?
75 .error_for_status()?)
76 }
77
78 async fn multipart(&self, path: impl Into<String>, form: Form) -> anyhow::Result<Response> {
79 Ok(self
80 .http
81 .post(format!("{}{}", &self.base_url, path.into()))
82 .header(AUTHORIZATION, &self.state.token)
83 .multipart(form)
84 .send()
85 .await?
86 .error_for_status()?)
87 }
88
89 async fn get(&self, path: impl Into<String>) -> anyhow::Result<Response> {
90 Ok(self
91 .http
92 .get(format!("{}{}", &self.base_url, path.into()))
93 .header(AUTHORIZATION, &self.state.token)
94 .send()
95 .await?
96 .error_for_status()?)
97 }
98}