From be46d5ae8f5da52a45ee834c4c035067fe568969 Mon Sep 17 00:00:00 2001 From: Robin Dadswell <19610103+RobinDadswell@users.noreply.github.com> Date: Thu, 9 Dec 2021 21:57:55 +0000 Subject: [PATCH] New: On delete notifications --- .../Notifications/Notification.js | 120 +++++++++++++----- .../Notifications/NotificationEventItems.js | 51 ++++++++ .../Store/Actions/Settings/notifications.js | 4 + .../NotificationBaseFixture.cs | 23 ++++ .../Books/Events/AuthorDeletedEvent.cs | 1 + .../Books/Events/BookDeletedEvent.cs | 2 +- .../021_add_on_delete_to_notifications.cs | 17 +++ src/NzbDrone.Core/Datastore/TableMapping.cs | 4 + src/NzbDrone.Core/Localization/Core/en.json | 25 +++- .../MediaFiles/Events/DeleteCompletedEvent.cs | 8 ++ .../MediaFiles/MediaFileDeletionService.cs | 7 + .../Notifications/AuthorDeleteMessage.cs | 27 ++++ .../Notifications/BookDeleteMessage.cs | 28 ++++ .../Notifications/BookFileDeleteMessage.cs | 19 +++ .../Notifications/Boxcar/Boxcar.cs | 15 +++ .../CustomScript/CustomScript.cs | 67 ++++++++++ .../Notifications/Discord/Discord.cs | 48 +++++++ .../Notifications/Discord/DiscordColors.cs | 6 +- .../Notifications/Email/Email.cs | 21 +++ .../Goodreads/Bookshelf/GoodreadsBookshelf.cs | 48 +++++++ .../Notifications/Gotify/Gotify.cs | 15 +++ .../Notifications/INotification.cs | 8 ++ src/NzbDrone.Core/Notifications/Join/Join.cs | 15 +++ .../Notifications/Mailgun/Mailgun.cs | 15 +++ .../Notifications/Notifiarr/Notifiarr.cs | 67 ++++++++++ .../Notifications/NotificationBase.cs | 26 ++++ .../Notifications/NotificationDefinition.cs | 10 +- .../Notifications/NotificationFactory.cs | 28 ++++ .../Notifications/NotificationService.cs | 97 +++++++++++++- .../Notifications/Prowl/Prowl.cs | 15 +++ .../Notifications/PushBullet/PushBullet.cs | 15 +++ .../Notifications/Pushover/Pushover.cs | 15 +++ .../Notifications/SendGrid/SendGrid.cs | 15 +++ .../Notifications/Slack/Slack.cs | 48 +++++++ .../Notifications/Subsonic/Subsonic.cs | 32 +++++ .../Notifications/Synology/SynologyIndexer.cs | 27 ++++ .../Notifications/Telegram/Telegram.cs | 15 +++ .../Notifications/Twitter/Twitter.cs | 15 +++ .../Notifications/Webhook/Webhook.cs | 37 ++++++ .../Webhook/WebhookAuthorDeletePayload.cs | 8 ++ .../Webhook/WebhookBookDeletePayload.cs | 8 ++ .../Webhook/WebhookBookFileDeletePayload.cs | 9 ++ .../Notifications/Webhook/WebhookEventType.cs | 1 + .../Notifications/NotificationResource.cs | 24 ++++ 44 files changed, 1065 insertions(+), 41 deletions(-) create mode 100644 src/NzbDrone.Core/Datastore/Migration/021_add_on_delete_to_notifications.cs create mode 100644 src/NzbDrone.Core/MediaFiles/Events/DeleteCompletedEvent.cs create mode 100644 src/NzbDrone.Core/Notifications/AuthorDeleteMessage.cs create mode 100644 src/NzbDrone.Core/Notifications/BookDeleteMessage.cs create mode 100644 src/NzbDrone.Core/Notifications/BookFileDeleteMessage.cs create mode 100644 src/NzbDrone.Core/Notifications/Webhook/WebhookAuthorDeletePayload.cs create mode 100644 src/NzbDrone.Core/Notifications/Webhook/WebhookBookDeletePayload.cs create mode 100644 src/NzbDrone.Core/Notifications/Webhook/WebhookBookFileDeletePayload.cs diff --git a/frontend/src/Settings/Notifications/Notifications/Notification.js b/frontend/src/Settings/Notifications/Notifications/Notification.js index 739712884..63df259eb 100644 --- a/frontend/src/Settings/Notifications/Notifications/Notification.js +++ b/frontend/src/Settings/Notifications/Notifications/Notification.js @@ -59,6 +59,10 @@ class Notification extends Component { onReleaseImport, onUpgrade, onRename, + onAuthorDelete, + onBookDelete, + onBookFileDelete, + onBookFileDeleteForUpgrade, onHealthIssue, onDownloadFailure, onImportFailure, @@ -67,6 +71,10 @@ class Notification extends Component { supportsOnReleaseImport, supportsOnUpgrade, supportsOnRename, + supportsOnAuthorDelete, + supportsOnBookDelete, + supportsOnBookFileDelete, + supportsOnBookFileDeleteForUpgrade, supportsOnHealthIssue, supportsOnDownloadFailure, supportsOnImportFailure, @@ -84,70 +92,110 @@ class Notification extends Component { { - supportsOnGrab && onGrab && + supportsOnGrab && onGrab ? + {translate('OnGrab')} + : + null } { - supportsOnReleaseImport && onReleaseImport && + supportsOnReleaseImport && onReleaseImport ? + {translate('OnReleaseImport')} + : + null } { - supportsOnUpgrade && onReleaseImport && onUpgrade && + supportsOnUpgrade && onReleaseImport && onUpgrade ? + {translate('OnUpgrade')} + : + null } { - supportsOnRename && onRename && + supportsOnRename && onRename ? + {translate('OnRename')} + : + null } { - supportsOnBookRetag && onBookRetag && + supportsOnBookRetag && onBookRetag ? + {translate('OnBookTagUpdate')} + : + null } { - supportsOnHealthIssue && onHealthIssue && + supportsOnAuthorDelete && onAuthorDelete ? + {translate('OnAuthorDelete')} + : + null } { - supportsOnDownloadFailure && onDownloadFailure && + supportsOnBookDelete && onBookDelete ? + : + null + } + + { + supportsOnBookFileDelete && onBookFileDelete ? + : + null + } + + { + supportsOnBookFileDeleteForUpgrade && onBookFileDelete && onBookFileDeleteForUpgrade ? + : + null + } + + { + supportsOnHealthIssue && onHealthIssue ? + : + null + } + + { + supportsOnDownloadFailure && onDownloadFailure ? + {translate('OnDownloadFailure')} + : + null } { - supportsOnImportFailure && onImportFailure && + supportsOnImportFailure && onImportFailure ? + {translate('OnImportFailure')} + : + null } { - !onGrab && !onReleaseImport && !onRename && !onBookRetag && - !onHealthIssue && !onDownloadFailure && !onImportFailure && - + !onGrab && !onReleaseImport && !onRename && !onBookRetag && !onHealthIssue && !onDownloadFailure && !onImportFailure ? + : + null } +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
i.SupportsOnReleaseImport) .Ignore(i => i.SupportsOnUpgrade) .Ignore(i => i.SupportsOnRename) + .Ignore(i => i.SupportsOnAuthorDelete) + .Ignore(i => i.SupportsOnBookDelete) + .Ignore(i => i.SupportsOnBookFileDelete) + .Ignore(i => i.SupportsOnBookFileDeleteForUpgrade) .Ignore(i => i.SupportsOnHealthIssue) .Ignore(i => i.SupportsOnDownloadFailure) .Ignore(i => i.SupportsOnImportFailure) diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 49a142f10..36a8ad030 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -70,11 +70,11 @@ "BookAvailableButMissing": "Book Available, but Missing", "BookDownloaded": "Book Downloaded", "BookEditor": "Book Editor", - "BookIndex": "Book Index", "BookFileCountBookCountTotalTotalBookCountInterp": "{0} / {1} (Total: {2})", "BookFileCounttotalBookCountBooksDownloadedInterp": "{0}/{1} books downloaded", "BookFilesCountMessage": "No book files", "BookHasNotAired": "Book has not aired", + "BookIndex": "Book Index", "BookIsDownloading": "Book is downloading", "BookIsDownloadingInterp": "Book is downloading - {0}% {1}", "BookIsNotMonitored": "Book is not monitored", @@ -188,6 +188,7 @@ "DetailedProgressBar": "Detailed Progress Bar", "DetailedProgressBarHelpText": "Show text on progess bar", "Development": "Development", + "Disabled": "Disabled", "DiscCount": "Disc Count", "DiscNumber": "Disc Number", "DiskSpace": "Disk Space", @@ -429,13 +430,29 @@ "NotificationTriggers": "Notification Triggers", "NotMonitored": "Not Monitored", "NoUpdatesAreAvailable": "No updates are available", + "OnAuthorDelete": "On Author Delete", + "OnAuthorDeleteHelpText": "On Author Delete", + "OnBookDelete": "On Book Delete", + "OnBookDeleteHelpText": "On Book Delete", + "OnBookFileDelete": "On Book File Delete", + "OnBookFileDeleteForUpgrade": "On Book File Delete For Upgrade", + "OnBookFileDeleteForUpgradeHelpText": "On Book File Delete For Upgrade", + "OnBookFileDeleteHelpText": "On Book File Delete", "OnBookRetagHelpText": "On Book Retag", + "OnBookTagUpdate": "On Book Tag Update", + "OnDownloadFailure": "On Download Failure", "OnDownloadFailureHelpText": "On Download Failure", + "OnGrab": "On Grab", "OnGrabHelpText": "On Grab", + "OnHealthIssue": "On Health Issue", "OnHealthIssueHelpText": "On Health Issue", + "OnImportFailure": "On Import Failure", "OnImportFailureHelpText": "On Import Failure", + "OnReleaseImport": "On Release Import", "OnReleaseImportHelpText": "On Release Import", + "OnRename": "On Rename", "OnRenameHelpText": "On Rename", + "OnUpgrade": "On Upgrade", "OnUpgradeHelpText": "On Upgrade", "OpenBrowserOnStart": "Open browser on start", "Options": "Options", @@ -588,9 +605,9 @@ "SetPermissionsLinuxHelpTextWarning": "If you're unsure what these settings do, do not alter them.", "Settings": "Settings", "ShortDateFormat": "Short Date Format", - "ShouldMonitorHelpText": "Monitor new authors and books added from this list", "ShouldMonitorExisting": "Monitor existing books", "ShouldMonitorExistingHelpText": "Automatically monitor books on this list which are already in Readarr", + "ShouldMonitorHelpText": "Monitor new authors and books added from this list", "ShouldSearchHelpText": "Search indexers for newly added items. Use with caution for large lists.", "ShowBanners": "Show Banners", "ShowBannersHelpText": "Show banners instead of names", @@ -729,13 +746,13 @@ "UnmonitoredHelpText": "Include unmonitored books in the iCal feed", "UnselectAll": "Unselect All", "UpdateAll": "Update all", - "UpdateSelected": "Updated selected", "UpdateAutomaticallyHelpText": "Automatically download and install updates. You will still be able to install from System: Updates", "UpdateCovers": "Update Covers", "UpdateCoversHelpText": "Set book covers in Calibre to match those in Readarr", "UpdateMechanismHelpText": "Use Readarr's built-in updater or a script", "Updates": "Updates", "UpdateScriptPathHelpText": "Path to a custom script that takes an extracted update package and handle the remainder of the update process", + "UpdateSelected": "Updated selected", "UpdatingIsDisabledInsideADockerContainerUpdateTheContainerImageInstead": "Updating is disabled inside a docker container. Update the container image instead.", "UpgradeAllowedHelpText": "If disabled qualities will not be upgraded", "Uptime": "Uptime", @@ -769,4 +786,4 @@ "WriteTagsSync": "All files; keep in sync with Goodreads", "Year": "Year", "YesCancel": "Yes, Cancel" -} \ No newline at end of file +} diff --git a/src/NzbDrone.Core/MediaFiles/Events/DeleteCompletedEvent.cs b/src/NzbDrone.Core/MediaFiles/Events/DeleteCompletedEvent.cs new file mode 100644 index 000000000..f987bc1c2 --- /dev/null +++ b/src/NzbDrone.Core/MediaFiles/Events/DeleteCompletedEvent.cs @@ -0,0 +1,8 @@ +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.MediaFiles.Events +{ + public class DeleteCompletedEvent : IEvent + { + } +} diff --git a/src/NzbDrone.Core/MediaFiles/MediaFileDeletionService.cs b/src/NzbDrone.Core/MediaFiles/MediaFileDeletionService.cs index ba6a5fdf2..2fd57c370 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaFileDeletionService.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaFileDeletionService.cs @@ -33,6 +33,7 @@ public class MediaFileDeletionService : IDeleteMediaFiles, private readonly IMediaFileService _mediaFileService; private readonly IAuthorService _authorService; private readonly IConfigService _configService; + private readonly IEventAggregator _eventAggregator; private readonly IRootFolderService _rootFolderService; private readonly ICalibreProxy _calibre; private readonly Logger _logger; @@ -42,6 +43,7 @@ public MediaFileDeletionService(IDiskProvider diskProvider, IMediaFileService mediaFileService, IAuthorService authorService, IConfigService configService, + IEventAggregator eventAggregator, IRootFolderService rootFolderService, ICalibreProxy calibre, Logger logger) @@ -51,6 +53,7 @@ public MediaFileDeletionService(IDiskProvider diskProvider, _mediaFileService = mediaFileService; _authorService = authorService; _configService = configService; + _eventAggregator = eventAggregator; _rootFolderService = rootFolderService; _calibre = calibre; _logger = logger; @@ -97,6 +100,8 @@ public void DeleteTrackFile(BookFile bookFile, string subfolder = "") // Delete the track file from the database to clean it up even if the file was already deleted _mediaFileService.Delete(bookFile, DeleteMediaFileReason.Manual); + + _eventAggregator.PublishEvent(new DeleteCompletedEvent()); } private void DeleteFile(BookFile bookFile, string subfolder = "") @@ -178,6 +183,8 @@ public void HandleAsync(AuthorDeletedEvent message) { _recycleBinProvider.DeleteFolder(message.Author.Path); } + + _eventAggregator.PublishEvent(new DeleteCompletedEvent()); } } } diff --git a/src/NzbDrone.Core/Notifications/AuthorDeleteMessage.cs b/src/NzbDrone.Core/Notifications/AuthorDeleteMessage.cs new file mode 100644 index 000000000..7b245a16d --- /dev/null +++ b/src/NzbDrone.Core/Notifications/AuthorDeleteMessage.cs @@ -0,0 +1,27 @@ +using NzbDrone.Core.Books; + +namespace NzbDrone.Core.Notifications +{ + public class AuthorDeleteMessage + { + public string Message { get; set; } + public Author Author { get; set; } + public bool DeletedFiles { get; set; } + public string DeletedFilesMessage { get; set; } + + public override string ToString() + { + return Message; + } + + public AuthorDeleteMessage(Author author, bool deleteFiles) + { + Author = author; + DeletedFiles = deleteFiles; + DeletedFilesMessage = DeletedFiles ? + "Author removed and all files were deleted" : + "Author removed, files were not deleted"; + Message = author.Name + " - " + DeletedFilesMessage; + } + } +} diff --git a/src/NzbDrone.Core/Notifications/BookDeleteMessage.cs b/src/NzbDrone.Core/Notifications/BookDeleteMessage.cs new file mode 100644 index 000000000..c46f02cab --- /dev/null +++ b/src/NzbDrone.Core/Notifications/BookDeleteMessage.cs @@ -0,0 +1,28 @@ +using NzbDrone.Core.Books; +using NzbDrone.Core.MediaFiles; + +namespace NzbDrone.Core.Notifications +{ + public class BookDeleteMessage + { + public string Message { get; set; } + public Book Book { get; set; } + public bool DeletedFiles { get; set; } + public string DeletedFilesMessage { get; set; } + + public override string ToString() + { + return Message; + } + + public BookDeleteMessage(Book book, bool deleteFiles) + { + Book = book; + DeletedFiles = deleteFiles; + DeletedFilesMessage = DeletedFiles ? + "Book removed and all files were deleted" : + "Book removed, files were not deleted"; + Message = book.Title + " - " + DeletedFilesMessage; + } + } +} diff --git a/src/NzbDrone.Core/Notifications/BookFileDeleteMessage.cs b/src/NzbDrone.Core/Notifications/BookFileDeleteMessage.cs new file mode 100644 index 000000000..938f11bf6 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/BookFileDeleteMessage.cs @@ -0,0 +1,19 @@ +using NzbDrone.Core.Books; +using NzbDrone.Core.MediaFiles; + +namespace NzbDrone.Core.Notifications +{ + public class BookFileDeleteMessage + { + public string Message { get; set; } + public Book Book { get; set; } + public BookFile BookFile { get; set; } + + public DeleteMediaFileReason Reason { get; set; } + + public override string ToString() + { + return Message; + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Boxcar/Boxcar.cs b/src/NzbDrone.Core/Notifications/Boxcar/Boxcar.cs index 178170b41..033c24c71 100644 --- a/src/NzbDrone.Core/Notifications/Boxcar/Boxcar.cs +++ b/src/NzbDrone.Core/Notifications/Boxcar/Boxcar.cs @@ -26,6 +26,21 @@ public override void OnReleaseImport(BookDownloadMessage message) _proxy.SendNotification(BOOK_DOWNLOADED_TITLE, message.Message, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _proxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck message) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs index 4bdd413ac..9b1316f11 100644 --- a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs +++ b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs @@ -105,6 +105,73 @@ public override void OnRename(Author author) ExecuteScript(environmentVariables); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + var author = deleteMessage.Author; + var environmentVariables = new StringDictionary(); + + environmentVariables.Add("Readarr_EventType", "AuthorDelete"); + environmentVariables.Add("Readarr_Author_Id", author.Id.ToString()); + environmentVariables.Add("Readarr_Author_Name", author.Name); + environmentVariables.Add("Readarr_Author_Path", author.Path); + environmentVariables.Add("Readarr_Author_GoodreadsId", author.ForeignAuthorId); + environmentVariables.Add("Readarr_Author_DeletedFiles", deleteMessage.DeletedFiles.ToString()); + + ExecuteScript(environmentVariables); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + var author = deleteMessage.Book.Author.Value; + var book = deleteMessage.Book; + + var environmentVariables = new StringDictionary(); + + environmentVariables.Add("Readarr_EventType", "BookDelete"); + environmentVariables.Add("Readarr_Author_Id", author.Id.ToString()); + environmentVariables.Add("Readarr_Author_Name", author.Name); + environmentVariables.Add("Readarr_Author_Path", author.Path); + environmentVariables.Add("Readarr_Author_GoodreadsId", author.ForeignAuthorId); + environmentVariables.Add("Readarr_Book_Id", book.Id.ToString()); + environmentVariables.Add("Readarr_Book_Title", book.Title); + environmentVariables.Add("Readarr_Book_GoodreadsId", book.ForeignBookId); + environmentVariables.Add("Readarr_Book_DeletedFiles", deleteMessage.DeletedFiles.ToString()); + + ExecuteScript(environmentVariables); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + var author = deleteMessage.Book.Author.Value; + var book = deleteMessage.Book; + var bookFile = deleteMessage.BookFile; + var edition = bookFile.Edition.Value; + + var environmentVariables = new StringDictionary(); + + environmentVariables.Add("Readarr_EventType", "BookFileDelete"); + environmentVariables.Add("Readarr_Delete_Reason", deleteMessage.Reason.ToString()); + environmentVariables.Add("Readarr_Author_Id", author.Id.ToString()); + environmentVariables.Add("Readarr_Author_Name", author.Name); + environmentVariables.Add("Readarr_Author_GoodreadsId", author.ForeignAuthorId); + environmentVariables.Add("Readarr_Book_Id", book.Id.ToString()); + environmentVariables.Add("Readarr_Book_Title", book.Title); + environmentVariables.Add("Readarr_Book_GoodreadsId", book.ForeignBookId); + environmentVariables.Add("Readarr_BookFile_Id", bookFile.Id.ToString()); + environmentVariables.Add("Readarr_BookFile_Path", bookFile.Path); + environmentVariables.Add("Readarr_BookFile_Quality", bookFile.Quality.Quality.Name); + environmentVariables.Add("Readarr_BookFile_QualityVersion", bookFile.Quality.Revision.Version.ToString()); + environmentVariables.Add("Readarr_BookFile_ReleaseGroup", bookFile.ReleaseGroup ?? string.Empty); + environmentVariables.Add("Readarr_BookFile_SceneName", bookFile.SceneName ?? string.Empty); + environmentVariables.Add("Readarr_BookFile_Edition_Id", edition.Id.ToString()); + environmentVariables.Add("Readarr_BookFile_Edition_Name", edition.Title); + environmentVariables.Add("Readarr_BookFile_Edition_GoodreadsId", edition.ForeignEditionId); + environmentVariables.Add("Readarr_BookFile_Edition_Isbn13", edition.Isbn13); + environmentVariables.Add("Readarr_BookFile_Edition_Asin", edition.Asin); + + ExecuteScript(environmentVariables); + } + public override void OnBookRetag(BookRetagMessage message) { var author = message.Author; diff --git a/src/NzbDrone.Core/Notifications/Discord/Discord.cs b/src/NzbDrone.Core/Notifications/Discord/Discord.cs index 6480d765e..1fa1e7383 100644 --- a/src/NzbDrone.Core/Notifications/Discord/Discord.cs +++ b/src/NzbDrone.Core/Notifications/Discord/Discord.cs @@ -69,6 +69,54 @@ public override void OnRename(Author author) _proxy.SendPayload(payload, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + var attachments = new List + { + new Embed + { + Title = deleteMessage.Author.Name, + Description = deleteMessage.DeletedFilesMessage + } + }; + + var payload = CreatePayload("Author Deleted", attachments); + + _proxy.SendPayload(payload, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + var attachments = new List + { + new Embed + { + Title = $"${deleteMessage.Book.Author.Value.Name} - ${deleteMessage.Book.Title}", + Description = deleteMessage.DeletedFilesMessage + } + }; + + var payload = CreatePayload("Book Deleted", attachments); + + _proxy.SendPayload(payload, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + var attachments = new List + { + new Embed + { + Title = $"${deleteMessage.Book.Author.Value.Name} - ${deleteMessage.Book.Title} - file deleted", + Description = deleteMessage.BookFile.Path + } + }; + + var payload = CreatePayload("Book File Deleted", attachments); + + _proxy.SendPayload(payload, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { var attachments = new List diff --git a/src/NzbDrone.Core/Notifications/Discord/DiscordColors.cs b/src/NzbDrone.Core/Notifications/Discord/DiscordColors.cs index 16590aade..3524af890 100644 --- a/src/NzbDrone.Core/Notifications/Discord/DiscordColors.cs +++ b/src/NzbDrone.Core/Notifications/Discord/DiscordColors.cs @@ -1,9 +1,11 @@ -namespace NzbDrone.Core.Notifications.Discord +namespace NzbDrone.Core.Notifications.Discord { public enum DiscordColors { Danger = 15749200, Success = 2605644, - Warning = 16753920 + Warning = 16753920, + Standard = 16761392, + Upgrade = 4089856 } } diff --git a/src/NzbDrone.Core/Notifications/Email/Email.cs b/src/NzbDrone.Core/Notifications/Email/Email.cs index 666bd05de..86956f318 100644 --- a/src/NzbDrone.Core/Notifications/Email/Email.cs +++ b/src/NzbDrone.Core/Notifications/Email/Email.cs @@ -40,6 +40,27 @@ public override void OnReleaseImport(BookDownloadMessage message) SendEmail(Settings, BOOK_DOWNLOADED_TITLE_BRANDED, body, false, paths); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + var body = deleteMessage.Message; + + SendEmail(Settings, AUTHOR_DELETED_TITlE_BRANDED, body); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + var body = deleteMessage.Message; + + SendEmail(Settings, AUTHOR_DELETED_TITlE_BRANDED, body); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + var body = deleteMessage.Message; + + SendEmail(Settings, AUTHOR_DELETED_TITlE_BRANDED, body); + } + public override void OnHealthIssue(HealthCheck.HealthCheck message) { SendEmail(Settings, HEALTH_ISSUE_TITLE_BRANDED, message.Message); diff --git a/src/NzbDrone.Core/Notifications/Goodreads/Bookshelf/GoodreadsBookshelf.cs b/src/NzbDrone.Core/Notifications/Goodreads/Bookshelf/GoodreadsBookshelf.cs index be6a37da9..5769d5041 100644 --- a/src/NzbDrone.Core/Notifications/Goodreads/Bookshelf/GoodreadsBookshelf.cs +++ b/src/NzbDrone.Core/Notifications/Goodreads/Bookshelf/GoodreadsBookshelf.cs @@ -40,6 +40,54 @@ public override void OnReleaseImport(BookDownloadMessage message) AddToShelves(bookId, Settings.AddIds); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + if (deleteMessage.DeletedFiles) + { + foreach (var shelf in Settings.RemoveIds) + { + var listBooks = SearchShelf(shelf, deleteMessage.Author.Name); + var toRemove = listBooks.Where(x => deleteMessage.Author.Books.Value.Select(b => b.ForeignBookId).Contains(x.Book.WorkId.ToString())); + + foreach (var listBook in toRemove) + { + RemoveBookFromShelves(listBook.Book.Id, shelf); + } + } + } + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + if (deleteMessage.DeletedFiles) + { + foreach (var shelf in Settings.RemoveIds) + { + var listBooks = SearchShelf(shelf, deleteMessage.Book.Author.Value.Name); + var toRemove = listBooks.Where(x => x.Book.WorkId.ToString() == deleteMessage.Book.ForeignBookId); + + foreach (var listBook in toRemove) + { + RemoveBookFromShelves(listBook.Book.Id, shelf); + } + } + } + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + foreach (var shelf in Settings.RemoveIds) + { + var listBooks = SearchShelf(shelf, deleteMessage.Book.Author.Value.Name); + var toRemove = listBooks.Where(x => x.Book.WorkId.ToString() == deleteMessage.Book.ForeignBookId); + + foreach (var listBook in toRemove) + { + RemoveBookFromShelves(listBook.Book.Id, shelf); + } + } + } + public override object RequestAction(string action, IDictionary query) { if (action == "getBookshelves") diff --git a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs index f5174cb04..d4ab4a392 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs @@ -29,6 +29,21 @@ public override void OnReleaseImport(BookDownloadMessage message) _proxy.SendNotification(BOOK_DOWNLOADED_TITLE, message.Message, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _proxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/INotification.cs b/src/NzbDrone.Core/Notifications/INotification.cs index dafc099ba..de9fe4804 100644 --- a/src/NzbDrone.Core/Notifications/INotification.cs +++ b/src/NzbDrone.Core/Notifications/INotification.cs @@ -10,14 +10,22 @@ public interface INotification : IProvider void OnGrab(GrabMessage grabMessage); void OnReleaseImport(BookDownloadMessage message); void OnRename(Author author); + void OnAuthorDelete(AuthorDeleteMessage deleteMessage); + void OnBookDelete(BookDeleteMessage deleteMessage); + void OnBookFileDelete(BookFileDeleteMessage deleteMessage); void OnHealthIssue(HealthCheck.HealthCheck healthCheck); void OnDownloadFailure(DownloadFailedMessage message); void OnImportFailure(BookDownloadMessage message); void OnBookRetag(BookRetagMessage message); + void ProcessQueue(); bool SupportsOnGrab { get; } bool SupportsOnReleaseImport { get; } bool SupportsOnUpgrade { get; } bool SupportsOnRename { get; } + bool SupportsOnAuthorDelete { get; } + bool SupportsOnBookDelete { get; } + bool SupportsOnBookFileDelete { get; } + bool SupportsOnBookFileDeleteForUpgrade { get; } bool SupportsOnHealthIssue { get; } bool SupportsOnDownloadFailure { get; } bool SupportsOnImportFailure { get; } diff --git a/src/NzbDrone.Core/Notifications/Join/Join.cs b/src/NzbDrone.Core/Notifications/Join/Join.cs index 6a8ffb641..9dcfd9d4e 100644 --- a/src/NzbDrone.Core/Notifications/Join/Join.cs +++ b/src/NzbDrone.Core/Notifications/Join/Join.cs @@ -27,6 +27,21 @@ public override void OnReleaseImport(BookDownloadMessage message) _proxy.SendNotification(BOOK_DOWNLOADED_TITLE_BRANDED, message.Message, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _proxy.SendNotification(AUTHOR_DELETED_TITlE_BRANDED, deleteMessage.Message, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_FILE_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck message) { _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, message.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs b/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs index 89b7707a9..c3a956cb2 100644 --- a/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs +++ b/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs @@ -29,6 +29,21 @@ public override void OnReleaseImport(BookDownloadMessage downloadMessage) _proxy.SendNotification(BOOK_DOWNLOADED_TITLE, downloadMessage.Message, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _proxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheckMessage) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheckMessage.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs b/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs index 2eb36a552..4d6afa118 100644 --- a/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs +++ b/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs @@ -79,6 +79,73 @@ public override void OnReleaseImport(BookDownloadMessage message) _proxy.SendNotification(variables, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + var author = deleteMessage.Author; + var variables = new StringDictionary(); + + variables.Add("Readarr_EventType", "AuthorDelete"); + variables.Add("Readarr_Author_Id", author.Id.ToString()); + variables.Add("Readarr_Author_Name", author.Name); + variables.Add("Readarr_Author_Path", author.Path); + variables.Add("Readarr_Author_GoodreadsId", author.ForeignAuthorId); + variables.Add("Readarr_Author_DeletedFiles", deleteMessage.DeletedFiles.ToString()); + + _proxy.SendNotification(variables, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + var author = deleteMessage.Book.Author.Value; + var book = deleteMessage.Book; + + var variables = new StringDictionary(); + + variables.Add("Readarr_EventType", "BookDelete"); + variables.Add("Readarr_Author_Id", author.Id.ToString()); + variables.Add("Readarr_Author_Name", author.Name); + variables.Add("Readarr_Author_Path", author.Path); + variables.Add("Readarr_Author_GoodreadsId", author.ForeignAuthorId); + variables.Add("Readarr_Book_Id", book.Id.ToString()); + variables.Add("Readarr_Book_Title", book.Title); + variables.Add("Readarr_Book_GoodreadsId", book.ForeignBookId); + variables.Add("Readarr_Book_DeletedFiles", deleteMessage.DeletedFiles.ToString()); + + _proxy.SendNotification(variables, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + var author = deleteMessage.Book.Author.Value; + var book = deleteMessage.Book; + var bookFile = deleteMessage.BookFile; + var edition = bookFile.Edition.Value; + + var variables = new StringDictionary(); + + variables.Add("Readarr_EventType", "BookFileDelete"); + variables.Add("Readarr_Delete_Reason", deleteMessage.Reason.ToString()); + variables.Add("Readarr_Author_Id", author.Id.ToString()); + variables.Add("Readarr_Author_Name", author.Name); + variables.Add("Readarr_Author_GoodreadsId", author.ForeignAuthorId); + variables.Add("Readarr_Book_Id", book.Id.ToString()); + variables.Add("Readarr_Book_Title", book.Title); + variables.Add("Readarr_Book_GoodreadsId", book.ForeignBookId); + variables.Add("Readarr_BookFile_Id", bookFile.Id.ToString()); + variables.Add("Readarr_BookFile_Path", bookFile.Path); + variables.Add("Readarr_BookFile_Quality", bookFile.Quality.Quality.Name); + variables.Add("Readarr_BookFile_QualityVersion", bookFile.Quality.Revision.Version.ToString()); + variables.Add("Readarr_BookFile_ReleaseGroup", bookFile.ReleaseGroup ?? string.Empty); + variables.Add("Readarr_BookFile_SceneName", bookFile.SceneName ?? string.Empty); + variables.Add("Readarr_BookFile_Edition_Id", edition.Id.ToString()); + variables.Add("Readarr_BookFile_Edition_Name", edition.Title); + variables.Add("Readarr_BookFile_Edition_GoodreadsId", edition.ForeignEditionId); + variables.Add("Readarr_BookFile_Edition_Isbn13", edition.Isbn13); + variables.Add("Readarr_BookFile_Edition_Asin", edition.Asin); + + _proxy.SendNotification(variables, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { var variables = new StringDictionary(); diff --git a/src/NzbDrone.Core/Notifications/NotificationBase.cs b/src/NzbDrone.Core/Notifications/NotificationBase.cs index 9297d39dd..677751b17 100644 --- a/src/NzbDrone.Core/Notifications/NotificationBase.cs +++ b/src/NzbDrone.Core/Notifications/NotificationBase.cs @@ -11,6 +11,9 @@ public abstract class NotificationBase : INotification { protected const string BOOK_GRABBED_TITLE = "Book Grabbed"; protected const string BOOK_DOWNLOADED_TITLE = "Book Downloaded"; + protected const string AUTHOR_DELETED_TITLE = "Author Deleted"; + protected const string BOOK_DELETED_TITLE = "Book Deleted"; + protected const string BOOK_FILE_DELETED_TITLE = "Book File Deleted"; protected const string HEALTH_ISSUE_TITLE = "Health Check Failure"; protected const string DOWNLOAD_FAILURE_TITLE = "Download Failed"; protected const string IMPORT_FAILURE_TITLE = "Import Failed"; @@ -18,6 +21,9 @@ public abstract class NotificationBase : INotification protected const string BOOK_GRABBED_TITLE_BRANDED = "Readarr - " + BOOK_GRABBED_TITLE; protected const string BOOK_DOWNLOADED_TITLE_BRANDED = "Readarr - " + BOOK_DOWNLOADED_TITLE; + protected const string AUTHOR_DELETED_TITlE_BRANDED = "Readarr - " + AUTHOR_DELETED_TITLE; + protected const string BOOK_DELETED_TITLE_BRANDED = "Readarr - " + BOOK_DELETED_TITLE; + protected const string BOOK_FILE_DELETED_TITLE_BRANDED = "Readarr - " + BOOK_FILE_DELETED_TITLE; protected const string HEALTH_ISSUE_TITLE_BRANDED = "Readarr - " + HEALTH_ISSUE_TITLE; protected const string DOWNLOAD_FAILURE_TITLE_BRANDED = "Readarr - " + DOWNLOAD_FAILURE_TITLE; protected const string IMPORT_FAILURE_TITLE_BRANDED = "Readarr - " + IMPORT_FAILURE_TITLE; @@ -48,6 +54,18 @@ public virtual void OnRename(Author author) { } + public virtual void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + } + + public virtual void OnBookDelete(BookDeleteMessage deleteMessage) + { + } + + public virtual void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + } + public virtual void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { } @@ -64,8 +82,16 @@ public virtual void OnBookRetag(BookRetagMessage message) { } + public virtual void ProcessQueue() + { + } + public bool SupportsOnGrab => HasConcreteImplementation("OnGrab"); public bool SupportsOnRename => HasConcreteImplementation("OnRename"); + public bool SupportsOnAuthorDelete => HasConcreteImplementation("OnAuthorDelete"); + public bool SupportsOnBookDelete => HasConcreteImplementation("OnBookDelete"); + public bool SupportsOnBookFileDelete => HasConcreteImplementation("OnBookFileDelete"); + public bool SupportsOnBookFileDeleteForUpgrade => SupportsOnBookFileDelete; public bool SupportsOnReleaseImport => HasConcreteImplementation("OnReleaseImport"); public bool SupportsOnUpgrade => SupportsOnReleaseImport; public bool SupportsOnHealthIssue => HasConcreteImplementation("OnHealthIssue"); diff --git a/src/NzbDrone.Core/Notifications/NotificationDefinition.cs b/src/NzbDrone.Core/Notifications/NotificationDefinition.cs index a3cf53d1d..0e494294f 100644 --- a/src/NzbDrone.Core/Notifications/NotificationDefinition.cs +++ b/src/NzbDrone.Core/Notifications/NotificationDefinition.cs @@ -8,6 +8,10 @@ public class NotificationDefinition : ProviderDefinition public bool OnReleaseImport { get; set; } public bool OnUpgrade { get; set; } public bool OnRename { get; set; } + public bool OnAuthorDelete { get; set; } + public bool OnBookDelete { get; set; } + public bool OnBookFileDelete { get; set; } + public bool OnBookFileDeleteForUpgrade { get; set; } public bool OnHealthIssue { get; set; } public bool OnDownloadFailure { get; set; } public bool OnImportFailure { get; set; } @@ -16,12 +20,16 @@ public class NotificationDefinition : ProviderDefinition public bool SupportsOnReleaseImport { get; set; } public bool SupportsOnUpgrade { get; set; } public bool SupportsOnRename { get; set; } + public bool SupportsOnAuthorDelete { get; set; } + public bool SupportsOnBookDelete { get; set; } + public bool SupportsOnBookFileDelete { get; set; } + public bool SupportsOnBookFileDeleteForUpgrade { get; set; } public bool SupportsOnHealthIssue { get; set; } public bool IncludeHealthWarnings { get; set; } public bool SupportsOnDownloadFailure { get; set; } public bool SupportsOnImportFailure { get; set; } public bool SupportsOnBookRetag { get; set; } - public override bool Enable => OnGrab || OnReleaseImport || (OnReleaseImport && OnUpgrade) || OnHealthIssue || OnDownloadFailure || OnImportFailure || OnBookRetag; + public override bool Enable => OnGrab || OnReleaseImport || (OnReleaseImport && OnUpgrade) || OnAuthorDelete || OnBookDelete || OnBookFileDelete || OnBookFileDeleteForUpgrade || OnHealthIssue || OnDownloadFailure || OnImportFailure || OnBookRetag; } } diff --git a/src/NzbDrone.Core/Notifications/NotificationFactory.cs b/src/NzbDrone.Core/Notifications/NotificationFactory.cs index a75cb6214..8c9f483b5 100644 --- a/src/NzbDrone.Core/Notifications/NotificationFactory.cs +++ b/src/NzbDrone.Core/Notifications/NotificationFactory.cs @@ -15,6 +15,10 @@ public interface INotificationFactory : IProviderFactory OnUpgradeEnabled(); List OnRenameEnabled(); List OnHealthIssueEnabled(); + List OnAuthorDeleteEnabled(); + List OnBookDeleteEnabled(); + List OnBookFileDeleteEnabled(); + List OnBookFileDeleteForUpgradeEnabled(); List OnDownloadFailureEnabled(); List OnImportFailureEnabled(); List OnBookRetagEnabled(); @@ -47,6 +51,26 @@ public List OnRenameEnabled() return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnRename).ToList(); } + public List OnAuthorDeleteEnabled() + { + return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnAuthorDelete).ToList(); + } + + public List OnBookDeleteEnabled() + { + return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnBookDelete).ToList(); + } + + public List OnBookFileDeleteEnabled() + { + return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnBookFileDelete).ToList(); + } + + public List OnBookFileDeleteForUpgradeEnabled() + { + return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnBookFileDeleteForUpgrade).ToList(); + } + public List OnHealthIssueEnabled() { return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnHealthIssue).ToList(); @@ -75,6 +99,10 @@ public override void SetProviderCharacteristics(INotification provider, Notifica definition.SupportsOnReleaseImport = provider.SupportsOnReleaseImport; definition.SupportsOnUpgrade = provider.SupportsOnUpgrade; definition.SupportsOnRename = provider.SupportsOnRename; + definition.SupportsOnAuthorDelete = provider.SupportsOnAuthorDelete; + definition.SupportsOnBookDelete = provider.SupportsOnBookDelete; + definition.SupportsOnBookFileDelete = provider.SupportsOnBookFileDelete; + definition.SupportsOnBookFileDeleteForUpgrade = provider.SupportsOnBookFileDeleteForUpgrade; definition.SupportsOnHealthIssue = provider.SupportsOnHealthIssue; definition.SupportsOnDownloadFailure = provider.SupportsOnDownloadFailure; definition.SupportsOnImportFailure = provider.SupportsOnImportFailure; diff --git a/src/NzbDrone.Core/Notifications/NotificationService.cs b/src/NzbDrone.Core/Notifications/NotificationService.cs index df25ebd7a..b8f7e4cea 100644 --- a/src/NzbDrone.Core/Notifications/NotificationService.cs +++ b/src/NzbDrone.Core/Notifications/NotificationService.cs @@ -4,6 +4,7 @@ using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Core.Books; +using NzbDrone.Core.Books.Events; using NzbDrone.Core.Download; using NzbDrone.Core.HealthCheck; using NzbDrone.Core.MediaFiles; @@ -18,10 +19,14 @@ public class NotificationService : IHandle, IHandle, IHandle, + IHandle, + IHandle, + IHandle, IHandle, IHandle, IHandle, - IHandle + IHandle, + IHandleAsync { private readonly INotificationFactory _notificationFactory; private readonly Logger _logger; @@ -195,6 +200,76 @@ public void Handle(AuthorRenamedEvent message) } } + public void Handle(AuthorDeletedEvent message) + { + var deleteMessage = new AuthorDeleteMessage(message.Author, message.DeleteFiles); + + foreach (var notification in _notificationFactory.OnAuthorDeleteEnabled()) + { + try + { + if (ShouldHandleAuthor(notification.Definition, deleteMessage.Author)) + { + notification.OnAuthorDelete(deleteMessage); + } + } + catch (Exception ex) + { + _logger.Warn(ex, "Unable to send OnAuthorDelete notification to: " + notification.Definition.Name); + } + } + } + + public void Handle(BookDeletedEvent message) + { + var deleteMessage = new BookDeleteMessage(message.Book, message.DeleteFiles); + + foreach (var notification in _notificationFactory.OnBookDeleteEnabled()) + { + try + { + if (ShouldHandleAuthor(notification.Definition, deleteMessage.Book.Author)) + { + notification.OnBookDelete(deleteMessage); + } + } + catch (Exception ex) + { + _logger.Warn(ex, "Unable to send OnBookDelete notification to: " + notification.Definition.Name); + } + } + } + + public void Handle(BookFileDeletedEvent message) + { + var deleteMessage = new BookFileDeleteMessage(); + + var book = new List { message.BookFile.Edition.Value.Book }; + + deleteMessage.Message = GetMessage(message.BookFile.Author, book, message.BookFile.Quality); + deleteMessage.BookFile = message.BookFile; + deleteMessage.Book = message.BookFile.Edition.Value.Book; + deleteMessage.Reason = message.Reason; + + foreach (var notification in _notificationFactory.OnBookFileDeleteEnabled()) + { + try + { + if (message.Reason != MediaFiles.DeleteMediaFileReason.Upgrade || ((NotificationDefinition)notification.Definition).OnBookFileDeleteForUpgrade) + { + if (ShouldHandleAuthor(notification.Definition, message.BookFile.Author)) + { + notification.OnBookFileDelete(deleteMessage); + } + } + } + catch (Exception ex) + { + _logger.Warn(ex, "Unable to send OnBookFileDelete notification to: " + notification.Definition.Name); + } + } + } + public void Handle(HealthCheckFailedEvent message) { foreach (var notification in _notificationFactory.OnHealthIssueEnabled()) @@ -270,5 +345,25 @@ public void Handle(BookFileRetaggedEvent message) } } } + + public void HandleAsync(DeleteCompletedEvent message) + { + ProcessQueue(); + } + + private void ProcessQueue() + { + foreach (var notification in _notificationFactory.GetAvailableProviders()) + { + try + { + notification.ProcessQueue(); + } + catch (Exception ex) + { + _logger.Warn(ex, "Unable to process notification queue for " + notification.Definition.Name); + } + } + } } } diff --git a/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs b/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs index 6372b1272..afd239a51 100644 --- a/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs +++ b/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs @@ -26,6 +26,21 @@ public override void OnReleaseImport(BookDownloadMessage message) _prowlProxy.SendNotification(BOOK_DOWNLOADED_TITLE, message.Message, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _prowlProxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _prowlProxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _prowlProxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _prowlProxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs index 535cbb0a4..2f297149f 100644 --- a/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs @@ -29,6 +29,21 @@ public override void OnReleaseImport(BookDownloadMessage message) _proxy.SendNotification(BOOK_DOWNLOADED_TITLE_BRANDED, message.Message, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _proxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs b/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs index 001d7d616..5bc4808f7 100644 --- a/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs +++ b/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs @@ -26,6 +26,21 @@ public override void OnReleaseImport(BookDownloadMessage message) _proxy.SendNotification(BOOK_DOWNLOADED_TITLE, message.Message, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _proxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs b/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs index 19147c2ed..95123076e 100644 --- a/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs +++ b/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs @@ -29,6 +29,21 @@ public override void OnReleaseImport(BookDownloadMessage message) _proxy.SendNotification(BOOK_DOWNLOADED_TITLE, message.Message, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _proxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Slack/Slack.cs b/src/NzbDrone.Core/Notifications/Slack/Slack.cs index db511d6c0..f2d360bec 100644 --- a/src/NzbDrone.Core/Notifications/Slack/Slack.cs +++ b/src/NzbDrone.Core/Notifications/Slack/Slack.cs @@ -69,6 +69,54 @@ public override void OnRename(Author author) _proxy.SendPayload(payload, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + var attachments = new List + { + new Attachment + { + Title = deleteMessage.Author.Name, + Text = deleteMessage.DeletedFilesMessage + } + }; + + var payload = CreatePayload("Author Deleted", attachments); + + _proxy.SendPayload(payload, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + var attachments = new List + { + new Attachment + { + Title = $"${deleteMessage.Book.Author.Value.Name} - ${deleteMessage.Book.Title}", + Text = deleteMessage.DeletedFilesMessage + } + }; + + var payload = CreatePayload("Book Deleted", attachments); + + _proxy.SendPayload(payload, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + var attachments = new List + { + new Attachment + { + Title = $"${deleteMessage.Book.Author.Value.Name} - ${deleteMessage.Book.Title} - file deleted", + Text = deleteMessage.BookFile.Path + } + }; + + var payload = CreatePayload("Book File Deleted", attachments); + + _proxy.SendPayload(payload, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { var attachments = new List diff --git a/src/NzbDrone.Core/Notifications/Subsonic/Subsonic.cs b/src/NzbDrone.Core/Notifications/Subsonic/Subsonic.cs index 09a90557e..fc92ab20b 100644 --- a/src/NzbDrone.Core/Notifications/Subsonic/Subsonic.cs +++ b/src/NzbDrone.Core/Notifications/Subsonic/Subsonic.cs @@ -40,6 +40,38 @@ public override void OnRename(Author author) Update(); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + const string header = "Readarr - Author Deleted"; + + Notify(Settings, header, deleteMessage.Message); + + if (deleteMessage.DeletedFiles) + { + Update(); + } + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + const string header = "Readarr - Book Deleted"; + + Notify(Settings, header, deleteMessage.Message); + + if (deleteMessage.DeletedFiles) + { + Update(); + } + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + const string header = "Readarr - Book File Deleted"; + + Notify(Settings, header, deleteMessage.Message); + Update(); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { Notify(Settings, HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message); diff --git a/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs b/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs index d9a679ab8..bd58073e1 100644 --- a/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs +++ b/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs @@ -46,6 +46,33 @@ public override void OnRename(Author author) } } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + if (Settings.UpdateLibrary) + { + _indexerProxy.DeleteFolder(deleteMessage.Author.Path); + } + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + if (Settings.UpdateLibrary && deleteMessage.DeletedFiles) + { + foreach (var bookFile in deleteMessage.Book.BookFiles.Value) + { + _indexerProxy.DeleteFile(bookFile.Path); + } + } + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + if (Settings.UpdateLibrary) + { + _indexerProxy.DeleteFile(deleteMessage.BookFile.Path); + } + } + public override void OnBookRetag(BookRetagMessage message) { if (Settings.UpdateLibrary) diff --git a/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs b/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs index 6df08082c..102841583 100644 --- a/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs +++ b/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs @@ -26,6 +26,21 @@ public override void OnReleaseImport(BookDownloadMessage message) _proxy.SendNotification(BOOK_DOWNLOADED_TITLE, message.Message, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _proxy.SendNotification(AUTHOR_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_DELETED_TITLE, deleteMessage.Message, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _proxy.SendNotification(BOOK_FILE_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Twitter/Twitter.cs b/src/NzbDrone.Core/Notifications/Twitter/Twitter.cs index c1d29895a..6ac803481 100644 --- a/src/NzbDrone.Core/Notifications/Twitter/Twitter.cs +++ b/src/NzbDrone.Core/Notifications/Twitter/Twitter.cs @@ -28,6 +28,21 @@ public override void OnReleaseImport(BookDownloadMessage message) _twitterService.SendNotification($"Imported: {message.Message}", Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + _twitterService.SendNotification($"Deleted: {deleteMessage.Message}", Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + _twitterService.SendNotification($"Deleted: {deleteMessage.Message}", Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + _twitterService.SendNotification($"Deleted: {deleteMessage.Message}", Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _twitterService.SendNotification($"Health Issue: {healthCheck.Message}", Settings); diff --git a/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs b/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs index afa4bf6fc..e952060fa 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs @@ -71,6 +71,43 @@ public override void OnRename(Author author) _proxy.SendWebhook(payload, Settings); } + public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage) + { + var payload = new WebhookAuthorDeletePayload + { + EventType = WebhookEventType.Delete, + Author = new WebhookAuthor(deleteMessage.Author), + DeletedFiles = deleteMessage.DeletedFiles + }; + + _proxy.SendWebhook(payload, Settings); + } + + public override void OnBookDelete(BookDeleteMessage deleteMessage) + { + var payload = new WebhookBookDeletePayload + { + EventType = WebhookEventType.Delete, + Author = new WebhookAuthor(deleteMessage.Book.Author), + Book = new WebhookBook(deleteMessage.Book) + }; + + _proxy.SendWebhook(payload, Settings); + } + + public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage) + { + var payload = new WebhookBookFileDeletePayload + { + EventType = WebhookEventType.Delete, + Author = new WebhookAuthor(deleteMessage.Book.Author), + Book = new WebhookBook(deleteMessage.Book), + BookFile = new WebhookBookFile(deleteMessage.BookFile) + }; + + _proxy.SendWebhook(payload, Settings); + } + public override void OnBookRetag(BookRetagMessage message) { var payload = new WebhookRetagPayload diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookAuthorDeletePayload.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookAuthorDeletePayload.cs new file mode 100644 index 000000000..fb9722bb8 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookAuthorDeletePayload.cs @@ -0,0 +1,8 @@ +namespace NzbDrone.Core.Notifications.Webhook +{ + public class WebhookAuthorDeletePayload : WebhookPayload + { + public WebhookAuthor Author { get; set; } + public bool DeletedFiles { get; set; } + } +} diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookBookDeletePayload.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookBookDeletePayload.cs new file mode 100644 index 000000000..804ddf77b --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookBookDeletePayload.cs @@ -0,0 +1,8 @@ +namespace NzbDrone.Core.Notifications.Webhook +{ + public class WebhookBookDeletePayload : WebhookPayload + { + public WebhookAuthor Author { get; set; } + public WebhookBook Book { get; set; } + } +} diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookBookFileDeletePayload.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookBookFileDeletePayload.cs new file mode 100644 index 000000000..439ac2160 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookBookFileDeletePayload.cs @@ -0,0 +1,9 @@ +namespace NzbDrone.Core.Notifications.Webhook +{ + public class WebhookBookFileDeletePayload : WebhookPayload + { + public WebhookAuthor Author { get; set; } + public WebhookBook Book { get; set; } + public WebhookBookFile BookFile { get; set; } + } +} diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookEventType.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookEventType.cs index 610c03338..4c2fd85cf 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookEventType.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookEventType.cs @@ -12,6 +12,7 @@ public enum WebhookEventType Grab, Download, Rename, + Delete, Health, Retag } diff --git a/src/Readarr.Api.V1/Notifications/NotificationResource.cs b/src/Readarr.Api.V1/Notifications/NotificationResource.cs index 36753dafb..7642c8f4c 100644 --- a/src/Readarr.Api.V1/Notifications/NotificationResource.cs +++ b/src/Readarr.Api.V1/Notifications/NotificationResource.cs @@ -9,6 +9,10 @@ public class NotificationResource : ProviderResource public bool OnReleaseImport { get; set; } public bool OnUpgrade { get; set; } public bool OnRename { get; set; } + public bool OnAuthorDelete { get; set; } + public bool OnBookDelete { get; set; } + public bool OnBookFileDelete { get; set; } + public bool OnBookFileDeleteForUpgrade { get; set; } public bool OnHealthIssue { get; set; } public bool OnDownloadFailure { get; set; } public bool OnImportFailure { get; set; } @@ -17,6 +21,10 @@ public class NotificationResource : ProviderResource public bool SupportsOnReleaseImport { get; set; } public bool SupportsOnUpgrade { get; set; } public bool SupportsOnRename { get; set; } + public bool SupportsOnAuthorDelete { get; set; } + public bool SupportsOnBookDelete { get; set; } + public bool SupportsOnBookFileDelete { get; set; } + public bool SupportsOnBookFileDeleteForUpgrade { get; set; } public bool SupportsOnHealthIssue { get; set; } public bool IncludeHealthWarnings { get; set; } public bool SupportsOnDownloadFailure { get; set; } @@ -40,6 +48,10 @@ public override NotificationResource ToResource(NotificationDefinition definitio resource.OnReleaseImport = definition.OnReleaseImport; resource.OnUpgrade = definition.OnUpgrade; resource.OnRename = definition.OnRename; + resource.OnAuthorDelete = definition.OnAuthorDelete; + resource.OnBookDelete = definition.OnBookDelete; + resource.OnBookFileDelete = definition.OnBookFileDelete; + resource.OnBookFileDeleteForUpgrade = definition.OnBookFileDeleteForUpgrade; resource.OnHealthIssue = definition.OnHealthIssue; resource.OnDownloadFailure = definition.OnDownloadFailure; resource.OnImportFailure = definition.OnImportFailure; @@ -48,6 +60,10 @@ public override NotificationResource ToResource(NotificationDefinition definitio resource.SupportsOnReleaseImport = definition.SupportsOnReleaseImport; resource.SupportsOnUpgrade = definition.SupportsOnUpgrade; resource.SupportsOnRename = definition.SupportsOnRename; + resource.SupportsOnAuthorDelete = definition.SupportsOnAuthorDelete; + resource.SupportsOnBookDelete = definition.SupportsOnBookDelete; + resource.SupportsOnBookFileDelete = definition.SupportsOnBookFileDelete; + resource.SupportsOnBookFileDeleteForUpgrade = definition.SupportsOnBookFileDeleteForUpgrade; resource.SupportsOnHealthIssue = definition.SupportsOnHealthIssue; resource.IncludeHealthWarnings = definition.IncludeHealthWarnings; resource.SupportsOnDownloadFailure = definition.SupportsOnDownloadFailure; @@ -70,6 +86,10 @@ public override NotificationDefinition ToModel(NotificationResource resource) definition.OnReleaseImport = resource.OnReleaseImport; definition.OnUpgrade = resource.OnUpgrade; definition.OnRename = resource.OnRename; + definition.OnAuthorDelete = resource.OnAuthorDelete; + definition.OnBookDelete = resource.OnBookDelete; + definition.OnBookFileDelete = resource.OnBookFileDelete; + definition.OnBookFileDeleteForUpgrade = resource.OnBookFileDeleteForUpgrade; definition.OnHealthIssue = resource.OnHealthIssue; definition.OnDownloadFailure = resource.OnDownloadFailure; definition.OnImportFailure = resource.OnImportFailure; @@ -78,6 +98,10 @@ public override NotificationDefinition ToModel(NotificationResource resource) definition.SupportsOnReleaseImport = resource.SupportsOnReleaseImport; definition.SupportsOnUpgrade = resource.SupportsOnUpgrade; definition.SupportsOnRename = resource.SupportsOnRename; + definition.SupportsOnAuthorDelete = resource.SupportsOnAuthorDelete; + definition.SupportsOnBookDelete = resource.SupportsOnBookDelete; + definition.SupportsOnBookFileDelete = resource.SupportsOnBookFileDelete; + definition.SupportsOnBookFileDeleteForUpgrade = resource.SupportsOnBookFileDeleteForUpgrade; definition.SupportsOnHealthIssue = resource.SupportsOnHealthIssue; definition.IncludeHealthWarnings = resource.IncludeHealthWarnings; definition.SupportsOnDownloadFailure = resource.SupportsOnDownloadFailure;