1use crate::Error;
4use crate::api::v3::models::ApiResponse;
5use log::debug;
6use serde::Serialize;
7
8pub mod aria2;
9pub mod directory;
10pub mod file;
11pub mod models;
12pub mod object;
13pub mod session;
14pub mod share;
15pub mod site;
16pub mod user;
17
18#[derive(Debug, Clone)]
20pub struct ApiV3Client {
21 pub base_url: String,
22 pub http_client: reqwest::Client,
23 pub session_cookie: Option<String>,
24}
25
26impl ApiV3Client {
27 pub fn new(base_url: &str) -> Self {
28 crate::ensure_tls_crypto_provider();
29
30 Self {
31 base_url: base_url.to_string(),
32 http_client: reqwest::Client::new(),
33 session_cookie: None,
34 }
35 }
36
37 pub fn set_session_cookie(&mut self, cookie: String) {
38 self.session_cookie = Some(cookie);
39 }
40
41 pub fn get_session_cookie(&self) -> Option<&str> {
42 self.session_cookie.as_deref()
43 }
44
45 pub fn clear_session_cookie(&mut self) {
46 self.session_cookie = None;
47 }
48
49 pub fn get_url(&self, endpoint: &str) -> String {
50 format!(
51 "{}/api/v3/{}",
52 self.base_url.trim_end_matches('/'),
53 endpoint.trim_start_matches('/')
54 )
55 }
56
57 pub async fn get<T>(&self, endpoint: &str) -> Result<T, Error>
58 where
59 T: serde::de::DeserializeOwned + std::fmt::Debug,
60 {
61 let url = self.get_url(endpoint);
62 let mut request = self.http_client.get(&url);
63
64 if let Some(cookie) = &self.session_cookie {
65 request = request.header("Cookie", format!("cloudreve-session={}", cookie));
66 debug!("cookie: {}", cookie);
67 }
68
69 debug!("GET URL: {}", url);
70
71 let response = request.send().await?;
72 let status = response.status();
73
74 if !status.is_success() {
76 let raw_text = response.text().await?;
77 if let Ok(api_response) =
78 serde_json::from_str::<ApiResponse<serde_json::Value>>(&raw_text)
79 && api_response.code != 0
80 {
81 return Err(Error::Api {
82 code: api_response.code,
83 message: api_response.msg,
84 });
85 }
86 return Err(Error::Api {
87 code: status.as_u16() as i32,
88 message: raw_text.trim().to_string(),
89 });
90 }
91
92 let raw_text = response.text().await?;
93
94 match serde_json::from_str::<T>(&raw_text) {
95 Ok(json) => {
96 debug!("Response status: {}, JSON: {:?}", status, json);
97 Ok(json)
98 }
99 Err(e) => {
100 debug!("JSON parse error: {}, raw response: {}", e, raw_text);
101 Err(Error::Json(e))
102 }
103 }
104 }
105
106 pub async fn post<T>(&self, endpoint: &str, body: &impl Serialize) -> Result<T, Error>
107 where
108 T: serde::de::DeserializeOwned + std::fmt::Debug,
109 {
110 let url = self.get_url(endpoint);
111 let mut request = self.http_client.post(&url).json(body);
112
113 if let Some(cookie) = &self.session_cookie {
114 request = request.header("Cookie", format!("cloudreve-session={}", cookie));
115 debug!("cookie: {}", cookie);
116 }
117
118 debug!("POST URL: {}", url);
119
120 let response = request.send().await?;
121 let status = response.status();
122
123 if !status.is_success() {
125 let raw_text = response.text().await?;
126 if let Ok(api_response) =
128 serde_json::from_str::<ApiResponse<serde_json::Value>>(&raw_text)
129 && api_response.code != 0
130 {
131 return Err(Error::Api {
132 code: api_response.code,
133 message: api_response.msg,
134 });
135 }
136 return Err(Error::Api {
138 code: status.as_u16() as i32,
139 message: raw_text.trim().to_string(),
140 });
141 }
142
143 let raw_text = response.text().await?;
145
146 match serde_json::from_str::<T>(&raw_text) {
147 Ok(json) => {
148 debug!("Response status: {}, JSON: {:?}", status, json);
149 Ok(json)
150 }
151 Err(e) => {
152 debug!("JSON parse error: {}, raw response: {}", e, raw_text);
153 Err(Error::Json(e))
154 }
155 }
156 }
157
158 pub async fn post_raw(&self, endpoint: &str, body: &impl Serialize) -> Result<String, Error> {
160 let url = self.get_url(endpoint);
161 let mut request = self.http_client.post(&url).json(body);
162
163 if let Some(cookie) = &self.session_cookie {
164 request = request.header("Cookie", format!("cloudreve-session={}", cookie));
165 debug!("cookie: {}", cookie);
166 }
167
168 debug!("POST RAW URL: {}", url);
169
170 let response = request.send().await?;
171 let status = response.status();
172
173 if !status.is_success() {
174 let raw_text = response.text().await?;
175 return Err(Error::Api {
176 code: status.as_u16() as i32,
177 message: raw_text.trim().to_string(),
178 });
179 }
180
181 let text = response.text().await?;
182 debug!("Response status: {}, Text: {:?}", status, text);
183 Ok(text)
184 }
185
186 pub async fn put<T>(&self, endpoint: &str, body: &impl Serialize) -> Result<T, Error>
187 where
188 T: serde::de::DeserializeOwned + std::fmt::Debug,
189 {
190 let url = self.get_url(endpoint);
191 let mut request = self.http_client.put(&url).json(body);
192
193 if let Some(cookie) = &self.session_cookie {
194 request = request.header("Cookie", format!("cloudreve-session={}", cookie));
195 debug!("cookie: {}", cookie);
196 }
197
198 debug!("PUT URL: {}", url);
199
200 let response = request.send().await?;
201 let status = response.status();
202 let json: T = response.json().await?;
203 debug!("Response status: {}, JSON: {:?}", status, json);
204 Ok(json)
205 }
206
207 pub async fn patch<T>(&self, endpoint: &str, body: &impl Serialize) -> Result<T, Error>
208 where
209 T: serde::de::DeserializeOwned + std::fmt::Debug,
210 {
211 let url = self.get_url(endpoint);
212 let mut request = self.http_client.patch(&url).json(body);
213
214 if let Some(cookie) = &self.session_cookie {
215 request = request.header("Cookie", format!("cloudreve-session={}", cookie));
216 debug!("cookie: {}", cookie);
217 }
218
219 debug!("PATCH URL: {}", url);
220
221 let response = request.send().await?;
222 let status = response.status();
223 let json: T = response.json().await?;
224 debug!("Response status: {}, JSON: {:?}", status, json);
225 Ok(json)
226 }
227
228 pub async fn delete<T>(&self, endpoint: &str) -> Result<T, Error>
229 where
230 T: serde::de::DeserializeOwned + std::fmt::Debug,
231 {
232 let url = self.get_url(endpoint);
233 let mut request = self.http_client.delete(&url);
234
235 if let Some(cookie) = &self.session_cookie {
236 request = request.header("Cookie", format!("cloudreve-session={}", cookie));
237 debug!("cookie: {}", cookie);
238 }
239
240 debug!("DELETE URL: {}", url);
241
242 let response = request.send().await?;
243 let status = response.status();
244 let json: T = response.json().await?;
245 debug!("Response status: {}, JSON: {:?}", status, json);
246 Ok(json)
247 }
248
249 pub async fn delete_with_body<T>(
250 &self,
251 endpoint: &str,
252 body: &impl Serialize,
253 ) -> Result<T, Error>
254 where
255 T: serde::de::DeserializeOwned + std::fmt::Debug,
256 {
257 let url = self.get_url(endpoint);
258 let mut request = self.http_client.delete(&url).json(body);
259
260 if let Some(cookie) = &self.session_cookie {
261 request = request.header("Cookie", format!("cloudreve-session={}", cookie));
262 debug!("cookie: {}", cookie);
263 }
264
265 debug!("DELETE WITH BODY URL: {}", url);
266
267 let response = request.send().await?;
268 let status = response.status();
269 let json: T = response.json().await?;
270 debug!("Response status: {}, JSON: {:?}", status, json);
271 Ok(json)
272 }
273
274 pub async fn put_text(&self, endpoint: &str, body: &impl Serialize) -> Result<String, Error> {
276 let url = self.get_url(endpoint);
277 let mut request = self.http_client.put(&url).json(body);
278
279 if let Some(cookie) = &self.session_cookie {
280 request = request.header("Cookie", format!("cloudreve-session={}", cookie));
281 debug!("cookie: {}", cookie);
282 }
283
284 debug!("PUT TEXT URL: {}", url);
285
286 let response = request.send().await?;
287 let status = response.status();
288 let text = response.text().await?;
289 debug!("Response status: {}, Text: {:?}", status, text);
290
291 if !status.is_success() {
292 return Err(Error::Api {
293 code: status.as_u16() as i32,
294 message: text,
295 });
296 }
297
298 Ok(text)
299 }
300}