New: On Delete Notifications

Closes #2410
pull/4288/head
Robin Dadswell 4 years ago committed by GitHub
parent 21fafb895f
commit c91fabcf2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -42,11 +42,15 @@ function EditNotificationModalContent(props) {
onDownload,
onUpgrade,
onRename,
onSeriesDelete,
onEpisodeFileDelete,
onHealthIssue,
supportsOnGrab,
supportsOnDownload,
supportsOnUpgrade,
supportsOnRename,
supportsOnSeriesDelete,
supportsOnEpisodeFileDelete,
supportsOnHealthIssue,
includeHealthWarnings,
tags,
@ -150,6 +154,32 @@ function EditNotificationModalContent(props) {
/>
</FormGroup>
<FormGroup>
<FormLabel>On Series Delete</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="onSeriesDelete"
helpText="Be notified when series are deleted"
isDisabled={!supportsOnSeriesDelete.value}
{...onSeriesDelete}
onChange={onInputChange}
/>
</FormGroup>
<FormGroup>
<FormLabel>On Episode File Delete</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="onEpisodeFileDelete"
helpText="Be notified when episode files are deleted"
isDisabled={!supportsOnEpisodeFileDelete.value}
{...onEpisodeFileDelete}
onChange={onInputChange}
/>
</FormGroup>
<FormGroup>
<FormLabel>On Health Issue</FormLabel>

@ -58,11 +58,15 @@ class Notification extends Component {
onDownload,
onUpgrade,
onRename,
onSeriesDelete,
onEpisodeFileDelete,
onHealthIssue,
supportsOnGrab,
supportsOnDownload,
supportsOnUpgrade,
supportsOnRename,
supportsOnSeriesDelete,
supportsOnEpisodeFileDelete,
supportsOnHealthIssue
} = this.props;
@ -77,48 +81,70 @@ class Notification extends Component {
</div>
{
supportsOnGrab && onGrab &&
supportsOnGrab && onGrab ?
<Label kind={kinds.SUCCESS}>
On Grab
</Label>
</Label> :
null
}
{
supportsOnDownload && onDownload &&
supportsOnDownload && onDownload ?
<Label kind={kinds.SUCCESS}>
On Import
</Label>
</Label> :
null
}
{
supportsOnUpgrade && onDownload && onUpgrade &&
supportsOnUpgrade && onDownload && onUpgrade ?
<Label kind={kinds.SUCCESS}>
On Upgrade
</Label>
</Label> :
null
}
{
supportsOnRename && onRename &&
supportsOnRename && onRename ?
<Label kind={kinds.SUCCESS}>
On Rename
</Label>
</Label> :
null
}
{
supportsOnHealthIssue && onHealthIssue &&
supportsOnHealthIssue && onHealthIssue ?
<Label kind={kinds.SUCCESS}>
On Health Issue
</Label>
</Label> :
null
}
{
!onGrab && !onDownload && !onRename && !onHealthIssue &&
supportsOnSeriesDelete && onSeriesDelete ?
<Label kind={kinds.SUCCESS}>
On Series Delete
</Label> :
null
}
{
supportsOnEpisodeFileDelete && onEpisodeFileDelete ?
<Label kind={kinds.SUCCESS}>
On Series Delete
</Label> :
null
}
{
!onGrab && !onDownload && !onRename && !onHealthIssue && !onSeriesDelete && !onEpisodeFileDelete ?
<Label
kind={kinds.DISABLED}
outline={true}
>
Disabled
</Label>
</Label> :
null
}
<EditNotificationModalConnector
@ -149,9 +175,13 @@ Notification.propTypes = {
onDownload: PropTypes.bool.isRequired,
onUpgrade: PropTypes.bool.isRequired,
onRename: PropTypes.bool.isRequired,
onSeriesDelete: PropTypes.bool.isRequired,
onEpisodeFileDelete: PropTypes.bool.isRequired,
onHealthIssue: PropTypes.bool.isRequired,
supportsOnGrab: PropTypes.bool.isRequired,
supportsOnDownload: PropTypes.bool.isRequired,
supportsOnSeriesDelete: PropTypes.bool.isRequired,
supportsOnEpisodeFileDelete: PropTypes.bool.isRequired,
supportsOnUpgrade: PropTypes.bool.isRequired,
supportsOnRename: PropTypes.bool.isRequired,
supportsOnHealthIssue: PropTypes.bool.isRequired,

@ -106,6 +106,8 @@ export default {
selectedSchema.onDownload = selectedSchema.supportsOnDownload;
selectedSchema.onUpgrade = selectedSchema.supportsOnUpgrade;
selectedSchema.onRename = selectedSchema.supportsOnRename;
selectedSchema.OnSeriesDelete = selectedSchema.supportsOnSeriesDelete;
selectedSchema.OnEpisodeFileDelete = selectedSchema.supportsOnEpisodeFileDelete;
return selectedSchema;
});

@ -64,7 +64,14 @@ namespace NzbDrone.Core.Test.NotificationTests
{
TestLogger.Info("OnRename was called");
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage message)
{
TestLogger.Info("Episode OnDelete was called");
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
TestLogger.Info("Series OnDelete was called");
}
public override void OnHealthIssue(NzbDrone.Core.HealthCheck.HealthCheck artist)
{
TestLogger.Info("OnHealthIssue was called");
@ -107,6 +114,8 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnDownload.Should().BeTrue();
notification.SupportsOnUpgrade.Should().BeTrue();
notification.SupportsOnRename.Should().BeTrue();
notification.SupportsOnSeriesDelete.Should().BeTrue();
notification.SupportsOnEpisodeFileDelete.Should().BeTrue();
notification.SupportsOnHealthIssue.Should().BeTrue();
}
@ -120,6 +129,8 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnDownload.Should().BeFalse();
notification.SupportsOnUpgrade.Should().BeFalse();
notification.SupportsOnRename.Should().BeFalse();
notification.SupportsOnSeriesDelete.Should().BeFalse();
notification.SupportsOnEpisodeFileDelete.Should().BeFalse();
notification.SupportsOnHealthIssue.Should().BeFalse();
}
}

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

@ -74,6 +74,8 @@ namespace NzbDrone.Core.Datastore
.Ignore(i => i.SupportsOnDownload)
.Ignore(i => i.SupportsOnUpgrade)
.Ignore(i => i.SupportsOnRename)
.Ignore(i => i.SupportsOnSeriesDelete)
.Ignore(i => i.SupportsOnEpisodeFileDelete)
.Ignore(i => i.SupportsOnHealthIssue);
Mapper.Entity<MetadataDefinition>().RegisterDefinition("Metadata")

@ -0,0 +1,9 @@
using NzbDrone.Common.Messaging;
namespace NzbDrone.Core.MediaFiles.Events
{
public class DeleteCompletedEvent : IEvent
{
}
}

@ -28,6 +28,7 @@ namespace NzbDrone.Core.MediaFiles
private readonly IMediaFileService _mediaFileService;
private readonly ISeriesService _seriesService;
private readonly IConfigService _configService;
private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger;
public MediaFileDeletionService(IDiskProvider diskProvider,
@ -35,6 +36,7 @@ namespace NzbDrone.Core.MediaFiles
IMediaFileService mediaFileService,
ISeriesService seriesService,
IConfigService configService,
IEventAggregator eventAggregator,
Logger logger)
{
_diskProvider = diskProvider;
@ -42,6 +44,7 @@ namespace NzbDrone.Core.MediaFiles
_mediaFileService = mediaFileService;
_seriesService = seriesService;
_configService = configService;
_eventAggregator = eventAggregator;
_logger = logger;
}
@ -81,6 +84,8 @@ namespace NzbDrone.Core.MediaFiles
// Delete the episode file from the database to clean it up even if the file was already deleted
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
_eventAggregator.PublishEvent(new DeleteCompletedEvent());
}
public void HandleAsync(SeriesDeletedEvent message)
@ -111,6 +116,7 @@ namespace NzbDrone.Core.MediaFiles
{
_recycleBinProvider.DeleteFolder(message.Series.Path);
}
_eventAggregator.PublishEvent(new DeleteCompletedEvent());
}
}

