项目初始化:小说创作工具集
- 创建飞书同步工具 (Python版) - 创建字数统计工具 - 创建章节生成器 - 创建番茄黄金三章模板 - 完善项目文档和结构 - 配置完整的工具链
This commit is contained in:
commit
5ae289decb
96
PROJECT.md
Normal file
96
PROJECT.md
Normal 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
95
README.md
Normal 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
199
analyzers/word_count.py
Executable 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
205
create_novel_project.sh
Executable 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
204
generators/chapter_generator.py
Executable 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
287
sync_tools/feishu_sync.py
Executable 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()
|
||||||
116
templates/番茄黄金三章模板.md
Normal file
116
templates/番茄黄金三章模板.md
Normal 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
|
||||||
|
|
||||||
|
### 听书分成
|
||||||
|
- **对话占比高**: 提升听书体验
|
||||||
|
- **节奏明快**: 减少听书疲劳
|
||||||
|
- **口语化**: 适合语音朗读
|
||||||
|
- **章节分明**: 每章完整故事
|
||||||
Loading…
Reference in New Issue
Block a user