项目初始化:小说创作工具集

- 创建飞书同步工具 (Python版)
- 创建字数统计工具
- 创建章节生成器
- 创建番茄黄金三章模板
- 完善项目文档和结构
- 配置完整的工具链
This commit is contained in:
唐天洛 2026-03-30 12:32:57 +08:00
commit 5ae289decb
7 changed files with 1202 additions and 0 deletions

96
PROJECT.md Normal file
View File

@ -0,0 +1,96 @@
# 小说创作工具项目
## 项目信息
- **名称**: 小说创作工具集
- **类型**: 工具、脚本、自动化
- **状态**: 持续开发中
- **目标**: 提供高效的小说创作工具链
- **作者**: 唐天洛
- **创建时间**: 2026年3月30日
## 项目目标
1. **提升效率**: 自动化重复性工作
2. **质量控制**: 辅助质量检查和优化
3. **进度管理**: 跟踪创作进度和数据
4. **同步备份**: 管理多平台同步和备份
## 核心工具
### 1. 创作管理工具
- **章节生成器**: 结构化章节生成
- **大纲助手**: 大纲规划和梳理
- **人物管理**: 人物设定和关系管理
- **情节设计**: 爽点设计和情节编排
### 2. 质量检查工具
- **字数统计**: 章节字数、总字数统计
- **节奏分析**: 节奏快慢和爽点密度分析
- **对话检查**: 对话占比和口语化检查
- **逻辑校验**: 时间线、空间位置逻辑检查
### 3. 同步工具
- **飞书同步**: 自动同步到飞书文档
- **Git同步**: 版本控制和云端备份
- **多平台适配**: 适配番茄、起点等平台格式
- **数据同步**: 进度数据自动同步
### 4. 自动化工具
- **定时检查**: 自动检查创作进度
- **模板应用**: 快速应用创作模板
- **文件整理**: 自动整理和归档文件
- **数据分析**: 创作数据分析和报告
## 项目结构
```
小说工具/
├── PROJECT.md # 项目说明(本文件)
├── README.md # 详细使用说明
├── generators/ # 生成器工具
│ ├── chapter_generator.py
│ ├── outline_generator.py
│ └── character_generator.py
├── analyzers/ # 分析工具
│ ├── word_count.py
│ ├── rhythm_analyzer.py
│ └── dialogue_checker.py
├── sync_tools/ # 同步工具
│ ├── feishu_sync.py
│ ├── git_sync.py
│ └── platform_adapter.py
├── automation/ # 自动化脚本
│ ├── daily_check.sh
│ ├── file_organizer.py
│ └── data_analyzer.py
├── templates/ # 模板文件
│ ├── 番茄黄金三章.md
│ ├── 玄幻大纲模板.md
│ └── 悬疑情节模板.md
└── configs/ # 配置文件
├── feishu_config.json
├── git_config.json
└── platform_config.json
```
## 当前已有工具
1. **feishu_novel_sync.sh**: 飞书小说同步脚本
2. **sync_novel_to_feishu.py**: Python版同步脚本
3. **inkos_monitor.sh**: inkos创作监控脚本
4. **番茄创作工作流.md**: 番茄平台创作工作流文档
## 开发计划
1. **第一阶段**: 完善已有工具,统一接口
2. **第二阶段**: 开发Web界面方便使用
3. **第三阶段**: 集成AI辅助创作功能
4. **第四阶段**: 开发团队协作功能
## 使用说明
1. **安装依赖**: 根据工具要求安装Python/Shell依赖
2. **配置环境**: 配置飞书、Git等平台API
3. **定时运行**: 设置定时任务自动运行
4. **监控反馈**: 监控运行结果,调整配置
## 项目价值
1. **个人效率**: 大幅提升个人创作效率
2. **质量保障**: 系统化保障作品质量
3. **数据驱动**: 基于数据的创作决策
4. **可扩展性**: 可扩展到团队协作和多平台

95
README.md Normal file
View File

