#!/usr/bin/env python3 """ 小说内容同步到飞书脚本 将《末日重生-开局囤货十亿物资》同步到飞书云文档 """ import os import re import json import time from pathlib import Path import subprocess class NovelToFeishuSync: def __init__(self): # 小说目录 self.novel_dir = "/root/.openclaw/workspace/tomato-novel/books/末日重生-开局囤货十亿物资" self.chapters_dir = os.path.join(self.novel_dir, "chapters") # 同步状态记录 self.sync_state_file = "/root/.openclaw/workspace/novel_sync_state.json" self.load_sync_state() # 飞书文档配置 self.feishu_doc_id = None # 需要创建或指定 def load_sync_state(self): """加载同步状态""" if os.path.exists(self.sync_state_file): with open(self.sync_state_file, 'r', encoding='utf-8') as f: self.sync_state = json.load(f) else: self.sync_state = { "last_sync_time": None, "synced_chapters": [], "feishu_doc_id": None, "total_chapters": 0 } def save_sync_state(self): """保存同步状态""" with open(self.sync_state_file, 'w', encoding='utf-8') as f: json.dump(self.sync_state, f, ensure_ascii=False, indent=2) def discover_chapters(self): """发现所有章节""" chapters = [] for file in Path(self.chapters_dir).glob("*.md"): # 只处理主章节文件,避免备份文件 if not any(x in file.name for x in ["_fixed", "_备份", "_修复", "backup", "_质检前", "_最终", "_原始", "_全面"]): # 提取章节号 match = re.match(r'(\d{4})_(.*?)\.md', file.name) if match: chapter_num = int(match.group(1)) chapter_title = match.group(2) chapters.append({ "number": chapter_num, "title": chapter_title, "file": str(file), "size": os.path.getsize(file), "modified": os.path.getmtime(file) }) # 按章节号排序 chapters.sort(key=lambda x: x["number"]) return chapters def read_chapter_content(self, chapter_file): """读取章节内容""" try: with open(chapter_file, 'r', encoding='utf-8') as f: content = f.read() # 清理内容,确保格式正确 content = content.replace('\r', '') # 限制内容长度(飞书文档有长度限制) if len(content) > 15000: content = content[:15000] + "\n\n【内容过长,已截断】" return content except Exception as e: print(f"❌ 读取章节失败: {e}") return f"读取失败: {e}" def create_feishu_document(self): """创建飞书文档""" print("📝 创建飞书文档...") # 生成文档内容 title = "《末日重生-开局囤货十亿物资》完整版" current_time = time.strftime("%Y-%m-%d %H:%M:%S") markdown_content = f"""# 《末日重生-开局囤货十亿物资》完整版 ## 📖 小说信息 - **书名**: 末日重生:开局囤货十亿物资 - **平台**: 番茄小说 - **类型**: 都市/末世/重生 - **状态**: 连载中 - **总章节**: {self.sync_state.get('total_chapters', 0)} 章 - **最后更新**: {current_time} - **同步状态**: 自动同步中 ## 📋 章节列表 (以下为章节列表,具体内容请查看各章节) --- """ # 创建文档 try: result = subprocess.run( [ "python3", "-c", f""" import sys sys.path.insert(0, '/root/.openclaw/workspace') from tools.feishu_tools import create_doc result = create_doc( title='{title}', content='''{markdown_content}''', folder_token='root' # 根目录 ) print(result) """ ], capture_output=True, text=True, encoding='utf-8' ) if result.returncode == 0: # 解析返回结果获取文档ID # 这里简化处理,实际需要解析飞书API返回 print("✅ 文档创建成功") return "dummy_doc_id" # 需要替换为实际文档ID else: print(f"❌ 文档创建失败: {result.stderr}") return None except Exception as e: print(f"❌ 创建文档异常: {e}") return None def update_feishu_document(self, chapters): """更新飞书文档""" if not self.sync_state.get("feishu_doc_id"): # 创建新文档 doc_id = self.create_feishu_document() if doc_id: self.sync_state["feishu_doc_id"] = doc_id self.save_sync_state() else: print("❌ 无法创建飞书文档") return False print(f"📤 更新飞书文档: {self.sync_state['feishu_doc_id']}") # 构建完整的Markdown内容 full_content = self.build_complete_markdown(chapters) # 更新文档 try: result = subprocess.run( [ "python3", "-c", f""" import sys sys.path.insert(0, '/root/.openclaw/workspace') from tools.feishu_tools import update_doc result = update_doc( doc_id='{self.sync_state["feishu_doc_id"]}', content='''{full_content}''', mode='overwrite' ) print(result) """ ], capture_output=True, text=True, encoding='utf-8' ) if result.returncode == 0: print("✅ 文档更新成功") return True else: print(f"❌ 文档更新失败: {result.stderr}") return False except Exception as e: print(f"❌ 更新文档异常: {e}") return False def build_complete_markdown(self, chapters): """构建完整的Markdown内容""" current_time = time.strftime("%Y-%m-%d %H:%M:%S") markdown_lines = [ f"# 《末日重生-开局囤货十亿物资》完整版", "", f"## 📖 小说信息", f"- **书名**: 末日重生:开局囤货十亿物资", f"- **平台**: 番茄小说", f"- **类型**: 都市/末世/重生", f"- **状态**: 连载中", f"- **总章节**: {len(chapters)} 章", f"- **最后更新**: {current_time}", f"- **同步状态**: 自动同步", "", "## 📋 章节列表", "" ] # 添加章节链接(实际为锚点) for chap in chapters: markdown_lines.append(f"### 第{chap['number']}章 {chap['title']}") markdown_lines.append(f"字数: {chap['size']} 字符 | 更新时间: {time.strftime('%Y-%m-%d %H:%M', time.localtime(chap['modified']))}") markdown_lines.append("") # 读取章节内容(前500字符预览) try: with open(chap['file'], 'r', encoding='utf-8') as f: preview = f.read(500) preview = preview.replace('\n', ' ').strip() if len(preview) > 200: preview = preview[:200] + "..." markdown_lines.append(f"**内容预览**: {preview}") except: markdown_lines.append("**内容预览**: [读取失败]") markdown_lines.append("") markdown_lines.append("---") markdown_lines.append("") # 添加所有完整章节内容 markdown_lines.append("## 📖 完整章节内容") markdown_lines.append("") for chap in chapters: markdown_lines.append(f"### 第{chap['number']}章 {chap['title']}") markdown_lines.append("") content = self.read_chapter_content(chap['file']) markdown_lines.append(content) markdown_lines.append("") markdown_lines.append("---") markdown_lines.append("") return "\n".join(markdown_lines) def sync_to_feishu_table(self, chapters): """同步到飞书多维表格(更好的方案)""" print("🔄 同步到飞书多维表格...") # 检查是否已经有表格 app_token = "MkRqbphc2afqEksxf6vcJjZVn8O" # 来自记忆的表格token table_id = "tbllH7wGmGbSCtPD" # 为每章创建记录 for chap in chapters: if chap["number"] not in self.sync_state["synced_chapters"]: print(f"📤 同步第{chap['number']}章: {chap['title']}") # 读取内容 content = self.read_chapter_content(chap['file']) # 构建记录数据 record_data = { "章节号": chap["number"], "标题": chap["title"], "字数": chap["size"], "状态": "已同步", "更新时间": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(chap["modified"])) } # 这里需要调用飞书API添加记录 # 实际实现需要飞书API调用 # 标记为已同步 self.sync_state["synced_chapters"].append(chap["number"]) self.save_sync_state() print(f"✅ 已同步 {len(self.sync_state['synced_chapters'])} 章到飞书表格") return True def run_sync(self, mode="table"): """执行同步""" print("=== 小说内容同步到飞书 ===") print(f"时间: {time.strftime('%Y-%m-%d %H:%M:%S')}") print(f"小说: 《末日重生-开局囤货十亿物资》") print(f"目录: {self.chapters_dir}") print("") # 发现章节 chapters = self.discover_chapters() print(f"📚 发现 {len(chapters)} 个章节:") for chap in chapters[:5]: # 显示前5章 print(f" 第{chap['number']:02d}章: {chap['title']} ({chap['size']} 字符)") if len(chapters) > 5: print(f" ... 还有 {len(chapters)-5} 章") print("") # 更新状态 self.sync_state["total_chapters"] = len(chapters) self.sync_state["last_sync_time"] = time.time() # 选择同步模式 if mode == "table": success = self.sync_to_feishu_table(chapters) else: success = self.update_feishu_document(chapters) if success: print("") print("✅ 同步完成!") print(f"📊 统计:") print(f" - 总章节: {len(chapters)} 章") print(f" - 已同步: {len(self.sync_state['synced_chapters'])} 章") print(f" - 新章节: {len(chapters) - len(self.sync_state['synced_chapters'])} 章") print("") print("🔗 飞书查看:") if mode == "table": print(" https://ecncmdjvm81e.feishu.cn/base/MkRqbphc2afqEksxf6vcJjZVn8O") elif self.sync_state.get("feishu_doc_id"): print(f" 文档ID: {self.sync_state['feishu_doc_id']}") else: print("❌ 同步失败") return success def main(): """主函数""" import argparse parser = argparse.ArgumentParser(description="同步小说内容到飞书") parser.add_argument("--mode", choices=["doc", "table"], default="table", help="同步模式: doc=文档, table=表格(默认)") parser.add_argument("--force", action="store_true", help="强制重新同步所有章节") args = parser.parse_args() sync = NovelToFeishuSync() if args.force: sync.sync_state["synced_chapters"] = [] sync.run_sync(mode=args.mode) if __name__ == "__main__": main()