New: On Health Restored notification

Closes #4262
This commit is contained in:
The Dark 2023-05-08 02:57:14 +01:00 committed by GitHub
parent fbf79c6639
commit 5fdc8514da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 285 additions and 5 deletions

View File

@ -63,6 +63,7 @@ class Notification extends Component {
onEpisodeFileDelete, onEpisodeFileDelete,
onEpisodeFileDeleteForUpgrade, onEpisodeFileDeleteForUpgrade,
onHealthIssue, onHealthIssue,
onHealthRestored,
onApplicationUpdate, onApplicationUpdate,
supportsOnGrab, supportsOnGrab,
supportsOnDownload, supportsOnDownload,
@ -73,6 +74,7 @@ class Notification extends Component {
supportsOnEpisodeFileDelete, supportsOnEpisodeFileDelete,
supportsOnEpisodeFileDeleteForUpgrade, supportsOnEpisodeFileDeleteForUpgrade,
supportsOnHealthIssue, supportsOnHealthIssue,
supportsOnHealthRestored,
supportsOnApplicationUpdate supportsOnApplicationUpdate
} = this.props; } = this.props;
@ -126,6 +128,14 @@ class Notification extends Component {
null null
} }
{
supportsOnHealthRestored && onHealthRestored ?
<Label kind={kinds.SUCCESS}>
On Health Restored
</Label> :
null
}
{ {
supportsOnApplicationUpdate && onApplicationUpdate ? supportsOnApplicationUpdate && onApplicationUpdate ?
<Label kind={kinds.SUCCESS}> <Label kind={kinds.SUCCESS}>
@ -167,7 +177,7 @@ class Notification extends Component {
} }
{ {
!onGrab && !onDownload && !onRename && !onHealthIssue && !onApplicationUpdate && !onSeriesDelete && !onEpisodeFileDelete ? !onGrab && !onDownload && !onRename && !onHealthIssue && !onHealthRestored && !onApplicationUpdate && !onSeriesDelete && !onEpisodeFileDelete ?
<Label <Label
kind={kinds.DISABLED} kind={kinds.DISABLED}
outline={true} outline={true}
@ -210,6 +220,7 @@ Notification.propTypes = {
onEpisodeFileDelete: PropTypes.bool.isRequired, onEpisodeFileDelete: PropTypes.bool.isRequired,
onEpisodeFileDeleteForUpgrade: PropTypes.bool.isRequired, onEpisodeFileDeleteForUpgrade: PropTypes.bool.isRequired,
onHealthIssue: PropTypes.bool.isRequired, onHealthIssue: PropTypes.bool.isRequired,
onHealthRestored: PropTypes.bool.isRequired,
onApplicationUpdate: PropTypes.bool.isRequired, onApplicationUpdate: PropTypes.bool.isRequired,
supportsOnGrab: PropTypes.bool.isRequired, supportsOnGrab: PropTypes.bool.isRequired,
supportsOnDownload: PropTypes.bool.isRequired, supportsOnDownload: PropTypes.bool.isRequired,
@ -220,6 +231,7 @@ Notification.propTypes = {
supportsOnUpgrade: PropTypes.bool.isRequired, supportsOnUpgrade: PropTypes.bool.isRequired,
supportsOnRename: PropTypes.bool.isRequired, supportsOnRename: PropTypes.bool.isRequired,
supportsOnHealthIssue: PropTypes.bool.isRequired, supportsOnHealthIssue: PropTypes.bool.isRequired,
supportsOnHealthRestored: PropTypes.bool.isRequired,
supportsOnApplicationUpdate: PropTypes.bool.isRequired, supportsOnApplicationUpdate: PropTypes.bool.isRequired,
onConfirmDeleteNotification: PropTypes.func.isRequired onConfirmDeleteNotification: PropTypes.func.isRequired
}; };

View File

@ -23,6 +23,7 @@ function NotificationEventItems(props) {
onEpisodeFileDelete, onEpisodeFileDelete,
onEpisodeFileDeleteForUpgrade, onEpisodeFileDeleteForUpgrade,
onHealthIssue, onHealthIssue,
onHealthRestored,
onApplicationUpdate, onApplicationUpdate,
supportsOnGrab, supportsOnGrab,
supportsOnDownload, supportsOnDownload,
@ -34,6 +35,7 @@ function NotificationEventItems(props) {
supportsOnEpisodeFileDeleteForUpgrade, supportsOnEpisodeFileDeleteForUpgrade,
supportsOnApplicationUpdate, supportsOnApplicationUpdate,
supportsOnHealthIssue, supportsOnHealthIssue,
supportsOnHealthRestored,
includeHealthWarnings includeHealthWarnings
} = item; } = item;
@ -151,8 +153,19 @@ function NotificationEventItems(props) {
/> />
</div> </div>
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onHealthRestored"
helpText="On Health Restored"
isDisabled={!supportsOnHealthRestored.value}
{...onHealthRestored}
onChange={onInputChange}
/>
</div>
{ {
onHealthIssue.value && (onHealthIssue.value || onHealthRestored.value) &&
<div> <div>
<FormInputGroup <FormInputGroup
type={inputTypes.CHECK} type={inputTypes.CHECK}

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using FluentAssertions; using FluentAssertions;
using FluentValidation.Results; using FluentValidation.Results;
@ -79,6 +79,11 @@ namespace NzbDrone.Core.Test.NotificationTests
TestLogger.Info("OnHealthIssue was called"); TestLogger.Info("OnHealthIssue was called");
} }
public override void OnHealthRestored(Core.HealthCheck.HealthCheck healthCheck)
{
TestLogger.Info("OnHealthRestored was called");
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
TestLogger.Info("OnApplicationUpdate was called"); TestLogger.Info("OnApplicationUpdate was called");
@ -121,6 +126,7 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnEpisodeFileDelete.Should().BeTrue(); notification.SupportsOnEpisodeFileDelete.Should().BeTrue();
notification.SupportsOnEpisodeFileDeleteForUpgrade.Should().BeTrue(); notification.SupportsOnEpisodeFileDeleteForUpgrade.Should().BeTrue();
notification.SupportsOnHealthIssue.Should().BeTrue(); notification.SupportsOnHealthIssue.Should().BeTrue();
notification.SupportsOnHealthRestored.Should().BeTrue();
notification.SupportsOnApplicationUpdate.Should().BeTrue(); notification.SupportsOnApplicationUpdate.Should().BeTrue();
} }
@ -137,6 +143,7 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnEpisodeFileDelete.Should().BeFalse(); notification.SupportsOnEpisodeFileDelete.Should().BeFalse();
notification.SupportsOnEpisodeFileDeleteForUpgrade.Should().BeFalse(); notification.SupportsOnEpisodeFileDeleteForUpgrade.Should().BeFalse();
notification.SupportsOnHealthIssue.Should().BeFalse(); notification.SupportsOnHealthIssue.Should().BeFalse();
notification.SupportsOnHealthRestored.Should().BeFalse();
notification.SupportsOnApplicationUpdate.Should().BeFalse(); notification.SupportsOnApplicationUpdate.Should().BeFalse();
} }
} }

