diff --git a/src/NzbDrone.Core/Notifications/Pushalot/Pushalot.cs b/src/NzbDrone.Core/Notifications/Pushalot/Pushalot.cs new file mode 100644 index 000000000..0f54e344e --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Pushalot/Pushalot.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using FluentValidation.Results; +using NzbDrone.Common; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Notifications.Pushalot +{ + public class Pushalot : NotificationBase + { + private readonly IPushalotProxy _proxy; + + public Pushalot(IPushalotProxy proxy) + { + _proxy = proxy; + } + + public override string Link + { + get { return "https://www.Pushalot.com/"; } + } + + public override void OnGrab(String message) + { + const string title = "Episode Grabbed"; + + _proxy.SendNotification(title, message, Settings); + } + + public override void OnDownload(DownloadMessage message) + { + const string title = "Episode Downloaded"; + + _proxy.SendNotification(title, message.Message, Settings); + } + + public override void AfterRename(Series series) + { + } + + public override ValidationResult Test() + { + var failures = new List(); + + failures.AddIfNotNull(_proxy.Test(Settings)); + + return new ValidationResult(failures); + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Pushalot/PushalotPriority.cs b/src/NzbDrone.Core/Notifications/Pushalot/PushalotPriority.cs new file mode 100644 index 000000000..58effba2f --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Pushalot/PushalotPriority.cs @@ -0,0 +1,9 @@ +namespace NzbDrone.Core.Notifications.Pushalot +{ + public enum PushalotPriority + { + Silent = -1, + Normal = 0, + Important = 1 + } +} diff --git a/src/NzbDrone.Core/Notifications/Pushalot/PushalotProxy.cs b/src/NzbDrone.Core/Notifications/Pushalot/PushalotProxy.cs new file mode 100644 index 000000000..aeb3a71d0 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Pushalot/PushalotProxy.cs @@ -0,0 +1,102 @@ +using System; +using System.Net; +using FluentValidation.Results; +using NLog; +using NzbDrone.Common.Serializer; +using NzbDrone.Core.Rest; +using RestSharp; + +namespace NzbDrone.Core.Notifications.Pushalot +{ + public interface IPushalotProxy + { + void SendNotification(String title, String message, PushalotSettings settings); + ValidationFailure Test(PushalotSettings settings); + } + + public class PushalotProxy : IPushalotProxy + { + private readonly Logger _logger; + private const string URL = "https://pushalot.com/api/sendmessage"; + + public PushalotProxy(Logger logger) + { + _logger = logger; + } + + public void SendNotification(String title, String message, PushalotSettings settings) + { + var client = RestClientFactory.BuildClient(URL); + var request = BuildRequest(); + + request.AddParameter("Source", "NzbDrone"); + request.AddParameter("Image", "https://raw.githubusercontent.com/NzbDrone/NzbDrone/master/Logo/128.png"); + + request.AddParameter("Title", title); + request.AddParameter("Body", message); + request.AddParameter("AuthorizationToken", settings.AuthToken); + + if ((PushalotPriority)settings.Priority == PushalotPriority.Important) + { + request.AddParameter("IsImportant", true); + } + + if ((PushalotPriority)settings.Priority == PushalotPriority.Silent) + { + request.AddParameter("IsSilent", true); + } + + client.ExecuteAndValidate(request); + } + + public RestRequest BuildRequest() + { + var request = new RestRequest(Method.POST); + + return request; + } + + public ValidationFailure Test(PushalotSettings settings) + { + try + { + const string title = "Test Notification"; + const string body = "This is a test message from NzbDrone"; + + SendNotification(title, body, settings); + } + catch (RestException ex) + { + if (ex.Response.StatusCode == HttpStatusCode.Unauthorized) + { + _logger.ErrorException("Authentication Token is invalid: " + ex.Message, ex); + return new ValidationFailure("AuthToken", "Authentication Token is invalid"); + } + + if (ex.Response.StatusCode == HttpStatusCode.NotAcceptable) + { + _logger.ErrorException("Message limit reached: " + ex.Message, ex); + return new ValidationFailure("AuthToken", "Message limit reached"); + } + + if (ex.Response.StatusCode == HttpStatusCode.Gone) + { + _logger.ErrorException("Authorization Token is no longer valid: " + ex.Message, ex); + return new ValidationFailure("AuthToken", "Authorization Token is no longer valid, please use a new one."); + } + + var response = Json.Deserialize(ex.Response.Content); + + _logger.ErrorException("Unable to send test message: " + ex.Message, ex); + return new ValidationFailure("AuthToken", response.Description); + } + catch (Exception ex) + { + _logger.ErrorException("Unable to send test message: " + ex.Message, ex); + return new ValidationFailure("", "Unable to send test message"); + } + + return null; + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Pushalot/PushalotResponse.cs b/src/NzbDrone.Core/Notifications/Pushalot/PushalotResponse.cs new file mode 100644 index 000000000..f98807a5a --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Pushalot/PushalotResponse.cs @@ -0,0 +1,11 @@ +using System; + +namespace NzbDrone.Core.Notifications.Pushalot +{ + public class PushalotResponse + { + public Boolean Success { get; set; } + public Int32 Status { get; set; } + public String Description { get; set; } + } +} diff --git a/src/NzbDrone.Core/Notifications/Pushalot/PushalotSettings.cs b/src/NzbDrone.Core/Notifications/Pushalot/PushalotSettings.cs new file mode 100644 index 000000000..7e5e9c8cd --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Pushalot/PushalotSettings.cs @@ -0,0 +1,40 @@ +using System; +using FluentValidation; +using FluentValidation.Results; +using NzbDrone.Core.Annotations; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.Notifications.Pushalot +{ + public class PushalotSettingsValidator : AbstractValidator + { + public PushalotSettingsValidator() + { + RuleFor(c => c.AuthToken).NotEmpty(); + } + } + + public class PushalotSettings : IProviderConfig + { + private static readonly PushalotSettingsValidator Validator = new PushalotSettingsValidator(); + + [FieldDefinition(0, Label = "Authorization Token", HelpLink = "https://pushalot.com/manager/authorizations")] + public String AuthToken { get; set; } + + [FieldDefinition(1, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(PushalotPriority))] + public Int32 Priority { get; set; } + + public bool IsValid + { + get + { + return !String.IsNullOrWhiteSpace(AuthToken); + } + } + + public ValidationResult Validate() + { + return Validator.Validate(this); + } + } +} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 7e12f2d21..f85d0f043 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -415,6 +415,11 @@ + + + + +