DraftPublisher 插件使用说明

功能

DraftPublisher 为 Typecho 增加一个仅接收 JSON 的草稿写入接口。它不会发布文章、不会使用后台 Cookie,也不会接受 HTML 格式的正文;成功请求只会创建一篇 post_draft Markdown 草稿。

接口地址固定为:

POST https://example.com/index.php/action/draftpublisher

如果站点启用了 URL 重写,index.php 可按站点现有规则省略。接口始终需要 Authorization: Bearer <Token>Idempotency-Key 请求头。

安装与配置

  1. DraftPublisher 整个目录放到 usr/plugins/
  2. 在 Typecho 后台“控制台 -> 插件”启用 DraftPublisher
  3. 打开插件设置,复制自动生成的 Bearer Token,并设置草稿作者 UID。建议为接口单独创建一个 Contributor 或 Editor 账户。
  4. 默认接口关闭、仅接受 127.0.0.1::1。本地 Codex 使用时,勾选“启用接口”即可。
  5. 要允许远程主机时,同时勾选“允许非本机来源”,在“允许的来源 CIDR”中仅加入发布机的固定地址,并保持“远程请求必须使用 HTTPS”启用。

Token 是完整写权限凭据。不要放到 Git 仓库、文章文件、聊天记录、浏览器前端代码或截图中。Token 泄露后,在插件配置中替换为新的随机值并保存即可;旧 Token 立刻失效。

请求格式

请求体必须是 application/json

{
  "title": "一篇由 AI 起草的文章",
  "text": "# 标题\n\n正文使用 Markdown。",
  "format": "markdown",
  "slug": "ai-draft-example",
  "tags": ["Typecho", "AI"],
  "categories": [1],
  "allow_comment": false
}

字段说明:

  • title:必填,最长 150 个字符。
  • text:必填,Markdown 正文;最大长度由插件配置决定。
  • format:可选,默认且仅支持 markdown
  • slug:可选,最长 150 个字符,Typecho 会按其自身规则规范化及去重。
  • tags:可选,字符串数组,最多 20 项;不存在的标签会被创建。
  • categories:可选,分类 ID 数组,最多 10 项;所有 ID 必须已存在。
  • allow_comment:可选布尔值,默认 false

每次逻辑发布操作都必须使用新的 Idempotency-Key。同一个 Key 重试相同内容会返回首次创建的草稿;以同一个 Key 发送不同内容会返回 409,不会创建第二篇草稿。

curl 示例

curl --fail-with-body --request POST "https://example.com/index.php/action/draftpublisher" \
  --header "Authorization: Bearer $TYPECHO_DRAFT_TOKEN" \
  --header "Idempotency-Key: 5d379d1d-56a2-4e86-a6b1-049ce8d40d19" \
  --header "Content-Type: application/json" \
  --data '{"title":"接口草稿","text":"正文","format":"markdown"}'

含代码正文的 JSON

Markdown 代码块、反引号、花括号、方括号和普通换行都可以出现在 text 中,不会导致接口解析失败。接口会把 text 当作一个 JSON 字符串,成功后按原样保存为 Markdown。

失败通常来自手工拼接了无效 JSON,例如字符串中的双引号、反斜杠或换行没有转义。请始终使用 JSON 库序列化请求体;内置的 publish_draft.py 使用 Python json.dumps,可安全处理代码、JSON 示例、Shell 命令和多行内容。不要把 Markdown 直接拼到 curl --data '...' 中。

如果直接用 curl 调试,先把序列化后的 JSON 写入文件,再用 --data-binary @request.json 发送:

curl --fail-with-body --request POST "https://example.com/index.php/action/draftpublisher" \
  --header "Authorization: Bearer $TYPECHO_DRAFT_TOKEN" \
  --header "Idempotency-Key: 5d379d1d-56a2-4e86-a6b1-049ce8d40d19" \
  --header "Content-Type: application/json" \
  --data-binary @request.json

成功时返回 201

{
  "success": true,
  "duplicate": false,
  "cid": 42,
  "draft_id": 42,
  "status": "draft"
}

网络重试时,使用原来的 Idempotency-Key。接口返回 duplicate: true 表示此前的草稿已被识别,不会重复创建。

安全与部署

  • 接口默认为关闭,且未开启远程模式时只接受服务器本机回环地址。
  • 每次请求都校验 Bearer Token,使用恒定时间比较;错误响应不暴露 Token、数据库信息或文章内容。
  • 远程模式默认要求 HTTPS。不要为了排障关闭它;应修正站点、负载均衡或反向代理的 TLS 配置。
  • 对远程发布,CIDR 应写成单个发布机的 /32/128,不要填写 0.0.0.0/0::/0
  • 默认不信任 X-Forwarded-ForX-Forwarded-Proto。只有在这些头由反向代理覆盖而非透传时,才把代理的实际 IP/CIDR 填入“受信任反向代理 CIDR”。
  • 插件按来源 IP 限流;限流与幂等状态存于 PHP 临时目录,适合单机部署。多应用服务器时,还必须在网关/WAF 对该路径做共享限流和 IP 白名单。
  • 在 Nginx、Apache 或 CDN 中额外限制此路径的方法、请求体大小和来源地址。Web 服务器应正确转发 Authorization 请求头。
  • 接口拥有草稿创建权,不要把 Token 授予不受信任的 AI、浏览器脚本或第三方自动化服务。

常见响应

  • 401 unauthorized:缺少、格式错误或失效的 Bearer Token。
  • 403 source_not_allowed:来源 IP 不在允许范围内。
  • 400 https_required:远程请求没有通过受信任的 HTTPS 链路到达。
  • 413 payload_too_large:请求体超过插件配置。
  • 429 rate_limited:当前来源超过限流阈值。
  • 409 idempotency_conflict:同一个幂等键被用于不同内容。
  • 503 invalid_author:插件设置的作者 UID 已不存在或不具有 Contributor 以上权限。

下载地址:
DraftPublisher.zip