use reqwest::Method;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::core::{
api_req::ApiRequest,
api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
config::Config,
constants::AccessTokenType,
endpoints::{cloud_docs::*, EndpointBuilder},
http::Transport,
req_option::RequestOption,
trait_system::Service,
SDKResult,
};
pub struct DocumentBlockService {
config: Config,
}
impl DocumentBlockService {
pub fn new(config: Config) -> Self {
Self { config }
}
pub async fn create(
&self,
document_id: impl Into<String>,
request: CreateBlockRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<CreateBlockRespData>> {
let api_req = ApiRequest {
http_method: Method::POST,
api_path: DOCX_V1_DOCUMENT_BLOCKS.replace("{}", &document_id.into()),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
body: serde_json::to_vec(&request)?,
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn get(
&self,
document_id: impl Into<String>,
block_id: impl Into<String>,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<GetBlockRespData>> {
let api_req = ApiRequest {
http_method: Method::GET,
api_path: DOCX_V1_DOCUMENT_BLOCK_GET
.replace("{document_id}", &document_id.into())
.replace("{block_id}", &block_id.into()),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn patch(
&self,
document_id: impl Into<String>,
block_id: impl Into<String>,
request: PatchBlockRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<PatchBlockRespData>> {
let api_req = ApiRequest {
http_method: Method::PATCH,
api_path: DOCX_V1_DOCUMENT_BLOCK_GET
.replace("{document_id}", &document_id.into())
.replace("{block_id}", &block_id.into()),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
body: serde_json::to_vec(&request)?,
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn batch_update(
&self,
document_id: impl Into<String>,
request: BatchUpdateBlockRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<BatchUpdateBlockRespData>> {
let mut api_req = ApiRequest {
http_method: Method::PATCH,
api_path: DOCX_V1_DOCUMENT_BLOCKS_BATCH_UPDATE
.replace("{document_id}", &document_id.into()),
..Default::default()
};
api_req.supported_access_token_types = vec![AccessTokenType::User, AccessTokenType::Tenant];
api_req.body = serde_json::to_vec(&request)?;
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn batch_delete(
&self,
document_id: impl Into<String>,
request: BatchDeleteBlockRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<BatchDeleteBlockRespData>> {
let mut api_req = ApiRequest {
http_method: Method::DELETE,
api_path: EndpointBuilder::replace_param(
DOCX_V1_DOCUMENT_BLOCKS_BATCH_DELETE,
"document_id",
&document_id.into(),
),
..Default::default()
};
api_req.supported_access_token_types = vec![AccessTokenType::User, AccessTokenType::Tenant];
api_req.body = serde_json::to_vec(&request)?;
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn list_children(
&self,
document_id: impl Into<String>,
block_id: impl Into<String>,
request: ListChildrenRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<ListChildrenRespData>> {
let document_id_str = document_id.into();
let block_id_str = block_id.into();
let mut api_req = ApiRequest {
http_method: Method::GET,
api_path: EndpointBuilder::replace_params_from_array(
DOCX_V1_DOCUMENT_BLOCK_CHILDREN,
&[
("document_id", &document_id_str),
("block_id", &block_id_str),
],
),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
..Default::default()
};
if let Some(page_size) = request.page_size {
api_req
.query_params
.insert("page_size", page_size.to_string());
}
if let Some(page_token) = request.page_token {
api_req.query_params.insert("page_token", page_token);
}
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CreateBlockRequest {
pub parent_id: String,
pub index: Option<i32>,
pub blocks: Vec<BlockData>,
}
impl CreateBlockRequest {
pub fn builder() -> CreateBlockRequestBuilder {
CreateBlockRequestBuilder::default()
}
pub fn new(parent_id: impl Into<String>, blocks: Vec<BlockData>) -> Self {
Self {
parent_id: parent_id.into(),
index: None,
blocks,
}
}
pub fn with_index(mut self, index: i32) -> Self {
self.index = Some(index);
self
}
}
#[derive(Default)]
pub struct CreateBlockRequestBuilder {
request: CreateBlockRequest,
document_id: String,
}
impl CreateBlockRequestBuilder {
pub fn document_id(mut self, document_id: impl Into<String>) -> Self {
self.document_id = document_id.into();
self
}
pub fn parent_id(mut self, parent_id: impl Into<String>) -> Self {
self.request.parent_id = parent_id.into();
self
}
pub fn index(mut self, index: i32) -> Self {
self.request.index = Some(index);
self
}
pub fn blocks(mut self, blocks: Vec<BlockData>) -> Self {
self.request.blocks = blocks;
self
}
pub fn add_block(mut self, block: BlockData) -> Self {
self.request.blocks.push(block);
self
}
pub fn build(self) -> (String, CreateBlockRequest) {
(self.document_id, self.request)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlockData {
pub block_type: i32,
pub block: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateBlockRespData {
pub blocks: Vec<BlockInfo>,
pub document_revision_id: i64,
}
impl ApiResponseTrait for CreateBlockRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlockInfo {
pub block_id: String,
pub parent_id: String,
pub children: Vec<String>,
pub block_type: i32,
pub index: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetBlockRespData {
pub block: DetailedBlock,
}
impl ApiResponseTrait for GetBlockRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DetailedBlock {
pub block_id: String,
pub parent_id: String,
pub children: Vec<String>,
pub block_type: i32,
pub index: i32,
pub block: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PatchBlockRequest {
pub block: Value,
}
impl PatchBlockRequest {
pub fn new(block: Value) -> Self {
Self { block }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PatchBlockRespData {
pub block: DetailedBlock,
pub document_revision_id: i64,
}
impl ApiResponseTrait for PatchBlockRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct BatchUpdateBlockRequest {
pub requests: Vec<UpdateBlockItem>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateBlockItem {
pub block_id: String,
pub block: Value,
}
impl BatchUpdateBlockRequest {
pub fn builder() -> BatchUpdateBlockRequestBuilder {
BatchUpdateBlockRequestBuilder::default()
}
pub fn new(requests: Vec<UpdateBlockItem>) -> Self {
Self { requests }
}
}
#[derive(Default)]
pub struct BatchUpdateBlockRequestBuilder {
request: BatchUpdateBlockRequest,
document_id: String,
}
impl BatchUpdateBlockRequestBuilder {
pub fn document_id(mut self, document_id: impl Into<String>) -> Self {
self.document_id = document_id.into();
self
}
pub fn requests(mut self, requests: Vec<UpdateBlockItem>) -> Self {
self.request.requests = requests;
self
}
pub fn add_request(mut self, block_id: impl Into<String>, block: Value) -> Self {
self.request.requests.push(UpdateBlockItem {
block_id: block_id.into(),
block,
});
self
}
pub fn build(self) -> (String, BatchUpdateBlockRequest) {
(self.document_id, self.request)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BatchUpdateBlockRespData {
pub blocks: Vec<DetailedBlock>,
pub document_revision_id: i64,
}
impl ApiResponseTrait for BatchUpdateBlockRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct BatchDeleteBlockRequest {
pub block_ids: Vec<String>,
}
impl BatchDeleteBlockRequest {
pub fn builder() -> BatchDeleteBlockRequestBuilder {
BatchDeleteBlockRequestBuilder::default()
}
pub fn new(block_ids: Vec<String>) -> Self {
Self { block_ids }
}
}
#[derive(Default)]
pub struct BatchDeleteBlockRequestBuilder {
request: BatchDeleteBlockRequest,
document_id: String,
}
impl BatchDeleteBlockRequestBuilder {
pub fn document_id(mut self, document_id: impl Into<String>) -> Self {
self.document_id = document_id.into();
self
}
pub fn block_ids(mut self, block_ids: Vec<String>) -> Self {
self.request.block_ids = block_ids;
self
}
pub fn add_block_id(mut self, block_id: impl Into<String>) -> Self {
self.request.block_ids.push(block_id.into());
self
}
pub fn build(self) -> (String, BatchDeleteBlockRequest) {
(self.document_id, self.request)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BatchDeleteBlockRespData {
pub document_revision_id: i64,
}
impl ApiResponseTrait for BatchDeleteBlockRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListChildrenRequest {
pub page_size: Option<i32>,
pub page_token: Option<String>,
}
impl ListChildrenRequest {
pub fn new() -> Self {
Self {
page_size: None,
page_token: None,
}
}
pub fn with_page_size(mut self, page_size: i32) -> Self {
self.page_size = Some(page_size);
self
}
pub fn with_page_token(mut self, page_token: impl Into<String>) -> Self {
self.page_token = Some(page_token.into());
self
}
}
impl Default for ListChildrenRequest {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListChildrenRespData {
pub items: Vec<DetailedBlock>,
pub has_more: bool,
pub page_token: Option<String>,
}
impl ApiResponseTrait for ListChildrenRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
macro_rules! impl_execute_with_path {
($builder:ty, $response:ty, $method:ident) => {
impl $builder {
pub async fn execute(
self,
service: &DocumentBlockService,
option: Option<RequestOption>,
) -> SDKResult<$response> {
let (document_id, request) = self.build();
service.$method(document_id, request, option).await
}
pub async fn execute_with_options(
self,
service: &DocumentBlockService,
option: RequestOption,
) -> SDKResult<$response> {
self.execute(service, Some(option)).await
}
}
};
}
impl_execute_with_path!(
CreateBlockRequestBuilder,
BaseResponse<CreateBlockRespData>,
create
);
impl_execute_with_path!(
BatchUpdateBlockRequestBuilder,
BaseResponse<BatchUpdateBlockRespData>,
batch_update
);
impl_execute_with_path!(
BatchDeleteBlockRequestBuilder,
BaseResponse<BatchDeleteBlockRespData>,
batch_delete
);
impl Service for DocumentBlockService {
fn config(&self) -> &Config {
&self.config
}
fn service_name() -> &'static str {
"document_block"
}
fn service_version() -> &'static str {
"v1"
}
}