@ -0,0 +1,95 @@
# 小说创作工具集
## 项目简介
为番茄小说创作者提供完整的工具链,涵盖创作、管理、同步、分析全流程。
## 核心功能
### 1. 创作管理
- 章节生成器
- 大纲助手
- 人物管理
- 情节设计
### 2. 质量检查
- 字数统计
- 节奏分析
- 对话检查
- 逻辑校验
### 3. 同步工具
- 飞书同步
- Git同步
- 多平台适配
- 数据同步
### 4. 自动化
- 定时检查
- 模板应用
- 文件整理
- 数据分析
## 快速开始
### 安装
```bash
# 克隆项目
git clone https://gitea.nevadalice.top:226/liyuchen/novel-tools.git
# 安装依赖
pip install -r requirements.txt
```
### 使用
```bash
# 创建新小说项目
./create_novel_project.sh 末日重生 "末日重生-开局囤货十亿物资" 末世重生
# 统计章节
cd 末日重生 && ./tools/章节统计.sh
# 同步到飞书
python sync_tools/feishu_sync.py
```
## 项目结构
```
小说工具/
├── README.md # 项目说明
├── create_novel_project.sh # 项目创建工具
├── generators/ # 生成器
├── analyzers/ # 分析工具
├── sync_tools/ # 同步工具
├── automation/ # 自动化脚本
├── templates/ # 模板文件
└── configs/ # 配置文件
```
## 已有工具
1. `create_novel_project.sh` - 快速创建小说项目
2. `feishu_novel_sync.sh` - 飞书小说同步(原版)
3. `sync_novel_to_feishu.py` - Python版同步
4. `inkos_monitor.sh` - inkos创作监控
## 开发计划
### 第一阶段(已完成)
- [x] 基础工具框架
- [x] 项目创建工具
- [x] 基础同步工具
### 第二阶段(进行中)
- [ ] 章节生成器
- [ ] 质量分析工具
- [ ] Web管理界面
### 第三阶段(规划中)
- [ ] AI辅助创作
- [ ] 数据分析平台
- [ ] 团队协作功能
## 贡献指南
1. Fork本项目
2. 创建功能分支
3. 提交Pull Request
4. 通过代码审查
## 许可证
MIT License

199
analyzers/word_count.py Executable file
View File

