1use reqwest::Method;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5use crate::core::{
6 api_req::ApiRequest,
7 api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
8 config::Config,
9 constants::AccessTokenType,
10 endpoints::{cloud_docs::*, EndpointBuilder},
11 http::Transport,
12 req_option::RequestOption,
13 trait_system::Service,
14 SDKResult,
15};
16
17pub struct DocumentBlockService {
19 config: Config,
20}
21
22impl DocumentBlockService {
23 pub fn new(config: Config) -> Self {
24 Self { config }
25 }
26
27 pub async fn create(
33 &self,
34 document_id: impl Into<String>,
35 request: CreateBlockRequest,
36 option: Option<RequestOption>,
37 ) -> SDKResult<BaseResponse<CreateBlockRespData>> {
38 let api_req = ApiRequest {
39 http_method: Method::POST,
40 api_path: DOCX_V1_DOCUMENT_BLOCKS.replace("{}", &document_id.into()),
41 supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
42 body: serde_json::to_vec(&request)?,
43 ..Default::default()
44 };
45
46 let api_resp = Transport::request(api_req, &self.config, option).await?;
47 Ok(api_resp)
48 }
49
50 pub async fn get(
56 &self,
57 document_id: impl Into<String>,
58 block_id: impl Into<String>,
59 option: Option<RequestOption>,
60 ) -> SDKResult<BaseResponse<GetBlockRespData>> {
61 let api_req = ApiRequest {
62 http_method: Method::GET,
63 api_path: DOCX_V1_DOCUMENT_BLOCK_GET
64 .replace("{document_id}", &document_id.into())
65 .replace("{block_id}", &block_id.into()),
66 supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
67 ..Default::default()
68 };
69
70 let api_resp = Transport::request(api_req, &self.config, option).await?;
71 Ok(api_resp)
72 }
73
74 pub async fn patch(
80 &self,
81 document_id: impl Into<String>,
82 block_id: impl Into<String>,
83 request: PatchBlockRequest,
84 option: Option<RequestOption>,
85 ) -> SDKResult<BaseResponse<PatchBlockRespData>> {
86 let api_req = ApiRequest {
87 http_method: Method::PATCH,
88 api_path: DOCX_V1_DOCUMENT_BLOCK_GET
89 .replace("{document_id}", &document_id.into())
90 .replace("{block_id}", &block_id.into()),
91 supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
92 body: serde_json::to_vec(&request)?,
93 ..Default::default()
94 };
95
96 let api_resp = Transport::request(api_req, &self.config, option).await?;
97 Ok(api_resp)
98 }
99
100 pub async fn batch_update(
106 &self,
107 document_id: impl Into<String>,
108 request: BatchUpdateBlockRequest,
109 option: Option<RequestOption>,
110 ) -> SDKResult<BaseResponse<BatchUpdateBlockRespData>> {
111 let mut api_req = ApiRequest {
112 http_method: Method::PATCH,
113 api_path: DOCX_V1_DOCUMENT_BLOCKS_BATCH_UPDATE
114 .replace("{document_id}", &document_id.into()),
115 ..Default::default()
116 };
117 api_req.supported_access_token_types = vec![AccessTokenType::User, AccessTokenType::Tenant];
118 api_req.body = serde_json::to_vec(&request)?;
119
120 let api_resp = Transport::request(api_req, &self.config, option).await?;
121 Ok(api_resp)
122 }
123
124 pub async fn batch_delete(
130 &self,
131 document_id: impl Into<String>,
132 request: BatchDeleteBlockRequest,
133 option: Option<RequestOption>,
134 ) -> SDKResult<BaseResponse<BatchDeleteBlockRespData>> {
135 let mut api_req = ApiRequest {
136 http_method: Method::DELETE,
137 api_path: EndpointBuilder::replace_param(
138 DOCX_V1_DOCUMENT_BLOCKS_BATCH_DELETE,
139 "document_id",
140 &document_id.into(),
141 ),
142 ..Default::default()
143 };
144 api_req.supported_access_token_types = vec![AccessTokenType::User, AccessTokenType::Tenant];
145 api_req.body = serde_json::to_vec(&request)?;
146
147 let api_resp = Transport::request(api_req, &self.config, option).await?;
148 Ok(api_resp)
149 }
150
151 pub async fn list_children(
157 &self,
158 document_id: impl Into<String>,
159 block_id: impl Into<String>,
160 request: ListChildrenRequest,
161 option: Option<RequestOption>,
162 ) -> SDKResult<BaseResponse<ListChildrenRespData>> {
163 let document_id_str = document_id.into();
164 let block_id_str = block_id.into();
165 let mut api_req = ApiRequest {
166 http_method: Method::GET,
167 api_path: EndpointBuilder::replace_params_from_array(
168 DOCX_V1_DOCUMENT_BLOCK_CHILDREN,
169 &[
170 ("document_id", &document_id_str),
171 ("block_id", &block_id_str),
172 ],
173 ),
174 supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
175 ..Default::default()
176 };
177
178 if let Some(page_size) = request.page_size {
180 api_req
181 .query_params
182 .insert("page_size", page_size.to_string());
183 }
184 if let Some(page_token) = request.page_token {
185 api_req.query_params.insert("page_token", page_token);
186 }
187
188 let api_resp = Transport::request(api_req, &self.config, option).await?;
189 Ok(api_resp)
190 }
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize, Default)]
197pub struct CreateBlockRequest {
198 pub parent_id: String,
200 pub index: Option<i32>,
202 pub blocks: Vec<BlockData>,
204}
205
206impl CreateBlockRequest {
207 pub fn builder() -> CreateBlockRequestBuilder {
208 CreateBlockRequestBuilder::default()
209 }
210
211 pub fn new(parent_id: impl Into<String>, blocks: Vec<BlockData>) -> Self {
212 Self {
213 parent_id: parent_id.into(),
214 index: None,
215 blocks,
216 }
217 }
218
219 pub fn with_index(mut self, index: i32) -> Self {
220 self.index = Some(index);
221 self
222 }
223}
224
225#[derive(Default)]
227pub struct CreateBlockRequestBuilder {
228 request: CreateBlockRequest,
229 document_id: String,
230}
231
232impl CreateBlockRequestBuilder {
233 pub fn document_id(mut self, document_id: impl Into<String>) -> Self {
234 self.document_id = document_id.into();
235 self
236 }
237
238 pub fn parent_id(mut self, parent_id: impl Into<String>) -> Self {
239 self.request.parent_id = parent_id.into();
240 self
241 }
242
243 pub fn index(mut self, index: i32) -> Self {
244 self.request.index = Some(index);
245 self
246 }
247
248 pub fn blocks(mut self, blocks: Vec<BlockData>) -> Self {
249 self.request.blocks = blocks;
250 self
251 }
252
253 pub fn add_block(mut self, block: BlockData) -> Self {
254 self.request.blocks.push(block);
255 self
256 }
257
258 pub fn build(self) -> (String, CreateBlockRequest) {
259 (self.document_id, self.request)
260 }
261}
262
263#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct BlockData {
266 pub block_type: i32,
268 pub block: Value,
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct CreateBlockRespData {
275 pub blocks: Vec<BlockInfo>,
277 pub document_revision_id: i64,
279}
280
281impl ApiResponseTrait for CreateBlockRespData {
282 fn data_format() -> ResponseFormat {
283 ResponseFormat::Data
284 }
285}
286
287#[derive(Debug, Clone, Serialize, Deserialize)]
289pub struct BlockInfo {
290 pub block_id: String,
292 pub parent_id: String,
294 pub children: Vec<String>,
296 pub block_type: i32,
298 pub index: i32,
300}
301
302#[derive(Debug, Clone, Serialize, Deserialize)]
304pub struct GetBlockRespData {
305 pub block: DetailedBlock,
307}
308
309impl ApiResponseTrait for GetBlockRespData {
310 fn data_format() -> ResponseFormat {
311 ResponseFormat::Data
312 }
313}
314
315#[derive(Debug, Clone, Serialize, Deserialize)]
317pub struct DetailedBlock {
318 pub block_id: String,
320 pub parent_id: String,
322 pub children: Vec<String>,
324 pub block_type: i32,
326 pub index: i32,
328 pub block: Value,
330}
331
332#[derive(Debug, Clone, Serialize, Deserialize)]
334pub struct PatchBlockRequest {
335 pub block: Value,
337}
338
339impl PatchBlockRequest {
340 pub fn new(block: Value) -> Self {
341 Self { block }
342 }
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize)]
347pub struct PatchBlockRespData {
348 pub block: DetailedBlock,
350 pub document_revision_id: i64,
352}
353
354impl ApiResponseTrait for PatchBlockRespData {
355 fn data_format() -> ResponseFormat {
356 ResponseFormat::Data
357 }
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize, Default)]
362pub struct BatchUpdateBlockRequest {
363 pub requests: Vec<UpdateBlockItem>,
365}
366
367#[derive(Debug, Clone, Serialize, Deserialize)]
369pub struct UpdateBlockItem {
370 pub block_id: String,
372 pub block: Value,
374}
375
376impl BatchUpdateBlockRequest {
377 pub fn builder() -> BatchUpdateBlockRequestBuilder {
378 BatchUpdateBlockRequestBuilder::default()
379 }
380
381 pub fn new(requests: Vec<UpdateBlockItem>) -> Self {
382 Self { requests }
383 }
384}
385
386#[derive(Default)]
388pub struct BatchUpdateBlockRequestBuilder {
389 request: BatchUpdateBlockRequest,
390 document_id: String,
391}
392
393impl BatchUpdateBlockRequestBuilder {
394 pub fn document_id(mut self, document_id: impl Into<String>) -> Self {
395 self.document_id = document_id.into();
396 self
397 }
398
399 pub fn requests(mut self, requests: Vec<UpdateBlockItem>) -> Self {
400 self.request.requests = requests;
401 self
402 }
403
404 pub fn add_request(mut self, block_id: impl Into<String>, block: Value) -> Self {
405 self.request.requests.push(UpdateBlockItem {
406 block_id: block_id.into(),
407 block,
408 });
409 self
410 }
411
412 pub fn build(self) -> (String, BatchUpdateBlockRequest) {
413 (self.document_id, self.request)
414 }
415}
416
417#[derive(Debug, Clone, Serialize, Deserialize)]
419pub struct BatchUpdateBlockRespData {
420 pub blocks: Vec<DetailedBlock>,
422 pub document_revision_id: i64,
424}
425
426impl ApiResponseTrait for BatchUpdateBlockRespData {
427 fn data_format() -> ResponseFormat {
428 ResponseFormat::Data
429 }
430}
431
432#[derive(Debug, Clone, Serialize, Deserialize, Default)]
434pub struct BatchDeleteBlockRequest {
435 pub block_ids: Vec<String>,
437}
438
439impl BatchDeleteBlockRequest {
440 pub fn builder() -> BatchDeleteBlockRequestBuilder {
441 BatchDeleteBlockRequestBuilder::default()
442 }
443
444 pub fn new(block_ids: Vec<String>) -> Self {
445 Self { block_ids }
446 }
447}
448
449#[derive(Default)]
451pub struct BatchDeleteBlockRequestBuilder {
452 request: BatchDeleteBlockRequest,
453 document_id: String,
454}
455
456impl BatchDeleteBlockRequestBuilder {
457 pub fn document_id(mut self, document_id: impl Into<String>) -> Self {
458 self.document_id = document_id.into();
459 self
460 }
461
462 pub fn block_ids(mut self, block_ids: Vec<String>) -> Self {
463 self.request.block_ids = block_ids;
464 self
465 }
466
467 pub fn add_block_id(mut self, block_id: impl Into<String>) -> Self {
468 self.request.block_ids.push(block_id.into());
469 self
470 }
471
472 pub fn build(self) -> (String, BatchDeleteBlockRequest) {
473 (self.document_id, self.request)
474 }
475}
476
477#[derive(Debug, Clone, Serialize, Deserialize)]
479pub struct BatchDeleteBlockRespData {
480 pub document_revision_id: i64,
482}
483
484impl ApiResponseTrait for BatchDeleteBlockRespData {
485 fn data_format() -> ResponseFormat {
486 ResponseFormat::Data
487 }
488}
489
490#[derive(Debug, Clone, Serialize, Deserialize)]
492pub struct ListChildrenRequest {
493 pub page_size: Option<i32>,
495 pub page_token: Option<String>,
497}
498
499impl ListChildrenRequest {
500 pub fn new() -> Self {
501 Self {
502 page_size: None,
503 page_token: None,
504 }
505 }
506
507 pub fn with_page_size(mut self, page_size: i32) -> Self {
508 self.page_size = Some(page_size);
509 self
510 }
511
512 pub fn with_page_token(mut self, page_token: impl Into<String>) -> Self {
513 self.page_token = Some(page_token.into());
514 self
515 }
516}
517
518impl Default for ListChildrenRequest {
519 fn default() -> Self {
520 Self::new()
521 }
522}
523
524#[derive(Debug, Clone, Serialize, Deserialize)]
526pub struct ListChildrenRespData {
527 pub items: Vec<DetailedBlock>,
529 pub has_more: bool,
531 pub page_token: Option<String>,
533}
534
535impl ApiResponseTrait for ListChildrenRespData {
536 fn data_format() -> ResponseFormat {
537 ResponseFormat::Data
538 }
539}
540
541macro_rules! impl_execute_with_path {
545 ($builder:ty, $response:ty, $method:ident) => {
546 impl $builder {
547 pub async fn execute(
549 self,
550 service: &DocumentBlockService,
551 option: Option<RequestOption>,
552 ) -> SDKResult<$response> {
553 let (document_id, request) = self.build();
554 service.$method(document_id, request, option).await
555 }
556
557 pub async fn execute_with_options(
559 self,
560 service: &DocumentBlockService,
561 option: RequestOption,
562 ) -> SDKResult<$response> {
563 self.execute(service, Some(option)).await
564 }
565 }
566 };
567}
568
569impl_execute_with_path!(
570 CreateBlockRequestBuilder,
571 BaseResponse<CreateBlockRespData>,
572 create
573);
574
575impl_execute_with_path!(
576 BatchUpdateBlockRequestBuilder,
577 BaseResponse<BatchUpdateBlockRespData>,
578 batch_update
579);
580
581impl_execute_with_path!(
582 BatchDeleteBlockRequestBuilder,
583 BaseResponse<BatchDeleteBlockRespData>,
584 batch_delete
585);
586
587impl Service for DocumentBlockService {
590 fn config(&self) -> &Config {
591 &self.config
592 }
593
594 fn service_name() -> &'static str {
595 "document_block"
596 }
597
598 fn service_version() -> &'static str {
599 "v1"
600 }
601}