context69_sdk/client/library/
files.rs1use context69_contracts::{
2 LibraryFileDetailResponse, LibraryFileUploadMetadata, LibraryUploadResponse, MoveFileRequest,
3 PrepareLibraryUploadRequest, PrepareLibraryUploadResponse,
4};
5use reqwest::{Method, multipart::Part};
6use sha2::{Digest, Sha256};
7use uuid::Uuid;
8
9use super::Context69Client;
10use crate::{
11 Error,
12 client::transport::{file_upload_form, file_upload_form_with_sha256},
13};
14
15pub struct LibraryFilesApi<'a> {
16 client: &'a Context69Client,
17 base_path: String,
18}
19
20impl<'a> LibraryFilesApi<'a> {
21 pub(super) fn new(client: &'a Context69Client, base_path: String) -> Self {
22 Self { client, base_path }
23 }
24
25 pub async fn upload(
26 &self,
27 folder_id: Option<Uuid>,
28 files: Vec<Part>,
29 ) -> Result<LibraryUploadResponse, Error> {
30 let path = format!("{}/files/upload", self.base_path);
31 self.client
32 .execute_json(
33 self.client
34 .authorized_request(Method::POST, &path)
35 .await?
36 .multipart(file_upload_form(folder_id, files)),
37 )
38 .await
39 }
40
41 pub async fn prepare_upload(
42 &self,
43 request: &PrepareLibraryUploadRequest,
44 ) -> Result<PrepareLibraryUploadResponse, Error> {
45 let path = format!("{}/files/prepare-upload", self.base_path);
46 self.client
47 .execute_json(
48 self.client
49 .authorized_request(Method::POST, &path)
50 .await?
51 .json(request),
52 )
53 .await
54 }
55
56 pub async fn upload_bytes_deduplicated(
57 &self,
58 folder_id: Option<Uuid>,
59 filename: impl Into<String>,
60 media_type: impl Into<String>,
61 bytes: Vec<u8>,
62 ) -> Result<LibraryUploadResponse, Error> {
63 self.upload_bytes_deduplicated_with_metadata(folder_id, filename, media_type, bytes, None)
64 .await
65 }
66
67 pub async fn upload_bytes_deduplicated_with_metadata(
68 &self,
69 folder_id: Option<Uuid>,
70 filename: impl Into<String>,
71 media_type: impl Into<String>,
72 bytes: Vec<u8>,
73 metadata: Option<LibraryFileUploadMetadata>,
74 ) -> Result<LibraryUploadResponse, Error> {
75 let filename = filename.into();
76 let media_type = media_type.into();
77 let sha256: String = Sha256::digest(&bytes)
78 .iter()
79 .map(|byte| format!("{byte:02x}"))
80 .collect();
81 let prepared = self
82 .prepare_upload(&PrepareLibraryUploadRequest {
83 folder_id,
84 filename: filename.clone(),
85 media_type: media_type.clone(),
86 size_bytes: bytes.len() as i64,
87 sha256: sha256.clone(),
88 metadata: metadata.clone(),
89 })
90 .await?;
91 if !prepared.upload_required {
92 return Ok(LibraryUploadResponse {
93 files: prepared.file.into_iter().collect(),
94 jobs: prepared.job.into_iter().collect(),
95 });
96 }
97
98 let part = Part::bytes(bytes)
99 .file_name(filename)
100 .mime_str(&media_type)?;
101 let path = format!("{}/files/upload", self.base_path);
102 self.client
103 .execute_json(
104 self.client
105 .authorized_request(Method::POST, &path)
106 .await?
107 .multipart(file_upload_form_with_sha256(
108 folder_id,
109 sha256,
110 metadata.as_ref(),
111 part,
112 )?),
113 )
114 .await
115 }
116}
117
118pub struct LibraryFileApi<'a> {
119 client: &'a Context69Client,
120 base_path: String,
121 file_id: Uuid,
122}
123
124impl<'a> LibraryFileApi<'a> {
125 pub(super) fn new(client: &'a Context69Client, base_path: String, file_id: Uuid) -> Self {
126 Self {
127 client,
128 base_path,
129 file_id,
130 }
131 }
132
133 pub async fn get(&self) -> Result<LibraryFileDetailResponse, Error> {
134 let path = format!("{}/files/{}", self.base_path, self.file_id);
135 self.client
136 .execute_json(self.client.authorized_request(Method::GET, &path).await?)
137 .await
138 }
139
140 pub async fn move_to(
141 &self,
142 request: &MoveFileRequest,
143 ) -> Result<LibraryFileDetailResponse, Error> {
144 let path = format!("{}/files/{}/move", self.base_path, self.file_id);
145 self.client
146 .execute_json(
147 self.client
148 .authorized_request(Method::POST, &path)
149 .await?
150 .json(request),
151 )
152 .await
153 }
154
155 pub async fn delete(&self) -> Result<(), Error> {
156 let path = format!("{}/files/{}", self.base_path, self.file_id);
157 self.client
158 .execute_empty(
159 self.client
160 .authorized_request(Method::DELETE, &path)
161 .await?,
162 )
163 .await
164 }
165}