diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 9aecc80ef..364ffe5c2 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -1347,6 +1347,10 @@ "NotificationsGotifySettingsAppToken": "App Token", "NotificationsGotifySettingsAppTokenHelpText": "The Application Token generated by Gotify", "NotificationsGotifySettingsPriorityHelpText": "Priority of the notification", + "NotificationsGotifySettingsMetadataLinks": "Metadata Links", + "NotificationsGotifySettingsMetadataLinksHelpText": "Add a links to series metadata when sending notifications", + "NotificationsGotifySettingsPreferredMetadataLink": "Preferred Metadata Link", + "NotificationsGotifySettingsPreferredMetadataLinkHelpText": "Metadata link for clients that only support a single link", "NotificationsGotifySettingsServer": "Gotify Server", "NotificationsGotifySettingsServerHelpText": "Gotify server URL, including http(s):// and port if needed", "NotificationsJoinSettingsApiKeyHelpText": "The API Key from your Join account settings (click Join API button).", diff --git a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs index 47060065c..83b3568bd 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs @@ -4,6 +4,7 @@ using System.Text; using FluentValidation.Results; using NLog; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Localization; using NzbDrone.Core.MediaCover; using NzbDrone.Core.Tv; @@ -12,6 +13,8 @@ namespace NzbDrone.Core.Notifications.Gotify { public class Gotify : NotificationBase { + private const string SonarrImageUrl = "https://raw.githubusercontent.com/Sonarr/Sonarr/develop/Logo/128.png"; + private readonly IGotifyProxy _proxy; private readonly ILocalizationService _localizationService; private readonly Logger _logger; @@ -88,20 +91,30 @@ public override ValidationResult Test() var sb = new StringBuilder(); sb.AppendLine("This is a test message from Sonarr"); + var payload = new GotifyMessage + { + Title = title, + Priority = Settings.Priority + }; + if (Settings.IncludeSeriesPoster) { isMarkdown = true; - sb.AppendLine("\r![](https://raw.githubusercontent.com/Sonarr/Sonarr/develop/Logo/128.png)"); + sb.AppendLine($"\r![]({SonarrImageUrl})"); + payload.SetImage(SonarrImageUrl); } - var payload = new GotifyMessage + if (Settings.MetadataLinks.Any()) { - Title = title, - Message = sb.ToString(), - Priority = Settings.Priority - }; + isMarkdown = true; + sb.AppendLine(""); + sb.AppendLine("[Sonarr.tv](https://sonarr.tv)"); + payload.SetClickUrl("https://sonarr.tv"); + } + + payload.Message = sb.ToString(); payload.SetContentType(isMarkdown); _proxy.SendNotification(payload, Settings); @@ -122,24 +135,72 @@ private void SendNotification(string title, string message, Series series) sb.AppendLine(message); - if (Settings.IncludeSeriesPoster && series != null) - { - var poster = series.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.RemoteUrl; - - if (poster != null) - { - isMarkdown = true; - sb.AppendLine($"\r![]({poster})"); - } - } - var payload = new GotifyMessage { Title = title, - Message = sb.ToString(), Priority = Settings.Priority }; + if (series != null) + { + if (Settings.IncludeSeriesPoster) + { + var poster = series.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.RemoteUrl; + + if (poster != null) + { + isMarkdown = true; + sb.AppendLine($"\r![]({poster})"); + payload.SetImage(poster); + } + } + + if (Settings.MetadataLinks.Any()) + { + isMarkdown = true; + sb.AppendLine(""); + + foreach (var link in Settings.MetadataLinks) + { + var linkType = (MetadataLinkType)link; + var linkText = ""; + var linkUrl = ""; + + if (linkType == MetadataLinkType.Imdb && series.ImdbId.IsNotNullOrWhiteSpace()) + { + linkText = "IMDb"; + linkUrl = $"https://www.imdb.com/title/{series.ImdbId}"; + } + + if (linkType == MetadataLinkType.Tvdb && series.TvdbId > 0) + { + linkText = "TVDb"; + linkUrl = $"http://www.thetvdb.com/?tab=series&id={series.TvdbId}"; + } + + if (linkType == MetadataLinkType.Trakt && series.TvdbId > 0) + { + linkText = "TVMaze"; + linkUrl = $"http://trakt.tv/search/tvdb/{series.TvdbId}?id_type=show"; + } + + if (linkType == MetadataLinkType.Tvmaze && series.TvMazeId > 0) + { + linkText = "Trakt"; + linkUrl = $"http://www.tvmaze.com/shows/{series.TvMazeId}/_"; + } + + sb.AppendLine($"[{linkText}]({linkUrl})"); + + if (link == Settings.PreferredMetadataLink) + { + payload.SetClickUrl(linkUrl); + } + } + } + } + + payload.Message = sb.ToString(); payload.SetContentType(isMarkdown); _proxy.SendNotification(payload, Settings); diff --git a/src/NzbDrone.Core/Notifications/Gotify/GotifyMessage.cs b/src/NzbDrone.Core/Notifications/Gotify/GotifyMessage.cs index 170ce1367..576294946 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/GotifyMessage.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/GotifyMessage.cs @@ -20,12 +20,27 @@ public void SetContentType(bool isMarkdown) Extras.ClientDisplay = new GotifyClientDisplay(contentType); } + + public void SetImage(string imageUrl) + { + Extras.ClientNotification ??= new GotifyClientNotification(); + Extras.ClientNotification.BigImageUrl = imageUrl; + } + + public void SetClickUrl(string url) + { + Extras.ClientNotification ??= new GotifyClientNotification(); + Extras.ClientNotification.Click = new GotifyClientNotificationClick(url); + } } public class GotifyExtras { [JsonProperty("client::display")] public GotifyClientDisplay ClientDisplay { get; set; } + + [JsonProperty("client::notification")] + public GotifyClientNotification ClientNotification { get; set; } } public class GotifyClientDisplay @@ -37,4 +52,20 @@ public GotifyClientDisplay(string contentType) ContentType = contentType; } } + + public class GotifyClientNotification + { + public string BigImageUrl { get; set; } + public GotifyClientNotificationClick Click { get; set; } + } + + public class GotifyClientNotificationClick + { + public string Url { get; set; } + + public GotifyClientNotificationClick(string url) + { + Url = url; + } + } } diff --git a/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs b/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs index b152ef5fe..94efd379f 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs @@ -1,4 +1,8 @@ +using System; +using System.Collections.Generic; +using System.Linq; using FluentValidation; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Annotations; using NzbDrone.Core.Validation; @@ -10,6 +14,30 @@ public GotifySettingsValidator() { RuleFor(c => c.Server).IsValidUrl(); RuleFor(c => c.AppToken).NotEmpty(); + + RuleFor(c => c.MetadataLinks).Custom((links, context) => + { + foreach (var link in links) + { + if (!Enum.IsDefined(typeof(MetadataLinkType), link)) + { + context.AddFailure("MetadataLinks", $"MetadataLink is not valid: {link}"); + } + } + }); + + RuleFor(c => c).Custom((c, context) => + { + if (c.MetadataLinks.Empty()) + { + return; + } + + if (!c.MetadataLinks.Contains(c.PreferredMetadataLink)) + { + context.AddFailure("PreferredMetadataLink", "Must be a selected link"); + } + }); } } @@ -20,6 +48,8 @@ public class GotifySettings : NotificationSettingsBase public GotifySettings() { Priority = 5; + MetadataLinks = Enumerable.Empty(); + PreferredMetadataLink = (int)MetadataLinkType.Tvdb; } [FieldDefinition(0, Label = "NotificationsGotifySettingsServer", HelpText = "NotificationsGotifySettingsServerHelpText")] @@ -34,6 +64,12 @@ public GotifySettings() [FieldDefinition(3, Label = "NotificationsGotifySettingIncludeSeriesPoster", Type = FieldType.Checkbox, HelpText = "NotificationsGotifySettingIncludeSeriesPosterHelpText")] public bool IncludeSeriesPoster { get; set; } + [FieldDefinition(4, Label = "NotificationsGotifySettingsMetadataLinks", Type = FieldType.Select, SelectOptions = typeof(MetadataLinkType), HelpText = "NotificationsGotifySettingsMetadataLinksHelpText")] + public IEnumerable MetadataLinks { get; set; } + + [FieldDefinition(5, Label = "NotificationsGotifySettingsPreferredMetadataLink", Type = FieldType.Select, SelectOptions = typeof(MetadataLinkType), HelpText = "NotificationsGotifySettingsPreferredMetadataLinkHelpText")] + public int PreferredMetadataLink { get; set; } + public override NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this)); diff --git a/src/NzbDrone.Core/Notifications/MetadataLinkType.cs b/src/NzbDrone.Core/Notifications/MetadataLinkType.cs new file mode 100644 index 000000000..0a6644bd7 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/MetadataLinkType.cs @@ -0,0 +1,19 @@ +using NzbDrone.Core.Annotations; + +namespace NzbDrone.Core.Notifications +{ + public enum MetadataLinkType + { + [FieldOption(Label = "IMDb")] + Imdb = 0, + + [FieldOption(Label = "TVDb")] + Tvdb = 1, + + [FieldOption(Label = "TVMaze")] + Tvmaze = 2, + + [FieldOption(Label = "Trakt")] + Trakt = 3 + } +} diff --git a/src/NzbDrone.Core/Notifications/Telegram/TelegramSettings.cs b/src/NzbDrone.Core/Notifications/Telegram/TelegramSettings.cs index 6ec3d4d15..ac39a1b45 100644 --- a/src/NzbDrone.Core/Notifications/Telegram/TelegramSettings.cs +++ b/src/NzbDrone.Core/Notifications/Telegram/TelegramSettings.cs @@ -59,19 +59,4 @@ public override NzbDroneValidationResult Validate() return new NzbDroneValidationResult(Validator.Validate(this)); } } - - public enum MetadataLinkType - { - [FieldOption(Label = "IMDb")] - Imdb, - - [FieldOption(Label = "TVDb")] - Tvdb, - - [FieldOption(Label = "TVMaze")] - Tvmaze, - - [FieldOption(Label = "Trakt")] - Trakt, - } }