@ -26,6 +26,16 @@ namespace NzbDrone.Core.Notifications.Boxcar
_proxy.SendNotification(EPISODE_DOWNLOADED_TITLE , message.Message, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
_proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
_proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck message)
{
_proxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings);

@ -127,6 +127,56 @@ namespace NzbDrone.Core.Notifications.CustomScript
ExecuteScript(environmentVariables);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
var series = deleteMessage.Series;
var episodeFile = deleteMessage.EpisodeFile;
var environmentVariables = new StringDictionary();
environmentVariables.Add("Sonarr_EventType", "EpisodeDeleted");
environmentVariables.Add("Sonarr_Series_Id", series.Id.ToString());
environmentVariables.Add("Sonarr_Series_Title", series.Title);
environmentVariables.Add("Sonarr_Series_Path", series.Path);
environmentVariables.Add("Sonarr_Series_TvdbId", series.TvdbId.ToString());
environmentVariables.Add("Sonarr_Series_TvMazeId", series.TvMazeId.ToString());
environmentVariables.Add("Sonarr_Series_ImdbId", series.ImdbId ?? string.Empty);
environmentVariables.Add("Sonarr_Series_Type", series.SeriesType.ToString());
environmentVariables.Add("Sonarr_EpisodeFile_Id", episodeFile.Id.ToString());
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeCount", episodeFile.Episodes.Value.Count.ToString());
environmentVariables.Add("Sonarr_EpisodeFile_RelativePath", episodeFile.RelativePath);
environmentVariables.Add("Sonarr_EpisodeFile_Path", Path.Combine(series.Path, episodeFile.RelativePath));
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeIds", string.Join(",", episodeFile.Episodes.Value.Select(e => e.Id)));
environmentVariables.Add("Sonarr_EpisodeFile_SeasonNumber", episodeFile.SeasonNumber.ToString());
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeNumbers", string.Join(",", episodeFile.Episodes.Value.Select(e => e.EpisodeNumber)));
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeAirDates", string.Join(",", episodeFile.Episodes.Value.Select(e => e.AirDate)));
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeAirDatesUtc", string.Join(",", episodeFile.Episodes.Value.Select(e => e.AirDateUtc)));
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeTitles", string.Join("|", episodeFile.Episodes.Value.Select(e => e.Title)));
environmentVariables.Add("Sonarr_EpisodeFile_Quality", episodeFile.Quality.Quality.Name);
environmentVariables.Add("Sonarr_EpisodeFile_QualityVersion", episodeFile.Quality.Revision.Version.ToString());
environmentVariables.Add("Sonarr_EpisodeFile_ReleaseGroup", episodeFile.ReleaseGroup ?? string.Empty);
environmentVariables.Add("Sonarr_EpisodeFile_SceneName", episodeFile.SceneName ?? string.Empty);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
var series = deleteMessage.Series;
var environmentVariables = new StringDictionary();
environmentVariables.Add("Sonarr_EventType", "SeriesDeleted");
environmentVariables.Add("Sonarr_Series_Id", series.Id.ToString());
environmentVariables.Add("Sonarr_Series_Title", series.Title);
environmentVariables.Add("Sonarr_Series_Path", series.Path);
environmentVariables.Add("Sonarr_Series_TvdbId", series.TvdbId.ToString());
environmentVariables.Add("Sonarr_Series_TvMazeId", series.TvMazeId.ToString());
environmentVariables.Add("Sonarr_Series_ImdbId", series.ImdbId ?? string.Empty);
environmentVariables.Add("Sonarr_Series_Type", series.SeriesType.ToString());
environmentVariables.Add("Sonarr_Series_DeletedFiles", deleteMessage.DeletedFiles.ToString());
ExecuteScript(environmentVariables);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
var environmentVariables = new StringDictionary();

