ForcePilot/backend/package/yuxi/channel/extensions/feishu/tools/doc.py
Kris 5e91bb9985 feat(feishu): 新增飞书渠道完整插件实现
新增飞书渠道插件,包含基础配置、事件处理、消息收发、工具调用、权限管理等完整功能模块,支持WebSocket长连接、卡片消息、流式响应、群管理、审批通知等能力
2026-05-21 10:46:42 +08:00

360 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import logging
from yuxi.channel.extensions.feishu.client import get_client
logger = logging.getLogger(__name__)
FEISHU_DOC_TOOLS = [
{
"name": "feishu_doc_read",
"description": "读取飞书文档内容",
"parameters": {"doc_token": "文档 token"},
},
{
"name": "feishu_doc_create",
"description": "创建飞书文档",
"parameters": {"title": "文档标题", "folder_token": "文件夹 token可选"},
},
{
"name": "feishu_doc_append",
"description": "追加内容到飞书文档",
"parameters": {"doc_token": "文档 token", "content": "要追加的内容"},
},
{
"name": "feishu_doc_list_blocks",
"description": "列出文档的所有块",
"parameters": {"doc_token": "文档 token"},
},
{
"name": "feishu_doc_export",
"description": "导出飞书文档为 PDF 或其他格式",
"parameters": {"doc_token": "文档 token", "export_format": "导出格式pdf/docx默认 pdf"},
},
]
async def read_doc(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
http_timeout_ms: int = 30000,
) -> dict:
try:
client = get_client(app_id, app_secret, domain, http_timeout_ms)
import lark_oapi
req = lark_oapi.docx.v1.GetDocumentRequest(document_id=doc_token)
resp = await client.docx.v1.document.get_async(req)
if resp.success() and resp.data:
doc = resp.data.document
return {
"success": True,
"title": getattr(doc, "title", ""),
"document_id": getattr(doc, "document_id", ""),
}
else:
return {"success": False, "error": getattr(resp, "msg", "")}
except ImportError:
return {"success": False, "error": "lark-oapi SDK not installed"}
except Exception:
logger.exception("Feishu read_doc error")
return {"success": False, "error": "Internal error"}
async def write_doc(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
content: str,
http_timeout_ms: int = 30000,
) -> dict:
try:
client = get_client(app_id, app_secret, domain, http_timeout_ms)
import lark_oapi
blocks = [
lark_oapi.docx.v1.Block(
block_type=2,
text=lark_oapi.docx.v1.Text(
elements=[
lark_oapi.docx.v1.TextElement(
text_run=lark_oapi.docx.v1.TextRun(content=content),
)
]
),
)
]
req = lark_oapi.docx.v1.UpdateDocumentRequest(
document_id=doc_token,
request_body=lark_oapi.docx.v1.UpdateDocumentRequestBody(
document_id=doc_token,
blocks=blocks,
),
)
resp = await client.docx.v1.document.update_async(req)
if resp.success():
return {"success": True}
else:
return {"success": False, "error": getattr(resp, "msg", "")}
except ImportError:
return {"success": False, "error": "lark-oapi SDK not installed"}
except Exception:
logger.exception("Feishu write_doc error")
return {"success": False, "error": "Internal error"}
async def append_doc(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
content: str,
http_timeout_ms: int = 30000,
) -> dict:
return await write_doc(app_id, app_secret, domain, doc_token, content, http_timeout_ms)
async def create_doc(
app_id: str,
app_secret: str,
domain: str,
title: str,
folder_token: str = "",
http_timeout_ms: int = 30000,
) -> dict:
try:
client = get_client(app_id, app_secret, domain, http_timeout_ms)
import lark_oapi
req = lark_oapi.docx.v1.CreateDocumentRequest(
request_body=lark_oapi.docx.v1.CreateDocumentRequestBody(
title=title,
folder_token=folder_token if folder_token else None,
),
)
resp = await client.docx.v1.document.create_async(req)
if resp.success() and resp.data:
return {
"success": True,
"document_id": getattr(resp.data.document, "document_id", ""),
"url": getattr(resp.data.document, "url", ""),
}
else:
return {"success": False, "error": getattr(resp, "msg", "")}
except ImportError:
return {"success": False, "error": "lark-oapi SDK not installed"}
except Exception:
logger.exception("Feishu create_doc error")
return {"success": False, "error": "Internal error"}
async def list_doc_blocks(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
http_timeout_ms: int = 30000,
) -> dict:
try:
client = get_client(app_id, app_secret, domain, http_timeout_ms)
import lark_oapi
req = lark_oapi.docx.v1.ListDocumentBlockRequest(
document_id=doc_token,
page_size=500,
)
resp = await client.docx.v1.document_block.list_async(req)
if resp.success() and resp.data:
items = getattr(resp.data, "items", []) or []
return {
"success": True,
"blocks": [
{
"block_id": getattr(b, "block_id", ""),
"block_type": getattr(b, "block_type", 0),
"text": getattr(getattr(b, "text", None), "elements", []),
}
for b in items
],
}
else:
return {"success": False, "error": getattr(resp, "msg", "")}
except ImportError:
return {"success": False, "error": "lark-oapi SDK not installed"}
except Exception:
logger.exception("Feishu list_doc_blocks error")
return {"success": False, "error": "Internal error"}
async def get_doc_block(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
block_id: str,
http_timeout_ms: int = 30000,
) -> dict:
try:
client = get_client(app_id, app_secret, domain, http_timeout_ms)
import lark_oapi
req = lark_oapi.docx.v1.GetDocumentBlockRequest(
document_id=doc_token,
block_id=block_id,
)
resp = await client.docx.v1.document_block.get_async(req)
if resp.success() and resp.data:
block = resp.data.block
return {
"success": True,
"block": {
"block_id": getattr(block, "block_id", ""),
"block_type": getattr(block, "block_type", 0),
},
}
else:
return {"success": False, "error": getattr(resp, "msg", "")}
except ImportError:
return {"success": False, "error": "lark-oapi SDK not installed"}
except Exception:
logger.exception("Feishu get_doc_block error")
return {"success": False, "error": "Internal error"}
async def update_doc_block(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
block_id: str,
content: str,
http_timeout_ms: int = 30000,
) -> dict:
try:
client = get_client(app_id, app_secret, domain, http_timeout_ms)
import lark_oapi
req = lark_oapi.docx.v1.UpdateDocumentBlockRequest(
document_id=doc_token,
block_id=block_id,
request_body=lark_oapi.docx.v1.UpdateDocumentBlockRequestBody(
update_text_elements={
"elements": [
{"text_run": {"content": content}}
]
},
),
)
resp = await client.docx.v1.document_block.update_async(req)
if resp.success():
return {"success": True}
else:
return {"success": False, "error": getattr(resp, "msg", "")}
except ImportError:
return {"success": False, "error": "lark-oapi SDK not installed"}
except Exception:
logger.exception("Feishu update_doc_block error")
return {"success": False, "error": "Internal error"}
async def delete_doc_block(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
block_id: str,
http_timeout_ms: int = 30000,
) -> dict:
try:
client = get_client(app_id, app_secret, domain, http_timeout_ms)
import lark_oapi
req = lark_oapi.docx.v1.DeleteDocumentBlockRequest(
document_id=doc_token,
block_id=block_id,
)
resp = await client.docx.v1.document_block.delete_async(req)
if resp.success():
return {"success": True}
else:
return {"success": False, "error": getattr(resp, "msg", "")}
except ImportError:
return {"success": False, "error": "lark-oapi SDK not installed"}
except Exception:
logger.exception("Feishu delete_doc_block error")
return {"success": False, "error": "Internal error"}
async def create_doc_table(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
row_size: int,
column_size: int,
http_timeout_ms: int = 30000,
) -> dict:
header = "| " + " | ".join(f"{i + 1}" for i in range(column_size)) + " |\n"
sep = "| " + " | ".join("---" for _ in range(column_size)) + " |\n"
rows = "".join("| " + " | ".join("" for _ in range(column_size)) + " |\n" for _ in range(row_size))
table_md = header + sep + rows
return await write_doc(app_id, app_secret, domain, doc_token, table_md, http_timeout_ms)
async def write_table_cells(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
table_block_id: str,
values: list[list[str]],
http_timeout_ms: int = 30000,
) -> dict:
text = "".join("| " + " | ".join(row) + " |\n" for row in values)
return await update_doc_block(app_id, app_secret, domain, doc_token, table_block_id, text, http_timeout_ms)
async def export_doc(
app_id: str,
app_secret: str,
domain: str,
doc_token: str,
export_format: str = "pdf",
http_timeout_ms: int = 30000,
) -> dict:
try:
client = get_client(app_id, app_secret, domain, http_timeout_ms)
import lark_oapi
req = lark_oapi.docx.v1.GetDocumentExportRequest(
document_id=doc_token,
export_format=export_format,
export_type="download",
)
resp = await client.docx.v1.document.export_async(req)
if resp.success():
return {
"success": True,
"document_id": doc_token,
"format": export_format,
}
else:
return {"success": False, "error": getattr(resp, "msg", "")}
except ImportError:
return {"success": False, "error": "lark-oapi SDK not installed"}
except Exception:
logger.exception("Feishu export_doc error")
return {"success": False, "error": "Internal error"}