在 Emacs 里用 Markdown 或 Org 编写并发布豆瓣长评、日记、读书笔记和普通广播。
Warning
这是实验性软件,依赖豆瓣未公开的网页接口。接口随时可能变化。当前仅支持 GNU/Linux,其中 Firefox 组合测试最充分。
- GNU/Linux;
- Emacs 29.1 或更新版本,并带 SQLite、libxml 与 GnuTLS 支持;
plz0.10-pre 或更新版本,用于所有 HTTP 请求;curl可执行程序,作为plz的底层 HTTP 传输;yaml1.2.4 或更新版本,用于 Markdown metadata;pandoc3.0 或更新版本,用于转换 Markdown 和 Org 正文;- 已在受支持的浏览器 profile 中登录豆瓣。
浏览器和 profile 都由用户显式指定。本包不会扫描、猜测或自动选择 profile:
douban-cookie-browser 可设为:
firefoxchromiumchrome
douban-cookie-profile-directory 必须指向所选 profile:
- Firefox:包含
cookies.sqlite; - Chromium、Chrome:包含
Network/Cookies。
Chromium 系浏览器的 Cookie 可能需要从 Linux 桌面的 Secret Service 或 KWallet 取得解密密钥。
Firefox Container 还应显式设置对应的 originAttributes,普通非 Container profile 使用空字符串。
M-x douban-new-review 先选择品类,再通过名称搜索或标准条目 URL 选择评论
对象,最后创建 .md、.markdown 或 .org 源稿。它只生成本地模板;
父目录不存在时会递归创建,目标文件已存在则直接报错。
读书笔记不提供专门的新建命令。在普通 Markdown 文件的顶层 douban: 下
调用当前补全前端,选择 annotation:,随后可继续补全 subject-id:、
privacy: 等字段;Org 中对应补全 DOUBAN_ANNOTATION 字段。日记和普通
广播同样直接在普通 Markdown 或 Org 文件中写出类型标记,然后执行
M-x douban-publish。
读书笔记只支持当前“新笔记”协议,不导入已有笔记,也不兼容旧的
/annotation/ID/ 写接口。
Markdown 的 douban: 必须且只能包含 review、note、annotation 或 status 中的
一个子 mapping。id、topic-id、privacy 等都是相应类型 mapping 内的叶子字段。初次发布
省略 id,新广播也省略 topic-id;一旦写出 ID 字段,其值就必须是
非空正整数。
Org 使用值为空的 #+DOUBAN_REVIEW:、#+DOUBAN_NOTE:、
#+DOUBAN_ANNOTATION: 或 #+DOUBAN_STATUS: 作为唯一内容类型标记;
其余字段使用包含类型的完整路径,
例如 #+DOUBAN_REVIEW_SUBJECT_ID:、#+DOUBAN_NOTE_PRIVACY: 和
#+DOUBAN_STATUS_TOPIC_ID:。标记本身必须保留空值。
打开受支持的源稿时,douban-mode 会自动启用:Markdown 以 YAML front
matter 中的顶层 douban: 为识别标记,Org 以上述任一内容类型标记为识别
标记。空白源稿或尚未写出完整识别
标记的残缺源稿也可以手动运行:
M-x douban-mode
下列字段表使用 Markdown 各类型子 mapping 中的叶子名称;Org 在字段名前
加上相应的 DOUBAN_REVIEW_、DOUBAN_NOTE_、DOUBAN_ANNOTATION_ 或
DOUBAN_STATUS_ 前缀。
review 字段:
| 字段 | 含义 |
|---|---|
id |
初次发布时省略;创建成功后写回,存在时更新这篇长评 |
subject-id |
必填,豆瓣条目 ID;新长评可在值槽按名称动态补全 |
subject-type |
必填,必须是 book、movie、tv、music 或 game |
introduction |
可选导语,最多 140 个 UTF-16 code unit |
rating |
可选,整数 1–5 |
spoiler / donate |
可选布尔值 |
explanation-types |
可选的单项内容说明,值与普通广播相同 |
rtype / platforms |
仅用于游戏评论;platforms 保存一个或多个平台 ID |
游戏长评的 rtype 只接受 review(评测)或 guide(攻略)。必须在 metadata 中明确填写 rtype
游戏评论已经具有合法 subject-id 时,platforms 值槽会通过该条目的匿名
详情接口取得当前可用平台。候选显示平台名称、缩写和 ID,完成补全后只保存
平台 ID。Markdown 的多个平台必须使用 YAML block sequence,不然没法自动补全:
douban:
review:
subject-id: '36932396'
subject-type: game
platforms:
- '1'
- '2'Org 在同一个关键字值中使用逗号分隔:
#+DOUBAN_REVIEW:
#+DOUBAN_REVIEW_SUBJECT_ID: 36932396
#+DOUBAN_REVIEW_SUBJECT_TYPE: game
#+DOUBAN_REVIEW_PLATFORMS: 1,2
note 字段:
| 字段 | 含义 |
|---|---|
id |
初次发布时省略;新建页预分配后会在上传或发布前写回 |
privacy |
可选:public(所有人可见)或 friends(仅朋友可见) |
cannot-reply |
是否禁止回复 |
author-tags |
标签列表 |
没有 id 时读取创建页并绑定其预分配 ID;有 id 时读取对应编辑页,
由页面的 action 判断状态:new 表示恢复同一次首次发布,其他受支持的
提交模式表示更新已发布日记。源稿不另存 URL。
annotation 字段:
| 字段 | 含义 |
|---|---|
id |
初次发布时省略;创建成功后写回 topic ID,存在时更新这篇笔记 |
subject-id |
必填,笔记所属的豆瓣图书 ID;新稿可按书名动态补全 |
privacy |
可选:public(公开)或 private(仅自己可见) |
explanation-types |
可选的单项内容说明,值与普通广播相同 |
读书笔记标题最多 70 个 UTF-16 code unit。新建默认公开,其回复范围由
douban-default-reply-limit 决定;私密笔记始终禁止回复。更新时保留编辑页
中的现有回复范围,只有从私密切回公开时重新使用该全局配置。省略其他可选
字段同样会保留编辑页中的现有设置。源稿只保存 topic ID,规范公开地址为
https://www.douban.com/topic/ID/。
status 字段:
| 字段 | 含义 |
|---|---|
id |
初次发布时省略;发布后写入公开页面使用的 sid |
topic-id |
personal topic 的 aid;更新 API 使用这个 ID |
explanation-types |
可选的单项内容说明,见下表 |
anthology-id |
可选文集 ID;可在字段值处按文集名称补全 |
内容说明严格单选:
| metadata 值 | 网页选项 |
|---|---|
ai-generated |
含 AI 生成内容 |
fictional |
含虚构内容 |
marketing |
含营销信息 |
minor-safety |
含或影响未成年人身心健康信息 |
public-affairs |
涉及时事、公共政策、社会事件 |
personal-opinion |
个人观点仅供参考 |
repost |
内容为转载,来源见正文 |
none |
无需标注 |
新建广播固定公开,回复范围由 douban-default-reply-limit 决定。更新时
保留编辑页中的现有回复范围,不使用新建默认值。
例如:
douban:
status:
explanation-types: ai-generatedOrg 使用 #+DOUBAN_STATUS_EXPLANATION_TYPES。
长评、读书笔记和普通广播都不接受 original metadata。
douban-default-original 是唯一的原创声明开关,默认为 t:新建这三类
内容时使用它,更新长评时也由它控制;更新读书笔记和普通广播时
则保留编辑页中的现有原创状态。
读书笔记和普通广播的回复范围也不属于源稿 metadata。统一配置项
douban-default-reply-limit 可选 all 或 following,默认为 all;它用于
新建公开读书笔记和广播,也用于把已有读书笔记从私密切回公开。
普通广播还接受可选的 anthology-id,用于把本次内容加入已有文集。metadata 中只填写正整数 ID:
douban:
status:
anthology-id: '123456'所有元数据都带有自动补全。
需要新建文集时运行:
M-x douban-new-anthology
命令会提示名称和封面,并立即在远端创建公开文集。名称不能为空且最多 20 个 UTF-16 code unit;当前网页编辑器要求封面,并把交互裁剪结果上传为 800×800 JPEG。本命令会验证文件具有 JPEG 标识,但不代替网页端裁剪,请预先 准备 800×800 方图。
图片独占段落时才生成豆瓣 IMAGE。夹在文字、标题或表格单元格中的行内
图片改用其 alt 文字;空白或缺失 alt 时直接消失,也不会上传。链接
包裹的独立图片仍按独立图片处理。
读书笔记沿用普通引用语法:Markdown 使用 >,Org 使用 quote block;
发布后都是普通 blockquote。本包不生成豆瓣原生摘录块,也不解析章节、
页码元数据;如需记录出处,请把章节和页码直接写入可见正文。
长评、日记、读书笔记和普通广播都支持指向正文标题的文章内链接。Markdown 使用普通 fragment 链接,并给目标标题设置稳定 ID:
[跳到结论](#conclusion)
## 结论 {#conclusion}Org 使用 CUSTOM_ID:
[[#conclusion][跳到结论]]
* 结论
:PROPERTIES:
:CUSTOM_ID: conclusion
:END:
发布时会把源稿 ID 改写为豆瓣公开页实际使用的标题文字锚点;带 fragment 的完整外部 URL 不会被改写。作为跳转目标的标题必须是正文顶层的纯文字标题, 而且可见文字必须唯一。标题中的粗体、斜体、代码、链接或图片都会使远端锚点 不稳定,因此这类标题不能作为跳转目标;没有被引用、也没有进入目录的普通 标题不受此限制。引用、列表、脚注和参考文献中的标题不属于正文导航目标。
Markdown 可在 YAML front matter 顶层启用自动目录:
toc: true
toc-depth: 3toc-depth 可选,范围为 1–6,省略时为 3。Markdown 目录固定出现在正文
开头。Org 使用原生指令,并在指令所在位置生成目录:
#+TOC: headlines 2
Org 的可选深度范围为 1–3,省略时为 3。豆瓣没有独立目录实体;生成结果是 正文中的粗体“目录”段落和带文章内链接的嵌套普通列表,因此发布后的内容也能 在网页端继续编辑。
长评、日记、读书笔记和普通广播都支持豆瓣原生用户 mention。在源稿中把光标移到插入 位置,然后 运行:
M-x douban-insert-user-mention
输入搜索词并选择候选后,命令会插入持久化
链接标记;发布时该标记转换为豆瓣原生 USER entity。补全使用所选浏览器
profile 的豆瓣登录态,并只显示已经关注的用户。
在 Markdown 源稿中,douban-mode 还会安装用户 mention 的
completion-at-point。输入非空的 @名称前缀,会自动补全。
不记得条目 URL 时,可以运行:
M-x douban-search-subject
选择品类并输入名称(也可以直接输入规范 URL)后,命令会让你选择搜索结果,
并把规范条目 URL 直接插入光标处。随后可以把 URL 用在普通 Markdown/Org
链接或下面的显式卡片语法中。这里的规范 URL 指 HTTPS 的
book/movie/music.douban.com/subject/ID/ 或
www.douban.com/game/ID/,不带 query、fragment 或额外路径。
Markdown 必须把带有 "card" title 的链接单独放成一段:
[示例文章](https://example.com/articles/1 "card")Org 必须先写 ATTR_DOUBAN,再紧跟一个独立链接段落:
#+ATTR_DOUBAN: :type link-card
[[https://example.com/articles/1][示例文章]]
卡片地址必须是带主机名的绝对 HTTP 或 HTTPS URL
发布前,程序通过豆瓣当前的 URL 解析接口取得卡片数据;服务端按 URL 返回原生
LINK 或 SUBJECT 原子卡片。
在源稿 buffer 中运行:
M-x douban-publish
命令会保存当前 buffer,按 douban 中唯一的子 mapping 或 Org 中唯一的
内容类型标记确定稿件类型,并直接执行对应发布流程。
douban-publish 不依赖 douban-mode;即使没有自动识别、手动关闭了 mode,
只要源稿 metadata 合法,仍可照常发布。
如需在长评和日记末尾自动追加 Creative Commons 许可引用,可设置
douban-cc-statement。它支持 CC0 1.0 与六种 CC 4.0 许可,默认不追加;
声明只进入发布正文,不修改源稿,也不作用于读书笔记或普通广播。
长评和读书笔记默认不发送或保留关联广播。设置
douban-review-send-broadcast 为非 nil 可以恢复广播:读书笔记直接通过发布
请求控制;长评网页接口会无条件生成广播,因此默认关闭时,程序先把评论 ID
写回源稿,再从首页唯一核对并删除对应广播。长评广播可能短暂可见;若清理
失败,错误会明确说明评论已经发布,源稿中的 ID 也会保留,切勿重复发布。
更新已有长评不会删除历史广播。
| 变量 | 默认值 | 作用 |
|---|---|---|
douban-cookie-browser |
firefox |
Cookie 来源浏览器 |
douban-cookie-profile-directory |
nil |
必须显式设置的 profile 目录 |
douban-firefox-origin-attributes |
"" |
Firefox 普通上下文或 Container 值 |
douban-default-reply-limit |
all |
新建公开读书笔记和广播的回复范围;也用于读书笔记从私密切回公开 |
douban-default-original |
t |
长评、读书笔记和普通广播的全局原创声明开关 |
douban-review-send-broadcast |
nil |
长评和读书笔记是否发送并保留关联广播 |
douban-cc-statement |
nil |
长评和日记末尾的可选 CC 许可声明 |
douban-user-agent |
Firefox UA | 网页请求的 User-Agent |