diff --git a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs new file mode 100644 index 000000000..63ffadd92 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using FluentValidation.Results; +using NLog; +using NzbDrone.Core.Movies; + +namespace NzbDrone.Core.Notifications.Gotify +{ + public class Gotify : NotificationBase + { + private readonly IGotifyProxy _proxy; + private readonly Logger _logger; + + public Gotify(IGotifyProxy proxy, Logger logger) + { + _proxy = proxy; + _logger = logger; + } + + public override string Name => "Gotify"; + public override string Link => "https://gotify.net/"; + + public override void OnGrab(GrabMessage grabMessage) + { + const string title = "Movie Grabbed"; + + _proxy.SendNotification(title, grabMessage.Message, Settings); + } + + public override void OnDownload(DownloadMessage message) + { + const string title = "Movie Downloaded"; + + _proxy.SendNotification(title, message.Message, Settings); + } + + public override void OnMovieRename(Movie movie) + { + } + + public override bool SupportsOnRename => false; + + public override ValidationResult Test() + { + var failures = new List(); + + try + { + const string title = "Test Notification"; + const string body = "This is a test message from Radarr"; + + _proxy.SendNotification(title, body, Settings); + } + catch (Exception ex) + { + _logger.Error(ex, "Unable to send test message"); + failures.Add(new ValidationFailure("", "Unable to send test message")); + } + + return new ValidationResult(failures); + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Gotify/GotifyPriority.cs b/src/NzbDrone.Core/Notifications/Gotify/GotifyPriority.cs new file mode 100644 index 000000000..9a5f9c5dc --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Gotify/GotifyPriority.cs @@ -0,0 +1,10 @@ +namespace NzbDrone.Core.Notifications.Gotify +{ + public enum GotifyPriority + { + Min = 0, + Low = 2, + Normal = 5, + High = 8 + } +} diff --git a/src/NzbDrone.Core/Notifications/Gotify/GotifyService.cs b/src/NzbDrone.Core/Notifications/Gotify/GotifyService.cs new file mode 100644 index 000000000..b14b530d3 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Gotify/GotifyService.cs @@ -0,0 +1,26 @@ +using RestSharp; +using NzbDrone.Core.Rest; + +namespace NzbDrone.Core.Notifications.Gotify +{ + public interface IGotifyProxy + { + void SendNotification(string title, string message, GotifySettings settings); + } + + public class GotifyProxy : IGotifyProxy + { + public void SendNotification(string title, string message, GotifySettings settings) + { + var client = RestClientFactory.BuildClient(settings.Server); + var request = new RestRequest("message", Method.POST); + + request.AddQueryParameter("token", settings.AppToken); + request.AddParameter("title", title); + request.AddParameter("message", message); + request.AddParameter("priority", settings.Priority); + + client.ExecuteAndValidate(request); + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs b/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs new file mode 100644 index 000000000..4e6f929c9 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Gotify/GotifySettings.cs @@ -0,0 +1,40 @@ +using FluentValidation; +using NzbDrone.Core.Annotations; +using NzbDrone.Core.ThingiProvider; +using NzbDrone.Core.Validation; + +namespace NzbDrone.Core.Notifications.Gotify +{ + public class GotifySettingsValidator : AbstractValidator + { + public GotifySettingsValidator() + { + RuleFor(c => c.Server).IsValidUrl(); + RuleFor(c => c.AppToken).NotEmpty(); + } + } + + public class GotifySettings : IProviderConfig + { + private static readonly GotifySettingsValidator Validator = new GotifySettingsValidator(); + + public GotifySettings() + { + Priority = 5; + } + + [FieldDefinition(0, Label = "Gotify Server", HelpText = "Gotify server URL, including http(s):// and port if needed")] + public string Server { get; set; } + + [FieldDefinition(1, Label = "App Token", HelpText = "The Application Token generated by Gotify")] + public string AppToken { get; set; } + + [FieldDefinition(2, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(GotifyPriority), HelpText = "Priority of the notification")] + public int Priority { get; set; } + + public NzbDroneValidationResult Validate() + { + return new NzbDroneValidationResult(Validator.Validate(this)); + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Gotify/InvalidResponseException.cs b/src/NzbDrone.Core/Notifications/Gotify/InvalidResponseException.cs new file mode 100644 index 000000000..0a4c20b4d --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Gotify/InvalidResponseException.cs @@ -0,0 +1,15 @@ +using System; + +namespace NzbDrone.Core.Notifications.Gotify +{ + public class InvalidResponseException : Exception + { + public InvalidResponseException() + { + } + + public InvalidResponseException(string message) : base(message) + { + } + } +} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index bf24d10b2..90f2ded6c 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -925,6 +925,11 @@ + + + + +