open_lark/service/cloud_docs/drive/v1/
files.rs1use log;
2use reqwest::Method;
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 core::{
7 api_req::ApiRequest,
8 api_resp::{ApiResponseTrait, BaseResponse, BinaryResponse, ResponseFormat},
9 config::Config,
10 constants::AccessTokenType,
11 endpoints::cloud_docs::*,
12 http::Transport,
13 req_option::RequestOption,
14 standard_response::StandardResponse,
15 validation::{validate_file_name, validate_upload_file, ValidateBuilder, ValidationResult},
16 SDKResult,
17 },
18 impl_executable_builder_owned,
19};
20
21pub struct FilesService {
22 config: Config,
23}
24
25#[derive(Debug, Clone, Default, Serialize, Deserialize)]
27pub struct UploadAllRequest {
28 #[serde(skip)]
30 api_req: ApiRequest,
31 file_name: String,
35 parent_type: String,
39 parent_node: String,
43 size: i32,
47 checksum: Option<String>,
49}
50
51impl UploadAllRequest {
52 pub fn builder() -> UploadAllRequestBuilder {
53 UploadAllRequestBuilder::default()
54 }
55}
56
57#[derive(Default)]
59pub struct UploadAllRequestBuilder {
60 request: UploadAllRequest,
61}
62
63impl UploadAllRequestBuilder {
64 pub fn file_name(mut self, file_name: impl ToString) -> Self {
66 self.request.file_name = file_name.to_string();
67 self
68 }
69
70 pub fn parent_type(mut self, parent_type: impl ToString) -> Self {
72 self.request.parent_type = parent_type.to_string();
73 self
74 }
75
76 pub fn parent_node(mut self, parent_node: impl ToString) -> Self {
78 self.request.parent_node = parent_node.to_string();
79 self
80 }
81
82 pub fn size(mut self, size: i32) -> Self {
84 self.request.size = size;
85 self
86 }
87
88 pub fn checksum(mut self, checksum: impl ToString) -> Self {
90 self.request.checksum = Some(checksum.to_string());
91 self
92 }
93
94 pub fn file(mut self, file: Vec<u8>) -> Self {
96 self.request.api_req.file = file;
97 self
98 }
99
100 pub fn build(mut self) -> UploadAllRequest {
101 if self.request.file_name.is_empty() {
103 log::error!("file_name is required for upload");
104 return UploadAllRequest {
105 api_req: ApiRequest {
106 body: Vec::new(),
107 ..Default::default()
108 },
109 ..self.request
110 };
111 }
112
113 if self.request.parent_type.is_empty() {
114 log::error!("parent_type is required for upload");
115 return UploadAllRequest {
116 api_req: ApiRequest {
117 body: Vec::new(),
118 ..Default::default()
119 },
120 ..self.request
121 };
122 }
123
124 if self.request.parent_node.is_empty() {
125 log::error!("parent_node is required for upload");
126 return UploadAllRequest {
127 api_req: ApiRequest {
128 body: Vec::new(),
129 ..Default::default()
130 },
131 ..self.request
132 };
133 }
134
135 if self.request.size <= 0 {
137 log::error!("file size must be greater than 0");
138 return UploadAllRequest {
139 api_req: ApiRequest {
140 body: Vec::new(),
141 ..Default::default()
142 },
143 ..self.request
144 };
145 }
146
147 let (_, name_result) = validate_file_name(&self.request.file_name);
149 if !name_result.is_valid() {
150 log::error!(
151 "Invalid file_name: {}",
152 name_result.error().unwrap_or("unknown error")
153 );
154 return UploadAllRequest {
155 api_req: ApiRequest {
156 body: Vec::new(),
157 ..Default::default()
158 },
159 ..self.request
160 };
161 }
162
163 if !self.request.api_req.file.is_empty() {
165 let upload_result =
166 validate_upload_file(&self.request.api_req.file, &self.request.file_name, false);
167 if !upload_result.is_valid() {
168 log::error!(
169 "File validation failed: {}",
170 upload_result.error().unwrap_or("unknown error")
171 );
172 return UploadAllRequest {
173 api_req: ApiRequest {
174 body: Vec::new(),
175 ..Default::default()
176 },
177 ..self.request
178 };
179 }
180 }
181
182 self.request.api_req.body = match serde_json::to_vec(&self.request) {
183 Ok(body) => body,
184 Err(e) => {
185 log::error!("Failed to serialize upload request: {}", e);
186 return UploadAllRequest {
187 api_req: ApiRequest {
188 body: Vec::new(),
189 ..Default::default()
190 },
191 ..self.request
192 };
193 }
194 };
195 self.request
196 }
197}
198
199impl ValidateBuilder for UploadAllRequestBuilder {
200 fn validate(&self) -> ValidationResult {
201 if self.request.file_name.is_empty() {
203 return ValidationResult::Invalid("file_name is required".to_string());
204 }
205
206 if self.request.parent_type.is_empty() {
207 return ValidationResult::Invalid("parent_type is required".to_string());
208 }
209
210 if self.request.parent_node.is_empty() {
211 return ValidationResult::Invalid("parent_node is required".to_string());
212 }
213
214 if self.request.size <= 0 {
216 return ValidationResult::Invalid("file size must be greater than 0".to_string());
217 }
218
219 let (_, name_result) = validate_file_name(&self.request.file_name);
221 if !name_result.is_valid() {
222 return name_result;
223 }
224
225 if !self.request.api_req.file.is_empty() {
227 validate_upload_file(&self.request.api_req.file, &self.request.file_name, false)
228 } else {
229 ValidationResult::Valid
230 }
231 }
232}
233
234impl FilesService {
235 pub fn new(config: Config) -> Self {
236 Self { config }
237 }
238
239 pub fn upload_all_builder(&self) -> UploadAllRequestBuilder {
241 UploadAllRequestBuilder::default()
242 }
243
244 pub fn download_builder(&self) -> DownloadRequestBuilder {
246 DownloadRequestBuilder::default()
247 }
248
249 pub async fn upload_all_with_builder(
251 &self,
252 builder_result: SDKResult<UploadAllRequest>,
253 option: Option<RequestOption>,
254 ) -> SDKResult<UploadAllResponse> {
255 let request = builder_result?;
256 self.upload_all(request, option).await
257 }
258
259 pub async fn upload_all(
261 &self,
262 upload_all_request: UploadAllRequest,
263 option: Option<RequestOption>,
264 ) -> SDKResult<UploadAllResponse> {
265 let mut api_req = upload_all_request.api_req;
266 api_req.http_method = Method::POST;
267 api_req.api_path = DRIVE_V1_FILES_UPLOAD_ALL.to_string();
268 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
269
270 let api_resp: BaseResponse<UploadAllResponse> =
271 Transport::request(api_req, &self.config, option).await?;
272
273 api_resp.into_result()
274 }
275
276 pub async fn download(
278 &self,
279 request: DownloadRequest,
280 option: Option<RequestOption>,
281 ) -> SDKResult<BinaryResponse> {
282 let mut api_req = request.api_req;
283 api_req.http_method = Method::GET;
284 api_req.api_path = DRIVE_V1_FILE_DOWNLOAD.replace("{}", &request.file_token);
285 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
286
287 let api_resp: BaseResponse<BinaryResponse> =
288 Transport::request(api_req, &self.config, option).await?;
289
290 api_resp.into_result()
291 }
292}
293
294#[derive(Debug, Serialize, Deserialize)]
296pub struct UploadAllResponse {
297 pub file_token: String,
299}
300
301impl ApiResponseTrait for UploadAllResponse {
302 fn data_format() -> ResponseFormat {
303 ResponseFormat::Data
304 }
305}
306
307#[derive(Default, Serialize, Deserialize)]
309pub struct DownloadRequest {
310 #[serde(skip)]
312 api_req: ApiRequest,
313 file_token: String,
315}
316
317#[derive(Default)]
319pub struct DownloadRequestBuilder {
320 req: DownloadRequest,
321}
322
323impl DownloadRequestBuilder {
324 pub fn file_token(mut self, file_token: impl ToString) -> Self {
325 self.req.file_token = file_token.to_string();
326 self
327 }
328
329 pub fn build(self) -> DownloadRequest {
330 self.req
331 }
332}
333
334impl DownloadRequest {
335 pub fn builder() -> DownloadRequestBuilder {
336 DownloadRequestBuilder::default()
337 }
338}
339
340impl_executable_builder_owned!(
343 UploadAllRequestBuilder,
344 FilesService,
345 UploadAllRequest,
346 UploadAllResponse,
347 upload_all
348);
349
350impl_executable_builder_owned!(
351 DownloadRequestBuilder,
352 FilesService,
353 DownloadRequest,
354 BinaryResponse,
355 download
356);