View File

@ -0,0 +1,14 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(190)]
public class health_restored_notification : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("Notifications").AddColumn("OnHealthRestored").AsBoolean().WithDefaultValue(0);
}
}
}

View File

@ -93,6 +93,7 @@ namespace NzbDrone.Core.Datastore
.Ignore(i => i.SupportsOnEpisodeFileDelete) .Ignore(i => i.SupportsOnEpisodeFileDelete)
.Ignore(i => i.SupportsOnEpisodeFileDeleteForUpgrade) .Ignore(i => i.SupportsOnEpisodeFileDeleteForUpgrade)
.Ignore(i => i.SupportsOnHealthIssue) .Ignore(i => i.SupportsOnHealthIssue)
.Ignore(i => i.SupportsOnHealthRestored)
.Ignore(i => i.SupportsOnApplicationUpdate); .Ignore(i => i.SupportsOnApplicationUpdate);
Mapper.Entity<MetadataDefinition>("Metadata").RegisterModel() Mapper.Entity<MetadataDefinition>("Metadata").RegisterModel()

View File

@ -0,0 +1,16 @@
using NzbDrone.Common.Messaging;
namespace NzbDrone.Core.HealthCheck
{
public class HealthCheckRestoredEvent : IEvent
{
public HealthCheck PreviousCheck { get; private set; }
public bool IsInStartupGracePeriod { get; private set; }
public HealthCheckRestoredEvent(HealthCheck previousCheck, bool isInStartupGracePeriod)
{
PreviousCheck = previousCheck;
IsInStartupGracePeriod = isInStartupGracePeriod;
}
}
}

