feat(subscriptions): private rule groups, MP quality presets, save path, reset and calendar API

- include/exclude sync to a per-subscription private rule group (rule_group.hard, migration 0036);
  evaluation merges chain hard conditions; private groups hidden from GET /rules, soft-deleted with
  the subscription and rebuilt on resubscribe
- MP resolution / quality / effect map to presets written onto the subscription's own slots
  (default slot template on create); UHD / Atmos go to the private group include
- downloadSavePath mapped to the downloader path and passed as qB savepath; libraryRootId used
  for the first organize when the work has no path binding; keywords appended to active search
- POST /subscriptions/{id}/reset releases stale in-flight plans, clears deferrals, re-evaluates
- GET /subscriptions/calendar from episode air dates; refreshMetadata writes TMDB season
  episode air dates for tracked seasons

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 20:14:40 +08:00
1 parent 52402864d6
commit 70d56645fe
20 files changed
+1663 -44

No files matched your search

+22
View File
@@ -629,6 +629,28 @@ export const Api = {
},
R,
),
/** 日历(静态路径,须先于 /subscriptions/{id} 注册) */
calendar: ep({
method: "get",
path: "/subscriptions/calendar",
scope: "read",
summary:
"订阅日历:追踪中订阅范围内集的播出日期(同日同季聚合)与入库状态,电影取上映日期;没有播出日期的列在 unknown。from/to 为 YYYY-MM-DD,跨度不超过 62 天",
query: z.object({
from: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
to: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
mediaKind: policy.SubscriptionMediaKind.optional(),
}),
response: policy.SubscriptionCalendar,
}),
reset: ep({
method: "post",
path: "/subscriptions/{id}/reset",
scope: "admin",
summary: "重置进度:取消已预留未提交、下载任务已不在的计划,清延后记录,立即重评;仍在下载的计划与已入库资产保留",
params: IdParam,
response: policy.SubscriptionResetResult,
}),
/** 总览:在 crud 列表上加分组/排序/筛选,条目带卡片派生字段,另给各分组计数(docs/design/subscriptions.md §1) */
list: ep({
method: "get",