You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Readarr/src/NzbDrone.Core/MetadataSource/Goodreads/Resources/BookResource.cs

241 lines
8.5 KiB

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;
namespace NzbDrone.Core.MetadataSource.Goodreads
{
/// <summary>
/// This class models a single book as defined by the Goodreads API.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public sealed class BookResource : GoodreadsResource
{
public override string ElementName => "book";
/// <summary>
/// The Goodreads Id for this book.
/// </summary>
public long Id { get; private set; }
/// <summary>
/// The title of this book.
/// </summary>
public string Title { get; private set; }
public string TitleWithoutSeries { get; private set; }
/// <summary>
/// The description of this book.
/// </summary>
public string Description { get; private set; }
/// <summary>
/// The ISBN of this book.
/// </summary>
public string Isbn { get; private set; }
/// <summary>
/// The ISBN13 of this book.
/// </summary>
public string Isbn13 { get; private set; }
/// <summary>
/// The ASIN of this book.
/// </summary>
public string Asin { get; private set; }
/// <summary>
/// The Kindle ASIN of this book.
/// </summary>
public string KindleAsin { get; private set; }
/// <summary>
/// The marketplace Id of this book.
/// </summary>
public string MarketplaceId { get; private set; }
/// <summary>
/// The country code of this book.
/// </summary>
public string CountryCode { get; private set; }
/// <summary>
/// The cover image for this book.
/// </summary>
public string ImageUrl { get; private set; }
/// <summary>
/// The date this book was published.
/// </summary>
public DateTime? PublicationDate { get; private set; }
/// <summary>
/// The publisher of this book.
/// </summary>
public string Publisher { get; private set; }
/// <summary>
/// The language code of this book.
/// </summary>
public string LanguageCode { get; private set; }
/// <summary>
/// Signifies if this is an eBook or not.
/// </summary>
public bool IsEbook { get; private set; }
/// <summary>
/// The average rating of this book by Goodreads users.
/// </summary>
public decimal AverageRating { get; private set; }
/// <summary>
/// The number of pages in this book.
/// </summary>
public int Pages { get; private set; }
/// <summary>
/// The format of this book.
/// </summary>
public string Format { get; private set; }
/// <summary>
/// Brief information about this edition of the book.
/// </summary>
public string EditionInformation { get; private set; }
/// <summary>
/// The count of all Goodreads ratings for this book.
/// </summary>
public int RatingsCount { get; private set; }
/// <summary>
/// The count of all reviews that contain text for this book.
/// </summary>
public int TextReviewsCount { get; private set; }
/// <summary>
/// The Goodreads Url for this book.
/// </summary>
public string Url { get; private set; }
public string EditionsUrl { get; private set; }
/// <summary>
/// The aggregate information for this work across all editions of the book.
/// </summary>
public WorkResource Work { get; private set; }
/// <summary>
/// The list of authors that worked on this book.
/// </summary>
public IReadOnlyList<AuthorSummaryResource> Authors { get; private set; }
/// <summary>
/// HTML and CSS for the Goodreads iFrame. Used to display the reviews for this book.
/// </summary>
public string ReviewsWidget { get; private set; }
/// <summary>
/// The most popular shelf names this book appears on. This is a
/// dictionary of shelf name -> count.
/// </summary>
public IReadOnlyDictionary<string, int> PopularShelves { get; private set; }
/// <summary>
/// The list of book links tracked by Goodreads.
/// This is usually a list of libraries that the user can borrow the book from.
/// </summary>
public IReadOnlyList<BookLinkResource> BookLinks { get; private set; }
/// <summary>
/// The list of buy links tracked by Goodreads.
/// This is usually a list of third-party sites that the
/// user can purchase the book from.
/// </summary>
public IReadOnlyList<BookLinkResource> BuyLinks { get; private set; }
/// <summary>
/// Summary information about similar books to this one.
/// </summary>
public IReadOnlyList<BookSummaryResource> SimilarBooks { get; private set; }
// TODO: parse series information once I get a better sense
// of what series are from the other API calls.
//// public List<Series> Series { get; private set; }
public override void Parse(XElement element)
{
Id = element.ElementAsLong("id");
Title = element.ElementAsString("title");
TitleWithoutSeries = element.ElementAsString("title_without_series");
Isbn = element.ElementAsString("isbn");
Isbn13 = element.ElementAsString("isbn13");
Asin = element.ElementAsString("asin");
KindleAsin = element.ElementAsString("kindle_asin");
MarketplaceId = element.ElementAsString("marketplace_id");
CountryCode = element.ElementAsString("country_code");
ImageUrl = element.ElementAsString("large_image_url") ??
element.ElementAsString("image_url") ??
element.ElementAsString("small_image_url");
PublicationDate = element.ElementAsMultiDateField("publication");
Publisher = element.ElementAsString("publisher");
LanguageCode = element.ElementAsString("language_code");
IsEbook = element.ElementAsBool("is_ebook");
Description = element.ElementAsString("description");
AverageRating = element.ElementAsDecimal("average_rating");
Pages = element.ElementAsInt("num_pages");
Format = element.ElementAsString("format");
EditionInformation = element.ElementAsString("edition_information");
RatingsCount = element.ElementAsInt("ratings_count");
TextReviewsCount = element.ElementAsInt("text_reviews_count");
Url = element.ElementAsString("link");
EditionsUrl = element.ElementAsString("editions_url");
ReviewsWidget = element.ElementAsString("reviews_widget");
var workElement = element.Element("work");
if (workElement != null)
{
Work = new WorkResource();
Work.Parse(workElement);
}
Authors = element.ParseChildren<AuthorSummaryResource>("authors", "author");
SimilarBooks = element.ParseChildren<BookSummaryResource>("similar_books", "book");
var bookLinks = element.ParseChildren<BookLinkResource>("book_links", "book_link");
if (bookLinks != null)
{
bookLinks.ForEach(x => x.FixBookLink(Id));
BookLinks = bookLinks;
}
var buyLinks = element.ParseChildren<BookLinkResource>("buy_links", "buy_link");
if (buyLinks != null)
{
buyLinks.ForEach(x => x.FixBookLink(Id));
BuyLinks = buyLinks;
}
var shelves = element.ParseChildren(
"popular_shelves",
"shelf",
(shelfElement) =>
{
var shelfName = shelfElement?.Attribute("name")?.Value;
var shelfCountValue = shelfElement?.Attribute("count")?.Value;
int.TryParse(shelfCountValue, out var shelfCount);
return new KeyValuePair<string, int>(shelfName, shelfCount);
});
if (shelves != null)
{
PopularShelves = shelves.GroupBy(obj => obj.Key).ToDictionary(shelf => shelf.Key, shelf => shelf.Sum(x => x.Value));
}
}
}
}