< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.Library.Resolvers.Books.BookResolver
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs
Line coverage
10%
Covered lines: 4
Uncovered lines: 36
Coverable lines: 40
Total lines: 86
Line coverage: 10%
Branch coverage
6%
Covered branches: 1
Total branches: 16
Branch coverage: 6.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 3/26/2026 - 12:14:14 AM Line coverage: 10.5% (4/38) Branch coverage: 6.2% (1/16) Total lines: 866/18/2026 - 12:16:24 AM Line coverage: 10% (4/40) Branch coverage: 6.2% (1/16) Total lines: 86 3/26/2026 - 12:14:14 AM Line coverage: 10.5% (4/38) Branch coverage: 6.2% (1/16) Total lines: 866/18/2026 - 12:16:24 AM Line coverage: 10% (4/40) Branch coverage: 6.2% (1/16) Total lines: 86

Coverage delta

Coverage delta 1 -1

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
Resolve(...)10%701015.78%
GetBook(...)0%4260%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs

#LineLine coverage
 1#pragma warning disable CS1591
 2
 3using System;
 4using System.IO;
 5using System.Linq;
 6using Emby.Naming.Book;
 7using Jellyfin.Data.Enums;
 8using Jellyfin.Extensions;
 9using MediaBrowser.Controller.Entities;
 10using MediaBrowser.Controller.Library;
 11using MediaBrowser.Controller.Resolvers;
 12
 13namespace Emby.Server.Implementations.Library.Resolvers.Books
 14{
 15    public class BookResolver : ItemResolver<Book>
 16    {
 2217        private readonly string[] _validExtensions = { ".azw", ".azw3", ".cb7", ".cbr", ".cbt", ".cbz", ".epub", ".mobi"
 18
 19        protected override Book? Resolve(ItemResolveArgs args)
 20        {
 1021            var collectionType = args.GetCollectionType();
 22
 23            // Only process items that are in a collection folder containing books
 1024            if (collectionType != CollectionType.books)
 25            {
 1026                return null;
 27            }
 28
 029            if (args.IsDirectory)
 30            {
 031                return GetBook(args);
 32            }
 33
 034            var extension = Path.GetExtension(args.Path.AsSpan());
 35
 036            if (!_validExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
 37            {
 038                return null;
 39            }
 40
 041            var result = BookFileNameParser.Parse(Path.GetFileNameWithoutExtension(args.Path));
 42
 043            return new Book
 044            {
 045                Path = args.Path,
 046                Name = result.Name ?? string.Empty,
 047                IndexNumber = result.Index,
 048                ParentIndexNumber = result.ParentIndex,
 049                ProductionYear = result.Year,
 050                SeriesName = result.SeriesName ?? Path.GetFileName(Path.GetDirectoryName(args.Path)),
 051                IsInMixedFolder = true,
 052            };
 53        }
 54
 55        private Book? GetBook(ItemResolveArgs args)
 56        {
 057            var bookFiles = args.FileSystemChildren.Where(f =>
 058            {
 059                var fileExtension = Path.GetExtension(f.FullName.AsSpan());
 060
 061                return _validExtensions.Contains(
 062                    fileExtension,
 063                    StringComparison.OrdinalIgnoreCase);
 064            }).ToList();
 65
 66            // directory is only considered a book when it contains exactly one supported file
 67            // other library structures with multiple books to a directory will get picked up as individual files
 068            if (bookFiles.Count != 1)
 69            {
 070                return null;
 71            }
 72
 073            var result = BookFileNameParser.Parse(Path.GetFileName(args.Path));
 74
 075            return new Book
 076            {
 077                Path = bookFiles[0].FullName,
 078                Name = result.Name ?? string.Empty,
 079                IndexNumber = result.Index,
 080                ParentIndexNumber = result.ParentIndex,
 081                ProductionYear = result.Year,
 082                SeriesName = result.SeriesName ?? string.Empty,
 083            };
 84        }
 85    }
 86}