mirror of
https://github.com/Readarr/Readarr
synced 2025-12-14 12:24:49 +01:00
Method, Variable, Class Renames in Readarr.Api
This commit is contained in:
parent
8080d375d0
commit
ee4e44b81a
91 changed files with 945 additions and 948 deletions
|
|
@ -21,7 +21,7 @@ public void artist_page()
|
|||
{
|
||||
_page.LibraryNavIcon.Click();
|
||||
_page.WaitForNoSpinner();
|
||||
_page.Find(By.CssSelector("div[class*='ArtistIndex']")).Should().NotBeNull();
|
||||
_page.Find(By.CssSelector("div[class*='AuthorIndex']")).Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public void Setup()
|
|||
private void GivenUnmonitorDeletedTracks(bool enabled)
|
||||
{
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(v => v.AutoUnmonitorPreviouslyDownloadedTracks)
|
||||
.SetupGet(v => v.AutoUnmonitorPreviouslyDownloadedBooks)
|
||||
.Returns(enabled);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public void Setup()
|
|||
.Returns(_artist);
|
||||
|
||||
Mocker.GetMock<ISearchForNzb>()
|
||||
.Setup(s => s.ArtistSearch(_artist.Id, false, true, false))
|
||||
.Setup(s => s.AuthorSearch(_artist.Id, false, true, false))
|
||||
.Returns(new List<DownloadDecision>());
|
||||
|
||||
Mocker.GetMock<IProcessDownloadDecisions>()
|
||||
|
|
@ -46,7 +46,7 @@ public void should_only_include_monitored_albums()
|
|||
Subject.Execute(new AuthorSearchCommand { AuthorId = _artist.Id, Trigger = CommandTrigger.Manual });
|
||||
|
||||
Mocker.GetMock<ISearchForNzb>()
|
||||
.Verify(v => v.ArtistSearch(_artist.Id, false, true, false),
|
||||
.Verify(v => v.AuthorSearch(_artist.Id, false, true, false),
|
||||
Times.Exactly(_artist.Books.Value.Count(s => s.Monitored)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ public void Handle(BookImportedEvent message)
|
|||
public void Handle(BookEditedEvent message)
|
||||
{
|
||||
_cache.Remove("AllAuthors");
|
||||
_cache.Remove(message.Album.AuthorId.ToString());
|
||||
_cache.Remove(message.Book.AuthorId.ToString());
|
||||
}
|
||||
|
||||
[EventHandleOrder(EventHandleOrder.First)]
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ namespace NzbDrone.Core.Books.Events
|
|||
{
|
||||
public class BookEditedEvent : IEvent
|
||||
{
|
||||
public Book Album { get; private set; }
|
||||
public Book Book { get; private set; }
|
||||
public Book OldAlbum { get; private set; }
|
||||
|
||||
public BookEditedEvent(Book book, Book oldAlbum)
|
||||
{
|
||||
Album = book;
|
||||
Book = book;
|
||||
OldAlbum = oldAlbum;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ public bool IsDefined(string key)
|
|||
return _repository.Get(key.ToLower()) != null;
|
||||
}
|
||||
|
||||
public bool AutoUnmonitorPreviouslyDownloadedTracks
|
||||
public bool AutoUnmonitorPreviouslyDownloadedBooks
|
||||
{
|
||||
get { return GetValueBoolean("AutoUnmonitorPreviouslyDownloadedTracks"); }
|
||||
set { SetValue("AutoUnmonitorPreviouslyDownloadedTracks", value); }
|
||||
|
|
@ -158,7 +158,7 @@ public bool RemoveFailedDownloads
|
|||
set { SetValue("RemoveFailedDownloads", value); }
|
||||
}
|
||||
|
||||
public bool CreateEmptyArtistFolders
|
||||
public bool CreateEmptyAuthorFolders
|
||||
{
|
||||
get { return GetValueBoolean("CreateEmptyArtistFolders", false); }
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ public interface IConfigService
|
|||
bool RemoveFailedDownloads { get; set; }
|
||||
|
||||
//Media Management
|
||||
bool AutoUnmonitorPreviouslyDownloadedTracks { get; set; }
|
||||
bool AutoUnmonitorPreviouslyDownloadedBooks { get; set; }
|
||||
string RecycleBin { get; set; }
|
||||
int RecycleBinCleanupDays { get; set; }
|
||||
ProperDownloadTypes DownloadPropersAndRepacks { get; set; }
|
||||
bool CreateEmptyArtistFolders { get; set; }
|
||||
bool CreateEmptyAuthorFolders { get; set; }
|
||||
bool DeleteEmptyFolders { get; set; }
|
||||
FileDateType FileDate { get; set; }
|
||||
bool SkipFreeSpaceCheckWhenImporting { get; set; }
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public DeletedBookFileSpecification(IDiskProvider diskProvider,
|
|||
|
||||
public virtual Decision IsSatisfiedBy(RemoteBook subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (!_configService.AutoUnmonitorPreviouslyDownloadedTracks)
|
||||
if (!_configService.AutoUnmonitorPreviouslyDownloadedBooks)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public bool IsImported(TrackedDownload trackedDownload, List<History.History> hi
|
|||
return false;
|
||||
}
|
||||
|
||||
return new[] { HistoryEventType.DownloadImported, HistoryEventType.TrackFileImported }.Contains(lastHistoryItem.EventType);
|
||||
return new[] { HistoryEventType.DownloadImported, HistoryEventType.BookFileImported }.Contains(lastHistoryItem.EventType);
|
||||
});
|
||||
|
||||
return allAlbumsImportedInHistory;
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ private static TrackedDownloadState GetStateFromHistory(NzbDrone.Core.History.Hi
|
|||
}
|
||||
|
||||
// Since DownloadComplete is a new event type, we can't assume it exists for old downloads
|
||||
if (history.EventType == HistoryEventType.TrackFileImported)
|
||||
if (history.EventType == HistoryEventType.BookFileImported)
|
||||
{
|
||||
return DateTime.UtcNow.Subtract(history.Date).TotalSeconds < 60 ? TrackedDownloadState.Importing : TrackedDownloadState.Imported;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,14 +32,14 @@ public enum HistoryEventType
|
|||
{
|
||||
Unknown = 0,
|
||||
Grabbed = 1,
|
||||
ArtistFolderImported = 2,
|
||||
TrackFileImported = 3,
|
||||
AuthorFolderImported = 2,
|
||||
BookFileImported = 3,
|
||||
DownloadFailed = 4,
|
||||
TrackFileDeleted = 5,
|
||||
TrackFileRenamed = 6,
|
||||
BookFileDeleted = 5,
|
||||
BookFileRenamed = 6,
|
||||
BookImportIncomplete = 7,
|
||||
DownloadImported = 8,
|
||||
TrackFileRetagged = 9,
|
||||
BookFileRetagged = 9,
|
||||
DownloadIgnored = 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public List<History> GetByBook(int bookId, HistoryEventType? eventType)
|
|||
|
||||
public List<History> FindDownloadHistory(int idAuthorId, QualityModel quality)
|
||||
{
|
||||
var allowed = new[] { HistoryEventType.Grabbed, HistoryEventType.DownloadFailed, HistoryEventType.TrackFileImported };
|
||||
var allowed = new[] { HistoryEventType.Grabbed, HistoryEventType.DownloadFailed, HistoryEventType.BookFileImported };
|
||||
|
||||
return Query(h => h.AuthorId == idAuthorId &&
|
||||
h.Quality == quality &&
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ public void Handle(TrackImportedEvent message)
|
|||
|
||||
var history = new History
|
||||
{
|
||||
EventType = HistoryEventType.TrackFileImported,
|
||||
EventType = HistoryEventType.BookFileImported,
|
||||
Date = DateTime.UtcNow,
|
||||
Quality = message.BookInfo.Quality,
|
||||
SourceTitle = message.ImportedBook.SceneName ?? Path.GetFileNameWithoutExtension(message.BookInfo.Path),
|
||||
|
|
@ -289,7 +289,7 @@ public void Handle(BookFileDeletedEvent message)
|
|||
|
||||
var history = new History
|
||||
{
|
||||
EventType = HistoryEventType.TrackFileDeleted,
|
||||
EventType = HistoryEventType.BookFileDeleted,
|
||||
Date = DateTime.UtcNow,
|
||||
Quality = message.BookFile.Quality,
|
||||
SourceTitle = message.BookFile.Path,
|
||||
|
|
@ -309,7 +309,7 @@ public void Handle(BookFileRenamedEvent message)
|
|||
|
||||
var history = new History
|
||||
{
|
||||
EventType = HistoryEventType.TrackFileRenamed,
|
||||
EventType = HistoryEventType.BookFileRenamed,
|
||||
Date = DateTime.UtcNow,
|
||||
Quality = message.BookFile.Quality,
|
||||
SourceTitle = message.OriginalPath,
|
||||
|
|
@ -329,7 +329,7 @@ public void Handle(BookFileRetaggedEvent message)
|
|||
|
||||
var history = new History
|
||||
{
|
||||
EventType = HistoryEventType.TrackFileRetagged,
|
||||
EventType = HistoryEventType.BookFileRetagged,
|
||||
Date = DateTime.UtcNow,
|
||||
Quality = message.BookFile.Quality,
|
||||
SourceTitle = path,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public AuthorSearchService(ISearchForNzb nzbSearchService,
|
|||
|
||||
public void Execute(AuthorSearchCommand message)
|
||||
{
|
||||
var decisions = _nzbSearchService.ArtistSearch(message.AuthorId, false, message.Trigger == CommandTrigger.Manual, false);
|
||||
var decisions = _nzbSearchService.AuthorSearch(message.AuthorId, false, message.Trigger == CommandTrigger.Manual, false);
|
||||
var processed = _processDownloadDecisions.ProcessDecisions(decisions);
|
||||
|
||||
_logger.ProgressInfo("Author search completed. {0} reports downloaded.", processed.Grabbed.Count);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ private void SearchForMissingBooks(List<Book> books, bool userInvokedSearch)
|
|||
foreach (var book in books)
|
||||
{
|
||||
List<DownloadDecision> decisions;
|
||||
decisions = _nzbSearchService.AlbumSearch(book.Id, false, userInvokedSearch, false);
|
||||
decisions = _nzbSearchService.BookSearch(book.Id, false, userInvokedSearch, false);
|
||||
var processed = _processDownloadDecisions.ProcessDecisions(decisions);
|
||||
|
||||
downloadedCount += processed.Grabbed.Count;
|
||||
|
|
@ -61,7 +61,7 @@ public void Execute(BookSearchCommand message)
|
|||
foreach (var bookId in message.BookIds)
|
||||
{
|
||||
var decisions =
|
||||
_nzbSearchService.AlbumSearch(bookId, false, message.Trigger == CommandTrigger.Manual, false);
|
||||
_nzbSearchService.BookSearch(bookId, false, message.Trigger == CommandTrigger.Manual, false);
|
||||
var processed = _processDownloadDecisions.ProcessDecisions(decisions);
|
||||
|
||||
_logger.ProgressInfo("Book search completed. {0} reports downloaded.", processed.Grabbed.Count);
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ namespace NzbDrone.Core.IndexerSearch
|
|||
{
|
||||
public interface ISearchForNzb
|
||||
{
|
||||
List<DownloadDecision> AlbumSearch(int bookId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch);
|
||||
List<DownloadDecision> ArtistSearch(int authorId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch);
|
||||
List<DownloadDecision> BookSearch(int bookId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch);
|
||||
List<DownloadDecision> AuthorSearch(int authorId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch);
|
||||
}
|
||||
|
||||
public class NzbSearchService : ISearchForNzb
|
||||
|
|
@ -41,13 +41,13 @@ public NzbSearchService(IIndexerFactory indexerFactory,
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public List<DownloadDecision> AlbumSearch(int bookId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch)
|
||||
public List<DownloadDecision> BookSearch(int bookId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch)
|
||||
{
|
||||
var book = _bookService.GetBook(bookId);
|
||||
return AlbumSearch(book, missingOnly, userInvokedSearch, interactiveSearch);
|
||||
}
|
||||
|
||||
public List<DownloadDecision> ArtistSearch(int authorId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch)
|
||||
public List<DownloadDecision> AuthorSearch(int authorId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch)
|
||||
{
|
||||
var author = _authorService.GetAuthor(authorId);
|
||||
return ArtistSearch(author, missingOnly, userInvokedSearch, interactiveSearch);
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public interface IRenameTrackFileService
|
||||
public interface IRenameBookFileService
|
||||
{
|
||||
List<RenameBookFilePreview> GetRenamePreviews(int authorId);
|
||||
List<RenameBookFilePreview> GetRenamePreviews(int authorId, int bookId);
|
||||
}
|
||||
|
||||
public class RenameBookFileService : IRenameTrackFileService, IExecute<RenameFilesCommand>, IExecute<RenameAuthorCommand>
|
||||
public class RenameBookFileService : IRenameBookFileService, IExecute<RenameFilesCommand>, IExecute<RenameAuthorCommand>
|
||||
{
|
||||
private readonly IAuthorService _authorService;
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
namespace NzbDrone.Core.Validation.Paths
|
||||
{
|
||||
public class ArtistExistsValidator : PropertyValidator
|
||||
public class AuthorExistsValidator : PropertyValidator
|
||||
{
|
||||
private readonly IAuthorService _authorService;
|
||||
|
||||
public ArtistExistsValidator(IAuthorService authorService)
|
||||
public AuthorExistsValidator(IAuthorService authorService)
|
||||
: base("This author has already been added.")
|
||||
{
|
||||
_authorService = authorService;
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using Readarr.Api.V1.Artist;
|
||||
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ArtistEditorFixture : IntegrationTest
|
||||
{
|
||||
private void GivenExistingArtist()
|
||||
{
|
||||
foreach (var name in new[] { "Alien Ant Farm", "Kiss" })
|
||||
{
|
||||
var newArtist = Artist.Lookup(name).First();
|
||||
|
||||
newArtist.QualityProfileId = 1;
|
||||
newArtist.MetadataProfileId = 1;
|
||||
newArtist.Path = string.Format(@"C:\Test\{0}", name).AsOsAgnostic();
|
||||
|
||||
Artist.Post(newArtist);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_update_multiple_artist()
|
||||
{
|
||||
GivenExistingArtist();
|
||||
|
||||
var artist = Artist.All();
|
||||
|
||||
var artistEditor = new ArtistEditorResource
|
||||
{
|
||||
QualityProfileId = 2,
|
||||
AuthorIds = artist.Select(o => o.Id).ToList()
|
||||
};
|
||||
|
||||
var result = Artist.Editor(artistEditor);
|
||||
|
||||
result.Should().HaveCount(2);
|
||||
result.TrueForAll(s => s.QualityProfileId == 2).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ArtistLookupFixture : IntegrationTest
|
||||
{
|
||||
[TestCase("Robert Harris", "Robert Harris")]
|
||||
[TestCase("J.K. Rowling", "J.K. Rowling")]
|
||||
public void lookup_new_artist_by_name(string term, string name)
|
||||
{
|
||||
var artist = Artist.Lookup(term);
|
||||
|
||||
artist.Should().NotBeEmpty();
|
||||
artist.Should().Contain(c => c.ArtistName == name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void lookup_new_artist_by_goodreads_book_id()
|
||||
{
|
||||
var artist = Artist.Lookup("readarr:1");
|
||||
|
||||
artist.Should().NotBeEmpty();
|
||||
artist.Should().Contain(c => c.ArtistName == "J.K. Rowling");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using Readarr.Api.V1.Author;
|
||||
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AuthorEditorFixture : IntegrationTest
|
||||
{
|
||||
private void GivenExistingAuthor()
|
||||
{
|
||||
foreach (var name in new[] { "Alien Ant Farm", "Kiss" })
|
||||
{
|
||||
var newAuthor = Author.Lookup(name).First();
|
||||
|
||||
newAuthor.QualityProfileId = 1;
|
||||
newAuthor.MetadataProfileId = 1;
|
||||
newAuthor.Path = string.Format(@"C:\Test\{0}", name).AsOsAgnostic();
|
||||
|
||||
Author.Post(newAuthor);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_update_multiple_artist()
|
||||
{
|
||||
GivenExistingAuthor();
|
||||
|
||||
var author = Author.All();
|
||||
|
||||
var artistEditor = new AuthorEditorResource
|
||||
{
|
||||
QualityProfileId = 2,
|
||||
AuthorIds = author.Select(o => o.Id).ToList()
|
||||
};
|
||||
|
||||
var result = Author.Editor(artistEditor);
|
||||
|
||||
result.Should().HaveCount(2);
|
||||
result.TrueForAll(s => s.QualityProfileId == 2).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ArtistFixture : IntegrationTest
|
||||
public class AuthorFixture : IntegrationTest
|
||||
{
|
||||
[Test]
|
||||
[Order(0)]
|
||||
|
|
@ -16,15 +16,15 @@ public void add_artist_with_tags_should_store_them()
|
|||
EnsureNoArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "J.K. Rowling");
|
||||
var tag = EnsureTag("abc");
|
||||
|
||||
var artist = Artist.Lookup("readarr:1").Single();
|
||||
var author = Author.Lookup("readarr:1").Single();
|
||||
|
||||
artist.QualityProfileId = 1;
|
||||
artist.MetadataProfileId = 1;
|
||||
artist.Path = Path.Combine(ArtistRootFolder, artist.ArtistName);
|
||||
artist.Tags = new HashSet<int>();
|
||||
artist.Tags.Add(tag.Id);
|
||||
author.QualityProfileId = 1;
|
||||
author.MetadataProfileId = 1;
|
||||
author.Path = Path.Combine(AuthorRootFolder, author.AuthorName);
|
||||
author.Tags = new HashSet<int>();
|
||||
author.Tags.Add(tag.Id);
|
||||
|
||||
var result = Artist.Post(artist);
|
||||
var result = Author.Post(author);
|
||||
|
||||
result.Should().NotBeNull();
|
||||
result.Tags.Should().Equal(tag.Id);
|
||||
|
|
@ -38,11 +38,11 @@ public void add_artist_without_profileid_should_return_badrequest()
|
|||
|
||||
EnsureNoArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "J.K. Rowling");
|
||||
|
||||
var artist = Artist.Lookup("readarr:1").Single();
|
||||
var artist = Author.Lookup("readarr:1").Single();
|
||||
|
||||
artist.Path = Path.Combine(ArtistRootFolder, artist.ArtistName);
|
||||
artist.Path = Path.Combine(AuthorRootFolder, artist.AuthorName);
|
||||
|
||||
Artist.InvalidPost(artist);
|
||||
Author.InvalidPost(artist);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
@ -53,11 +53,11 @@ public void add_artist_without_path_should_return_badrequest()
|
|||
|
||||
EnsureNoArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "J.K. Rowling");
|
||||
|
||||
var artist = Artist.Lookup("readarr:1").Single();
|
||||
var artist = Author.Lookup("readarr:1").Single();
|
||||
|
||||
artist.QualityProfileId = 1;
|
||||
|
||||
Artist.InvalidPost(artist);
|
||||
Author.InvalidPost(artist);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
@ -66,29 +66,29 @@ public void add_artist()
|
|||
{
|
||||
EnsureNoArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "J.K. Rowling");
|
||||
|
||||
var artist = Artist.Lookup("readarr:1").Single();
|
||||
var artist = Author.Lookup("readarr:1").Single();
|
||||
|
||||
artist.QualityProfileId = 1;
|
||||
artist.MetadataProfileId = 1;
|
||||
artist.Path = Path.Combine(ArtistRootFolder, artist.ArtistName);
|
||||
artist.Path = Path.Combine(AuthorRootFolder, artist.AuthorName);
|
||||
|
||||
var result = Artist.Post(artist);
|
||||
var result = Author.Post(artist);
|
||||
|
||||
result.Should().NotBeNull();
|
||||
result.Id.Should().NotBe(0);
|
||||
result.QualityProfileId.Should().Be(1);
|
||||
result.MetadataProfileId.Should().Be(1);
|
||||
result.Path.Should().Be(Path.Combine(ArtistRootFolder, artist.ArtistName));
|
||||
result.Path.Should().Be(Path.Combine(AuthorRootFolder, artist.AuthorName));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Order(2)]
|
||||
public void get_all_artist()
|
||||
{
|
||||
EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
EnsureArtist("amzn1.gr.author.v1.qTrNu9-PIaaBj5gYRDmN4Q", "34497", "Terry Pratchett");
|
||||
EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
EnsureAuthor("amzn1.gr.author.v1.qTrNu9-PIaaBj5gYRDmN4Q", "34497", "Terry Pratchett");
|
||||
|
||||
var artists = Artist.All();
|
||||
var artists = Author.All();
|
||||
|
||||
artists.Should().NotBeNullOrEmpty();
|
||||
artists.Should().Contain(v => v.ForeignAuthorId == "amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ");
|
||||
|
|
@ -99,9 +99,9 @@ public void get_all_artist()
|
|||
[Order(2)]
|
||||
public void get_artist_by_id()
|
||||
{
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
|
||||
var result = Artist.Get(artist.Id);
|
||||
var result = Author.Get(artist.Id);
|
||||
|
||||
result.ForeignAuthorId.Should().Be("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ");
|
||||
}
|
||||
|
|
@ -111,14 +111,14 @@ public void get_artist_by_unknown_id_should_return_404()
|
|||
{
|
||||
IgnoreOnMonoVersions("5.12", "5.14");
|
||||
|
||||
var result = Artist.InvalidGet(1000000);
|
||||
var result = Author.InvalidGet(1000000);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Order(2)]
|
||||
public void update_artist_profile_id()
|
||||
{
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
|
||||
var profileId = 1;
|
||||
if (artist.QualityProfileId == profileId)
|
||||
|
|
@ -128,16 +128,16 @@ public void update_artist_profile_id()
|
|||
|
||||
artist.QualityProfileId = profileId;
|
||||
|
||||
var result = Artist.Put(artist);
|
||||
var result = Author.Put(artist);
|
||||
|
||||
Artist.Get(artist.Id).QualityProfileId.Should().Be(profileId);
|
||||
Author.Get(artist.Id).QualityProfileId.Should().Be(profileId);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Order(3)]
|
||||
public void update_artist_monitored()
|
||||
{
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
|
||||
artist.Monitored.Should().BeFalse();
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ public void update_artist_monitored()
|
|||
//{
|
||||
// season.Monitored = true;
|
||||
//});
|
||||
var result = Artist.Put(artist);
|
||||
var result = Author.Put(artist);
|
||||
|
||||
result.Monitored.Should().BeTrue();
|
||||
|
||||
|
|
@ -159,22 +159,22 @@ public void update_artist_monitored()
|
|||
[Order(3)]
|
||||
public void update_artist_tags()
|
||||
{
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
var tag = EnsureTag("abc");
|
||||
|
||||
if (artist.Tags.Contains(tag.Id))
|
||||
{
|
||||
artist.Tags.Remove(tag.Id);
|
||||
|
||||
var result = Artist.Put(artist);
|
||||
Artist.Get(artist.Id).Tags.Should().NotContain(tag.Id);
|
||||
var result = Author.Put(artist);
|
||||
Author.Get(artist.Id).Tags.Should().NotContain(tag.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
artist.Tags.Add(tag.Id);
|
||||
|
||||
var result = Artist.Put(artist);
|
||||
Artist.Get(artist.Id).Tags.Should().Contain(tag.Id);
|
||||
var result = Author.Put(artist);
|
||||
Author.Get(artist.Id).Tags.Should().Contain(tag.Id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -182,13 +182,13 @@ public void update_artist_tags()
|
|||
[Order(4)]
|
||||
public void delete_artist()
|
||||
{
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
|
||||
Artist.Get(artist.Id).Should().NotBeNull();
|
||||
Author.Get(artist.Id).Should().NotBeNull();
|
||||
|
||||
Artist.Delete(artist.Id);
|
||||
Author.Delete(artist.Id);
|
||||
|
||||
Artist.All().Should().NotContain(v => v.ForeignAuthorId == "amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ");
|
||||
Author.All().Should().NotContain(v => v.ForeignAuthorId == "amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AuthorLookupFixture : IntegrationTest
|
||||
{
|
||||
[TestCase("Robert Harris", "Robert Harris")]
|
||||
[TestCase("J.K. Rowling", "J.K. Rowling")]
|
||||
public void lookup_new_author_by_name(string term, string name)
|
||||
{
|
||||
var author = Author.Lookup(term);
|
||||
|
||||
author.Should().NotBeEmpty();
|
||||
author.Should().Contain(c => c.AuthorName == name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void lookup_new_author_by_goodreads_book_id()
|
||||
{
|
||||
var author = Author.Lookup("readarr:1");
|
||||
|
||||
author.Should().NotBeEmpty();
|
||||
author.Should().Contain(c => c.AuthorName == "J.K. Rowling");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Blacklist;
|
||||
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
|
|
@ -8,13 +8,13 @@ namespace NzbDrone.Integration.Test.ApiTests
|
|||
[TestFixture]
|
||||
public class BlacklistFixture : IntegrationTest
|
||||
{
|
||||
private ArtistResource _artist;
|
||||
private AuthorResource _artist;
|
||||
|
||||
[Test]
|
||||
[Ignore("Adding to blacklist not supported")]
|
||||
public void should_be_able_to_add_to_blacklist()
|
||||
{
|
||||
_artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
_artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling");
|
||||
|
||||
Blacklist.Post(new BlacklistResource
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
using NUnit.Framework;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TrackFileFixture : IntegrationTest
|
||||
public class BookFileFixture : IntegrationTest
|
||||
{
|
||||
[Test]
|
||||
public void get_all_trackfiles()
|
||||
public void get_all_bookfiles()
|
||||
{
|
||||
Assert.Ignore("TODO");
|
||||
}
|
||||
|
|
@ -4,31 +4,31 @@
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Integration.Test.Client;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Books;
|
||||
|
||||
namespace NzbDrone.Integration.Test.ApiTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class CalendarFixture : IntegrationTest
|
||||
{
|
||||
public ClientBase<AlbumResource> Calendar;
|
||||
public ClientBase<BookResource> Calendar;
|
||||
|
||||
protected override void InitRestClients()
|
||||
{
|
||||
base.InitRestClients();
|
||||
|
||||
Calendar = new ClientBase<AlbumResource>(RestClient, ApiKey, "calendar");
|
||||
Calendar = new ClientBase<BookResource>(RestClient, ApiKey, "calendar");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_get_albums()
|
||||
{
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
|
||||
var request = Calendar.BuildRequest();
|
||||
request.AddParameter("start", new DateTime(2003, 06, 20).ToString("s") + "Z");
|
||||
request.AddParameter("end", new DateTime(2003, 06, 22).ToString("s") + "Z");
|
||||
var items = Calendar.Get<List<AlbumResource>>(request);
|
||||
var items = Calendar.Get<List<BookResource>>(request);
|
||||
|
||||
items = items.Where(v => v.AuthorId == artist.Id).ToList();
|
||||
|
||||
|
|
@ -39,13 +39,13 @@ public void should_be_able_to_get_albums()
|
|||
[Test]
|
||||
public void should_not_be_able_to_get_unmonitored_albums()
|
||||
{
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
|
||||
var request = Calendar.BuildRequest();
|
||||
request.AddParameter("start", new DateTime(2003, 06, 20).ToString("s") + "Z");
|
||||
request.AddParameter("end", new DateTime(2003, 06, 22).ToString("s") + "Z");
|
||||
request.AddParameter("unmonitored", "false");
|
||||
var items = Calendar.Get<List<AlbumResource>>(request);
|
||||
var items = Calendar.Get<List<BookResource>>(request);
|
||||
|
||||
items = items.Where(v => v.AuthorId == artist.Id).ToList();
|
||||
|
||||
|
|
@ -55,13 +55,13 @@ public void should_not_be_able_to_get_unmonitored_albums()
|
|||
[Test]
|
||||
public void should_be_able_to_get_unmonitored_albums()
|
||||
{
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
|
||||
var request = Calendar.BuildRequest();
|
||||
request.AddParameter("start", new DateTime(2003, 06, 20).ToString("s") + "Z");
|
||||
request.AddParameter("end", new DateTime(2003, 06, 22).ToString("s") + "Z");
|
||||
request.AddParameter("unmonitored", "true");
|
||||
var items = Calendar.Get<List<AlbumResource>>(request);
|
||||
var items = Calendar.Get<List<BookResource>>(request);
|
||||
|
||||
items = items.Where(v => v.AuthorId == artist.Id).ToList();
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ private bool BeValidRelease(ReleaseResource releaseResource)
|
|||
releaseResource.Age.Should().BeGreaterOrEqualTo(-1);
|
||||
releaseResource.Title.Should().NotBeNullOrWhiteSpace();
|
||||
releaseResource.DownloadUrl.Should().NotBeNullOrWhiteSpace();
|
||||
releaseResource.ArtistName.Should().NotBeNullOrWhiteSpace();
|
||||
releaseResource.AuthorName.Should().NotBeNullOrWhiteSpace();
|
||||
|
||||
//TODO: uncomment these after moving to restsharp for rss
|
||||
//releaseResource.NzbInfoUrl.Should().NotBeNullOrWhiteSpace();
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public void Setup()
|
|||
RootFolders.Post(new RootFolderResource
|
||||
{
|
||||
Name = "TestLibrary",
|
||||
Path = ArtistRootFolder,
|
||||
Path = AuthorRootFolder,
|
||||
DefaultMetadataProfileId = 1,
|
||||
DefaultQualityProfileId = 1,
|
||||
DefaultMonitorOption = MonitorTypes.All
|
||||
|
|
@ -39,7 +39,7 @@ public void missing_should_be_empty()
|
|||
[Order(1)]
|
||||
public void missing_should_have_monitored_items()
|
||||
{
|
||||
EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
|
||||
var result = WantedMissing.GetPaged(0, 15, "releaseDate", "desc");
|
||||
|
||||
|
|
@ -50,12 +50,12 @@ public void missing_should_have_monitored_items()
|
|||
[Order(1)]
|
||||
public void missing_should_have_artist()
|
||||
{
|
||||
EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
|
||||
var result = WantedMissing.GetPaged(0, 15, "releaseDate", "desc");
|
||||
|
||||
result.Records.First().Artist.Should().NotBeNull();
|
||||
result.Records.First().Artist.ArtistName.Should().Be("J.K. Rowling");
|
||||
result.Records.First().Author.Should().NotBeNull();
|
||||
result.Records.First().Author.AuthorName.Should().Be("J.K. Rowling");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
@ -63,8 +63,8 @@ public void missing_should_have_artist()
|
|||
public void cutoff_should_have_monitored_items()
|
||||
{
|
||||
EnsureProfileCutoff(1, Quality.AZW3);
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
EnsureTrackFile(artist, 1, Quality.MOBI);
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
EnsureBookFile(artist, 1, Quality.MOBI);
|
||||
|
||||
var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc");
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ public void cutoff_should_have_monitored_items()
|
|||
[Order(1)]
|
||||
public void missing_should_not_have_unmonitored_items()
|
||||
{
|
||||
EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
|
||||
var result = WantedMissing.GetPaged(0, 15, "releaseDate", "desc");
|
||||
|
||||
|
|
@ -87,8 +87,8 @@ public void missing_should_not_have_unmonitored_items()
|
|||
public void cutoff_should_not_have_unmonitored_items()
|
||||
{
|
||||
EnsureProfileCutoff(1, Quality.AZW3);
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
EnsureTrackFile(artist, 1, Quality.MOBI);
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
EnsureBookFile(artist, 1, Quality.MOBI);
|
||||
|
||||
var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc");
|
||||
|
||||
|
|
@ -100,20 +100,20 @@ public void cutoff_should_not_have_unmonitored_items()
|
|||
public void cutoff_should_have_artist()
|
||||
{
|
||||
EnsureProfileCutoff(1, Quality.AZW3);
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
EnsureTrackFile(artist, 1, Quality.MOBI);
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", true);
|
||||
EnsureBookFile(artist, 1, Quality.MOBI);
|
||||
|
||||
var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc");
|
||||
|
||||
result.Records.First().Artist.Should().NotBeNull();
|
||||
result.Records.First().Artist.ArtistName.Should().Be("J.K. Rowling");
|
||||
result.Records.First().Author.Should().NotBeNull();
|
||||
result.Records.First().Author.AuthorName.Should().Be("J.K. Rowling");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Order(2)]
|
||||
public void missing_should_have_unmonitored_items()
|
||||
{
|
||||
EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
|
||||
var result = WantedMissing.GetPaged(0, 15, "releaseDate", "desc", "monitored", "false");
|
||||
|
||||
|
|
@ -125,8 +125,8 @@ public void missing_should_have_unmonitored_items()
|
|||
public void cutoff_should_have_unmonitored_items()
|
||||
{
|
||||
EnsureProfileCutoff(1, Quality.AZW3);
|
||||
var artist = EnsureArtist("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
EnsureTrackFile(artist, 1, Quality.MOBI);
|
||||
var artist = EnsureAuthor("amzn1.gr.author.v1.SHA8asP5mFyLIP9NlujvLQ", "1", "J.K. Rowling", false);
|
||||
EnsureBookFile(artist, 1, Quality.MOBI);
|
||||
|
||||
var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc", "monitored", "false");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using RestSharp;
|
||||
|
||||
namespace NzbDrone.Integration.Test.Client
|
||||
{
|
||||
public class AlbumClient : ClientBase<AlbumResource>
|
||||
{
|
||||
public AlbumClient(IRestClient restClient, string apiKey)
|
||||
: base(restClient, apiKey, "album")
|
||||
{
|
||||
}
|
||||
|
||||
public List<AlbumResource> GetAlbumsInArtist(int authorId)
|
||||
{
|
||||
var request = BuildRequest("?authorId=" + authorId.ToString());
|
||||
return Get<List<AlbumResource>>(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +1,39 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using RestSharp;
|
||||
|
||||
namespace NzbDrone.Integration.Test.Client
|
||||
{
|
||||
public class ArtistClient : ClientBase<ArtistResource>
|
||||
public class AuthorClient : ClientBase<AuthorResource>
|
||||
{
|
||||
public ArtistClient(IRestClient restClient, string apiKey)
|
||||
public AuthorClient(IRestClient restClient, string apiKey)
|
||||
: base(restClient, apiKey)
|
||||
{
|
||||
}
|
||||
|
||||
public List<ArtistResource> Lookup(string term)
|
||||
public List<AuthorResource> Lookup(string term)
|
||||
{
|
||||
var request = BuildRequest("lookup");
|
||||
request.AddQueryParameter("term", term);
|
||||
return Get<List<ArtistResource>>(request);
|
||||
return Get<List<AuthorResource>>(request);
|
||||
}
|
||||
|
||||
public List<ArtistResource> Editor(ArtistEditorResource artist)
|
||||
public List<AuthorResource> Editor(AuthorEditorResource artist)
|
||||
{
|
||||
var request = BuildRequest("editor");
|
||||
request.AddJsonBody(artist);
|
||||
return Put<List<ArtistResource>>(request);
|
||||
return Put<List<AuthorResource>>(request);
|
||||
}
|
||||
|
||||
public ArtistResource Get(string slug, HttpStatusCode statusCode = HttpStatusCode.OK)
|
||||
public AuthorResource Get(string slug, HttpStatusCode statusCode = HttpStatusCode.OK)
|
||||
{
|
||||
var request = BuildRequest(slug);
|
||||
return Get<ArtistResource>(request, statusCode);
|
||||
return Get<AuthorResource>(request, statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public class SystemInfoClient : ClientBase<ArtistResource>
|
||||
public class SystemInfoClient : ClientBase<AuthorResource>
|
||||
{
|
||||
public SystemInfoClient(IRestClient restClient, string apiKey)
|
||||
: base(restClient, apiKey)
|
||||
20
src/NzbDrone.Integration.Test/Client/BookClient.cs
Normal file
20
src/NzbDrone.Integration.Test/Client/BookClient.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using System.Collections.Generic;
|
||||
using Readarr.Api.V1.Books;
|
||||
using RestSharp;
|
||||
|
||||
namespace NzbDrone.Integration.Test.Client
|
||||
{
|
||||
public class BookClient : ClientBase<BookResource>
|
||||
{
|
||||
public BookClient(IRestClient restClient, string apiKey)
|
||||
: base(restClient, apiKey, "book")
|
||||
{
|
||||
}
|
||||
|
||||
public List<BookResource> GetBooksInAuthor(int authorId)
|
||||
{
|
||||
var request = BuildRequest("?authorId=" + authorId.ToString());
|
||||
return Get<List<BookResource>>(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ namespace NzbDrone.Integration.Test
|
|||
[TestFixture]
|
||||
public class CorsFixture : IntegrationTest
|
||||
{
|
||||
private RestRequest BuildGet(string route = "artist")
|
||||
private RestRequest BuildGet(string route = "author")
|
||||
{
|
||||
var request = new RestRequest(route, Method.GET);
|
||||
request.AddHeader(AccessControlHeaders.RequestMethod, "POST");
|
||||
|
|
@ -16,7 +16,7 @@ private RestRequest BuildGet(string route = "artist")
|
|||
return request;
|
||||
}
|
||||
|
||||
private RestRequest BuildOptions(string route = "artist")
|
||||
private RestRequest BuildOptions(string route = "author")
|
||||
{
|
||||
var request = new RestRequest(route, Method.OPTIONS);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,20 +17,20 @@ public void should_log_on_error()
|
|||
config.LogLevel = "Trace";
|
||||
HostConfig.Put(config);
|
||||
|
||||
var resultGet = Artist.All();
|
||||
var resultGet = Author.All();
|
||||
|
||||
var logFile = "Readarr.trace.txt";
|
||||
var logLines = Logs.GetLogFileLines(logFile);
|
||||
|
||||
var result = Artist.InvalidPost(new Readarr.Api.V1.Artist.ArtistResource());
|
||||
var result = Author.InvalidPost(new Readarr.Api.V1.Author.AuthorResource());
|
||||
|
||||
// Skip 2 and 1 to ignore the logs endpoint
|
||||
logLines = Logs.GetLogFileLines(logFile).Skip(logLines.Length + 2).ToArray();
|
||||
Array.Resize(ref logLines, logLines.Length - 1);
|
||||
|
||||
logLines.Should().Contain(v => v.Contains("|Trace|Http|Req") && v.Contains("/api/v1/artist/"));
|
||||
logLines.Should().Contain(v => v.Contains("|Trace|Http|Res") && v.Contains("/api/v1/artist/: 400.BadRequest"));
|
||||
logLines.Should().Contain(v => v.Contains("|Debug|Api|") && v.Contains("/api/v1/artist/: 400.BadRequest"));
|
||||
logLines.Should().Contain(v => v.Contains("|Trace|Http|Req") && v.Contains("/api/v1/author/"));
|
||||
logLines.Should().Contain(v => v.Contains("|Trace|Http|Res") && v.Contains("/api/v1/author/: 400.BadRequest"));
|
||||
logLines.Should().Contain(v => v.Contains("|Debug|Api|") && v.Contains("/api/v1/author/: 400.BadRequest"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ public abstract class IntegrationTest : IntegrationTestBase
|
|||
{
|
||||
protected NzbDroneRunner _runner;
|
||||
|
||||
public override string ArtistRootFolder => GetTempDirectory("ArtistRootFolder");
|
||||
public override string AuthorRootFolder => GetTempDirectory("AuthorRootFolder");
|
||||
|
||||
protected override string RootUrl => "http://localhost:8787/";
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
using NzbDrone.SignalR;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Test.Common.Categories;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Blacklist;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Api.V1.Config;
|
||||
using Readarr.Api.V1.DownloadClient;
|
||||
using Readarr.Api.V1.History;
|
||||
|
|
@ -38,7 +38,7 @@ public abstract class IntegrationTestBase
|
|||
public ClientBase<BlacklistResource> Blacklist;
|
||||
public CommandClient Commands;
|
||||
public DownloadClientClient DownloadClients;
|
||||
public AlbumClient Albums;
|
||||
public BookClient Books;
|
||||
public ClientBase<HistoryResource> History;
|
||||
public ClientBase<HostConfigResource> HostConfig;
|
||||
public IndexerClient Indexers;
|
||||
|
|
@ -49,10 +49,10 @@ public abstract class IntegrationTestBase
|
|||
public ReleaseClient Releases;
|
||||
public ReleasePushClient ReleasePush;
|
||||
public ClientBase<RootFolderResource> RootFolders;
|
||||
public ArtistClient Artist;
|
||||
public AuthorClient Author;
|
||||
public ClientBase<TagResource> Tags;
|
||||
public ClientBase<AlbumResource> WantedMissing;
|
||||
public ClientBase<AlbumResource> WantedCutoffUnmet;
|
||||
public ClientBase<BookResource> WantedMissing;
|
||||
public ClientBase<BookResource> WantedCutoffUnmet;
|
||||
|
||||
private List<SignalRMessage> _signalRReceived;
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ public IntegrationTestBase()
|
|||
|
||||
public string TempDirectory { get; private set; }
|
||||
|
||||
public abstract string ArtistRootFolder { get; }
|
||||
public abstract string AuthorRootFolder { get; }
|
||||
|
||||
protected abstract string RootUrl { get; }
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ protected virtual void InitRestClients()
|
|||
Blacklist = new ClientBase<BlacklistResource>(RestClient, ApiKey);
|
||||
Commands = new CommandClient(RestClient, ApiKey);
|
||||
DownloadClients = new DownloadClientClient(RestClient, ApiKey);
|
||||
Albums = new AlbumClient(RestClient, ApiKey);
|
||||
Books = new BookClient(RestClient, ApiKey);
|
||||
History = new ClientBase<HistoryResource>(RestClient, ApiKey);
|
||||
HostConfig = new ClientBase<HostConfigResource>(RestClient, ApiKey, "config/host");
|
||||
Indexers = new IndexerClient(RestClient, ApiKey);
|
||||
|
|
@ -112,10 +112,10 @@ protected virtual void InitRestClients()
|
|||
Releases = new ReleaseClient(RestClient, ApiKey);
|
||||
ReleasePush = new ReleasePushClient(RestClient, ApiKey);
|
||||
RootFolders = new ClientBase<RootFolderResource>(RestClient, ApiKey);
|
||||
Artist = new ArtistClient(RestClient, ApiKey);
|
||||
Author = new AuthorClient(RestClient, ApiKey);
|
||||
Tags = new ClientBase<TagResource>(RestClient, ApiKey);
|
||||
WantedMissing = new ClientBase<AlbumResource>(RestClient, ApiKey, "wanted/missing");
|
||||
WantedCutoffUnmet = new ClientBase<AlbumResource>(RestClient, ApiKey, "wanted/cutoff");
|
||||
WantedMissing = new ClientBase<BookResource>(RestClient, ApiKey, "wanted/missing");
|
||||
WantedCutoffUnmet = new ClientBase<BookResource>(RestClient, ApiKey, "wanted/cutoff");
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
|
|
@ -249,33 +249,33 @@ public static void WaitForCompletion(Func<bool> predicate, int timeout = 10000,
|
|||
Assert.Fail("Timed on wait");
|
||||
}
|
||||
|
||||
public ArtistResource EnsureArtist(string authorId, string goodreadsBookId, string artistName, bool? monitored = null)
|
||||
public AuthorResource EnsureAuthor(string authorId, string goodreadsBookId, string authorName, bool? monitored = null)
|
||||
{
|
||||
var result = Artist.All().FirstOrDefault(v => v.ForeignAuthorId == authorId);
|
||||
var result = Author.All().FirstOrDefault(v => v.ForeignAuthorId == authorId);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
var lookup = Artist.Lookup("readarr:" + goodreadsBookId);
|
||||
var artist = lookup.First();
|
||||
artist.QualityProfileId = 1;
|
||||
artist.MetadataProfileId = 1;
|
||||
artist.Path = Path.Combine(ArtistRootFolder, artist.ArtistName);
|
||||
artist.Monitored = true;
|
||||
artist.AddOptions = new Core.Books.AddAuthorOptions();
|
||||
Directory.CreateDirectory(artist.Path);
|
||||
var lookup = Author.Lookup("readarr:" + goodreadsBookId);
|
||||
var author = lookup.First();
|
||||
author.QualityProfileId = 1;
|
||||
author.MetadataProfileId = 1;
|
||||
author.Path = Path.Combine(AuthorRootFolder, author.AuthorName);
|
||||
author.Monitored = true;
|
||||
author.AddOptions = new Core.Books.AddAuthorOptions();
|
||||
Directory.CreateDirectory(author.Path);
|
||||
|
||||
result = Artist.Post(artist);
|
||||
result = Author.Post(author);
|
||||
Commands.WaitAll();
|
||||
WaitForCompletion(() => Albums.GetAlbumsInArtist(result.Id).Count > 0);
|
||||
WaitForCompletion(() => Books.GetBooksInAuthor(result.Id).Count > 0);
|
||||
}
|
||||
|
||||
var changed = false;
|
||||
|
||||
if (result.RootFolderPath != ArtistRootFolder)
|
||||
if (result.RootFolderPath != AuthorRootFolder)
|
||||
{
|
||||
changed = true;
|
||||
result.RootFolderPath = ArtistRootFolder;
|
||||
result.Path = Path.Combine(ArtistRootFolder, result.ArtistName);
|
||||
result.RootFolderPath = AuthorRootFolder;
|
||||
result.Path = Path.Combine(AuthorRootFolder, result.AuthorName);
|
||||
}
|
||||
|
||||
if (monitored.HasValue)
|
||||
|
|
@ -289,7 +289,7 @@ public ArtistResource EnsureArtist(string authorId, string goodreadsBookId, stri
|
|||
|
||||
if (changed)
|
||||
{
|
||||
Artist.Put(result);
|
||||
Author.Put(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -297,22 +297,22 @@ public ArtistResource EnsureArtist(string authorId, string goodreadsBookId, stri
|
|||
|
||||
public void EnsureNoArtist(string readarrId, string artistTitle)
|
||||
{
|
||||
var result = Artist.All().FirstOrDefault(v => v.ForeignAuthorId == readarrId);
|
||||
var result = Author.All().FirstOrDefault(v => v.ForeignAuthorId == readarrId);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
Artist.Delete(result.Id);
|
||||
Author.Delete(result.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public void EnsureTrackFile(ArtistResource artist, int bookId, Quality quality)
|
||||
public void EnsureBookFile(AuthorResource artist, int bookId, Quality quality)
|
||||
{
|
||||
var result = Albums.GetAlbumsInArtist(artist.Id).Single(v => v.Id == bookId);
|
||||
var result = Books.GetBooksInAuthor(artist.Id).Single(v => v.Id == bookId);
|
||||
|
||||
// if (result.BookFile == null)
|
||||
if (true)
|
||||
{
|
||||
var path = Path.Combine(ArtistRootFolder, artist.ArtistName, "Track.mp3");
|
||||
var path = Path.Combine(AuthorRootFolder, artist.AuthorName, "Track.mp3");
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
File.WriteAllText(path, "Fake Track");
|
||||
|
|
@ -332,7 +332,7 @@ public void EnsureTrackFile(ArtistResource artist, int bookId, Quality quality)
|
|||
});
|
||||
Commands.WaitAll();
|
||||
|
||||
var track = Albums.GetAlbumsInArtist(artist.Id).Single(x => x.Id == bookId);
|
||||
var track = Books.GetBooksInAuthor(artist.Id).Single(x => x.Id == bookId);
|
||||
|
||||
// track.BookFileId.Should().NotBe(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using Readarr.Api.V1.Albums;
|
||||
|
||||
namespace Readarr.Api.V1.AlbumStudio
|
||||
{
|
||||
public class AlbumStudioArtistResource
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public bool? Monitored { get; set; }
|
||||
public List<AlbumResource> Albums { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Core.Books;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.AlbumStudio
|
||||
{
|
||||
public class AlbumStudioModule : ReadarrV1Module
|
||||
{
|
||||
private readonly IAuthorService _authorService;
|
||||
private readonly IBookMonitoredService _albumMonitoredService;
|
||||
|
||||
public AlbumStudioModule(IAuthorService authorService, IBookMonitoredService albumMonitoredService)
|
||||
: base("/albumstudio")
|
||||
{
|
||||
_authorService = authorService;
|
||||
_albumMonitoredService = albumMonitoredService;
|
||||
Post("/", artist => UpdateAll());
|
||||
}
|
||||
|
||||
private object UpdateAll()
|
||||
{
|
||||
//Read from request
|
||||
var request = Request.Body.FromJson<AlbumStudioResource>();
|
||||
var artistToUpdate = _authorService.GetAuthors(request.Artist.Select(s => s.Id));
|
||||
|
||||
foreach (var s in request.Artist)
|
||||
{
|
||||
var artist = artistToUpdate.Single(c => c.Id == s.Id);
|
||||
|
||||
if (s.Monitored.HasValue)
|
||||
{
|
||||
artist.Monitored = s.Monitored.Value;
|
||||
}
|
||||
|
||||
if (request.MonitoringOptions != null && request.MonitoringOptions.Monitor == MonitorTypes.None)
|
||||
{
|
||||
artist.Monitored = false;
|
||||
}
|
||||
|
||||
_albumMonitoredService.SetBookMonitoredStatus(artist, request.MonitoringOptions);
|
||||
}
|
||||
|
||||
return ResponseWithCode("ok", HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.AuthorStats;
|
||||
using NzbDrone.Core.Books;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.SignalR;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Http;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
{
|
||||
public abstract class AlbumModuleWithSignalR : ReadarrRestModuleWithSignalR<AlbumResource, Book>
|
||||
{
|
||||
protected readonly IBookService _bookService;
|
||||
protected readonly IAuthorStatisticsService _artistStatisticsService;
|
||||
protected readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
||||
protected readonly IMapCoversToLocal _coverMapper;
|
||||
|
||||
protected AlbumModuleWithSignalR(IBookService bookService,
|
||||
IAuthorStatisticsService artistStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_bookService = bookService;
|
||||
_artistStatisticsService = artistStatisticsService;
|
||||
_coverMapper = coverMapper;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
|
||||
GetResourceById = GetAlbum;
|
||||
}
|
||||
|
||||
protected AlbumModuleWithSignalR(IBookService bookService,
|
||||
IAuthorStatisticsService artistStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster,
|
||||
string resource)
|
||||
: base(signalRBroadcaster, resource)
|
||||
{
|
||||
_bookService = bookService;
|
||||
_artistStatisticsService = artistStatisticsService;
|
||||
_coverMapper = coverMapper;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
|
||||
GetResourceById = GetAlbum;
|
||||
}
|
||||
|
||||
protected AlbumResource GetAlbum(int id)
|
||||
{
|
||||
var album = _bookService.GetBook(id);
|
||||
var resource = MapToResource(album, true);
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected AlbumResource MapToResource(Book album, bool includeArtist)
|
||||
{
|
||||
var resource = album.ToResource();
|
||||
|
||||
if (includeArtist)
|
||||
{
|
||||
var artist = album.Author.Value;
|
||||
|
||||
resource.Artist = artist.ToResource();
|
||||
}
|
||||
|
||||
FetchAndLinkAlbumStatistics(resource);
|
||||
MapCoversToLocal(resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected List<AlbumResource> MapToResource(List<Book> albums, bool includeArtist)
|
||||
{
|
||||
var result = albums.ToResource();
|
||||
|
||||
if (includeArtist)
|
||||
{
|
||||
var artistDict = new Dictionary<int, NzbDrone.Core.Books.Author>();
|
||||
for (var i = 0; i < albums.Count; i++)
|
||||
{
|
||||
var album = albums[i];
|
||||
var resource = result[i];
|
||||
var artist = artistDict.GetValueOrDefault(albums[i].AuthorMetadataId) ?? album.Author?.Value;
|
||||
artistDict[artist.AuthorMetadataId] = artist;
|
||||
|
||||
resource.Artist = artist.ToResource();
|
||||
}
|
||||
}
|
||||
|
||||
var artistStats = _artistStatisticsService.AuthorStatistics();
|
||||
LinkArtistStatistics(result, artistStats);
|
||||
MapCoversToLocal(result.ToArray());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void FetchAndLinkAlbumStatistics(AlbumResource resource)
|
||||
{
|
||||
LinkArtistStatistics(resource, _artistStatisticsService.AuthorStatistics(resource.AuthorId));
|
||||
}
|
||||
|
||||
private void LinkArtistStatistics(List<AlbumResource> resources, List<AuthorStatistics> artistStatistics)
|
||||
{
|
||||
foreach (var album in resources)
|
||||
{
|
||||
var stats = artistStatistics.SingleOrDefault(ss => ss.AuthorId == album.AuthorId);
|
||||
LinkArtistStatistics(album, stats);
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkArtistStatistics(AlbumResource resource, AuthorStatistics artistStatistics)
|
||||
{
|
||||
if (artistStatistics?.BookStatistics != null)
|
||||
{
|
||||
var dictAlbumStats = artistStatistics.BookStatistics.ToDictionary(v => v.BookId);
|
||||
|
||||
resource.Statistics = dictAlbumStats.GetValueOrDefault(resource.Id).ToResource();
|
||||
}
|
||||
}
|
||||
|
||||
private void MapCoversToLocal(params AlbumResource[] albums)
|
||||
{
|
||||
foreach (var albumResource in albums)
|
||||
{
|
||||
_coverMapper.ConvertToLocalUrls(albumResource.Id, MediaCoverEntity.Book, albumResource.Images);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
using NzbDrone.Core.AuthorStats;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
{
|
||||
public class AlbumStatisticsResource
|
||||
{
|
||||
public int TrackFileCount { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public int TotalTrackCount { get; set; }
|
||||
public long SizeOnDisk { get; set; }
|
||||
|
||||
public decimal PercentOfTracks
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TrackCount == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return TrackFileCount / (decimal)TrackCount * 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class AlbumStatisticsResourceMapper
|
||||
{
|
||||
public static AlbumStatisticsResource ToResource(this BookStatistics model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AlbumStatisticsResource
|
||||
{
|
||||
TrackFileCount = model.BookFileCount,
|
||||
TrackCount = model.BookCount,
|
||||
SizeOnDisk = model.SizeOnDisk
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
namespace Readarr.Api.V1.Artist
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class AlternateTitleResource
|
||||
{
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Readarr.Api.V1.Artist
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class ArtistEditorDeleteResource
|
||||
public class AuthorEditorDeleteResource
|
||||
{
|
||||
public List<int> AuthorIds { get; set; }
|
||||
public bool DeleteFiles { get; set; }
|
||||
|
|
@ -7,52 +7,52 @@
|
|||
using NzbDrone.Core.Messaging.Commands;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Artist
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class ArtistEditorModule : ReadarrV1Module
|
||||
public class AuthorEditorModule : ReadarrV1Module
|
||||
{
|
||||
private readonly IAuthorService _authorService;
|
||||
private readonly IManageCommandQueue _commandQueueManager;
|
||||
|
||||
public ArtistEditorModule(IAuthorService authorService, IManageCommandQueue commandQueueManager)
|
||||
: base("/artist/editor")
|
||||
public AuthorEditorModule(IAuthorService authorService, IManageCommandQueue commandQueueManager)
|
||||
: base("/author/editor")
|
||||
{
|
||||
_authorService = authorService;
|
||||
_commandQueueManager = commandQueueManager;
|
||||
Put("/", artist => SaveAll());
|
||||
Delete("/", artist => DeleteArtist());
|
||||
Put("/", author => SaveAll());
|
||||
Delete("/", author => DeleteAuthor());
|
||||
}
|
||||
|
||||
private object SaveAll()
|
||||
{
|
||||
var resource = Request.Body.FromJson<ArtistEditorResource>();
|
||||
var artistToUpdate = _authorService.GetAuthors(resource.AuthorIds);
|
||||
var artistToMove = new List<BulkMoveAuthor>();
|
||||
var resource = Request.Body.FromJson<AuthorEditorResource>();
|
||||
var authorsToUpdate = _authorService.GetAuthors(resource.AuthorIds);
|
||||
var authorsToMove = new List<BulkMoveAuthor>();
|
||||
|
||||
foreach (var artist in artistToUpdate)
|
||||
foreach (var author in authorsToUpdate)
|
||||
{
|
||||
if (resource.Monitored.HasValue)
|
||||
{
|
||||
artist.Monitored = resource.Monitored.Value;
|
||||
author.Monitored = resource.Monitored.Value;
|
||||
}
|
||||
|
||||
if (resource.QualityProfileId.HasValue)
|
||||
{
|
||||
artist.QualityProfileId = resource.QualityProfileId.Value;
|
||||
author.QualityProfileId = resource.QualityProfileId.Value;
|
||||
}
|
||||
|
||||
if (resource.MetadataProfileId.HasValue)
|
||||
{
|
||||
artist.MetadataProfileId = resource.MetadataProfileId.Value;
|
||||
author.MetadataProfileId = resource.MetadataProfileId.Value;
|
||||
}
|
||||
|
||||
if (resource.RootFolderPath.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
artist.RootFolderPath = resource.RootFolderPath;
|
||||
artistToMove.Add(new BulkMoveAuthor
|
||||
author.RootFolderPath = resource.RootFolderPath;
|
||||
authorsToMove.Add(new BulkMoveAuthor
|
||||
{
|
||||
AuthorId = artist.Id,
|
||||
SourcePath = artist.Path
|
||||
AuthorId = author.Id,
|
||||
SourcePath = author.Path
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -64,35 +64,35 @@ private object SaveAll()
|
|||
switch (applyTags)
|
||||
{
|
||||
case ApplyTags.Add:
|
||||
newTags.ForEach(t => artist.Tags.Add(t));
|
||||
newTags.ForEach(t => author.Tags.Add(t));
|
||||
break;
|
||||
case ApplyTags.Remove:
|
||||
newTags.ForEach(t => artist.Tags.Remove(t));
|
||||
newTags.ForEach(t => author.Tags.Remove(t));
|
||||
break;
|
||||
case ApplyTags.Replace:
|
||||
artist.Tags = new HashSet<int>(newTags);
|
||||
author.Tags = new HashSet<int>(newTags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource.MoveFiles && artistToMove.Any())
|
||||
if (resource.MoveFiles && authorsToMove.Any())
|
||||
{
|
||||
_commandQueueManager.Push(new BulkMoveAuthorCommand
|
||||
{
|
||||
DestinationRootFolder = resource.RootFolderPath,
|
||||
Author = artistToMove
|
||||
Author = authorsToMove
|
||||
});
|
||||
}
|
||||
|
||||
return ResponseWithCode(_authorService.UpdateAuthors(artistToUpdate, !resource.MoveFiles)
|
||||
return ResponseWithCode(_authorService.UpdateAuthors(authorsToUpdate, !resource.MoveFiles)
|
||||
.ToResource(),
|
||||
HttpStatusCode.Accepted);
|
||||
}
|
||||
|
||||
private object DeleteArtist()
|
||||
private object DeleteAuthor()
|
||||
{
|
||||
var resource = Request.Body.FromJson<ArtistEditorResource>();
|
||||
var resource = Request.Body.FromJson<AuthorEditorResource>();
|
||||
|
||||
foreach (var authorId in resource.AuthorIds)
|
||||
{
|
||||
|
|
@ -1,14 +1,13 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Readarr.Api.V1.Artist
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class ArtistEditorResource
|
||||
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 bool? AlbumFolder { get; set; }
|
||||
public string RootFolderPath { get; set; }
|
||||
public List<int> Tags { get; set; }
|
||||
public ApplyTags ApplyTags { get; set; }
|
||||
|
|
@ -4,14 +4,14 @@
|
|||
using Readarr.Http;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Artist
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class ArtistImportModule : ReadarrRestModule<ArtistResource>
|
||||
public class AuthorImportModule : ReadarrRestModule<AuthorResource>
|
||||
{
|
||||
private readonly IAddAuthorService _addAuthorService;
|
||||
|
||||
public ArtistImportModule(IAddAuthorService addAuthorService)
|
||||
: base("/artist/import")
|
||||
public AuthorImportModule(IAddAuthorService addAuthorService)
|
||||
: base("/author/import")
|
||||
{
|
||||
_addAuthorService = addAuthorService;
|
||||
Post("/", x => Import());
|
||||
|
|
@ -19,10 +19,10 @@ public ArtistImportModule(IAddAuthorService addAuthorService)
|
|||
|
||||
private object Import()
|
||||
{
|
||||
var resource = Request.Body.FromJson<List<ArtistResource>>();
|
||||
var newArtists = resource.ToModel();
|
||||
var resource = Request.Body.FromJson<List<AuthorResource>>();
|
||||
var newAuthors = resource.ToModel();
|
||||
|
||||
return _addAuthorService.AddAuthors(newArtists).ToResource();
|
||||
return _addAuthorService.AddAuthors(newAuthors).ToResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,14 +5,14 @@
|
|||
using NzbDrone.Core.MetadataSource;
|
||||
using Readarr.Http;
|
||||
|
||||
namespace Readarr.Api.V1.Artist
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class ArtistLookupModule : ReadarrRestModule<ArtistResource>
|
||||
public class AuthorLookupModule : ReadarrRestModule<AuthorResource>
|
||||
{
|
||||
private readonly ISearchForNewAuthor _searchProxy;
|
||||
|
||||
public ArtistLookupModule(ISearchForNewAuthor searchProxy)
|
||||
: base("/artist/lookup")
|
||||
public AuthorLookupModule(ISearchForNewAuthor searchProxy)
|
||||
: base("/author/lookup")
|
||||
{
|
||||
_searchProxy = searchProxy;
|
||||
Get("/", x => Search());
|
||||
|
|
@ -24,12 +24,12 @@ private object Search()
|
|||
return MapToResource(searchResults).ToList();
|
||||
}
|
||||
|
||||
private static IEnumerable<ArtistResource> MapToResource(IEnumerable<NzbDrone.Core.Books.Author> artist)
|
||||
private static IEnumerable<AuthorResource> MapToResource(IEnumerable<NzbDrone.Core.Books.Author> author)
|
||||
{
|
||||
foreach (var currentArtist in artist)
|
||||
foreach (var currentAuthor in author)
|
||||
{
|
||||
var resource = currentArtist.ToResource();
|
||||
var poster = currentArtist.Metadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
var resource = currentAuthor.ToResource();
|
||||
var poster = currentAuthor.Metadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
if (poster != null)
|
||||
{
|
||||
resource.RemotePoster = poster.Url;
|
||||
|
|
@ -19,9 +19,9 @@
|
|||
using Readarr.Http;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Artist
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class ArtistModule : ReadarrRestModuleWithSignalR<ArtistResource, NzbDrone.Core.Books.Author>,
|
||||
public class AuthorModule : ReadarrRestModuleWithSignalR<AuthorResource, NzbDrone.Core.Books.Author>,
|
||||
IHandle<BookImportedEvent>,
|
||||
IHandle<BookEditedEvent>,
|
||||
IHandle<BookFileDeletedEvent>,
|
||||
|
|
@ -34,24 +34,24 @@ public class ArtistModule : ReadarrRestModuleWithSignalR<ArtistResource, NzbDron
|
|||
private readonly IAuthorService _authorService;
|
||||
private readonly IBookService _bookService;
|
||||
private readonly IAddAuthorService _addAuthorService;
|
||||
private readonly IAuthorStatisticsService _artistStatisticsService;
|
||||
private readonly IAuthorStatisticsService _authorStatisticsService;
|
||||
private readonly IMapCoversToLocal _coverMapper;
|
||||
private readonly IManageCommandQueue _commandQueueManager;
|
||||
private readonly IRootFolderService _rootFolderService;
|
||||
|
||||
public ArtistModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
public AuthorModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IAuthorService authorService,
|
||||
IBookService bookService,
|
||||
IAddAuthorService addAuthorService,
|
||||
IAuthorStatisticsService artistStatisticsService,
|
||||
IAuthorStatisticsService authorStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IManageCommandQueue commandQueueManager,
|
||||
IRootFolderService rootFolderService,
|
||||
RootFolderValidator rootFolderValidator,
|
||||
MappedNetworkDriveValidator mappedNetworkDriveValidator,
|
||||
AuthorPathValidator artistPathValidator,
|
||||
ArtistExistsValidator artistExistsValidator,
|
||||
AuthorAncestorValidator artistAncestorValidator,
|
||||
AuthorPathValidator authorPathValidator,
|
||||
AuthorExistsValidator authorExistsValidator,
|
||||
AuthorAncestorValidator authorAncestorValidator,
|
||||
SystemFolderValidator systemFolderValidator,
|
||||
QualityProfileExistsValidator qualityProfileExistsValidator,
|
||||
MetadataProfileExistsValidator metadataProfileExistsValidator)
|
||||
|
|
@ -60,17 +60,17 @@ public ArtistModule(IBroadcastSignalRMessage signalRBroadcaster,
|
|||
_authorService = authorService;
|
||||
_bookService = bookService;
|
||||
_addAuthorService = addAuthorService;
|
||||
_artistStatisticsService = artistStatisticsService;
|
||||
_authorStatisticsService = authorStatisticsService;
|
||||
|
||||
_coverMapper = coverMapper;
|
||||
_commandQueueManager = commandQueueManager;
|
||||
_rootFolderService = rootFolderService;
|
||||
|
||||
GetResourceAll = AllArtists;
|
||||
GetResourceById = GetArtist;
|
||||
CreateResource = AddArtist;
|
||||
UpdateResource = UpdateArtist;
|
||||
DeleteResource = DeleteArtist;
|
||||
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));
|
||||
|
|
@ -80,8 +80,8 @@ public ArtistModule(IBroadcastSignalRMessage signalRBroadcaster,
|
|||
.IsValidPath()
|
||||
.SetValidator(rootFolderValidator)
|
||||
.SetValidator(mappedNetworkDriveValidator)
|
||||
.SetValidator(artistPathValidator)
|
||||
.SetValidator(artistAncestorValidator)
|
||||
.SetValidator(authorPathValidator)
|
||||
.SetValidator(authorAncestorValidator)
|
||||
.SetValidator(systemFolderValidator)
|
||||
.When(s => !s.Path.IsNullOrWhiteSpace());
|
||||
|
||||
|
|
@ -90,26 +90,26 @@ public ArtistModule(IBroadcastSignalRMessage signalRBroadcaster,
|
|||
|
||||
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.ArtistName).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.ForeignAuthorId).NotEmpty().SetValidator(artistExistsValidator);
|
||||
PostValidator.RuleFor(s => s.AuthorName).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.ForeignAuthorId).NotEmpty().SetValidator(authorExistsValidator);
|
||||
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
}
|
||||
|
||||
private ArtistResource GetArtist(int id)
|
||||
private AuthorResource GetAuthor(int id)
|
||||
{
|
||||
var artist = _authorService.GetAuthor(id);
|
||||
return GetArtistResource(artist);
|
||||
var author = _authorService.GetAuthor(id);
|
||||
return GetArtistResource(author);
|
||||
}
|
||||
|
||||
private ArtistResource GetArtistResource(NzbDrone.Core.Books.Author artist)
|
||||
private AuthorResource GetArtistResource(NzbDrone.Core.Books.Author author)
|
||||
{
|
||||
if (artist == null)
|
||||
if (author == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var resource = artist.ToResource();
|
||||
var resource = author.ToResource();
|
||||
MapCoversToLocal(resource);
|
||||
FetchAndLinkArtistStatistics(resource);
|
||||
LinkNextPreviousAlbums(resource);
|
||||
|
|
@ -120,53 +120,53 @@ private ArtistResource GetArtistResource(NzbDrone.Core.Books.Author artist)
|
|||
return resource;
|
||||
}
|
||||
|
||||
private List<ArtistResource> AllArtists()
|
||||
private List<AuthorResource> AllAuthors()
|
||||
{
|
||||
var artistStats = _artistStatisticsService.AuthorStatistics();
|
||||
var artistsResources = _authorService.GetAllAuthors().ToResource();
|
||||
var authorStats = _authorStatisticsService.AuthorStatistics();
|
||||
var authorResources = _authorService.GetAllAuthors().ToResource();
|
||||
|
||||
MapCoversToLocal(artistsResources.ToArray());
|
||||
LinkNextPreviousAlbums(artistsResources.ToArray());
|
||||
LinkArtistStatistics(artistsResources, artistStats);
|
||||
MapCoversToLocal(authorResources.ToArray());
|
||||
LinkNextPreviousAlbums(authorResources.ToArray());
|
||||
LinkArtistStatistics(authorResources, authorStats);
|
||||
|
||||
//PopulateAlternateTitles(seriesResources);
|
||||
return artistsResources;
|
||||
return authorResources;
|
||||
}
|
||||
|
||||
private int AddArtist(ArtistResource artistResource)
|
||||
private int AddAuthor(AuthorResource authorResource)
|
||||
{
|
||||
var artist = _addAuthorService.AddAuthor(artistResource.ToModel());
|
||||
var author = _addAuthorService.AddAuthor(authorResource.ToModel());
|
||||
|
||||
return artist.Id;
|
||||
return author.Id;
|
||||
}
|
||||
|
||||
private void UpdateArtist(ArtistResource artistResource)
|
||||
private void UpdateAuthor(AuthorResource authorResource)
|
||||
{
|
||||
var moveFiles = Request.GetBooleanQueryParameter("moveFiles");
|
||||
var artist = _authorService.GetAuthor(artistResource.Id);
|
||||
var author = _authorService.GetAuthor(authorResource.Id);
|
||||
|
||||
if (moveFiles)
|
||||
{
|
||||
var sourcePath = artist.Path;
|
||||
var destinationPath = artistResource.Path;
|
||||
var sourcePath = author.Path;
|
||||
var destinationPath = authorResource.Path;
|
||||
|
||||
_commandQueueManager.Push(new MoveAuthorCommand
|
||||
{
|
||||
AuthorId = artist.Id,
|
||||
AuthorId = author.Id,
|
||||
SourcePath = sourcePath,
|
||||
DestinationPath = destinationPath,
|
||||
Trigger = CommandTrigger.Manual
|
||||
});
|
||||
}
|
||||
|
||||
var model = artistResource.ToModel(artist);
|
||||
var model = authorResource.ToModel(author);
|
||||
|
||||
_authorService.UpdateAuthor(model);
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, artistResource);
|
||||
BroadcastResourceChange(ModelAction.Updated, authorResource);
|
||||
}
|
||||
|
||||
private void DeleteArtist(int id)
|
||||
private void DeleteAuthor(int id)
|
||||
{
|
||||
var deleteFiles = Request.GetBooleanQueryParameter("deleteFiles");
|
||||
var addImportListExclusion = Request.GetBooleanQueryParameter("addImportListExclusion");
|
||||
|
|
@ -174,48 +174,48 @@ private void DeleteArtist(int id)
|
|||
_authorService.DeleteAuthor(id, deleteFiles, addImportListExclusion);
|
||||
}
|
||||
|
||||
private void MapCoversToLocal(params ArtistResource[] artists)
|
||||
private void MapCoversToLocal(params AuthorResource[] authors)
|
||||
{
|
||||
foreach (var artistResource in artists)
|
||||
foreach (var authorResource in authors)
|
||||
{
|
||||
_coverMapper.ConvertToLocalUrls(artistResource.Id, MediaCoverEntity.Author, artistResource.Images);
|
||||
_coverMapper.ConvertToLocalUrls(authorResource.Id, MediaCoverEntity.Author, authorResource.Images);
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkNextPreviousAlbums(params ArtistResource[] artists)
|
||||
private void LinkNextPreviousAlbums(params AuthorResource[] authors)
|
||||
{
|
||||
var nextAlbums = _bookService.GetNextBooksByAuthorMetadataId(artists.Select(x => x.ArtistMetadataId));
|
||||
var lastAlbums = _bookService.GetLastBooksByAuthorMetadataId(artists.Select(x => x.ArtistMetadataId));
|
||||
var nextBooks = _bookService.GetNextBooksByAuthorMetadataId(authors.Select(x => x.AuthorMetadataId));
|
||||
var lastBooks = _bookService.GetLastBooksByAuthorMetadataId(authors.Select(x => x.AuthorMetadataId));
|
||||
|
||||
foreach (var artistResource in artists)
|
||||
foreach (var authorResource in authors)
|
||||
{
|
||||
artistResource.NextAlbum = nextAlbums.FirstOrDefault(x => x.AuthorMetadataId == artistResource.ArtistMetadataId);
|
||||
artistResource.LastAlbum = lastAlbums.FirstOrDefault(x => x.AuthorMetadataId == artistResource.ArtistMetadataId);
|
||||
authorResource.NextBook = nextBooks.FirstOrDefault(x => x.AuthorMetadataId == authorResource.AuthorMetadataId);
|
||||
authorResource.LastBook = lastBooks.FirstOrDefault(x => x.AuthorMetadataId == authorResource.AuthorMetadataId);
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchAndLinkArtistStatistics(ArtistResource resource)
|
||||
private void FetchAndLinkArtistStatistics(AuthorResource resource)
|
||||
{
|
||||
LinkArtistStatistics(resource, _artistStatisticsService.AuthorStatistics(resource.Id));
|
||||
LinkArtistStatistics(resource, _authorStatisticsService.AuthorStatistics(resource.Id));
|
||||
}
|
||||
|
||||
private void LinkArtistStatistics(List<ArtistResource> resources, List<AuthorStatistics> artistStatistics)
|
||||
private void LinkArtistStatistics(List<AuthorResource> resources, List<AuthorStatistics> authorStatistics)
|
||||
{
|
||||
foreach (var artist in resources)
|
||||
foreach (var author in resources)
|
||||
{
|
||||
var stats = artistStatistics.SingleOrDefault(ss => ss.AuthorId == artist.Id);
|
||||
var stats = authorStatistics.SingleOrDefault(ss => ss.AuthorId == author.Id);
|
||||
if (stats == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LinkArtistStatistics(artist, stats);
|
||||
LinkArtistStatistics(author, stats);
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkArtistStatistics(ArtistResource resource, AuthorStatistics artistStatistics)
|
||||
private void LinkArtistStatistics(AuthorResource resource, AuthorStatistics authorStatistics)
|
||||
{
|
||||
resource.Statistics = artistStatistics.ToResource();
|
||||
resource.Statistics = authorStatistics.ToResource();
|
||||
}
|
||||
|
||||
//private void PopulateAlternateTitles(List<ArtistResource> resources)
|
||||
|
|
@ -234,7 +234,7 @@ private void LinkArtistStatistics(ArtistResource resource, AuthorStatistics arti
|
|||
|
||||
// resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
||||
//}
|
||||
private void LinkRootFolderPath(ArtistResource resource)
|
||||
private void LinkRootFolderPath(AuthorResource resource)
|
||||
{
|
||||
resource.RootFolderPath = _rootFolderService.GetBestRootFolderPath(resource.Path);
|
||||
}
|
||||
|
|
@ -246,7 +246,7 @@ public void Handle(BookImportedEvent message)
|
|||
|
||||
public void Handle(BookEditedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Album.Author.Value));
|
||||
BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Book.Author.Value));
|
||||
}
|
||||
|
||||
public void Handle(BookFileDeletedEvent message)
|
||||
|
|
@ -7,30 +7,30 @@
|
|||
using NzbDrone.Core.MediaCover;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Artist
|
||||
namespace Readarr.Api.V1.Author
|
||||
{
|
||||
public class ArtistResource : RestResource
|
||||
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 ArtistMetadataId { get; set; }
|
||||
public int AuthorMetadataId { get; set; }
|
||||
public AuthorStatusType Status { get; set; }
|
||||
|
||||
public bool Ended => Status == AuthorStatusType.Ended;
|
||||
|
||||
public string ArtistName { get; set; }
|
||||
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 ArtistType { get; set; }
|
||||
public string AuthorType { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
public List<Links> Links { get; set; }
|
||||
|
||||
public Book NextAlbum { get; set; }
|
||||
public Book LastAlbum { get; set; }
|
||||
public Book NextBook { get; set; }
|
||||
public Book LastBook { get; set; }
|
||||
|
||||
public List<MediaCover> Images { get; set; }
|
||||
|
||||
|
|
@ -42,7 +42,6 @@ public class ArtistResource : RestResource
|
|||
public int MetadataProfileId { get; set; }
|
||||
|
||||
//Editing Only
|
||||
public bool AlbumFolder { get; set; }
|
||||
public bool Monitored { get; set; }
|
||||
|
||||
public string RootFolderPath { get; set; }
|
||||
|
|
@ -54,31 +53,31 @@ public class ArtistResource : RestResource
|
|||
public AddAuthorOptions AddOptions { get; set; }
|
||||
public Ratings Ratings { get; set; }
|
||||
|
||||
public ArtistStatisticsResource Statistics { get; set; }
|
||||
public AuthorStatisticsResource Statistics { get; set; }
|
||||
}
|
||||
|
||||
public static class ArtistResourceMapper
|
||||
public static class AuthorResourceMapper
|
||||
{
|
||||
public static ArtistResource ToResource(this NzbDrone.Core.Books.Author model)
|
||||
public static AuthorResource ToResource(this NzbDrone.Core.Books.Author model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ArtistResource
|
||||
return new AuthorResource
|
||||
{
|
||||
Id = model.Id,
|
||||
ArtistMetadataId = model.AuthorMetadataId,
|
||||
AuthorMetadataId = model.AuthorMetadataId,
|
||||
|
||||
ArtistName = model.Name,
|
||||
AuthorName = model.Name,
|
||||
|
||||
//AlternateTitles
|
||||
SortName = model.SortName,
|
||||
|
||||
Status = model.Metadata.Value.Status,
|
||||
Overview = model.Metadata.Value.Overview,
|
||||
ArtistType = model.Metadata.Value.Type,
|
||||
AuthorType = model.Metadata.Value.Type,
|
||||
Disambiguation = model.Metadata.Value.Disambiguation,
|
||||
|
||||
Images = model.Metadata.Value.Images.JsonClone(),
|
||||
|
|
@ -103,11 +102,11 @@ public static ArtistResource ToResource(this NzbDrone.Core.Books.Author model)
|
|||
AddOptions = model.AddOptions,
|
||||
Ratings = model.Metadata.Value.Ratings,
|
||||
|
||||
Statistics = new ArtistStatisticsResource()
|
||||
Statistics = new AuthorStatisticsResource()
|
||||
};
|
||||
}
|
||||
|
||||
public static NzbDrone.Core.Books.Author ToModel(this ArtistResource resource)
|
||||
public static NzbDrone.Core.Books.Author ToModel(this AuthorResource resource)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
|
|
@ -123,14 +122,14 @@ public static NzbDrone.Core.Books.Author ToModel(this ArtistResource resource)
|
|||
ForeignAuthorId = resource.ForeignAuthorId,
|
||||
GoodreadsId = resource.GoodreadsId,
|
||||
TitleSlug = resource.TitleSlug,
|
||||
Name = resource.ArtistName,
|
||||
Name = resource.AuthorName,
|
||||
Status = resource.Status,
|
||||
Overview = resource.Overview,
|
||||
Links = resource.Links,
|
||||
Images = resource.Images,
|
||||
Genres = resource.Genres,
|
||||
Ratings = resource.Ratings,
|
||||
Type = resource.ArtistType
|
||||
Type = resource.AuthorType
|
||||
},
|
||||
|
||||
//AlternateTitles
|
||||
|
|
@ -150,21 +149,21 @@ public static NzbDrone.Core.Books.Author ToModel(this ArtistResource resource)
|
|||
};
|
||||
}
|
||||
|
||||
public static NzbDrone.Core.Books.Author ToModel(this ArtistResource resource, NzbDrone.Core.Books.Author artist)
|
||||
public static NzbDrone.Core.Books.Author ToModel(this AuthorResource resource, NzbDrone.Core.Books.Author author)
|
||||
{
|
||||
var updatedArtist = resource.ToModel();
|
||||
var updatedAuthor = resource.ToModel();
|
||||
|
||||
artist.ApplyChanges(updatedArtist);
|
||||
author.ApplyChanges(updatedAuthor);
|
||||
|
||||
return artist;
|
||||
return author;
|
||||
}
|
||||
|
||||
public static List<ArtistResource> ToResource(this IEnumerable<NzbDrone.Core.Books.Author> artist)
|
||||
public static List<AuthorResource> ToResource(this IEnumerable<NzbDrone.Core.Books.Author> author)
|
||||
{
|
||||
return artist.Select(ToResource).ToList();
|
||||
return author.Select(ToResource).ToList();
|
||||
}
|
||||
|
||||
public static List<NzbDrone.Core.Books.Author> ToModel(this IEnumerable<ArtistResource> resources)
|
||||
public static List<NzbDrone.Core.Books.Author> ToModel(this IEnumerable<AuthorResource> resources)
|
||||
{
|
||||
return resources.Select(ToModel).ToList();
|
||||
}
|
||||
43
src/Readarr.Api.V1/Author/AuthorStatisticsResource.cs
Normal file
43
src/Readarr.Api.V1/Author/AuthorStatisticsResource.cs
Normal file
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Blacklist
|
||||
|
|
@ -18,7 +18,7 @@ public class BlacklistResource : RestResource
|
|||
public string Indexer { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public ArtistResource Artist { get; set; }
|
||||
public AuthorResource Author { get; set; }
|
||||
}
|
||||
|
||||
public static class BlacklistResourceMapper
|
||||
|
|
@ -43,7 +43,7 @@ public static BlacklistResource MapToResource(this NzbDrone.Core.Blacklisting.Bl
|
|||
Indexer = model.Indexer,
|
||||
Message = model.Message,
|
||||
|
||||
Artist = model.Author.ToResource()
|
||||
Author = model.Author.ToResource()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace Readarr.Api.V1.TrackFiles
|
||||
namespace Readarr.Api.V1.BookFiles
|
||||
{
|
||||
public class TrackFileListResource
|
||||
public class BookFileListResource
|
||||
{
|
||||
public List<int> TrackFileIds { get; set; }
|
||||
public List<int> BookFileIds { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -14,9 +14,9 @@
|
|||
using Readarr.Http.Extensions;
|
||||
using HttpStatusCode = System.Net.HttpStatusCode;
|
||||
|
||||
namespace Readarr.Api.V1.TrackFiles
|
||||
namespace Readarr.Api.V1.BookFiles
|
||||
{
|
||||
public class TrackFileModule : ReadarrRestModuleWithSignalR<TrackFileResource, BookFile>,
|
||||
public class BookFileModule : ReadarrRestModuleWithSignalR<BookFileResource, BookFile>,
|
||||
IHandle<BookFileAddedEvent>,
|
||||
IHandle<BookFileDeletedEvent>
|
||||
{
|
||||
|
|
@ -27,7 +27,7 @@ public class TrackFileModule : ReadarrRestModuleWithSignalR<TrackFileResource, B
|
|||
private readonly IBookService _bookService;
|
||||
private readonly IUpgradableSpecification _upgradableSpecification;
|
||||
|
||||
public TrackFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
public BookFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMediaFileService mediaFileService,
|
||||
IDeleteMediaFiles mediaFileDeletionService,
|
||||
IAudioTagService audioTagService,
|
||||
|
|
@ -43,44 +43,44 @@ public TrackFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
|||
_bookService = bookService;
|
||||
_upgradableSpecification = upgradableSpecification;
|
||||
|
||||
GetResourceById = GetTrackFile;
|
||||
GetResourceAll = GetTrackFiles;
|
||||
GetResourceById = GetBookFile;
|
||||
GetResourceAll = GetBookFiles;
|
||||
UpdateResource = SetQuality;
|
||||
DeleteResource = DeleteTrackFile;
|
||||
DeleteResource = DeleteBookFile;
|
||||
|
||||
Put("/editor", trackFiles => SetQuality());
|
||||
Delete("/bulk", trackFiles => DeleteTrackFiles());
|
||||
Delete("/bulk", trackFiles => DeleteBookFiles());
|
||||
}
|
||||
|
||||
private TrackFileResource MapToResource(BookFile trackFile)
|
||||
private BookFileResource MapToResource(BookFile bookFile)
|
||||
{
|
||||
if (trackFile.BookId > 0 && trackFile.Author != null && trackFile.Author.Value != null)
|
||||
if (bookFile.BookId > 0 && bookFile.Author != null && bookFile.Author.Value != null)
|
||||
{
|
||||
return trackFile.ToResource(trackFile.Author.Value, _upgradableSpecification);
|
||||
return bookFile.ToResource(bookFile.Author.Value, _upgradableSpecification);
|
||||
}
|
||||
else
|
||||
{
|
||||
return trackFile.ToResource();
|
||||
return bookFile.ToResource();
|
||||
}
|
||||
}
|
||||
|
||||
private TrackFileResource GetTrackFile(int id)
|
||||
private BookFileResource GetBookFile(int id)
|
||||
{
|
||||
var resource = MapToResource(_mediaFileService.Get(id));
|
||||
resource.AudioTags = _audioTagService.ReadTags(resource.Path);
|
||||
return resource;
|
||||
}
|
||||
|
||||
private List<TrackFileResource> GetTrackFiles()
|
||||
private List<BookFileResource> GetBookFiles()
|
||||
{
|
||||
var authorIdQuery = Request.Query.AuthorId;
|
||||
var trackFileIdsQuery = Request.Query.TrackFileIds;
|
||||
var bookFileIdsQuery = Request.Query.TrackFileIds;
|
||||
var bookIdQuery = Request.Query.BookId;
|
||||
var unmappedQuery = Request.Query.Unmapped;
|
||||
|
||||
if (!authorIdQuery.HasValue && !trackFileIdsQuery.HasValue && !bookIdQuery.HasValue && !unmappedQuery.HasValue)
|
||||
if (!authorIdQuery.HasValue && !bookFileIdsQuery.HasValue && !bookIdQuery.HasValue && !unmappedQuery.HasValue)
|
||||
{
|
||||
throw new Readarr.Http.REST.BadRequestException("authorId, bookId, trackFileIds or unmapped must be provided");
|
||||
throw new Readarr.Http.REST.BadRequestException("authorId, bookId, bookFileIds or unmapped must be provided");
|
||||
}
|
||||
|
||||
if (unmappedQuery.HasValue && Convert.ToBoolean(unmappedQuery.Value))
|
||||
|
|
@ -92,9 +92,9 @@ private List<TrackFileResource> GetTrackFiles()
|
|||
if (authorIdQuery.HasValue && !bookIdQuery.HasValue)
|
||||
{
|
||||
int authorId = Convert.ToInt32(authorIdQuery.Value);
|
||||
var artist = _authorService.GetAuthor(authorId);
|
||||
var author = _authorService.GetAuthor(authorId);
|
||||
|
||||
return _mediaFileService.GetFilesByAuthor(authorId).ConvertAll(f => f.ToResource(artist, _upgradableSpecification));
|
||||
return _mediaFileService.GetFilesByAuthor(authorId).ConvertAll(f => f.ToResource(author, _upgradableSpecification));
|
||||
}
|
||||
|
||||
if (bookIdQuery.HasValue)
|
||||
|
|
@ -105,84 +105,84 @@ private List<TrackFileResource> GetTrackFiles()
|
|||
.Select(e => Convert.ToInt32(e))
|
||||
.ToList();
|
||||
|
||||
var result = new List<TrackFileResource>();
|
||||
var result = new List<BookFileResource>();
|
||||
foreach (var bookId in bookIds)
|
||||
{
|
||||
var album = _bookService.GetBook(bookId);
|
||||
var albumArtist = _authorService.GetAuthor(album.AuthorId);
|
||||
result.AddRange(_mediaFileService.GetFilesByBook(album.Id).ConvertAll(f => f.ToResource(albumArtist, _upgradableSpecification)));
|
||||
var book = _bookService.GetBook(bookId);
|
||||
var bookAuthor = _authorService.GetAuthor(book.AuthorId);
|
||||
result.AddRange(_mediaFileService.GetFilesByBook(book.Id).ConvertAll(f => f.ToResource(bookAuthor, _upgradableSpecification)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
string trackFileIdsValue = trackFileIdsQuery.Value.ToString();
|
||||
string bookFileIdsValue = bookFileIdsQuery.Value.ToString();
|
||||
|
||||
var trackFileIds = trackFileIdsValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
var bookFileIds = bookFileIdsValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(e => Convert.ToInt32(e))
|
||||
.ToList();
|
||||
|
||||
// trackfiles will come back with the artist already populated
|
||||
var trackFiles = _mediaFileService.Get(trackFileIds);
|
||||
return trackFiles.ConvertAll(e => MapToResource(e));
|
||||
var bookFiles = _mediaFileService.Get(bookFileIds);
|
||||
return bookFiles.ConvertAll(e => MapToResource(e));
|
||||
}
|
||||
}
|
||||
|
||||
private void SetQuality(TrackFileResource trackFileResource)
|
||||
private void SetQuality(BookFileResource bookFileResource)
|
||||
{
|
||||
var trackFile = _mediaFileService.Get(trackFileResource.Id);
|
||||
trackFile.Quality = trackFileResource.Quality;
|
||||
_mediaFileService.Update(trackFile);
|
||||
var bookFile = _mediaFileService.Get(bookFileResource.Id);
|
||||
bookFile.Quality = bookFileResource.Quality;
|
||||
_mediaFileService.Update(bookFile);
|
||||
}
|
||||
|
||||
private object SetQuality()
|
||||
{
|
||||
var resource = Request.Body.FromJson<TrackFileListResource>();
|
||||
var trackFiles = _mediaFileService.Get(resource.TrackFileIds);
|
||||
var resource = Request.Body.FromJson<BookFileListResource>();
|
||||
var bookFiles = _mediaFileService.Get(resource.BookFileIds);
|
||||
|
||||
foreach (var trackFile in trackFiles)
|
||||
foreach (var bookFile in bookFiles)
|
||||
{
|
||||
if (resource.Quality != null)
|
||||
{
|
||||
trackFile.Quality = resource.Quality;
|
||||
bookFile.Quality = resource.Quality;
|
||||
}
|
||||
}
|
||||
|
||||
_mediaFileService.Update(trackFiles);
|
||||
_mediaFileService.Update(bookFiles);
|
||||
|
||||
return ResponseWithCode(trackFiles.ConvertAll(f => f.ToResource(trackFiles.First().Author.Value, _upgradableSpecification)),
|
||||
return ResponseWithCode(bookFiles.ConvertAll(f => f.ToResource(bookFiles.First().Author.Value, _upgradableSpecification)),
|
||||
Nancy.HttpStatusCode.Accepted);
|
||||
}
|
||||
|
||||
private void DeleteTrackFile(int id)
|
||||
private void DeleteBookFile(int id)
|
||||
{
|
||||
var trackFile = _mediaFileService.Get(id);
|
||||
var bookFile = _mediaFileService.Get(id);
|
||||
|
||||
if (trackFile == null)
|
||||
if (bookFile == null)
|
||||
{
|
||||
throw new NzbDroneClientException(HttpStatusCode.NotFound, "Track file not found");
|
||||
throw new NzbDroneClientException(HttpStatusCode.NotFound, "Book file not found");
|
||||
}
|
||||
|
||||
if (trackFile.BookId > 0 && trackFile.Author != null && trackFile.Author.Value != null)
|
||||
if (bookFile.BookId > 0 && bookFile.Author != null && bookFile.Author.Value != null)
|
||||
{
|
||||
_mediaFileDeletionService.DeleteTrackFile(trackFile.Author.Value, trackFile);
|
||||
_mediaFileDeletionService.DeleteTrackFile(bookFile.Author.Value, bookFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mediaFileDeletionService.DeleteTrackFile(trackFile, "Unmapped_Files");
|
||||
_mediaFileDeletionService.DeleteTrackFile(bookFile, "Unmapped_Files");
|
||||
}
|
||||
}
|
||||
|
||||
private object DeleteTrackFiles()
|
||||
private object DeleteBookFiles()
|
||||
{
|
||||
var resource = Request.Body.FromJson<TrackFileListResource>();
|
||||
var trackFiles = _mediaFileService.Get(resource.TrackFileIds);
|
||||
var artist = trackFiles.First().Author.Value;
|
||||
var resource = Request.Body.FromJson<BookFileListResource>();
|
||||
var bookFiles = _mediaFileService.Get(resource.BookFileIds);
|
||||
var author = bookFiles.First().Author.Value;
|
||||
|
||||
foreach (var trackFile in trackFiles)
|
||||
foreach (var bookFile in bookFiles)
|
||||
{
|
||||
_mediaFileDeletionService.DeleteTrackFile(artist, trackFile);
|
||||
_mediaFileDeletionService.DeleteTrackFile(author, bookFile);
|
||||
}
|
||||
|
||||
return new object();
|
||||
|
|
@ -7,9 +7,9 @@
|
|||
using NzbDrone.Core.Qualities;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.TrackFiles
|
||||
namespace Readarr.Api.V1.BookFiles
|
||||
{
|
||||
public class TrackFileResource : RestResource
|
||||
public class BookFileResource : RestResource
|
||||
{
|
||||
public int AuthorId { get; set; }
|
||||
public int BookId { get; set; }
|
||||
|
|
@ -24,7 +24,7 @@ public class TrackFileResource : RestResource
|
|||
public ParsedTrackInfo AudioTags { get; set; }
|
||||
}
|
||||
|
||||
public static class TrackFileResourceMapper
|
||||
public static class BookFileResourceMapper
|
||||
{
|
||||
private static int QualityWeight(QualityModel quality)
|
||||
{
|
||||
|
|
@ -39,14 +39,14 @@ private static int QualityWeight(QualityModel quality)
|
|||
return qualityWeight;
|
||||
}
|
||||
|
||||
public static TrackFileResource ToResource(this BookFile model)
|
||||
public static BookFileResource ToResource(this BookFile model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TrackFileResource
|
||||
return new BookFileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
BookId = model.BookId,
|
||||
|
|
@ -59,18 +59,18 @@ public static TrackFileResource ToResource(this BookFile model)
|
|||
};
|
||||
}
|
||||
|
||||
public static TrackFileResource ToResource(this BookFile model, NzbDrone.Core.Books.Author artist, IUpgradableSpecification upgradableSpecification)
|
||||
public static BookFileResource ToResource(this BookFile model, NzbDrone.Core.Books.Author author, IUpgradableSpecification upgradableSpecification)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TrackFileResource
|
||||
return new BookFileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
AuthorId = artist.Id,
|
||||
AuthorId = author.Id,
|
||||
BookId = model.BookId,
|
||||
Path = model.Path,
|
||||
Size = model.Size,
|
||||
|
|
@ -78,7 +78,7 @@ public static TrackFileResource ToResource(this BookFile model, NzbDrone.Core.Bo
|
|||
Quality = model.Quality,
|
||||
QualityWeight = QualityWeight(model.Quality),
|
||||
MediaInfo = model.MediaInfo.ToResource(),
|
||||
QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(artist.QualityProfile.Value, model.Quality)
|
||||
QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(author.QualityProfile.Value, model.Quality)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
using NzbDrone.Core.Parser.Model;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.TrackFiles
|
||||
namespace Readarr.Api.V1.BookFiles
|
||||
{
|
||||
public class MediaInfoResource : RestResource
|
||||
{
|
||||
12
src/Readarr.Api.V1/BookShelf/BookshelfAuthorResource1.cs
Normal file
12
src/Readarr.Api.V1/BookShelf/BookshelfAuthorResource1.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using System.Collections.Generic;
|
||||
using Readarr.Api.V1.Books;
|
||||
|
||||
namespace Readarr.Api.V1.Bookshelf
|
||||
{
|
||||
public class BookshelfAuthorResource
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public bool? Monitored { get; set; }
|
||||
public List<BookResource> Books { get; set; }
|
||||
}
|
||||
}
|
||||
47
src/Readarr.Api.V1/BookShelf/BookshelfModule1.cs
Normal file
47
src/Readarr.Api.V1/BookShelf/BookshelfModule1.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Core.Books;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Bookshelf
|
||||
{
|
||||
public class BookshelfModule : ReadarrV1Module
|
||||
{
|
||||
private readonly IAuthorService _authorService;
|
||||
private readonly IBookMonitoredService _bookMonitoredService;
|
||||
|
||||
public BookshelfModule(IAuthorService authorService, IBookMonitoredService bookMonitoredService)
|
||||
: base("/bookshelf")
|
||||
{
|
||||
_authorService = authorService;
|
||||
_bookMonitoredService = bookMonitoredService;
|
||||
Post("/", artist => UpdateAll());
|
||||
}
|
||||
|
||||
private object UpdateAll()
|
||||
{
|
||||
//Read from request
|
||||
var request = Request.Body.FromJson<BookshelfResource>();
|
||||
var authorToUpdate = _authorService.GetAuthors(request.Authors.Select(s => s.Id));
|
||||
|
||||
foreach (var s in request.Authors)
|
||||
{
|
||||
var author = authorToUpdate.Single(c => c.Id == s.Id);
|
||||
|
||||
if (s.Monitored.HasValue)
|
||||
{
|
||||
author.Monitored = s.Monitored.Value;
|
||||
}
|
||||
|
||||
if (request.MonitoringOptions != null && request.MonitoringOptions.Monitor == MonitorTypes.None)
|
||||
{
|
||||
author.Monitored = false;
|
||||
}
|
||||
|
||||
_bookMonitoredService.SetBookMonitoredStatus(author, request.MonitoringOptions);
|
||||
}
|
||||
|
||||
return ResponseWithCode("ok", HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Books;
|
||||
|
||||
namespace Readarr.Api.V1.AlbumStudio
|
||||
namespace Readarr.Api.V1.Bookshelf
|
||||
{
|
||||
public class AlbumStudioResource
|
||||
public class BookshelfResource
|
||||
{
|
||||
public List<AlbumStudioArtistResource> Artist { get; set; }
|
||||
public List<BookshelfAuthorResource> Authors { get; set; }
|
||||
public MonitoringOptions MonitoringOptions { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -5,14 +5,14 @@
|
|||
using NzbDrone.Core.MetadataSource;
|
||||
using Readarr.Http;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public class AlbumLookupModule : ReadarrRestModule<AlbumResource>
|
||||
public class BookLookupModule : ReadarrRestModule<BookResource>
|
||||
{
|
||||
private readonly ISearchForNewBook _searchProxy;
|
||||
|
||||
public AlbumLookupModule(ISearchForNewBook searchProxy)
|
||||
: base("/album/lookup")
|
||||
public BookLookupModule(ISearchForNewBook searchProxy)
|
||||
: base("/book/lookup")
|
||||
{
|
||||
_searchProxy = searchProxy;
|
||||
Get("/", x => Search());
|
||||
|
|
@ -24,12 +24,12 @@ private object Search()
|
|||
return MapToResource(searchResults).ToList();
|
||||
}
|
||||
|
||||
private static IEnumerable<AlbumResource> MapToResource(IEnumerable<NzbDrone.Core.Books.Book> albums)
|
||||
private static IEnumerable<BookResource> MapToResource(IEnumerable<NzbDrone.Core.Books.Book> books)
|
||||
{
|
||||
foreach (var currentAlbum in albums)
|
||||
foreach (var currentBook in books)
|
||||
{
|
||||
var resource = currentAlbum.ToResource();
|
||||
var cover = currentAlbum.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Cover);
|
||||
var resource = currentBook.ToResource();
|
||||
var cover = currentBook.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Cover);
|
||||
if (cover != null)
|
||||
{
|
||||
resource.RemoteCover = cover.Url;
|
||||
|
|
@ -19,9 +19,9 @@
|
|||
using NzbDrone.SignalR;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public class AlbumModule : AlbumModuleWithSignalR,
|
||||
public class BookModule : BookModuleWithSignalR,
|
||||
IHandle<BookGrabbedEvent>,
|
||||
IHandle<BookEditedEvent>,
|
||||
IHandle<BookUpdatedEvent>,
|
||||
|
|
@ -32,53 +32,53 @@ public class AlbumModule : AlbumModuleWithSignalR,
|
|||
protected readonly IAuthorService _authorService;
|
||||
protected readonly IAddBookService _addBookService;
|
||||
|
||||
public AlbumModule(IAuthorService authorService,
|
||||
public BookModule(IAuthorService authorService,
|
||||
IBookService bookService,
|
||||
IAddBookService addBookService,
|
||||
IAuthorStatisticsService artistStatisticsService,
|
||||
IAuthorStatisticsService authorStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster,
|
||||
QualityProfileExistsValidator qualityProfileExistsValidator,
|
||||
MetadataProfileExistsValidator metadataProfileExistsValidator)
|
||||
|
||||
: base(bookService, artistStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster)
|
||||
: base(bookService, authorStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster)
|
||||
{
|
||||
_authorService = authorService;
|
||||
_addBookService = addBookService;
|
||||
|
||||
GetResourceAll = GetAlbums;
|
||||
CreateResource = AddAlbum;
|
||||
UpdateResource = UpdateAlbum;
|
||||
DeleteResource = DeleteAlbum;
|
||||
Put("/monitor", x => SetAlbumsMonitored());
|
||||
GetResourceAll = GetBooks;
|
||||
CreateResource = AddBook;
|
||||
UpdateResource = UpdateBook;
|
||||
DeleteResource = DeleteBook;
|
||||
Put("/monitor", x => SetBooksMonitored());
|
||||
|
||||
PostValidator.RuleFor(s => s.ForeignBookId).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.Artist.QualityProfileId).SetValidator(qualityProfileExistsValidator);
|
||||
PostValidator.RuleFor(s => s.Artist.MetadataProfileId).SetValidator(metadataProfileExistsValidator);
|
||||
PostValidator.RuleFor(s => s.Artist.RootFolderPath).IsValidPath().When(s => s.Artist.Path.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.Artist.ForeignAuthorId).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.Author.QualityProfileId).SetValidator(qualityProfileExistsValidator);
|
||||
PostValidator.RuleFor(s => s.Author.MetadataProfileId).SetValidator(metadataProfileExistsValidator);
|
||||
PostValidator.RuleFor(s => s.Author.RootFolderPath).IsValidPath().When(s => s.Author.Path.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.Author.ForeignAuthorId).NotEmpty();
|
||||
}
|
||||
|
||||
private List<AlbumResource> GetAlbums()
|
||||
private List<BookResource> GetBooks()
|
||||
{
|
||||
var authorIdQuery = Request.Query.AuthorId;
|
||||
var bookIdsQuery = Request.Query.BookIds;
|
||||
var slugQuery = Request.Query.TitleSlug;
|
||||
var includeAllArtistAlbumsQuery = Request.Query.IncludeAllArtistAlbums;
|
||||
var includeAllAuthorBooksQuery = Request.Query.IncludeAllAuthorBooks;
|
||||
|
||||
if (!Request.Query.AuthorId.HasValue && !bookIdsQuery.HasValue && !slugQuery.HasValue)
|
||||
{
|
||||
var albums = _bookService.GetAllBooks();
|
||||
var books = _bookService.GetAllBooks();
|
||||
|
||||
var artists = _authorService.GetAllAuthors().ToDictionary(x => x.AuthorMetadataId);
|
||||
var authors = _authorService.GetAllAuthors().ToDictionary(x => x.AuthorMetadataId);
|
||||
|
||||
foreach (var album in albums)
|
||||
foreach (var book in books)
|
||||
{
|
||||
album.Author = artists[album.AuthorMetadataId];
|
||||
book.Author = authors[book.AuthorMetadataId];
|
||||
}
|
||||
|
||||
return MapToResource(albums, false);
|
||||
return MapToResource(books, false);
|
||||
}
|
||||
|
||||
if (authorIdQuery.HasValue)
|
||||
|
|
@ -92,20 +92,20 @@ private List<AlbumResource> GetAlbums()
|
|||
{
|
||||
string titleSlug = slugQuery.Value.ToString();
|
||||
|
||||
var album = _bookService.FindBySlug(titleSlug);
|
||||
var book = _bookService.FindBySlug(titleSlug);
|
||||
|
||||
if (album == null)
|
||||
if (book == null)
|
||||
{
|
||||
return MapToResource(new List<Book>(), false);
|
||||
}
|
||||
|
||||
if (includeAllArtistAlbumsQuery.HasValue && Convert.ToBoolean(includeAllArtistAlbumsQuery.Value))
|
||||
if (includeAllAuthorBooksQuery.HasValue && Convert.ToBoolean(includeAllAuthorBooksQuery.Value))
|
||||
{
|
||||
return MapToResource(_bookService.GetBooksByAuthor(album.AuthorId), false);
|
||||
return MapToResource(_bookService.GetBooksByAuthor(book.AuthorId), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return MapToResource(new List<Book> { album }, false);
|
||||
return MapToResource(new List<Book> { book }, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,25 +118,25 @@ private List<AlbumResource> GetAlbums()
|
|||
return MapToResource(_bookService.GetBooks(bookIds), false);
|
||||
}
|
||||
|
||||
private int AddAlbum(AlbumResource albumResource)
|
||||
private int AddBook(BookResource bookResource)
|
||||
{
|
||||
var album = _addBookService.AddBook(albumResource.ToModel());
|
||||
var book = _addBookService.AddBook(bookResource.ToModel());
|
||||
|
||||
return album.Id;
|
||||
return book.Id;
|
||||
}
|
||||
|
||||
private void UpdateAlbum(AlbumResource albumResource)
|
||||
private void UpdateBook(BookResource bookResource)
|
||||
{
|
||||
var album = _bookService.GetBook(albumResource.Id);
|
||||
var book = _bookService.GetBook(bookResource.Id);
|
||||
|
||||
var model = albumResource.ToModel(album);
|
||||
var model = bookResource.ToModel(book);
|
||||
|
||||
_bookService.UpdateBook(model);
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, model.Id);
|
||||
}
|
||||
|
||||
private void DeleteAlbum(int id)
|
||||
private void DeleteBook(int id)
|
||||
{
|
||||
var deleteFiles = Request.GetBooleanQueryParameter("deleteFiles");
|
||||
var addImportListExclusion = Request.GetBooleanQueryParameter("addImportListExclusion");
|
||||
|
|
@ -144,9 +144,9 @@ private void DeleteAlbum(int id)
|
|||
_bookService.DeleteBook(id, deleteFiles, addImportListExclusion);
|
||||
}
|
||||
|
||||
private object SetAlbumsMonitored()
|
||||
private object SetBooksMonitored()
|
||||
{
|
||||
var resource = Request.Body.FromJson<AlbumsMonitoredResource>();
|
||||
var resource = Request.Body.FromJson<BooksMonitoredResource>();
|
||||
|
||||
_bookService.SetMonitored(resource.BookIds, resource.Monitored);
|
||||
|
||||
|
|
@ -155,9 +155,9 @@ private object SetAlbumsMonitored()
|
|||
|
||||
public void Handle(BookGrabbedEvent message)
|
||||
{
|
||||
foreach (var album in message.Book.Books)
|
||||
foreach (var book in message.Book.Books)
|
||||
{
|
||||
var resource = album.ToResource();
|
||||
var resource = book.ToResource();
|
||||
resource.Grabbed = true;
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, resource);
|
||||
|
|
@ -166,7 +166,7 @@ public void Handle(BookGrabbedEvent message)
|
|||
|
||||
public void Handle(BookEditedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, MapToResource(message.Album, true));
|
||||
BroadcastResourceChange(ModelAction.Updated, MapToResource(message.Book, true));
|
||||
}
|
||||
|
||||
public void Handle(BookUpdatedEvent message)
|
||||
133
src/Readarr.Api.V1/Books/BookModuleWithSignalR.cs
Normal file
133
src/Readarr.Api.V1/Books/BookModuleWithSignalR.cs
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
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;
|
||||
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public abstract class BookModuleWithSignalR : ReadarrRestModuleWithSignalR<BookResource, Book>
|
||||
{
|
||||
protected readonly IBookService _bookService;
|
||||
protected readonly IAuthorStatisticsService _authorStatisticsService;
|
||||
protected readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
||||
protected readonly IMapCoversToLocal _coverMapper;
|
||||
|
||||
protected BookModuleWithSignalR(IBookService bookService,
|
||||
IAuthorStatisticsService authorStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_bookService = bookService;
|
||||
_authorStatisticsService = authorStatisticsService;
|
||||
_coverMapper = coverMapper;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
|
||||
GetResourceById = GetBook;
|
||||
}
|
||||
|
||||
protected BookModuleWithSignalR(IBookService bookService,
|
||||
IAuthorStatisticsService authorStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster,
|
||||
string resource)
|
||||
: base(signalRBroadcaster, resource)
|
||||
{
|
||||
_bookService = bookService;
|
||||
_authorStatisticsService = authorStatisticsService;
|
||||
_coverMapper = coverMapper;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
|
||||
GetResourceById = GetBook;
|
||||
}
|
||||
|
||||
protected BookResource GetBook(int id)
|
||||
{
|
||||
var book = _bookService.GetBook(id);
|
||||
var resource = MapToResource(book, true);
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected BookResource MapToResource(Book book, bool includeAuthor)
|
||||
{
|
||||
var resource = book.ToResource();
|
||||
|
||||
if (includeAuthor)
|
||||
{
|
||||
var artist = book.Author.Value;
|
||||
|
||||
resource.Author = artist.ToResource();
|
||||
}
|
||||
|
||||
FetchAndLinkAlbumStatistics(resource);
|
||||
MapCoversToLocal(resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected List<BookResource> MapToResource(List<Book> books, bool includeAuthor)
|
||||
{
|
||||
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 FetchAndLinkAlbumStatistics(BookResource resource)
|
||||
{
|
||||
LinkAuthorStatistics(resource, _authorStatisticsService.AuthorStatistics(resource.AuthorId));
|
||||
}
|
||||
|
||||
private void LinkAuthorStatistics(List<BookResource> resources, List<AuthorStatistics> authorStatistics)
|
||||
{
|
||||
foreach (var book in resources)
|
||||
{
|
||||
var stats = authorStatistics.SingleOrDefault(ss => ss.AuthorId == book.AuthorId);
|
||||
LinkAuthorStatistics(book, stats);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,13 +4,13 @@
|
|||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.Books;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.TrackFiles;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.BookFiles;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public class AlbumResource : RestResource
|
||||
public class BookResource : RestResource
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
|
|
@ -27,10 +27,10 @@ public class AlbumResource : RestResource
|
|||
public Ratings Ratings { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public List<string> Genres { get; set; }
|
||||
public ArtistResource Artist { get; set; }
|
||||
public AuthorResource Author { get; set; }
|
||||
public List<MediaCover> Images { get; set; }
|
||||
public List<Links> Links { get; set; }
|
||||
public AlbumStatisticsResource Statistics { get; set; }
|
||||
public BookStatisticsResource Statistics { get; set; }
|
||||
public AddBookOptions AddOptions { get; set; }
|
||||
public string RemoteCover { get; set; }
|
||||
|
||||
|
|
@ -39,16 +39,16 @@ public class AlbumResource : RestResource
|
|||
public bool Grabbed { get; set; }
|
||||
}
|
||||
|
||||
public static class AlbumResourceMapper
|
||||
public static class BookResourceMapper
|
||||
{
|
||||
public static AlbumResource ToResource(this Book model)
|
||||
public static BookResource ToResource(this Book model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AlbumResource
|
||||
return new BookResource
|
||||
{
|
||||
Id = model.Id,
|
||||
AuthorId = model.AuthorId,
|
||||
|
|
@ -68,18 +68,18 @@ public static AlbumResource ToResource(this Book model)
|
|||
Images = model.Images,
|
||||
Links = model.Links,
|
||||
Ratings = model.Ratings,
|
||||
Artist = model.Author?.Value.ToResource()
|
||||
Author = model.Author?.Value.ToResource()
|
||||
};
|
||||
}
|
||||
|
||||
public static Book ToModel(this AlbumResource resource)
|
||||
public static Book ToModel(this BookResource resource)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var artist = resource.Artist?.ToModel() ?? new NzbDrone.Core.Books.Author();
|
||||
var author = resource.Author?.ToModel() ?? new NzbDrone.Core.Books.Author();
|
||||
|
||||
return new Book
|
||||
{
|
||||
|
|
@ -97,26 +97,26 @@ public static Book ToModel(this AlbumResource resource)
|
|||
Images = resource.Images,
|
||||
Monitored = resource.Monitored,
|
||||
AddOptions = resource.AddOptions,
|
||||
Author = artist,
|
||||
AuthorMetadata = artist.Metadata.Value
|
||||
Author = author,
|
||||
AuthorMetadata = author.Metadata.Value
|
||||
};
|
||||
}
|
||||
|
||||
public static Book ToModel(this AlbumResource resource, Book album)
|
||||
public static Book ToModel(this BookResource resource, Book book)
|
||||
{
|
||||
var updatedAlbum = resource.ToModel();
|
||||
var updatedBook = resource.ToModel();
|
||||
|
||||
album.ApplyChanges(updatedAlbum);
|
||||
book.ApplyChanges(updatedBook);
|
||||
|
||||
return album;
|
||||
return book;
|
||||
}
|
||||
|
||||
public static List<AlbumResource> ToResource(this IEnumerable<Book> models)
|
||||
public static List<BookResource> ToResource(this IEnumerable<Book> models)
|
||||
{
|
||||
return models?.Select(ToResource).ToList();
|
||||
}
|
||||
|
||||
public static List<Book> ToModel(this IEnumerable<AlbumResource> resources)
|
||||
public static List<Book> ToModel(this IEnumerable<BookResource> resources)
|
||||
{
|
||||
return resources.Select(ToModel).ToList();
|
||||
}
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
using NzbDrone.Core.AuthorStats;
|
||||
|
||||
namespace Readarr.Api.V1.Artist
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public class ArtistStatisticsResource
|
||||
public class BookStatisticsResource
|
||||
{
|
||||
public int BookCount { get; set; }
|
||||
public int BookFileCount { get; set; }
|
||||
public int TrackCount { get; set; }
|
||||
public int BookCount { get; set; }
|
||||
public int TotalTrackCount { get; set; }
|
||||
public long SizeOnDisk { get; set; }
|
||||
|
||||
|
|
@ -14,29 +13,29 @@ public decimal PercentOfTracks
|
|||
{
|
||||
get
|
||||
{
|
||||
if (TrackCount == 0)
|
||||
if (BookCount == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BookFileCount / (decimal)TrackCount * 100;
|
||||
return BookFileCount / (decimal)BookCount * 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArtistStatisticsResourceMapper
|
||||
public static class BookStatisticsResourceMapper
|
||||
{
|
||||
public static ArtistStatisticsResource ToResource(this AuthorStatistics model)
|
||||
public static BookStatisticsResource ToResource(this BookStatistics model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ArtistStatisticsResource
|
||||
return new BookStatisticsResource
|
||||
{
|
||||
BookCount = model.BookCount,
|
||||
BookFileCount = model.BookFileCount,
|
||||
BookCount = model.BookCount,
|
||||
SizeOnDisk = model.SizeOnDisk
|
||||
};
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public class AlbumsMonitoredResource
|
||||
public class BooksMonitoredResource
|
||||
{
|
||||
public List<int> BookIds { get; set; }
|
||||
public bool Monitored { get; set; }
|
||||
|
|
@ -3,21 +3,21 @@
|
|||
using Readarr.Http;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public class RenameTrackModule : ReadarrRestModule<RenameTrackResource>
|
||||
public class RenameBookModule : ReadarrRestModule<RenameBookResource>
|
||||
{
|
||||
private readonly IRenameTrackFileService _renameTrackFileService;
|
||||
private readonly IRenameBookFileService _renameBookFileService;
|
||||
|
||||
public RenameTrackModule(IRenameTrackFileService renameTrackFileService)
|
||||
public RenameBookModule(IRenameBookFileService renameBookFileService)
|
||||
: base("rename")
|
||||
{
|
||||
_renameTrackFileService = renameTrackFileService;
|
||||
_renameBookFileService = renameBookFileService;
|
||||
|
||||
GetResourceAll = GetTracks;
|
||||
GetResourceAll = GetBookFiles;
|
||||
}
|
||||
|
||||
private List<RenameTrackResource> GetTracks()
|
||||
private List<RenameBookResource> GetBookFiles()
|
||||
{
|
||||
int authorId;
|
||||
|
||||
|
|
@ -33,10 +33,10 @@ private List<RenameTrackResource> GetTracks()
|
|||
if (Request.Query.bookId.HasValue)
|
||||
{
|
||||
var bookId = (int)Request.Query.bookId;
|
||||
return _renameTrackFileService.GetRenamePreviews(authorId, bookId).ToResource();
|
||||
return _renameBookFileService.GetRenamePreviews(authorId, bookId).ToResource();
|
||||
}
|
||||
|
||||
return _renameTrackFileService.GetRenamePreviews(authorId).ToResource();
|
||||
return _renameBookFileService.GetRenamePreviews(authorId).ToResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,37 +2,37 @@
|
|||
using System.Linq;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public class RenameTrackResource : RestResource
|
||||
public class RenameBookResource : RestResource
|
||||
{
|
||||
public int AuthorId { get; set; }
|
||||
public int BookId { get; set; }
|
||||
public int TrackFileId { get; set; }
|
||||
public int BookFileId { get; set; }
|
||||
public string ExistingPath { get; set; }
|
||||
public string NewPath { get; set; }
|
||||
}
|
||||
|
||||
public static class RenameTrackResourceMapper
|
||||
public static class RenameBookResourceMapper
|
||||
{
|
||||
public static RenameTrackResource ToResource(this NzbDrone.Core.MediaFiles.RenameBookFilePreview model)
|
||||
public static RenameBookResource ToResource(this NzbDrone.Core.MediaFiles.RenameBookFilePreview model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RenameTrackResource
|
||||
return new RenameBookResource
|
||||
{
|
||||
AuthorId = model.AuthorId,
|
||||
BookId = model.BookId,
|
||||
TrackFileId = model.BookFileId,
|
||||
BookFileId = model.BookFileId,
|
||||
ExistingPath = model.ExistingPath,
|
||||
NewPath = model.NewPath
|
||||
};
|
||||
}
|
||||
|
||||
public static List<RenameTrackResource> ToResource(this IEnumerable<NzbDrone.Core.MediaFiles.RenameBookFilePreview> models)
|
||||
public static List<RenameBookResource> ToResource(this IEnumerable<NzbDrone.Core.MediaFiles.RenameBookFilePreview> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
|
|
@ -4,21 +4,21 @@
|
|||
using Readarr.Http;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public class RetagTrackModule : ReadarrRestModule<RetagTrackResource>
|
||||
public class RetagBookModule : ReadarrRestModule<RetagBookResource>
|
||||
{
|
||||
private readonly IAudioTagService _audioTagService;
|
||||
|
||||
public RetagTrackModule(IAudioTagService audioTagService)
|
||||
public RetagBookModule(IAudioTagService audioTagService)
|
||||
: base("retag")
|
||||
{
|
||||
_audioTagService = audioTagService;
|
||||
|
||||
GetResourceAll = GetTracks;
|
||||
GetResourceAll = GetBooks;
|
||||
}
|
||||
|
||||
private List<RetagTrackResource> GetTracks()
|
||||
private List<RetagBookResource> GetBooks()
|
||||
{
|
||||
if (Request.Query.bookId.HasValue)
|
||||
{
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
using System.Linq;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Albums
|
||||
namespace Readarr.Api.V1.Books
|
||||
{
|
||||
public class TagDifference
|
||||
{
|
||||
|
|
@ -11,31 +11,31 @@ public class TagDifference
|
|||
public string NewValue { get; set; }
|
||||
}
|
||||
|
||||
public class RetagTrackResource : RestResource
|
||||
public class RetagBookResource : RestResource
|
||||
{
|
||||
public int AuthorId { get; set; }
|
||||
public int BookId { get; set; }
|
||||
public List<int> TrackNumbers { get; set; }
|
||||
public int TrackFileId { get; set; }
|
||||
public int BookFileId { get; set; }
|
||||
public string Path { get; set; }
|
||||
public List<TagDifference> Changes { get; set; }
|
||||
}
|
||||
|
||||
public static class RetagTrackResourceMapper
|
||||
{
|
||||
public static RetagTrackResource ToResource(this NzbDrone.Core.MediaFiles.RetagBookFilePreview model)
|
||||
public static RetagBookResource ToResource(this NzbDrone.Core.MediaFiles.RetagBookFilePreview model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RetagTrackResource
|
||||
return new RetagBookResource
|
||||
{
|
||||
AuthorId = model.AuthorId,
|
||||
BookId = model.BookId,
|
||||
TrackNumbers = model.TrackNumbers.ToList(),
|
||||
TrackFileId = model.BookFileId,
|
||||
BookFileId = model.BookFileId,
|
||||
Path = model.Path,
|
||||
Changes = model.Changes.Select(x => new TagDifference
|
||||
{
|
||||
|
|
@ -46,7 +46,7 @@ public static RetagTrackResource ToResource(this NzbDrone.Core.MediaFiles.RetagB
|
|||
};
|
||||
}
|
||||
|
||||
public static List<RetagTrackResource> ToResource(this IEnumerable<NzbDrone.Core.MediaFiles.RetagBookFilePreview> models)
|
||||
public static List<RetagBookResource> ToResource(this IEnumerable<NzbDrone.Core.MediaFiles.RetagBookFilePreview> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
|
|
@ -61,35 +61,35 @@ private object GetCalendarFeed()
|
|||
tags.AddRange(tagInput.Split(',').Select(_tagService.GetTag).Select(t => t.Id));
|
||||
}
|
||||
|
||||
var albums = _bookService.BooksBetweenDates(start, end, unmonitored);
|
||||
var books = _bookService.BooksBetweenDates(start, end, unmonitored);
|
||||
var calendar = new Ical.Net.Calendar
|
||||
{
|
||||
ProductId = "-//readarr.com//Readarr//EN"
|
||||
};
|
||||
|
||||
var calendarName = "Readarr Music Schedule";
|
||||
var calendarName = "Readarr Book Schedule";
|
||||
calendar.AddProperty(new CalendarProperty("NAME", calendarName));
|
||||
calendar.AddProperty(new CalendarProperty("X-WR-CALNAME", calendarName));
|
||||
|
||||
foreach (var album in albums.OrderBy(v => v.ReleaseDate.Value))
|
||||
foreach (var book in books.OrderBy(v => v.ReleaseDate.Value))
|
||||
{
|
||||
var artist = _authorService.GetAuthor(album.AuthorId); // Temp fix TODO: Figure out why Album.Artist is not populated during AlbumsBetweenDates Query
|
||||
var author = _authorService.GetAuthor(book.AuthorId); // Temp fix TODO: Figure out why Album.Artist is not populated during AlbumsBetweenDates Query
|
||||
|
||||
if (tags.Any() && tags.None(artist.Tags.Contains))
|
||||
if (tags.Any() && tags.None(author.Tags.Contains))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var occurrence = calendar.Create<CalendarEvent>();
|
||||
occurrence.Uid = "Readarr_album_" + album.Id;
|
||||
occurrence.Uid = "Readarr_book_" + book.Id;
|
||||
|
||||
//occurrence.Status = album.HasFile ? EventStatus.Confirmed : EventStatus.Tentative;
|
||||
occurrence.Description = album.Overview;
|
||||
occurrence.Categories = album.Genres;
|
||||
occurrence.Description = book.Overview;
|
||||
occurrence.Categories = book.Genres;
|
||||
|
||||
occurrence.Start = new CalDateTime(album.ReleaseDate.Value.ToLocalTime()) { HasTime = false };
|
||||
occurrence.Start = new CalDateTime(book.ReleaseDate.Value.ToLocalTime()) { HasTime = false };
|
||||
|
||||
occurrence.Summary = $"{artist.Name} - {album.Title}";
|
||||
occurrence.Summary = $"{author.Name} - {book.Title}";
|
||||
}
|
||||
|
||||
var serializer = (IStringSerializer)new SerializerFactory().Build(calendar.GetType(), new SerializationContext());
|
||||
|
|
|
|||
|
|
@ -6,32 +6,32 @@
|
|||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.SignalR;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Calendar
|
||||
{
|
||||
public class CalendarModule : AlbumModuleWithSignalR
|
||||
public class CalendarModule : BookModuleWithSignalR
|
||||
{
|
||||
public CalendarModule(IBookService bookService,
|
||||
IAuthorStatisticsService artistStatisticsService,
|
||||
IAuthorStatisticsService authorStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(bookService, artistStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster, "calendar")
|
||||
: base(bookService, authorStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster, "calendar")
|
||||
{
|
||||
GetResourceAll = GetCalendar;
|
||||
}
|
||||
|
||||
private List<AlbumResource> GetCalendar()
|
||||
private List<BookResource> GetCalendar()
|
||||
{
|
||||
var start = DateTime.Today;
|
||||
var end = DateTime.Today.AddDays(2);
|
||||
var includeUnmonitored = Request.GetBooleanQueryParameter("unmonitored");
|
||||
var includeArtist = Request.GetBooleanQueryParameter("includeArtist");
|
||||
var includeAuthor = Request.GetBooleanQueryParameter("includeAuthor");
|
||||
|
||||
//TODO: Add Album Image support to AlbumModuleWithSignalR
|
||||
var includeAlbumImages = Request.GetBooleanQueryParameter("includeAlbumImages");
|
||||
var includeBookImages = Request.GetBooleanQueryParameter("includeBookImages");
|
||||
|
||||
var queryStart = Request.Query.Start;
|
||||
var queryEnd = Request.Query.End;
|
||||
|
|
@ -46,7 +46,7 @@ private List<AlbumResource> GetCalendar()
|
|||
end = DateTime.Parse(queryEnd.Value);
|
||||
}
|
||||
|
||||
var resources = MapToResource(_bookService.BooksBetweenDates(start, end, includeUnmonitored), includeArtist);
|
||||
var resources = MapToResource(_bookService.BooksBetweenDates(start, end, includeUnmonitored), includeAuthor);
|
||||
|
||||
return resources.OrderBy(e => e.ReleaseDate).ToList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ namespace Readarr.Api.V1.Config
|
|||
{
|
||||
public class MediaManagementConfigResource : RestResource
|
||||
{
|
||||
public bool AutoUnmonitorPreviouslyDownloadedTracks { get; set; }
|
||||
public bool AutoUnmonitorPreviouslyDownloadedBooks { get; set; }
|
||||
public string RecycleBin { get; set; }
|
||||
public int RecycleBinCleanupDays { get; set; }
|
||||
public ProperDownloadTypes DownloadPropersAndRepacks { get; set; }
|
||||
public bool CreateEmptyArtistFolders { get; set; }
|
||||
public bool CreateEmptyAuthorFolders { get; set; }
|
||||
public bool DeleteEmptyFolders { get; set; }
|
||||
public FileDateType FileDate { get; set; }
|
||||
public bool WatchLibraryForChanges { get; set; }
|
||||
|
|
@ -37,11 +37,11 @@ public static MediaManagementConfigResource ToResource(IConfigService model)
|
|||
{
|
||||
return new MediaManagementConfigResource
|
||||
{
|
||||
AutoUnmonitorPreviouslyDownloadedTracks = model.AutoUnmonitorPreviouslyDownloadedTracks,
|
||||
AutoUnmonitorPreviouslyDownloadedBooks = model.AutoUnmonitorPreviouslyDownloadedBooks,
|
||||
RecycleBin = model.RecycleBin,
|
||||
RecycleBinCleanupDays = model.RecycleBinCleanupDays,
|
||||
DownloadPropersAndRepacks = model.DownloadPropersAndRepacks,
|
||||
CreateEmptyArtistFolders = model.CreateEmptyArtistFolders,
|
||||
CreateEmptyAuthorFolders = model.CreateEmptyAuthorFolders,
|
||||
DeleteEmptyFolders = model.DeleteEmptyFolders,
|
||||
FileDate = model.FileDate,
|
||||
WatchLibraryForChanges = model.WatchLibraryForChanges,
|
||||
|
|
|
|||
|
|
@ -75,11 +75,11 @@ private object GetExamples(NamingConfigResource config)
|
|||
|
||||
var singleTrackSampleResult = _filenameSampleService.GetStandardTrackSample(nameSpec);
|
||||
|
||||
sampleResource.SingleTrackExample = _filenameValidationService.ValidateTrackFilename(singleTrackSampleResult) != null
|
||||
sampleResource.SingleBookExample = _filenameValidationService.ValidateTrackFilename(singleTrackSampleResult) != null
|
||||
? null
|
||||
: singleTrackSampleResult.FileName;
|
||||
|
||||
sampleResource.ArtistFolderExample = nameSpec.AuthorFolderFormat.IsNullOrWhiteSpace()
|
||||
sampleResource.AuthorFolderExample = nameSpec.AuthorFolderFormat.IsNullOrWhiteSpace()
|
||||
? null
|
||||
: _filenameSampleService.GetAuthorFolderSample(nameSpec);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ namespace Readarr.Api.V1.Config
|
|||
{
|
||||
public class NamingExampleResource
|
||||
{
|
||||
public string SingleTrackExample { get; set; }
|
||||
public string ArtistFolderExample { get; set; }
|
||||
public string SingleBookExample { get; set; }
|
||||
public string AuthorFolderExample { get; set; }
|
||||
}
|
||||
|
||||
public static class NamingConfigResourceMapper
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http;
|
||||
using Readarr.Http.Extensions;
|
||||
using Readarr.Http.REST;
|
||||
|
|
@ -30,7 +30,7 @@ public HistoryModule(IHistoryService historyService,
|
|||
GetResourcePaged = GetHistory;
|
||||
|
||||
Get("/since", x => GetHistorySince());
|
||||
Get("/artist", x => GetArtistHistory());
|
||||
Get("/author", x => GetArtistHistory());
|
||||
Post("/failed", x => MarkAsFailed());
|
||||
}
|
||||
|
||||
|
|
@ -40,12 +40,12 @@ protected HistoryResource MapToResource(NzbDrone.Core.History.History model, boo
|
|||
|
||||
if (includeArtist)
|
||||
{
|
||||
resource.Artist = model.Author.ToResource();
|
||||
resource.Author = model.Author.ToResource();
|
||||
}
|
||||
|
||||
if (includeAlbum)
|
||||
{
|
||||
resource.Album = model.Book.ToResource();
|
||||
resource.Book = model.Book.ToResource();
|
||||
}
|
||||
|
||||
if (model.Author != null)
|
||||
|
|
@ -59,8 +59,8 @@ protected HistoryResource MapToResource(NzbDrone.Core.History.History model, boo
|
|||
private PagingResource<HistoryResource> GetHistory(PagingResource<HistoryResource> pagingResource)
|
||||
{
|
||||
var pagingSpec = pagingResource.MapToPagingSpec<HistoryResource, NzbDrone.Core.History.History>("date", SortDirection.Descending);
|
||||
var includeArtist = Request.GetBooleanQueryParameter("includeArtist");
|
||||
var includeAlbum = Request.GetBooleanQueryParameter("includeAlbum");
|
||||
var includeAuthor = Request.GetBooleanQueryParameter("includeAuthor");
|
||||
var includeBook = Request.GetBooleanQueryParameter("includeBook");
|
||||
|
||||
var eventTypeFilter = pagingResource.Filters.FirstOrDefault(f => f.Key == "eventType");
|
||||
var bookIdFilter = pagingResource.Filters.FirstOrDefault(f => f.Key == "bookId");
|
||||
|
|
@ -84,7 +84,7 @@ private PagingResource<HistoryResource> GetHistory(PagingResource<HistoryResourc
|
|||
pagingSpec.FilterExpressions.Add(h => h.DownloadId == downloadId);
|
||||
}
|
||||
|
||||
return ApplyToPage(_historyService.Paged, pagingSpec, h => MapToResource(h, includeArtist, includeAlbum));
|
||||
return ApplyToPage(_historyService.Paged, pagingSpec, h => MapToResource(h, includeAuthor, includeBook));
|
||||
}
|
||||
|
||||
private List<HistoryResource> GetHistorySince()
|
||||
|
|
@ -99,15 +99,15 @@ private List<HistoryResource> GetHistorySince()
|
|||
|
||||
DateTime date = DateTime.Parse(queryDate.Value);
|
||||
HistoryEventType? eventType = null;
|
||||
var includeArtist = Request.GetBooleanQueryParameter("includeArtist");
|
||||
var includeAlbum = Request.GetBooleanQueryParameter("includeAlbum");
|
||||
var includeAuthor = Request.GetBooleanQueryParameter("includeAuthor");
|
||||
var includeBook = Request.GetBooleanQueryParameter("includeBook");
|
||||
|
||||
if (queryEventType.HasValue)
|
||||
{
|
||||
eventType = (HistoryEventType)Convert.ToInt32(queryEventType.Value);
|
||||
}
|
||||
|
||||
return _historyService.Since(date, eventType).Select(h => MapToResource(h, includeArtist, includeAlbum)).ToList();
|
||||
return _historyService.Since(date, eventType).Select(h => MapToResource(h, includeAuthor, includeBook)).ToList();
|
||||
}
|
||||
|
||||
private List<HistoryResource> GetArtistHistory()
|
||||
|
|
@ -123,8 +123,8 @@ private List<HistoryResource> GetArtistHistory()
|
|||
|
||||
int authorId = Convert.ToInt32(queryAuthorId.Value);
|
||||
HistoryEventType? eventType = null;
|
||||
var includeArtist = Request.GetBooleanQueryParameter("includeArtist");
|
||||
var includeAlbum = Request.GetBooleanQueryParameter("includeAlbum");
|
||||
var includeAuthor = Request.GetBooleanQueryParameter("includeAuthor");
|
||||
var includeBook = Request.GetBooleanQueryParameter("includeBook");
|
||||
|
||||
if (queryEventType.HasValue)
|
||||
{
|
||||
|
|
@ -135,10 +135,10 @@ private List<HistoryResource> GetArtistHistory()
|
|||
{
|
||||
int bookId = Convert.ToInt32(queryBookId.Value);
|
||||
|
||||
return _historyService.GetByBook(bookId, eventType).Select(h => MapToResource(h, includeArtist, includeAlbum)).ToList();
|
||||
return _historyService.GetByBook(bookId, eventType).Select(h => MapToResource(h, includeAuthor, includeBook)).ToList();
|
||||
}
|
||||
|
||||
return _historyService.GetByAuthor(authorId, eventType).Select(h => MapToResource(h, includeArtist, includeAlbum)).ToList();
|
||||
return _historyService.GetByAuthor(authorId, eventType).Select(h => MapToResource(h, includeAuthor, includeBook)).ToList();
|
||||
}
|
||||
|
||||
private object MarkAsFailed()
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.History
|
||||
|
|
@ -22,8 +22,8 @@ public class HistoryResource : RestResource
|
|||
|
||||
public Dictionary<string, string> Data { get; set; }
|
||||
|
||||
public AlbumResource Album { get; set; }
|
||||
public ArtistResource Artist { get; set; }
|
||||
public BookResource Book { get; set; }
|
||||
public AuthorResource Author { get; set; }
|
||||
}
|
||||
|
||||
public static class HistoryResourceMapper
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public ImportListExclusionModule(IImportListExclusionService importListExclusion
|
|||
DeleteResource = DeleteImportListExclusionResource;
|
||||
|
||||
SharedValidator.RuleFor(c => c.ForeignId).NotEmpty().SetValidator(guidValidator).SetValidator(importListExclusionExistsValidator);
|
||||
SharedValidator.RuleFor(c => c.ArtistName).NotEmpty();
|
||||
SharedValidator.RuleFor(c => c.AuthorName).NotEmpty();
|
||||
}
|
||||
|
||||
private ImportListExclusionResource GetImportListExclusion(int id)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace Readarr.Api.V1.ImportLists
|
|||
public class ImportListExclusionResource : RestResource
|
||||
{
|
||||
public string ForeignId { get; set; }
|
||||
public string ArtistName { get; set; }
|
||||
public string AuthorName { get; set; }
|
||||
}
|
||||
|
||||
public static class ImportListExclusionResourceMapper
|
||||
|
|
@ -24,7 +24,7 @@ public static ImportListExclusionResource ToResource(this ImportListExclusion mo
|
|||
{
|
||||
Id = model.Id,
|
||||
ForeignId = model.ForeignId,
|
||||
ArtistName = model.Name,
|
||||
AuthorName = model.Name,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ public static ImportListExclusion ToModel(this ImportListExclusionResource resou
|
|||
{
|
||||
Id = resource.Id,
|
||||
ForeignId = resource.ForeignId,
|
||||
Name = resource.ArtistName
|
||||
Name = resource.AuthorName
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class ReleaseModule : ReleaseModuleBase
|
|||
private readonly IDownloadService _downloadService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private readonly ICached<RemoteBook> _remoteAlbumCache;
|
||||
private readonly ICached<RemoteBook> _remoteBookCache;
|
||||
|
||||
public ReleaseModule(IFetchAndParseRss rssFetcherAndParser,
|
||||
ISearchForNzb nzbSearchService,
|
||||
|
|
@ -47,12 +47,12 @@ public ReleaseModule(IFetchAndParseRss rssFetcherAndParser,
|
|||
PostValidator.RuleFor(s => s.IndexerId).ValidId();
|
||||
PostValidator.RuleFor(s => s.Guid).NotEmpty();
|
||||
|
||||
_remoteAlbumCache = cacheManager.GetCache<RemoteBook>(GetType(), "remoteAlbums");
|
||||
_remoteBookCache = cacheManager.GetCache<RemoteBook>(GetType(), "remoteBooks");
|
||||
}
|
||||
|
||||
private object DownloadRelease(ReleaseResource release)
|
||||
{
|
||||
var remoteAlbum = _remoteAlbumCache.Find(GetCacheKey(release));
|
||||
var remoteAlbum = _remoteBookCache.Find(GetCacheKey(release));
|
||||
|
||||
if (remoteAlbum == null)
|
||||
{
|
||||
|
|
@ -78,46 +78,46 @@ private List<ReleaseResource> GetReleases()
|
|||
{
|
||||
if (Request.Query.bookId.HasValue)
|
||||
{
|
||||
return GetAlbumReleases(Request.Query.bookId);
|
||||
return GetBookReleases(Request.Query.bookId);
|
||||
}
|
||||
|
||||
if (Request.Query.authorId.HasValue)
|
||||
{
|
||||
return GetArtistReleases(Request.Query.authorId);
|
||||
return GetAuthorReleases(Request.Query.authorId);
|
||||
}
|
||||
|
||||
return GetRss();
|
||||
}
|
||||
|
||||
private List<ReleaseResource> GetAlbumReleases(int bookId)
|
||||
private List<ReleaseResource> GetBookReleases(int bookId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var decisions = _nzbSearchService.AlbumSearch(bookId, true, true, true);
|
||||
var decisions = _nzbSearchService.BookSearch(bookId, true, true, true);
|
||||
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(decisions);
|
||||
|
||||
return MapDecisions(prioritizedDecisions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Album search failed");
|
||||
_logger.Error(ex, "Book search failed");
|
||||
}
|
||||
|
||||
return new List<ReleaseResource>();
|
||||
}
|
||||
|
||||
private List<ReleaseResource> GetArtistReleases(int authorId)
|
||||
private List<ReleaseResource> GetAuthorReleases(int authorId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var decisions = _nzbSearchService.ArtistSearch(authorId, false, true, true);
|
||||
var decisions = _nzbSearchService.AuthorSearch(authorId, false, true, true);
|
||||
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(decisions);
|
||||
|
||||
return MapDecisions(prioritizedDecisions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Artist search failed");
|
||||
_logger.Error(ex, "Author search failed");
|
||||
}
|
||||
|
||||
return new List<ReleaseResource>();
|
||||
|
|
@ -135,7 +135,7 @@ private List<ReleaseResource> GetRss()
|
|||
protected override ReleaseResource MapDecision(DownloadDecision decision, int initialWeight)
|
||||
{
|
||||
var resource = base.MapDecision(decision, initialWeight);
|
||||
_remoteAlbumCache.Set(GetCacheKey(resource), decision.RemoteBook, TimeSpan.FromMinutes(30));
|
||||
_remoteBookCache.Set(GetCacheKey(resource), decision.RemoteBook, TimeSpan.FromMinutes(30));
|
||||
return resource;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ public class ReleaseResource : RestResource
|
|||
public bool Discography { get; set; }
|
||||
public bool SceneSource { get; set; }
|
||||
public string AirDate { get; set; }
|
||||
public string ArtistName { get; set; }
|
||||
public string AlbumTitle { get; set; }
|
||||
public string AuthorName { get; set; }
|
||||
public string BookTitle { get; set; }
|
||||
public bool Approved { get; set; }
|
||||
public bool TemporarilyRejected { get; set; }
|
||||
public bool Rejected { get; set; }
|
||||
|
|
@ -65,15 +65,15 @@ public static class ReleaseResourceMapper
|
|||
public static ReleaseResource ToResource(this DownloadDecision model)
|
||||
{
|
||||
var releaseInfo = model.RemoteBook.Release;
|
||||
var parsedAlbumInfo = model.RemoteBook.ParsedBookInfo;
|
||||
var remoteAlbum = model.RemoteBook;
|
||||
var parsedBookInfo = model.RemoteBook.ParsedBookInfo;
|
||||
var remoteBook = model.RemoteBook;
|
||||
var torrentInfo = (model.RemoteBook.Release as TorrentInfo) ?? new TorrentInfo();
|
||||
|
||||
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead? (Got a huge Deja Vu, didn't we talk about this already once?)
|
||||
return new ReleaseResource
|
||||
{
|
||||
Guid = releaseInfo.Guid,
|
||||
Quality = parsedAlbumInfo.Quality,
|
||||
Quality = parsedBookInfo.Quality,
|
||||
|
||||
//QualityWeight
|
||||
Age = releaseInfo.Age,
|
||||
|
|
@ -82,12 +82,12 @@ public static ReleaseResource ToResource(this DownloadDecision model)
|
|||
Size = releaseInfo.Size,
|
||||
IndexerId = releaseInfo.IndexerId,
|
||||
Indexer = releaseInfo.Indexer,
|
||||
ReleaseGroup = parsedAlbumInfo.ReleaseGroup,
|
||||
ReleaseHash = parsedAlbumInfo.ReleaseHash,
|
||||
ReleaseGroup = parsedBookInfo.ReleaseGroup,
|
||||
ReleaseHash = parsedBookInfo.ReleaseHash,
|
||||
Title = releaseInfo.Title,
|
||||
ArtistName = parsedAlbumInfo.AuthorName,
|
||||
AlbumTitle = parsedAlbumInfo.BookTitle,
|
||||
Discography = parsedAlbumInfo.Discography,
|
||||
AuthorName = parsedBookInfo.AuthorName,
|
||||
BookTitle = parsedBookInfo.BookTitle,
|
||||
Discography = parsedBookInfo.Discography,
|
||||
Approved = model.Approved,
|
||||
TemporarilyRejected = model.TemporarilyRejected,
|
||||
Rejected = model.Rejected,
|
||||
|
|
@ -96,10 +96,10 @@ public static ReleaseResource ToResource(this DownloadDecision model)
|
|||
CommentUrl = releaseInfo.CommentUrl,
|
||||
DownloadUrl = releaseInfo.DownloadUrl,
|
||||
InfoUrl = releaseInfo.InfoUrl,
|
||||
DownloadAllowed = remoteAlbum.DownloadAllowed,
|
||||
DownloadAllowed = remoteBook.DownloadAllowed,
|
||||
|
||||
//ReleaseWeight
|
||||
PreferredWordScore = remoteAlbum.PreferredWordScore,
|
||||
PreferredWordScore = remoteBook.PreferredWordScore,
|
||||
|
||||
MagnetUrl = torrentInfo.MagnetUrl,
|
||||
InfoHash = torrentInfo.InfoHash,
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ private List<ManualImportResource> UpdateImportItems(List<ManualImportResource>
|
|||
Path = resource.Path,
|
||||
Name = resource.Name,
|
||||
Size = resource.Size,
|
||||
Author = resource.Artist == null ? null : _authorService.GetAuthor(resource.Artist.Id),
|
||||
Book = resource.Album == null ? null : _bookService.GetBook(resource.Album.Id),
|
||||
Author = resource.Author == null ? null : _authorService.GetAuthor(resource.Author.Id),
|
||||
Book = resource.Book == null ? null : _bookService.GetBook(resource.Book.Id),
|
||||
Quality = resource.Quality,
|
||||
DownloadId = resource.DownloadId,
|
||||
AdditionalFile = resource.AdditionalFile,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
using NzbDrone.Core.MediaFiles.BookImport.Manual;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.ManualImport
|
||||
|
|
@ -15,8 +15,8 @@ public class ManualImportResource : RestResource
|
|||
public string Path { get; set; }
|
||||
public string Name { get; set; }
|
||||
public long Size { get; set; }
|
||||
public ArtistResource Artist { get; set; }
|
||||
public AlbumResource Album { get; set; }
|
||||
public AuthorResource Author { get; set; }
|
||||
public BookResource Book { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public int QualityWeight { get; set; }
|
||||
public string DownloadId { get; set; }
|
||||
|
|
@ -41,8 +41,8 @@ public static ManualImportResource ToResource(this ManualImportItem model)
|
|||
Path = model.Path,
|
||||
Name = model.Name,
|
||||
Size = model.Size,
|
||||
Artist = model.Author.ToResource(),
|
||||
Album = model.Book.ToResource(),
|
||||
Author = model.Author.ToResource(),
|
||||
Book = model.Book.ToResource(),
|
||||
Quality = model.Quality,
|
||||
|
||||
//QualityWeight
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ namespace Readarr.Api.V1.MediaCovers
|
|||
{
|
||||
public class MediaCoverModule : ReadarrV1Module
|
||||
{
|
||||
private const string MEDIA_COVER_ARTIST_ROUTE = @"/Artist/(?<authorId>\d+)/(?<filename>(.+)\.(jpg|png|gif))";
|
||||
private const string MEDIA_COVER_ALBUM_ROUTE = @"/Album/(?<authorId>\d+)/(?<filename>(.+)\.(jpg|png|gif))";
|
||||
private const string MEDIA_COVER_AUTHOR_ROUTE = @"/Author/(?<authorId>\d+)/(?<filename>(.+)\.(jpg|png|gif))";
|
||||
private const string MEDIA_COVER_BOOK_ROUTE = @"/Book/(?<authorId>\d+)/(?<filename>(.+)\.(jpg|png|gif))";
|
||||
|
||||
private static readonly Regex RegexResizedImage = new Regex(@"-\d+(?=\.(jpg|png|gif)$)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
|
|
@ -24,8 +24,8 @@ public MediaCoverModule(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider
|
|||
_appFolderInfo = appFolderInfo;
|
||||
_diskProvider = diskProvider;
|
||||
|
||||
Get(MEDIA_COVER_ARTIST_ROUTE, options => GetArtistMediaCover(options.authorId, options.filename));
|
||||
Get(MEDIA_COVER_ALBUM_ROUTE, options => GetAlbumMediaCover(options.authorId, options.filename));
|
||||
Get(MEDIA_COVER_AUTHOR_ROUTE, options => GetArtistMediaCover(options.authorId, options.filename));
|
||||
Get(MEDIA_COVER_BOOK_ROUTE, options => GetAlbumMediaCover(options.authorId, options.filename));
|
||||
}
|
||||
|
||||
private object GetArtistMediaCover(int authorId, string filename)
|
||||
|
|
@ -50,7 +50,7 @@ private object GetArtistMediaCover(int authorId, string filename)
|
|||
|
||||
private object GetAlbumMediaCover(int bookId, string filename)
|
||||
{
|
||||
var filePath = Path.Combine(_appFolderInfo.GetAppDataPath(), "MediaCover", "Albums", bookId.ToString(), filename);
|
||||
var filePath = Path.Combine(_appFolderInfo.GetAppDataPath(), "MediaCover", "Books", bookId.ToString(), filename);
|
||||
|
||||
if (!_diskProvider.FileExists(filePath) || _diskProvider.GetFileSize(filePath) == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using NzbDrone.Core.Parser;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http;
|
||||
|
||||
namespace Readarr.Api.V1.Parse
|
||||
|
|
@ -33,9 +33,9 @@ private ParseResource Parse()
|
|||
return new ParseResource
|
||||
{
|
||||
Title = title,
|
||||
ParsedAlbumInfo = remoteAlbum.ParsedBookInfo,
|
||||
Artist = remoteAlbum.Author.ToResource(),
|
||||
Albums = remoteAlbum.Books.ToResource()
|
||||
ParsedBookInfo = remoteAlbum.ParsedBookInfo,
|
||||
Author = remoteAlbum.Author.ToResource(),
|
||||
Books = remoteAlbum.Books.ToResource()
|
||||
};
|
||||
}
|
||||
else
|
||||
|
|
@ -43,7 +43,7 @@ private ParseResource Parse()
|
|||
return new ParseResource
|
||||
{
|
||||
Title = title,
|
||||
ParsedAlbumInfo = parsedAlbumInfo
|
||||
ParsedBookInfo = parsedAlbumInfo
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Parse
|
||||
|
|
@ -9,8 +9,8 @@ namespace Readarr.Api.V1.Parse
|
|||
public class ParseResource : RestResource
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public ParsedBookInfo ParsedAlbumInfo { get; set; }
|
||||
public ArtistResource Artist { get; set; }
|
||||
public List<AlbumResource> Albums { get; set; }
|
||||
public ParsedBookInfo ParsedBookInfo { get; set; }
|
||||
public AuthorResource Author { get; set; }
|
||||
public List<BookResource> Books { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ public QueueDetailsModule(IBroadcastSignalRMessage broadcastSignalRMessage, IQue
|
|||
|
||||
private List<QueueResource> GetQueue()
|
||||
{
|
||||
var includeArtist = Request.GetBooleanQueryParameter("includeArtist");
|
||||
var includeAlbum = Request.GetBooleanQueryParameter("includeAlbum", true);
|
||||
var includeAuthor = Request.GetBooleanQueryParameter("includeAuthor");
|
||||
var includeBook = Request.GetBooleanQueryParameter("includeBook", true);
|
||||
var queue = _queueService.GetQueue();
|
||||
var pending = _pendingReleaseService.GetPendingQueue();
|
||||
var fullQueue = queue.Concat(pending);
|
||||
|
|
@ -38,7 +38,7 @@ private List<QueueResource> GetQueue()
|
|||
|
||||
if (authorIdQuery.HasValue)
|
||||
{
|
||||
return fullQueue.Where(q => q.Author?.Id == (int)authorIdQuery).ToResource(includeArtist, includeAlbum);
|
||||
return fullQueue.Where(q => q.Author?.Id == (int)authorIdQuery).ToResource(includeAuthor, includeBook);
|
||||
}
|
||||
|
||||
if (bookIdsQuery.HasValue)
|
||||
|
|
@ -49,10 +49,10 @@ private List<QueueResource> GetQueue()
|
|||
.Select(e => Convert.ToInt32(e))
|
||||
.ToList();
|
||||
|
||||
return fullQueue.Where(q => q.Book != null && bookIds.Contains(q.Book.Id)).ToResource(includeArtist, includeAlbum);
|
||||
return fullQueue.Where(q => q.Book != null && bookIds.Contains(q.Book.Id)).ToResource(includeAuthor, includeBook);
|
||||
}
|
||||
|
||||
return fullQueue.ToResource(includeArtist, includeAlbum);
|
||||
return fullQueue.ToResource(includeAuthor, includeBook);
|
||||
}
|
||||
|
||||
public void Handle(QueueUpdatedEvent message)
|
||||
|
|
|
|||
|
|
@ -38,20 +38,20 @@ public QueueModule(IBroadcastSignalRMessage broadcastSignalRMessage,
|
|||
private PagingResource<QueueResource> GetQueue(PagingResource<QueueResource> pagingResource)
|
||||
{
|
||||
var pagingSpec = pagingResource.MapToPagingSpec<QueueResource, NzbDrone.Core.Queue.Queue>("timeleft", SortDirection.Ascending);
|
||||
var includeUnknownArtistItems = Request.GetBooleanQueryParameter("includeUnknownArtistItems");
|
||||
var includeArtist = Request.GetBooleanQueryParameter("includeArtist");
|
||||
var includeAlbum = Request.GetBooleanQueryParameter("includeAlbum");
|
||||
var includeUnknownAuthorItems = Request.GetBooleanQueryParameter("includeUnknownAuthorItems");
|
||||
var includeAuthor = Request.GetBooleanQueryParameter("includeAuthor");
|
||||
var includeBook = Request.GetBooleanQueryParameter("includeBook");
|
||||
|
||||
return ApplyToPage((spec) => GetQueue(spec, includeUnknownArtistItems), pagingSpec, (q) => MapToResource(q, includeArtist, includeAlbum));
|
||||
return ApplyToPage((spec) => GetQueue(spec, includeUnknownAuthorItems), pagingSpec, (q) => MapToResource(q, includeAuthor, includeBook));
|
||||
}
|
||||
|
||||
private PagingSpec<NzbDrone.Core.Queue.Queue> GetQueue(PagingSpec<NzbDrone.Core.Queue.Queue> pagingSpec, bool includeUnknownArtistItems)
|
||||
private PagingSpec<NzbDrone.Core.Queue.Queue> GetQueue(PagingSpec<NzbDrone.Core.Queue.Queue> pagingSpec, bool includeUnknownAuthorItems)
|
||||
{
|
||||
var ascending = pagingSpec.SortDirection == SortDirection.Ascending;
|
||||
var orderByFunc = GetOrderByFunc(pagingSpec);
|
||||
|
||||
var queue = _queueService.GetQueue();
|
||||
var filteredQueue = includeUnknownArtistItems ? queue : queue.Where(q => q.Author != null);
|
||||
var filteredQueue = includeUnknownAuthorItems ? queue : queue.Where(q => q.Author != null);
|
||||
var pending = _pendingReleaseService.GetPendingQueue();
|
||||
var fullQueue = filteredQueue.Concat(pending).ToList();
|
||||
IOrderedEnumerable<NzbDrone.Core.Queue.Queue> ordered;
|
||||
|
|
@ -122,11 +122,11 @@ private PagingResource<QueueResource> GetQueue(PagingResource<QueueResource> pag
|
|||
return q => q.Author?.SortName;
|
||||
case "title":
|
||||
return q => q.Title;
|
||||
case "album":
|
||||
case "book":
|
||||
return q => q.Book;
|
||||
case "books.title":
|
||||
case "book.title":
|
||||
return q => q.Book?.Title;
|
||||
case "album.releaseDate":
|
||||
case "book.releaseDate":
|
||||
return q => q.Book?.ReleaseDate;
|
||||
case "quality":
|
||||
return q => q.Quality;
|
||||
|
|
@ -138,9 +138,9 @@ private PagingResource<QueueResource> GetQueue(PagingResource<QueueResource> pag
|
|||
}
|
||||
}
|
||||
|
||||
private QueueResource MapToResource(NzbDrone.Core.Queue.Queue queueItem, bool includeArtist, bool includeAlbum)
|
||||
private QueueResource MapToResource(NzbDrone.Core.Queue.Queue queueItem, bool includeAuthor, bool includeBook)
|
||||
{
|
||||
return queueItem.ToResource(includeArtist, includeAlbum);
|
||||
return queueItem.ToResource(includeAuthor, includeBook);
|
||||
}
|
||||
|
||||
public void Handle(QueueUpdatedEvent message)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Queue
|
||||
|
|
@ -15,8 +15,8 @@ public class QueueResource : RestResource
|
|||
{
|
||||
public int? AuthorId { get; set; }
|
||||
public int? BookId { get; set; }
|
||||
public ArtistResource Artist { get; set; }
|
||||
public AlbumResource Album { get; set; }
|
||||
public AuthorResource Author { get; set; }
|
||||
public BookResource Book { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public decimal Size { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
|
@ -50,8 +50,8 @@ public static QueueResource ToResource(this NzbDrone.Core.Queue.Queue model, boo
|
|||
Id = model.Id,
|
||||
AuthorId = model.Author?.Id,
|
||||
BookId = model.Book?.Id,
|
||||
Artist = includeArtist && model.Author != null ? model.Author.ToResource() : null,
|
||||
Album = includeAlbum && model.Book != null ? model.Book.ToResource() : null,
|
||||
Author = includeArtist && model.Author != null ? model.Author.ToResource() : null,
|
||||
Book = includeAlbum && model.Book != null ? model.Book.ToResource() : null,
|
||||
Quality = model.Quality,
|
||||
Size = model.Size,
|
||||
Title = model.Title,
|
||||
|
|
@ -72,9 +72,9 @@ public static QueueResource ToResource(this NzbDrone.Core.Queue.Queue model, boo
|
|||
};
|
||||
}
|
||||
|
||||
public static List<QueueResource> ToResource(this IEnumerable<NzbDrone.Core.Queue.Queue> models, bool includeArtist, bool includeAlbum)
|
||||
public static List<QueueResource> ToResource(this IEnumerable<NzbDrone.Core.Queue.Queue> models, bool includeAuthor, bool includeBook)
|
||||
{
|
||||
return models.Select((m) => ToResource(m, includeArtist, includeAlbum)).ToList();
|
||||
return models.Select((m) => ToResource(m, includeAuthor, includeBook)).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
using Nancy;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http;
|
||||
|
||||
namespace Readarr.Api.V1.Search
|
||||
|
|
@ -37,26 +37,26 @@ private static IEnumerable<SearchResource> MapToResource(IEnumerable<object> res
|
|||
|
||||
if (result is NzbDrone.Core.Books.Author)
|
||||
{
|
||||
var artist = (NzbDrone.Core.Books.Author)result;
|
||||
resource.Artist = artist.ToResource();
|
||||
resource.ForeignId = artist.ForeignAuthorId;
|
||||
var author = (NzbDrone.Core.Books.Author)result;
|
||||
resource.Author = author.ToResource();
|
||||
resource.ForeignId = author.ForeignAuthorId;
|
||||
|
||||
var poster = artist.Metadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
var poster = author.Metadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
if (poster != null)
|
||||
{
|
||||
resource.Artist.RemotePoster = poster.Url;
|
||||
resource.Author.RemotePoster = poster.Url;
|
||||
}
|
||||
}
|
||||
else if (result is NzbDrone.Core.Books.Book)
|
||||
{
|
||||
var album = (NzbDrone.Core.Books.Book)result;
|
||||
resource.Album = album.ToResource();
|
||||
resource.ForeignId = album.ForeignBookId;
|
||||
var book = (NzbDrone.Core.Books.Book)result;
|
||||
resource.Book = book.ToResource();
|
||||
resource.ForeignId = book.ForeignBookId;
|
||||
|
||||
var cover = album.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Cover);
|
||||
var cover = book.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Cover);
|
||||
if (cover != null)
|
||||
{
|
||||
resource.Album.RemoteCover = cover.Url;
|
||||
resource.Book.RemoteCover = cover.Url;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Artist;
|
||||
using Readarr.Api.V1.Author;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http.REST;
|
||||
|
||||
namespace Readarr.Api.V1.Search
|
||||
|
|
@ -8,7 +8,7 @@ public class
|
|||
SearchResource : RestResource
|
||||
{
|
||||
public string ForeignId { get; set; }
|
||||
public ArtistResource Artist { get; set; }
|
||||
public AlbumResource Album { get; set; }
|
||||
public AuthorResource Author { get; set; }
|
||||
public BookResource Book { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,29 +5,29 @@
|
|||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.SignalR;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Wanted
|
||||
{
|
||||
public class CutoffModule : AlbumModuleWithSignalR
|
||||
public class CutoffModule : BookModuleWithSignalR
|
||||
{
|
||||
private readonly IBookCutoffService _albumCutoffService;
|
||||
private readonly IBookCutoffService _bookCutoffService;
|
||||
|
||||
public CutoffModule(IBookCutoffService albumCutoffService,
|
||||
public CutoffModule(IBookCutoffService bookCutoffService,
|
||||
IBookService bookService,
|
||||
IAuthorStatisticsService artistStatisticsService,
|
||||
IAuthorStatisticsService authorStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(bookService, artistStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
||||
: base(bookService, authorStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
||||
{
|
||||
_albumCutoffService = albumCutoffService;
|
||||
GetResourcePaged = GetCutoffUnmetAlbums;
|
||||
_bookCutoffService = bookCutoffService;
|
||||
GetResourcePaged = GetCutoffUnmetBooks;
|
||||
}
|
||||
|
||||
private PagingResource<AlbumResource> GetCutoffUnmetAlbums(PagingResource<AlbumResource> pagingResource)
|
||||
private PagingResource<BookResource> GetCutoffUnmetBooks(PagingResource<BookResource> pagingResource)
|
||||
{
|
||||
var pagingSpec = new PagingSpec<Book>
|
||||
{
|
||||
|
|
@ -37,7 +37,7 @@ private PagingResource<AlbumResource> GetCutoffUnmetAlbums(PagingResource<AlbumR
|
|||
SortDirection = pagingResource.SortDirection
|
||||
};
|
||||
|
||||
var includeArtist = Request.GetBooleanQueryParameter("includeArtist");
|
||||
var includeAuthor = Request.GetBooleanQueryParameter("includeAuthor");
|
||||
var filter = pagingResource.Filters.FirstOrDefault(f => f.Key == "monitored");
|
||||
|
||||
if (filter != null && filter.Value == "false")
|
||||
|
|
@ -49,7 +49,7 @@ private PagingResource<AlbumResource> GetCutoffUnmetAlbums(PagingResource<AlbumR
|
|||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Author.Value.Monitored == true);
|
||||
}
|
||||
|
||||
var resource = ApplyToPage(_albumCutoffService.BooksWhereCutoffUnmet, pagingSpec, v => MapToResource(v, includeArtist));
|
||||
var resource = ApplyToPage(_bookCutoffService.BooksWhereCutoffUnmet, pagingSpec, v => MapToResource(v, includeAuthor));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,25 +5,25 @@
|
|||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.SignalR;
|
||||
using Readarr.Api.V1.Albums;
|
||||
using Readarr.Api.V1.Books;
|
||||
using Readarr.Http;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace Readarr.Api.V1.Wanted
|
||||
{
|
||||
public class MissingModule : AlbumModuleWithSignalR
|
||||
public class MissingModule : BookModuleWithSignalR
|
||||
{
|
||||
public MissingModule(IBookService bookService,
|
||||
IAuthorStatisticsService artistStatisticsService,
|
||||
IAuthorStatisticsService authorStatisticsService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
IUpgradableSpecification upgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(bookService, artistStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||
: base(bookService, authorStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||
{
|
||||
GetResourcePaged = GetMissingAlbums;
|
||||
GetResourcePaged = GetMissingBooks;
|
||||
}
|
||||
|
||||
private PagingResource<AlbumResource> GetMissingAlbums(PagingResource<AlbumResource> pagingResource)
|
||||
private PagingResource<BookResource> GetMissingBooks(PagingResource<BookResource> pagingResource)
|
||||
{
|
||||
var pagingSpec = new PagingSpec<Book>
|
||||
{
|
||||
|
|
@ -33,7 +33,7 @@ private PagingResource<AlbumResource> GetMissingAlbums(PagingResource<AlbumResou
|
|||
SortDirection = pagingResource.SortDirection
|
||||
};
|
||||
|
||||
var includeArtist = Request.GetBooleanQueryParameter("includeArtist");
|
||||
var includeAuthor = Request.GetBooleanQueryParameter("includeAuthor");
|
||||
var monitoredFilter = pagingResource.Filters.FirstOrDefault(f => f.Key == "monitored");
|
||||
|
||||
if (monitoredFilter != null && monitoredFilter.Value == "false")
|
||||
|
|
@ -45,7 +45,7 @@ private PagingResource<AlbumResource> GetMissingAlbums(PagingResource<AlbumResou
|
|||
pagingSpec.FilterExpressions.Add(v => v.Monitored == true && v.Author.Value.Monitored == true);
|
||||
}
|
||||
|
||||
var resource = ApplyToPage(_bookService.BooksWithoutFiles, pagingSpec, v => MapToResource(v, includeArtist));
|
||||
var resource = ApplyToPage(_bookService.BooksWithoutFiles, pagingSpec, v => MapToResource(v, includeAuthor));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue