feat(telegram): 订阅/下载补齐 year/rating/genres/原名/语言 富通知字段

- 模型: Subscription/DownloadTask 新增 OriginalName/OriginalLanguage/Year/
  Rating/Genres 列(GORM AutoMigrate 自动建列, 无需手写迁移)
- enrich 链路: displayMetadata 与 DownloadTaskMeta 携带新字段, 从
  SearchExternalMedia(TMDb/豆瓣/Bangumi)结果回填并持久化; 放宽提前返回
  门槛, 已有海报但缺新字段时仍补齐
- 通知: 订阅/下载完成事件 data 注入 year/rating/genres/original_title/
  original_language, 喂给作者富模板 formatTelegramMediaNotification
- 测试: 新增端到端断言, 验证补齐字段透传进 Telegram caption
This commit is contained in:
ShukeBta
2026-06-20 01:45:40 +08:00
parent 9ef7721527
commit 6e61c8b545
5 changed files with 229 additions and 29 deletions
+25
View File
@@ -110,6 +110,11 @@ type DownloadTaskMeta struct {
MediaType string
MediaCategory string
SourceCategory string
OriginalName string
OriginalLanguage string
Year int
Rating float32
Genres string
AllowExistingLibrary bool
}
@@ -570,6 +575,11 @@ func (d *DownloadService) createTask(ctx context.Context, userID, urlStr, savePa
SavePath: savePath,
MediaType: meta.MediaType,
MediaCategory: meta.MediaCategory,
OriginalName: meta.OriginalName,
OriginalLanguage: meta.OriginalLanguage,
Year: meta.Year,
Rating: meta.Rating,
Genres: meta.Genres,
Status: "queued",
AllowExistingLibrary: meta.AllowExistingLibrary,
}
@@ -1381,6 +1391,21 @@ func (d *DownloadService) notifyDownloadComplete(ctx context.Context, torrent QB
if strings.TrimSpace(task.Overview) != "" {
data["overview"] = task.Overview
}
if strings.TrimSpace(task.OriginalName) != "" {
data["original_title"] = task.OriginalName
}
if strings.TrimSpace(task.OriginalLanguage) != "" {
data["original_language"] = task.OriginalLanguage
}
if task.Year > 0 {
data["year"] = task.Year
}
if task.Rating > 0 {
data["rating"] = task.Rating
}
if strings.TrimSpace(task.Genres) != "" {
data["genres"] = task.Genres
}
}
go func() {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+39
View File
@@ -127,3 +127,42 @@ func TestTelegramDispatchUsesPhotoAndFormattedCaption(t *testing.T) {
}
}
}
// TestTelegramMediaTemplateRendersEnrichedFields 验证补齐的媒体字段
// (年份/评分/类型/原名/语言)确实透传进 Telegram 富模板 caption。
// 这是「模型/刮削链路补齐字段」与「作者富模板」对接的端到端断言。
func TestTelegramMediaTemplateRendersEnrichedFields(t *testing.T) {
caption := formatTelegramNotification(NotifyEvent{
Type: EventSubscriptionHit,
Title: "MediaStationGo 订阅命中新资源",
Message: "订阅:遮天\n新增资源:1",
Data: map[string]interface{}{
"media_category": "国漫",
"title": "遮天",
"original_title": "Shrouding the Heavens",
"original_language": "zh",
"year": 2023,
"rating": 8.6,
"genres": "动画,奇幻",
"overview": "荒古禁地中走出的少年。",
"tmdb_url": "https://www.themoviedb.org/tv/223911",
"imdb_url": "https://www.imdb.com/title/tt12345678/",
},
})
for _, want := range []string{
"#国漫",
"📺 中文片名:遮天",
"🧿 原始片名:Shrouding the Heavens",
"🌐 原始语言:中文",
"📅 发行年份:2023",
"⭐️ 评分:8.6",
"💎 类型:动画、奇幻",
"🪬 简介:",
`<a href="https://www.themoviedb.org/tv/223911">TMDB</a>`,
`<a href="https://www.imdb.com/title/tt12345678/">IMDB</a>`,
} {
if !strings.Contains(caption, want) {
t.Fatalf("caption missing %q:\n%s", want, caption)
}
}
}
+18 -2
View File
@@ -469,11 +469,27 @@ func (s *SubscriptionService) notifySubscriptionHit(sub *model.Subscription, que
if strings.TrimSpace(sub.MediaCategory) != "" {
data["media_category"] = sub.MediaCategory
}
// 补充媒体通知模板(formatTelegramMediaNotification)所需字段:片名 / 简介 /
// 外链 / 资源标题(供模板提取季集 + 版本)。仅填现成可用的,缺失项模板会自动略过。
// 补充媒体通知模板(formatTelegramMediaNotification)所需字段:片名 / 原名 /
// 语言 / 年份 / 评分 / 类型 / 简介 / 外链 / 资源标题(供模板提取季集 + 版本)。
// 仅填现成可用的,缺失项模板会自动略过。
if strings.TrimSpace(sub.Name) != "" {
data["title"] = sub.Name
}
if strings.TrimSpace(sub.OriginalName) != "" {
data["original_title"] = sub.OriginalName
}
if strings.TrimSpace(sub.OriginalLanguage) != "" {
data["original_language"] = sub.OriginalLanguage
}
if sub.Year > 0 {
data["year"] = sub.Year
}
if sub.Rating > 0 {
data["rating"] = sub.Rating
}
if strings.TrimSpace(sub.Genres) != "" {
data["genres"] = sub.Genres
}
if strings.TrimSpace(sub.Overview) != "" {
data["overview"] = sub.Overview
}