using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using NLog; using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Core.Books; using NzbDrone.Core.Datastore; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Queue; namespace NzbDrone.Core.IndexerSearch { internal class BookSearchService : IExecute, IExecute, IExecute { private readonly ISearchForReleases _releaseSearchService; private readonly IBookService _bookService; private readonly IBookCutoffService _bookCutoffService; private readonly IQueueService _queueService; private readonly IProcessDownloadDecisions _processDownloadDecisions; private readonly Logger _logger; public BookSearchService(ISearchForReleases releaseSearchService, IBookService bookService, IBookCutoffService bookCutoffService, IQueueService queueService, IProcessDownloadDecisions processDownloadDecisions, Logger logger) { _releaseSearchService = releaseSearchService; _bookService = bookService; _bookCutoffService = bookCutoffService; _queueService = queueService; _processDownloadDecisions = processDownloadDecisions; _logger = logger; } private void SearchForMissingBooks(List books, bool userInvokedSearch) { _logger.ProgressInfo("Performing missing search for {0} books", books.Count); var downloadedCount = 0; foreach (var book in books) { List decisions; decisions = _releaseSearchService.BookSearch(book.Id, false, userInvokedSearch, false); var processed = _processDownloadDecisions.ProcessDecisions(decisions); downloadedCount += processed.Grabbed.Count; } _logger.ProgressInfo("Completed missing search for {0} books. {1} reports downloaded.", books.Count, downloadedCount); } public void Execute(BookSearchCommand message) { foreach (var bookId in message.BookIds) { var decisions = _releaseSearchService.BookSearch(bookId, false, message.Trigger == CommandTrigger.Manual, false); var processed = _processDownloadDecisions.ProcessDecisions(decisions); _logger.ProgressInfo("Book search completed. {0} reports downloaded.", processed.Grabbed.Count); } } public void Execute(MissingBookSearchCommand message) { List books; if (message.AuthorId.HasValue) { var authorId = message.AuthorId.Value; var pagingSpec = new PagingSpec { Page = 1, PageSize = 100000, SortDirection = SortDirection.Ascending, SortKey = "Id" }; pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Author.Value.Monitored == true); books = _bookService.BooksWithoutFiles(pagingSpec).Records.Where(e => e.AuthorId.Equals(authorId)).ToList(); } else { var pagingSpec = new PagingSpec { Page = 1, PageSize = 100000, SortDirection = SortDirection.Ascending, SortKey = "Id" }; pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Author.Value.Monitored == true); books = _bookService.BooksWithoutFiles(pagingSpec).Records.ToList(); } var queue = _queueService.GetQueue().Where(q => q.Book != null).Select(q => q.Book.Id); var missing = books.Where(e => !queue.Contains(e.Id)).ToList(); SearchForMissingBooks(missing, message.Trigger == CommandTrigger.Manual); } public void Execute(CutoffUnmetBookSearchCommand message) { Expression> filterExpression; filterExpression = v => v.Monitored == true && v.Author.Value.Monitored == true; var pagingSpec = new PagingSpec { Page = 1, PageSize = 100000, SortDirection = SortDirection.Ascending, SortKey = "Id" }; pagingSpec.FilterExpressions.Add(filterExpression); var books = _bookCutoffService.BooksWhereCutoffUnmet(pagingSpec).Records.ToList(); var queue = _queueService.GetQueue().Where(q => q.Book != null).Select(q => q.Book.Id); var missing = books.Where(e => !queue.Contains(e.Id)).ToList(); SearchForMissingBooks(missing, message.Trigger == CommandTrigger.Manual); } } }