Skip to content

站点信息聚合模块(站免 / 公告 / PT监护室) ​

这三个功能聚合各 PT 站点的「信息层」数据:全站免费促销、站点公告、以及第三方站点健康监控站 savept.icu 的存续状态。三者复用同一套站点 capability 扩展范式(站免/公告)或独立外部抓取(监护室)。

功能覆盖 ​

模块能力数据来源
站免检测每个站点的全站免费/促销横幅(正在站免 / 即将站免 / 暂无),区分单种 Free 与全站促销各站首页 index.php
公告抓取每个站点的站点公告,结构化为标题/日期/正文(支持现代/经典两种 NexusPHP 皮肤)各站首页 index.php
PT监护室聚合 savept.icu 全站 PT 站点健康(正常/病危/已关站)+ 病危/恢复/站庆公告 + 抢救时长,并与本地已配置站点匹配(已绑定/可添加/未收录)第三方 savept.icu(公开,无需登录)

「站免」抓的是首页横幅级别的全站促销,与搜索结果里单条种子的 Free 图标不同。

后端结构 ​

站免 / 公告 — 站点 capability 范式(套用 H&R 全链路) ​

新增一个站点抓取能力 = 复制 H&R 链改名,每层落点:

internal/site/
├── types.go          FreeleechDef / AnnouncementDef(挂 SiteMetadata)+ SiteFreeleech / AnnouncementItem / SiteAnnouncement
├── adapter.go        FreeleechCapable / AnnouncementCapable 接口(type-assert 按需实现)
├── freeleech.go      ParseFreeleech 纯函数(候选选择器 + looksLikeFreeleech 双关键词 + isUpcoming + findInlineBackground)
├── announcement.go   ParseAnnouncements 纯函数(li.index-news-item 现代 / [id^=ka] 经典 / div#announcement / rowhead / 最大文本块 5 级联)
├── defaults.go       DefaultNexusPHPFreeleech / Announcement(默认 index.php,enabled 默认 true)
└── schemas/
    ├── freeleech.go      (*NexusPHP).FetchFreeleech(GET index → ParseFreeleech;NONE/FAILED 兜底)
    └── announcement.go   (*NexusPHP).FetchAnnouncement(GET index → ParseAnnouncements)

internal/chain/site_info.go   SiteChain.Freeleech/Announcements(单站)+ FreeleechAll/AnnouncementsAll(并发聚合 + per-site 缓存)
internal/automation/info.go    runFreeleech(刷新缓存 + WS 推送正在站免)/ runAnnouncements(刷新缓存)
internal/ws/broadcaster.go     FreeleechAlert + EncodeFreeleechAlert(freeleech-alert 消息)
internal/api/v1/freeleech.go   FreeleechHandler / AnnouncementHandler(GET 聚合 + POST 单站刷新)

缓存策略:站点为全局共享配置(非 per-user),故 per-site 缓存按 siteID 分桶(站免 30min / 公告 60s)。cron 定时刷新缓存,前端读取秒返回;?refresh=1 或 POST /sync/:id 强制刷新。

PT监护室 — 独立外部聚合模块 ​

internal/savept/
├── types.go      SaveptSiteCard / SaveptAlert / SaveptSummary + 状态/匹配/告警枚举
│                  (告警细分 danger 病危 / obituary 讣告 / warning 恢复 / info 站庆 / celebration 今日站庆)
├── parse.go      parseSavept(卡片 data-* 抽取含 opentime/closetime/anniversary + 状态归一 +
│                  公告切片 + 抢救时长回填;讣告与病危独立类型)
├── matcher.go    matchCards(URL→域名→名称精确→名称模糊 4 级匹配)+ summarize(含内外站/今日站庆/年份/mp 计数)
└── service.go    Service.Fetch(全局缓存 6h + 每次实时本地匹配 + CF 拦截降级返回 stale 缓存)

internal/api/v1/savept.go   SaveptHandler(GET /savept?refresh=1)
internal/app/app.go         savept-refresh cron(每 2h 刷新;病危/讣告通知)

frontend/src/views/Savept.vue        ICU 仪表盘页面(迁移自 MoviePilot savept 插件 Page.vue)
frontend/src/utils/savept.ts         状态/MP 元信息 + 公告分区 + 站点名高亮分词
frontend/src/components/SptIcon.vue   Lucide 描边 SVG 图标集(替代 MDI)
mobile/lib/features/savept/savept_page.dart  Flutter 同款(紧凑生命体征 + 筛选 + 公告 + 年份折叠 + confetti 彩带)

匹配优先级:URL 完全 > 域名 > 名称精确 > 名称模糊。URL/域名匹配 → 「已拥有」(回填本地站点 ID/名);名称匹配 → 「可添加」;否则「未收录」。mp 状态由前端从 match_type 派生,后端不冗余。

UI(三端一致,ICU 仪表盘风格):融合头部 6 项生命体征(监护中/健康/已拥有/病危/已关站/站庆)+ 内嵌筛选栏(搜索 + 年份 + MP状态 + 状态 + 类型 + 近期站庆)+ 结构化公告区(病危/恢复/站庆/讣告 4 卡片,站点名高亮)+ 按建站年份分组折叠 + 丰富站点卡片(图标/类型/运营时长/站庆/开站关站时间/MP 标签)+ 今天站庆卡片彩带(Web canvas-confetti 动态加载 + CSS 星光;Flutter confetti 包)。

API ​

方法路径说明
GET/freeleech全站站免聚合(带缓存;?refresh=1 强制刷新)
POST/freeleech/sync/:id单站站免重抓
GET/announcements全站公告聚合(?refresh=1)
POST/announcements/sync/:id单站公告重抓
GET/saveptPT监护室数据(?refresh=1 重抓 savept.icu)

均挂 guarded 组(RequireAuth + 好学 VIP 准入)。

配置(环境变量) ​

变量默认说明
FREELEECH_CRON*/30 * * * *站免缓存刷新
ANNOUNCEMENT_CRON0 * * * *公告缓存刷新(每小时)
SAVEPT_CRON0 */2 * * *监护室 savept.icu 刷新(每 2h)

站点定义 ​

站免/公告默认对所有 NexusPHP 站启用(首页横幅/公告区通用)。MTeam(schema: mteam)亦默认启用——其适配器已实现 FetchFreeleech(/api/system/promotion/rules)与 FetchAnnouncement(/api/news/list),EnsureDefaults 的 ensureMTeamDefaults 放行两项 capability。站点可在 YAML 显式关闭:

yaml
id: example
name: 示例站
schema: nexusphp
urls: [https://example.pt]
freeleech:
  enabled: false   # 关闭该站站免检测
announcement:
  enabled: false   # 关闭该站公告抓取

三端入口 ​

  • Web:左侧导航「站免 / 公告 / 监护室」三个视图。站免页顶部汇总条 5 个状态 tile(站点/正在站免/即将站免/暂无/失败)可点击筛选卡片(按站点首条 notice 状态归类,再点同一 tile 取消),下方卡片网格 + 单站/全部刷新。
  • Mobile:账户页「更多功能」→ 站免 / 公告 / PT监护室 三个页面(下拉刷新 + 单站刷新 + 监护室健康卡片筛选)。

校准工作流 ​

站免/公告/监护室的解析基于 NexusPHP/savept.icu 的稳定结构。若某站页面改版导致取值异常,参照站点选择器校准工作流:浏览器登录 → 另存完整网页 → 替换 internal/site/testdata/ 或 internal/savept/testdata/ fixture → 调整选择器/正则 → 钉值测试保绿。

测试 ​

go test ./internal/site/... ./internal/savept/...:

  • TestParseFreeleech:正在/即将站免判定 + 种子表不被误识别。
  • TestParseAnnouncements:现代皮肤三件套解析。
  • TestParseSavept:卡片抽取(含 opentime/closetime/anniversary_flag)+ 状态归一 + 抢救时长回填 + 公告切片(病危/讣告/恢复独立类型)。
  • TestSummarize:汇总统计含内外站/今日站庆/建站年份数/mp 占有-可添加-未收录。
  • TestMatchCards:4 级匹配优先级 + 已绑定回填。