🔄 卡若AI 同步 2026-02-25 10:22 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 13 个
This commit is contained in:
@@ -14,12 +14,18 @@ import subprocess
|
||||
import requests
|
||||
from datetime import datetime, timedelta
|
||||
import time
|
||||
import re
|
||||
|
||||
# ============ 配置 ============
|
||||
CONFIG = {
|
||||
'APP_ID': 'cli_a48818290ef8100d',
|
||||
'APP_SECRET': 'dhjU0qWd5AzicGWTf4cTqhCWJOrnuCk4',
|
||||
'WIKI_TOKEN': 'JZiiwxEjHiRxouk8hSPcqBn6nrd',
|
||||
# 按月份路由到对应日志文档,避免跨月误写
|
||||
'MONTH_WIKI_TOKENS': {
|
||||
1: 'JZiiwxEjHiRxouk8hSPcqBn6nrd', # 2026年1月 运营团队启动
|
||||
2: 'Jn2EwXP2OiTujNkAbNCcDcM7nRA', # 2026年2月 (突破执行)
|
||||
},
|
||||
'SERVICE_PORT': 5050,
|
||||
'TOKEN_FILE': os.path.join(os.path.dirname(__file__), '.feishu_tokens.json')
|
||||
}
|
||||
@@ -217,20 +223,50 @@ def build_blocks(date_str, tasks):
|
||||
|
||||
return blocks
|
||||
|
||||
def write_log(token, date_str=None, tasks=None):
|
||||
|
||||
def parse_month_from_date_str(date_str):
|
||||
"""从如 '2月25日' 提取月份整数"""
|
||||
m = re.search(r'(\d+)\s*月', date_str or '')
|
||||
if not m:
|
||||
return None
|
||||
try:
|
||||
return int(m.group(1))
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
def resolve_wiki_token_for_date(date_str, explicit_wiki_token=None):
|
||||
"""根据日期路由文档token;允许显式覆盖"""
|
||||
if explicit_wiki_token:
|
||||
return explicit_wiki_token
|
||||
month = parse_month_from_date_str(date_str)
|
||||
if month and month in CONFIG.get('MONTH_WIKI_TOKENS', {}):
|
||||
return CONFIG['MONTH_WIKI_TOKENS'][month]
|
||||
return CONFIG['WIKI_TOKEN']
|
||||
|
||||
def write_log(token, date_str=None, tasks=None, wiki_token=None):
|
||||
"""写入日志(倒序插入:新日期在最上面)"""
|
||||
headers = {'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'}
|
||||
|
||||
if not date_str or not tasks:
|
||||
date_str, tasks = get_today_tasks()
|
||||
target_wiki_token = resolve_wiki_token_for_date(date_str, wiki_token)
|
||||
|
||||
# 获取文档ID
|
||||
r = requests.get(f"https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node?token={CONFIG['WIKI_TOKEN']}",
|
||||
r = requests.get(f"https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node?token={target_wiki_token}",
|
||||
headers=headers, timeout=30)
|
||||
if r.json().get('code') != 0:
|
||||
print(f"❌ 获取文档失败")
|
||||
return False
|
||||
doc_id = r.json()['data']['node']['obj_token']
|
||||
node = r.json()['data']['node']
|
||||
doc_id = node['obj_token']
|
||||
doc_title = node.get('title', '')
|
||||
|
||||
# 防串月:日期月份与文档标题不一致时拒绝写入
|
||||
month = parse_month_from_date_str(date_str)
|
||||
if month and f"{month}月" not in doc_title:
|
||||
print(f"❌ 月份校验失败:{date_str} 不应写入《{doc_title}》")
|
||||
return False
|
||||
|
||||
# 获取blocks检查日期是否存在
|
||||
r = requests.get(f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_id}/blocks",
|
||||
@@ -261,16 +297,18 @@ def write_log(token, date_str=None, tasks=None):
|
||||
headers=headers, json={'children': content_blocks, 'index': insert_index}, timeout=30)
|
||||
|
||||
if r.json().get('code') == 0:
|
||||
print(f"✅ {date_str} 日志写入成功")
|
||||
print(f"✅ {date_str} 日志写入成功 -> {doc_title}")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ 写入失败: {r.json().get('msg')}")
|
||||
return False
|
||||
|
||||
def open_result():
|
||||
def open_result(wiki_token=None):
|
||||
"""打开飞书查看结果"""
|
||||
subprocess.run(['open', WIKI_URL], capture_output=True)
|
||||
print(f"📎 已打开飞书: {WIKI_URL}")
|
||||
token = wiki_token or CONFIG['WIKI_TOKEN']
|
||||
url = f"https://cunkebao.feishu.cn/wiki/{token}"
|
||||
subprocess.run(['open', url], capture_output=True)
|
||||
print(f"📎 已打开飞书: {url}")
|
||||
|
||||
# ============ 主流程 ============
|
||||
def main():
|
||||
@@ -289,14 +327,16 @@ def main():
|
||||
print("❌ 无法获取Token")
|
||||
sys.exit(1)
|
||||
|
||||
# 3. 写入日志
|
||||
# 3. 写入日志(按月份自动路由)
|
||||
print("\n📝 Step 3: 写入日志...")
|
||||
if not write_log(token):
|
||||
date_str, tasks = get_today_tasks()
|
||||
target_wiki_token = resolve_wiki_token_for_date(date_str)
|
||||
if not write_log(token, date_str, tasks, target_wiki_token):
|
||||
sys.exit(1)
|
||||
|
||||
# 4. 打开结果
|
||||
print("\n🎉 Step 4: 完成!")
|
||||
open_result()
|
||||
open_result(target_wiki_token)
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
print("✅ 全部完成!")
|
||||
|
||||
@@ -35,11 +35,25 @@ def _image_placeholder(idx: int, path: str) -> dict:
|
||||
return {"__image__": path, "__index__": idx}
|
||||
|
||||
|
||||
def _clean_inline_markdown(text: str) -> str:
|
||||
"""清理常见行内 markdown 标记,输出更适合飞书阅读的纯文本。"""
|
||||
t = text
|
||||
# 粗体/斜体标记
|
||||
t = re.sub(r"\*\*(.*?)\*\*", r"\1", t)
|
||||
t = re.sub(r"__(.*?)__", r"\1", t)
|
||||
t = re.sub(r"\*(.*?)\*", r"\1", t)
|
||||
t = re.sub(r"_(.*?)_", r"\1", t)
|
||||
# 行内代码保留内容,去掉反引号
|
||||
t = re.sub(r"`([^`]+)`", r"\1", t)
|
||||
return t.strip()
|
||||
|
||||
|
||||
def md_to_blocks(md: str, image_paths: list[str] | None = None) -> list:
|
||||
"""将 Markdown 转为飞书 blocks"""
|
||||
blocks = []
|
||||
image_paths = image_paths or []
|
||||
img_idx = 0
|
||||
first_h1_consumed = False
|
||||
|
||||
in_code = False
|
||||
code_lines = []
|
||||
@@ -73,16 +87,33 @@ def md_to_blocks(md: str, image_paths: list[str] | None = None) -> list:
|
||||
|
||||
# 标题
|
||||
if line.startswith("# "):
|
||||
blocks.append(_h1(line[2:].strip()))
|
||||
# 避免正文和文档标题重复:默认跳过第一行 H1
|
||||
if first_h1_consumed:
|
||||
blocks.append(_h1(_clean_inline_markdown(line[2:].strip())))
|
||||
else:
|
||||
first_h1_consumed = True
|
||||
elif line.startswith("## "):
|
||||
blocks.append(_h2(line[3:].strip()))
|
||||
blocks.append(_h2(_clean_inline_markdown(line[3:].strip())))
|
||||
elif line.startswith("### "):
|
||||
blocks.append(_h3(line[4:].strip()))
|
||||
blocks.append(_h3(_clean_inline_markdown(line[4:].strip())))
|
||||
elif line.lstrip().startswith(">"):
|
||||
# 引用块转普通说明行,降低写入失败概率
|
||||
blocks.append(_text(line.lstrip()[1:].strip()))
|
||||
quote = line.lstrip()
|
||||
while quote.startswith(">"):
|
||||
quote = quote[1:].lstrip()
|
||||
quote = _clean_inline_markdown(quote)
|
||||
if quote:
|
||||
blocks.append(_text(quote))
|
||||
elif line.strip():
|
||||
blocks.append(_text(line.strip()))
|
||||
raw = line.strip()
|
||||
# 无序列表统一成 •,减少 markdown 观感噪音
|
||||
if re.match(r"^[-*]\s+", raw):
|
||||
raw = "• " + re.sub(r"^[-*]\s+", "", raw)
|
||||
# 有序列表统一成 1)2)样式
|
||||
raw = re.sub(r"^(\d+)\.\s+", r"\1)", raw)
|
||||
cleaned = _clean_inline_markdown(raw)
|
||||
if cleaned:
|
||||
blocks.append(_text(cleaned))
|
||||
|
||||
return blocks
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
if SCRIPT_DIR not in sys.path:
|
||||
sys.path.insert(0, SCRIPT_DIR)
|
||||
|
||||
from auto_log import get_token_silent, write_log, open_result
|
||||
from auto_log import get_token_silent, write_log, open_result, resolve_wiki_token_for_date
|
||||
|
||||
DATE_STR = "2月25日"
|
||||
TASKS = [
|
||||
@@ -46,5 +46,5 @@ if __name__ == "__main__":
|
||||
print("📝 写入飞书日志(2月25日)...")
|
||||
ok = write_log(token, DATE_STR, TASKS)
|
||||
if ok:
|
||||
open_result()
|
||||
open_result(resolve_wiki_token_for_date(DATE_STR))
|
||||
sys.exit(0 if ok else 1)
|
||||
|
||||
@@ -135,3 +135,4 @@
|
||||
| 2026-02-25 09:24:48 | 🔄 卡若AI 同步 2026-02-25 09:24 | 更新:水桥平台对接、总索引与入口、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 13 个 |
|
||||
| 2026-02-25 09:28:50 | 🔄 卡若AI 同步 2026-02-25 09:28 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 13 个 |
|
||||
| 2026-02-25 09:31:15 | 🔄 卡若AI 同步 2026-02-25 09:31 | 更新:运营中枢、运营中枢工作台 | 排除 >20MB: 13 个 |
|
||||
| 2026-02-25 10:15:21 | 🔄 卡若AI 同步 2026-02-25 10:15 | 更新:水桥平台对接、运营中枢、运营中枢工作台 | 排除 >20MB: 13 个 |
|
||||
|
||||
@@ -138,3 +138,4 @@
|
||||
| 2026-02-25 09:24:48 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-25 09:24 | 更新:水桥平台对接、总索引与入口、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 13 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
| 2026-02-25 09:28:50 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-25 09:28 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 13 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
| 2026-02-25 09:31:15 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-25 09:31 | 更新:运营中枢、运营中枢工作台 | 排除 >20MB: 13 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
| 2026-02-25 10:15:21 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-25 10:15 | 更新:水桥平台对接、运营中枢、运营中枢工作台 | 排除 >20MB: 13 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
|
||||
Reference in New Issue
Block a user