From b3dd116d273d6bde624efb6650b0f7a4545cc4b0 Mon Sep 17 00:00:00 2001 From: ta264 Date: Tue, 20 Jul 2021 21:41:57 +0100 Subject: [PATCH] Fixed: Deleting author removes books from Calibre Fixes #1144 --- .../Books/Calibre/CalibreProxy.cs | 20 +++--- .../MediaFiles/MediaFileDeletionService.cs | 61 +++++++++++++------ .../MediaFiles/MediaFileRepository.cs | 6 ++ .../MediaFiles/MediaFileService.cs | 6 ++ 4 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/NzbDrone.Core/Books/Calibre/CalibreProxy.cs b/src/NzbDrone.Core/Books/Calibre/CalibreProxy.cs index 224c170c4..0d6119d95 100644 --- a/src/NzbDrone.Core/Books/Calibre/CalibreProxy.cs +++ b/src/NzbDrone.Core/Books/Calibre/CalibreProxy.cs @@ -23,6 +23,7 @@ namespace NzbDrone.Core.Books.Calibre { CalibreImportJob AddBook(BookFile book, CalibreSettings settings); void DeleteBook(BookFile book, CalibreSettings settings); + void DeleteBooks(List books, CalibreSettings settings); void AddFormat(BookFile file, CalibreSettings settings); void RemoveFormats(int calibreId, IEnumerable formats, CalibreSettings settings); void SetFields(BookFile file, CalibreSettings settings, bool updateCover = true, bool embed = false); @@ -102,16 +103,15 @@ namespace NzbDrone.Core.Books.Calibre public void DeleteBook(BookFile book, CalibreSettings settings) { - try - { - var request = GetBuilder($"cdb/delete-books/{book.CalibreId}/{settings.Library}", settings).Build(); - _httpClient.Post(request); - } - catch (Exception e) - { - Console.WriteLine(e); - throw; - } + var request = GetBuilder($"cdb/delete-books/{book.CalibreId}/{settings.Library}", settings).Build(); + _httpClient.Post(request); + } + + public void DeleteBooks(List books, CalibreSettings settings) + { + var idString = books.Where(x => x.CalibreId != 0).Select(x => x.CalibreId).ConcatToString(","); + var request = GetBuilder($"cdb/delete-books/{idString}/{settings.Library}", settings).Build(); + _httpClient.Post(request); } public void AddFormat(BookFile file, CalibreSettings settings) diff --git a/src/NzbDrone.Core/MediaFiles/MediaFileDeletionService.cs b/src/NzbDrone.Core/MediaFiles/MediaFileDeletionService.cs index d0eda9fc8..ba6a5fdf2 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaFileDeletionService.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaFileDeletionService.cs @@ -23,6 +23,7 @@ namespace NzbDrone.Core.MediaFiles } public class MediaFileDeletionService : IDeleteMediaFiles, + IHandle, IHandleAsync, IHandleAsync, IHandle @@ -121,37 +122,63 @@ namespace NzbDrone.Core.MediaFiles } } + [EventHandleOrder(EventHandleOrder.First)] + public void Handle(AuthorDeletedEvent message) + { + if (message.DeleteFiles) + { + var author = message.Author; + + var rootFolder = _rootFolderService.GetBestRootFolder(message.Author.Path); + var isCalibre = rootFolder.IsCalibreLibrary && rootFolder.CalibreSettings != null; + + if (isCalibre) + { + // use metadataId instead of authorId so that query works even after author deleted + var books = _mediaFileService.GetFilesByAuthorMetadataId(author.AuthorMetadataId); + _calibre.DeleteBooks(books, rootFolder.CalibreSettings); + } + } + } + public void HandleAsync(AuthorDeletedEvent message) { if (message.DeleteFiles) { var author = message.Author; - var allAuthors = _authorService.AllAuthorPaths(); - foreach (var s in allAuthors) + var rootFolder = _rootFolderService.GetBestRootFolder(message.Author.Path); + var isCalibre = rootFolder.IsCalibreLibrary && rootFolder.CalibreSettings != null; + + if (!isCalibre) { - if (s.Key == author.Id) - { - continue; - } + var allAuthors = _authorService.AllAuthorPaths(); - if (author.Path.IsParentPath(s.Value)) + foreach (var s in allAuthors) { - _logger.Error("Author path: '{0}' is a parent of another author, not deleting files.", author.Path); - return; + if (s.Key == author.Id) + { + continue; + } + + if (author.Path.IsParentPath(s.Value)) + { + _logger.Error("Author path: '{0}' is a parent of another author, not deleting files.", author.Path); + return; + } + + if (author.Path.PathEquals(s.Value)) + { + _logger.Error("Author path: '{0}' is the same as another author, not deleting files.", author.Path); + return; + } } - if (author.Path.PathEquals(s.Value)) + if (_diskProvider.FolderExists(message.Author.Path)) { - _logger.Error("Author path: '{0}' is the same as another author, not deleting files.", author.Path); - return; + _recycleBinProvider.DeleteFolder(message.Author.Path); } } - - if (_diskProvider.FolderExists(message.Author.Path)) - { - _recycleBinProvider.DeleteFolder(message.Author.Path); - } } } diff --git a/src/NzbDrone.Core/MediaFiles/MediaFileRepository.cs b/src/NzbDrone.Core/MediaFiles/MediaFileRepository.cs index 8295096f8..c878f840f 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaFileRepository.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaFileRepository.cs @@ -12,6 +12,7 @@ namespace NzbDrone.Core.MediaFiles public interface IMediaFileRepository : IBasicRepository { List GetFilesByAuthor(int authorId); + List GetFilesByAuthorMetadataId(int authorMetadataId); List GetFilesByBook(int bookId); List GetFilesByEdition(int editionId); List GetUnmappedFiles(); @@ -68,6 +69,11 @@ namespace NzbDrone.Core.MediaFiles return Query(Builder().Where(a => a.Id == authorId)); } + public List GetFilesByAuthorMetadataId(int authorMetadataId) + { + return Query(Builder().Where(b => b.AuthorMetadataId == authorMetadataId)); + } + public List GetFilesByBook(int bookId) { return Query(Builder().Where(b => b.Id == bookId)); diff --git a/src/NzbDrone.Core/MediaFiles/MediaFileService.cs b/src/NzbDrone.Core/MediaFiles/MediaFileService.cs index 437aee7d9..ec313330e 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaFileService.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaFileService.cs @@ -22,6 +22,7 @@ namespace NzbDrone.Core.MediaFiles void Delete(BookFile bookFile, DeleteMediaFileReason reason); void DeleteMany(List bookFiles, DeleteMediaFileReason reason); List GetFilesByAuthor(int authorId); + List GetFilesByAuthorMetadataId(int authorMetadataId); List GetFilesByBook(int bookId); List GetFilesByEdition(int editionId); List GetUnmappedFiles(); @@ -182,6 +183,11 @@ namespace NzbDrone.Core.MediaFiles return _mediaFileRepository.GetFilesByAuthor(authorId); } + public List GetFilesByAuthorMetadataId(int authorMetadataId) + { + return _mediaFileRepository.GetFilesByAuthorMetadataId(authorMetadataId); + } + public List GetFilesByBook(int bookId) { return _mediaFileRepository.GetFilesByBook(bookId);