View File

@ -83,6 +83,13 @@ namespace NzbDrone.Core.HealthCheck
{ {
if (result.Type == HealthCheckResult.Ok) if (result.Type == HealthCheckResult.Ok)
{ {
var previous = _healthCheckResults.Find(result.Source.Name);
if (previous != null)
{
_eventAggregator.PublishEvent(new HealthCheckRestoredEvent(previous, !_hasRunHealthChecksAfterGracePeriod));
}
_healthCheckResults.Remove(result.Source.Name); _healthCheckResults.Remove(result.Source.Name);
} }
else else

View File

@ -47,6 +47,11 @@ namespace NzbDrone.Core.Notifications.Apprise
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousCheck.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);

View File

@ -46,6 +46,11 @@ namespace NzbDrone.Core.Notifications.Boxcar
_proxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousCheck.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage message) public override void OnApplicationUpdate(ApplicationUpdateMessage message)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, message.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE, message.Message, Settings);

View File

@ -274,6 +274,21 @@ namespace NzbDrone.Core.Notifications.CustomScript
ExecuteScript(environmentVariables); ExecuteScript(environmentVariables);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
var environmentVariables = new StringDictionary();
environmentVariables.Add("Sonarr_EventType", "HealthRestored");
environmentVariables.Add("Sonarr_InstanceName", _configFileProvider.InstanceName);
environmentVariables.Add("Sonarr_ApplicationUrl", _configService.ApplicationUrl);
environmentVariables.Add("Sonarr_Health_Restored_Level", Enum.GetName(typeof(HealthCheckResult), previousCheck.Type));
environmentVariables.Add("Sonarr_Health_Restored_Message", previousCheck.Message);
environmentVariables.Add("Sonarr_Health_Restored_Type", previousCheck.Source.Name);
environmentVariables.Add("Sonarr_Health_Restored_Wiki", previousCheck.WikiUrl.ToString() ?? string.Empty);
ExecuteScript(environmentVariables);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
var environmentVariables = new StringDictionary(); var environmentVariables = new StringDictionary();

View File

@ -317,6 +317,29 @@ namespace NzbDrone.Core.Notifications.Discord
_proxy.SendPayload(payload, Settings); _proxy.SendPayload(payload, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
var attachments = new List<Embed>
{
new Embed
{
Author = new DiscordAuthor
{
Name = Settings.Author.IsNullOrWhiteSpace() ? Environment.MachineName : Settings.Author,
IconUrl = "https://raw.githubusercontent.com/Sonarr/Sonarr/develop/Logo/256.png"
},
Title = "Health Issue Resolved: " + previousCheck.Source.Name,
Description = $"The following issue is now resolved: {previousCheck.Message}",
Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),
Color = (int)DiscordColors.Success
}
};
var payload = CreatePayload(null, attachments);
_proxy.SendPayload(payload, Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
var attachments = new List<Embed> var attachments = new List<Embed>

View File

@ -66,6 +66,11 @@ namespace NzbDrone.Core.Notifications.Email
SendEmail(Settings, HEALTH_ISSUE_TITLE_BRANDED, message.Message); SendEmail(Settings, HEALTH_ISSUE_TITLE_BRANDED, message.Message);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousMessage)
{
SendEmail(Settings, HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousMessage.Message}");
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
var body = $"{updateMessage.Message}"; var body = $"{updateMessage.Message}";

View File

@ -53,6 +53,11 @@ namespace NzbDrone.Core.Notifications.Gotify
SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, null); SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, null);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousCheck.Message}", null);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage message) public override void OnApplicationUpdate(ApplicationUpdateMessage message)
{ {
SendNotification(APPLICATION_UPDATE_TITLE, message.Message, null); SendNotification(APPLICATION_UPDATE_TITLE, message.Message, null);

View File

@ -16,6 +16,7 @@ namespace NzbDrone.Core.Notifications
void OnSeriesAdd(SeriesAddMessage message); void OnSeriesAdd(SeriesAddMessage message);
void OnSeriesDelete(SeriesDeleteMessage deleteMessage); void OnSeriesDelete(SeriesDeleteMessage deleteMessage);
void OnHealthIssue(HealthCheck.HealthCheck healthCheck); void OnHealthIssue(HealthCheck.HealthCheck healthCheck);
void OnHealthRestored(HealthCheck.HealthCheck previousCheck);
void OnApplicationUpdate(ApplicationUpdateMessage updateMessage); void OnApplicationUpdate(ApplicationUpdateMessage updateMessage);
void ProcessQueue(); void ProcessQueue();
bool SupportsOnGrab { get; } bool SupportsOnGrab { get; }
@ -27,6 +28,7 @@ namespace NzbDrone.Core.Notifications
bool SupportsOnEpisodeFileDelete { get; } bool SupportsOnEpisodeFileDelete { get; }
bool SupportsOnEpisodeFileDeleteForUpgrade { get; } bool SupportsOnEpisodeFileDeleteForUpgrade { get; }
bool SupportsOnHealthIssue { get; } bool SupportsOnHealthIssue { get; }
bool SupportsOnHealthRestored { get; }
bool SupportsOnApplicationUpdate { get; } bool SupportsOnApplicationUpdate { get; }
} }
} }

