运维 | ANI-RSS 的微信通知:一个占位符引发的 400近期更新
运维 | ANI-RSS 的微信通知:一个占位符引发的 400
有些事,做完只需要一分钟;有些坑,填平却要绕一个大圈。给 ANI-RSS 加上微信通知,本以为是「填个 Webhook 地址」的小事,最后却变成了一场跟源码较劲的短跑。
写在前面
家里的自动追番链路是 ANI-RSS 加 qBittorrent:蜜柑的 RSS 一更新,ANI-RSS 自动拉取、识别集数、推给下载器,番剧就安安静静地躺在媒体库里。链路跑通了大半年,唯一缺的是一双「眼睛」——新番开始下载了,人在外面看不到;下载失败了,也要等回家才发现。
于是想加个通知:番剧开始下载、下载完成、缺集、出错,都推送到微信。推送服务选了 WxPusher,免费、稳定、微信直达,注册应用拿一个 token,用户扫码关注拿到自己的 UID,就能开始推送。
配置过程
ANI-RSS 的通知设置里没有 WxPusher 的现成选项,但有一个通用的 WebHook 类型:可以自定义 Method、URL、Header 和 Body,本质上就是向任意 HTTP 接口 POST 一段 JSON。WxPusher 也恰好提供标准的消息推送接口——把 APP token 和收到人的 UID 放进请求体,就能把内容推到微信。
配置本身很简单:
- 通知类型:WebHook
- Method:POST
- URL:WxPusher 的消息接口
- Header:
Content-Type: application/json - Body:一个 JSON,把通知模板作为消息内容填进去
第一版配置写完,点击测试——400。
那个占位符
ANI-RSS 的通知模板支持占位符替换:${title}、${episode}、${subgroup} 这些会被换成真实的番剧信息。官方文档里的 WebHook 示例写的是把 ${notification} 放到 Body 里,让 ANI-RSS 把渲染好的整段通知文本填进去。
但实测返回 400。单独用 curl 测 WxPusher 接口是通的,说明问题出在 ANI-RSS 生成的请求体上。
翻源码(WebHookNotification.java + BaseNotification.java)才看明白:
- ANI-RSS 会先走一遍
replaceNotificationTemplate,把 Body 里的${notification}提前替换成一段包含了换行符的原始多行模板文本; - 之后才轮到对
${message}这类占位符做 JSON 转义处理。
于是 Body 里如果写 ${notification},最终得到的是一段没有经过 JSON 转义的多行文本,直接把 JSON 结构撑破了——响应自然是 400。
解法只有一行字的区别:把 Body 里的占位符从 ${notification} 改成 ${message}。后者不会被提前替换,会在 JSON 转义之后才填入,生成的就是合法 JSON。
教训:官方文档示例的占位符不一定比另一条路径更正确。 同样是「整段通知文本」,两个占位符在代码里的处理时机完全不同。遇到 400 先怀疑占位符在流水线里的位置,而不是接口本身。
验证
改完配置后,从 ANI-RSS 容器内向 WxPusher 接口发了一条真实消息:
{
"code": 1000,
"msg": "处理成功",
"data": [{ "status": "创建发送任务成功" }]
}几秒钟后,手机微信上弹出了那条写着「链路已打通」的测试消息。
现在的通知模板保持精简——事件类型、标题、季、集、字幕组、进度、首播日期、事件说明、下载位置,去掉了一开始模板里附带的 TMDB / BGM 元数据(那部分信息在微信这种轻量场景里属于噪音)。开始下载、下载完成、缺集、出错四个事件,都会实时推过来。
以后新番开播,人不在家也知道它在安静地下载了。
全部操作由 Hermes Agent 辅助完成:读取配置、查 WxPusher 接口文档、翻 ANI-RSS 源码定位占位符时序、通过 API 写回配置并验证。
最后更新于 2026-09-30 「部分内容存在时效性,如有失效请留言反馈」
除注明外为 袅残烟的冥想盆 原创文章,转载请注明出处。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。