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