yunce: v6 移除 HTML 输出,改为纯 Markdown
This commit is contained in:
827
openclaw/yunce/n8n-content-pipeline-workflow-v5.md.bak
Normal file
827
openclaw/yunce/n8n-content-pipeline-workflow-v5.md.bak
Normal file
@@ -0,0 +1,827 @@
|
|||||||
|
# N8N 内容转化流水线工作流设计(v4 → v5 升级)
|
||||||
|
|
||||||
|
> 用于:AI 英文文章 → 中文公众号/X/视频 内容转化
|
||||||
|
> 工作流ID:`iOf32aOKvTjfTDSM`(v4基础)
|
||||||
|
> 触发方式:OpenClaw 通过 Webhook 调用
|
||||||
|
> 管理平台:Mac mini 上的 n8n (`https://n8n.ishenwei.online`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 核心需求更新(v5)
|
||||||
|
|
||||||
|
### 输出要求(重要!)
|
||||||
|
|
||||||
|
**必须同时输出两个版本:**
|
||||||
|
|
||||||
|
| 输出文件 | 路径 | 格式 | 用途 |
|
||||||
|
|---------|------|------|------|
|
||||||
|
| **Markdown 源文件** | `content-output/{原文件名}.md` | 中文 Markdown | Obsidian 留存、溯源 |
|
||||||
|
| **公众号 HTML** | `content-output/{原文件名}.html` | 带样式的 HTML | 直接复制到公众号编辑器 |
|
||||||
|
|
||||||
|
### Obsidian 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
~/Workspace/nexus/openclaw/
|
||||||
|
├── content-queue/ # 原始英文文章(输入)
|
||||||
|
│ └── 2026-03-29-ai-solopreneur.md
|
||||||
|
│
|
||||||
|
└── content-output/ # 成品(输出)
|
||||||
|
├── 2026-03-29-ai-solopreneur.md # 翻译后 Markdown
|
||||||
|
└── 2026-03-29-ai-solopreneur.html # 公众号 HTML(新增)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 工作流概述
|
||||||
|
|
||||||
|
```
|
||||||
|
OpenClaw (发现文章)
|
||||||
|
↓ (保存文件到 n8n-files 目录)
|
||||||
|
↓ (触发 Webhook)
|
||||||
|
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ N8N 工作流 (v5): content-translation-pipeline-v5 │
|
||||||
|
│ │
|
||||||
|
│ [Webhook] → [Read File] → [Extract Text] → [AI Agent] │
|
||||||
|
│ ↓ ↑ (DeepSeek) │
|
||||||
|
│ [Build Markdown] → [Write .md] → [Build HTML] → [Write .html] │
|
||||||
|
│ ↓ │
|
||||||
|
│ [Send Telegram] │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔌 节点详细设计(v5)
|
||||||
|
|
||||||
|
### 节点 1️⃣:Webhook Trigger
|
||||||
|
|
||||||
|
**类型:** Webhook
|
||||||
|
**名称:** `Webhook Trigger`
|
||||||
|
**Path:** `/content-translation-v5`(新建 path)
|
||||||
|
**Method:** POST
|
||||||
|
|
||||||
|
**接收数据格式:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"note_name": "2026-03-29-ai-solopreneur.md",
|
||||||
|
"source_path": "/Users/weishen/Workspace/nexus/openclaw/content-queue/2026-03-29-ai-solopreneur.md",
|
||||||
|
"callback_url": "http://192.168.3.189:18789/webhook/yunce"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 节点 2️⃣:Read Obsidian Note
|
||||||
|
|
||||||
|
**类型:** Read Binary File
|
||||||
|
**名称:** `Read Obsidian Note`
|
||||||
|
|
||||||
|
**配置:**
|
||||||
|
- File Path: `=/home/node/.n8n-files/{{ $json.body.note_name }}`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 节点 3️⃣:Extract from File
|
||||||
|
|
||||||
|
**类型:** Extract from File
|
||||||
|
**名称:** `Extract from File`
|
||||||
|
**Operation:** `text`
|
||||||
|
|
||||||
|
**输出:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"original_content": "...",
|
||||||
|
"note_name": "2026-03-29-ai-solopreneur.md",
|
||||||
|
"source_path": "/Users/weishen/Workspace/nexus/openclaw/content-queue/..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 节点 4️⃣:AI Agent(翻译+改写)
|
||||||
|
|
||||||
|
**类型:** LangChain Agent
|
||||||
|
**名称:** `AI Agent`
|
||||||
|
**Version:** 3.1
|
||||||
|
**Model:** DeepSeek Chat Model
|
||||||
|
|
||||||
|
**Prompt 模板:**
|
||||||
|
```
|
||||||
|
你是一个专业的中文内容编辑,擅长将英文文章转化为适合中国读者的高质量内容。
|
||||||
|
|
||||||
|
## 你的任务
|
||||||
|
|
||||||
|
将以下英文原文转化为:
|
||||||
|
1. 公众号风格的深度文章(2000-3000字)
|
||||||
|
2. X/Twitter 风格的短文案(280字内,带钩子)
|
||||||
|
3. 视频口播脚本(3-5分钟,适合抖音/YouTube)
|
||||||
|
|
||||||
|
## 内容要求
|
||||||
|
|
||||||
|
- 语言:地道中文,无翻译腔
|
||||||
|
- 风格:专业、有干货、适合中国读者
|
||||||
|
- 调性:公众号大V风格,有观点有案例
|
||||||
|
- 商业化:可自然植入 AI Agent / 知识管理相关内容(软性,不硬广)
|
||||||
|
|
||||||
|
## 输出格式(严格按此 JSON 返回)
|
||||||
|
|
||||||
|
{
|
||||||
|
"wechat_title": "中文标题",
|
||||||
|
"wechat_excerpt": "公众号摘要(100字内)",
|
||||||
|
"wechat_content": "完整公众号文章(Markdown格式)",
|
||||||
|
"twitter_copy": "X/Twitter文案(280字内,带emoji)",
|
||||||
|
"video_title": "视频标题",
|
||||||
|
"video_script": "口播脚本(含时间戳和字幕)",
|
||||||
|
"cover_keywords": ["关键词1", "关键词2", "关键词3"]
|
||||||
|
}
|
||||||
|
|
||||||
|
## 原文内容
|
||||||
|
{{ $json.data }}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 节点 5️⃣:Build Markdown(新增)
|
||||||
|
|
||||||
|
**类型:** Code
|
||||||
|
**名称:** `Build Markdown`
|
||||||
|
|
||||||
|
**功能:** 将 AI 输出组装成 Markdown 文件
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const aiResult = $input.first().json.message;
|
||||||
|
const data = typeof aiResult === 'string' ? JSON.parse(aiResult) : aiResult;
|
||||||
|
|
||||||
|
const noteName = $('Webhook Trigger').first().json.body.note_name;
|
||||||
|
// 去掉 .md 后缀,输出到 content-output
|
||||||
|
const outputName = noteName.replace('.md', '.md');
|
||||||
|
const outputPath = '/Users/weishen/Workspace/nexus/openclaw/content-output/' + outputName;
|
||||||
|
|
||||||
|
const markdown = `# ${data.wechat_title}
|
||||||
|
|
||||||
|
${data.wechat_content}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## X/Twitter 文案
|
||||||
|
|
||||||
|
${data.twitter_copy}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 视频信息
|
||||||
|
|
||||||
|
**标题:** ${data.video_title}
|
||||||
|
|
||||||
|
**口播脚本:**
|
||||||
|
|
||||||
|
${data.video_script}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*封面图关键词:${data.cover_keywords?.join(', ')}*
|
||||||
|
`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
json: {
|
||||||
|
output_path: outputPath,
|
||||||
|
output_content: markdown,
|
||||||
|
source_path: $('Webhook Trigger').first().json.body.source_path
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 节点 6️⃣:Write .md File(新增)
|
||||||
|
|
||||||
|
**类型:** Write Binary File / ReadWriteFile
|
||||||
|
**名称:** `Write Markdown Note`
|
||||||
|
|
||||||
|
**配置:**
|
||||||
|
- Operation: `write`
|
||||||
|
- File Path: `=/home/node/.n8n-files/{{ $json.body.output_name }}_output.md`
|
||||||
|
- Content: `={{ $json.output_content }}`
|
||||||
|
|
||||||
|
**注意:** 输出到 n8n-files/ 目录,由 OpenClaw 负责复制回 Obsidian。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 节点 7️⃣:Build HTML(新增,核心)
|
||||||
|
|
||||||
|
**类型:** Code
|
||||||
|
**名称:** `Build WeChat HTML`
|
||||||
|
|
||||||
|
**功能:** 将 Markdown 转为带样式的公众号 HTML
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const aiResult = $input.first().json.message;
|
||||||
|
const data = typeof aiResult === 'string' ? JSON.parse(aiResult) : aiResult;
|
||||||
|
|
||||||
|
const outputName = $('Webhook Trigger').first().json.body.output_name;
|
||||||
|
const htmlPath = '/home/node/.n8n-files/' + outputName + '_output.html';
|
||||||
|
|
||||||
|
// 公众号 HTML 模板
|
||||||
|
const html = `<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: #333;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
text-align: center;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
border-left: 4px solid #007aff;
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
text-align: justify;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
text-indent: 2em;
|
||||||
|
}
|
||||||
|
.twitter-copy {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 20px 0;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.video-info {
|
||||||
|
background: #f0f7ff;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.video-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #007aff;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.script {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
.cover-keywords {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
padding-top: 20px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>${data.wechat_title}</h1>
|
||||||
|
|
||||||
|
${data.wechat_content.split('\n').map(line => {
|
||||||
|
if (line.startsWith('# ')) return `<h1 style="text-align:center;font-size:24px;margin:30px 0;">${line.slice(2)}</h1>`;
|
||||||
|
if (line.startsWith('## ')) return `<h2>${line.slice(3)}</h2>`;
|
||||||
|
if (line.startsWith('### ')) return `<h3 style="font-size:17px;color:#333;margin:20px 0 10px;">${line.slice(4)}</h3>`;
|
||||||
|
if (line.trim() === '---') return '<hr style="border:none;border-top:1px solid #eee;margin:30px 0;">';
|
||||||
|
if (line.startsWith('- ') || line.startsWith('* ')) return `<li style="margin:8px 0;">${line.slice(2)}</li>`;
|
||||||
|
if (line.trim() === '') return '';
|
||||||
|
return `<p>${line}</p>`;
|
||||||
|
}).join('\n')}
|
||||||
|
|
||||||
|
<div class="twitter-copy">
|
||||||
|
<strong>📱 X/Twitter 文案:</strong><br>
|
||||||
|
${data.twitter_copy.replace(/\n/g, '<br>')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="video-info">
|
||||||
|
<div class="video-title">🎬 视频标题:${data.video_title}</div>
|
||||||
|
<div class="script">
|
||||||
|
<strong>口播脚本:</strong><br>
|
||||||
|
${data.video_script.replace(/\n/g, '<br>')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cover-keywords">
|
||||||
|
封面图关键词:${data.cover_keywords?.join(' | ')}<br>
|
||||||
|
原文路径:${$('Webhook Trigger').first().json.body.source_path}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
json: {
|
||||||
|
html_path: htmlPath,
|
||||||
|
html_content: html
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 节点 8️⃣:Write .html File(新增)
|
||||||
|
|
||||||
|
**类型:** Write Binary File / ReadWriteFile
|
||||||
|
**名称:** `Write WeChat HTML`
|
||||||
|
|
||||||
|
**配置:**
|
||||||
|
- Operation: `write`
|
||||||
|
- File Path: `=/home/node/.n8n-files/{{ $json.body.output_name }}_output.html`
|
||||||
|
- Content: `={{ $json.html_content }}`
|
||||||
|
|
||||||
|
**注意:** 输出到 n8n-files/ 目录,由 OpenClaw 负责复制回 Obsidian。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 节点 9️⃣:Send Telegram Message
|
||||||
|
|
||||||
|
**类型:** Telegram
|
||||||
|
**名称:** `Send Telegram Message`
|
||||||
|
|
||||||
|
**配置:**
|
||||||
|
- Chat ID: `5038825565`
|
||||||
|
- Text:
|
||||||
|
```
|
||||||
|
✅ 文章转换完成!
|
||||||
|
|
||||||
|
📝 标题:{{ $json.wechat_title }}
|
||||||
|
📁 Markdown:/home/node/.n8n-files/{{ $json.body.output_name }}_output.md
|
||||||
|
🌐 HTML:/home/node/.n8n-files/{{ $json.body.output_name }}_output.html
|
||||||
|
🐦 Twitter 文案:{{ $json.twitter_copy }}
|
||||||
|
```
|
||||||
|
- Credentials: `Telegram XingJiang Bot`
|
||||||
|
|
||||||
|
**注意:** Telegram 只通知完成,OpenClaw 收到通知后负责将文件复制回 Obsidian。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔗 完整节点连接图(v5)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Webhook Trigger │
|
||||||
|
│ POST /content-translation-v5 │
|
||||||
|
└──────────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Read Obsidian Note │
|
||||||
|
│ (Read Binary File) │
|
||||||
|
└──────────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Extract from File │
|
||||||
|
│ (text operation) │
|
||||||
|
└──────────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
┌──────────┴──────────┐
|
||||||
|
│ │
|
||||||
|
│ ┌───────┴────────┐
|
||||||
|
│ │ DeepSeek │
|
||||||
|
│ │ Chat Model │
|
||||||
|
│ └───────┬────────┘
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ AI Agent (LangChain) │
|
||||||
|
│ - system prompt │
|
||||||
|
│ - original content │
|
||||||
|
└──────────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Build Markdown (NEW) │
|
||||||
|
│ 组装中文 Markdown 文件 │
|
||||||
|
└──────────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Write Markdown Note (NEW) │
|
||||||
|
│ → content-output/*.md │
|
||||||
|
└──────────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Build WeChat HTML (NEW) │
|
||||||
|
│ Markdown → 带样式 HTML │
|
||||||
|
└──────────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Write WeChat HTML (NEW) │
|
||||||
|
│ → content-output/*.html │
|
||||||
|
└──────────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Send Telegram Message │
|
||||||
|
│ 文章转换完成通知 │
|
||||||
|
└─────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 调用方式(OpenClaw 侧)
|
||||||
|
|
||||||
|
**重要说明:n8n 只能读写 `/home/node/.n8n-files/` 目录,无法直接访问 Obsidian 目录。因此 OpenClaw 负责文件搬运,n8n 专注处理。**
|
||||||
|
|
||||||
|
### OpenClaw 完整流程:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# =============================================
|
||||||
|
# 步骤 1:OpenClaw 复制原文到 n8n-files 目录
|
||||||
|
# =============================================
|
||||||
|
# SSH 到 MacMini,将源文件复制到 n8n 容器可访问的目录
|
||||||
|
scp /Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md \
|
||||||
|
macmini:/home/node/.n8n-files/article-2026-03-29.md
|
||||||
|
|
||||||
|
# =============================================
|
||||||
|
# 步骤 2:OpenClaw 触发 n8n Webhook
|
||||||
|
# =============================================
|
||||||
|
curl -X POST "https://n8n.ishenwei.online/webhook/content-translation-v5" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"note_name": "article-2026-03-29.md",
|
||||||
|
"source_path": "/Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md",
|
||||||
|
"output_name": "article-2026-03-29",
|
||||||
|
"callback_url": "http://192.168.3.189:18789/webhook/yunce"
|
||||||
|
}'
|
||||||
|
|
||||||
|
# =============================================
|
||||||
|
# 步骤 3:n8n 流程执行中...
|
||||||
|
# =============================================
|
||||||
|
# n8n 读取 /home/node/.n8n-files/article-2026-03-29.md
|
||||||
|
# 处理(翻译、改写)
|
||||||
|
# 输出到 /home/node/.n8n-files/article-2026-03-29_output.md
|
||||||
|
# 输出到 /home/node/.n8n-files/article-2026-03-29_output.html
|
||||||
|
# 发送 Telegram 通知
|
||||||
|
|
||||||
|
# =============================================
|
||||||
|
# 步骤 4:OpenClaw 复制输出文件回 Obsidian(工作流完成后)
|
||||||
|
# =============================================
|
||||||
|
# 复制 Markdown 成品
|
||||||
|
scp macmini:/home/node/.n8n-files/article-2026-03-29_output.md \
|
||||||
|
/Users/weishen/Workspace/nexus/openclaw/content-output/article-2026-03-29.md
|
||||||
|
|
||||||
|
# 复制 HTML 成品
|
||||||
|
scp macmini:/home/node/.n8n-files/article-2026-03-29_output.html \
|
||||||
|
/Users/weishen/Workspace/nexus/openclaw/content-output/article-2026-03-29.html
|
||||||
|
|
||||||
|
# =============================================
|
||||||
|
# 步骤 5:清理 n8n-files 临时文件(可选)
|
||||||
|
# =============================================
|
||||||
|
ssh macmini "rm /home/node/.n8n-files/article-2026-03-29.md \
|
||||||
|
/home/node/.n8n-files/article-2026-03-29_output.md \
|
||||||
|
/home/node/.n8n-files/article-2026-03-29_output.html"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 简化版 OpenClaw 代码流程:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
note_name = "article-2026-03-29.md"
|
||||||
|
source_path = "/Users/weishen/Workspace/nexus/openclaw/content-queue/" + note_name
|
||||||
|
output_name = note_name.replace('.md', '')
|
||||||
|
n8n_files = "/home/node/.n8n-files"
|
||||||
|
|
||||||
|
# 1. 复制原文到 n8n-files
|
||||||
|
subprocess.run(['scp', source_path, f'macmini:{n8n_files}/{note_name}'])
|
||||||
|
|
||||||
|
# 2. 触发 Webhook
|
||||||
|
subprocess.run(['curl', '-X', 'POST',
|
||||||
|
'https://n8n.ishenwei.online/webhook/content-translation-v5',
|
||||||
|
'-H', 'Content-Type: application/json',
|
||||||
|
'-d', f'{{"note_name": "{note_name}", "output_name": "{output_name}", ...}}'
|
||||||
|
])
|
||||||
|
|
||||||
|
# 3. 等待 Telegram 通知(工作流完成)
|
||||||
|
|
||||||
|
# 4. 复制输出回 Obsidian
|
||||||
|
subprocess.run(['scp',
|
||||||
|
f'macmini:{n8n_files}/{output_name}_output.md',
|
||||||
|
f'/Users/weishen/Workspace/nexus/openclaw/content-output/{output_name}.md'])
|
||||||
|
subprocess.run(['scp',
|
||||||
|
f'macmini:{n8n_files}/{output_name}_output.html',
|
||||||
|
f'/Users/weishen/Workspace/nexus/openclaw/content-output/{output_name}.html'])
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 最终 Obsidian 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
~/Workspace/nexus/openclaw/
|
||||||
|
├── content-queue/ # 原始英文(输入,OpenClaw 放置)
|
||||||
|
│ └── article-2026-03-29.md
|
||||||
|
│
|
||||||
|
└── content-output/ # 成品(OpenClaw 从 n8n-files/ 复制回来)
|
||||||
|
├── article-2026-03-29.md # 中文 Markdown ✅
|
||||||
|
└── article-2026-03-29.html # 公众号 HTML ✅
|
||||||
|
```
|
||||||
|
|
||||||
|
**文件来源说明:**
|
||||||
|
- n8n 工作流只读写 `/home/node/.n8n-files/` 目录
|
||||||
|
- OpenClaw 在工作流完成后负责将输出文件复制到 Obsidian 目录
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ 验收标准
|
||||||
|
|
||||||
|
1. 触发后自动完成整个流程,无需人工干预
|
||||||
|
2. `content-output/` 目录同时生成 `.md` 和 `.html` 两个文件
|
||||||
|
3. HTML 文件可直接复制粘贴到微信公众号编辑器,格式基本正确
|
||||||
|
4. Telegram 收到完成通知(含标题和文件路径)
|
||||||
|
5. 错误时 n8n 记录错误节点并停止流程
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 备注
|
||||||
|
|
||||||
|
- **Markdown 源文件**:保留中文原文,方便后续修改和溯源
|
||||||
|
- **HTML 文件**:带内联样式,兼容微信公众号编辑器,复制后格式不走形
|
||||||
|
- **文件路径**:写入 Obsidian vault 的 `content-output/` 子目录,需确保 n8n 容器有对应目录的写权限
|
||||||
|
- **API Key**:DeepSeek API 通过 n8n credential 配置,无需在代码中硬编码
|
||||||
|
# 📖 附录:OpenClaw ↔ N8N 通用工作流调用规范(v1.0)
|
||||||
|
|
||||||
|
> 本规范旨在为 OpenClaw 与 N8N 之间的每次交互建立统一标准,使星辉(XingHui)或其他 Agent 能够通过标准化步骤执行任意 N8N 工作流。
|
||||||
|
>
|
||||||
|
> **适用范围**:任何由 OpenClaw 触发、N8N 执行的工作流(不仅限于内容转化流水线)
|
||||||
|
>
|
||||||
|
> **核心约束**:N8N 容器只读写 `/home/node/.n8n-files/` 目录,无法直接访问 Obsidian 或其他宿主机路径。OpenClaw 负责所有文件搬运。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ 架构总览
|
||||||
|
|
||||||
|
```
|
||||||
|
OpenClaw N8N 容器 其他存储
|
||||||
|
Agent (/home/node/.n8n-files/) 位置
|
||||||
|
│ │ │
|
||||||
|
│ ── ① 复制输入文件 ─────────────────→│ │
|
||||||
|
│ │ │
|
||||||
|
│ ── ② POST webhook ─────────────────→│ │
|
||||||
|
│ │ │
|
||||||
|
│ [N8N 执行工作流] │
|
||||||
|
│ │ │
|
||||||
|
│ ←── ③ Telegram / callback 通知 ───│ │
|
||||||
|
│ │ │
|
||||||
|
│ ←── ④ 复制输出文件 ─────────────────│──→ Obsidian 目录 │
|
||||||
|
│ │ │
|
||||||
|
│ ── ⑤ 清理 n8n-files ───────────────→│ │
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 标准化执行步骤(星辉操作指南)
|
||||||
|
|
||||||
|
### 步骤 ①:准备输入文件
|
||||||
|
|
||||||
|
**规则**:所有传递给 N8N 的文件,必须先复制到 N8N 容器可访问的路径。
|
||||||
|
|
||||||
|
**源路径**(由具体任务决定)× → **目标路径**:`macmini:/home/node/.n8n-files/{文件名}`
|
||||||
|
|
||||||
|
**示例(内容转化流水线 v5)**:
|
||||||
|
```bash
|
||||||
|
scp /Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md \
|
||||||
|
macmini:/home/node/.n8n-files/article-2026-03-29.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 步骤 ②:触发 Webhook
|
||||||
|
|
||||||
|
**规则**:通过 `curl` 向 N8N Webhook 端点发送 POST 请求,JSON 数据包含工作流所需的所有元数据。
|
||||||
|
|
||||||
|
**通用格式**:
|
||||||
|
```bash
|
||||||
|
curl -X POST "<N8N_BASE_URL>/webhook/<webhook-path>" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"note_name": "<文件名>",
|
||||||
|
"source_path": "<原始文件路径>",
|
||||||
|
"output_name": "<输出文件名(不含扩展名)>",
|
||||||
|
"callback_url": "<完成后通知地址(可选)>"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**具体示例(内容转化流水线 v5)**:
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://n8n.ishenwei.online/webhook/content-translation-v5" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"note_name": "article-2026-03-29.md",
|
||||||
|
"source_path": "/Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md",
|
||||||
|
"output_name": "article-2026-03-29",
|
||||||
|
"callback_url": "http://192.168.3.189:18789/webhook/yunce"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Webhook Path 查询方式**:
|
||||||
|
如不知道目标工作流的 Webhook path,可通过以下方式确认:
|
||||||
|
1. 在 n8n 管理界面(https://n8n.ishenwei.online)打开对应工作流
|
||||||
|
2. 点击 Webhook 节点,查看右侧 Path 字段
|
||||||
|
3. 或参考本文档相关章节的「Webhook Trigger」配置
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 步骤 ③:等待执行完成
|
||||||
|
|
||||||
|
**规则**:N8N 工作流完成后会发送通知,OpenClaw 需等待此信号后再执行后续复制操作。
|
||||||
|
|
||||||
|
**通知方式**(由具体工作流决定,优先级如下):
|
||||||
|
|
||||||
|
| 方式 | 说明 | 适用场景 |
|
||||||
|
|------|------|---------|
|
||||||
|
| **Telegram Bot** | N8N 通过 Telegram 节点发送消息到指定 Chat ID | 推荐,已知用户 Chat ID |
|
||||||
|
| **Callback URL** | N8N POST 到指定 URL(OpenClaw Webhook) | 需要 OpenClaw 监听端口 |
|
||||||
|
| **轮询 n8n API** | 定期查询工作流执行状态 | 无通知配置时兜底 |
|
||||||
|
|
||||||
|
**Telegram 通知格式(示例)**:
|
||||||
|
```
|
||||||
|
✅ [工作流名称] 执行完成!
|
||||||
|
|
||||||
|
📝 标题:<title>
|
||||||
|
📁 输出文件:/home/node/.n8n-files/<output_name>_output.md
|
||||||
|
🌐 HTML:/home/node/.n8n-files/<output_name>_output.html
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 步骤 ④:复制输出文件
|
||||||
|
|
||||||
|
**规则**:收到完成通知后,从 N8N 容器的 `n8n-files/` 目录复制输出文件到目标存储位置。
|
||||||
|
|
||||||
|
**通用格式**:
|
||||||
|
```bash
|
||||||
|
# 单文件
|
||||||
|
scp macmini:/home/node/.n8n-files/<输出文件名> <目标完整路径>
|
||||||
|
|
||||||
|
# 多文件(循环)
|
||||||
|
for file in <输出文件1> <输出文件2>; do
|
||||||
|
scp macmini:/home/node/.n8n-files/$file <目标目录>/$file
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
**具体示例(内容转化流水线 v5)**:
|
||||||
|
```bash
|
||||||
|
# 复制 Markdown 成品
|
||||||
|
scp macmini:/home/node/.n8n-files/article-2026-03-29_output.md \
|
||||||
|
/Users/weishen/Workspace/nexus/openclaw/content-output/article-2026-03-29.md
|
||||||
|
|
||||||
|
# 复制 HTML 成品
|
||||||
|
scp macmini:/home/node/.n8n-files/article-2026-03-29_output.html \
|
||||||
|
/Users/weishen/Workspace/nexus/openclaw/content-output/article-2026-03-29.html
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 步骤 ⑤:清理临时文件
|
||||||
|
|
||||||
|
**规则**:工作流完成后,删除 `n8n-files/` 下的临时文件,保持容器目录整洁。
|
||||||
|
|
||||||
|
**通用格式**:
|
||||||
|
```bash
|
||||||
|
ssh macmini "rm /home/node/.n8n-files/<输入文件> /home/node/.n8n-files/<输出文件1> /home/node/.n8n-files/<输出文件2>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**具体示例(内容转化流水线 v5)**:
|
||||||
|
```bash
|
||||||
|
ssh macmini "rm /home/node/.n8n-files/article-2026-03-29.md \
|
||||||
|
/home/node/.n8n-files/article-2026-03-29_output.md \
|
||||||
|
/home/node/.n8n-files/article-2026-03-29_output.html"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 OpenClaw 自动化脚本模板(Python)
|
||||||
|
|
||||||
|
以下为通用 Python 模板,适用于任何 OpenClaw → N8N 的文件处理工作流。星辉可直接复制修改使用。
|
||||||
|
|
||||||
|
```python
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# ========== 配置区(每个工作流需修改) ==========
|
||||||
|
N8N_BASE_URL = "https://n8n.ishenwei.online"
|
||||||
|
WEBHOOK_PATH = "content-translation-v5" # <-- 修改为实际 webhook path
|
||||||
|
SOURCE_FILE = "/path/to/source/file.md" # <-- 修改为实际源文件路径
|
||||||
|
N8N_FILES = "/home/node/.n8n-files"
|
||||||
|
NOTE_NAME = "source-file.md" # <-- 修改为实际文件名
|
||||||
|
OUTPUT_NAME = "source-file" # <-- 修改为输出文件名(无扩展名)
|
||||||
|
OUTPUT_DIR = "/Users/weishen/Workspace/nexus/openclaw/content-output"
|
||||||
|
# ============================================
|
||||||
|
|
||||||
|
source_path = SOURCE_FILE
|
||||||
|
n8n_input_path = f"{N8N_FILES}/{NOTE_NAME}"
|
||||||
|
|
||||||
|
print(f"[Step 1/5] 复制输入文件到 N8N 容器: {NOTE_NAME}")
|
||||||
|
result = subprocess.run(
|
||||||
|
['scp', source_path, f'macmini:{n8n_input_path}'],
|
||||||
|
capture_output=True, text=True
|
||||||
|
)
|
||||||
|
if result.returncode != 0:
|
||||||
|
print(f"X 文件复制失败: {result.stderr}")
|
||||||
|
sys.exit(1)
|
||||||
|
print(f"V 已复制到 {n8n_input_path}")
|
||||||
|
|
||||||
|
print(f"[Step 2/5] 触发 N8N Webhook: {WEBHOOK_PATH}")
|
||||||
|
webhook_url = f"{N8N_BASE_URL}/webhook/{WEBHOOK_PATH}"
|
||||||
|
payload = ("{"
|
||||||
|
"\"note_name\": \"" + NOTE_NAME + "\", "
|
||||||
|
"\"source_path\": \"" + source_path + "\", "
|
||||||
|
"\"output_name\": \"" + OUTPUT_NAME + "\""
|
||||||
|
"}")
|
||||||
|
result = subprocess.run(
|
||||||
|
['curl', '-X', 'POST', webhook_url,
|
||||||
|
'-H', 'Content-Type: application/json',
|
||||||
|
'-d', payload],
|
||||||
|
capture_output=True, text=True
|
||||||
|
)
|
||||||
|
print(f"Webhook 触发响应: {result.stdout[:200]}")
|
||||||
|
|
||||||
|
print("[Step 3/5] 等待 N8N 执行完成(Telegram 通知将发送到本会话)...")
|
||||||
|
print("请等待 Telegram 通知,收到后继续执行步骤 4。")
|
||||||
|
print("如需手动检查状态,请访问: https://n8n.ishenwei.online")
|
||||||
|
sys.exit(0) # <-- 此处退出,等待 Telegram 通知后再手动执行步骤 4
|
||||||
|
|
||||||
|
# ---- 以下为步骤 4 和 5,需在收到 Telegram 通知后执行 ----
|
||||||
|
|
||||||
|
output_files = [f"{OUTPUT_NAME}_output.md", f"{OUTPUT_NAME}_output.html"]
|
||||||
|
|
||||||
|
print(f"[Step 4/5] 复制输出文件回 Obsidian...")
|
||||||
|
for file in output_files:
|
||||||
|
src = f"macmini:{N8N_FILES}/{file}"
|
||||||
|
dst = f"{OUTPUT_DIR}/{file}"
|
||||||
|
result = subprocess.run(['scp', src, dst], capture_output=True, text=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print(f" V {file}")
|
||||||
|
else:
|
||||||
|
print(f" X {file}: {result.stderr}")
|
||||||
|
|
||||||
|
print(f"[Step 5/5] 清理 N8N 容器临时文件...")
|
||||||
|
files_to_clean = [NOTE_NAME] + output_files
|
||||||
|
result = subprocess.run(
|
||||||
|
['ssh', 'macmini', 'rm'] + [f"{N8N_FILES}/{f}" for f in files_to_clean],
|
||||||
|
capture_output=True, text=True
|
||||||
|
)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print(" V 清理完成")
|
||||||
|
else:
|
||||||
|
print(f" ! 清理失败(不影响结果): {result.stderr}")
|
||||||
|
|
||||||
|
print("🎉 工作流执行完毕!")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 速查表:常见工作流配置
|
||||||
|
|
||||||
|
| 工作流 | Webhook Path | 输入文件规则 | 输出文件规则 | 通知方式 |
|
||||||
|
|--------|-------------|-------------|-------------|---------|
|
||||||
|
| 内容转化 v5 | `content-translation-v5` | `content-queue/*.md` | `content-output/*_output.md` + `*_output.html` | Telegram |
|
||||||
|
| (待补充) | | | | |
|
||||||
|
|
||||||
|
> **添加新工作流时**:在此表新增一行,注明 Webhook Path 和文件路径规则,星辉即可照此执行。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 异常处理规范
|
||||||
|
|
||||||
|
| 异常情况 | 处理方式 |
|
||||||
|
|---------|---------|
|
||||||
|
| `scp` 文件复制失败 | 检查源文件是否存在、检查目标目录权限 |
|
||||||
|
| `curl` Webhook 请求超时 | 重试 1 次(间隔 5 秒),仍失败则中止并通知用户 |
|
||||||
|
| Telegram 未收到完成通知 | 登录 n8n 管理界面 → 查看对应工作流执行记录 |
|
||||||
|
| 输出文件复制失败 | 检查 n8n-files 中是否已生成文件,确认文件名是否匹配 |
|
||||||
|
| N8N 工作流报错 | 登录 n8n 管理界面 → 打开对应工作流 → 查看错误节点日志 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔑 关键约束汇总
|
||||||
|
|
||||||
|
1. **N8N 容器路径**:`/home/node/.n8n-files/`(只读/写此目录)
|
||||||
|
2. **文件传输方式**:`scp` via `macmini` 主机名
|
||||||
|
3. **Webhook 触发**:统一使用 `curl -X POST`,Content-Type 为 `application/json`
|
||||||
|
4. **通知等待**:必须等待 Telegram/callback 通知后再复制输出文件,不得跳过
|
||||||
|
5. **清理时机**:步骤 4 成功后再执行清理,步骤 4 失败时不清理(保留现场)
|
||||||
|
6. **配置文件**:`~/.openclaw/.env` 中的 `N8N_API_KEY` 和 `N8N_BASE_URL` 供脚本读取
|
||||||
@@ -1,22 +1,30 @@
|
|||||||
# N8N 内容转化流水线工作流设计(v4 → v5 升级)
|
# N8N 内容转化流水线工作流设计(v6)
|
||||||
|
|
||||||
> 用于:AI 英文文章 → 中文公众号/X/视频 内容转化
|
> 用于:AI 英文文章 → 中文公众号/X/视频 内容转化
|
||||||
> 工作流ID:`iOf32aOKvTjfTDSM`(v4基础)
|
> 工作流 ID:`iOf32aOKvTjfTDSM`(v5 基础)
|
||||||
> 触发方式:OpenClaw 通过 Webhook 调用
|
> 触发方式:OpenClaw 通过 Webhook 调用
|
||||||
> 管理平台:Mac mini 上的 n8n (`https://n8n.ishenwei.online`)
|
> 管理平台:Mac mini 上的 n8n (`https://n8n.ishenwei.online`)
|
||||||
|
>
|
||||||
|
> **v6 变更(相比 v5):**
|
||||||
|
> - ✅ 移除 Node 7(Build HTML)、Node 8(Write HTML)
|
||||||
|
> - ✅ n8n 仅输出 Markdown 文件,HTML 转换不再需要
|
||||||
|
> - ✅ 最终输出纯 Markdown,便于在 Obsidian 中编辑后再发布到公众号
|
||||||
|
> - ⚠️ Telegram 通知中的 HTML 相关字段已移除
|
||||||
|
> - ⚠️ 验收标准调整为仅检查 Markdown 文件
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📋 核心需求更新(v5)
|
## 核心需求更新(v6)
|
||||||
|
|
||||||
### 输出要求(重要!)
|
### 输出要求
|
||||||
|
|
||||||
**必须同时输出两个版本:**
|
**单一输出:中文 Markdown 文件**
|
||||||
|
|
||||||
| 输出文件 | 路径 | 格式 | 用途 |
|
| 输出文件 | 路径 | 格式 | 用途 |
|
||||||
|---------|------|------|------|
|
|---------|------|------|------|
|
||||||
| **Markdown 源文件** | `content-output/{原文件名}.md` | 中文 Markdown | Obsidian 留存、溯源 |
|
| **Markdown 源文件** | `content-output/{原文件名}.md` | 中文 Markdown | Obsidian 留存、编辑、发布 |
|
||||||
| **公众号 HTML** | `content-output/{原文件名}.html` | 带样式的 HTML | 直接复制到公众号编辑器 |
|
|
||||||
|
> 不再生成公众号 HTML。公众号排版在 Obsidian 中手动完成,或通过其他工具转换。
|
||||||
|
|
||||||
### Obsidian 目录结构
|
### Obsidian 目录结构
|
||||||
|
|
||||||
@@ -25,14 +33,13 @@
|
|||||||
├── content-queue/ # 原始英文文章(输入)
|
├── content-queue/ # 原始英文文章(输入)
|
||||||
│ └── 2026-03-29-ai-solopreneur.md
|
│ └── 2026-03-29-ai-solopreneur.md
|
||||||
│
|
│
|
||||||
└── content-output/ # 成品(输出)
|
└── content-output/ # 成品(输出,v6 仅 Markdown)
|
||||||
├── 2026-03-29-ai-solopreneur.md # 翻译后 Markdown
|
└── 2026-03-29-ai-solopreneur.md # 翻译后 Markdown ✅
|
||||||
└── 2026-03-29-ai-solopreneur.html # 公众号 HTML(新增)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📋 工作流概述
|
## 工作流概述
|
||||||
|
|
||||||
```
|
```
|
||||||
OpenClaw (发现文章)
|
OpenClaw (发现文章)
|
||||||
@@ -40,25 +47,25 @@ OpenClaw (发现文章)
|
|||||||
↓ (触发 Webhook)
|
↓ (触发 Webhook)
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
│ N8N 工作流 (v5): content-translation-pipeline-v5 │
|
│ N8N 工作流 (v6): content-translation-pipeline-v6 │
|
||||||
│ │
|
│ │
|
||||||
│ [Webhook] → [Read File] → [Extract Text] → [AI Agent] │
|
│ [Webhook] → [Read File] → [Extract Text] → [AI Agent] │
|
||||||
│ ↓ ↑ (DeepSeek) │
|
│ ↓ ↑ (DeepSeek) │
|
||||||
│ [Build Markdown] → [Write .md] → [Build HTML] → [Write .html] │
|
│ [Build Markdown] → [Write .md] │
|
||||||
│ ↓ │
|
│ ↓ │
|
||||||
│ [Send Telegram] │
|
│ [Send Telegram] │
|
||||||
└─────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔌 节点详细设计(v5)
|
## 节点详细设计(v6)
|
||||||
|
|
||||||
### 节点 1️⃣:Webhook Trigger
|
### 节点 1️⃣:Webhook Trigger
|
||||||
|
|
||||||
**类型:** Webhook
|
**类型:** Webhook
|
||||||
**名称:** `Webhook Trigger`
|
**名称:** `Webhook Trigger`
|
||||||
**Path:** `/content-translation-v5`(新建 path)
|
**Path:** `/content-translation-v6`(新建 path)
|
||||||
**Method:** POST
|
**Method:** POST
|
||||||
|
|
||||||
**接收数据格式:**
|
**接收数据格式:**
|
||||||
@@ -66,6 +73,7 @@ OpenClaw (发现文章)
|
|||||||
{
|
{
|
||||||
"note_name": "2026-03-29-ai-solopreneur.md",
|
"note_name": "2026-03-29-ai-solopreneur.md",
|
||||||
"source_path": "/Users/weishen/Workspace/nexus/openclaw/content-queue/2026-03-29-ai-solopreneur.md",
|
"source_path": "/Users/weishen/Workspace/nexus/openclaw/content-queue/2026-03-29-ai-solopreneur.md",
|
||||||
|
"output_name": "2026-03-29-ai-solopreneur",
|
||||||
"callback_url": "http://192.168.3.189:18789/webhook/yunce"
|
"callback_url": "http://192.168.3.189:18789/webhook/yunce"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -88,15 +96,6 @@ OpenClaw (发现文章)
|
|||||||
**名称:** `Extract from File`
|
**名称:** `Extract from File`
|
||||||
**Operation:** `text`
|
**Operation:** `text`
|
||||||
|
|
||||||
**输出:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"original_content": "...",
|
|
||||||
"note_name": "2026-03-29-ai-solopreneur.md",
|
|
||||||
"source_path": "/Users/weishen/Workspace/nexus/openclaw/content-queue/..."
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 节点 4️⃣:AI Agent(翻译+改写)
|
### 节点 4️⃣:AI Agent(翻译+改写)
|
||||||
@@ -124,6 +123,11 @@ OpenClaw (发现文章)
|
|||||||
- 调性:公众号大V风格,有观点有案例
|
- 调性:公众号大V风格,有观点有案例
|
||||||
- 商业化:可自然植入 AI Agent / 知识管理相关内容(软性,不硬广)
|
- 商业化:可自然植入 AI Agent / 知识管理相关内容(软性,不硬广)
|
||||||
|
|
||||||
|
## 文章主题方向(供校准时参考)
|
||||||
|
- AI Agent 落地实践与工具推荐
|
||||||
|
- AI 赋能商业的最佳实践
|
||||||
|
- AI 时代的网络安全与运维
|
||||||
|
|
||||||
## 输出格式(严格按此 JSON 返回)
|
## 输出格式(严格按此 JSON 返回)
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -142,24 +146,24 @@ OpenClaw (发现文章)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 节点 5️⃣:Build Markdown(新增)
|
### 节点 5️⃣:Build Markdown(v6 精简版)
|
||||||
|
|
||||||
**类型:** Code
|
**类型:** Code
|
||||||
**名称:** `Build Markdown`
|
**名称:** `Build Markdown`
|
||||||
|
|
||||||
**功能:** 将 AI 输出组装成 Markdown 文件
|
**功能:** 将 AI 输出的 JSON 组装成结构清晰的 Markdown 文件
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const aiResult = $input.first().json.message;
|
const aiResult = $input.first().json.message;
|
||||||
const data = typeof aiResult === 'string' ? JSON.parse(aiResult) : aiResult;
|
const data = typeof aiResult === 'string' ? JSON.parse(aiResult) : aiResult;
|
||||||
|
|
||||||
const noteName = $('Webhook Trigger').first().json.body.note_name;
|
const noteName = $('Webhook Trigger').first().json.body.note_name;
|
||||||
// 去掉 .md 后缀,输出到 content-output
|
const outputName = noteName.replace('.md', '');
|
||||||
const outputName = noteName.replace('.md', '.md');
|
|
||||||
const outputPath = '/Users/weishen/Workspace/nexus/openclaw/content-output/' + outputName;
|
|
||||||
|
|
||||||
const markdown = `# ${data.wechat_title}
|
const markdown = `# ${data.wechat_title}
|
||||||
|
|
||||||
|
> ${data.wechat_excerpt}
|
||||||
|
|
||||||
${data.wechat_content}
|
${data.wechat_content}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -185,7 +189,7 @@ ${data.video_script}
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
json: {
|
json: {
|
||||||
output_path: outputPath,
|
output_name: outputName,
|
||||||
output_content: markdown,
|
output_content: markdown,
|
||||||
source_path: $('Webhook Trigger').first().json.body.source_path
|
source_path: $('Webhook Trigger').first().json.body.source_path
|
||||||
}
|
}
|
||||||
@@ -194,163 +198,21 @@ return {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 节点 6️⃣:Write .md File(新增)
|
### 节点 6️⃣:Write .md File
|
||||||
|
|
||||||
**类型:** Write Binary File / ReadWriteFile
|
**类型:** Write Binary File / ReadWriteFile
|
||||||
**名称:** `Write Markdown Note`
|
**名称:** `Write Markdown Note`
|
||||||
|
|
||||||
**配置:**
|
**配置:**
|
||||||
- Operation: `write`
|
- Operation: `write`
|
||||||
- File Path: `=/home/node/.n8n-files/{{ $json.body.output_name }}_output.md`
|
- File Path: `=/home/node/.n8n-files/{{ $json.output_name }}_output.md`
|
||||||
- Content: `={{ $json.output_content }}`
|
- Content: `={{ $json.output_content }}`
|
||||||
|
|
||||||
**注意:** 输出到 n8n-files/ 目录,由 OpenClaw 负责复制回 Obsidian。
|
**注意:** 输出到 n8n-files/ 目录,由 OpenClaw 负责复制回 Obsidian。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 节点 7️⃣:Build HTML(新增,核心)
|
### 节点 7️⃣:Send Telegram Message
|
||||||
|
|
||||||
**类型:** Code
|
|
||||||
**名称:** `Build WeChat HTML`
|
|
||||||
|
|
||||||
**功能:** 将 Markdown 转为带样式的公众号 HTML
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const aiResult = $input.first().json.message;
|
|
||||||
const data = typeof aiResult === 'string' ? JSON.parse(aiResult) : aiResult;
|
|
||||||
|
|
||||||
const outputName = $('Webhook Trigger').first().json.body.output_name;
|
|
||||||
const htmlPath = '/home/node/.n8n-files/' + outputName + '_output.html';
|
|
||||||
|
|
||||||
// 公众号 HTML 模板
|
|
||||||
const html = `<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.8;
|
|
||||||
color: #333;
|
|
||||||
max-width: 100%;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 24px;
|
|
||||||
text-align: center;
|
|
||||||
color: #1a1a1a;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
font-size: 20px;
|
|
||||||
color: #1a1a1a;
|
|
||||||
margin-top: 30px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
font-weight: 600;
|
|
||||||
border-left: 4px solid #007aff;
|
|
||||||
padding-left: 12px;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
text-align: justify;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
text-indent: 2em;
|
|
||||||
}
|
|
||||||
.twitter-copy {
|
|
||||||
background: #f5f5f5;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin: 20px 0;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
.video-info {
|
|
||||||
background: #f0f7ff;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
.video-title {
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #007aff;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.script {
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.6;
|
|
||||||
color: #555;
|
|
||||||
}
|
|
||||||
.cover-keywords {
|
|
||||||
color: #999;
|
|
||||||
font-size: 12px;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 30px;
|
|
||||||
padding-top: 20px;
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h1>${data.wechat_title}</h1>
|
|
||||||
|
|
||||||
${data.wechat_content.split('\n').map(line => {
|
|
||||||
if (line.startsWith('# ')) return `<h1 style="text-align:center;font-size:24px;margin:30px 0;">${line.slice(2)}</h1>`;
|
|
||||||
if (line.startsWith('## ')) return `<h2>${line.slice(3)}</h2>`;
|
|
||||||
if (line.startsWith('### ')) return `<h3 style="font-size:17px;color:#333;margin:20px 0 10px;">${line.slice(4)}</h3>`;
|
|
||||||
if (line.trim() === '---') return '<hr style="border:none;border-top:1px solid #eee;margin:30px 0;">';
|
|
||||||
if (line.startsWith('- ') || line.startsWith('* ')) return `<li style="margin:8px 0;">${line.slice(2)}</li>`;
|
|
||||||
if (line.trim() === '') return '';
|
|
||||||
return `<p>${line}</p>`;
|
|
||||||
}).join('\n')}
|
|
||||||
|
|
||||||
<div class="twitter-copy">
|
|
||||||
<strong>📱 X/Twitter 文案:</strong><br>
|
|
||||||
${data.twitter_copy.replace(/\n/g, '<br>')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="video-info">
|
|
||||||
<div class="video-title">🎬 视频标题:${data.video_title}</div>
|
|
||||||
<div class="script">
|
|
||||||
<strong>口播脚本:</strong><br>
|
|
||||||
${data.video_script.replace(/\n/g, '<br>')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="cover-keywords">
|
|
||||||
封面图关键词:${data.cover_keywords?.join(' | ')}<br>
|
|
||||||
原文路径:${$('Webhook Trigger').first().json.body.source_path}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>`;
|
|
||||||
|
|
||||||
return {
|
|
||||||
json: {
|
|
||||||
html_path: htmlPath,
|
|
||||||
html_content: html
|
|
||||||
}
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 节点 8️⃣:Write .html File(新增)
|
|
||||||
|
|
||||||
**类型:** Write Binary File / ReadWriteFile
|
|
||||||
**名称:** `Write WeChat HTML`
|
|
||||||
|
|
||||||
**配置:**
|
|
||||||
- Operation: `write`
|
|
||||||
- File Path: `=/home/node/.n8n-files/{{ $json.body.output_name }}_output.html`
|
|
||||||
- Content: `={{ $json.html_content }}`
|
|
||||||
|
|
||||||
**注意:** 输出到 n8n-files/ 目录,由 OpenClaw 负责复制回 Obsidian。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 节点 9️⃣:Send Telegram Message
|
|
||||||
|
|
||||||
**类型:** Telegram
|
**类型:** Telegram
|
||||||
**名称:** `Send Telegram Message`
|
**名称:** `Send Telegram Message`
|
||||||
@@ -361,23 +223,23 @@ return {
|
|||||||
```
|
```
|
||||||
✅ 文章转换完成!
|
✅ 文章转换完成!
|
||||||
|
|
||||||
📝 标题:{{ $json.wechat_title }}
|
📝 标题:${$json.wechat_title}
|
||||||
📁 Markdown:/home/node/.n8n-files/{{ $json.body.output_name }}_output.md
|
📁 Markdown:/home/node/.n8n-files/${$json.output_name}_output.md
|
||||||
🌐 HTML:/home/node/.n8n-files/{{ $json.body.output_name }}_output.html
|
🐦 Twitter 文案:${$json.twitter_copy}
|
||||||
🐦 Twitter 文案:{{ $json.twitter_copy }}
|
🎬 视频标题:${$json.video_title}
|
||||||
```
|
```
|
||||||
- Credentials: `Telegram XingJiang Bot`
|
- Credentials: `Telegram XingJiang Bot`
|
||||||
|
|
||||||
**注意:** Telegram 只通知完成,OpenClaw 收到通知后负责将文件复制回 Obsidian。
|
**注意:** OpenClaw 收到通知后负责将 Markdown 文件复制回 Obsidian。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔗 完整节点连接图(v5)
|
## 节点连接图(v6)
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────┐
|
┌─────────────────────────────────┐
|
||||||
│ Webhook Trigger │
|
│ Webhook Trigger │
|
||||||
│ POST /content-translation-v5 │
|
│ POST /content-translation-v6 │
|
||||||
└──────────────┬──────────────────┘
|
└──────────────┬──────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
@@ -402,61 +264,47 @@ return {
|
|||||||
▼ ▼
|
▼ ▼
|
||||||
┌─────────────────────────────────┐
|
┌─────────────────────────────────┐
|
||||||
│ AI Agent (LangChain) │
|
│ AI Agent (LangChain) │
|
||||||
│ - system prompt │
|
│ 输出 JSON 格式结果 │
|
||||||
│ - original content │
|
|
||||||
└──────────────┬──────────────────┘
|
└──────────────┬──────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────┐
|
┌─────────────────────────────────┐
|
||||||
│ Build Markdown (NEW) │
|
│ Build Markdown │
|
||||||
│ 组装中文 Markdown 文件 │
|
│ 组装中文 Markdown 文件 │
|
||||||
└──────────────┬──────────────────┘
|
└──────────────┬──────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────┐
|
┌─────────────────────────────────┐
|
||||||
│ Write Markdown Note (NEW) │
|
│ Write Markdown Note │
|
||||||
│ → content-output/*.md │
|
│ → content-output/*.md │
|
||||||
└──────────────┬──────────────────┘
|
└──────────────┬──────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────┐
|
┌─────────────────────────────────┐
|
||||||
│ Build WeChat HTML (NEW) │
|
|
||||||
│ Markdown → 带样式 HTML │
|
|
||||||
└──────────────┬──────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────┐
|
|
||||||
│ Write WeChat HTML (NEW) │
|
|
||||||
│ → content-output/*.html │
|
|
||||||
└──────────────┬──────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────┐
|
|
||||||
│ Send Telegram Message │
|
│ Send Telegram Message │
|
||||||
│ 文章转换完成通知 │
|
│ Markdown 文件路径通知 │
|
||||||
└─────────────────────────────────┘
|
└─────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔄 调用方式(OpenClaw 侧)
|
## 调用方式(OpenClaw 侧)
|
||||||
|
|
||||||
**重要说明:n8n 只能读写 `/home/node/.n8n-files/` 目录,无法直接访问 Obsidian 目录。因此 OpenClaw 负责文件搬运,n8n 专注处理。**
|
**核心约束:n8n 只能读写 `/home/node/.n8n-files/` 目录,OpenClaw 负责文件搬运。**
|
||||||
|
|
||||||
### OpenClaw 完整流程:
|
### OpenClaw 完整流程(v6):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# =============================================
|
# =============================================
|
||||||
# 步骤 1:OpenClaw 复制原文到 n8n-files 目录
|
# 步骤 1:OpenClaw 复制原文到 n8n-files 目录
|
||||||
# =============================================
|
# =============================================
|
||||||
# SSH 到 MacMini,将源文件复制到 n8n 容器可访问的目录
|
|
||||||
scp /Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md \
|
scp /Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md \
|
||||||
macmini:/home/node/.n8n-files/article-2026-03-29.md
|
macmini:/home/node/.n8n-files/article-2026-03-29.md
|
||||||
|
|
||||||
# =============================================
|
# =============================================
|
||||||
# 步骤 2:OpenClaw 触发 n8n Webhook
|
# 步骤 2:OpenClaw 触发 n8n Webhook
|
||||||
# =============================================
|
# =============================================
|
||||||
curl -X POST "https://n8n.ishenwei.online/webhook/content-translation-v5" \
|
curl -X POST "https://n8n.ishenwei.online/webhook/content-translation-v6" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"note_name": "article-2026-03-29.md",
|
"note_name": "article-2026-03-29.md",
|
||||||
@@ -471,95 +319,130 @@ curl -X POST "https://n8n.ishenwei.online/webhook/content-translation-v5" \
|
|||||||
# n8n 读取 /home/node/.n8n-files/article-2026-03-29.md
|
# n8n 读取 /home/node/.n8n-files/article-2026-03-29.md
|
||||||
# 处理(翻译、改写)
|
# 处理(翻译、改写)
|
||||||
# 输出到 /home/node/.n8n-files/article-2026-03-29_output.md
|
# 输出到 /home/node/.n8n-files/article-2026-03-29_output.md
|
||||||
# 输出到 /home/node/.n8n-files/article-2026-03-29_output.html
|
|
||||||
# 发送 Telegram 通知
|
# 发送 Telegram 通知
|
||||||
|
|
||||||
# =============================================
|
# =============================================
|
||||||
# 步骤 4:OpenClaw 复制输出文件回 Obsidian(工作流完成后)
|
# 步骤 4:OpenClaw 复制输出文件回 Obsidian(工作流完成后)
|
||||||
# =============================================
|
# =============================================
|
||||||
# 复制 Markdown 成品
|
|
||||||
scp macmini:/home/node/.n8n-files/article-2026-03-29_output.md \
|
scp macmini:/home/node/.n8n-files/article-2026-03-29_output.md \
|
||||||
/Users/weishen/Workspace/nexus/openclaw/content-output/article-2026-03-29.md
|
/Users/weishen/Workspace/nexus/openclaw/content-output/article-2026-03-29.md
|
||||||
|
|
||||||
# 复制 HTML 成品
|
|
||||||
scp macmini:/home/node/.n8n-files/article-2026-03-29_output.html \
|
|
||||||
/Users/weishen/Workspace/nexus/openclaw/content-output/article-2026-03-29.html
|
|
||||||
|
|
||||||
# =============================================
|
# =============================================
|
||||||
# 步骤 5:清理 n8n-files 临时文件(可选)
|
# 步骤 5:清理 n8n-files 临时文件(可选)
|
||||||
# =============================================
|
# =============================================
|
||||||
ssh macmini "rm /home/node/.n8n-files/article-2026-03-29.md \
|
ssh macmini "rm /home/node/.n8n-files/article-2026-03-29.md \
|
||||||
/home/node/.n8n-files/article-2026-03-29_output.md \
|
/home/node/.n8n-files/article-2026-03-29_output.md"
|
||||||
/home/node/.n8n-files/article-2026-03-29_output.html"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 简化版 OpenClaw 代码流程:
|
### OpenClaw Python 脚本模板(v6):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
note_name = "article-2026-03-29.md"
|
# ========== 配置区 ==========
|
||||||
source_path = "/Users/weishen/Workspace/nexus/openclaw/content-queue/" + note_name
|
N8N_BASE_URL = "https://n8n.ishenwei.online"
|
||||||
output_name = note_name.replace('.md', '')
|
WEBHOOK_PATH = "content-translation-v6" # <-- 实际 webhook path
|
||||||
n8n_files = "/home/node/.n8n-files"
|
SOURCE_FILE = "/path/to/source/file.md" # <-- 实际源文件路径
|
||||||
|
N8N_FILES = "/home/node/.n8n-files"
|
||||||
|
NOTE_NAME = "source-file.md" # <-- 实际文件名
|
||||||
|
OUTPUT_NAME = "source-file" # <-- 输出文件名(无扩展名)
|
||||||
|
OUTPUT_DIR = "/Users/weishen/Workspace/nexus/openclaw/content-output"
|
||||||
|
# ===================================
|
||||||
|
|
||||||
# 1. 复制原文到 n8n-files
|
n8n_input_path = f"{N8N_FILES}/{NOTE_NAME}"
|
||||||
subprocess.run(['scp', source_path, f'macmini:{n8n_files}/{note_name}'])
|
|
||||||
|
|
||||||
# 2. 触发 Webhook
|
print(f"[Step 1/5] 复制输入文件到 N8N 容器: {NOTE_NAME}")
|
||||||
subprocess.run(['curl', '-X', 'POST',
|
result = subprocess.run(
|
||||||
'https://n8n.ishenwei.online/webhook/content-translation-v5',
|
['scp', SOURCE_FILE, f'macmini:{n8n_input_path}'],
|
||||||
'-H', 'Content-Type: application/json',
|
capture_output=True, text=True
|
||||||
'-d', f'{{"note_name": "{note_name}", "output_name": "{output_name}", ...}}'
|
)
|
||||||
])
|
if result.returncode != 0:
|
||||||
|
print(f"X 文件复制失败: {result.stderr}")
|
||||||
|
sys.exit(1)
|
||||||
|
print(f"V 已复制到 {n8n_input_path}")
|
||||||
|
|
||||||
# 3. 等待 Telegram 通知(工作流完成)
|
print(f"[Step 2/5] 触发 N8N Webhook: {WEBHOOK_PATH}")
|
||||||
|
webhook_url = f"{N8N_BASE_URL}/webhook/{WEBHOOK_PATH}"
|
||||||
|
payload = ("{"
|
||||||
|
"\"note_name\": \"" + NOTE_NAME + "\", "
|
||||||
|
"\"source_path\": \"" + SOURCE_FILE + "\", "
|
||||||
|
"\"output_name\": \"" + OUTPUT_NAME + "\""
|
||||||
|
"}")
|
||||||
|
result = subprocess.run(
|
||||||
|
['curl', '-X', 'POST', webhook_url,
|
||||||
|
'-H', 'Content-Type: application/json',
|
||||||
|
'-d', payload],
|
||||||
|
capture_output=True, text=True
|
||||||
|
)
|
||||||
|
print(f"Webhook 触发响应: {result.stdout[:200]}")
|
||||||
|
|
||||||
# 4. 复制输出回 Obsidian
|
print("[Step 3/5] 等待 N8N 执行完成(Telegram 通知将发送到本会话)...")
|
||||||
subprocess.run(['scp',
|
print("请等待 Telegram 通知,收到后继续执行步骤 4。")
|
||||||
f'macmini:{n8n_files}/{output_name}_output.md',
|
sys.exit(0) # <-- 退出等待通知
|
||||||
f'/Users/weishen/Workspace/nexus/openclaw/content-output/{output_name}.md'])
|
|
||||||
subprocess.run(['scp',
|
# ---- 以下为步骤 4 和 5,需在收到 Telegram 通知后执行 ----
|
||||||
f'macmini:{n8n_files}/{output_name}_output.html',
|
|
||||||
f'/Users/weishen/Workspace/nexus/openclaw/content-output/{output_name}.html'])
|
print(f"[Step 4/5] 复制输出文件回 Obsidian...")
|
||||||
|
output_file = f"{OUTPUT_NAME}_output.md"
|
||||||
|
src = f"macmini:{N8N_FILES}/{output_file}"
|
||||||
|
dst = f"{OUTPUT_DIR}/{output_file}"
|
||||||
|
result = subprocess.run(['scp', src, dst], capture_output=True, text=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print(f" V {output_file}")
|
||||||
|
else:
|
||||||
|
print(f" X {result.stderr}")
|
||||||
|
|
||||||
|
print("[Step 5/5] 清理 N8N 容器临时文件...")
|
||||||
|
files_to_clean = [NOTE_NAME, output_file]
|
||||||
|
result = subprocess.run(
|
||||||
|
['ssh', 'macmini', 'rm'] + [f"{N8N_FILES}/{f}" for f in files_to_clean],
|
||||||
|
capture_output=True, text=True
|
||||||
|
)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print(" V 清理完成")
|
||||||
|
else:
|
||||||
|
print(f" ! 清理失败(不影响结果): {result.stderr}")
|
||||||
|
|
||||||
|
print("🎉 工作流执行完毕!")
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📁 最终 Obsidian 目录结构
|
## Obsidian 最终目录结构(v6)
|
||||||
|
|
||||||
```
|
```
|
||||||
~/Workspace/nexus/openclaw/
|
~/Workspace/nexus/openclaw/
|
||||||
├── content-queue/ # 原始英文(输入,OpenClaw 放置)
|
├── content-queue/ # 原始英文(输入,OpenClaw 放置)
|
||||||
│ └── article-2026-03-29.md
|
│ └── article-2026-03-29.md
|
||||||
│
|
│
|
||||||
└── content-output/ # 成品(OpenClaw 从 n8n-files/ 复制回来)
|
└── content-output/ # 成品(v6 仅 Markdown)
|
||||||
├── article-2026-03-29.md # 中文 Markdown ✅
|
└── article-2026-03-29.md # 中文 Markdown ✅
|
||||||
└── article-2026-03-29.html # 公众号 HTML ✅
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**文件来源说明:**
|
|
||||||
- n8n 工作流只读写 `/home/node/.n8n-files/` 目录
|
|
||||||
- OpenClaw 在工作流完成后负责将输出文件复制到 Obsidian 目录
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✅ 验收标准
|
## 验收标准(v6)
|
||||||
|
|
||||||
1. 触发后自动完成整个流程,无需人工干预
|
1. 触发后自动完成整个流程,无需人工干预
|
||||||
2. `content-output/` 目录同时生成 `.md` 和 `.html` 两个文件
|
2. `content-output/` 目录生成 `.md` 文件(v6 无 HTML)
|
||||||
3. HTML 文件可直接复制粘贴到微信公众号编辑器,格式基本正确
|
3. Markdown 文件内容完整,包含:公众号正文 + Twitter 文案 + 视频脚本
|
||||||
4. Telegram 收到完成通知(含标题和文件路径)
|
4. Telegram 收到完成通知(含标题和文件路径)
|
||||||
5. 错误时 n8n 记录错误节点并停止流程
|
5. 错误时 n8n 记录错误节点并停止流程
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📝 备注
|
## 备注(v6)
|
||||||
|
|
||||||
- **Markdown 源文件**:保留中文原文,方便后续修改和溯源
|
- **Markdown 源文件**:保留中文原文,便于在 Obsidian 中编辑、排版后再发布
|
||||||
- **HTML 文件**:带内联样式,兼容微信公众号编辑器,复制后格式不走形
|
- **公众号排版**:在 Obsidian 中手动完成,或通过 Markdown→公众号工具转换
|
||||||
- **文件路径**:写入 Obsidian vault 的 `content-output/` 子目录,需确保 n8n 容器有对应目录的写权限
|
- **文件路径**:写入 Obsidian vault 的 `content-output/` 子目录,需确保 n8n 容器有对应目录的写权限
|
||||||
- **API Key**:DeepSeek API 通过 n8n credential 配置,无需在代码中硬编码
|
- **API Key**:DeepSeek API 通过 n8n credential 配置,无需在代码中硬编码
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# 📖 附录:OpenClaw ↔ N8N 通用工作流调用规范(v1.0)
|
# 📖 附录:OpenClaw ↔ N8N 通用工作流调用规范(v1.0)
|
||||||
|
|
||||||
> 本规范旨在为 OpenClaw 与 N8N 之间的每次交互建立统一标准,使星辉(XingHui)或其他 Agent 能够通过标准化步骤执行任意 N8N 工作流。
|
> 本规范旨在为 OpenClaw 与 N8N 之间的每次交互建立统一标准,使星辉(XingHui)或其他 Agent 能够通过标准化步骤执行任意 N8N 工作流。
|
||||||
@@ -570,7 +453,7 @@ subprocess.run(['scp',
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🏗️ 架构总览
|
## 架构总览
|
||||||
|
|
||||||
```
|
```
|
||||||
OpenClaw N8N 容器 其他存储
|
OpenClaw N8N 容器 其他存储
|
||||||
@@ -591,26 +474,16 @@ OpenClaw N8N 容器 其他存储
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📋 标准化执行步骤(星辉操作指南)
|
## 标准化执行步骤(星辉操作指南)
|
||||||
|
|
||||||
### 步骤 ①:准备输入文件
|
### 步骤 ①:准备输入文件
|
||||||
|
|
||||||
**规则**:所有传递给 N8N 的文件,必须先复制到 N8N 容器可访问的路径。
|
**规则**:所有传递给 N8N 的文件,必须先复制到 N8N 容器可访问的路径。
|
||||||
|
|
||||||
**源路径**(由具体任务决定)× → **目标路径**:`macmini:/home/node/.n8n-files/{文件名}`
|
**通用格式**:`scp <源路径> macmini:/home/node/.n8n-files/<文件名>`
|
||||||
|
|
||||||
**示例(内容转化流水线 v5)**:
|
|
||||||
```bash
|
|
||||||
scp /Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md \
|
|
||||||
macmini:/home/node/.n8n-files/article-2026-03-29.md
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 步骤 ②:触发 Webhook
|
### 步骤 ②:触发 Webhook
|
||||||
|
|
||||||
**规则**:通过 `curl` 向 N8N Webhook 端点发送 POST 请求,JSON 数据包含工作流所需的所有元数据。
|
|
||||||
|
|
||||||
**通用格式**:
|
**通用格式**:
|
||||||
```bash
|
```bash
|
||||||
curl -X POST "<N8N_BASE_URL>/webhook/<webhook-path>" \
|
curl -X POST "<N8N_BASE_URL>/webhook/<webhook-path>" \
|
||||||
@@ -618,194 +491,42 @@ curl -X POST "<N8N_BASE_URL>/webhook/<webhook-path>" \
|
|||||||
-d '{
|
-d '{
|
||||||
"note_name": "<文件名>",
|
"note_name": "<文件名>",
|
||||||
"source_path": "<原始文件路径>",
|
"source_path": "<原始文件路径>",
|
||||||
"output_name": "<输出文件名(不含扩展名)>",
|
"output_name": "<输出文件名(不含扩展名)>"
|
||||||
"callback_url": "<完成后通知地址(可选)>"
|
|
||||||
}'
|
|
||||||
```
|
|
||||||
|
|
||||||
**具体示例(内容转化流水线 v5)**:
|
|
||||||
```bash
|
|
||||||
curl -X POST "https://n8n.ishenwei.online/webhook/content-translation-v5" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"note_name": "article-2026-03-29.md",
|
|
||||||
"source_path": "/Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md",
|
|
||||||
"output_name": "article-2026-03-29",
|
|
||||||
"callback_url": "http://192.168.3.189:18789/webhook/yunce"
|
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
**Webhook Path 查询方式**:
|
**Webhook Path 查询方式**:
|
||||||
如不知道目标工作流的 Webhook path,可通过以下方式确认:
|
|
||||||
1. 在 n8n 管理界面(https://n8n.ishenwei.online)打开对应工作流
|
1. 在 n8n 管理界面(https://n8n.ishenwei.online)打开对应工作流
|
||||||
2. 点击 Webhook 节点,查看右侧 Path 字段
|
2. 点击 Webhook 节点,查看右侧 Path 字段
|
||||||
3. 或参考本文档相关章节的「Webhook Trigger」配置
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 步骤 ③:等待执行完成
|
### 步骤 ③:等待执行完成
|
||||||
|
|
||||||
**规则**:N8N 工作流完成后会发送通知,OpenClaw 需等待此信号后再执行后续复制操作。
|
**规则**:N8N 工作流完成后会发送通知,OpenClaw 需等待此信号后再执行后续复制操作。
|
||||||
|
|
||||||
**通知方式**(由具体工作流决定,优先级如下):
|
**通知方式优先级**:Telegram Bot > Callback URL > 轮询 n8n API
|
||||||
|
|
||||||
| 方式 | 说明 | 适用场景 |
|
|
||||||
|------|------|---------|
|
|
||||||
| **Telegram Bot** | N8N 通过 Telegram 节点发送消息到指定 Chat ID | 推荐,已知用户 Chat ID |
|
|
||||||
| **Callback URL** | N8N POST 到指定 URL(OpenClaw Webhook) | 需要 OpenClaw 监听端口 |
|
|
||||||
| **轮询 n8n API** | 定期查询工作流执行状态 | 无通知配置时兜底 |
|
|
||||||
|
|
||||||
**Telegram 通知格式(示例)**:
|
|
||||||
```
|
|
||||||
✅ [工作流名称] 执行完成!
|
|
||||||
|
|
||||||
📝 标题:<title>
|
|
||||||
📁 输出文件:/home/node/.n8n-files/<output_name>_output.md
|
|
||||||
🌐 HTML:/home/node/.n8n-files/<output_name>_output.html
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 步骤 ④:复制输出文件
|
### 步骤 ④:复制输出文件
|
||||||
|
|
||||||
**规则**:收到完成通知后,从 N8N 容器的 `n8n-files/` 目录复制输出文件到目标存储位置。
|
**通用格式**:`scp macmini:/home/node/.n8n-files/<输出文件名> <目标完整路径>`
|
||||||
|
|
||||||
**通用格式**:
|
|
||||||
```bash
|
|
||||||
# 单文件
|
|
||||||
scp macmini:/home/node/.n8n-files/<输出文件名> <目标完整路径>
|
|
||||||
|
|
||||||
# 多文件(循环)
|
|
||||||
for file in <输出文件1> <输出文件2>; do
|
|
||||||
scp macmini:/home/node/.n8n-files/$file <目标目录>/$file
|
|
||||||
done
|
|
||||||
```
|
|
||||||
|
|
||||||
**具体示例(内容转化流水线 v5)**:
|
|
||||||
```bash
|
|
||||||
# 复制 Markdown 成品
|
|
||||||
scp macmini:/home/node/.n8n-files/article-2026-03-29_output.md \
|
|
||||||
/Users/weishen/Workspace/nexus/openclaw/content-output/article-2026-03-29.md
|
|
||||||
|
|
||||||
# 复制 HTML 成品
|
|
||||||
scp macmini:/home/node/.n8n-files/article-2026-03-29_output.html \
|
|
||||||
/Users/weishen/Workspace/nexus/openclaw/content-output/article-2026-03-29.html
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 步骤 ⑤:清理临时文件
|
### 步骤 ⑤:清理临时文件
|
||||||
|
|
||||||
**规则**:工作流完成后,删除 `n8n-files/` 下的临时文件,保持容器目录整洁。
|
**通用格式**:`ssh macmini "rm /home/node/.n8n-files/<输入文件> /home/node/.n8n-files/<输出文件>"`
|
||||||
|
|
||||||
**通用格式**:
|
|
||||||
```bash
|
|
||||||
ssh macmini "rm /home/node/.n8n-files/<输入文件> /home/node/.n8n-files/<输出文件1> /home/node/.n8n-files/<输出文件2>"
|
|
||||||
```
|
|
||||||
|
|
||||||
**具体示例(内容转化流水线 v5)**:
|
|
||||||
```bash
|
|
||||||
ssh macmini "rm /home/node/.n8n-files/article-2026-03-29.md \
|
|
||||||
/home/node/.n8n-files/article-2026-03-29_output.md \
|
|
||||||
/home/node/.n8n-files/article-2026-03-29_output.html"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔧 OpenClaw 自动化脚本模板(Python)
|
## 速查表:常见工作流配置
|
||||||
|
|
||||||
以下为通用 Python 模板,适用于任何 OpenClaw → N8N 的文件处理工作流。星辉可直接复制修改使用。
|
|
||||||
|
|
||||||
```python
|
|
||||||
import subprocess
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# ========== 配置区(每个工作流需修改) ==========
|
|
||||||
N8N_BASE_URL = "https://n8n.ishenwei.online"
|
|
||||||
WEBHOOK_PATH = "content-translation-v5" # <-- 修改为实际 webhook path
|
|
||||||
SOURCE_FILE = "/path/to/source/file.md" # <-- 修改为实际源文件路径
|
|
||||||
N8N_FILES = "/home/node/.n8n-files"
|
|
||||||
NOTE_NAME = "source-file.md" # <-- 修改为实际文件名
|
|
||||||
OUTPUT_NAME = "source-file" # <-- 修改为输出文件名(无扩展名)
|
|
||||||
OUTPUT_DIR = "/Users/weishen/Workspace/nexus/openclaw/content-output"
|
|
||||||
# ============================================
|
|
||||||
|
|
||||||
source_path = SOURCE_FILE
|
|
||||||
n8n_input_path = f"{N8N_FILES}/{NOTE_NAME}"
|
|
||||||
|
|
||||||
print(f"[Step 1/5] 复制输入文件到 N8N 容器: {NOTE_NAME}")
|
|
||||||
result = subprocess.run(
|
|
||||||
['scp', source_path, f'macmini:{n8n_input_path}'],
|
|
||||||
capture_output=True, text=True
|
|
||||||
)
|
|
||||||
if result.returncode != 0:
|
|
||||||
print(f"X 文件复制失败: {result.stderr}")
|
|
||||||
sys.exit(1)
|
|
||||||
print(f"V 已复制到 {n8n_input_path}")
|
|
||||||
|
|
||||||
print(f"[Step 2/5] 触发 N8N Webhook: {WEBHOOK_PATH}")
|
|
||||||
webhook_url = f"{N8N_BASE_URL}/webhook/{WEBHOOK_PATH}"
|
|
||||||
payload = ("{"
|
|
||||||
"\"note_name\": \"" + NOTE_NAME + "\", "
|
|
||||||
"\"source_path\": \"" + source_path + "\", "
|
|
||||||
"\"output_name\": \"" + OUTPUT_NAME + "\""
|
|
||||||
"}")
|
|
||||||
result = subprocess.run(
|
|
||||||
['curl', '-X', 'POST', webhook_url,
|
|
||||||
'-H', 'Content-Type: application/json',
|
|
||||||
'-d', payload],
|
|
||||||
capture_output=True, text=True
|
|
||||||
)
|
|
||||||
print(f"Webhook 触发响应: {result.stdout[:200]}")
|
|
||||||
|
|
||||||
print("[Step 3/5] 等待 N8N 执行完成(Telegram 通知将发送到本会话)...")
|
|
||||||
print("请等待 Telegram 通知,收到后继续执行步骤 4。")
|
|
||||||
print("如需手动检查状态,请访问: https://n8n.ishenwei.online")
|
|
||||||
sys.exit(0) # <-- 此处退出,等待 Telegram 通知后再手动执行步骤 4
|
|
||||||
|
|
||||||
# ---- 以下为步骤 4 和 5,需在收到 Telegram 通知后执行 ----
|
|
||||||
|
|
||||||
output_files = [f"{OUTPUT_NAME}_output.md", f"{OUTPUT_NAME}_output.html"]
|
|
||||||
|
|
||||||
print(f"[Step 4/5] 复制输出文件回 Obsidian...")
|
|
||||||
for file in output_files:
|
|
||||||
src = f"macmini:{N8N_FILES}/{file}"
|
|
||||||
dst = f"{OUTPUT_DIR}/{file}"
|
|
||||||
result = subprocess.run(['scp', src, dst], capture_output=True, text=True)
|
|
||||||
if result.returncode == 0:
|
|
||||||
print(f" V {file}")
|
|
||||||
else:
|
|
||||||
print(f" X {file}: {result.stderr}")
|
|
||||||
|
|
||||||
print(f"[Step 5/5] 清理 N8N 容器临时文件...")
|
|
||||||
files_to_clean = [NOTE_NAME] + output_files
|
|
||||||
result = subprocess.run(
|
|
||||||
['ssh', 'macmini', 'rm'] + [f"{N8N_FILES}/{f}" for f in files_to_clean],
|
|
||||||
capture_output=True, text=True
|
|
||||||
)
|
|
||||||
if result.returncode == 0:
|
|
||||||
print(" V 清理完成")
|
|
||||||
else:
|
|
||||||
print(f" ! 清理失败(不影响结果): {result.stderr}")
|
|
||||||
|
|
||||||
print("🎉 工作流执行完毕!")
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 速查表:常见工作流配置
|
|
||||||
|
|
||||||
| 工作流 | Webhook Path | 输入文件规则 | 输出文件规则 | 通知方式 |
|
| 工作流 | Webhook Path | 输入文件规则 | 输出文件规则 | 通知方式 |
|
||||||
|--------|-------------|-------------|-------------|---------|
|
|--------|-------------|-------------|-------------|---------|
|
||||||
| 内容转化 v5 | `content-translation-v5` | `content-queue/*.md` | `content-output/*_output.md` + `*_output.html` | Telegram |
|
| 内容转化 v6 | `content-translation-v6` | `content-queue/*.md` | `content-output/*_output.md` | Telegram |
|
||||||
| (待补充) | | | | |
|
| (待补充) | | | | |
|
||||||
|
|
||||||
> **添加新工作流时**:在此表新增一行,注明 Webhook Path 和文件路径规则,星辉即可照此执行。
|
> **添加新工作流时**:在此表新增一行,注明 Webhook Path 和文件路径规则,星辉即可照此执行。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚠️ 异常处理规范
|
## 异常处理规范
|
||||||
|
|
||||||
| 异常情况 | 处理方式 |
|
| 异常情况 | 处理方式 |
|
||||||
|---------|---------|
|
|---------|---------|
|
||||||
@@ -817,7 +538,7 @@ print("🎉 工作流执行完毕!")
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔑 关键约束汇总
|
## 关键约束汇总
|
||||||
|
|
||||||
1. **N8N 容器路径**:`/home/node/.n8n-files/`(只读/写此目录)
|
1. **N8N 容器路径**:`/home/node/.n8n-files/`(只读/写此目录)
|
||||||
2. **文件传输方式**:`scp` via `macmini` 主机名
|
2. **文件传输方式**:`scp` via `macmini` 主机名
|
||||||
|
|||||||
Reference in New Issue
Block a user