View File

@ -47,6 +47,11 @@ namespace NzbDrone.Core.Notifications.Join
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, message.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, message.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousMessage)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousMessage.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings);

View File

@ -55,6 +55,11 @@ namespace NzbDrone.Core.Notifications.Mailgun
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheckMessage.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheckMessage.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheckMessage)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousCheckMessage.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);

View File

@ -94,6 +94,14 @@ namespace NzbDrone.Core.Notifications.Emby
} }
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousMessage)
{
if (Settings.Notify)
{
_mediaBrowserService.Notify(Settings, HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousMessage.Message}");
}
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
if (Settings.Notify) if (Settings.Notify)

View File

@ -57,6 +57,11 @@ namespace NzbDrone.Core.Notifications.Notifiarr
_proxy.SendNotification(BuildHealthPayload(healthCheck), Settings); _proxy.SendNotification(BuildHealthPayload(healthCheck), Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendNotification(BuildHealthRestoredPayload(previousCheck), Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(BuildApplicationUpdatePayload(updateMessage), Settings); _proxy.SendNotification(BuildApplicationUpdatePayload(updateMessage), Settings);

View File

@ -16,6 +16,7 @@ namespace NzbDrone.Core.Notifications
protected const string SERIES_ADDED_TITLE = "Series Added"; protected const string SERIES_ADDED_TITLE = "Series Added";
protected const string SERIES_DELETED_TITLE = "Series Deleted"; protected const string SERIES_DELETED_TITLE = "Series Deleted";
protected const string HEALTH_ISSUE_TITLE = "Health Check Failure"; protected const string HEALTH_ISSUE_TITLE = "Health Check Failure";
protected const string HEALTH_RESTORED_TITLE = "Health Check Restored";
protected const string APPLICATION_UPDATE_TITLE = "Application Updated"; protected const string APPLICATION_UPDATE_TITLE = "Application Updated";
protected const string EPISODE_GRABBED_TITLE_BRANDED = "Sonarr - " + EPISODE_GRABBED_TITLE; protected const string EPISODE_GRABBED_TITLE_BRANDED = "Sonarr - " + EPISODE_GRABBED_TITLE;
@ -24,6 +25,7 @@ namespace NzbDrone.Core.Notifications
protected const string SERIES_ADDED_TITLE_BRANDED = "Sonarr - " + SERIES_DELETED_TITLE; protected const string SERIES_ADDED_TITLE_BRANDED = "Sonarr - " + SERIES_DELETED_TITLE;
protected const string SERIES_DELETED_TITLE_BRANDED = "Sonarr - " + SERIES_DELETED_TITLE; protected const string SERIES_DELETED_TITLE_BRANDED = "Sonarr - " + SERIES_DELETED_TITLE;
protected const string HEALTH_ISSUE_TITLE_BRANDED = "Sonarr - " + HEALTH_ISSUE_TITLE; protected const string HEALTH_ISSUE_TITLE_BRANDED = "Sonarr - " + HEALTH_ISSUE_TITLE;
protected const string HEALTH_RESTORED_TITLE_BRANDED = "Sonarr - " + HEALTH_RESTORED_TITLE;
protected const string APPLICATION_UPDATE_TITLE_BRANDED = "Sonarr - " + APPLICATION_UPDATE_TITLE; protected const string APPLICATION_UPDATE_TITLE_BRANDED = "Sonarr - " + APPLICATION_UPDATE_TITLE;
public abstract string Name { get; } public abstract string Name { get; }
@ -67,6 +69,10 @@ namespace NzbDrone.Core.Notifications
{ {
} }
public virtual void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
}
public virtual void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public virtual void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
} }
@ -84,6 +90,7 @@ namespace NzbDrone.Core.Notifications
public bool SupportsOnEpisodeFileDelete => HasConcreteImplementation("OnEpisodeFileDelete"); public bool SupportsOnEpisodeFileDelete => HasConcreteImplementation("OnEpisodeFileDelete");
public bool SupportsOnEpisodeFileDeleteForUpgrade => SupportsOnEpisodeFileDelete; public bool SupportsOnEpisodeFileDeleteForUpgrade => SupportsOnEpisodeFileDelete;
public bool SupportsOnHealthIssue => HasConcreteImplementation("OnHealthIssue"); public bool SupportsOnHealthIssue => HasConcreteImplementation("OnHealthIssue");
public bool SupportsOnHealthRestored => HasConcreteImplementation("OnHealthRestored");
public bool SupportsOnApplicationUpdate => HasConcreteImplementation("OnApplicationUpdate"); public bool SupportsOnApplicationUpdate => HasConcreteImplementation("OnApplicationUpdate");
protected TSettings Settings => (TSettings)Definition.Settings; protected TSettings Settings => (TSettings)Definition.Settings;