@ -0,0 +1,199 @@
#!/usr/bin/env python3
"""
小说字数统计工具
统计章节字数总字数进度等
"""
import os
import re
from datetime import datetime
import json
class WordCounter:
def __init__(self):
self.total_words = 0
self.total_chars = 0
self.chapter_stats = []
def count_file(self, file_path):
"""统计单个文件"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 计算字数(中文字符+英文单词)
chinese_chars = len(re.findall(r'[\u4e00-\u9fff]', content))
english_words = len(re.findall(r'\b[a-zA-Z]+\b', content))
total_words = chinese_chars + english_words
# 计算总字符数
total_chars = len(content)
# 计算段落数
paragraphs = len([p for p in content.split('\n\n') if p.strip()])
# 计算对话行数
dialogue_lines = len(re.findall(r'["「][^"」]+["」]', content))
return {
"file": file_path,
"words": total_words,
"chars": total_chars,
"paragraphs": paragraphs,
"dialogue_lines": dialogue_lines,
"dialogue_ratio": round(dialogue_lines / max(paragraphs, 1), 2)
}
except Exception as e:
print(f"统计文件失败 {file_path}: {e}")
return None
def count_project(self, project_path):
"""统计整个项目"""
chapters_dir = os.path.join(project_path, "chapters")
if not os.path.exists(chapters_dir):
print(f"章节目录不存在: {chapters_dir}")
return None
# 获取所有章节文件
chapter_files = []
for root, dirs, files in os.walk(chapters_dir):
for file in files:
if file.endswith('.md'):
chapter_files.append(os.path.join(root, file))
if not chapter_files:
print("没有找到章节文件")
return None
# 按文件名排序
chapter_files.sort()
# 统计每个章节
self.chapter_stats = []
self.total_words = 0
self.total_chars = 0
for chapter_file in chapter_files:
stats = self.count_file(chapter_file)
if stats:
self.chapter_stats.append(stats)
self.total_words += stats['words']
self.total_chars += stats['chars']
return {
"project": project_path,
"total_chapters": len(self.chapter_stats),
"total_words": self.total_words,
"total_chars": self.total_chars,
"avg_words_per_chapter": round(self.total_words / max(len(self.chapter_stats), 1)),
"chapters": self.chapter_stats
}
def generate_report(self, project_path, output_path=None):
"""生成统计报告"""
stats = self.count_project(project_path)
if not stats:
return None
# 番茄平台标准
tomato_standard = 2500 # 每章标准字数
daily_target = 4000 # 日更目标
# 计算进度
completed_chapters = stats['total_chapters']
total_words = stats['total_words']
avg_words = stats['avg_words_per_chapter']
# 评估
if avg_words < 2000:
word_rating = "⚠️ 字数偏少"
elif avg_words < 2500:
word_rating = "✅ 符合标准"
elif avg_words < 3500:
word_rating = "✅ 字数充足"
else:
word_rating = "⚠️ 字数偏多"
# 对话占比评估
avg_dialogue_ratio = sum(s['dialogue_ratio'] for s in self.chapter_stats) / len(self.chapter_stats)
if avg_dialogue_ratio < 0.3:
dialogue_rating = "⚠️ 对话偏少(影响听书分成)"
elif avg_dialogue_ratio < 0.5:
dialogue_rating = "✅ 对话适中"
else:
dialogue_rating = "✅ 对话丰富(适合听书)"
# 生成报告
report = f"""
# 小说字数统计报告
## 项目信息
- 项目路径: {project_path}
- 统计时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
- 章节数量: {completed_chapters}
- 总字数: {total_words}
- 总字符数: {stats['total_chars']} 字符
## 章节统计
- 平均每章字数: {avg_words}
- 字数评估: {word_rating}
- 平均对话占比: {avg_dialogue_ratio:.1%}
- 对话评估: {dialogue_rating}
## 番茄平台适配
### 字数要求
- 标准章节字数: 2500-3500
- 当前平均: {avg_words}
- 状态: {"符合" if 2000 <= avg_words <= 3500 else "需要调整"}
### 更新要求
- 日更全勤要求: 4000/
- 当前总字数: {total_words}
- 相当于: {total_words // 4000} 天的全勤更新量
### 听书优化
- 推荐对话占比: >30%
- 当前对话占比: {avg_dialogue_ratio:.1%}
- 状态: {"适合听书" if avg_dialogue_ratio >= 0.3 else "需要增加对话"}
## 详细章节数据
"""
# 添加每个章节的详细数据
for i, chapter in enumerate(self.chapter_stats, 1):
chapter_name = os.path.basename(chapter['file']).replace('.md', '')
report += f"\n### 第{i}章: {chapter_name}\n"
report += f"- 字数: {chapter['words']}\n"
report += f"- 字符: {chapter['chars']} 字符\n"
report += f"- 段落: {chapter['paragraphs']}\n"
report += f"- 对话行: {chapter['dialogue_lines']}\n"
report += f"- 对话占比: {chapter['dialogue_ratio']:.1%}\n"
# 保存报告
if output_path:
os.makedirs(os.path.dirname(output_path), exist_ok=True)
with open(output_path, 'w', encoding='utf-8') as f:
f.write(report)
print(f"报告已保存: {output_path}")
return report
def main():
"""主函数"""
import argparse
parser = argparse.ArgumentParser(description="小说字数统计工具")
parser.add_argument("--project", help="项目路径", default=".")
parser.add_argument("--output", help="输出报告路径")
args = parser.parse_args()
counter = WordCounter()
report = counter.generate_report(args.project, args.output)
if report:
print(report)
if __name__ == "__main__":
main()

205
create_novel_project.sh Executable file
View File

@ -0,0 +1,205 @@
#!/bin/bash
# 小说项目创建工具
# 用法: ./create_novel_project.sh 项目名称 "小说名称" 类型
if [ $# -lt 3 ]; then
echo "用法: $0 项目目录名 小说名称 类型"
echo "示例: $0 末日重生_囤货 \"末日重生-开局囤货十亿物资\" 末世重生"
exit 1
fi
PROJECT_DIR="$1"
NOVEL_NAME="$2"
NOVEL_TYPE="$3"
PROJECTS_ROOT="/root/.openclaw/workspace/projects"
TARGET_DIR="$PROJECTS_ROOT/$PROJECT_DIR"
# 检查是否已存在
if [ -d "$TARGET_DIR" ]; then
echo "错误: 项目目录 '$PROJECT_DIR' 已存在"
exit 1
fi
# 创建项目目录
echo "创建项目: $NOVEL_NAME"
mkdir -p "$TARGET_DIR"
cd "$TARGET_DIR"
# 初始化Git仓库
git init
git config user.name "唐天洛"
git config user.email "563415956@qq.com"
# 创建基础目录结构
mkdir -p chapters outlines assets/characters assets/settings assets/plots tools sync progress
# 创建PROJECT.md
cat > PROJECT.md << EOF
# 《$NOVEL_NAME》项目
## 项目信息
- **书名**: $NOVEL_NAME
- **类型**: $NOVEL_TYPE
- **状态**: 新项目
- **目标平台**: 番茄小说
- **作者**: 唐天洛
- **创建时间**: $(date '+%Y年%m月%d日')
## 项目结构
\`\`\`
$PROJECT_DIR/
├── PROJECT.md # 项目说明(本文件)
├── README.md # 项目详细介绍
├── chapters/ # 章节文件
├── outlines/ # 大纲和规划
├── assets/ # 资源文件
│ ├── characters/ # 人物资料
│ ├── settings/ # 世界观设定
│ └── plots/ # 情节设计
├── tools/ # 项目工具
├── sync/ # 同步配置
└── progress/ # 进度跟踪
\`\`\`
## 当前进度
- **章节**: 0章
- **字数**: 0字
- **状态**: 规划阶段
## 平台要求
- **番茄黄金三章**: 待完成
- **章节结构**: 承接→推进→高潮→钩子
- **字数要求**: 每章2500-3500字
- **更新要求**: 日更4000字全勤奖最低要求
## 创作计划
1. **第一阶段**: 人物设定和世界观构建
2. **第二阶段**: 大纲规划和爽点设计
3. **第三阶段**: 黄金三章创作
4. **第四阶段**: 持续更新
EOF
# 创建README.md
cat > README.md << EOF
# 《$NOVEL_NAME》
## 项目简介
$NOVEL_TYPE题材小说$NOVEL_NAME
## 项目状态
- 🟡 规划阶段
- 📅 创建时间: $(date '+%Y-%m-%d')
- ✍️ 作者: 唐天洛
## 快速开始
1. 在 \`outlines/\` 目录下规划大纲
2. 在 \`assets/\` 目录下创建人物和设定
3. 在 \`chapters/\` 目录下创作章节
4. 使用 \`tools/\` 中的工具进行管理
## 目录说明
- \`chapters/\` - 章节文件 (.md格式)
- \`outlines/\` - 大纲文件
- \`assets/characters/\` - 人物设定
- \`assets/settings/\` - 世界观设定
- \`assets/plots/\` - 情节设计
- \`tools/\` - 管理工具
- \`sync/\` - 同步配置
- \`progress/\` - 进度跟踪
## 更新日志
- $(date '+%Y-%m-%d'): 项目创建
EOF
# 创建.gitignore
cat > .gitignore << EOF
# 临时文件
*.tmp
*.log
*.bak
# 系统文件
.DS_Store
Thumbs.db
# 编辑器文件
.vscode/
.idea/
*.swp
# 配置文件(包含敏感信息)
config.json
*.key
*.pem
.env
# 大文件
*.zip
*.rar
*.7z
EOF
# 创建基础工具
cat > tools/章节统计.sh << 'EOF'
#!/bin/bash
# 章节统计工具
echo "=== 章节统计 ==="
echo "项目: 《'$NOVEL_NAME'》"
echo "统计时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
# 统计章节数量
if [ -d "chapters" ]; then
CHAPTER_COUNT=$(find chapters -name "*.md" | wc -l)
echo "章节数量: $CHAPTER_COUNT"
# 统计总字数
TOTAL_WORDS=0
for file in chapters/*.md; do
if [ -f "$file" ]; then
WORDS=$(wc -w < "$file" 2>/dev/null || echo 0)
TOTAL_WORDS=$((TOTAL_WORDS + WORDS))
fi
done
echo "总字数: $TOTAL_WORDS"
# 显示最近章节
echo "最近章节:"
find chapters -name "*.md" -exec ls -lt {} + | head -5 | awk '{print $9}'
else
echo "chapters目录不存在"
fi
echo ""
echo "=== 统计完成 ==="
EOF
chmod +x tools/章节统计.sh
# 创建进度跟踪文件
cat > progress/更新日志.md << EOF
# 更新日志
## $(date '+%Y年%m月')
### $(date '+%Y-%m-%d')
- [x] 项目创建
- [ ] 人物设定完成
- [ ] 大纲规划完成
- [ ] 第一章完成
EOF
# 初始化提交
git add .
git commit -m "项目初始化: $NOVEL_NAME"
echo ""
echo "✅ 项目创建完成: $TARGET_DIR"
echo "📖 小说: $NOVEL_NAME"
echo "📁 目录结构已创建"
echo "🔧 Git仓库已初始化"
echo ""
echo "下一步:"
echo "1. 在 outlines/ 目录下规划大纲"
echo "2. 在 assets/ 目录下创建人物设定"
echo "3. 开始创作第一章"

204
generators/chapter_generator.py Executable file
View File

@ -0,0 +1,204 @@
#!/usr/bin/env python3
"""
章节生成器
根据模板生成标准化的章节结构
"""
import os
import re
from datetime import datetime
class ChapterGenerator:
def __init__(self, template_path=None):
"""初始化生成器"""
self.template = self.load_template(template_path) or self.default_template()
def load_template(self, template_path):
"""加载模板文件"""
if template_path and os.path.exists(template_path):
with open(template_path, 'r', encoding='utf-8') as f:
return f.read()
return None
def default_template(self):
"""默认模板(番茄黄金三章模板)"""
return """# 第{chapter_number}章:{chapter_title}
## 承接100-300字
{setup}
## 推进800-2000字
{development}
## 高潮500-1000字
{climax}
## 钩子100-300字
{hook}
---
**字数统计**: {word_count}
**更新时间**: {update_time}
**作者备注**: {note}
"""
def generate(self, chapter_number, chapter_title, setup, development, climax, hook, note=""):
"""生成章节内容"""
# 计算字数
word_count = len(setup + development + climax + hook)
# 填充模板
content = self.template.format(
chapter_number=chapter_number,
chapter_title=chapter_title,
setup=setup,
development=development,
climax=climax,
hook=hook,
word_count=word_count,
update_time=datetime.now().strftime('%Y-%m-%d %H:%M'),
note=note or "正常更新"
)
return content
def save_chapter(self, project_path, chapter_number, chapter_title, content, **kwargs):
"""保存章节文件"""
# 创建章节目录
chapters_dir = os.path.join(project_path, "chapters")
os.makedirs(chapters_dir, exist_ok=True)
# 生成文件名
filename = f"ch{chapter_number:02d}-{chapter_title}.md"
filepath = os.path.join(chapters_dir, filename)
# 保存文件
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
print(f"章节已保存: {filepath}")
return filepath
def generate_from_outline(self, project_path, outline_file):
"""根据大纲文件生成章节"""
if not os.path.exists(outline_file):
print(f"大纲文件不存在: {outline_file}")
return []
# 读取大纲
with open(outline_file, 'r', encoding='utf-8') as f:
outline_content = f.read()
# 解析大纲中的章节信息
# 这里假设大纲有特定的格式
chapters = []
# 简单示例:解析 ## 第X章标题 格式
chapter_pattern = r'##\s*第(\d+)章[:]\s*(.+?)\n(.*?)(?=##\s*第|\Z)'
matches = re.findall(chapter_pattern, outline_content, re.DOTALL)
for match in matches:
chapter_num = int(match[0])
chapter_title = match[1].strip()
chapter_content = match[2].strip()
# 从内容中提取各个部分(简单实现)
sections = self.parse_chapter_content(chapter_content)
# 生成章节
content = self.generate(
chapter_number=chapter_num,
chapter_title=chapter_title,
setup=sections.get('承接', ''),
development=sections.get('推进', ''),
climax=sections.get('高潮', ''),
hook=sections.get('钩子', ''),
note="从大纲生成"
)
# 保存章节
filepath = self.save_chapter(project_path, chapter_num, chapter_title, content)
chapters.append(filepath)
return chapters
def parse_chapter_content(self, content):
"""解析章节内容为各个部分"""
sections = {}
# 简单按行分割
current_section = None
section_content = []
for line in content.split('\n'):
line = line.strip()
# 检查是否是新的章节部分
if line.startswith('###'):
if current_section and section_content:
sections[current_section] = '\n'.join(section_content).strip()
# 提取章节标题
section_title = line.replace('###', '').strip()
if '承接' in section_title:
current_section = '承接'
elif '推进' in section_title:
current_section = '推进'
elif '高潮' in section_title:
current_section = '高潮'
elif '钩子' in section_title:
current_section = '钩子'
else:
current_section = None
section_content = []
elif current_section and line:
section_content.append(line)
# 处理最后一个部分
if current_section and section_content:
sections[current_section] = '\n'.join(section_content).strip()
return sections
def main():
"""主函数"""
import argparse
parser = argparse.ArgumentParser(description="章节生成器")
parser.add_argument("--project", help="项目路径", default=".")
parser.add_argument("--number", type=int, help="章节编号", required=True)
parser.add_argument("--title", help="章节标题", required=True)
parser.add_argument("--setup", help="承接部分", default="")
parser.add_argument("--development", help="推进部分", default="")
parser.add_argument("--climax", help="高潮部分", default="")
parser.add_argument("--hook", help="钩子部分", default="")
parser.add_argument("--note", help="作者备注", default="")
parser.add_argument("--outline", help="从大纲文件生成")
args = parser.parse_args()
generator = ChapterGenerator()
if args.outline:
# 从大纲生成
chapters = generator.generate_from_outline(args.project, args.outline)
print(f"从大纲生成了 {len(chapters)} 个章节")
else:
# 直接生成
content = generator.generate(
chapter_number=args.number,
chapter_title=args.title,
setup=args.setup or "承接内容待补充",
development=args.development or "推进内容待补充",
climax=args.climax or "高潮内容待补充",
hook=args.hook or "钩子内容待补充",
note=args.note
)
generator.save_chapter(args.project, args.number, args.title, content)
print("章节生成完成")
if __name__ == "__main__":
main()

287
sync_tools/feishu_sync.py Executable file
View File

@ -0,0 +1,287 @@
#!/usr/bin/env python3
"""
飞书小说同步工具
将本地章节同步到飞书文档
"""
import os
import json
import time
from datetime import datetime
import requests
class FeishuNovelSync:
def __init__(self, config_path="configs/feishu_config.json"):
"""初始化同步工具"""
self.config = self.load_config(config_path)
self.base_url = "https://open.feishu.cn/open-apis"
self.headers = {
"Authorization": f"Bearer {self.config.get('access_token')}",
"Content-Type": "application/json"
}
def load_config(self, config_path):
"""加载配置文件"""
if os.path.exists(config_path):
with open(config_path, 'r', encoding='utf-8') as f:
return json.load(f)
else:
# 默认配置
return {
"app_id": "",
"app_secret": "",
"access_token": "",
"refresh_token": "",
"expire_time": 0
}
def save_config(self, config_path="configs/feishu_config.json"):
"""保存配置文件"""
os.makedirs(os.path.dirname(config_path), exist_ok=True)
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(self.config, f, ensure_ascii=False, indent=2)
def get_access_token(self):
"""获取访问令牌"""
if self.config.get('expire_time', 0) > time.time():
return self.config.get('access_token')
url = f"{self.base_url}/auth/v3/tenant_access_token/internal"
data = {
"app_id": self.config['app_id'],
"app_secret": self.config['app_secret']
}
try:
response = requests.post(url, json=data)
result = response.json()
if result.get('code') == 0:
self.config['access_token'] = result['tenant_access_token']
self.config['expire_time'] = time.time() + result['expire'] - 60
self.save_config()
return self.config['access_token']
else:
print(f"获取token失败: {result}")
return None
except Exception as e:
print(f"请求失败: {e}")
return None
def create_doc(self, title, folder_token=None):
"""创建飞书文档"""
token = self.get_access_token()
if not token:
return None
url = f"{self.base_url}/drive/v1/files/create"
headers = self.headers.copy()
headers["Authorization"] = f"Bearer {token}"
data = {
"title": title,
"type": "doc",
"folder_token": folder_token or ""
}
try:
response = requests.post(url, headers=headers, json=data)
result = response.json()
if result.get('code') == 0:
doc_token = result['data']['token']
print(f"文档创建成功: {title} (token: {doc_token})")
return doc_token
else:
print(f"创建文档失败: {result}")
return None
except Exception as e:
print(f"创建文档请求失败: {e}")
return None
def update_doc(self, doc_token, content):
"""更新文档内容"""
token = self.get_access_token()
if not token:
return False
url = f"{self.base_url}/drive/v1/files/{doc_token}/content"
headers = self.headers.copy()
headers["Authorization"] = f"Bearer {token}"
# 构建文档内容
doc_content = {
"title": "小说章节",
"body": {
"blocks": [
{
"type": "paragraph",
"paragraph": {
"elements": [
{
"type": "text",
"text": content
}
]
}
}
]
}
}
try:
response = requests.put(url, headers=headers, json=doc_content)
result = response.json()
if result.get('code') == 0:
print(f"文档更新成功: {doc_token}")
return True
else:
print(f"更新文档失败: {result}")
return False
except Exception as e:
print(f"更新文档请求失败: {e}")
return False
def sync_chapter(self, chapter_path, doc_token=None, title=None):
"""同步单个章节"""
if not os.path.exists(chapter_path):
print(f"章节文件不存在: {chapter_path}")
return None
# 读取章节内容
with open(chapter_path, 'r', encoding='utf-8') as f:
content = f.read()
# 获取章节标题
if not title:
title = os.path.basename(chapter_path).replace('.md', '')
# 如果没有文档token先创建文档
if not doc_token:
doc_token = self.create_doc(title)
if not doc_token:
return None
# 更新文档内容
if self.update_doc(doc_token, content):
return doc_token
else:
return None
def sync_project(self, project_path, folder_token=None):
"""同步整个项目"""
if not os.path.exists(project_path):
print(f"项目路径不存在: {project_path}")
return False
chapters_dir = os.path.join(project_path, "chapters")
if not os.path.exists(chapters_dir):
print(f"章节目录不存在: {chapters_dir}")
return False
# 获取所有章节文件
chapter_files = []
for root, dirs, files in os.walk(chapters_dir):
for file in files:
if file.endswith('.md'):
chapter_files.append(os.path.join(root, file))
if not chapter_files:
print("没有找到章节文件")
return False
print(f"找到 {len(chapter_files)} 个章节文件")
# 按文件名排序
chapter_files.sort()
# 同步每个章节
results = []
for i, chapter_file in enumerate(chapter_files, 1):
print(f"[{i}/{len(chapter_files)}] 同步: {os.path.basename(chapter_file)}")
chapter_title = os.path.basename(chapter_file).replace('.md', '')
doc_token = self.sync_chapter(chapter_file, None, chapter_title)
if doc_token:
results.append({
"file": chapter_file,
"title": chapter_title,
"doc_token": doc_token,
"status": "success"
})
print(f" 成功: https://example.feishu.cn/docx/{doc_token}")
else:
results.append({
"file": chapter_file,
"title": chapter_title,
"doc_token": None,
"status": "failed"
})
print(f" 失败")
# 避免请求过快
time.sleep(1)
# 保存同步结果
sync_log = {
"project": project_path,
"sync_time": datetime.now().isoformat(),
"total_chapters": len(chapter_files),
"success": len([r for r in results if r['status'] == 'success']),
"failed": len([r for r in results if r['status'] == 'failed']),
"details": results
}
log_file = os.path.join(project_path, "sync", "sync_log.json")
os.makedirs(os.path.dirname(log_file), exist_ok=True)
with open(log_file, 'w', encoding='utf-8') as f:
json.dump(sync_log, f, ensure_ascii=False, indent=2)
print(f"\n同步完成:")
print(f" 总章节: {len(chapter_files)}")
print(f" 成功: {sync_log['success']}")
print(f" 失败: {sync_log['failed']}")
print(f" 日志: {log_file}")
return sync_log['success'] > 0
def main():
"""主函数"""
import argparse
parser = argparse.ArgumentParser(description="飞书小说同步工具")
parser.add_argument("--project", help="项目路径", default=".")
parser.add_argument("--config", help="配置文件路径", default="configs/feishu_config.json")
parser.add_argument("--chapter", help="单个章节文件路径")
parser.add_argument("--init", action="store_true", help="初始化配置")
args = parser.parse_args()
sync_tool = FeishuNovelSync(args.config)
if args.init:
# 初始化配置
app_id = input("请输入 App ID: ")
app_secret = input("请输入 App Secret: ")
sync_tool.config.update({
"app_id": app_id,
"app_secret": app_secret
})
sync_tool.save_config()
print("配置已保存")
return
if args.chapter:
# 同步单个章节
sync_tool.sync_chapter(args.chapter)
else:
# 同步整个项目
sync_tool.sync_project(args.project)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,116 @@
# 番茄黄金三章模板
## 核心原则
1. **第一章300字内出冲突**
2. **第一章出现金手指**
3. **前三章必须有第一个小爽点打脸**
## 第一章模板
### 结构
1. **开篇50字**: 吸引注意力,立即进入场景
2. **冲突100字**: 立即出现矛盾或危机
3. **金手指100字**: 展现主角的特殊能力或优势
4. **初步解决50字**: 展现金手指的作用
5. **钩子50字**: 引出下一章的内容
### 示例
```
# 第一章:重生末日七天前
**开篇**:冰冷的触感从指尖传来,苏晨猛地睁开眼睛。
**冲突**手机日期显示2026年3月30日。七天前。他重生了回到了末日降临前的七天。
**金手指**:【叮!末日生存系统激活!当前任务:在七天内囤积足够物资】
**初步解决**:苏晨看着账户里的五十万存款,笑了。这一世,他要活下来。
**钩子**:门铃突然响起,快递员送来一个神秘木盒:“苏先生,寄件人说您看到里面的东西就会明白。”
```
## 第二章模板
### 结构
1. **承接100字**: 连接第一章的钩子
2. **发展800字**: 展开金手指,开始行动
3. **小高潮300字**: 第一个小爽点
4. **新挑战100字**: 引出新的问题
5. **钩子100字**: 为第三章铺垫
## 第三章模板
### 结构
1. **承接100字**: 解决第二章的挑战
2. **推进600字**: 主角继续发展
3. **第一个爽点400字**: 第一次打脸,让读者爽
4. **世界观展开200字**: 展现更大的世界
5. **钩子100字**: 引出长期目标
## 后续章节模板第4章起
### 标准结构
```
# 第X章章节标题
## 承接100-300字
连接上一章,平稳过渡
## 推进800-2000字
发展情节,展现人物成长
## 高潮500-1000字
本章的核心爽点
## 钩子100-300字
引出下一章的内容
```
## 字数要求
- **每章**: 2500-3500字
- **黄金三章**: 每章至少3000字
- **对话占比**: >30%(适合听书)
- **段落长度**: 每段不超过3行
## 爽点设计
### 常见爽点类型
1. **重生先知**: 利用未来信息碾压
2. **系统外挂**: 系统任务和奖励
3. **家世背景**: 富二代/世家子弟
4. **实力碾压**: 等级压制,装备碾压
5. **打脸反派**: 反派挑衅→主角打脸
### 爽点频率
- **第一章**: 至少1个爽点
- **前三章**: 至少3个爽点
- **后续每章**: 至少1-2个爽点
## 对话技巧
### 听书优化
1. **多对话**: 对话占比30-50%
2. **短对话**: 每句对话不超过2行
3. **口语化**: 使用自然的口语表达
4. **情绪化**: 通过对话展现人物情绪
### 对话示例
```
"就这?"苏鸣歪头,"我还以为多厉害呢。"
"你……你到底是什么境界?"林浩脸色惨白。
"比你高一点点。"苏鸣微笑,"大概高一个大境界吧。"
```
## 避坑指南
1. **不要直白写设定**: 通过对话和行动展现
2. **不要过多心理描写**: 减少内心独白
3. **不要拖沓**: 节奏要快300字内必出进展
4. **不要降智反派**: 反派要有合理动机
## 变现优化
### 全勤奖要求
- **日更4000字**: 600元 + 5%分成
- **日更6000字**: 800元 + 5%分成
- **月更10万字**: 听读≥500
### 听书分成
- **对话占比高**: 提升听书体验
- **节奏明快**: 减少听书疲劳
- **口语化**: 适合语音朗读
- **章节分明**: 每章完整故事