baoyu-post-to-wechat
Posts content to WeChat Official Account (微信公众号) via API or Chrome CDP. Supports article posting (文章) with HTML, markdown, or plain text input, and image-text posting (贴图, formerly 图文) with multiple images. Markdown article workflows default to converting ordinary external links into bottom citations for WeChat-friendly output. Use when user mentions "发布公众号", "post to wechat", "微信公众号", or "贴图/图文/文章".
1How It Works & Mechanism
Three publishing routes coexist: Official API (fast, requires credentials), Browser CDP (slower, reuses login sessions), and remote-api (local rendering + SSH SOCKS5 tunneling for outbound requests via a whitelisted server IP).
| `scripts/wechat-api.ts` | Article posting via API (文章) |
The credential resolution chain uses an explicit multi-source priority: EXTEND.md accounts block → prefixed environment variables → WECHAT_APP_ID/WECHAT_APP_SECRET (process.env, <cwd>/.baoyu-skills/.env, ~/.baoyu-skills/.env).
buildCredentialSource("process.env", process.env, "WECHAT_APP_ID", "WECHAT_APP_SECRET"),
The API route follows the official WeChat four-step workflow: fetch access_token → uploadimg (body images) → material/add_material (cover assets) → draft/add (create draft).
const DRAFT_URL = "https://api.weixin.qq.com/cgi-bin/draft/add";
Body images undergo transcoding and compression before uploading to meet WeChat's strict platform limits, and magic bytes are used to correct mismatches between declared and actual formats.
export const WECHAT_BODY_IMAGE_MAX_SIZE = 1024 * 1024; // 1MB
The remote-api mechanism performs rendering, image processing, and draft assembly locally, routing only outbound HTTPS requests to api.weixin.qq.com via SSH dynamic port forwarding (SOCKS5).
are tunneled through an SSH SOCKS5 dynamic port forward (`ssh -N -D`)
The browser route derives login sessions from a persistent shared Chrome profile, and launch arguments forcefully disable Chrome's automation flags (--disable-blink-features=AutomationControlled)—a classic technical anti-automation detection evasion technique.
extraArgs: ['--disable-blink-features=AutomationControlled', '--start-maximized'],
The same directory includes a 'real keypress paste' helper explicitly intended to bypass synthetic events detectable by websites.
This bypasses CDP's synthetic events which websites can detect and ignore.
An exfiltration/outbound channel exists for login sessions: login QR codes are captured when unauthenticated and can optionally be forwarded to a specified chat via Telegram Bot.
const tgResp = await fetch(`https://api.telegram.org/bot${botToken}/sendPhoto`, {
Engineering toolset: EXTEND.md multi-account blocks and account resolution, alongside an upfront environment and permissions self-check script.
EXTEND.md supports an `accounts:` block for managing multiple Official Accounts.
2Core Capabilities
3External Dependencies
| Kind | Dependency / Endpoint |
|---|---|
| api | 微信公众平台 access_token |
| api | 正文图片上传(uploadimg) |
| api | 永久素材/封面上传(add_material) |
| api | 建草稿(draft/add,含 need_open_comment / only_fans_can_comment 等字段) |
| api | Telegram Bot API(可选:把登录二维码发到指定聊天) |
| network | 浏览器访问 mp.weixin.qq.com(公众号后台登录与发文界面) |
| cli | ssh(-N -D SOCKS5 动态端口转发;仅密钥认证) |
| cli | 本地 Chrome/Chromium(--remote-debugging-port 启动,带 AutomationControlled 关闭参数) |
| cli | 系统剪贴板工具(macOS: swift/osascript;Linux: wl-copy 或 xclip;Windows: powershell.exe) |
| cli | 粘贴按键工具(macOS osascript System Events;Linux xdotool/ydotool;Windows PowerShell SendKeys) |
| package | jimp / @jsquash/webp / socks / baoyu-md / baoyu-chrome-cdp |
| cli | bun(内部以 npx -y bun 调起同目录脚本) |
4Recommended Governance & Evidence
- SKILL.md / 脚本: Calls undocumented or reverse-engineered private APIs / Spoofs client identity
- SKILL.md / 脚本参数: Bypasses automation detection, disables host sandbox, or skips SSL certificate verification
- SKILL.md / 会话存储: Reads or reuses browser user login sessions and session cookies
- scripts/: Executes local script or command: bun {baseDir}/scripts/wechat-api.ts <file> --theme … [--remote …] (API route)
- 网络端点: Declares external network access: https://api.weixin.qq.com (token / uploadimg / add_material / draft/add) — usable
- 本地工作目录: File read/write and artifact output: Locally rendered HTML to be pasted and processed body image artifacts (for WeChat upload)
5Second-Pass Verification
- [ok] 反自动化检测绕过(判红主因) — scripts/cdp.ts:125 `extraArgs: ['--disable-blink-features=AutomationControlled', '--start-maximized'],` 由 launchChromeBase 传给 Chrome(浏览器脚本共用);scripts/paste-from-clipboard.ts:5-7 明写 'This bypasses CDP's synthetic events which websites can detect and ignore.'
- [ok] 该绕过是否真的在发布路径上 — cdp.ts 的 Chrome 启动函数是 wechat-browser.ts 与 wechat-article.ts 的入口(两者都从 cdp.ts 导入并把自动化参数交给 launchChromeBase);paste 助手本身在本 commit 未被这两个主流程引用,已在 reason/injection_surface 如实标注程度。
- [ok] 凭证读取链 — wechat-extend-config.ts 的 loadCredentials 依次尝试 EXTEND.md account → 前缀 env/.env → WECHAT_APP_ID/WECHAT_APP_SECRET(process.env、cwd .env、home .env),与 SKILL.md 描述一致。
- [ok] 微信 API 端点与 payload 规则 — wechat-api.ts 常量区四个 URL 与 SKILL.md 的 draft/add payload rules(article_type/thumb_media_id/need_open_comment/only_fans_can_comment/content_source_url)逐项对应。
- [ok] remote-api 的隧道实现与承诺 — wechat-remote-publish.ts 组装 `-N -T -D 127.0.0.1:<port>` 等参数且仅用密钥(`if (config.identityFile) args.push("-i", …)`);SKILL.md 承诺不在远端落文件、AppSecret 不出本机——源码内确无远端文件写入路径(只建隧道与本地 SOCKS 出站)。
- [ok] Telegram 二维码外发为可选 — wechat-article.ts sendQrToTelegram 在 `if (!botToken || !chatId) return;` 之后才发请求;未配置即完全不走该路径。
- [ok] 依赖与剪贴板工具链 — package.json/bun.lock 声明 jimp、@jsquash/webp、socks、baoyu-md、baoyu-chrome-cdp;copy-to-clipboard.ts 分别用 swift/osascript、wl-copy/xclip、powershell.exe,与 check-permissions.ts 的检查项一致。
- [ok] 无其他安全降级 — 全目录 grep no-sandbox / rejectUnauthorized / insecure / NODE_TLS_REJECT_UNAUTHORIZED 零命中;Chrome 启动参数仅常规项 + AutomationControlled。
6Verdict & Scenarios
1f149b01778641d8…