From 5455d4d2e46e476a6f280174ed3a69a326d537df Mon Sep 17 00:00:00 2001 From: ShukeBta <272197458+ShukeBta@users.noreply.github.com> Date: Sat, 27 Jun 2026 18:08:04 +0800 Subject: [PATCH] fix download notification privacy --- internal/service/download_notification.go | 3 +- internal/service/downloads_view_test.go | 6 ++- internal/service/notify_channels_test.go | 50 +++++++++++++++-------- internal/service/notify_telegram_media.go | 15 +++++++ 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/internal/service/download_notification.go b/internal/service/download_notification.go index 2288bdd..dac1120 100644 --- a/internal/service/download_notification.go +++ b/internal/service/download_notification.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" "path/filepath" "strings" "time" @@ -33,7 +32,7 @@ func (d *DownloadService) notifyDownloadComplete(ctx context.Context, torrent QB func downloadCompleteNotificationPayload(torrent QBitTorrent, task *model.DownloadTask) (string, map[string]interface{}) { name := downloadCompleteNotificationName(torrent, task) - body := fmt.Sprintf("任务:%s\n保存路径:%s\nHash:%s", name, firstNonEmpty(torrent.ContentPath, torrent.SavePath), torrent.Hash) + body := "任务:" + name data := downloadCompleteNotificationData(torrent, task) return body, data } diff --git a/internal/service/downloads_view_test.go b/internal/service/downloads_view_test.go index 747ca79..00168ab 100644 --- a/internal/service/downloads_view_test.go +++ b/internal/service/downloads_view_test.go @@ -58,8 +58,10 @@ func TestDownloadCompleteNotificationPayloadUsesTaskMetadata(t *testing.T) { if !strings.Contains(body, "任务:正式标题") { t.Fatalf("body should prefer task title, got %q", body) } - if !strings.Contains(body, "保存路径:/downloads/show/Release.Name.S01E02.1080p.mkv") { - t.Fatalf("body should include content path, got %q", body) + for _, private := range []string{"保存路径", "/downloads/show", "Hash", "done123"} { + if strings.Contains(body, private) { + t.Fatalf("body should not expose %q, got %q", private, body) + } } for key, want := range map[string]interface{}{ "resource_title": "Release.Name.S01E02.1080p", diff --git a/internal/service/notify_channels_test.go b/internal/service/notify_channels_test.go index f007085..83a75a0 100644 --- a/internal/service/notify_channels_test.go +++ b/internal/service/notify_channels_test.go @@ -101,27 +101,45 @@ func TestTelegramDispatchUsesPhotoAndFormattedCaption(t *testing.T) { } caption := gotForm["caption"] for _, want := range []string{ - "🐈‍⬛🐈‍⬛ MediaStationGo 更新啦 🐈‍⬛🐈‍⬛", - "--------------------------------", - "#剧集", - "📺 中文片名:美国甜心:达拉斯牛仔啦啦队", - "🧿 原始片名:AMERICA'S SWEETHEARTS: Dallas Cowboys Cheerleaders", - "🌐 原始语言:英语", - "📅 发行年份:2024", - "🐈‍⬛ 类别:纪录片剧集", - "🫧 季集:S03E07", - "🔎 大小:3.0GB / 5.7Mbps", - "📁 版本:H264.NF.FHD-HHWEB", - "⭐️ 评分:8.2", - "💎 类型:纪录", - "🪬 简介:", - `🔗 外链:TMDB / IMDB / 豆瓣`, + "#下载完成", + "📺 任务:示例影片", } { if !strings.Contains(caption, want) { t.Fatalf("caption missing %q: %s", want, caption) } } - for _, unwanted := range []string{"✅ 下载完成", "🎯 订阅命中新资源", "保存路径", "abcdef"} { + for _, unwanted := range []string{ + "✅ 下载完成", + "🎯 订阅命中新资源", + "保存路径", + "abcdef", + "美国甜心:达拉斯牛仔啦啦队", + "AMERICA'S SWEETHEARTS", + "2024", + "3.0GB", + "简介", + server.URL + "/tmdb", + } { + if strings.Contains(caption, unwanted) { + t.Fatalf("caption should not include %q: %s", unwanted, caption) + } + } +} + +func TestTelegramDownloadCompleteNeverFallsBackToSensitiveFields(t *testing.T) { + caption := formatTelegramNotification(NotifyEvent{ + Type: EventDownloadComplete, + Data: map[string]interface{}{ + "save_path": "/downloads/private/movie.mkv", + "hash": "abcdef", + }, + }) + for _, want := range []string{"#下载完成", "📺 任务:下载任务"} { + if !strings.Contains(caption, want) { + t.Fatalf("caption missing %q: %s", want, caption) + } + } + for _, unwanted := range []string{"保存路径", "/downloads/private", "Hash", "abcdef"} { if strings.Contains(caption, unwanted) { t.Fatalf("caption should not include %q: %s", unwanted, caption) } diff --git a/internal/service/notify_telegram_media.go b/internal/service/notify_telegram_media.go index a0be82e..fccc22b 100644 --- a/internal/service/notify_telegram_media.go +++ b/internal/service/notify_telegram_media.go @@ -13,6 +13,10 @@ const ( var telegramSeasonEpisodePattern = regexp.MustCompile(`(?i)S\d{1,2}E\d{1,3}(?:[\-.~_ ]?E?\d{1,3})?`) func formatTelegramMediaNotification(event NotifyEvent) string { + if strings.TrimSpace(event.Type) == EventDownloadComplete { + return formatTelegramDownloadCompleteNotification(event) + } + tag := telegramMediaTag(event.Data) if tag == "" { return "" @@ -97,6 +101,17 @@ func formatTelegramMediaNotification(event NotifyEvent) string { return strings.TrimSpace(strings.Join(lines, "\n")) } +func formatTelegramDownloadCompleteNotification(event NotifyEvent) string { + title := telegramMessageFieldValue(event.Message, "任务", "媒体", "资源") + if title == "" { + title = telegramFirstValue(event.Data, "title", "name", "media_title", "chinese_title", "resource_title") + } + if title == "" { + title = "下载任务" + } + return "#下载完成\n📺 任务:" + escapeHTML(title) +} + func telegramMediaTag(data map[string]interface{}) string { for _, key := range []string{"media_category", "category", "media_type"} { value := strings.TrimSpace(telegramDataString(data, key))