Fixed: "Specific Book" setting for readarr list import (#1200)

pull/1202/head
Thomas White 4 years ago committed by GitHub
parent 109fd22d1f
commit 466876da62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -88,6 +88,19 @@ namespace NzbDrone.Core.Test.ImportListTests
_importListReports.First().EditionGoodreadsId = "1234";
}
private void WithSecondBook()
{
var importListItem2 = new ImportListItemInfo
{
Author = "Linkin Park",
AuthorGoodreadsId = "f59c5520-5f46-4d2c-b2c4-822eabf53419",
Book = "Meteora 2",
EditionGoodreadsId = "5678",
BookGoodreadsId = "8765"
};
_importListReports.Add(importListItem2);
}
private void WithExistingAuthor()
{
Mocker.GetMock<IAuthorService>()
@ -290,5 +303,26 @@ namespace NzbDrone.Core.Test.ImportListTests
Mocker.GetMock<IAddBookService>()
.Verify(v => v.AddBooks(It.Is<List<Book>>(t => t.Count == 0), false));
}
[TestCase(ImportListMonitorType.None, 0, false)]
[TestCase(ImportListMonitorType.SpecificBook, 2, true)]
[TestCase(ImportListMonitorType.EntireAuthor, 0, true)]
public void should_add_two_books(ImportListMonitorType monitor, int expectedBooksMonitored, bool expectedAuthorMonitored)
{
WithBook();
WithBookId();
WithSecondBook();
WithAuthorId();
WithMonitorType(monitor);
Subject.Execute(new ImportListSyncCommand());
Mocker.GetMock<IAddBookService>()
.Verify(v => v.AddBooks(It.Is<List<Book>>(t => t.Count == 2), false));
Mocker.GetMock<IAddAuthorService>()
.Verify(v => v.AddAuthors(It.Is<List<Author>>(t => t.Count == 1 &&
t.First().AddOptions.BooksToMonitor.Count == expectedBooksMonitored &&
t.First().Monitored == expectedAuthorMonitored), false));
}
}
}