View File

@ -13,6 +13,7 @@ namespace NzbDrone.Core.Notifications
public bool OnEpisodeFileDelete { get; set; } public bool OnEpisodeFileDelete { get; set; }
public bool OnEpisodeFileDeleteForUpgrade { get; set; } public bool OnEpisodeFileDeleteForUpgrade { get; set; }
public bool OnHealthIssue { get; set; } public bool OnHealthIssue { get; set; }
public bool OnHealthRestored { get; set; }
public bool OnApplicationUpdate { get; set; } public bool OnApplicationUpdate { get; set; }
public bool SupportsOnGrab { get; set; } public bool SupportsOnGrab { get; set; }
public bool SupportsOnDownload { get; set; } public bool SupportsOnDownload { get; set; }
@ -23,9 +24,10 @@ namespace NzbDrone.Core.Notifications
public bool SupportsOnEpisodeFileDelete { get; set; } public bool SupportsOnEpisodeFileDelete { get; set; }
public bool SupportsOnEpisodeFileDeleteForUpgrade { get; set; } public bool SupportsOnEpisodeFileDeleteForUpgrade { get; set; }
public bool SupportsOnHealthIssue { get; set; } public bool SupportsOnHealthIssue { get; set; }
public bool SupportsOnHealthRestored { get; set; }
public bool IncludeHealthWarnings { get; set; } public bool IncludeHealthWarnings { get; set; }
public bool SupportsOnApplicationUpdate { get; set; } public bool SupportsOnApplicationUpdate { get; set; }
public override bool Enable => OnGrab || OnDownload || (OnDownload && OnUpgrade) || OnSeriesAdd || OnSeriesDelete || OnEpisodeFileDelete || OnEpisodeFileDeleteForUpgrade || OnHealthIssue || OnApplicationUpdate; public override bool Enable => OnGrab || OnDownload || (OnDownload && OnUpgrade) || OnSeriesAdd || OnSeriesDelete || OnEpisodeFileDelete || OnEpisodeFileDeleteForUpgrade || OnHealthIssue || OnHealthRestored || OnApplicationUpdate;
} }
} }

View File

