mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-26 22:46:37 -04:00
Method, Variable, Class Renames in Readarr.Api
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AlternateTitleResource
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public int? SeasonNumber { get; set; }
|
||||
public int? SceneSeasonNumber { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AuthorEditorDeleteResource
|
||||
{
|
||||
public List<int> AuthorIds { get; set; }
|
||||
public bool DeleteFiles { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Books;
|
||||
using NzbDrone.Core.Books.Commands;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AuthorEditorModule : ReadarrV1Module
|
||||
{
|
||||
private readonly IAuthorService _authorService;
|
||||
private readonly IManageCommandQueue _commandQueueManager;
|
||||
|
||||
public AuthorEditorModule(IAuthorService authorService, IManageCommandQueue commandQueueManager)
|
||||
: base("/author/editor")
|
||||
{
|
||||
_authorService = authorService;
|
||||
_commandQueueManager = commandQueueManager;
|
||||
Put("/", author => SaveAll());
|
||||
Delete("/", author => DeleteAuthor());
|
||||
}
|
||||
|
||||
private object SaveAll()
|
||||
{
|
||||
var resource = Request.Body.FromJson<AuthorEditorResource>();
|
||||
var authorsToUpdate = _authorService.GetAuthors(resource.AuthorIds);
|
||||
var authorsToMove = new List<BulkMoveAuthor>();
|
||||
|
||||
foreach (var author in authorsToUpdate)
|
||||
{
|
||||
if (resource.Monitored.HasValue)
|
||||
{
|
||||
author.Monitored = resource.Monitored.Value;
|
||||
}
|
||||
|
||||
if (resource.QualityProfileId.HasValue)
|
||||
{
|
||||
author.QualityProfileId = resource.QualityProfileId.Value;
|
||||
}
|
||||
|
||||
if (resource.MetadataProfileId.HasValue)
|
||||
{
|
||||
author.MetadataProfileId = resource.MetadataProfileId.Value;
|
||||
}
|
||||
|
||||
if (resource.RootFolderPath.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
author.RootFolderPath = resource.RootFolderPath;
|
||||
authorsToMove.Add(new BulkMoveAuthor
|
||||
{
|
||||
AuthorId = author.Id,
|
||||
SourcePath = author.Path
|
||||
});
|
||||
}
|
||||
|
||||
if (resource.Tags != null)
|
||||
{
|
||||
var newTags = resource.Tags;
|
||||
var applyTags = resource.ApplyTags;
|
||||
|
||||
switch (applyTags)
|
||||
{
|
||||
case ApplyTags.Add:
|
||||
newTags.ForEach(t => author.Tags.Add(t));
|
||||
break;
|
||||
case ApplyTags.Remove:
|
||||
newTags.ForEach(t => author.Tags.Remove(t));
|
||||
break;
|
||||
case ApplyTags.Replace:
|
||||
author.Tags = new HashSet<int>(newTags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource.MoveFiles && authorsToMove.Any())
|
||||
{
|
||||
_commandQueueManager.Push(new BulkMoveAuthorCommand
|
||||
{
|
||||
DestinationRootFolder = resource.RootFolderPath,
|
||||
Author = authorsToMove
|
||||
});
|
||||
}
|
||||
|
||||
return ResponseWithCode(_authorService.UpdateAuthors(authorsToUpdate, !resource.MoveFiles)
|
||||
.ToResource(),
|
||||
HttpStatusCode.Accepted);
|
||||
}
|
||||
|
||||
private object DeleteAuthor()
|
||||
{
|
||||
var resource = Request.Body.FromJson<AuthorEditorResource>();
|
||||
|
||||
foreach (var authorId in resource.AuthorIds)
|
||||
{
|
||||
_authorService.DeleteAuthor(authorId, false);
|
||||
}
|
||||
|
||||
return new object();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AuthorEditorResource
|
||||
{
|
||||
public List<int> AuthorIds { get; set; }
|
||||
public bool? Monitored { get; set; }
|
||||
public int? QualityProfileId { get; set; }
|
||||
public int? MetadataProfileId { get; set; }
|
||||
public string RootFolderPath { get; set; }
|
||||
public List<int> Tags { get; set; }
|
||||
public ApplyTags ApplyTags { get; set; }
|
||||
public bool MoveFiles { get; set; }
|
||||
}
|
||||
|
||||
public enum ApplyTags
|
||||
{
|
||||
Add,
|
||||
Remove,
|
||||
Replace
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using Nancy;
|
||||
using NzbDrone.Core.Books;
|
||||
using Readarr.Http;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AuthorImportModule : ReadarrRestModule<AuthorResource>
|
||||
{
|
||||
private readonly IAddAuthorService _addAuthorService;
|
||||
|
||||
public AuthorImportModule(IAddAuthorService addAuthorService)
|
||||
: base("/author/import")
|
||||
{
|
||||
_addAuthorService = addAuthorService;
|
||||
Post("/", x => Import());
|
||||
}
|
||||
|
||||
private object Import()
|
||||
{
|
||||
var resource = Request.Body.FromJson<List<AuthorResource>>();
|
||||
var newAuthors = resource.ToModel();
|
||||
|
||||
return _addAuthorService.AddAuthors(newAuthors).ToResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using Readarr.Http;
|
||||
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AuthorLookupModule : ReadarrRestModule<AuthorResource>
|
||||
{
|
||||
private readonly ISearchForNewAuthor _searchProxy;
|
||||
|
||||
public AuthorLookupModule(ISearchForNewAuthor searchProxy)
|
||||
: base("/author/lookup")
|
||||
{
|
||||
_searchProxy = searchProxy;
|
||||
Get("/", x => Search());
|
||||
}
|
||||
|
||||
private object Search()
|
||||
{
|
||||
var searchResults = _searchProxy.SearchForNewAuthor((string)Request.Query.term);
|
||||
return MapToResource(searchResults).ToList();
|
||||
}
|
||||
|
||||
private static IEnumerable<AuthorResource> MapToResource(IEnumerable<NzbDrone.Core.Books.Author> author)
|
||||
{
|
||||
foreach (var currentAuthor in author)
|
||||
{
|
||||
var resource = currentAuthor.ToResource();
|
||||
var poster = currentAuthor.Metadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
if (poster != null)
|
||||
{
|
||||
resource.RemotePoster = poster.Url;
|
||||
}
|
||||
|
||||
yield return resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.AuthorStats;
|
||||
using NzbDrone.Core.Books;
|
||||
using NzbDrone.Core.Books.Commands;
|
||||
using NzbDrone.Core.Books.Events;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
using NzbDrone.SignalR;
|
||||
using Readarr.Http;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AuthorModule : ReadarrRestModuleWithSignalR<AuthorResource, NzbDrone.Core.Books.Author>,
|
||||
IHandle<BookImportedEvent>,
|
||||
IHandle<BookEditedEvent>,
|
||||
IHandle<BookFileDeletedEvent>,
|
||||
IHandle<AuthorUpdatedEvent>,
|
||||
IHandle<AuthorEditedEvent>,
|
||||
IHandle<AuthorDeletedEvent>,
|
||||
IHandle<AuthorRenamedEvent>,
|
||||
IHandle<MediaCoversUpdatedEvent>
|
||||
{
|
||||
private readonly IAuthorService _authorService;
|
||||
private readonly IBookService _bookService;
|
||||
private readonly IAddAuthorService _addAuthorService;
|
||||
private readonly IAuthorStatisticsService _authorStatisticsService;
|
||||
private readonly IMapCoversToLocal _coverMapper;
|
||||
private readonly IManageCommandQueue _commandQueueManager;
|
||||
private readonly IRootFolderService _rootFolderService;
|
||||
|
||||
public AuthorModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IAuthorService authorService,
|
||||
IBookService bookService,
|
||||
IAddAuthorService addAuthorService,
|
||||
IAuthorStatisticsService authorStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IManageCommandQueue commandQueueManager,
|
||||
IRootFolderService rootFolderService,
|
||||
RootFolderValidator rootFolderValidator,
|
||||
MappedNetworkDriveValidator mappedNetworkDriveValidator,
|
||||
AuthorPathValidator authorPathValidator,
|
||||
AuthorExistsValidator authorExistsValidator,
|
||||
AuthorAncestorValidator authorAncestorValidator,
|
||||
SystemFolderValidator systemFolderValidator,
|
||||
QualityProfileExistsValidator qualityProfileExistsValidator,
|
||||
MetadataProfileExistsValidator metadataProfileExistsValidator)
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_authorService = authorService;
|
||||
_bookService = bookService;
|
||||
_addAuthorService = addAuthorService;
|
||||
_authorStatisticsService = authorStatisticsService;
|
||||
|
||||
_coverMapper = coverMapper;
|
||||
_commandQueueManager = commandQueueManager;
|
||||
_rootFolderService = rootFolderService;
|
||||
|
||||
GetResourceAll = AllAuthors;
|
||||
GetResourceById = GetAuthor;
|
||||
CreateResource = AddAuthor;
|
||||
UpdateResource = UpdateAuthor;
|
||||
DeleteResource = DeleteAuthor;
|
||||
|
||||
Http.Validation.RuleBuilderExtensions.ValidId(SharedValidator.RuleFor(s => s.QualityProfileId));
|
||||
Http.Validation.RuleBuilderExtensions.ValidId(SharedValidator.RuleFor(s => s.MetadataProfileId));
|
||||
|
||||
SharedValidator.RuleFor(s => s.Path)
|
||||
.Cascade(CascadeMode.StopOnFirstFailure)
|
||||
.IsValidPath()
|
||||
.SetValidator(rootFolderValidator)
|
||||
.SetValidator(mappedNetworkDriveValidator)
|
||||
.SetValidator(authorPathValidator)
|
||||
.SetValidator(authorAncestorValidator)
|
||||
.SetValidator(systemFolderValidator)
|
||||
.When(s => !s.Path.IsNullOrWhiteSpace());
|
||||
|
||||
SharedValidator.RuleFor(s => s.QualityProfileId).SetValidator(qualityProfileExistsValidator);
|
||||
SharedValidator.RuleFor(s => s.MetadataProfileId).SetValidator(metadataProfileExistsValidator);
|
||||
|
||||
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.AuthorName).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.ForeignAuthorId).NotEmpty().SetValidator(authorExistsValidator);
|
||||
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
}
|
||||
|
||||
private AuthorResource GetAuthor(int id)
|
||||
{
|
||||
var author = _authorService.GetAuthor(id);
|
||||
return GetArtistResource(author);
|
||||
}
|
||||
|
||||
private AuthorResource GetArtistResource(NzbDrone.Core.Books.Author author)
|
||||
{
|
||||
if (author == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var resource = author.ToResource();
|
||||
MapCoversToLocal(resource);
|
||||
FetchAndLinkArtistStatistics(resource);
|
||||
LinkNextPreviousAlbums(resource);
|
||||
|
||||
//PopulateAlternateTitles(resource);
|
||||
LinkRootFolderPath(resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
private List<AuthorResource> AllAuthors()
|
||||
{
|
||||
var authorStats = _authorStatisticsService.AuthorStatistics();
|
||||
var authorResources = _authorService.GetAllAuthors().ToResource();
|
||||
|
||||
MapCoversToLocal(authorResources.ToArray());
|
||||
LinkNextPreviousAlbums(authorResources.ToArray());
|
||||
LinkArtistStatistics(authorResources, authorStats);
|
||||
|
||||
//PopulateAlternateTitles(seriesResources);
|
||||
return authorResources;
|
||||
}
|
||||
|
||||
private int AddAuthor(AuthorResource authorResource)
|
||||
{
|
||||
var author = _addAuthorService.AddAuthor(authorResource.ToModel());
|
||||
|
||||
return author.Id;
|
||||
}
|
||||
|
||||
private void UpdateAuthor(AuthorResource authorResource)
|
||||
{
|
||||
var moveFiles = Request.GetBooleanQueryParameter("moveFiles");
|
||||
var author = _authorService.GetAuthor(authorResource.Id);
|
||||
|
||||
if (moveFiles)
|
||||
{
|
||||
var sourcePath = author.Path;
|
||||
var destinationPath = authorResource.Path;
|
||||
|
||||
_commandQueueManager.Push(new MoveAuthorCommand
|
||||
{
|
||||
AuthorId = author.Id,
|
||||
SourcePath = sourcePath,
|
||||
DestinationPath = destinationPath,
|
||||
Trigger = CommandTrigger.Manual
|
||||
});
|
||||
}
|
||||
|
||||
var model = authorResource.ToModel(author);
|
||||
|
||||
_authorService.UpdateAuthor(model);
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, authorResource);
|
||||
}
|
||||
|
||||
private void DeleteAuthor(int id)
|
||||
{
|
||||
var deleteFiles = Request.GetBooleanQueryParameter("deleteFiles");
|
||||
var addImportListExclusion = Request.GetBooleanQueryParameter("addImportListExclusion");
|
||||
|
||||
_authorService.DeleteAuthor(id, deleteFiles, addImportListExclusion);
|
||||
}
|
||||
|
||||
private void MapCoversToLocal(params AuthorResource[] authors)
|
||||
{
|
||||
foreach (var authorResource in authors)
|
||||
{
|
||||
_coverMapper.ConvertToLocalUrls(authorResource.Id, MediaCoverEntity.Author, authorResource.Images);
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkNextPreviousAlbums(params AuthorResource[] authors)
|
||||
{
|
||||
var nextBooks = _bookService.GetNextBooksByAuthorMetadataId(authors.Select(x => x.AuthorMetadataId));
|
||||
var lastBooks = _bookService.GetLastBooksByAuthorMetadataId(authors.Select(x => x.AuthorMetadataId));
|
||||
|
||||
foreach (var authorResource in authors)
|
||||
{
|
||||
authorResource.NextBook = nextBooks.FirstOrDefault(x => x.AuthorMetadataId == authorResource.AuthorMetadataId);
|
||||
authorResource.LastBook = lastBooks.FirstOrDefault(x => x.AuthorMetadataId == authorResource.AuthorMetadataId);
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchAndLinkArtistStatistics(AuthorResource resource)
|
||||
{
|
||||
LinkArtistStatistics(resource, _authorStatisticsService.AuthorStatistics(resource.Id));
|
||||
}
|
||||
|
||||
private void LinkArtistStatistics(List<AuthorResource> resources, List<AuthorStatistics> authorStatistics)
|
||||
{
|
||||
foreach (var author in resources)
|
||||
{
|
||||
var stats = authorStatistics.SingleOrDefault(ss => ss.AuthorId == author.Id);
|
||||
if (stats == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LinkArtistStatistics(author, stats);
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkArtistStatistics(AuthorResource resource, AuthorStatistics authorStatistics)
|
||||
{
|
||||
resource.Statistics = authorStatistics.ToResource();
|
||||
}
|
||||
|
||||
//private void PopulateAlternateTitles(List<ArtistResource> resources)
|
||||
//{
|
||||
// foreach (var resource in resources)
|
||||
// {
|
||||
// PopulateAlternateTitles(resource);
|
||||
// }
|
||||
//}
|
||||
|
||||
//private void PopulateAlternateTitles(ArtistResource resource)
|
||||
//{
|
||||
// var mappings = _sceneMappingService.FindByTvdbId(resource.TvdbId);
|
||||
|
||||
// if (mappings == null) return;
|
||||
|
||||
// resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
||||
//}
|
||||
private void LinkRootFolderPath(AuthorResource resource)
|
||||
{
|
||||
resource.RootFolderPath = _rootFolderService.GetBestRootFolderPath(resource.Path);
|
||||
}
|
||||
|
||||
public void Handle(BookImportedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Author));
|
||||
}
|
||||
|
||||
public void Handle(BookEditedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Book.Author.Value));
|
||||
}
|
||||
|
||||
public void Handle(BookFileDeletedEvent message)
|
||||
{
|
||||
if (message.Reason == DeleteMediaFileReason.Upgrade)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.BookFile.Author.Value));
|
||||
}
|
||||
|
||||
public void Handle(AuthorUpdatedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Author));
|
||||
}
|
||||
|
||||
public void Handle(AuthorEditedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Author));
|
||||
}
|
||||
|
||||
public void Handle(AuthorDeletedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Deleted, message.Author.ToResource());
|
||||
}
|
||||
|
||||
public void Handle(AuthorRenamedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Author.Id);
|
||||
}
|
||||
|
||||
public void Handle(MediaCoversUpdatedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Author));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Books;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AuthorResource : RestResource
|
||||
{
|
||||
//Todo: Sorters should be done completely on the client
|
||||
//Todo: Is there an easy way to keep IgnoreArticlesWhenSorting in sync between, Series, History, Missing?
|
||||
//Todo: We should get the entire Profile instead of ID and Name separately
|
||||
[JsonIgnore]
|
||||
public int AuthorMetadataId { get; set; }
|
||||
public AuthorStatusType Status { get; set; }
|
||||
|
||||
public bool Ended => Status == AuthorStatusType.Ended;
|
||||
|
||||
public string AuthorName { get; set; }
|
||||
public string ForeignAuthorId { get; set; }
|
||||
public int GoodreadsId { get; set; }
|
||||
public string TitleSlug { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public string AuthorType { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
public List<Links> Links { get; set; }
|
||||
|
||||
public Book NextBook { get; set; }
|
||||
public Book LastBook { get; set; }
|
||||
|
||||
public List<MediaCover> Images { get; set; }
|
||||
|
||||
public string RemotePoster { get; set; }
|
||||
|
||||
//View & Edit
|
||||
public string Path { get; set; }
|
||||
public int QualityProfileId { get; set; }
|
||||
public int MetadataProfileId { get; set; }
|
||||
|
||||
//Editing Only
|
||||
public bool Monitored { get; set; }
|
||||
|
||||
public string RootFolderPath { get; set; }
|
||||
public List<string> Genres { get; set; }
|
||||
public string CleanName { get; set; }
|
||||
public string SortName { get; set; }
|
||||
public HashSet<int> Tags { get; set; }
|
||||
public DateTime Added { get; set; }
|
||||
public AddAuthorOptions AddOptions { get; set; }
|
||||
public Ratings Ratings { get; set; }
|
||||
|
||||
public AuthorStatisticsResource Statistics { get; set; }
|
||||
}
|
||||
|
||||
public static class AuthorResourceMapper
|
||||
{
|
||||
public static AuthorResource ToResource(this NzbDrone.Core.Books.Author model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AuthorResource
|
||||
{
|
||||
Id = model.Id,
|
||||
AuthorMetadataId = model.AuthorMetadataId,
|
||||
|
||||
AuthorName = model.Name,
|
||||
|
||||
//AlternateTitles
|
||||
SortName = model.SortName,
|
||||
|
||||
Status = model.Metadata.Value.Status,
|
||||
Overview = model.Metadata.Value.Overview,
|
||||
AuthorType = model.Metadata.Value.Type,
|
||||
Disambiguation = model.Metadata.Value.Disambiguation,
|
||||
|
||||
Images = model.Metadata.Value.Images.JsonClone(),
|
||||
|
||||
Path = model.Path,
|
||||
QualityProfileId = model.QualityProfileId,
|
||||
MetadataProfileId = model.MetadataProfileId,
|
||||
Links = model.Metadata.Value.Links,
|
||||
|
||||
Monitored = model.Monitored,
|
||||
|
||||
CleanName = model.CleanName,
|
||||
ForeignAuthorId = model.Metadata.Value.ForeignAuthorId,
|
||||
GoodreadsId = model.Metadata.Value.GoodreadsId,
|
||||
TitleSlug = model.Metadata.Value.TitleSlug,
|
||||
|
||||
// Root folder path is now calculated from the artist path
|
||||
// RootFolderPath = model.RootFolderPath,
|
||||
Genres = model.Metadata.Value.Genres,
|
||||
Tags = model.Tags,
|
||||
Added = model.Added,
|
||||
AddOptions = model.AddOptions,
|
||||
Ratings = model.Metadata.Value.Ratings,
|
||||
|
||||
Statistics = new AuthorStatisticsResource()
|
||||
};
|
||||
}
|
||||
|
||||
public static NzbDrone.Core.Books.Author ToModel(this AuthorResource resource)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new NzbDrone.Core.Books.Author
|
||||
{
|
||||
Id = resource.Id,
|
||||
|
||||
Metadata = new NzbDrone.Core.Books.AuthorMetadata
|
||||
{
|
||||
ForeignAuthorId = resource.ForeignAuthorId,
|
||||
GoodreadsId = resource.GoodreadsId,
|
||||
TitleSlug = resource.TitleSlug,
|
||||
Name = resource.AuthorName,
|
||||
Status = resource.Status,
|
||||
Overview = resource.Overview,
|
||||
Links = resource.Links,
|
||||
Images = resource.Images,
|
||||
Genres = resource.Genres,
|
||||
Ratings = resource.Ratings,
|
||||
Type = resource.AuthorType
|
||||
},
|
||||
|
||||
//AlternateTitles
|
||||
SortName = resource.SortName,
|
||||
Path = resource.Path,
|
||||
QualityProfileId = resource.QualityProfileId,
|
||||
MetadataProfileId = resource.MetadataProfileId,
|
||||
|
||||
Monitored = resource.Monitored,
|
||||
|
||||
CleanName = resource.CleanName,
|
||||
RootFolderPath = resource.RootFolderPath,
|
||||
|
||||
Tags = resource.Tags,
|
||||
Added = resource.Added,
|
||||
AddOptions = resource.AddOptions,
|
||||
};
|
||||
}
|
||||
|
||||
public static NzbDrone.Core.Books.Author ToModel(this AuthorResource resource, NzbDrone.Core.Books.Author author)
|
||||
{
|
||||
var updatedAuthor = resource.ToModel();
|
||||
|
||||
author.ApplyChanges(updatedAuthor);
|
||||
|
||||
return author;
|
||||
}
|
||||
|
||||
public static List<AuthorResource> ToResource(this IEnumerable<NzbDrone.Core.Books.Author> author)
|
||||
{
|
||||
return author.Select(ToResource).ToList();
|
||||
}
|
||||
|
||||
public static List<NzbDrone.Core.Books.Author> ToModel(this IEnumerable<AuthorResource> resources)
|
||||
{
|
||||
return resources.Select(ToModel).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using NzbDrone.Core.AuthorStats;
|
||||
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AuthorStatisticsResource
|
||||
{
|
||||
public int BookCount { get; set; }
|
||||
public int BookFileCount { get; set; }
|
||||
public int TotalBookCount { get; set; }
|
||||
public long SizeOnDisk { get; set; }
|
||||
|
||||
public decimal PercentOfBooks
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BookCount == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BookFileCount / (decimal)BookCount * 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class AuthorStatisticsResourceMapper
|
||||
{
|
||||
public static AuthorStatisticsResource ToResource(this AuthorStatistics model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AuthorStatisticsResource
|
||||
{
|
||||
BookCount = model.BookCount,
|
||||
BookFileCount = model.BookFileCount,
|
||||
SizeOnDisk = model.SizeOnDisk
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user