private void MapAlbumReport(ImportListItemInfo report) { Book mappedAlbum; if (report.EditionGoodreadsId.IsNotNullOrWhiteSpace() && int.TryParse(report.EditionGoodreadsId, out var goodreadsId)) { var search = _bookSearchService.SearchByGoodreadsId(goodreadsId); mappedAlbum = search.FirstOrDefault(x => x.Editions.Value.Any(e => int.TryParse(e.ForeignEditionId, out var editionId) && editionId == goodreadsId)); } else { mappedAlbum = _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. if (mappedAlbum == null) { _logger.Trace($"Nothing found for {report.EditionGoodreadsId}"); report.EditionGoodreadsId = null; return; } _logger.Trace($"Mapped {report.EditionGoodreadsId} to {mappedAlbum}"); report.EditionGoodreadsId = mappedAlbum.Editions.Value.Single(x => x.Monitored).ForeignEditionId; report.BookGoodreadsId = mappedAlbum.ForeignBookId; report.Book = mappedAlbum.Title; report.Author = mappedAlbum.AuthorMetadata?.Value?.Name; report.AuthorGoodreadsId = mappedAlbum.AuthorMetadata?.Value?.ForeignAuthorId; }
public IEnumerable <CandidateEdition> GetRemoteCandidates(LocalEdition localEdition, IdentificationOverrides idOverrides) { // TODO handle edition override // Gets candidate book releases from the metadata server. // Will eventually need adding locally if we find a match List <Book> remoteBooks; var seenCandidates = new HashSet <string>(); var isbns = localEdition.LocalBooks.Select(x => x.FileTrackInfo.Isbn).Distinct().ToList(); var asins = localEdition.LocalBooks.Select(x => x.FileTrackInfo.Asin).Distinct().ToList(); var goodreads = localEdition.LocalBooks.Select(x => x.FileTrackInfo.GoodreadsId).Distinct().ToList(); // grab possibilities for all the IDs present if (isbns.Count == 1 && isbns[0].IsNotNullOrWhiteSpace()) { _logger.Trace($"Searching by isbn {isbns[0]}"); try { remoteBooks = _bookSearchService.SearchByIsbn(isbns[0]); } catch (GoodreadsException e) { _logger.Info(e, "Skipping ISBN search due to Goodreads Error"); remoteBooks = new List <Book>(); } foreach (var candidate in ToCandidates(remoteBooks, seenCandidates, idOverrides)) { yield return(candidate); } } if (asins.Count == 1 && asins[0].IsNotNullOrWhiteSpace() && asins[0].Length == 10) { _logger.Trace($"Searching by asin {asins[0]}"); try { remoteBooks = _bookSearchService.SearchByAsin(asins[0]); } catch (GoodreadsException e) { _logger.Info(e, "Skipping ASIN search due to Goodreads Error"); remoteBooks = new List <Book>(); } foreach (var candidate in ToCandidates(remoteBooks, seenCandidates, idOverrides)) { yield return(candidate); } } if (goodreads.Count == 1 && goodreads[0].IsNotNullOrWhiteSpace()) { if (int.TryParse(goodreads[0], out var id)) { _logger.Trace($"Searching by goodreads id {id}"); try { remoteBooks = _bookSearchService.SearchByGoodreadsId(id); } catch (GoodreadsException e) { _logger.Info(e, "Skipping Goodreads ID search due to Goodreads Error"); remoteBooks = new List <Book>(); } foreach (var candidate in ToCandidates(remoteBooks, seenCandidates, idOverrides)) { yield return(candidate); } } } // If we got an id result, or any overrides are set, stop if (seenCandidates.Any() || idOverrides?.Edition != null || idOverrides?.Book != null || idOverrides?.Author != null) { yield break; } // fall back to author / book name search var authorTags = new List <string>(); if (TrackGroupingService.IsVariousAuthors(localEdition.LocalBooks)) { authorTags.Add("Various Authors"); } else { authorTags.AddRange(localEdition.LocalBooks.MostCommon(x => x.FileTrackInfo.Authors)); } var bookTag = localEdition.LocalBooks.MostCommon(x => x.FileTrackInfo.BookTitle) ?? ""; // If no valid author or book tags, stop if (!authorTags.Any() || bookTag.IsNullOrWhiteSpace()) { yield break; } // Search by author+book foreach (var authorTag in authorTags) { try { remoteBooks = _bookSearchService.SearchForNewBook(bookTag, authorTag); } catch (GoodreadsException e) { _logger.Info(e, "Skipping author/title search due to Goodreads Error"); remoteBooks = new List <Book>(); } foreach (var candidate in ToCandidates(remoteBooks, seenCandidates, idOverrides)) { yield return(candidate); } } // If we got an author/book search result, stop if (seenCandidates.Any()) { yield break; } // Search by just book title try { remoteBooks = _bookSearchService.SearchForNewBook(bookTag, null); } catch (GoodreadsException e) { _logger.Info(e, "Skipping book title search due to Goodreads Error"); remoteBooks = new List <Book>(); } foreach (var candidate in ToCandidates(remoteBooks, seenCandidates, idOverrides)) { yield return(candidate); } // Search by just author foreach (var a in authorTags) { try { remoteBooks = _bookSearchService.SearchForNewBook(a, null); } catch (GoodreadsException e) { _logger.Info(e, "Skipping author search due to Goodreads Error"); remoteBooks = new List <Book>(); } foreach (var candidate in ToCandidates(remoteBooks, seenCandidates, idOverrides)) { yield return(candidate); } } }
private object Search() { var searchResults = _searchProxy.SearchForNewBook((string)Request.Query.term, null); return(MapToResource(searchResults).ToList()); }
public List <CandidateEdition> GetRemoteCandidates(LocalEdition localEdition) { // Gets candidate book releases from the metadata server. // Will eventually need adding locally if we find a match var watch = System.Diagnostics.Stopwatch.StartNew(); List <Book> remoteBooks = null; var candidates = new List <CandidateEdition>(); var goodreads = localEdition.LocalBooks.Select(x => x.FileTrackInfo.GoodreadsId).Distinct().ToList(); var isbns = localEdition.LocalBooks.Select(x => x.FileTrackInfo.Isbn).Distinct().ToList(); var asins = localEdition.LocalBooks.Select(x => x.FileTrackInfo.Asin).Distinct().ToList(); try { if (goodreads.Count == 1 && goodreads[0].IsNotNullOrWhiteSpace()) { if (int.TryParse(goodreads[0], out var id)) { _logger.Trace($"Searching by goodreads id {id}"); remoteBooks = _bookSearchService.SearchByGoodreadsId(id); } } if ((remoteBooks == null || !remoteBooks.Any()) && isbns.Count == 1 && isbns[0].IsNotNullOrWhiteSpace()) { _logger.Trace($"Searching by isbn {isbns[0]}"); remoteBooks = _bookSearchService.SearchByIsbn(isbns[0]); } // Calibre puts junk asins into books it creates so check for sensible length if ((remoteBooks == null || !remoteBooks.Any()) && asins.Count == 1 && asins[0].IsNotNullOrWhiteSpace() && asins[0].Length == 10) { _logger.Trace($"Searching by asin {asins[0]}"); remoteBooks = _bookSearchService.SearchByAsin(asins[0]); } // if no asin/isbn or no result, fall back to text search if (remoteBooks == null || !remoteBooks.Any()) { // fall back to author / book name search string artistTag; if (TrackGroupingService.IsVariousArtists(localEdition.LocalBooks)) { artistTag = "Various Artists"; } else { artistTag = localEdition.LocalBooks.MostCommon(x => x.FileTrackInfo.ArtistTitle) ?? ""; } var albumTag = localEdition.LocalBooks.MostCommon(x => x.FileTrackInfo.AlbumTitle) ?? ""; if (artistTag.IsNullOrWhiteSpace() || albumTag.IsNullOrWhiteSpace()) { return(candidates); } remoteBooks = _bookSearchService.SearchForNewBook(albumTag, artistTag); if (!remoteBooks.Any()) { var albumSearch = _bookSearchService.SearchForNewBook(albumTag, null); var artistSearch = _bookSearchService.SearchForNewBook(artistTag, null); remoteBooks = albumSearch.Concat(artistSearch).DistinctBy(x => x.ForeignBookId).ToList(); } } } catch (SkyHookException e) { _logger.Info(e, "Skipping book due to SkyHook error"); remoteBooks = new List <Book>(); } foreach (var book in remoteBooks) { // We have to make sure various bits and pieces are populated that are normally handled // by a database lazy load foreach (var edition in book.Editions.Value) { edition.Book = book; candidates.Add(new CandidateEdition { Edition = edition, ExistingFiles = new List <BookFile>() }); } } watch.Stop(); _logger.Debug($"Getting {candidates.Count} remote candidates from tags for {localEdition.LocalBooks.Count} tracks took {watch.ElapsedMilliseconds}ms"); return(candidates); }
public object Search(string term) { var searchResults = _searchProxy.SearchForNewBook(term, null); return(MapToResource(searchResults).ToList()); }