@ -19,6 +19,7 @@ namespace NzbDrone.Core.Notifications
List<INotification> OnEpisodeFileDeleteEnabled(); List<INotification> OnEpisodeFileDeleteEnabled();
List<INotification> OnEpisodeFileDeleteForUpgradeEnabled(); List<INotification> OnEpisodeFileDeleteForUpgradeEnabled();
List<INotification> OnHealthIssueEnabled(); List<INotification> OnHealthIssueEnabled();
List<INotification> OnHealthRestoredEnabled();
List<INotification> OnApplicationUpdateEnabled(); List<INotification> OnApplicationUpdateEnabled();
} }
@ -74,6 +75,11 @@ namespace NzbDrone.Core.Notifications
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnHealthIssue).ToList(); return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnHealthIssue).ToList();
} }
public List<INotification> OnHealthRestoredEnabled()
{
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnHealthRestored).ToList();
}
public List<INotification> OnApplicationUpdateEnabled() public List<INotification> OnApplicationUpdateEnabled()
{ {
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnApplicationUpdate).ToList(); return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnApplicationUpdate).ToList();
@ -92,6 +98,7 @@ namespace NzbDrone.Core.Notifications
definition.SupportsOnEpisodeFileDelete = provider.SupportsOnEpisodeFileDelete; definition.SupportsOnEpisodeFileDelete = provider.SupportsOnEpisodeFileDelete;
definition.SupportsOnEpisodeFileDeleteForUpgrade = provider.SupportsOnEpisodeFileDeleteForUpgrade; definition.SupportsOnEpisodeFileDeleteForUpgrade = provider.SupportsOnEpisodeFileDeleteForUpgrade;
definition.SupportsOnHealthIssue = provider.SupportsOnHealthIssue; definition.SupportsOnHealthIssue = provider.SupportsOnHealthIssue;
definition.SupportsOnHealthRestored = provider.SupportsOnHealthRestored;
definition.SupportsOnApplicationUpdate = provider.SupportsOnApplicationUpdate; definition.SupportsOnApplicationUpdate = provider.SupportsOnApplicationUpdate;
} }
} }

View File

@ -23,6 +23,7 @@ namespace NzbDrone.Core.Notifications
IHandle<SeriesDeletedEvent>, IHandle<SeriesDeletedEvent>,
IHandle<EpisodeFileDeletedEvent>, IHandle<EpisodeFileDeletedEvent>,
IHandle<HealthCheckFailedEvent>, IHandle<HealthCheckFailedEvent>,
IHandle<HealthCheckRestoredEvent>,
IHandle<UpdateInstalledEvent>, IHandle<UpdateInstalledEvent>,
IHandleAsync<DeleteCompletedEvent>, IHandleAsync<DeleteCompletedEvent>,
IHandleAsync<DownloadsProcessedEvent>, IHandleAsync<DownloadsProcessedEvent>,
@ -327,6 +328,29 @@ namespace NzbDrone.Core.Notifications
} }
} }
public void Handle(HealthCheckRestoredEvent message)
{
if (message.IsInStartupGracePeriod)
{
return;
}
foreach (var notification in _notificationFactory.OnHealthRestoredEnabled())
{
try
{
if (ShouldHandleHealthFailure(message.PreviousCheck, ((NotificationDefinition)notification.Definition).IncludeHealthWarnings))
{
notification.OnHealthRestored(message.PreviousCheck);
}
}
catch (Exception ex)
{
_logger.Warn(ex, "Unable to send OnHealthRestored notification to: " + notification.Definition.Name);
}
}
}
public void HandleAsync(DeleteCompletedEvent message) public void HandleAsync(DeleteCompletedEvent message)
{ {
ProcessQueue(); ProcessQueue();

View File

@ -48,6 +48,11 @@ namespace NzbDrone.Core.Notifications.Ntfy
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousCheck.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings);

View File

@ -46,6 +46,11 @@ namespace NzbDrone.Core.Notifications.Prowl
_prowlProxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings); _prowlProxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousMessage)
{
_prowlProxy.SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousMessage.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_prowlProxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings); _prowlProxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);

View File

@ -49,6 +49,11 @@ namespace NzbDrone.Core.Notifications.PushBullet
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousCheck.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings);

View File

@ -46,6 +46,11 @@ namespace NzbDrone.Core.Notifications.Pushover
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousCheck.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);

View File

@ -49,6 +49,11 @@ namespace NzbDrone.Core.Notifications.SendGrid
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousCheck.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);

View File

@ -46,6 +46,11 @@ namespace NzbDrone.Core.Notifications.Simplepush
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousCheck.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);

View File

@ -134,6 +134,23 @@ namespace NzbDrone.Core.Notifications.Slack
_proxy.SendPayload(payload, Settings); _proxy.SendPayload(payload, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
var attachments = new List<Attachment>
{
new Attachment
{
Title = previousCheck.Source.Name,
Text = $"The following issue is now resolved: {previousCheck.Message}",
Color = "good"
}
};
var payload = CreatePayload("Health Issue Resolved", attachments);
_proxy.SendPayload(payload, Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
var attachments = new List<Attachment> var attachments = new List<Attachment>

View File

@ -46,6 +46,11 @@ namespace NzbDrone.Core.Notifications.Telegram
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousCheck.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings); _proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);

