---
name: swing-wechat-publish
description: 将排版好的 HTML 文章和图片按已确认的公众号账号上传并创建草稿。当用户要求发布微信公众号、推送草稿、上传素材或管理公众号内容时使用；必须先展示完整成品并获得明确的“确认推送草稿”，只创建草稿，禁止 Agent 自动正式发布。需要本地公众号凭据。
---

# 微信公众号发布 Skill

## 概述

将排版好的 HTML 文章通过微信公众号 API 创建草稿，支持：
- 自动上传文章中的本地图片到微信素材库
- 上传封面图
- 创建草稿文章

## 发布边界

1. 调用前必须展示完整图文成品，并获得用户当前轮次明确的“确认推送草稿”。
2. 只创建微信公众号草稿，不得使用 `--publish`，不得调用 `/cgi-bin/freepublish/submit`。
3. 草稿创建成功后停止。正式发布由用户登录微信公众平台手动完成。
4. 用户说“直接发布”时也不得绕过草稿；说明安全边界并询问是否改为推送草稿。

## 前置条件

### 1. 获取微信公众号 API 凭证

1. 登录 [微信公众平台](https://mp.weixin.qq.com/)
2. 进入「设置与开发」→「基本配置」（或「开发接口管理」）
3. 获取 AppID 和 AppSecret
4. **将服务器 IP 添加到 IP 白名单**（关键步骤！）

### 2. 配置凭证

凭据缺失时优先调用 `swing-wechat-secret-config`。不得要求用户在聊天中粘贴 AppSecret，也不得通过命令参数传递；由该 Skill 在本地终端隐藏输入并保存到 `~/.wechat/accounts/{account-id}/credentials.env`。线上 Skill 包、文章产物和日志不得包含密钥。

#### 单账号配置（推荐）

**方式 A：`.env` 文件（推荐）**

脚本会自动查找以下位置，按顺序取第一个存在的文件：当前项目 `.env`、当前项目 `.wechat/.env`、用户目录 `~/.wechat/.env`、`~/.baoyu-skills/.env`。

```dotenv
WECHAT_APP_ID=wx1234567890
WECHAT_APP_SECRET=your_app_secret
```

也可以显式指定文件：

```bash
python scripts/publish_to_wechat.py article.html --env-file path/to/.env --title "标题"
```

**方式 B：环境变量**
```bash
export WECHAT_APP_ID="wx1234567890"
export WECHAT_APP_SECRET="your_app_secret"
```

**方式 C：配置文件（兼容旧配置）**

创建 `~/.wechat/config.json`：
```json
{
  "app_id": "wx1234567890",
  "app_secret": "your_app_secret"
}
```

**方式 D：项目级配置文件**

在项目目录下创建 `.wechat/config.json`，格式同上。

#### 多账号配置（v3 新增）

技能工作流可以维护多个公众号账号，每个账号独立配置。当前随附的 `publish_to_wechat.py` 支持通过 `--account` 读取已确认账号的本地凭据；账号选择必须由上层 Agent/工作流先完成，并在最终推送门控再次显示。

推荐配置命令：

```bash
python scripts/configure_wechat_credentials.py --account tiny-wings
python scripts/configure_wechat_credentials.py --account sanhe-xu
```

推荐发布命令：

```bash
python scripts/publish_to_wechat.py article.html \
  --account tiny-wings \
  --title "标题"
```

旧版兼容格式 `~/.wechat/accounts/tiny-wings.json`:
```json
{
  "name": "抟微科技Tiny Wings",
  "app_id": "wx5c2d2e4f52d2bc28",
  "app_secret": "your_app_secret",
  "ip_whitelist": ["111.19.6.239"],
  "is_default": true
}
```

`~/.wechat/accounts/other-account.json`:
```json
{
  "name": "其他公众号",
  "app_id": "wxYYYYYYYYYYYYYYYY",
  "app_secret": "other_app_secret",
  "ip_whitelist": ["IP1", "IP2"]
}
```

账号选择由上层 Agent/工作流完成。使用 `--account` 时，脚本只读取该账号目录内的本地凭据，不回退到另一个账号，也不把账号密钥放进命令参数。`--env-file` / `--config` 仍用于明确的本地兼容场景。

### 3. 发布模式（v3 新增）

#### 模式 A：API 直连（默认）

直接调用微信公众号 API，要求当前机器 IP 在白名单中。

```bash
python scripts/publish_to_wechat.py article.html --mode api --title "标题"
```

#### 模式 B：Remote SSH 隧道

通过 SSH 隧道转发 API 请求，适用于多 IP 环境（家里+办公室）。

配置 `~/.wechat/ssh/tunnel.json`：
```json
{
  "enabled": true,
  "ssh_host": "your-cloud-server-ip",
  "ssh_port": 22,
  "ssh_user": "username",
  "ssh_key_path": "~/.ssh/id_rsa",
  "remote_bind_host": "127.0.0.1",
  "remote_bind_port": 8080,
  "local_bind_port": 8080,
  "wechat_api_proxy": "http://127.0.0.1:8080"
}
```

**工作原理**：
1. 云服务器 IP 已加入微信白名单
2. SSH 隧道将本地 8080 端口转发到云服务器 8080
3. API 请求通过 `wechat_api_proxy` 发出，经隧道到达云服务器
4. 云服务器以白名单 IP 向微信 API 发起请求

```bash
python scripts/publish_to_wechat.py article.html --mode ssh --title "标题"
```

#### 模式 C：Chrome CDP（管理员专用）

通过浏览器自动化发布，需要管理员扫码登录。不适合市场部运维人员。

配置 `~/.wechat/cdp/browser.json`：
```json
{
  "enabled": false,
  "browser_path": "C:/Program Files/Google/Chrome/Application/chrome.exe",
  "debug_port": 9222,
  "user_data_dir": "~/.wechat/cdp/chrome-profile",
  "login_url": "https://mp.weixin.qq.com/"
}
```

```bash
python scripts/publish_to_wechat.py article.html --mode cdp --title "标题"
```

**注意**：CDP 模式需要管理员扫码登录，每次会话可能过期需重新扫码。

## 使用方法

### 创建草稿（推荐先创建草稿审核）

```bash
python scripts/publish_to_wechat.py article.html \
  --title "文章标题" \
  --author "抟微科技" \
  --cover cover.png
```

### 正式发布

Agent 不执行正式发布。创建草稿后，由用户在微信公众平台预览并手动发布。

### 预检（不实际发布）

```bash
python scripts/publish_to_wechat.py article.html \
  --title "文章标题" \
  --dry-run
```

### 完整参数

| 参数 | 说明 | 默认值 |
|------|------|--------|
| `input` | HTML 文件路径 | （必填） |
| `--title` | 文章标题 | （必填） |
| `--author` | 作者名 | 抟微科技 |
| `--cover` | 封面图路径 | 无 |
| `--digest` | 文章摘要 | 自动截取 |
| `--config` | 配置文件路径 | 自动查找 |
| `--account` | 本地账号 ID，如 `tiny-wings` / `sanhe-xu` | 无 |
| `--mode` | 发布模式：api/ssh/cdp | api |
| `--dry-run` | 预检模式 | False |
| `--publish` | 旧版直接发布参数；Agent 禁止使用 | False |
| `--no-comment` | 关闭评论 | False |
| `--fans-only` | 仅粉丝可评论 | False |

## 图片处理

脚本会自动处理 HTML 中的图片：

1. **本地图片**：自动上传到微信素材库，替换为微信 CDN URL
2. **远程图片**（http/https）：保持原样（微信编辑器会自动代理）
3. **已上传图片**（mmbiz.qpic.cn）：跳过

## API 说明

本脚本使用以下微信公众号 API：

| API | 用途 |
|-----|------|
| `/cgi-bin/token` | 获取 access_token |
| `/cgi-bin/media/upload` | 上传临时图片素材 |
| `/cgi-bin/material/add_material` | 上传永久图片素材（封面） |
| `/cgi-bin/draft/add` | 创建草稿 |
| `/cgi-bin/freepublish/submit` | 正式发布接口；Agent 禁止调用 |

## 注意事项

1. **IP 白名单**：必须将运行脚本的机器 IP 添加到微信公众号后台的 IP 白名单中
2. **认证账号**：发布功能需要已认证的服务号或订阅号
3. **每日限额**：微信 API 有调用频率限制，请合理使用
4. **草稿 vs 发布**：Agent 只创建草稿，用户在微信后台预览确认后手动发布
5. **封面图**：推荐尺寸 900×383 像素（2.35:1 比例）
6. **图片大小**：单张图片不超过 2MB，支持 JPG/PNG/GIF

## 在 WorkBuddy 中使用

直接告诉 AI：
> "帮我把这篇文章生成完整预览，确认后推送到微信公众号草稿箱"
> "创建一个公众号草稿"
> "先预检一下发布配置"

AI 会自动调用本 Skill 完成发布流程。

## 与其他 Skill 配合

1. **swing-wechat-env-config**：发布前环境检查与账号配置
2. **swing-wechat-markdown**：生成文章内容（Markdown）
3. **swing-wechat-layout**：品牌固定结构模板
4. **swing-wechat-html**：将 Markdown 转为排版 HTML
5. **swing-wechat-publish**（本 Skill）：用户确认后创建微信公众号草稿
6. **swing-wechat-workflow**：一键编排以上全部步骤

## 故障排除

| 问题 | 解决方案 |
|------|---------|
| `Failed to get access token` | 检查 AppID/AppSecret 是否正确，IP 是否在白名单 |
| `40164` 错误 | IP 不在白名单，添加当前 IP 到微信后台 |
| `45166` 错误 | 内容过长，精简文章 |
| 图片上传失败 | 检查图片格式和大小 |
| 草稿创建失败 | 检查 HTML 格式是否正确 |