@ -41,9 +41,9 @@ namespace NzbDrone.Core.Books
if (monitoredBooks.Any())
{
ToggleBooksMonitoredState(
books.Where(s => monitoredBooks.Any(t => t == s.ForeignBookId)), true);
books.Where(s => monitoredBooks.Contains(s.ForeignBookId)), true);
ToggleBooksMonitoredState(
books.Where(s => monitoredBooks.Any(t => t != s.ForeignBookId)), false);
books.Where(s => !monitoredBooks.Contains(s.ForeignBookId)), false);
}
else
{

@ -99,12 +99,12 @@ namespace NzbDrone.Core.ImportLists
if (report.Book.IsNotNullOrWhiteSpace() || report.EditionGoodreadsId.IsNotNullOrWhiteSpace())
{
if (report.EditionGoodreadsId.IsNullOrWhiteSpace() || report.AuthorGoodreadsId.IsNullOrWhiteSpace())
if (report.EditionGoodreadsId.IsNullOrWhiteSpace() || report.AuthorGoodreadsId.IsNullOrWhiteSpace() || report.BookGoodreadsId.IsNullOrWhiteSpace())
{
MapBookReport(report);
}
ProcessBookReport(importList, report, listExclusions, booksToAdd);
ProcessBookReport(importList, report, listExclusions, booksToAdd, authorsToAdd);
}
else if (report.Author.IsNotNullOrWhiteSpace() || report.AuthorGoodreadsId.IsNotNullOrWhiteSpace())
{
@ -147,7 +147,7 @@ namespace NzbDrone.Core.ImportLists
mappedBook = _bookSearchService.SearchForNewBook(report.Book, report.Author).FirstOrDefault();
}
// Break if we are looking for an book and cant find it. This will avoid us from adding the author and possibly getting it wrong.
// Break if we are looking for a book and cant find it. This will avoid us from adding the author and possibly getting it wrong.
if (mappedBook == null)
{
_logger.Trace($"Nothing found for {report.EditionGoodreadsId}");
@ -159,11 +159,11 @@ namespace NzbDrone.Core.ImportLists
report.BookGoodreadsId = mappedBook.ForeignBookId;
report.Book = mappedBook.Title;
report.Author = mappedBook.AuthorMetadata?.Value?.Name;
report.AuthorGoodreadsId = mappedBook.AuthorMetadata?.Value?.ForeignAuthorId;
report.Author ??= mappedBook.AuthorMetadata?.Value?.Name;
report.AuthorGoodreadsId ??= mappedBook.AuthorMetadata?.Value?.ForeignAuthorId;
}
private void ProcessBookReport(ImportListDefinition importList, ImportListItemInfo report, List<ImportListExclusion> listExclusions, List<Book> booksToAdd)
private void ProcessBookReport(ImportListDefinition importList, ImportListItemInfo report, List<ImportListExclusion> listExclusions, List<Book> booksToAdd, List<Author> authorsToAdd)
{
if (report.EditionGoodreadsId == null)
{
@ -181,13 +181,13 @@ namespace NzbDrone.Core.ImportLists
if (excludedBook != null)
{
_logger.Debug("{0} [{1}] Rejected due to list exlcusion", report.EditionGoodreadsId, report.Book);
_logger.Debug("{0} [{1}] Rejected due to list exclusion", report.EditionGoodreadsId, report.Book);
return;
}
if (excludedAuthor != null)
{
_logger.Debug("{0} [{1}] Rejected due to list exlcusion for parent author", report.EditionGoodreadsId, report.Book);
_logger.Debug("{0} [{1}] Rejected due to list exclusion for parent author", report.EditionGoodreadsId, report.Book);
return;
}
@ -223,19 +223,7 @@ namespace NzbDrone.Core.ImportLists
{
var monitored = importList.ShouldMonitor != ImportListMonitorType.None;
var toAdd = new Book
{
ForeignBookId = report.BookGoodreadsId,
Monitored = monitored,
Editions = new List<Edition>
{
new Edition
{
ForeignEditionId = report.EditionGoodreadsId,
Monitored = true
}
},
Author = new Author
var toAddAuthor = new Author
{
Monitored = monitored,
RootFolderPath = importList.RootFolderPath,
@ -248,16 +236,35 @@ namespace NzbDrone.Core.ImportLists
Monitored = monitored,
Monitor = monitored ? MonitorTypes.All : MonitorTypes.None
}
};
if (report.AuthorGoodreadsId != null && report.Author != null)
{
toAddAuthor = ProcessAuthorReport(importList, report, listExclusions, authorsToAdd);
}
var toAdd = new Book
{
ForeignBookId = report.BookGoodreadsId,
Monitored = monitored,
Editions = new List<Edition>
{
new Edition
{
ForeignEditionId = report.EditionGoodreadsId,
Monitored = true
}
},
Author = toAddAuthor,
AddOptions = new AddBookOptions
{
SearchForNewBook = monitored
SearchForNewBook = importList.ShouldSearch
}
};
if (importList.ShouldMonitor == ImportListMonitorType.SpecificBook)
{
toAdd.Author.Value.AddOptions.BooksToMonitor.Add(toAdd.ForeignBookId);
toAddAuthor.AddOptions.BooksToMonitor.Add(toAdd.ForeignBookId);
}
booksToAdd.Add(toAdd);
@ -272,11 +279,11 @@ namespace NzbDrone.Core.ImportLists
report.Author = mappedAuthor?.Metadata.Value?.Name;
}
private void ProcessAuthorReport(ImportListDefinition importList, ImportListItemInfo report, List<ImportListExclusion> listExclusions, List<Author> authorsToAdd)
private Author ProcessAuthorReport(ImportListDefinition importList, ImportListItemInfo report, List<ImportListExclusion> listExclusions, List<Author> authorsToAdd)
{
if (report.AuthorGoodreadsId == null)
{
return;
return null;
}
// Check to see if author in DB
@ -285,10 +292,13 @@ namespace NzbDrone.Core.ImportLists
// Check to see if author excluded
var excludedAuthor = listExclusions.Where(s => s.ForeignId == report.AuthorGoodreadsId).SingleOrDefault();
// Check to see if author in import
var existingImportAuthor = authorsToAdd.Find(i => i.ForeignAuthorId == report.AuthorGoodreadsId);
if (excludedAuthor != null)
{
_logger.Debug("{0} [{1}] Rejected due to list exlcusion", report.AuthorGoodreadsId, report.Author);
return;
_logger.Debug("{0} [{1}] Rejected due to list exclusion", report.AuthorGoodreadsId, report.Author);
return null;
}
if (existingAuthor != null)
@ -301,15 +311,19 @@ namespace NzbDrone.Core.ImportLists
_authorService.UpdateAuthor(existingAuthor);
}
return;
return existingAuthor;
}
// Append Author if not already in DB or already on add list
if (authorsToAdd.All(s => s.Metadata.Value.ForeignAuthorId != report.AuthorGoodreadsId))
if (existingImportAuthor != null)
{
_logger.Debug("{0} [{1}] Rejected, Author Exists in Import.", report.AuthorGoodreadsId, report.Author);
return existingImportAuthor;
}
var monitored = importList.ShouldMonitor != ImportListMonitorType.None;
authorsToAdd.Add(new Author
var toAdd = new Author
{
Metadata = new AuthorMetadata
{
@ -327,8 +341,11 @@ namespace NzbDrone.Core.ImportLists
Monitored = monitored,
Monitor = monitored ? MonitorTypes.All : MonitorTypes.None
}
});
}
};
authorsToAdd.Add(toAdd);
return toAdd;
}
public void Execute(ImportListSyncCommand message)