View File

@ -48,6 +48,11 @@ namespace NzbDrone.Core.Notifications.Twitter
_twitterService.SendNotification($"Health Issue: {healthCheck.Message}", Settings); _twitterService.SendNotification($"Health Issue: {healthCheck.Message}", Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_twitterService.SendNotification($"Health Issue Resolved: {previousCheck.Message}", Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_twitterService.SendNotification($"Application Updated: {updateMessage.Message}", Settings); _twitterService.SendNotification($"Application Updated: {updateMessage.Message}", Settings);

View File

@ -55,6 +55,11 @@ namespace NzbDrone.Core.Notifications.Webhook
_proxy.SendWebhook(BuildHealthPayload(healthCheck), Settings); _proxy.SendWebhook(BuildHealthPayload(healthCheck), Settings);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
_proxy.SendWebhook(BuildHealthRestoredPayload(previousCheck), Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
_proxy.SendWebhook(BuildApplicationUpdatePayload(updateMessage), Settings); _proxy.SendWebhook(BuildApplicationUpdatePayload(updateMessage), Settings);

View File

@ -133,6 +133,19 @@ namespace NzbDrone.Core.Notifications.Webhook
}; };
} }
protected WebhookHealthPayload BuildHealthRestoredPayload(HealthCheck.HealthCheck healthCheck)
{
return new WebhookHealthPayload
{
EventType = WebhookEventType.HealthRestored,
InstanceName = _configFileProvider.InstanceName,
Level = healthCheck.Type,
Message = healthCheck.Message,
Type = healthCheck.Source.Name,
WikiUrl = healthCheck.WikiUrl?.ToString()
};
}
protected WebhookApplicationUpdatePayload BuildApplicationUpdatePayload(ApplicationUpdateMessage updateMessage) protected WebhookApplicationUpdatePayload BuildApplicationUpdatePayload(ApplicationUpdateMessage updateMessage)
{ {
return new WebhookApplicationUpdatePayload return new WebhookApplicationUpdatePayload

View File

@ -16,6 +16,7 @@ namespace NzbDrone.Core.Notifications.Webhook
SeriesDelete, SeriesDelete,
EpisodeFileDelete, EpisodeFileDelete,
Health, Health,
ApplicationUpdate ApplicationUpdate,
HealthRestored
} }
} }

View File

