SubsTracker 订阅提醒系统
一套自托管的订阅管理与到期提醒系统,部署在 Cloudflare Workers 边缘运行时上,用 KV 做持久化存储,零服务器成本管理域名、会员、账单等各类订阅的到期提醒。
概述
日常订阅的服务越来越多——域名、云服务、会员、保号套餐——散落在各个平台的续费日期很难手动追踪。SubsTracker 提供了一个网页管理后台统一录入订阅,由 Cloudflare Cron Triggers 每小时整点检查,命中提醒规则时自动通过即时消息渠道推送,避免因忘记续费导致服务中断。
核心功能
订阅管理
- 增删改查:名称、周期、金额、分类、备注一目了然,支持克隆同构订阅
- 两种续订模式:循环订阅(从当前到期日顺延)与到期重置(从支付日重新起算),覆盖会员续费和充值重置两类场景
- 周期灵活性:季度/半年/年快捷选项、公历"每月最后一天"、农历周期
- 支付记录:手动续订时记录支付历史,配合仪表盘统计多币种支出
提醒调度
- 多规则提醒:默认预设到期前 7/3/1 天与到期当天,每条订阅可自定义多条规则
- 精确日语义:仅在剩余天数正好等于 N 的当天发送一次,配合去重机制避免重复打扰
- 发送时间窗口:可配置允许发送的小时(如仅早 8 点),按时区判断,非窗口整点正常跳过
- 到期后追偿:支持"到期后每隔 X 小时提醒,直到续费"
消息渠道
Telegram(支持群话题 Topic)、Bark、企业微信、ntfy、Resend 邮件、Webhook、Gotify、Server酱、PushPlus、NotifyX 共 10 种渠道,任意勾选组合,每渠道可一键发送测试通知。
可观测性
- 通知历史:每条发送的成功/失败明细与错误原因
- 调度日志:命中、去重、跳过的完整链路记录,排查"为什么没收到"不求人
/debug诊断页:时区与通知窗口实时检查
架构
┌──────────────┐ ┌───────────────────┐ ┌─────────────┐
│ 管理后台(SPA) │────▶│ Worker (Hono) │────▶│ KV 存储 │
└──────────────┘ │ API + 定时调度 │ └─────────────┘
└─────────┬─────────┘
│ Cron Triggers(每小时整点)
┌─────────▼─────────┐
│ 通知服务(10 渠道)│
│ Telegram/Bark/... │
└───────────────────┘
- 入口:
fetch处理网页与 API 请求,scheduled处理定时调度 - 分层设计:
core/(时间、农历、货币、JWT)、data/(KV 与迁移)、services/(调度器与渠道)、api/(路由)、views/(管理端页面) - 数据迁移:首次访问自动执行 KV 结构迁移,升级无感
挑战与解决
时区一致性
问题:Cron 按 UTC 触发,“到期前 3 天"“早 8 点发送"的判断若按 UTC 理解会整天偏移。
解决:所有调度判断统一收敛到配置时区(如 Asia/Shanghai),配置页提供实时预览(当前会发/不会发),并有 /debug 页面诊断时区与窗口。
通知可靠性
问题:用户常反馈"没收到通知”,可能原因横跨渠道配置、时间窗口、规则命中、去重四层。
解决:把每次调度决策落盘——通知历史记录发送结果与错误详情,调度日志记录命中/去重/跳过原因,配合 FAQ 排查路径,让每次"没收到"都能定位到具体一层。
零成本持久化
问题:Workers 无本地磁盘,传统数据库在免费额度内成本高。
解决:采用 Cloudflare KV 单键 JSON 文档存储,配合结构版本迁移与 JSON 备份导入导出(合并/覆盖两种模式),免费额度内即可长期稳定运行,数据随时可迁移。
技术栈细节
运行时
- Cloudflare Workers 边缘运行时,全球就近响应
- KV 低延迟读、最终一致性写,契合订阅场景
框架与工程化
- Hono 轻量 Web 框架,路由与中间件
- Vitest + workerd 单元/集成测试
- GitHub Actions 自动化 CI
- 第三方通知 API 令牌,便于外部系统接入
成果
- 成本:完全运行在 Cloudflare 免费额度内,零固定支出
- 可靠性:整点调度 + 去重 + 失败明细,漏发/重发可追溯
- 可移植:JSON 备份一键迁移,不锁定平台
- 可扩展:10 种渠道抽象统一接口,新渠道接入成本低
后续计划
- 支出趋势图表
- 日历视图
- 更多币种汇率源
- PWA 离线查看
项目状态:✅ 生产运行中
GitHub:查看源码
Demo:Try it Live