@ -235,6 +235,42 @@ namespace NzbDrone.Core.Notifications.Discord
_proxy.SendPayload(payload, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
var series = deleteMessage.Series;
var episodes = deleteMessage.EpisodeFile.Episodes;
var attachments = new List<Embed>
{
new Embed
{
Title = GetTitle(series, episodes)
}
};
var payload = CreatePayload("Episode Deleted", attachments);
_proxy.SendPayload(payload, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
var series = deleteMessage.Series;
var attachments = new List<Embed>
{
new Embed
{
Title = series.Title,
Description = deleteMessage.DeletedFilesMessage
}
};
var payload = CreatePayload("Series Deleted", attachments);
_proxy.SendPayload(payload, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
var attachments = new List<Embed>

@ -33,6 +33,20 @@ namespace NzbDrone.Core.Notifications.Email
_emailService.SendEmail(Settings, EPISODE_DOWNLOADED_TITLE_BRANDED, body);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
var body = $"{deleteMessage.Message} deleted.";
_emailService.SendEmail(Settings, EPISODE_DELETED_TITLE_BRANDED, body);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
var body = $"{deleteMessage.Message}";
_emailService.SendEmail(Settings, SERIES_DELETED_TITLE_BRANDED, body);
}
public override void OnHealthIssue(HealthCheck.HealthCheck message)
{
_emailService.SendEmail(Settings, HEALTH_ISSUE_TITLE_BRANDED, message.Message);

@ -0,0 +1,20 @@
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Notifications
{
public class EpisodeDeleteMessage
{
public string Message { get; set; }
public Series Series { get; set; }
public EpisodeFile EpisodeFile { get; set; }
public DeleteMediaFileReason Reason { get; set; }
public override string ToString()
{
return Message;
}
}
}

@ -29,6 +29,16 @@ namespace NzbDrone.Core.Notifications.Gotify
_proxy.SendNotification(EPISODE_DOWNLOADED_TITLE, message.Message, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
_proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
_proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);

@ -10,12 +10,16 @@ namespace NzbDrone.Core.Notifications
void OnGrab(GrabMessage grabMessage);
void OnDownload(DownloadMessage message);
void OnRename(Series series);
void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage);
void OnSeriesDelete(SeriesDeleteMessage deleteMessage);
void OnHealthIssue(HealthCheck.HealthCheck healthCheck);
void ProcessQueue();
bool SupportsOnGrab { get; }
bool SupportsOnDownload { get; }
bool SupportsOnUpgrade { get; }
bool SupportsOnRename { get; }
bool SupportsOnSeriesDelete { get; }
bool SupportsOnEpisodeFileDelete { get; }
bool SupportsOnHealthIssue { get; }
}
}

