From 4189bc6f76347aee00db4449dba142ae04961e0a Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 28 Jun 2017 14:13:50 -0700 Subject: [PATCH] Webhook improvements New: Include Path/Relative Path for on download Webhooks New: IsUpgrade flag for on download Webhooks --- .../Notifications/Webhook/Webhook.cs | 95 ++++++++++++-- .../Webhook/WebhookEpisodeFile.cs | 28 +++++ .../Webhook/WebhookGrabPayload.cs | 10 ++ .../Webhook/WebhookImportPayload.cs | 11 ++ .../Notifications/Webhook/WebhookMethod.cs | 8 +- .../Notifications/Webhook/WebhookPayload.cs | 5 +- .../Notifications/Webhook/WebhookProxy.cs | 41 ++++++ .../Notifications/Webhook/WebhookRelease.cs | 27 ++++ .../Notifications/Webhook/WebhookService.cs | 118 ------------------ src/NzbDrone.Core/NzbDrone.Core.csproj | 6 +- 10 files changed, 214 insertions(+), 135 deletions(-) create mode 100644 src/NzbDrone.Core/Notifications/Webhook/WebhookEpisodeFile.cs create mode 100644 src/NzbDrone.Core/Notifications/Webhook/WebhookGrabPayload.cs create mode 100644 src/NzbDrone.Core/Notifications/Webhook/WebhookImportPayload.cs create mode 100644 src/NzbDrone.Core/Notifications/Webhook/WebhookProxy.cs create mode 100644 src/NzbDrone.Core/Notifications/Webhook/WebhookRelease.cs delete mode 100644 src/NzbDrone.Core/Notifications/Webhook/WebhookService.cs diff --git a/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs b/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs index 4bfcb867c..49037b701 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs @@ -1,35 +1,77 @@ - -using System.Collections.Generic; +using System.Collections.Generic; +using System.Linq; using FluentValidation.Results; using NzbDrone.Core.Tv; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Validation; namespace NzbDrone.Core.Notifications.Webhook { public class Webhook : NotificationBase { - private readonly IWebhookService _service; + private readonly IWebhookProxy _proxy; - public Webhook(IWebhookService service) + public Webhook(IWebhookProxy proxy) { - _service = service; + _proxy = proxy; } public override string Link => "https://github.com/Sonarr/Sonarr/wiki/Webhook"; public override void OnGrab(GrabMessage message) { - _service.OnGrab(message.Series, message.Episode, message.Quality, Settings); + var remoteEpisode = message.Episode; + var quality = message.Quality; + + var payload = new WebhookGrabPayload + { + EventType = "Grab", + Series = new WebhookSeries(message.Series), + Episodes = remoteEpisode.Episodes.ConvertAll(x => new WebhookEpisode(x) + { + // TODO: Stop passing these parameters inside an episode v3 + Quality = quality.Quality.Name, + QualityVersion = quality.Revision.Version, + ReleaseGroup = remoteEpisode.ParsedEpisodeInfo.ReleaseGroup + }), + Release = new WebhookRelease(quality, remoteEpisode) + }; + + _proxy.SendWebhook(payload, Settings); } public override void OnDownload(DownloadMessage message) { - _service.OnDownload(message.Series, message.EpisodeFile, Settings); + var episodeFile = message.EpisodeFile; + + var payload = new WebhookImportPayload + { + EventType = "Download", + Series = new WebhookSeries(message.Series), + Episodes = episodeFile.Episodes.Value.ConvertAll(x => new WebhookEpisode(x) + { + // TODO: Stop passing these parameters inside an episode v3 + Quality = episodeFile.Quality.Quality.Name, + QualityVersion = episodeFile.Quality.Revision.Version, + ReleaseGroup = episodeFile.ReleaseGroup, + SceneName = episodeFile.SceneName + }), + EpisodeFile = new WebhookEpisodeFile(episodeFile), + IsUpgrade = message.OldFiles.Any() + }; + + _proxy.SendWebhook(payload, Settings); } public override void OnRename(Series series) { - _service.OnRename(series, Settings); + var payload = new WebhookPayload + { + EventType = "Rename", + Series = new WebhookSeries(series) + }; + + _proxy.SendWebhook(payload, Settings); } public override string Name => "Webhook"; @@ -38,9 +80,44 @@ public override ValidationResult Test() { var failures = new List(); - failures.AddIfNotNull(_service.Test(Settings)); + failures.AddIfNotNull(SendWebhookTest()); return new ValidationResult(failures); } + + private ValidationFailure SendWebhookTest() + { + try + { + var payload = new WebhookGrabPayload + { + EventType = "Test", + Series = new WebhookSeries() + { + Id = 1, + Title = "Test Title", + Path = "C:\\testpath", + TvdbId = 1234 + }, + Episodes = new List() { + new WebhookEpisode() + { + Id = 123, + EpisodeNumber = 1, + SeasonNumber = 1, + Title = "Test title" + } + } + }; + + _proxy.SendWebhook(payload, Settings); + } + catch (WebhookException ex) + { + return new NzbDroneValidationFailure("Url", ex.Message); + } + + return null; + } } } diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookEpisodeFile.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookEpisodeFile.cs new file mode 100644 index 000000000..ad2779538 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookEpisodeFile.cs @@ -0,0 +1,28 @@ +using NzbDrone.Core.MediaFiles; + +namespace NzbDrone.Core.Notifications.Webhook +{ + public class WebhookEpisodeFile + { + public WebhookEpisodeFile() { } + + public WebhookEpisodeFile(EpisodeFile episodeFile) + { + Id = episodeFile.Id; + RelativePath = episodeFile.RelativePath; + Path = episodeFile.Path; + Quality = episodeFile.Quality.Quality.Name; + QualityVersion = episodeFile.Quality.Revision.Version; + ReleaseGroup = episodeFile.ReleaseGroup; + SceneName = episodeFile.SceneName; + } + + public int Id { get; set; } + public string RelativePath { get; set; } + public string Path { get; set; } + public string Quality { get; set; } + public int QualityVersion { get; set; } + public string ReleaseGroup { get; set; } + public string SceneName { get; set; } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookGrabPayload.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookGrabPayload.cs new file mode 100644 index 000000000..2498f9c96 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookGrabPayload.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace NzbDrone.Core.Notifications.Webhook +{ + public class WebhookGrabPayload : WebhookPayload + { + public List Episodes { get; set; } + public WebhookRelease Release { get; set; } + } +} diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookImportPayload.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookImportPayload.cs new file mode 100644 index 000000000..bc765b8dc --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookImportPayload.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace NzbDrone.Core.Notifications.Webhook +{ + public class WebhookImportPayload : WebhookPayload + { + public List Episodes { get; set; } + public WebhookEpisodeFile EpisodeFile { get; set; } + public bool IsUpgrade { get; set; } + } +} diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookMethod.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookMethod.cs index 42c080e00..a3d27a575 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookMethod.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookMethod.cs @@ -1,8 +1,10 @@ -namespace NzbDrone.Core.Notifications.Webhook +using NzbDrone.Common.Http; + +namespace NzbDrone.Core.Notifications.Webhook { public enum WebhookMethod { - POST = RestSharp.Method.POST, - PUT = RestSharp.Method.PUT + POST = HttpMethod.POST, + PUT = HttpMethod.PUT } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookPayload.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookPayload.cs index 41009a695..6dffbb714 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookPayload.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookPayload.cs @@ -1,11 +1,8 @@ -using System.Collections.Generic; - -namespace NzbDrone.Core.Notifications.Webhook +namespace NzbDrone.Core.Notifications.Webhook { public class WebhookPayload { public string EventType { get; set; } public WebhookSeries Series { get; set; } - public List Episodes { get; set; } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookProxy.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookProxy.cs new file mode 100644 index 000000000..1a6260252 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookProxy.cs @@ -0,0 +1,41 @@ +using NzbDrone.Common.Http; +using NzbDrone.Common.Serializer; +using NzbDrone.Core.Rest; + +namespace NzbDrone.Core.Notifications.Webhook +{ + public interface IWebhookProxy + { + void SendWebhook(WebhookPayload payload, WebhookSettings settings); + } + + public class WebhookProxy : IWebhookProxy + { + private readonly IHttpClient _httpClient; + + public WebhookProxy(IHttpClient httpClient) + { + _httpClient = httpClient; + } + + public void SendWebhook(WebhookPayload body, WebhookSettings settings) + { + try + { + var request = new HttpRequestBuilder(settings.Url) + .Accept(HttpAccept.Json) + .Build(); + + request.Method = (HttpMethod)settings.Method; + request.Headers.ContentType = "application/json"; + request.SetContent(body.ToJson()); + + _httpClient.Execute(request); + } + catch (RestException ex) + { + throw new WebhookException("Unable to post to webhook: {0}", ex, ex.Message); + } + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookRelease.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookRelease.cs new file mode 100644 index 000000000..dfab9c889 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookRelease.cs @@ -0,0 +1,27 @@ +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Qualities; + +namespace NzbDrone.Core.Notifications.Webhook +{ + public class WebhookRelease + { + public WebhookRelease() { } + + public WebhookRelease(QualityModel quality, RemoteEpisode remoteEpisode) + { + Quality = quality.Quality.Name; + QualityVersion = quality.Revision.Version; + ReleaseGroup = remoteEpisode.ParsedEpisodeInfo.ReleaseGroup; + ReleaseTitle = remoteEpisode.Release.Title; + Indexer = remoteEpisode.Release.Indexer; + Size = remoteEpisode.Release.Size; + } + + public string Quality { get; set; } + public int QualityVersion { get; set; } + public string ReleaseGroup { get; set; } + public string ReleaseTitle { get; set; } + public string Indexer { get; set; } + public long Size { get; set; } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookService.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookService.cs deleted file mode 100644 index b04efa168..000000000 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookService.cs +++ /dev/null @@ -1,118 +0,0 @@ -using FluentValidation.Results; -using NzbDrone.Core.MediaFiles; -using NzbDrone.Core.Tv; -using NzbDrone.Core.Validation; -using NzbDrone.Core.Rest; -using RestSharp; -using NzbDrone.Core.Qualities; -using NzbDrone.Core.Parser.Model; -using System.Collections.Generic; - -namespace NzbDrone.Core.Notifications.Webhook -{ - public interface IWebhookService - { - void OnDownload(Series series, EpisodeFile episodeFile, WebhookSettings settings); - void OnRename(Series series, WebhookSettings settings); - void OnGrab(Series series, RemoteEpisode episode, QualityModel quality, WebhookSettings settings); - ValidationFailure Test(WebhookSettings settings); - } - - public class WebhookService : IWebhookService - { - public void OnDownload(Series series, EpisodeFile episodeFile, WebhookSettings settings) - { - var payload = new WebhookPayload - { - EventType = "Download", - Series = new WebhookSeries(series), - Episodes = episodeFile.Episodes.Value.ConvertAll(x => new WebhookEpisode(x) { - Quality = episodeFile.Quality.Quality.Name, - QualityVersion = episodeFile.Quality.Revision.Version, - ReleaseGroup = episodeFile.ReleaseGroup, - SceneName = episodeFile.SceneName - }) - }; - - NotifyWebhook(payload, settings); - } - - public void OnRename(Series series, WebhookSettings settings) - { - var payload = new WebhookPayload - { - EventType = "Rename", - Series = new WebhookSeries(series) - }; - - NotifyWebhook(payload, settings); - } - - public void OnGrab(Series series, RemoteEpisode episode, QualityModel quality, WebhookSettings settings) - { - var payload = new WebhookPayload - { - EventType = "Grab", - Series = new WebhookSeries(series), - Episodes = episode.Episodes.ConvertAll(x => new WebhookEpisode(x) - { - Quality = quality.Quality.Name, - QualityVersion = quality.Revision.Version, - ReleaseGroup = episode.ParsedEpisodeInfo.ReleaseGroup - }) - }; - NotifyWebhook(payload, settings); - } - - public void NotifyWebhook(WebhookPayload body, WebhookSettings settings) - { - try { - var client = RestClientFactory.BuildClient(settings.Url); - var request = new RestRequest((Method) settings.Method); - request.RequestFormat = DataFormat.Json; - request.AddBody(body); - client.ExecuteAndValidate(request); - } - catch (RestException ex) - { - throw new WebhookException("Unable to post to webhook: {0}", ex, ex.Message); - } - } - - public ValidationFailure Test(WebhookSettings settings) - { - try - { - NotifyWebhook( - new WebhookPayload - { - EventType = "Test", - Series = new WebhookSeries() - { - Id = 1, - Title = "Test Title", - Path = "C:\\testpath", - TvdbId = 1234 - }, - Episodes = new List() { - new WebhookEpisode() - { - Id = 123, - EpisodeNumber = 1, - SeasonNumber = 1, - Title = "Test title" - } - } - }, - settings - ); - } - catch (WebhookException ex) - { - return new NzbDroneValidationFailure("Url", ex.Message); - } - - return null; - } - } -} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 3fe77287a..268dc2e8f 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -905,12 +905,16 @@ + + + + - +