From 82f3d2da51382cf252b432ea63f81bcf71ee242a Mon Sep 17 00:00:00 2001 From: Cody Kickertz Date: Sun, 21 Dec 2025 19:51:20 -0600 Subject: [PATCH] feat(qualities): add book and audiobook quality definitions (#120) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(db): add MediaType discriminator to Movies table Adds foundation for multi-media support by: - Adding MediaType column to Movies table (migration 244) - Adding MediaType property to Movie entity, defaulting to Movie Existing movies will have MediaType=1 (Movie) after migration. This prepares for future Book and Audiobook media types. Addresses Issue #1 * refactor(core): create MediaItem abstract base class Extracts common properties from Movie into a new MediaItem base class: - MediaType, Monitored, QualityProfileId - Path, RootFolderPath, Added, Tags, LastSearchTime Movie now inherits from MediaItem and implements abstract methods GetTitle() and GetYear() while maintaining backward-compatible Title/Year property accessors. This prepares for Book and Audiobook entities that will share the same base structure. Addresses Issue #1 * feat(core): add Author and Series entities for hierarchical monitoring Introduces hierarchical structure for books/audiobooks: - Author entity: tracks authors with monitoring, quality profiles, paths - Series entity: groups books/audiobooks by series, linked to Author - MediaItem: adds AuthorId and SeriesId for hierarchy support - Migration 245: creates Authors and Series tables, adds columns to Movies This enables Author → Series → Item monitoring inheritance for future book and audiobook support. Addresses Issue #2 * feat(core): add generic IProvideMediaInfo interface Introduces generic metadata provider interfaces: - IProvideMediaInfo: Base interface for all metadata providers - GetByExternalId, GetById, GetBulkInfo - GetTrending, GetPopular, GetChangedItems - ISearchableMediaProvider: Search capability interface - SearchByTitle with optional year filtering These interfaces establish the contract for future book and audiobook metadata providers while maintaining compatibility with the existing IProvideMovieInfo. Addresses Issue #3 * feat(qualities): add book and audiobook quality definitions Add quality source types and definitions for eBooks and audiobooks: - EBOOK source: Unknown, EPUB, MOBI, AZW3, PDF, TXT - AUDIOBOOK source: Unknown, MP3-128, MP3-320, M4B, FLAC Quality definitions include appropriate size limits for each format. New qualities auto-seed to database via QualityDefinitionService on startup. Closes #4, Closes #5 --------- Co-authored-by: admin --- src/NzbDrone.Core/Qualities/Quality.cs | 49 +++++++++++++++++++- src/NzbDrone.Core/Qualities/QualitySource.cs | 4 +- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/NzbDrone.Core/Qualities/Quality.cs b/src/NzbDrone.Core/Qualities/Quality.cs index 6b4819e877..bfee306c55 100644 --- a/src/NzbDrone.Core/Qualities/Quality.cs +++ b/src/NzbDrone.Core/Qualities/Quality.cs @@ -123,6 +123,21 @@ public override bool Equals(object obj) public static Quality WEBRip1080p => new Quality(15, "WEBRip-1080p", QualitySource.WEBRIP, 1080); public static Quality WEBRip2160p => new Quality(17, "WEBRip-2160p", QualitySource.WEBRIP, 2160); + // Book Qualities (IDs 100-109) + public static Quality EbookUnknown => new Quality(100, "Unknown eBook", QualitySource.EBOOK, 0); + public static Quality EPUB => new Quality(101, "EPUB", QualitySource.EBOOK, 0); + public static Quality MOBI => new Quality(102, "MOBI", QualitySource.EBOOK, 0); + public static Quality AZW3 => new Quality(103, "AZW3", QualitySource.EBOOK, 0); + public static Quality PDF => new Quality(104, "PDF", QualitySource.EBOOK, 0); + public static Quality TXT => new Quality(105, "TXT", QualitySource.EBOOK, 0); + + // Audiobook Qualities (IDs 200-209) + public static Quality AudiobookUnknown => new Quality(200, "Unknown Audiobook", QualitySource.AUDIOBOOK, 0); + public static Quality MP3_128 => new Quality(201, "MP3-128", QualitySource.AUDIOBOOK, 128); + public static Quality MP3_320 => new Quality(202, "MP3-320", QualitySource.AUDIOBOOK, 320); + public static Quality M4B => new Quality(203, "M4B", QualitySource.AUDIOBOOK, 256); + public static Quality AudioFLAC => new Quality(204, "FLAC", QualitySource.AUDIOBOOK, 1411); + static Quality() { All = new List @@ -156,7 +171,22 @@ static Quality() Remux1080p, Remux2160p, BRDISK, - RAWHD + RAWHD, + + // Book qualities + EbookUnknown, + EPUB, + MOBI, + AZW3, + PDF, + TXT, + + // Audiobook qualities + AudiobookUnknown, + MP3_128, + MP3_320, + M4B, + AudioFLAC }; AllLookup = new Quality[All.Select(v => v.Id).Max() + 1]; @@ -201,7 +231,22 @@ static Quality() new QualityDefinition(Quality.Remux2160p) { Weight = 24, MinSize = 0, MaxSize = null, PreferredSize = null }, new QualityDefinition(Quality.BRDISK) { Weight = 25, MinSize = 0, MaxSize = null, PreferredSize = null }, - new QualityDefinition(Quality.RAWHD) { Weight = 26, MinSize = 0, MaxSize = null, PreferredSize = null } + new QualityDefinition(Quality.RAWHD) { Weight = 26, MinSize = 0, MaxSize = null, PreferredSize = null }, + + // Book quality definitions (Weight 100+) + new QualityDefinition(Quality.EbookUnknown) { Weight = 100, MinSize = 0, MaxSize = 50, PreferredSize = 10 }, + new QualityDefinition(Quality.TXT) { Weight = 101, MinSize = 0, MaxSize = 5, PreferredSize = 1 }, + new QualityDefinition(Quality.PDF) { Weight = 102, MinSize = 0, MaxSize = 100, PreferredSize = 20 }, + new QualityDefinition(Quality.MOBI) { Weight = 103, MinSize = 0, MaxSize = 50, PreferredSize = 5 }, + new QualityDefinition(Quality.AZW3) { Weight = 104, MinSize = 0, MaxSize = 50, PreferredSize = 5 }, + new QualityDefinition(Quality.EPUB) { Weight = 105, MinSize = 0, MaxSize = 50, PreferredSize = 5 }, + + // Audiobook quality definitions (Weight 200+) + new QualityDefinition(Quality.AudiobookUnknown) { Weight = 200, MinSize = 0, MaxSize = null, PreferredSize = null }, + new QualityDefinition(Quality.MP3_128) { Weight = 201, MinSize = 0, MaxSize = 500, PreferredSize = 200 }, + new QualityDefinition(Quality.MP3_320) { Weight = 202, MinSize = 0, MaxSize = 1000, PreferredSize = 500 }, + new QualityDefinition(Quality.M4B) { Weight = 203, MinSize = 0, MaxSize = 1000, PreferredSize = 400 }, + new QualityDefinition(Quality.AudioFLAC) { Weight = 204, MinSize = 0, MaxSize = null, PreferredSize = null } }; } diff --git a/src/NzbDrone.Core/Qualities/QualitySource.cs b/src/NzbDrone.Core/Qualities/QualitySource.cs index c87639302c..05bd18190f 100644 --- a/src/NzbDrone.Core/Qualities/QualitySource.cs +++ b/src/NzbDrone.Core/Qualities/QualitySource.cs @@ -11,6 +11,8 @@ public enum QualitySource TV, WEBDL, WEBRIP, - BLURAY + BLURAY, + EBOOK, + AUDIOBOOK } }