@ -27,6 +27,15 @@ namespace NzbDrone.Core.Notifications.Join
_proxy.SendNotification(EPISODE_DOWNLOADED_TITLE_BRANDED, message.Message, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
_proxy.SendNotification(EPISODE_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
_proxy.SendNotification(SERIES_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck message)
{
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, message.Message, Settings);

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentValidation.Results;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Tv;
@ -10,10 +11,14 @@ namespace NzbDrone.Core.Notifications
{
protected const string EPISODE_GRABBED_TITLE = "Episode Grabbed";
protected const string EPISODE_DOWNLOADED_TITLE = "Episode Downloaded";
protected const string EPISODE_DELETED_TITLE = "Episode Deleted";
protected const string SERIES_DELETED_TITLE = "Series Deleted";
protected const string HEALTH_ISSUE_TITLE = "Health Check Failure";
protected const string EPISODE_GRABBED_TITLE_BRANDED = "Sonarr - " + EPISODE_GRABBED_TITLE;
protected const string EPISODE_DOWNLOADED_TITLE_BRANDED = "Sonarr - " + EPISODE_DOWNLOADED_TITLE;
protected const string EPISODE_DELETED_TITLE_BRANDED = "Sonarr - " + EPISODE_DELETED_TITLE;
protected const string SERIES_DELETED_TITLE_BRANDED = "Sonarr - " + SERIES_DELETED_TITLE;
protected const string HEALTH_ISSUE_TITLE_BRANDED = "Sonarr - " + HEALTH_ISSUE_TITLE;
public abstract string Name { get; }
@ -44,6 +49,16 @@ namespace NzbDrone.Core.Notifications
}
public virtual void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
}
public virtual void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
}
public virtual void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
@ -58,6 +73,8 @@ namespace NzbDrone.Core.Notifications
public bool SupportsOnRename => HasConcreteImplementation("OnRename");
public bool SupportsOnDownload => HasConcreteImplementation("OnDownload");
public bool SupportsOnUpgrade => SupportsOnDownload;
public bool SupportsOnSeriesDelete => HasConcreteImplementation("OnSeriesDelete");
public bool SupportsOnEpisodeFileDelete => HasConcreteImplementation("OnEpisodeFileDelete");
public bool SupportsOnHealthIssue => HasConcreteImplementation("OnHealthIssue");
protected TSettings Settings => (TSettings)Definition.Settings;