@ -13,6 +13,26 @@ namespace NzbDrone.Core.ImportLists.Readarr
public HashSet<int> Tags { get; set; }
}
public class ReadarrEdition
{
public string Title { get; set; }
public string ForeignEditionId { get; set; }
public string Overview { get; set; }
public List<MediaCover.MediaCover> Images { get; set; }
public bool Monitored { get; set; }
}
public class ReadarrBook
{
public string Title { get; set; }
public string ForeignBookId { get; set; }
public string Overview { get; set; }
public List<MediaCover.MediaCover> Images { get; set; }
public bool Monitored { get; set; }
public ReadarrAuthor Author { get; set; }
public List<ReadarrEdition> Editions { get; set; }
}
public class ReadarrProfile
{
public string Name { get; set; }

@ -30,21 +30,25 @@ namespace NzbDrone.Core.ImportLists.Readarr
public override IList<ImportListItemInfo> Fetch()
{
var authors = new List<ImportListItemInfo>();
var authorsAndBooks = new List<ImportListItemInfo>();
try
{
var remoteAuthors = _readarrV1Proxy.GetAuthors(Settings);
var remoteBooks = _readarrV1Proxy.GetBooks(Settings);
foreach (var remoteAuthor in remoteAuthors)
foreach (var remoteBook in remoteBooks)
{
if ((!Settings.ProfileIds.Any() || Settings.ProfileIds.Contains(remoteAuthor.QualityProfileId)) &&
(!Settings.TagIds.Any() || Settings.TagIds.Any(x => remoteAuthor.Tags.Any(y => y == x))))
if ((!Settings.ProfileIds.Any() || Settings.ProfileIds.Contains(remoteBook.Author.QualityProfileId)) &&
(!Settings.TagIds.Any() || Settings.TagIds.Any(x => remoteBook.Author.Tags.Any(y => y == x))) &&
remoteBook.Monitored && remoteBook.Author.Monitored)
{
authors.Add(new ImportListItemInfo
authorsAndBooks.Add(new ImportListItemInfo
{
AuthorGoodreadsId = remoteAuthor.ForeignAuthorId,
Author = remoteAuthor.AuthorName
BookGoodreadsId = remoteBook.ForeignBookId,
Book = remoteBook.Title,
EditionGoodreadsId = remoteBook.Editions.Single(x => x.Monitored).ForeignEditionId,
Author = remoteBook.Author.AuthorName,
AuthorGoodreadsId = remoteBook.Author.ForeignAuthorId
});
}
}
@ -56,7 +60,7 @@ namespace NzbDrone.Core.ImportLists.Readarr
_importListStatusService.RecordFailure(Definition.Id);
}
return CleanupListItems(authors);
return CleanupListItems(authorsAndBooks);
}
public override object RequestAction(string action, IDictionary<string, string> query)

@ -12,6 +12,7 @@ namespace NzbDrone.Core.ImportLists.Readarr
public interface IReadarrV1Proxy
{
List<ReadarrAuthor> GetAuthors(ReadarrSettings settings);
List<ReadarrBook> GetBooks(ReadarrSettings settings);
List<ReadarrProfile> GetProfiles(ReadarrSettings settings);
List<ReadarrTag> GetTags(ReadarrSettings settings);
ValidationFailure Test(ReadarrSettings settings);
@ -33,6 +34,11 @@ namespace NzbDrone.Core.ImportLists.Readarr
return Execute<ReadarrAuthor>("/api/v1/author", settings);
}
public List<ReadarrBook> GetBooks(ReadarrSettings settings)
{
return Execute<ReadarrBook>("/api/v1/book", settings);
}
public List<ReadarrProfile> GetProfiles(ReadarrSettings settings)
{
return Execute<ReadarrProfile>("/api/v1/qualityprofile", settings);

Loading…
Cancel
Save