家里服务一多,通知就乱了:我给自己搭了个通知中转站
我家那台群晖上跑着 Emby、qBittorrent,另外还有一台小主机跑了十几个docker和几个我自己写的脚本应用。
这些服务各有各的通知方式。用久了手机上就变成这样:Bark 里一堆、企业微信里一堆、邮箱里还有一堆,有时候干脆哪都没有。
最让我难受的是群晖的备份任务。它失败了只会在 DSM 的通知中心里躺一条,我得主动登进去看才知道。有一次连着几天备份失败,我是周末整理文件时才发现的——那会儿已经晚了。后来我改了用邮箱通知时不时就进垃圾邮箱了,挺烦的。然后就是emby的通知,用webhook不同类型的通知json完全不一样,还没办法定制。
那阵子我一直在想一件事:我好像不是缺一个推送 App,我是缺一个能把这些东西收拢起来的地方,可以对消息进行二次处理成符合各类渠道的格式,然后发送出来。
一开始我也找了很多Hub类型的项目自己部署,用来用去总觉得差那么一点儿。然后找到了NotifyCenter,它是一个通知中心,用了一段时间了,写下来给有同样困扰和需求的人看看。
它其实不是推送工具,是个「中转站」
其实很多人用通知用Bark就可以了,以为又是类似 Bark 的东西。其实方向完全不一样。
Bark、Telegram、企业微信这些,解决的是「怎么把消息推到手机上」。而 NotifyCenter 站在它们前面一层,解决的是「我这一堆服务,怎么统一往外发」。
这么一画就清楚了:所有服务只需要记住一个地址,至于发什么、长什么样、最后落到哪个 App,都由中间这层决定。
【图 1:整体架构图 】它自己不会弹通知,还是靠 Bark /Pushdeer这些类App 收。所以手机上并没有多装任何东西,这点我挺喜欢。
装起来比我想的省事
其实安装简单得多。
它是单镜像的,不需要 MySQL 也不需要 Redis,数据就是一个 SQLite 文件,扔在 data/ 目录里。备份的时候复制这个目录就行,不用操心数据库导出。
我在群晖上建了个 /volume1/docker/notifycenter,放一个 compose 文件:
services:
notifycenter:
image: ttt216/notifycenter:1.0
container_name: notifycenter
ports:
- "5400:5400"
volumes:
- ./data:/data
environment:
- TZ=Asia/Shanghai
- DATA_PATH=/data
restart: unless-stopped
docker compose up -d,几秒钟就起来了。打开 http://NAS地址:5400/admin/login,初始密码在启动日志里,首次登录会强制改。
那个 TZ 一定要设对,原因我在后面踩坑那节说,我就是在这儿栽过一次。
【图 2:后台仪表盘 】用起来之后,几个让我觉得值的地方
第一次收到带海报的入库通知
Emby 装个 Webhooks 插件,目标 URL 填 http://地址:5400/api/service/notify?api_key=密钥,勾上 Library 和 Playback,就完事了。
第一次收到带海报的入库通知时我愣了一下。我原以为要自己写模板拼图片地址,结果它自己认 Emby 的事件格式,连海报都拼好了。
Jellyfin 也一样,只是有个坑:Template 那一栏必须留空,填了反而认不出来。
群晖备份失败,我终于能及时知道了
这个是我最想要的。控制面板 → 通知 → 推送服务 → 加一个 Webhook,地址同上。
加完第一次收到「备份任务失败」的推送,说实话有点感动。以前这种事只能靠我自己想起来去翻。
换出口,不用动所有服务
这条是我用了一段时间才意识到的价值,也是最关键的一条。
一开始我的出口是 Bark。后来觉得 Bark 在国内偶尔抽风,想加个 Telegram 兜底。按以前的思路,我得把 Emby、qB、Grafana 里配的地址全都改一遍。
但实际上我只需要在后台加一个渠道,把它加进路由里。所有服务的配置一个字都不用改。
那一瞬间我才真正明白「中转站」这个设计省的是什么——不是省配置的步骤,是省掉「以后每加一个出口就要动一遍全局」这件事。
整季 20 集电视剧入库,手机没响一晚上
这个属于用久了才会碰上的问题。新下一季剧,20 集陆续入库,每条都推一次,手机能响到半夜。
后台有个「剧集合并」,能把同一部剧一个时间窗内的入库压成一条。开了之后基本清净了。
还有两个我没预料到的
一个是静默时段。设成 23:00 到 7:00,普通消息不响、存起来早上补发,但调用时标了紧急的照样立刻响。这个解决了「半夜被 qB 下载完成吵醒」的老问题。
另一个是送达保障。有一次 Bark 那边出问题,几条告警全丢了,我是在日志里看到红色的失败记录才知道的。开了之后,失败的消息会先落队列按退避重试,实在送不到进「死信」,后台能看到原因,渠道修好还能一键重放。
说明一下:剧集合并、静默时段、送达保障这三样是增强版的功能。前两个是我买增强版的原因,第三个是买完才发现的意外收获。
踩过的几个坑
接口返回 200,但消息其实没发出去。
这个我栽了挺久。密钥错了、路由没配对,接口照样返回 200,只是响应体里 success 是 false。写脚本的时候一定要判断这个字段,只看状态码会被骗。
Bark 的地址要整条粘。
App 里给的是 https://api.day.app/xxxxxx/ 这样一整条,我一开始只粘了后面那串 key,一直失败。
Jellyfin 的 Template 必须留空。
填了模板之后 payload 结构会被改写,服务端认不出事件类型,发出来的通知内容是空的。
时区。
容器里 TZ 没设对,静默时段会按 UTC 算。我在东八区,结果整个静默窗口错位了。设置页里会显示当前服务器时间,出问题先核对这个。
改了环境变量要 up -d,不是 restart。
环境变量是容器创建时固化的,光重启带不上新值。这个我试了两次才反应过来。
说点不足
github上的介绍比较粗,装好后才能看到内置的使用指南(在后台菜单里),写得比我想的细,新手可以仔细看看。
另外它没有自己的手机 App,靠 Bark 这些现成的收消息。这点我一开始觉得是缺点,用久了反而觉得是优点——手机上不用再多一个图标。
最后
这个工具提供了免费版,核心功能(渠道、模板、路由、日志)都能用,也没有时间限制,完全够用。
Docker Hub 上直接拉 ttt216/notifycenter:1.0,amd64 和 arm64 都有,群晖、威联通、树莓派都能跑。
有问题可以去群里问,折腾这类东西的乐趣,大概就是把一堆零散的小麻烦,慢慢收拢成自己顺手的样子。
