#6353·MoviePilot

[Feature Request]: 入库失败通知支持可配置模板

Author: wy19xxCreated Aug 18, 2026Updated Sep 17, 2026
Labelsfeature requeststale

[Feature Request]: 入库失败通知支持可配置模板

当前程序版本

v2.15.6(Docker;同时核对了当前 v3.0.0 源码,仍存在同一缺口)

运行环境

Docker

功能改进类型

主程序

功能改进

背景

当前可以通过 NotificationTemplates 自定义“开始下载”“已入库”“添加订阅”“订阅完成”四类通知,但“入库失败”仍由后端直接拼接标题和正文后发送。

当一个下载任务中有多个文件、特典、字幕或音轨时,失败通知只有识别后的媒体标题和错误原因,无法通过通知模板展示实际失败的源文件名,也无法按自己的通知格式组织内容。

本请求不涉及失败通知聚合;聚合需求已有 #6343。本请求关注单条入库失败通知的模板化能力,两者可以独立实现,也应能兼容。

已确认的现状

  • ContentType 目前只有 subscribeAddedsubscribeCompleteorganizeSuccessdownloadAdded,没有入库失败类型。
  • TransferChain 的入库成功路径创建 ctype=ContentType.OrganizeSuccess,并向 post_message() 传入 metamediainfotransferinfo 等模板上下文。
  • 入库失败路径则直接创建 mtype=Manual 的固定 Notification / Message,未设置 ctype,也未将 metamediainfotransferinfo 和转移历史 ID 传给模板渲染器。
  • 通知模板上下文已有 original_name,其值来自 meta.title。常规整理任务的 metaMetaInfoPath 按实际 FileItem.path 构造,因此该变量可用于输出实际源文件名(含扩展名、无完整路径),不必再增加重复的 source_file_name 变量。
  • downloadAdded 的官方默认模板已经使用 torrent_title;这部分不属于本 Issue 的范围。

v2.15.6 对应位置:

  • app/helper/message.pyTemplateContextBuilderMessageTemplateHelper
  • app/chain/transfer.py:入库成功及失败通知分支
  • app/schemas/types.pyContentType

当前 v3 对应位置:

  • app/application/messaging/message.py
  • app/chain/transfer.py
  • app/schemas/types.py

期望能力

  1. 新增 ContentType.OrganizeFailed = "organizeFailed",作为入库失败通知的模板键。
  2. 在默认 NotificationTemplates 中增加 organizeFailed 模板,并通过迁移为已有配置补齐该键;不能覆盖用户已有的四类自定义模板。
  3. 将整理链中的入库失败通知接入该内容类型。至少覆盖:
    • 已识别媒体后,实际整理失败的分支;
    • 未识别到媒体信息而无法入库的分支。
  4. 模板渲染上下文应提供:
    • original_name:实际源文件名,包含扩展名但不包含完整路径;
    • err_msg:失败原因;
    • transfer_history_id:失败历史记录 ID;
    • 已有的 title_yearseason_episodetypecategory 等字段在可用时继续提供。
  5. 模板只负责标题和正文。现有 mtype=Manual、通知渠道开关、图片、历史记录链接、重试按钮以及 /redo <id> 的可用性必须保持不变。
  6. 对旧配置或用户主动删除 organizeFailed 模板的情况,必须回退到当前固定标题和正文,不能发送空通知。

建议的默认模板结构示例:

python
{
    'title': '{{ title_year }}{% if season_episode %} {{ season_episode }}{% endif %} 入库失败!',
    'text': '{% if original_name %}源文件:{{ original_name }}\\n{% endif %}'
            '原因:{{ err_msg or "未知" }}'
            '{% if transfer_history_id %}\\n如果按钮不可用,可回复:\\n/redo {{ transfer_history_id }}{% endif %}'
}

这里仅展示模板字段;现有的重试按钮仍应由后端保留并照常发送。

建议实现方式

失败分支可在创建消息时设置 ctype=ContentType.OrganizeFailed,并通过 post_message() 传入 metamediainfotransferinfo。同时显式传入以下覆盖值:

python
original_name=task.fileitem.name or Path(task.fileitem.path).name,
err_msg=transferinfo.message or "未识别到媒体信息",
transfer_history_id=history.id if history else None,

TemplateContextBuilder.build() 会在构造默认上下文后合并额外参数,因此可确保 original_name 始终是实际源文件名,而不依赖元数据识别结果。未识别媒体信息的失败分支也应使用同一模板化路径,并传入对应的固定错误原因。

验收建议

  1. 配置 organizeFailed 自定义模板后,已识别媒体的整理失败通知能渲染 original_nameerr_msgtransfer_history_id
  2. 源文件名应与 FileItem.name 一致,包含扩展名,不泄露完整下载路径。
  3. 未识别媒体信息的失败路径也能发送有效通知;缺失的媒体字段应通过 Jinja 条件安全处理。
  4. 模板化后,通知仍保留 Manual 类型、历史链接、重试按钮和现有接收对象行为。
  5. 旧配置中没有 organizeFailed 时,通知回退为当前固定内容而不是空消息。
  6. 新迁移只补充缺失的 organizeFailed 键,不改写用户已有模板。

站点适配采集文件

不适用

参考资料

  • #6008:通知模板上下文新增变量并补充测试的先例。
  • #6343:入库失败通知聚合需求;本请求与其相关,但不重复。