@ -8,14 +8,18 @@ namespace NzbDrone.Core.Notifications
public bool OnDownload { get; set; }
public bool OnUpgrade { get; set; }
public bool OnRename { get; set; }
public bool OnSeriesDelete { get; set; }
public bool OnEpisodeFileDelete { get; set; }
public bool OnHealthIssue { get; set; }
public bool SupportsOnGrab { get; set; }
public bool SupportsOnDownload { get; set; }
public bool SupportsOnUpgrade { get; set; }
public bool SupportsOnRename { get; set; }
public bool SupportsOnSeriesDelete { get; set; }
public bool SupportsOnEpisodeFileDelete { get; set; }
public bool SupportsOnHealthIssue { get; set; }
public bool IncludeHealthWarnings { get; set; }
public override bool Enable => OnGrab || OnDownload || (OnDownload && OnUpgrade) || OnHealthIssue;
public override bool Enable => OnGrab || OnDownload || (OnDownload && OnUpgrade) || OnSeriesDelete || OnEpisodeFileDelete || OnHealthIssue;
}
}

@ -13,6 +13,8 @@ namespace NzbDrone.Core.Notifications
List<INotification> OnDownloadEnabled();
List<INotification> OnUpgradeEnabled();
List<INotification> OnRenameEnabled();
List<INotification> OnSeriesDeleteEnabled();
List<INotification> OnEpisodeFileDeleteEnabled();
List<INotification> OnHealthIssueEnabled();
}
@ -43,6 +45,16 @@ namespace NzbDrone.Core.Notifications
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnRename).ToList();
}
public List<INotification> OnSeriesDeleteEnabled()
{
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnSeriesDelete).ToList();
}
public List<INotification> OnEpisodeFileDeleteEnabled()
{
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnEpisodeFileDelete).ToList();
}
public List<INotification> OnHealthIssueEnabled()
{
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnHealthIssue).ToList();
@ -56,6 +68,8 @@ namespace NzbDrone.Core.Notifications
definition.SupportsOnDownload = provider.SupportsOnDownload;
definition.SupportsOnUpgrade = provider.SupportsOnUpgrade;
definition.SupportsOnRename = provider.SupportsOnRename;
definition.SupportsOnSeriesDelete = provider.SupportsOnSeriesDelete;
definition.SupportsOnEpisodeFileDelete = provider.SupportsOnEpisodeFileDelete;
definition.SupportsOnHealthIssue = provider.SupportsOnHealthIssue;
}
}

