From dbfda120266acaf2ab57927dbf9e121590e635b8 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sat, 8 Mar 2025 18:52:35 -0800 Subject: [PATCH] Settings for poster and links --- src/NzbDrone.Core/Localization/Core/en.json | 4 ++ ...ramLink.cs => NotificationMetadataLink.cs} | 6 +-- .../NotificationMetadataLinkGenerator.cs | 45 +++++++++++++++++++ .../Notifications/Pushcut/Pushcut.cs | 28 ++++++------ .../Notifications/Pushcut/PushcutProxy.cs | 16 +++---- .../Notifications/Pushcut/PushcutSettings.cs | 7 +++ .../Notifications/Telegram/Telegram.cs | 42 +++-------------- .../Telegram/TelegramLinkPreviewOptions.cs | 2 +- .../Notifications/Telegram/TelegramProxy.cs | 8 ++-- 9 files changed, 90 insertions(+), 68 deletions(-) rename src/NzbDrone.Core/Notifications/{Telegram/TelegramLink.cs => NotificationMetadataLink.cs} (59%) create mode 100644 src/NzbDrone.Core/Notifications/NotificationMetadataLinkGenerator.cs diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 980df83fd..5f71b236a 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -1423,6 +1423,10 @@ "NotificationsPushBulletSettingsDeviceIds": "Device IDs", "NotificationsPushBulletSettingsDeviceIdsHelpText": "List of device IDs (leave blank to send to all devices)", "NotificationsPushcutSettingsApiKeyHelpText": "API Keys can be managed in the Account view of the Pushcut app", + "NotificationsPushcutSettingsIncludePoster": "Include Poster", + "NotificationsPushcutSettingsIncludePosterHelpText": "Include poster with notification", + "NotificationsPushcutSettingsMetadataLinks": "Metadata Links", + "NotificationsPushcutSettingsMetadataLinksHelpText": "Add a links to series metadata when sending notifications", "NotificationsPushcutSettingsNotificationName": "Notification Name", "NotificationsPushcutSettingsNotificationNameHelpText": "Notification name from Notifications tab of the Pushcut app", "NotificationsPushcutSettingsTimeSensitive": "Time Sensitive", diff --git a/src/NzbDrone.Core/Notifications/Telegram/TelegramLink.cs b/src/NzbDrone.Core/Notifications/NotificationMetadataLink.cs similarity index 59% rename from src/NzbDrone.Core/Notifications/Telegram/TelegramLink.cs rename to src/NzbDrone.Core/Notifications/NotificationMetadataLink.cs index 00cfd026e..d7cfad39c 100644 --- a/src/NzbDrone.Core/Notifications/Telegram/TelegramLink.cs +++ b/src/NzbDrone.Core/Notifications/NotificationMetadataLink.cs @@ -1,12 +1,12 @@ -namespace NzbDrone.Core.Notifications.Telegram +namespace NzbDrone.Core.Notifications { - public class TelegramLink + public class NotificationMetadataLink { public MetadataLinkType? Type { get; set; } public string Label { get; set; } public string Link { get; set; } - public TelegramLink(MetadataLinkType? type, string label, string link) + public NotificationMetadataLink(MetadataLinkType? type, string label, string link) { Type = type; Label = label; diff --git a/src/NzbDrone.Core/Notifications/NotificationMetadataLinkGenerator.cs b/src/NzbDrone.Core/Notifications/NotificationMetadataLinkGenerator.cs new file mode 100644 index 000000000..278b4153a --- /dev/null +++ b/src/NzbDrone.Core/Notifications/NotificationMetadataLinkGenerator.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Notifications; + +public static class NotificationMetadataLinkGenerator +{ + public static List GenerateLinks(Series series, IEnumerable metadataLinks) + { + var links = new List(); + + if (series == null) + { + return links; + } + + foreach (var link in metadataLinks) + { + var linkType = (MetadataLinkType)link; + + if (linkType == MetadataLinkType.Imdb && series.ImdbId.IsNotNullOrWhiteSpace()) + { + links.Add(new NotificationMetadataLink(MetadataLinkType.Imdb, "IMDb", $"https://www.imdb.com/title/{series.ImdbId}")); + } + + if (linkType == MetadataLinkType.Tvdb && series.TvdbId > 0) + { + links.Add(new NotificationMetadataLink(MetadataLinkType.Tvdb, "TVDb", $"http://www.thetvdb.com/?tab=series&id={series.TvdbId}")); + } + + if (linkType == MetadataLinkType.Trakt && series.TvdbId > 0) + { + links.Add(new NotificationMetadataLink(MetadataLinkType.Trakt, "Trakt", $"http://trakt.tv/search/tvdb/{series.TvdbId}?id_type=show")); + } + + if (linkType == MetadataLinkType.Tvmaze && series.TvMazeId > 0) + { + links.Add(new NotificationMetadataLink(MetadataLinkType.Tvmaze, "TVMaze", $"http://www.tvmaze.com/shows/{series.TvMazeId}/_")); + } + } + + return links; + } +} diff --git a/src/NzbDrone.Core/Notifications/Pushcut/Pushcut.cs b/src/NzbDrone.Core/Notifications/Pushcut/Pushcut.cs index 22c7bcea6..c6706b5a7 100644 --- a/src/NzbDrone.Core/Notifications/Pushcut/Pushcut.cs +++ b/src/NzbDrone.Core/Notifications/Pushcut/Pushcut.cs @@ -31,62 +31,62 @@ namespace NzbDrone.Core.Notifications.Pushcut public override void OnGrab(GrabMessage grabMessage) { - _proxy.SendNotification(EPISODE_GRABBED_TITLE, grabMessage?.Message, GetPosterUrl(grabMessage.Series), GetImdbLink(grabMessage.Series), Settings); + _proxy.SendNotification(EPISODE_GRABBED_TITLE, grabMessage?.Message, GetPosterUrl(grabMessage.Series), GetLinks(grabMessage.Series), Settings); } public override void OnDownload(DownloadMessage downloadMessage) { - _proxy.SendNotification(EPISODE_DOWNLOADED_TITLE, downloadMessage.Message, GetPosterUrl(downloadMessage.Series), GetImdbLink(downloadMessage.Series), Settings); + _proxy.SendNotification(EPISODE_DOWNLOADED_TITLE, downloadMessage.Message, GetPosterUrl(downloadMessage.Series), GetLinks(downloadMessage.Series), Settings); } public override void OnImportComplete(ImportCompleteMessage message) { - _proxy.SendNotification(IMPORT_COMPLETE_TITLE, message.Message, GetPosterUrl(message.Series), GetImdbLink(message.Series), Settings); + _proxy.SendNotification(IMPORT_COMPLETE_TITLE, message.Message, GetPosterUrl(message.Series), GetLinks(message.Series), Settings); } public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage) { - _proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, GetPosterUrl(deleteMessage.Series), GetImdbLink(deleteMessage.Series), Settings); + _proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, GetPosterUrl(deleteMessage.Series), GetLinks(deleteMessage.Series), Settings); } public override void OnSeriesAdd(SeriesAddMessage seriesAddMessage) { - _proxy.SendNotification(SERIES_ADDED_TITLE, $"{seriesAddMessage.Series.Title} added to library", GetPosterUrl(seriesAddMessage.Series), GetImdbLink(seriesAddMessage.Series), Settings); + _proxy.SendNotification(SERIES_ADDED_TITLE, $"{seriesAddMessage.Series.Title} added to library", GetPosterUrl(seriesAddMessage.Series), GetLinks(seriesAddMessage.Series), Settings); } public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage) { - _proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, GetPosterUrl(deleteMessage.Series), GetImdbLink(deleteMessage.Series), Settings); + _proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, GetPosterUrl(deleteMessage.Series), GetLinks(deleteMessage.Series), Settings); } public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { - _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, null, null, Settings); + _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, null, [], Settings); } public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck) { - _proxy.SendNotification(HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousCheck.Message}", null, null, Settings); + _proxy.SendNotification(HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousCheck.Message}", null, [], Settings); } public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) { - _proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, null, null, Settings); + _proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, null, [], Settings); } public override void OnManualInteractionRequired(ManualInteractionRequiredMessage manualInteractionRequiredMessage) { - _proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE_BRANDED, manualInteractionRequiredMessage.Message, null, null, Settings); + _proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE_BRANDED, manualInteractionRequiredMessage.Message, null, [], Settings); } - private string GetImdbLink(Series series) + private string GetPosterUrl(Series series) { - return $"https://www.imdb.com/title/{series.ImdbId}"; + return series.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.RemoteUrl; } - private string GetPosterUrl(Series series) + private List GetLinks(Series series) { - return series.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.RemoteUrl; + return NotificationMetadataLinkGenerator.GenerateLinks(series, Settings.MetadataLinks); } } } diff --git a/src/NzbDrone.Core/Notifications/Pushcut/PushcutProxy.cs b/src/NzbDrone.Core/Notifications/Pushcut/PushcutProxy.cs index b438ad354..6fc3e8e32 100644 --- a/src/NzbDrone.Core/Notifications/Pushcut/PushcutProxy.cs +++ b/src/NzbDrone.Core/Notifications/Pushcut/PushcutProxy.cs @@ -12,7 +12,7 @@ namespace NzbDrone.Core.Notifications.Pushcut { public interface IPushcutProxy { - void SendNotification(string title, string message, string posterUrl, string imdbLink, PushcutSettings settings); + void SendNotification(string title, string message, string posterUrl, List links, PushcutSettings settings); ValidationFailure Test(PushcutSettings settings); } @@ -29,7 +29,7 @@ namespace NzbDrone.Core.Notifications.Pushcut _logger = logger; } - public void SendNotification(string title, string message, string posterUrl, string imdbLink, PushcutSettings settings) + public void SendNotification(string title, string message, string posterUrl, List links, PushcutSettings settings) { var request = new HttpRequestBuilder("https://api.pushcut.io/v1/notifications/{notificationName}") .SetSegment("notificationName", settings?.NotificationName) @@ -45,15 +45,13 @@ namespace NzbDrone.Core.Notifications.Pushcut Actions = new List() }; - if (imdbLink.IsNotNullOrWhiteSpace()) + foreach (var link in links) { - var action = new PushcutAction + payload.Actions.Add(new PushcutAction { - Name = "IMDb", - Url = imdbLink - }; - - payload.Actions.Add(action); + Name = link.Label, + Url = link.Link + }); } request.Method = HttpMethod.Post; diff --git a/src/NzbDrone.Core/Notifications/Pushcut/PushcutSettings.cs b/src/NzbDrone.Core/Notifications/Pushcut/PushcutSettings.cs index 1bd49e46a..c8ece07b4 100644 --- a/src/NzbDrone.Core/Notifications/Pushcut/PushcutSettings.cs +++ b/src/NzbDrone.Core/Notifications/Pushcut/PushcutSettings.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using FluentValidation; using NzbDrone.Core.Annotations; using NzbDrone.Core.Validation; @@ -26,6 +27,12 @@ namespace NzbDrone.Core.Notifications.Pushcut [FieldDefinition(2, Label = "NotificationsPushcutSettingsTimeSensitive", Type = FieldType.Checkbox, HelpText = "NotificationsPushcutSettingsTimeSensitiveHelpText")] public bool TimeSensitive { get; set; } + [FieldDefinition(3, Label = "NotificationsPushcutSettingsIncludePoster", Type = FieldType.Checkbox, HelpText = "NotificationsPushcutSettingsIncludePosterHelpText")] + public bool IncludePoster { get; set; } + + [FieldDefinition(4, Label = "NotificationsPushcutSettingsMetadataLinks", Type = FieldType.Select, SelectOptions = typeof(MetadataLinkType), HelpText = "NotificationsPushcutSettingsMetadataLinksHelpText")] + public IEnumerable MetadataLinks { get; set; } = []; + public override NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this)); diff --git a/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs b/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs index 17d429f2b..04ada04aa 100644 --- a/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs +++ b/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs @@ -81,7 +81,7 @@ namespace NzbDrone.Core.Notifications.Telegram var title = Settings.IncludeAppNameInTitle ? HEALTH_ISSUE_TITLE_BRANDED : HEALTH_ISSUE_TITLE; title = Settings.IncludeInstanceNameInTitle ? $"{title} - {InstanceName}" : title; - _proxy.SendNotification(title, healthCheck.Message, new List(), Settings); + _proxy.SendNotification(title, healthCheck.Message, new List(), Settings); } public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck) @@ -89,7 +89,7 @@ namespace NzbDrone.Core.Notifications.Telegram var title = Settings.IncludeAppNameInTitle ? HEALTH_RESTORED_TITLE_BRANDED : HEALTH_RESTORED_TITLE; title = Settings.IncludeInstanceNameInTitle ? $"{title} - {InstanceName}" : title; - _proxy.SendNotification(title, $"The following issue is now resolved: {previousCheck.Message}", new List(), Settings); + _proxy.SendNotification(title, $"The following issue is now resolved: {previousCheck.Message}", new List(), Settings); } public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) @@ -97,7 +97,7 @@ namespace NzbDrone.Core.Notifications.Telegram var title = Settings.IncludeAppNameInTitle ? APPLICATION_UPDATE_TITLE_BRANDED : APPLICATION_UPDATE_TITLE; title = Settings.IncludeInstanceNameInTitle ? $"{title} - {InstanceName}" : title; - _proxy.SendNotification(title, updateMessage.Message, new List(), Settings); + _proxy.SendNotification(title, updateMessage.Message, new List(), Settings); } public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message) @@ -118,41 +118,9 @@ namespace NzbDrone.Core.Notifications.Telegram return new ValidationResult(failures); } - private List GetLinks(Series series) + private List GetLinks(Series series) { - var links = new List(); - - if (series == null) - { - return links; - } - - foreach (var link in Settings.MetadataLinks) - { - var linkType = (MetadataLinkType)link; - - if (linkType == MetadataLinkType.Imdb && series.ImdbId.IsNotNullOrWhiteSpace()) - { - links.Add(new TelegramLink(MetadataLinkType.Imdb, "IMDb", $"https://www.imdb.com/title/{series.ImdbId}")); - } - - if (linkType == MetadataLinkType.Tvdb && series.TvdbId > 0) - { - links.Add(new TelegramLink(MetadataLinkType.Tvdb, "TVDb", $"http://www.thetvdb.com/?tab=series&id={series.TvdbId}")); - } - - if (linkType == MetadataLinkType.Trakt && series.TvdbId > 0) - { - links.Add(new TelegramLink(MetadataLinkType.Trakt, "Trakt", $"http://trakt.tv/search/tvdb/{series.TvdbId}?id_type=show")); - } - - if (linkType == MetadataLinkType.Tvmaze && series.TvMazeId > 0) - { - links.Add(new TelegramLink(MetadataLinkType.Tvmaze, "TVMaze", $"http://www.tvmaze.com/shows/{series.TvMazeId}/_")); - } - } - - return links; + return NotificationMetadataLinkGenerator.GenerateLinks(series, Settings.MetadataLinks); } } } diff --git a/src/NzbDrone.Core/Notifications/Telegram/TelegramLinkPreviewOptions.cs b/src/NzbDrone.Core/Notifications/Telegram/TelegramLinkPreviewOptions.cs index 45b421107..7d50115ce 100644 --- a/src/NzbDrone.Core/Notifications/Telegram/TelegramLinkPreviewOptions.cs +++ b/src/NzbDrone.Core/Notifications/Telegram/TelegramLinkPreviewOptions.cs @@ -12,7 +12,7 @@ public class TelegramLinkPreviewOptions [JsonProperty("url")] public string Url { get; set; } - public TelegramLinkPreviewOptions(List links, TelegramSettings settings) + public TelegramLinkPreviewOptions(List links, TelegramSettings settings) { IsDisabled = (MetadataLinkPreviewType)settings.LinkPreview == MetadataLinkPreviewType.None; Url = links.FirstOrDefault(l => l.Type.HasValue && (int)l.Type.Value == settings.LinkPreview)?.Link; diff --git a/src/NzbDrone.Core/Notifications/Telegram/TelegramProxy.cs b/src/NzbDrone.Core/Notifications/Telegram/TelegramProxy.cs index c83050992..972a23ed7 100644 --- a/src/NzbDrone.Core/Notifications/Telegram/TelegramProxy.cs +++ b/src/NzbDrone.Core/Notifications/Telegram/TelegramProxy.cs @@ -15,7 +15,7 @@ namespace NzbDrone.Core.Notifications.Telegram { public interface ITelegramProxy { - void SendNotification(string title, string message, List links, TelegramSettings settings); + void SendNotification(string title, string message, List links, TelegramSettings settings); ValidationFailure Test(TelegramSettings settings); } @@ -36,7 +36,7 @@ namespace NzbDrone.Core.Notifications.Telegram _logger = logger; } - public void SendNotification(string title, string message, List links, TelegramSettings settings) + public void SendNotification(string title, string message, List links, TelegramSettings settings) { var text = new StringBuilder($"{HttpUtility.HtmlEncode(title)}\n"); @@ -77,9 +77,9 @@ namespace NzbDrone.Core.Notifications.Telegram const string title = "Test Notification"; const string body = "This is a test message from Sonarr"; - var links = new List + var links = new List { - new TelegramLink(null, "Sonarr.tv", "https://sonarr.tv") + new NotificationMetadataLink(null, "Sonarr.tv", "https://sonarr.tv") }; var testMessageTitle = settings.IncludeAppNameInTitle ? brandedTitle : title;