From e57e68c97a9d24f8344623ac8f731c2da220686b Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 22 Dec 2022 23:47:05 -0800 Subject: [PATCH] New: Option to include series image for Gotify notifications Closes #4882 --- .../Notifications/Gotify/Gotify.cs | 77 ++++++++++++++++--- .../Notifications/Gotify/GotifyMessage.cs | 40 ++++++++++ .../Notifications/Gotify/GotifyProxy.cs | 21 +++-- .../Notifications/Gotify/GotifySettings.cs | 3 + 4 files changed, 121 insertions(+), 20 deletions(-) create mode 100644 src/NzbDrone.Core/Notifications/Gotify/GotifyMessage.cs diff --git a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs index 7de40ce31..4c6b9ad22 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs @@ -1,7 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Text; using FluentValidation.Results; using NLog; +using NzbDrone.Core.MediaCover; +using NzbDrone.Core.Tv; namespace NzbDrone.Core.Notifications.Gotify { @@ -19,34 +23,34 @@ namespace NzbDrone.Core.Notifications.Gotify public override string Name => "Gotify"; public override string Link => "https://gotify.net/"; - public override void OnGrab(GrabMessage grabMessage) + public override void OnGrab(GrabMessage message) { - _proxy.SendNotification(EPISODE_GRABBED_TITLE, grabMessage.Message, Settings); + SendNotification(EPISODE_GRABBED_TITLE, message.Message, message.Series); } public override void OnDownload(DownloadMessage message) { - _proxy.SendNotification(EPISODE_DOWNLOADED_TITLE, message.Message, Settings); + SendNotification(EPISODE_DOWNLOADED_TITLE, message.Message, message.Series); } - public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage) + public override void OnEpisodeFileDelete(EpisodeDeleteMessage message) { - _proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings); + SendNotification(EPISODE_DELETED_TITLE, message.Message, message.Series); } - public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage) + public override void OnSeriesDelete(SeriesDeleteMessage message) { - _proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings); + SendNotification(SERIES_DELETED_TITLE, message.Message, message.Series); } public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { - _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); + SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, null); } - public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) + public override void OnApplicationUpdate(ApplicationUpdateMessage message) { - _proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings); + SendNotification(APPLICATION_UPDATE_TITLE, message.Message, null); } public override ValidationResult Test() @@ -55,10 +59,29 @@ namespace NzbDrone.Core.Notifications.Gotify try { + var isMarkdown = false; const string title = "Test Notification"; - const string body = "This is a test message from Sonarr"; - _proxy.SendNotification(title, body, Settings); + var sb = new StringBuilder(); + sb.AppendLine("This is a test message from Sonarr"); + + if (Settings.IncludeSeriesPoster) + { + isMarkdown = true; + + sb.AppendLine("\r![](https://raw.githubusercontent.com/Sonarr/Sonarr/develop/Logo/128.png)"); + } + + var payload = new GotifyMessage + { + Title = title, + Message = sb.ToString(), + Priority = Settings.Priority + }; + + payload.SetContentType(isMarkdown); + + _proxy.SendNotification(payload, Settings); } catch (Exception ex) { @@ -68,5 +91,35 @@ namespace NzbDrone.Core.Notifications.Gotify return new ValidationResult(failures); } + + private void SendNotification(string title, string message, Series series) + { + var isMarkdown = false; + var sb = new StringBuilder(); + + sb.AppendLine(message); + + if (Settings.IncludeSeriesPoster && series != null) + { + var poster = series.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.Url; + + if (poster != null) + { + isMarkdown = true; + sb.AppendLine($"\r![]({poster})"); + } + } + + var payload = new GotifyMessage + { + Title = title, + Message = sb.ToString(), + Priority = Settings.Priority + }; + + 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 new file mode 100644 index 000000000..170ce1367 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Gotify/GotifyMessage.cs @@ -0,0 +1,40 @@ +using Newtonsoft.Json; + +namespace NzbDrone.Core.Notifications.Gotify +{ + public class GotifyMessage + { + public string Title { get; set; } + public string Message { get; set; } + public int Priority { get; set; } + public GotifyExtras Extras { get; set; } + + public GotifyMessage() + { + Extras = new GotifyExtras(); + } + + public void SetContentType(bool isMarkdown) + { + var contentType = isMarkdown ? "text/markdown" : "text/plain"; + + Extras.ClientDisplay = new GotifyClientDisplay(contentType); + } + } + + public class GotifyExtras + { + [JsonProperty("client::display")] + public GotifyClientDisplay ClientDisplay { get; set; } + } + + public class GotifyClientDisplay + { + public string ContentType { get; set; } + + public GotifyClientDisplay(string contentType) + { + ContentType = contentType; + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Gotify/GotifyProxy.cs b/src/NzbDrone.Core/Notifications/Gotify/GotifyProxy.cs index ab1130ab6..30eef6bd9 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/GotifyProxy.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/GotifyProxy.cs @@ -1,11 +1,12 @@ using System.Net; using NzbDrone.Common.Http; +using NzbDrone.Common.Serializer; namespace NzbDrone.Core.Notifications.Gotify { public interface IGotifyProxy { - void SendNotification(string title, string message, GotifySettings settings); + void SendNotification(GotifyMessage payload, GotifySettings settings); } public class GotifyProxy : IGotifyProxy @@ -17,16 +18,20 @@ namespace NzbDrone.Core.Notifications.Gotify _httpClient = httpClient; } - public void SendNotification(string title, string message, GotifySettings settings) + public void SendNotification(GotifyMessage payload, GotifySettings settings) { try { - var request = new HttpRequestBuilder(settings.Server).Resource("message").Post() - .AddQueryParam("token", settings.AppToken) - .AddFormParameter("title", title) - .AddFormParameter("message", message) - .AddFormParameter("priority", settings.Priority) - .Build(); + var request = new HttpRequestBuilder(settings.Server) + .Resource("message") + .Post() + .AddQueryParam("token", settings.AppToken) + .Build(); + + request.Headers.ContentType = "application/json"; + + var json = payload.ToJson(); + request.SetContent(payload.ToJson()); _httpClient.Execute(request); } diff --git a/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs b/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs index 7c5021e58..48f4aa7e8 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs @@ -32,6 +32,9 @@ namespace NzbDrone.Core.Notifications.Gotify [FieldDefinition(2, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(GotifyPriority), HelpText = "Priority of the notification")] public int Priority { get; set; } + [FieldDefinition(3, Label = "Include Series Poster", Type = FieldType.Checkbox, HelpText = "Include series poster in message")] + public bool IncludeSeriesPoster { get; set; } + public NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this));