@ -10,6 +10,7 @@ using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Tv.Events;
namespace NzbDrone.Core.Notifications
{
@ -17,7 +18,10 @@ namespace NzbDrone.Core.Notifications
: IHandle<EpisodeGrabbedEvent>,
IHandle<EpisodeImportedEvent>,
IHandle<SeriesRenamedEvent>,
IHandle<SeriesDeletedEvent>,
IHandle<EpisodeFileDeletedEvent>,
IHandle<HealthCheckFailedEvent>,
IHandleAsync<DeleteCompletedEvent>,
IHandleAsync<DownloadsProcessedEvent>,
IHandleAsync<RenameCompletedEvent>,
IHandleAsync<HealthCheckCompleteEvent>
@ -189,6 +193,50 @@ namespace NzbDrone.Core.Notifications
}
}
public void Handle(EpisodeFileDeletedEvent message)
{
var deleteMessage = new EpisodeDeleteMessage();
deleteMessage.Message = GetMessage(message.EpisodeFile.Series, message.EpisodeFile.Episodes, message.EpisodeFile.Quality);
deleteMessage.Series = message.EpisodeFile.Series;
deleteMessage.EpisodeFile = message.EpisodeFile;
deleteMessage.Reason = message.Reason;
foreach (var notification in _notificationFactory.OnEpisodeFileDeleteEnabled())
{
try
{
if (ShouldHandleSeries(notification.Definition, deleteMessage.EpisodeFile.Series))
{
notification.OnEpisodeFileDelete(deleteMessage);
}
}
catch (Exception ex)
{
_logger.Warn(ex, "Unable to send OnDelete notification to: " + notification.Definition.Name);
}
}
}
public void Handle(SeriesDeletedEvent message)
{
var deleteMessage = new SeriesDeleteMessage(message.Series,message.DeleteFiles);
foreach (var notification in _notificationFactory.OnSeriesDeleteEnabled())
{
try
{
if (ShouldHandleSeries(notification.Definition, deleteMessage.Series))
{
notification.OnSeriesDelete(deleteMessage);
}
}
catch (Exception ex)
{
_logger.Warn(ex, "Unable to send OnDelete notification to: " + notification.Definition.Name);
}
}
}
public void Handle(HealthCheckFailedEvent message)
{
foreach (var notification in _notificationFactory.OnHealthIssueEnabled())
@ -208,6 +256,11 @@ namespace NzbDrone.Core.Notifications
}
}
public void HandleAsync(DeleteCompletedEvent message)
{
ProcessQueue();
}
public void HandleAsync(DownloadsProcessedEvent message)
{
ProcessQueue();

@ -48,6 +48,19 @@ namespace NzbDrone.Core.Notifications.Plex.Server
UpdateIfEnabled(series);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
UpdateIfEnabled(deleteMessage.Series);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
if (deleteMessage.DeletedFiles)
{
UpdateIfEnabled(deleteMessage.Series);
}
}
private void UpdateIfEnabled(Series series)
{
if (Settings.UpdateLibrary)

@ -26,6 +26,16 @@ namespace NzbDrone.Core.Notifications.Prowl
_prowlProxy.SendNotification(EPISODE_DOWNLOADED_TITLE, message.Message, Settings.ApiKey, (ProwlPriority)Settings.Priority);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
_prowlProxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings.ApiKey, (ProwlPriority)Settings.Priority);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
_prowlProxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings.ApiKey, (ProwlPriority)Settings.Priority);
}
public override void OnHealthIssue(HealthCheck.HealthCheck message)
{
_prowlProxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings.ApiKey, (ProwlPriority)Settings.Priority);

@ -29,6 +29,15 @@ namespace NzbDrone.Core.Notifications.PushBullet
_proxy.SendNotification(EPISODE_DOWNLOADED_TITLE_BRANDED, message.Message, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
_proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
_proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings);

@ -26,6 +26,16 @@ namespace NzbDrone.Core.Notifications.Pushover
_proxy.SendNotification(EPISODE_DOWNLOADED_TITLE, message.Message, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
_proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
_proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);

@ -29,6 +29,15 @@ namespace NzbDrone.Core.Notifications.SendGrid
_proxy.SendNotification(EPISODE_DOWNLOADED_TITLE, message.Message, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
_proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
_proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);

