import os import sys from typing import List, Optional, Union, Dict import lark_oapi as lark from lark_oapi.api.wiki.v2 import CreateSpaceNodeRequest, Node, CreateSpaceNodeResponse from lark_oapi.api.docx.v1 import CreateDocumentBlockChildrenRequest, CreateDocumentBlockChildrenRequestBody, CreateDocumentBlockChildrenResponse import yaml from category_block import create_block_by_category from nest_block import NestBlock from lark import lark_client from itertools import chain sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from render import Render class Report: def __init__(self, title: str, space_id: str, folder_id: str) -> None: self.title = title self.space_id = space_id self.folder_id = folder_id self.report_id = '' def _create_report(self): request: CreateSpaceNodeRequest = CreateSpaceNodeRequest.builder() \ .space_id(self.space_id) \ .request_body(Node.builder() .parent_node_token(self.folder_id) .title(self.title) .obj_type("docx") .node_type("origin") .build()) \ .build() response: CreateSpaceNodeResponse = lark_client.wiki.v2.space_node.create(request) if not response.success(): lark.logger.error( f"client.wiki.v2.space_node.create failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}") return self.report_id = response.data.node.obj_token lark.logger.info(lark.JSON.marshal(response.data, indent=4)) def _create_blocks(self, blocks: List[NestBlock]): root_children: List[NestBlock] = [] children_group: Dict[str, List[NestBlock]] = {} next_round_blocks: List[NestBlock] = [] for block in blocks: block.report_id = self.report_id if block.parent == None: root_children.append(block) else: if children_group.get(str(block.parent.id), None) == None: children_group[str(block.parent.id)] = [] children_group[str(block.parent.id)].append(block) if block.children != None: if isinstance(block.children, list): for item in block.children: next_round_blocks.append(item) else: next_round_blocks.append(block.children) if len(root_children) != 0: self._create_blocks_throttle(root_children) for id, childrenBlocks in children_group.items(): self._create_blocks_throttle(childrenBlocks, id) if len(next_round_blocks): self._create_blocks(next_round_blocks) def _create_blocks_throttle(self, blocks: List[NestBlock], parent_id: Optional[str] = None): if len(blocks) > 50: blocks_group: List[List[NestBlock]] = [] for i in range(0, len(blocks), 50): if i+50 > len(blocks): blocks_group.append(blocks[i:]) else: blocks_group.append(blocks[i: i+50]) blocks_group.reverse() for g in blocks_group: self._exec_create_blokcs(g, parent_id) else: self._exec_create_blokcs(blocks, parent_id) def _exec_create_blokcs(self, blocks: List[NestBlock], parent_id: Optional[str] = None): request: CreateDocumentBlockChildrenRequest = CreateDocumentBlockChildrenRequest.builder() \ .document_id(str(self.report_id)) \ .block_id(parent_id or str(self.report_id)) \ .document_revision_id(-1) \ .request_body(CreateDocumentBlockChildrenRequestBody.builder() .children(list(map(lambda item: item.block, blocks))) .index(0) .build()) \ .build() response: CreateDocumentBlockChildrenResponse = lark_client.docx.v1.document_block_children.create(request) if not response.success(): lark.logger.error( f"client.docx.v1.document_block_children.create failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}") return lark.logger.info(lark.JSON.marshal(response.data, indent=4)) for idx, child in enumerate(response.data.children): blocks[idx].id = child.block_id for block in blocks: block.callback() def create(self, config_file: str, render: Render, slots: Dict[str, Union[NestBlock, List[NestBlock]]] = {}): self._create_report() with open(config_file, "r") as stream: config = yaml.safe_load(stream) blocks: List[NestBlock] = [] for cate in config: block = create_block_by_category(cate, render, slots) if block == None: continue else: if isinstance(block, list): for _item in list(chain.from_iterable([item] if not isinstance(item, list) else item for item in block)): blocks.append(_item) else: blocks.append(block) self._create_blocks(blocks)