bili-sunflower-publish
Unified publish pipeline for Bilibili: HTML/Markdown file → editor → publish. Uses window.editor API directly — no system clipboard dependency.
Supports two targets:
- - 专栏 (Article): long-form articles on INLINECODE1
- 小站 (Tribee): community posts on INLINECODE2
Prerequisites
- - Browser tool with
openclaw profile (Playwright-managed browser)
Input
- - Content file path (article body) — supports
.html and .md / .markdown files - Target type:
article (专栏) or tribee (小站) — infer from user intent - Title (optional — see Phase 2)
- For tribee: tribee name or ID (required)
- For tribee: 分区 (category, optional — user can specify or choose during publish)
Phase 1: Navigate & Login Check
Article mode
Navigate to https://member.bilibili.com/york/read-editor and take a snapshot.
- - Logged in: editor loads with title textbox INLINECODE10
- Not logged in: redirects to login page
Tribee mode
Publish URL: INLINECODE11
Both tribee_id and tribee_name are required for the publish URL. Resolve missing params:
| User provides | Resolution |
|---|
| id + name | Direct → publish URL |
| id only |
Navigate to
https://www.bilibili.com/bubble/home/{id}, extract tribee name from the page, then → publish URL |
| name only | Search
https://search.bilibili.com/all?keyword={name}, find the card linking to
bilibili.com/bubble/home/{id}, extract
{id}, then → publish URL |
After navigating to the publish URL:
- - Logged in + member: editor loads with title and body area
- Not logged in: redirects to login page
- Not a member: may show join prompt — tell user to join the tribee first
If not logged in, stop and tell the user to log in manually in the openclaw browser profile, then retry.
Phase 2: Preprocess & Title Handling
Run the preprocess script matching the file type. The script handles H1 extraction, heading promotion, image inlining, and (for HTML) whitespace cleanup.
2a. For .html files
CODEBLOCK0
Output (stdout, 3 lines):
CODEBLOCK1
Parse title and path from the output. The processed HTML at path is ready for injection in Phase 3.
2b. For .md / .markdown files
CODEBLOCK2
Output (stdout, 3 lines):
CODEBLOCK3
Parse title and path from the output. The processed Markdown at path is ready for injection in Phase 3.
2c. Title validation
If the user provided a title explicitly, use it instead of the script-extracted one.
After resolving, validate:
- - Title > 50 characters: present 2-3 shortened alternatives, let user choose
- Title looks meaningless (e.g.
output, untitled, temp, or clearly unrelated to the content): read the first few hundred chars of body, generate 2-3 title suggestions, let user choose
Do NOT silently use a bad title. Wait for user selection before proceeding.
Enter the title: click the title textbox and type.
Phase 3: Insert Article Body
Both editors share the same rich-text editor component (window.editor).
Use the preprocessed content from Phase 2 and inject it into the editor.
IMPORTANT — JS string escaping:
Content (HTML or Markdown) often contains characters that break JS syntax (backticks, quotes, newlines, backslashes, etc.). You must use the method below to safely construct the JS code. Do NOT paste raw content directly into a JS variable assignment.
How to construct the evaluate JS code
Follow these steps exactly for both HTML and Markdown injection:
- 1. Get the processed file path from Phase 2 output (
path=...) - Run the following command to produce a JSON-escaped string of the file content:
CODEBLOCK4
This outputs a double-quoted JSON string with all special characters escaped (newlines, quotes, backslashes, etc.), e.g. "line1\nline2\"quoted\"".
- 3. Capture the stdout output as INLINECODE33
- Build the full JS code by embedding
ESCAPED_JSON_STRING into the template (see 3a-HTML / 3a-MD below). It already includes its own surrounding double quotes, so place it directly after JSON.parse( with no additional quotes.
3a-HTML. Processed HTML → ClipboardEvent dispatch
CODEBLOCK5
Note: If the HTML content is large (>50KB), split it into chunks and paste sequentially.
3a-MD. Processed Markdown → editor importMarkdown command
CODEBLOCK6
3b. Verify content
Evaluate JS to confirm content was inserted:
CODEBLOCK7
Expected: chars > 100 and first80 matches the article opening.
Phase 4: Publish
Article mode
Editor bottom has a "发布设置" panel (usually already visible) with defaults that work out of the box:
- - 可见范围: 所有人可见 (default)
- 封面: auto-generated from body text (default)
- 评论: enabled (default)
If the user has specific publishing preferences, adjust before publishing:
| 设置 | 操作 | 说明 |
|---|
| 可见范围 | 选 radio: "所有人可见" / "仅自己可见" | 仅自己可见不支持分享和商业推广 |
| 自定义封面 |
勾选 checkbox → 上传图片 | 不设则自动抓正文开头文字 |
| 评论开关 | 勾选/取消 checkbox | 关闭后无法评论 |
| 精选评论 | 勾选 checkbox | 开启后需手动筛选评论才展示 |
| 定时发布 | 勾选 checkbox → 选择时间 | 范围: 当前+2h ~ 7天内,北京时间 |
| 创作声明-原创 | 勾选 checkbox | 声明原创,禁止转载 |
| 创作声明-AI | 勾选 checkbox | 标识使用 AI 合成技术 |
| 话题 | 点击"添加话题"按钮 | 可选 |
| 文集 | 点击"选择文集"按钮 | 可选 |
Steps:
- 1. Scroll down to confirm the "发布设置" panel is visible; if collapsed, click "发布设置" button to expand
- Apply any user-requested settings from the table above
- Click "发布" button (next to "保存为草稿", at the bottom right)
- If a confirmation dialog appears, confirm
- Verify publish succeeded (URL changes or success toast)
Tribee mode
Bottom bar appears after content is entered, with defaults that work out of the box:
- - 分区: 未选择 (some tribees may require)
- 同步至动态: enabled (default)
If the user has specific preferences, adjust before publishing:
| 设置 | 操作 | 说明 |
|---|
| 分区 | 点击"选择分区"下拉 → 选择分区 | 部分小站可能必选 |
| 同步至动态 |
取消勾选 checkbox | 默认开启,取消后不同步到动态 |
分区自动选择(Tribee only)
When the user did not specify a 分区:
- 1. Click "选择分区" dropdown to reveal available options
- Read the list of 分区 names from the dropdown (snapshot)
- Based on the article title + first ~200 chars of body content, pick the most relevant 分区:
- Match by keyword/topic similarity (e.g. tutorial content → "经验分享", questions → "提问求助")
- If no option is a clear fit, pick the most general/catch-all option
- If the tribee only has 1-2 generic options, just pick the best one without overthinking
- 4. Click the chosen 分区
- Do not ask the user to confirm — just pick and proceed (they can always re-publish if wrong)
If the user did specify a 分区, use it directly (skip auto-selection).
Steps:
- 1. Handle 分区 (user-specified or auto-selected per above)
- Apply any other user-requested settings
- Click "发布" button (blue, bottom right)
- Verify publish succeeded
Execution
Default: execute Phase 1 → 4 directly in the main session (supports user interaction for login/title).
Only delegate to subagent if the user explicitly requests it.
bili-sunflower-publish
B站统一发布流程:HTML/Markdown文件 → 编辑器 → 发布。直接使用 window.editor API,无需依赖系统剪贴板。
支持两种目标:
- - 专栏 (Article):在 member.bilibili.com 发布长文
- 小站 (Tribee):在 bilibili.com/bubble 发布社区帖子
前置条件
- - 浏览器工具,使用 openclaw 配置文件(Playwright 管理的浏览器)
输入
- - 内容文件路径(文章正文)—— 支持 .html 和 .md / .markdown 文件
- 目标类型:article(专栏)或 tribee(小站)—— 根据用户意图推断
- 标题(可选 —— 见第二阶段)
- 小站模式:小站名称或 ID(必填)
- 小站模式:分区(category,可选 —— 用户可指定或在发布时选择)
第一阶段:导航与登录检查
专栏模式
导航至 https://member.bilibili.com/york/read-editor 并截图。
- - 已登录:编辑器加载,显示标题输入框 请输入标题(建议30字以内)
- 未登录:重定向至登录页面
小站模式
发布 URL:https://www.bilibili.com/bubble/publish?tribeeid={id}&tribeename={name}
发布 URL 需要同时提供 tribeeid 和 tribeename。缺失参数的处理方式:
| 用户提供 | 处理方式 |
|---|
| id + 名称 | 直接 → 发布 URL |
| 仅 id |
导航至 https://www.bilibili.com/bubble/home/{id},从页面提取小站名称,然后 → 发布 URL |
| 仅名称 | 搜索 https://search.bilibili.com/all?keyword={名称},找到链接至 bilibili.com/bubble/home/{id} 的卡片,提取 {id},然后 → 发布 URL |
导航至发布 URL 后:
- - 已登录且为成员:编辑器加载,显示标题和正文区域
- 未登录:重定向至登录页面
- 非成员:可能显示加入提示 —— 告知用户先加入该小站
如果未登录,停止并告知用户在 openclaw 浏览器配置文件中手动登录,然后重试。
第二阶段:预处理与标题处理
运行与文件类型匹配的预处理脚本。脚本处理 H1 提取、标题层级提升、图片内联以及(针对 HTML)空白清理。
2a. 针对 .html 文件
bash
python3 {SKILLDIR}/scripts/preprocesshtml.py [output-dir]
输出(stdout,3行):
title=<提取的标题>
path=<处理后的 html 文件路径>
bytes=
从输出中解析 title 和 path。处理后的 HTML 文件位于 path,可直接用于第三阶段注入。
2b. 针对 .md / .markdown 文件
bash
python3 {SKILLDIR}/scripts/preprocessmd.py [output-dir]
输出(stdout,3行):
title=<提取的标题>
path=<处理后的 md 文件路径>
bytes=
从输出中解析 title 和 path。处理后的 Markdown 文件位于 path,可直接用于第三阶段注入。
2c. 标题验证
如果用户明确提供了标题,则使用用户提供的标题,而非脚本提取的标题。
解析完成后,进行验证:
- - 标题超过 50 个字符:提供 2-3 个缩短的备选方案,让用户选择
- 标题看起来无意义(例如 output、untitled、temp,或明显与内容无关):读取正文前几百个字符,生成 2-3 个标题建议,让用户选择
不要静默使用糟糕的标题。等待用户选择后再继续。
输入标题:点击标题输入框并输入。
第三阶段:插入文章正文
两个编辑器共享相同的富文本编辑器组件(window.editor)。
使用第二阶段预处理后的内容,注入到编辑器中。
重要 —— JS 字符串转义:
内容(HTML 或 Markdown)通常包含会破坏 JS 语法的字符(反引号、引号、换行符、反斜杠等)。你必须使用以下方法安全地构建 JS 代码。不要将原始内容直接粘贴到 JS 变量赋值中。
如何构建 evaluate 的 JS 代码
对于 HTML 和 Markdown 注入,请严格遵循以下步骤:
- 1. 从第二阶段输出中获取处理后的文件路径(path=...)
- 运行以下命令生成文件内容的 JSON 转义字符串:
bash
python3 -c import json,sys; print(json.dumps(open(sys.argv[1]).read())) <处理后的文件路径>
这将输出一个双引号括起的 JSON 字符串,其中所有特殊字符(换行符、引号、反斜杠等)均已转义,例如 line1\nline2\quoted\。
- 3. 捕获 stdout 输出作为 ESCAPEDJSONSTRING
- 通过将 ESCAPEDJSONSTRING 嵌入模板来构建完整的 JS 代码(见下方 3a-HTML / 3a-MD)。它已包含自身的双引号,因此直接放在 JSON.parse( 之后,无需额外引号。
3a-HTML. 处理后的 HTML → ClipboardEvent 分发
javascript
(function () {
const html = JSON.parse(ESCAPEDJSONSTRING);
const clipboardData = new DataTransfer();
clipboardData.setData(text/html, html);
clipboardData.setData(text/plain, );
const pasteEvent = new ClipboardEvent(paste, {
bubbles: true,
cancelable: true,
clipboardData,
});
window.editor.view.dom.dispatchEvent(pasteEvent);
})();
注意: 如果 HTML 内容较大(超过 50KB),请分块粘贴。
3a-MD. 处理后的 Markdown → editor importMarkdown 命令
javascript
(function () {
const markdown = JSON.parse(ESCAPEDJSONSTRING);
window.editor.commands.importMarkdown({
content: markdown,
replaceContent: true,
});
})();
3b. 验证内容
执行 JS 确认内容已插入:
javascript
(function () {
const e = window.editor.view.dom;
return { chars: e.textContent.length, first80: e.textContent.substring(0, 80) };
})();
预期结果:chars > 100 且 first80 与文章开头匹配。
第四阶段:发布
专栏模式
编辑器底部有发布设置面板(通常已可见),默认设置可直接使用:
- - 可见范围:所有人可见(默认)
- 封面:从正文文字自动生成(默认)
- 评论:已启用(默认)
如果用户有特定的发布偏好,请在发布前进行调整:
| 设置 | 操作 | 说明 |
|---|
| 可见范围 | 选择 radio:所有人可见 / 仅自己可见 | 仅自己可见不支持分享和商业推广 |
| 自定义封面 |
勾选 checkbox → 上传图片 | 不设则自动抓正文开头文字 |
| 评论开关 | 勾选/取消 checkbox | 关闭后无法评论 |
| 精选评论 | 勾选 checkbox | 开启后需手动筛选评论才展示 |
| 定时发布 | 勾选 checkbox → 选择时间 | 范围:当前+2h ~ 7天内,北京时间 |
| 创作声明-原创 | 勾选 checkbox | 声明原创,禁止转载 |
| 创作声明-AI | 勾选 checkbox | 标识使用 AI 合成技术 |
| 话题 | 点击添加话题按钮 | 可选 |
| 文集 | 点击选择文集按钮 | 可选 |
步骤:
- 1. 向下滚动确认发布设置面板可见;如果已折叠,点击发布设置按钮展开
- 应用上表中用户请求的任何设置
- 点击发布按钮(位于保存为草稿旁边,右下角)
- 如果出现确认对话框,确认
- 验证发布成功(URL 变化或成功提示)
小站模式
输入内容后出现底部栏,默认设置可直接使用:
-