@ -0,0 +1,28 @@
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Notifications
{
public class SeriesDeleteMessage
{
public string Message { get; set; }
public Series Series { get; set; }
public bool DeletedFiles { get; set; }
public string DeletedFilesMessage { get; set; }
public override string ToString()
{
return Message;
}
public SeriesDeleteMessage (Series series, bool deleteFiles)
{
Series = series;
DeletedFiles = deleteFiles;
DeletedFilesMessage = DeletedFiles ?
"Series removed and all files were deleted" :
"Series removed, files were not deleted";
Message = series.Title + " - " + DeletedFilesMessage;
}
}
}

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentValidation.Results;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Notifications.Slack.Payloads;
@ -70,6 +71,37 @@ namespace NzbDrone.Core.Notifications.Slack
_proxy.SendPayload(payload, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
var attachments = new List<Attachment>
{
new Attachment
{
Title = GetTitle(deleteMessage.Series, deleteMessage.EpisodeFile.Episodes),
}
};
var payload = CreatePayload("Episode Deleted", attachments);
_proxy.SendPayload(payload, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
var attachments = new List<Attachment>
{
new Attachment
{
Title = deleteMessage.Series.Title,
Text = deleteMessage.DeletedFilesMessage
}
};
var payload = CreatePayload("Series Deleted", attachments);
_proxy.SendPayload(payload, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
var attachments = new List<Attachment>
@ -146,5 +178,21 @@ namespace NzbDrone.Core.Notifications.Slack
return payload;
}
private string GetTitle(Series series, List<Episode> episodes)
{
if (series.SeriesType == SeriesTypes.Daily)
{
var episode = episodes.First();
return $"{series.Title} - {episode.AirDate} - {episode.Title}";
}
var episodeNumbers = string.Concat(episodes.Select(e => e.EpisodeNumber)
.Select(i => string.Format("x{0:00}", i)));
var episodeTitles = string.Join(" + ", episodes.Select(e => e.Title));
return $"{series.Title} - {episodes.First().SeasonNumber}{episodeNumbers} - {episodeTitles}";
}
}
}

