< 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: 34
Coverable lines: 38
Total lines: 86
Line coverage: 10.5%
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 9/14/2025 - 12:09:49 AM Line coverage: 14.2% (4/28) Branch coverage: 12.5% (1/8) Total lines: 7412/14/2025 - 12:12:01 AM Line coverage: 10.5% (4/38) Branch coverage: 6.2% (1/16) Total lines: 86 9/14/2025 - 12:09:49 AM Line coverage: 14.2% (4/28) Branch coverage: 12.5% (1/8) Total lines: 7412/14/2025 - 12:12:01 AM Line coverage: 10.5% (4/38) Branch coverage: 6.2% (1/16) Total lines: 86

Metrics

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

File(s)

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

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