openclaw-home-pc/workspace/create_feishu_doc_uat.py
2026-03-21 15:31:06 +08:00

171 lines
9.5 KiB
Python
Raw Permalink 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.

#!/usr/bin/env python3
"""
使用飞书 API 和用户访问令牌创建云文档
"""
import requests
import json
import sys
# 飞书应用凭证
APP_ID = "cli_a93815b250b9dcb5"
APP_SECRET = "NogaPY8DiMHMyadOKDW26bqkGPnrOkND"
# 用户访问令牌(从解密获取)
USER_ACCESS_TOKEN = "eyJhbGciOiJFUzI1NiIsImZlYXR1cmVfY29kZSI6IkZlYXR1cmVPQXV0aEpXVFNpZ25fQ04iLCJraWQiOiI3NjE2ODk0MzA1NzE3OTE0NTczIiwidHlwIjoiSldUIn0.eyJqdGkiOiI3NjE4Mjk3MjkyNDM2NTczMTE1IiwiaWF0IjoxNzczNzczMDYyLCJleHAiOjE3NzM3ODAyNjIsInZlciI6InYxIiwidHlwIjoiYWNjZXNzX3Rva2VuIiwiY2xpZW50X2lkIjoiY2xpX2E5MzgxNWIyNTBiOWRjYjUiLCJzY29wZSI6ImF1dGg6dXNlci5pZDpyZWFkIGJhc2U6YXBwOmNvcHkgYmFzZTphcHA6Y3JlYXRlIGJhc2U6YXBwOnJlYWQgYmFzZTphcHA6dXBkYXRlIGJhc2U6ZmllbGQ6Y3JlYXRlIGJhc2U6ZmllbGQ6ZGVsZXRlIGJhc2U6ZmllbGQ6cmVhZCBiYXNlOmZpZWxkOnVwZGF0ZSBiYXNlOnJlY29yZDpjcmVhdGUgYmFzZTpyZWNvcmQ6ZGVsZXRlIGJhc2U6cmVjb3JkOnJldHJpZXZlIGJhc2U6cmVjb3JkOnVwZGF0ZSBiYXNlOnRhYmxlOmNyZWF0ZSBiYXNlOnRhYmxlOmRlbGV0ZSBiYXNlOnRhYmxlOnJlYWQgYmFzZTp0YWJsZTp1cGRhdGUgYmFzZTp2aWV3OnJlYWQgYmFzZTp2aWV3OndyaXRlX29ubHkgYm9hcmQ6d2hpdGVib2FyZDpub2RlOmNyZWF0ZSBib2FyZDp3aGl0ZWJvYXJkOm5vZGU6cmVhZCBjYWxlbmRhcjpjYWxlbmRhci5ldmVudDpjcmVhdGUgY2FsZW5kYXI6Y2FsZW5kYXIuZXZlbnQ6ZGVsZXRlIGNhbGVuZGFyOmNhbGVuZGFyLmV2ZW50OnJlYWQgY2FsZW5kYXI6Y2FsZW5kYXIuZXZlbnQ6cmVwbHkgY2FsZW5kYXI6Y2FsZW5kYXIuZXZlbnQ6dXBkYXRlIGNhbGVuZGFyOmNhbGVuZGFyLmZyZWVfYnVzeTpyZWFkIGNhbGVuZGFyOmNhbGVuZGFyOnJlYWQgY29udGFjdDpjb250YWN0LmJhc2U6cmVhZG9ubHkgY29udGFjdDp1c2VyLmJhc2U6cmVhZG9ubHkgY29udGFjdDp1c2VyLmJhc2ljX3Byb2ZpbGU6cmVhZG9ubHkgY29udGFjdDp1c2VyLmVtcGxveWVlX2lkOnJlYWRvbmx5IGNvbnRhY3Q6dXNlcjpzZWFyY2ggZG9jczpkb2N1bWVudC5jb21tZW50OmNyZWF0ZSBkb2NzOmRvY3VtZW50LmNvbW1lbnQ6cmVhZCBkb2NzOmRvY3VtZW50LmNvbW1lbnQ6dXBkYXRlIGRvY3M6ZG9jdW1lbnQubWVkaWE6ZG93bmxvYWQgZG9jczpkb2N1bWVudC5tZWRpYTp1cGxvYWQgZG9jczpkb2N1bWVudDpjb3B5IGRvY3M6ZG9jdW1lbnQ6ZXhwb3J0IGRvY3g6ZG9jdW1lbnQ6Y3JlYXRlIGRvY3g6ZG9jdW1lbnQ6cmVhZG9ubHkgZG9jeDpkb2N1bWVudDp3cml0ZV9vbmx5IGRyaXZlOmRyaXZlLm1ldGFkYXRhOnJlYWRvbmx5IGRyaXZlOmZpbGU6ZG93bmxvYWQgZHJpdmU6ZmlsZTp1cGxvYWQgaW06Y2hhdC5tZW1iZXJzOnJlYWQgaW06Y2hhdDpyZWFkIGltOm1lc3NhZ2UgaW06bWVzc2FnZS5ncm91cF9tc2c6Z2V0X2FzX3VzZXIgaW06bWVzc2FnZS5wMnBfbXNnOmdldF9hc191c2VyIGltOm1lc3NhZ2U6cmVhZG9ubHkgc2VhcmNoOmRvY3M6cmVhZCBzZWFyY2g6bWVzc2FnZSBzaGVldHM6c3ByZWFkc2hlZXQubWV0YTpyZWFkIHNoZWV0czpzcHJlYWRzaGVldDpjcmVhdGUgc2hlZXRzOnNwcmVhZHNoZWV0OnJlYWQgc2hlZXRzOnNwcmVhZHNoZWV0OndyaXRlX29ubHkgc3BhY2U6ZG9jdW1lbnQ6ZGVsZXRlIHNwYWNlOmRvY3VtZW50Om1vdmUgc3BhY2U6ZG9jdW1lbnQ6cmV0cmlldmUgdGFzazpjb21tZW50OnJlYWQgdGFzazpjb21tZW50OndyaXRlIHRhc2s6dGFzazpyZWFkIHRhc2s6dGFzazp3cml0ZSB0YXNrOnRhc2s6d3JpdGVvbmx5IHRhc2s6dGFza2xpc3Q6cmVhZCB0YXNrOnRhc2tsaXN0OndyaXRlIHdpa2k6bm9kZTpjb3B5IHdpa2k6bm9kZTpjcmVhdGUgd2lraTpub2RlOm1vdmUgd2lraTpub2RlOnJlYWQgd2lraTpub2RlOnJldHJpZXZlIHdpa2k6c3BhY2U6cmVhZCB3aWtpOnNwYWNlOnJldHJpZXZlIHdpa2k6c3BhY2U6d3JpdGVfb25seSBvZmZsaW5lX2FjY2VzcyIsImF1dGhfaWQiOiI3NjE4Mjk3MjY2ODA5MzU5NTUzIiwiYXV0aF90aW1lIjoxNzczNzczMDYyLCJhdXRoX2V4cCI6MTgwNTMwOTA2MiwidW5pdCI6ImV1X25jIiwidGVuYW50X3VuaXQiOiJldV9uYyIsIm9wYXF1ZSI6dHJ1ZSwiZW5jIjoiQWlRa0FRRUNBTUlEQUFFQkF3QUNBUTBBQXdzTEFBQUFBd0FBQUFkR1pXRjBkWEpsQUFBQUVHOWhkWFJvWDI5d1lYRjFaVjlxZDNRQUFBQUlWR1Z1WVc1MFNXUUFBQUFCTUFBQUFBUlVhVzFsQUFBQUNqRTNOek0yTVRreU1EQVBBQVFNQUFBQUFRb0FBV0xGSWxtdmdBQWlDd0FDQUFBQURFNkdsUjZPN0VpWjJQeGh0UXNBQXdBQUFEQmFqSDRQSmx6d2lISDZybXlCZVg4TWRjSHAxc2t0U3R6c3h2U1F5NUtSL2JEYlJhMnhoeVA5RHVYWDFvUTRvaFVBQ3dBRkFBQUFCV1YxWDI1akFIakhLdlpTb3B4bGs2REJYb0xocVlKc1NoMVczQnJvVUZIL2kvd0hqUHpHalE1VjJRaVJlUXdxYzBHOE9wRTRjdXFkNk02QmluUUozdlpaK0JYdWo0SzlwOWdBMDRwZVF3TW5vSjlEY0l4SENlSGFCRmZSdmx5Wk5iZCtBY2RGZUxHRUdLZWNicTM4cUVGNE40bzlLYmRrWWZNUThFYU91bEhrcjh5WkFXWmdwczycllLVFBiNzFzTjVwS09mcU9aRmRvdz09IiwiZW5jX3ZlciI6InYxIn0.x-4ybLikzQ6WQEATSVbffwJGDKrTNYMydBp8RZtSAMuaCL1SUa8Wec7v6OBx0rLN3S4jEXMp9htJRsYZB09L5Q"
def create_document(token, title, markdown):
"""使用飞书 API 创建云文档"""
url = "https://open.feishu.cn/open-apis/docx/v1/documents"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
payload = {
"title": title,
"folder_token": "", # 空表示创建在个人空间根目录
}
print(f"正在创建文档:{title}")
resp = requests.post(url, json=payload, headers=headers, timeout=10)
print(f"HTTP 状态码:{resp.status_code}")
try:
data = resp.json()
except:
data = {"raw": resp.text, "code": -1}
print(f"响应:{json.dumps(data, indent=2, ensure_ascii=False)[:500]}")
if data.get("code") != 0:
raise Exception(f"创建文档失败:{data}")
doc_token = data["data"]["document"]["token"]
doc_id = data["data"]["document"]["doc_id"]
doc_url = f"https://www.feishu.cn/docx/{doc_token}"
# 更新文档内容
print(f"正在更新文档内容...")
update_document_content(token, doc_token, markdown)
return doc_token, doc_id, doc_url
def update_document_content(token, doc_token, markdown):
"""更新文档内容(使用批量更新 API"""
url = f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_token}/batch_update"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
# 简单处理:将 Markdown 作为纯文本插入
blocks = []
lines = markdown.split('\n')
current_text = []
for line in lines:
if line.startswith('# '):
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
current_text = []
blocks.append({"heading1": {"elements": [{"text_run": {"content": line[2:]}}]}})
elif line.startswith('## '):
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
current_text = []
blocks.append({"heading2": {"elements": [{"text_run": {"content": line[3:]}}]}})
elif line.startswith('### '):
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
current_text = []
blocks.append({"heading3": {"elements": [{"text_run": {"content": line[4:]}}]}})
elif line.startswith('> '):
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
current_text = []
blocks.append({"quote": {"elements": [{"text_run": {"content": line[2:]}}]}})
elif line.startswith('- ') or line.startswith('* '):
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
current_text = []
blocks.append({"bullet": {"elements": [{"text_run": {"content": line[2:]}}]}})
elif line.startswith('1. ') or line.startswith('2. '):
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
current_text = []
content_text = line.split('. ', 1)[1] if '. ' in line else line
blocks.append({"ordered": {"elements": [{"text_run": {"content": content_text}}]}})
elif line.startswith('```'):
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
current_text = []
elif line == '---':
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
current_text = []
blocks.append({"divider": {}})
elif line.strip() == '':
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
current_text = []
else:
current_text.append(line)
if current_text:
blocks.append({"text": {"elements": [{"text_run": {"content": "\n".join(current_text)}}]}})
# 构建请求体
requests_body = {
"requests": []
}
for i, block in enumerate(blocks):
requests_body["requests"].append({
"action": "append_block",
"args": {
"block": block,
"parent_block_id": "",
"index": i
}
})
resp = requests.post(url, json=requests_body, headers=headers, timeout=30)
print(f"更新内容 HTTP 状态码:{resp.status_code}")
try:
data = resp.json()
except:
data = {"raw": resp.text}
if data.get("code") != 0:
print(f"警告:更新文档内容部分失败:{data}")
else:
print(f"✓ 成功更新 {len(blocks)} 个块")
def main():
if len(sys.argv) < 3:
print("用法python3 create_feishu_doc_uat.py <title> <content_file>")
sys.exit(1)
title = sys.argv[1]
content_file = sys.argv[2]
# 读取文档内容
with open(content_file, 'r', encoding='utf-8') as f:
markdown = f.read()
print(f"创建文档:{title}")
print(f"内容来源:{content_file}")
print(f"内容长度:{len(markdown)} 字符")
print(f"使用用户访问令牌:{USER_ACCESS_TOKEN[:30]}...")
# 创建文档
doc_token, doc_id, doc_url = create_document(USER_ACCESS_TOKEN, title, markdown)
print(f"\n✓ 文档创建成功!")
print(f"文档 Token: {doc_token}")
print(f"文档 ID: {doc_id}")
print(f"文档 URL: {doc_url}")
return doc_url
if __name__ == "__main__":
main()