@ -74,6 +74,11 @@ namespace NzbDrone.Core.Notifications.Xbmc
Notify(Settings, HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message); Notify(Settings, HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message);
} }
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
{
Notify(Settings, HEALTH_RESTORED_TITLE_BRANDED, $"The following issue is now resolved: {previousCheck.Message}");
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage) public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{ {
Notify(Settings, APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message); Notify(Settings, APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message);

View File

@ -14,6 +14,7 @@ namespace Sonarr.Api.V3.Notifications
public bool OnEpisodeFileDelete { get; set; } public bool OnEpisodeFileDelete { get; set; }
public bool OnEpisodeFileDeleteForUpgrade { get; set; } public bool OnEpisodeFileDeleteForUpgrade { get; set; }
public bool OnHealthIssue { get; set; } public bool OnHealthIssue { get; set; }
public bool OnHealthRestored { get; set; }
public bool OnApplicationUpdate { get; set; } public bool OnApplicationUpdate { get; set; }
public bool SupportsOnGrab { get; set; } public bool SupportsOnGrab { get; set; }
public bool SupportsOnDownload { get; set; } public bool SupportsOnDownload { get; set; }
@ -24,6 +25,7 @@ namespace Sonarr.Api.V3.Notifications
public bool SupportsOnEpisodeFileDelete { get; set; } public bool SupportsOnEpisodeFileDelete { get; set; }
public bool SupportsOnEpisodeFileDeleteForUpgrade { get; set; } public bool SupportsOnEpisodeFileDeleteForUpgrade { get; set; }
public bool SupportsOnHealthIssue { get; set; } public bool SupportsOnHealthIssue { get; set; }
public bool SupportsOnHealthRestored { get; set; }
public bool SupportsOnApplicationUpdate { get; set; } public bool SupportsOnApplicationUpdate { get; set; }
public bool IncludeHealthWarnings { get; set; } public bool IncludeHealthWarnings { get; set; }
public string TestCommand { get; set; } public string TestCommand { get; set; }
@ -49,6 +51,7 @@ namespace Sonarr.Api.V3.Notifications
resource.OnEpisodeFileDelete = definition.OnEpisodeFileDelete; resource.OnEpisodeFileDelete = definition.OnEpisodeFileDelete;
resource.OnEpisodeFileDeleteForUpgrade = definition.OnEpisodeFileDeleteForUpgrade; resource.OnEpisodeFileDeleteForUpgrade = definition.OnEpisodeFileDeleteForUpgrade;
resource.OnHealthIssue = definition.OnHealthIssue; resource.OnHealthIssue = definition.OnHealthIssue;
resource.OnHealthRestored = definition.OnHealthRestored;
resource.OnApplicationUpdate = definition.OnApplicationUpdate; resource.OnApplicationUpdate = definition.OnApplicationUpdate;
resource.SupportsOnGrab = definition.SupportsOnGrab; resource.SupportsOnGrab = definition.SupportsOnGrab;
resource.SupportsOnDownload = definition.SupportsOnDownload; resource.SupportsOnDownload = definition.SupportsOnDownload;
@ -59,6 +62,7 @@ namespace Sonarr.Api.V3.Notifications
resource.SupportsOnEpisodeFileDelete = definition.SupportsOnEpisodeFileDelete; resource.SupportsOnEpisodeFileDelete = definition.SupportsOnEpisodeFileDelete;
resource.SupportsOnEpisodeFileDeleteForUpgrade = definition.SupportsOnEpisodeFileDeleteForUpgrade; resource.SupportsOnEpisodeFileDeleteForUpgrade = definition.SupportsOnEpisodeFileDeleteForUpgrade;
resource.SupportsOnHealthIssue = definition.SupportsOnHealthIssue; resource.SupportsOnHealthIssue = definition.SupportsOnHealthIssue;
resource.SupportsOnHealthRestored = definition.SupportsOnHealthRestored;
resource.IncludeHealthWarnings = definition.IncludeHealthWarnings; resource.IncludeHealthWarnings = definition.IncludeHealthWarnings;
resource.SupportsOnApplicationUpdate = definition.SupportsOnApplicationUpdate; resource.SupportsOnApplicationUpdate = definition.SupportsOnApplicationUpdate;
@ -83,6 +87,7 @@ namespace Sonarr.Api.V3.Notifications
definition.OnEpisodeFileDelete = resource.OnEpisodeFileDelete; definition.OnEpisodeFileDelete = resource.OnEpisodeFileDelete;
definition.OnEpisodeFileDeleteForUpgrade = resource.OnEpisodeFileDeleteForUpgrade; definition.OnEpisodeFileDeleteForUpgrade = resource.OnEpisodeFileDeleteForUpgrade;
definition.OnHealthIssue = resource.OnHealthIssue; definition.OnHealthIssue = resource.OnHealthIssue;
definition.OnHealthRestored = resource.OnHealthRestored;
definition.OnApplicationUpdate = resource.OnApplicationUpdate; definition.OnApplicationUpdate = resource.OnApplicationUpdate;
definition.SupportsOnGrab = resource.SupportsOnGrab; definition.SupportsOnGrab = resource.SupportsOnGrab;
definition.SupportsOnDownload = resource.SupportsOnDownload; definition.SupportsOnDownload = resource.SupportsOnDownload;
@ -93,6 +98,7 @@ namespace Sonarr.Api.V3.Notifications
definition.SupportsOnEpisodeFileDelete = resource.SupportsOnEpisodeFileDelete; definition.SupportsOnEpisodeFileDelete = resource.SupportsOnEpisodeFileDelete;
definition.SupportsOnEpisodeFileDeleteForUpgrade = resource.SupportsOnEpisodeFileDeleteForUpgrade; definition.SupportsOnEpisodeFileDeleteForUpgrade = resource.SupportsOnEpisodeFileDeleteForUpgrade;
definition.SupportsOnHealthIssue = resource.SupportsOnHealthIssue; definition.SupportsOnHealthIssue = resource.SupportsOnHealthIssue;
definition.SupportsOnHealthRestored = resource.SupportsOnHealthRestored;
definition.IncludeHealthWarnings = resource.IncludeHealthWarnings; definition.IncludeHealthWarnings = resource.IncludeHealthWarnings;
definition.SupportsOnApplicationUpdate = resource.SupportsOnApplicationUpdate; definition.SupportsOnApplicationUpdate = resource.SupportsOnApplicationUpdate;