@ -47,6 +47,25 @@ namespace NzbDrone.Core.Notifications.Synology
}
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
if (Settings.UpdateLibrary)
{
var fullPath = Path.Combine(deleteMessage.Series.Path, deleteMessage.EpisodeFile.RelativePath);
_indexerProxy.DeleteFile(fullPath);
}
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
if (deleteMessage.DeletedFiles)
{
if (Settings.UpdateLibrary)
{
_indexerProxy.DeleteFolder(deleteMessage.Series.Path);
}
}
}
public override ValidationResult Test()
{

@ -26,6 +26,16 @@ namespace NzbDrone.Core.Notifications.Telegram
_proxy.SendNotification(EPISODE_DOWNLOADED_TITLE, message.Message, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
_proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
_proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);

@ -29,6 +29,16 @@ namespace NzbDrone.Core.Notifications.Twitter
_twitterService.SendNotification($"Imported: {message.Message}", Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
_twitterService.SendNotification($"Episode Deleted: {deleteMessage.Message}", Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
_twitterService.SendNotification($"Series Deleted: {deleteMessage.Message}", Settings);
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
_twitterService.SendNotification($"Health Issue: {healthCheck.Message}", Settings);

@ -76,6 +76,27 @@ namespace NzbDrone.Core.Notifications.Webhook
_proxy.SendWebhook(payload, Settings);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
var payload = new WebhookEpisodeDeletePayload
{
EventType = WebhookEventType.Delete,
Series = new WebhookSeries(deleteMessage.Series),
Episodes = deleteMessage.EpisodeFile.Episodes.Value.ConvertAll(x => new WebhookEpisode(x))
};
_proxy.SendWebhook(payload, Settings);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
var payload = new WebhookSeriesDeletePayload
{
EventType = WebhookEventType.Delete,
Series = new WebhookSeries(deleteMessage.Series),
DeletedFiles = deleteMessage.DeletedFiles
};
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{
var payload = new WebhookHealthPayload

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace NzbDrone.Core.Notifications.Webhook
{
public class WebhookEpisodeDeletePayload : WebhookPayload
{
public WebhookSeries Series { get; set; }
public List<WebhookEpisode> Episodes { get; set; }
}
}

@ -12,6 +12,7 @@ namespace NzbDrone.Core.Notifications.Webhook
Grab,
Download,
Rename,
Delete,
Health
}
}

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace NzbDrone.Core.Notifications.Webhook
{
public class WebhookSeriesDeletePayload : WebhookPayload
{
public WebhookSeries Series { get; set; }
public bool DeletedFiles { get; set; }
}
}

@ -40,6 +40,24 @@ namespace NzbDrone.Core.Notifications.Xbmc
{
UpdateAndClean(series);
}
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
{
const string header = "Sonarr - Deleted";
Notify(Settings, header, deleteMessage.Message);
UpdateAndClean(deleteMessage.Series, true);
}
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{
if (deleteMessage.DeletedFiles)
{
const string header = "Sonarr - Deleted";
Notify(Settings, header, deleteMessage.Message);
UpdateAndClean(deleteMessage.Series, true);
}
}
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{

@ -9,11 +9,15 @@ namespace Sonarr.Api.V3.Notifications
public bool OnDownload { get; set; }
public bool OnUpgrade { get; set; }
public bool OnRename { get; set; }
public bool OnSeriesDelete { get; set; }
public bool OnEpisodeFileDelete { get; set; }
public bool OnHealthIssue { get; set; }
public bool SupportsOnGrab { get; set; }
public bool SupportsOnDownload { get; set; }
public bool SupportsOnUpgrade { get; set; }
public bool SupportsOnRename { get; set; }
public bool SupportsOnSeriesDelete { get; set; }
public bool SupportsOnEpisodeFileDelete { get; set; }
public bool SupportsOnHealthIssue { get; set; }
public bool IncludeHealthWarnings { get; set; }
public string TestCommand { get; set; }
@ -31,11 +35,15 @@ namespace Sonarr.Api.V3.Notifications
resource.OnDownload = definition.OnDownload;
resource.OnUpgrade = definition.OnUpgrade;
resource.OnRename = definition.OnRename;
resource.OnSeriesDelete = definition.OnSeriesDelete;
resource.OnEpisodeFileDelete = definition.OnEpisodeFileDelete;
resource.OnHealthIssue = definition.OnHealthIssue;
resource.SupportsOnGrab = definition.SupportsOnGrab;
resource.SupportsOnDownload = definition.SupportsOnDownload;
resource.SupportsOnUpgrade = definition.SupportsOnUpgrade;
resource.SupportsOnRename = definition.SupportsOnRename;
resource.SupportsOnSeriesDelete = definition.SupportsOnSeriesDelete;
resource.SupportsOnEpisodeFileDelete = definition.SupportsOnEpisodeFileDelete;
resource.SupportsOnHealthIssue = definition.SupportsOnHealthIssue;
resource.IncludeHealthWarnings = definition.IncludeHealthWarnings;
@ -52,11 +60,15 @@ namespace Sonarr.Api.V3.Notifications
definition.OnDownload = resource.OnDownload;
definition.OnUpgrade = resource.OnUpgrade;
definition.OnRename = resource.OnRename;
definition.OnSeriesDelete = resource.OnSeriesDelete;
definition.OnEpisodeFileDelete = resource.OnEpisodeFileDelete;
definition.OnHealthIssue = resource.OnHealthIssue;
definition.SupportsOnGrab = resource.SupportsOnGrab;
definition.SupportsOnDownload = resource.SupportsOnDownload;
definition.SupportsOnUpgrade = resource.SupportsOnUpgrade;
definition.SupportsOnRename = resource.SupportsOnRename;
definition.SupportsOnSeriesDelete = resource.SupportsOnSeriesDelete;
definition.SupportsOnEpisodeFileDelete = resource.SupportsOnEpisodeFileDelete;
definition.SupportsOnHealthIssue = resource.SupportsOnHealthIssue;
definition.IncludeHealthWarnings = resource.IncludeHealthWarnings;

Loading…
Cancel
Save