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.
145 lines
5.2 KiB
145 lines
5.2 KiB
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using NzbDrone.Core.AuthorStats;
|
|
using NzbDrone.Core.Books;
|
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
|
using NzbDrone.Core.MediaCover;
|
|
using NzbDrone.SignalR;
|
|
using Readarr.Api.V1.Author;
|
|
using Readarr.Http.REST;
|
|
|
|
namespace Readarr.Api.V1.Books
|
|
{
|
|
public abstract class BookControllerWithSignalR : RestControllerWithSignalR<BookResource, Book>
|
|
{
|
|
protected readonly IBookService _bookService;
|
|
protected readonly ISeriesBookLinkService _seriesBookLinkService;
|
|
protected readonly IAuthorStatisticsService _authorStatisticsService;
|
|
protected readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
|
protected readonly IMapCoversToLocal _coverMapper;
|
|
|
|
protected BookControllerWithSignalR(IBookService bookService,
|
|
ISeriesBookLinkService seriesBookLinkService,
|
|
IAuthorStatisticsService authorStatisticsService,
|
|
IMapCoversToLocal coverMapper,
|
|
IUpgradableSpecification qualityUpgradableSpecification,
|
|
IBroadcastSignalRMessage signalRBroadcaster)
|
|
: base(signalRBroadcaster)
|
|
{
|
|
_bookService = bookService;
|
|
_seriesBookLinkService = seriesBookLinkService;
|
|
_authorStatisticsService = authorStatisticsService;
|
|
_coverMapper = coverMapper;
|
|
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
|
}
|
|
|
|
protected override BookResource GetResourceById(int id)
|
|
{
|
|
var book = _bookService.GetBook(id);
|
|
var resource = MapToResource(book, true);
|
|
return resource;
|
|
}
|
|
|
|
protected override BookResource GetResourceByIdForBroadcast(int id)
|
|
{
|
|
var book = _bookService.GetBook(id);
|
|
var resource = MapToResource(book, false);
|
|
return resource;
|
|
}
|
|
|
|
protected BookResource MapToResource(Book book, bool includeAuthor)
|
|
{
|
|
var resource = book.ToResource();
|
|
|
|
if (includeAuthor)
|
|
{
|
|
var author = book.Author.Value;
|
|
|
|
resource.Author = author.ToResource();
|
|
}
|
|
|
|
FetchAndLinkBookStatistics(resource);
|
|
MapCoversToLocal(resource);
|
|
|
|
return resource;
|
|
}
|
|
|
|
protected List<BookResource> MapToResource(List<Book> books, bool includeAuthor)
|
|
{
|
|
var seriesLinks = _seriesBookLinkService.GetLinksByBook(books.Select(x => x.Id).ToList())
|
|
.GroupBy(x => x.BookId)
|
|
.ToDictionary(x => x.Key, y => y.ToList());
|
|
|
|
foreach (var book in books)
|
|
{
|
|
if (seriesLinks.TryGetValue(book.Id, out var links))
|
|
{
|
|
book.SeriesLinks = links;
|
|
}
|
|
else
|
|
{
|
|
book.SeriesLinks = new List<SeriesBookLink>();
|
|
}
|
|
}
|
|
|
|
var result = books.ToResource();
|
|
|
|
if (includeAuthor)
|
|
{
|
|
var authorDict = new Dictionary<int, NzbDrone.Core.Books.Author>();
|
|
for (var i = 0; i < books.Count; i++)
|
|
{
|
|
var book = books[i];
|
|
var resource = result[i];
|
|
var author = authorDict.GetValueOrDefault(books[i].AuthorMetadataId) ?? book.Author?.Value;
|
|
authorDict[author.AuthorMetadataId] = author;
|
|
|
|
resource.Author = author.ToResource();
|
|
}
|
|
}
|
|
|
|
var authorStats = _authorStatisticsService.AuthorStatistics();
|
|
LinkAuthorStatistics(result, authorStats);
|
|
MapCoversToLocal(result.ToArray());
|
|
|
|
return result;
|
|
}
|
|
|
|
private void FetchAndLinkBookStatistics(BookResource resource)
|
|
{
|
|
LinkAuthorStatistics(resource, _authorStatisticsService.AuthorStatistics(resource.AuthorId));
|
|
}
|
|
|
|
private void LinkAuthorStatistics(List<BookResource> resources, List<AuthorStatistics> authorStatistics)
|
|
{
|
|
var bookStatsDict = authorStatistics.SelectMany(x => x.BookStatistics).ToDictionary(x => x.BookId);
|
|
|
|
foreach (var book in resources)
|
|
{
|
|
if (bookStatsDict.TryGetValue(book.Id, out var stats))
|
|
{
|
|
book.Statistics = stats.ToResource();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LinkAuthorStatistics(BookResource resource, AuthorStatistics authorStatistics)
|
|
{
|
|
if (authorStatistics?.BookStatistics != null)
|
|
{
|
|
var dictBookStats = authorStatistics.BookStatistics.ToDictionary(v => v.BookId);
|
|
|
|
resource.Statistics = dictBookStats.GetValueOrDefault(resource.Id).ToResource();
|
|
}
|
|
}
|
|
|
|
private void MapCoversToLocal(params BookResource[] books)
|
|
{
|
|
foreach (var bookResource in books)
|
|
{
|
|
_coverMapper.ConvertToLocalUrls(bookResource.Id, MediaCoverEntity.Book, bookResource.Images);
|
|
}
|
|
}
|
|
}
|
|
}
|