1use crate::Error;
4use crate::api::v4::ApiV4Client;
5use crate::api::v4::models::*;
6use crate::api::v4::uri::*;
7
8impl ApiV4Client {
10 pub async fn upload_file(&self, request: &UploadRequest<'_>) -> Result<File, Error> {
11 let response: ApiResponse<File> = self.post("/file", request).await?;
12 match response.data {
13 Some(data) => Ok(data),
14 None => Err(Error::InvalidResponse(format!(
15 "API returned no data for upload_file request: {:?}",
16 response
17 ))),
18 }
19 }
20
21 pub async fn list_files(&self, request: &ListFilesRequest<'_>) -> Result<ListResponse, Error> {
33 let mut url = "/file".to_string();
34 let uri = match request.path.strip_prefix('/') {
38 Some(path) => path_to_uri(path),
39 None => path_to_uri(request.path),
40 };
41 url.push_str(&format!("?uri={}", urlencoding::encode(&uri)));
42 if let Some(page) = request.page {
43 url.push_str(&format!("&page={}", page));
44 }
45 if let Some(page_size) = request.page_size {
46 url.push_str(&format!("&page_size={}", page_size));
47 }
48 if let Some(order_by) = request.order_by {
49 url.push_str(&format!("&order_by={}", order_by));
50 }
51 if let Some(order_direction) = request.order_direction {
52 url.push_str(&format!("&order_direction={}", order_direction));
53 }
54 if let Some(next_page_token) = request.next_page_token {
55 url.push_str(&format!(
56 "&next_page_token={}",
57 urlencoding::encode(next_page_token)
58 ));
59 }
60
61 let response: ApiResponse<ListResponse> = self.get(&url).await?;
62 match response.data {
63 Some(data) => Ok(data),
64 None => Err(Error::InvalidResponse(format!(
65 "API returned no data for list_files request: {:?}",
66 response
67 ))),
68 }
69 }
70
71 pub async fn get_file_info(&self, file_path: &str) -> Result<File, Error> {
72 let uri = path_to_uri(file_path);
74 let response: ApiResponse<File> = self.get(&format!("/file/info?uri={}", uri)).await?;
75 match response.data {
76 Some(data) => Ok(data),
77 None => Err(Error::InvalidResponse(format!(
78 "API returned no data for get_file_info request: {:?}",
79 response
80 ))),
81 }
82 }
83
84 pub async fn get_file_stat(&self, file_path: &str) -> Result<FileStat, Error> {
85 let response: ApiResponse<FileStat> =
86 self.get(&format!("/file/stat/{}", file_path)).await?;
87 match response.data {
88 Some(data) => Ok(data),
89 None => Err(Error::InvalidResponse(format!(
90 "API returned no data for get_file_stat request: {:?}",
91 response
92 ))),
93 }
94 }
95
96 pub async fn search_files(
101 &self,
102 request: &SearchFilesRequest<'_>,
103 ) -> Result<ListResponse, Error> {
104 let uri = search_uri(request.path, request.keyword, request.case_folding);
105 self.list_files(&ListFilesRequest {
106 path: &uri,
107 page: request.page,
108 page_size: request.page_size,
109 order_by: None,
110 order_direction: None,
111 next_page_token: request.next_page_token,
112 })
113 .await
114 }
115
116 pub async fn move_file(&self, request: &MoveFileRequest<'_>) -> Result<(), Error> {
122 let response: ApiResponse<serde_json::Value> = self.post("/file/move", request).await?;
123 match response.code {
124 0 => Ok(()),
125 _ => Err(response.into_error()),
126 }
127 }
128
129 pub async fn copy_file(&self, request: &CopyFileRequest<'_>) -> Result<(), Error> {
133 let move_request = MoveFileRequest {
135 uris: request.uris.clone(),
136 dst: request.dst,
137 copy: Some(true),
138 };
139 self.move_file(&move_request).await
140 }
141
142 pub async fn rename_file(
143 &self,
144 request: &RenameFileRequest<'_>,
145 ) -> Result<crate::api::v4::models::File, Error> {
146 let response: ApiResponse<crate::api::v4::models::File> =
147 self.post("/file/rename", request).await?;
148 match response.data {
149 Some(data) => Ok(data),
150 None => Err(Error::InvalidResponse(format!(
151 "API returned no data for rename_file request: {:?}",
152 response
153 ))),
154 }
155 }
156
157 pub async fn delete_file(&self, file_path: &str) -> Result<(), Error> {
158 let request = DeleteFileRequest {
159 uris: vec![file_path],
160 unlink: None,
161 skip_soft_delete: None,
162 };
163 self.delete_files(&request).await
164 }
165
166 pub async fn delete_files(&self, request: &DeleteFileRequest<'_>) -> Result<(), Error> {
178 let uris = paths_to_uris(&request.uris);
179 let converted = DeleteFileRequest {
180 uris: uris.iter().map(|s| s.as_str()).collect(),
181 unlink: request.unlink,
182 skip_soft_delete: request.skip_soft_delete,
183 };
184 let response: ApiResponse<serde_json::Value> =
185 self.delete_with_body("/file", &converted).await?;
186 match response.code {
187 0 => Ok(()),
188 _ => Err(response.into_error()),
189 }
190 }
191
192 pub async fn unlock_files(&self, request: &UnlockFilesRequest<'_>) -> Result<(), Error> {
199 if request.tokens.is_empty() {
200 return Ok(());
201 }
202 let response: ApiResponse<serde_json::Value> =
203 self.delete_with_body("/file/lock", request).await?;
204 match response.code {
205 0 => Ok(()),
206 _ => Err(response.into_error()),
207 }
208 }
209
210 pub async fn create_directory(&self, path: &str) -> Result<(), Error> {
211 let uri = path_to_uri(path);
212 let request = CreateFileRequest {
213 uri: &uri,
214 r#type: CreateFileType::Folder,
215 metadata: None,
216 err_on_conflict: None,
217 };
218 let response: ApiResponse<serde_json::Value> = self.post("/file/create", &request).await?;
222 match response.code {
223 0 => Ok(()),
224 _ => Err(response.into_error()),
225 }
226 }
227
228 pub async fn set_file_permission(
229 &self,
230 request: &SetFilePermissionRequest<'_>,
231 ) -> Result<(), Error> {
232 let response: ApiResponse<()> = self.post("/file/permission", request).await?;
233 match response.code {
234 0 => Ok(()),
235 code => Err(Error::Api {
236 code,
237 message: response.msg,
238 }),
239 }
240 }
241
242 pub async fn delete_file_permission(&self, path: &str) -> Result<(), Error> {
243 let uri = path_to_uri(path);
244 let response: ApiResponse<()> = self
245 .delete(&format!("/file/permission?uri={}", uri))
246 .await?;
247 match response.code {
248 0 => Ok(()),
249 code => Err(Error::Api {
250 code,
251 message: response.msg,
252 }),
253 }
254 }
255
256 pub async fn create_upload_session(
257 &self,
258 request: &CreateUploadSessionRequest<'_>,
259 ) -> Result<UploadSessionResponse, Error> {
260 let response: ApiResponse<UploadSessionResponse> =
261 self.put("/file/upload", request).await?;
262 match response.data {
263 Some(data) => Ok(data),
264 None => Err(Error::InvalidResponse(format!(
265 "API returned no data for create_upload_session request: {:?}",
266 response
267 ))),
268 }
269 }
270
271 pub async fn upload_file_chunk(
272 &self,
273 session_id: &str,
274 index: u32,
275 chunk_data: &[u8],
276 ) -> Result<(), Error> {
277 let url = format!("/file/upload/{}/{}", session_id, index);
278 let full_url = self.get_url(&url);
279
280 let mut request = self.http_client.post(&full_url).body(chunk_data.to_vec());
281
282 if let Some(token) = &self.token {
283 request = request.bearer_auth(token);
284 }
285
286 let response = request.send().await?;
287 let status = response.status();
288
289 if !status.is_success() {
290 let error_text = response
291 .text()
292 .await
293 .unwrap_or_else(|_| "Unknown error".to_string());
294 return Err(Error::Api {
295 code: status.as_u16() as i32,
296 message: error_text,
297 });
298 }
299
300 Ok(())
301 }
302
303 pub async fn delete_upload_session(&self, path: &str, session_id: &str) -> Result<(), Error> {
304 let uri = path_to_uri(path);
305 let request = DeleteUploadSessionRequest {
306 id: session_id,
307 uri: &uri,
308 };
309 let url = self.get_url("/file/upload");
310
311 let body = serde_json::to_string(&request)?;
312
313 let mut http_req = self.http_client.delete(&url);
314 if let Some(token) = &self.token {
315 http_req = http_req.bearer_auth(token);
316 }
317
318 let response = http_req
319 .header("Content-Type", "application/json")
320 .body(body)
321 .send()
322 .await?;
323
324 let status = response.status();
325 if !status.is_success() {
326 let error_text = response
327 .text()
328 .await
329 .unwrap_or_else(|_| "Unknown error".to_string());
330 return Err(Error::Api {
331 code: status.as_u16() as i32,
332 message: error_text,
333 });
334 }
335
336 Ok(())
337 }
338
339 pub async fn get_thumbnail_url(
340 &self,
341 path: &str,
342 width: Option<u32>,
343 height: Option<u32>,
344 ) -> Result<String, Error> {
345 let uri = path_to_uri(path);
346 let mut url = format!("/file/thumb?uri={}", uri);
347 if let Some(w) = width {
348 url.push_str(&format!("&width={}", w));
349 }
350 if let Some(h) = height {
351 url.push_str(&format!("&height={}", h));
352 }
353
354 let response: ApiResponse<String> = self.get(&url).await?;
355 match response.data {
356 Some(data) => Ok(data),
357 None => Err(Error::InvalidResponse(format!(
358 "API returned no data for get_thumbnail_url request: {:?}",
359 response
360 ))),
361 }
362 }
363
364 pub async fn get_file_content(&self, path: &str) -> Result<String, Error> {
365 let uri = path_to_uri(path);
366 let response: ApiResponse<String> = self.get(&format!("/file/content?uri={}", uri)).await?;
367 match response.data {
368 Some(data) => Ok(data),
369 None => Err(Error::InvalidResponse(format!(
370 "API returned no data for get_file_content request: {:?}",
371 response
372 ))),
373 }
374 }
375
376 pub async fn update_file_content(
377 &self,
378 request: &UpdateFileContentRequest<'_>,
379 ) -> Result<(), Error> {
380 let response: ApiResponse<()> = self.put("/file/content", request).await?;
381 match response.code {
382 0 => Ok(()),
383 code => Err(Error::Api {
384 code,
385 message: response.msg,
386 }),
387 }
388 }
389
390 pub async fn create_viewer_session(
391 &self,
392 request: &CreateViewerSessionRequest<'_>,
393 ) -> Result<ViewerSessionResponse, Error> {
394 let response: ApiResponse<ViewerSessionResponse> =
395 self.put("/file/viewerSession", request).await?;
396 match response.data {
397 Some(data) => Ok(data),
398 None => Err(Error::InvalidResponse(format!(
399 "API returned no data for create_viewer_session request: {:?}",
400 response
401 ))),
402 }
403 }
404
405 pub async fn create_file(&self, request: &CreateFileRequest<'_>) -> Result<File, Error> {
407 let uri = path_to_uri(request.uri);
408 let converted = CreateFileRequest {
409 uri: &uri,
410 r#type: request.r#type,
411 metadata: request.metadata.clone(),
412 err_on_conflict: request.err_on_conflict,
413 };
414 let response: ApiResponse<File> = self.post("/file/create", &converted).await?;
415 if response.code != 0 {
416 return Err(Error::Api {
417 code: response.code,
418 message: response.msg,
419 });
420 }
421 match response.data {
422 Some(data) => Ok(data),
423 None => Err(Error::InvalidResponse(format!(
424 "API returned no data for create_file request: {:?}",
425 response
426 ))),
427 }
428 }
429
430 pub async fn rename_multiple(&self, request: &RenameMultipleRequest<'_>) -> Result<(), Error> {
431 let response: ApiResponse<()> = self.post("/file/rename", request).await?;
432 match response.code {
433 0 => Ok(()),
434 code => Err(Error::Api {
435 code,
436 message: response.msg,
437 }),
438 }
439 }
440
441 pub async fn move_copy_files(&self, request: &MoveCopyFileRequest<'_>) -> Result<(), Error> {
447 let move_request = MoveFileRequest {
448 uris: request.from.clone(),
449 dst: request.to,
450 copy: request.copy,
451 };
452 self.move_file(&move_request).await
453 }
454
455 pub async fn create_download_url(
456 &self,
457 request: &CreateDownloadUrlRequest<'_>,
458 ) -> Result<DownloadUrlResponse, Error> {
459 let uris = paths_to_uris(&request.uris);
460 let uris_refs: Vec<&str> = uris.iter().map(|s| s.as_str()).collect();
461
462 let converted_request = CreateDownloadUrlRequest {
463 uris: uris_refs,
464 download: request.download,
465 redirect: request.redirect,
466 entity: request.entity,
467 use_primary_site_url: request.use_primary_site_url,
468 skip_error: request.skip_error,
469 archive: request.archive,
470 no_cache: request.no_cache,
471 };
472
473 let response: ApiResponse<DownloadUrlResponse> =
474 self.post("/file/url", &converted_request).await?;
475 match response.data {
476 Some(data) => Ok(data),
477 None => Err(Error::InvalidResponse(format!(
478 "API returned no data for create_download_url request: {:?}",
479 response
480 ))),
481 }
482 }
483
484 pub async fn restore_from_trash(&self, request: &RestoreFileRequest<'_>) -> Result<(), Error> {
485 let uris = paths_to_uris(&request.uris);
486 let uris_refs: Vec<&str> = uris.iter().map(|s| s.as_str()).collect();
487
488 let converted_request = RestoreFileRequest { uris: uris_refs };
489
490 let response: ApiResponse<()> = self.post("/file/restore", &converted_request).await?;
491 match response.code {
492 0 => Ok(()),
493 code => Err(Error::Api {
494 code,
495 message: response.msg,
496 }),
497 }
498 }
499
500 pub async fn force_unlock(&self, path: &str) -> Result<(), Error> {
501 let uri = path_to_uri(path);
502 let response: ApiResponse<()> = self.delete(&format!("/file/lock?uri={}", uri)).await?;
503 match response.code {
504 0 => Ok(()),
505 code => Err(Error::Api {
506 code,
507 message: response.msg,
508 }),
509 }
510 }
511
512 pub async fn patch_metadata(
513 &self,
514 path: &str,
515 request: &UpdateMetadataRequest,
516 ) -> Result<(), Error> {
517 let uri = path_to_uri(path);
518 let full_url = format!("/file/metadata?uri={}", uri);
519 let response: ApiResponse<()> = self.patch(&full_url, request).await?;
520 match response.code {
521 0 => Ok(()),
522 code => Err(Error::Api {
523 code,
524 message: response.msg,
525 }),
526 }
527 }
528
529 pub async fn mount_storage_policy(
530 &self,
531 path: &str,
532 request: &MountStoragePolicyRequest,
533 ) -> Result<(), Error> {
534 let uri = path_to_uri(path);
535 let full_url = format!("/file/policy?uri={}", uri);
536 let response: ApiResponse<()> = self.patch(&full_url, request).await?;
537 match response.code {
538 0 => Ok(()),
539 code => Err(Error::Api {
540 code,
541 message: response.msg,
542 }),
543 }
544 }
545
546 pub async fn update_view_settings(
547 &self,
548 path: &str,
549 request: &UpdateViewRequest,
550 ) -> Result<(), Error> {
551 let uri = path_to_uri(path);
552 let full_url = format!("/file/view?uri={}", uri);
553 let response: ApiResponse<()> = self.patch(&full_url, request).await?;
554 match response.code {
555 0 => Ok(()),
556 code => Err(Error::Api {
557 code,
558 message: response.msg,
559 }),
560 }
561 }
562
563 pub async fn get_file_activities(
564 &self,
565 path: &str,
566 page: Option<u32>,
567 page_size: Option<u32>,
568 ) -> Result<FileActivitiesResponse, Error> {
569 let uri = path_to_uri(path);
570 let mut url = format!("/file/activities?uri={}", uri);
571 if let Some(p) = page {
572 url.push_str(&format!("&page={}", p));
573 }
574 if let Some(ps) = page_size {
575 url.push_str(&format!("&page_size={}", ps));
576 }
577
578 let response: ApiResponse<FileActivitiesResponse> = self.get(&url).await?;
579 match response.data {
580 Some(data) => Ok(data),
581 None => Err(Error::InvalidResponse(format!(
582 "API returned no data for get_file_activities request: {:?}",
583 response
584 ))),
585 }
586 }
587
588 pub async fn get_file_info_extended(
589 &self,
590 request: &GetFileInfoRequest<'_>,
591 ) -> Result<File, Error> {
592 let uri = path_to_uri(request.uri);
593 let mut url = format!("/file/info?uri={}", uri);
594 if let Some(include_extended) = request.include_extended_info {
595 url.push_str(&format!("&extended={}", include_extended));
596 }
597
598 let response: ApiResponse<File> = self.get(&url).await?;
599 match response.data {
600 Some(data) => Ok(data),
601 None => Err(Error::InvalidResponse(format!(
602 "API returned no data for get_file_info_extended request: {:?}",
603 response
604 ))),
605 }
606 }
607
608 pub async fn get_archive_list(
609 &self,
610 request: &GetArchiveListRequest<'_>,
611 ) -> Result<ArchiveListResponse, Error> {
612 let uri = path_to_uri(request.uri);
613 let url = format!("/file/archive?uri={}", uri);
614
615 let response: ApiResponse<ArchiveListResponse> = self.get(&url).await?;
616 match response.data {
617 Some(data) => Ok(data),
618 None => Err(Error::InvalidResponse(format!(
619 "API returned no data for get_archive_list request: {:?}",
620 response
621 ))),
622 }
623 }
624
625 pub async fn create_direct_link(
636 &self,
637 request: &CreateDirectLinkRequest<'_>,
638 ) -> Result<Vec<DirectLinkItem>, Error> {
639 let uris = paths_to_uris(&request.uris);
640 let uris_refs: Vec<&str> = uris.iter().map(|s| s.as_str()).collect();
641
642 let converted_request = CreateDirectLinkRequest { uris: uris_refs };
643
644 let response: ApiResponse<Vec<DirectLinkItem>> =
645 self.put("/file/source", &converted_request).await?;
646 match response.data {
647 Some(data) => Ok(data),
648 None => Err(Error::InvalidResponse(format!(
649 "API returned no data for create_direct_link request: {:?}",
650 response
651 ))),
652 }
653 }
654
655 pub async fn delete_direct_link(&self, id: &str) -> Result<(), Error> {
662 let response: ApiResponse<()> = self.delete(&format!("/file/source{}", id)).await?;
663 match response.code {
664 0 => Ok(()),
665 code => Err(Error::Api {
666 code,
667 message: response.msg,
668 }),
669 }
670 }
671}