parent
4c3484a898
commit
6546ba773c
@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Apprise
|
||||
{
|
||||
public class Apprise : NotificationBase<AppriseSettings>
|
||||
{
|
||||
public override string Name => "Apprise";
|
||||
|
||||
public override string Link => "https://github.com/caronc/apprise";
|
||||
|
||||
private readonly IAppriseProxy _proxy;
|
||||
|
||||
public Apprise(IAppriseProxy proxy)
|
||||
{
|
||||
_proxy = proxy;
|
||||
}
|
||||
|
||||
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
|
||||
{
|
||||
_proxy.SendNotification(Settings, HEALTH_ISSUE_TITLE_BRANDED, $"{healthCheck.Message}");
|
||||
}
|
||||
|
||||
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
|
||||
{
|
||||
_proxy.SendNotification(Settings, APPLICATION_UPDATE_TITLE_BRANDED, $"{updateMessage.Message}");
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
||||
failures.AddIfNotNull(_proxy.Test(Settings));
|
||||
|
||||
return new ValidationResult(failures);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Apprise
|
||||
{
|
||||
public interface IAppriseProxy
|
||||
{
|
||||
void SendNotification(AppriseSettings settings, string title, string message);
|
||||
|
||||
ValidationFailure Test(AppriseSettings settings);
|
||||
}
|
||||
|
||||
public class AppriseProxy : IAppriseProxy
|
||||
{
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public AppriseProxy(IHttpClient httpClient, Logger logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void SendNotification(AppriseSettings settings, string title, string body)
|
||||
{
|
||||
var requestBuilder = new HttpRequestBuilder(settings.BaseUrl.TrimEnd('/', ' ')).Post()
|
||||
.AddFormParameter("title", title)
|
||||
.AddFormParameter("body", body);
|
||||
|
||||
if (settings.ConfigurationKey.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder
|
||||
.Resource("/notify/{configurationKey}")
|
||||
.SetSegment("configurationKey", settings.ConfigurationKey);
|
||||
}
|
||||
else if (settings.StatelessUrls.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder
|
||||
.Resource("/notify")
|
||||
.AddFormParameter("urls", settings.StatelessUrls);
|
||||
}
|
||||
|
||||
if (settings.Tags.Any())
|
||||
{
|
||||
requestBuilder.AddFormParameter("tag", settings.Tags.Join(","));
|
||||
}
|
||||
|
||||
if (settings.AuthUsername.IsNotNullOrWhiteSpace() || settings.AuthPassword.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder.NetworkCredential = new BasicNetworkCredential(settings.AuthUsername, settings.AuthPassword);
|
||||
}
|
||||
|
||||
_httpClient.Execute(requestBuilder.Build());
|
||||
}
|
||||
|
||||
public ValidationFailure Test(AppriseSettings settings)
|
||||
{
|
||||
const string title = "Prowlarr - Test Notification";
|
||||
const string body = "Success! You have properly configured your apprise notification settings.";
|
||||
|
||||
try
|
||||
{
|
||||
SendNotification(settings, title, body);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
_logger.Error(ex, $"HTTP Auth credentials are invalid: {ex.Message}");
|
||||
return new ValidationFailure("AuthUsername", $"HTTP Auth credentials are invalid: {ex.Message}");
|
||||
}
|
||||
|
||||
_logger.Error(ex, "Unable to send test message. Server connection failed. Status code: {0}", ex.Message);
|
||||
return new ValidationFailure("Url", $"Unable to connect to Apprise API. Please try again later. Status code: {ex.Message}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send test message. Status code: {0}", ex.Message);
|
||||
return new ValidationFailure("Url", $"Unable to send test message. Status code: {ex.Message}");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Apprise
|
||||
{
|
||||
public class AppriseSettingsValidator : AbstractValidator<AppriseSettings>
|
||||
{
|
||||
public AppriseSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.BaseUrl).IsValidUrl();
|
||||
|
||||
RuleFor(c => c.ConfigurationKey).NotEmpty()
|
||||
.When(c => c.StatelessUrls.IsNullOrWhiteSpace())
|
||||
.WithMessage("Use either Configuration Key or Stateless Urls");
|
||||
|
||||
RuleFor(c => c.ConfigurationKey).Matches("^[a-z0-9-]*$")
|
||||
.WithMessage("Allowed characters a-z, 0-9 and -");
|
||||
|
||||
RuleFor(c => c.StatelessUrls).NotEmpty()
|
||||
.When(c => c.ConfigurationKey.IsNullOrWhiteSpace())
|
||||
.WithMessage("Use either Configuration Key or Stateless Urls");
|
||||
|
||||
RuleFor(c => c.StatelessUrls).Empty()
|
||||
.When(c => c.ConfigurationKey.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Use either Configuration Key or Stateless Urls");
|
||||
|
||||
RuleFor(c => c.Tags).Empty()
|
||||
.When(c => c.StatelessUrls.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Stateless Urls do not support tags");
|
||||
}
|
||||
}
|
||||
|
||||
public class AppriseSettings : IProviderConfig
|
||||
{
|
||||
private static readonly AppriseSettingsValidator Validator = new ();
|
||||
|
||||
public AppriseSettings()
|
||||
{
|
||||
Tags = Array.Empty<string>();
|
||||
}
|
||||
|
||||
[FieldDefinition(1, Label = "Apprise Base URL", Type = FieldType.Url, Placeholder = "http://localhost:8000", HelpText = "Apprise server Base URL, including http(s):// and port if needed", HelpLink = "https://github.com/caronc/apprise-api")]
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "Apprise Configuration Key", Type = FieldType.Textbox, HelpText = "Configuration Key for the Persistent Storage Solution. Leave empty if Stateless Urls is used.", HelpLink = "https://github.com/caronc/apprise-api#persistent-storage-solution")]
|
||||
public string ConfigurationKey { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "Apprise Stateless Urls", Type = FieldType.Textbox, HelpText = "One or more URLs separated by commas identifying where the notification should be sent to. Leave empty if Persistent Storage is used.", HelpLink = "https://github.com/caronc/apprise#productivity-based-notifications")]
|
||||
public string StatelessUrls { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Apprise Tags", Type = FieldType.Tag, HelpText = "Optionally notify only those tagged accordingly.")]
|
||||
public IEnumerable<string> Tags { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Auth Username", Type = FieldType.Textbox, HelpText = "HTTP Basic Auth Username", Privacy = PrivacyLevel.UserName)]
|
||||
public string AuthUsername { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Auth Password", Type = FieldType.Password, HelpText = "HTTP Basic Auth Password", Privacy = PrivacyLevel.Password)]
|
||||
public string AuthPassword { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue