< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.Library.Validators.CollectionPostScanTask
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs
Line coverage
100%
Covered lines: 4
Uncovered lines: 0
Coverable lines: 4
Total lines: 154
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Threading;
 5using System.Threading.Tasks;
 6using Jellyfin.Data.Enums;
 7using Jellyfin.Database.Implementations.Enums;
 8using MediaBrowser.Controller.Collections;
 9using MediaBrowser.Controller.Entities;
 10using MediaBrowser.Controller.Entities.Movies;
 11using MediaBrowser.Controller.Library;
 12using Microsoft.Extensions.Logging;
 13
 14namespace Emby.Server.Implementations.Library.Validators;
 15
 16/// <summary>
 17/// Class CollectionPostScanTask.
 18/// </summary>
 19public class CollectionPostScanTask : ILibraryPostScanTask
 20{
 21    private readonly ILibraryManager _libraryManager;
 22    private readonly ICollectionManager _collectionManager;
 23    private readonly ILogger<CollectionPostScanTask> _logger;
 24
 25    /// <summary>
 26    /// Initializes a new instance of the <see cref="CollectionPostScanTask" /> class.
 27    /// </summary>
 28    /// <param name="libraryManager">The library manager.</param>
 29    /// <param name="collectionManager">The collection manager.</param>
 30    /// <param name="logger">The logger.</param>
 31    public CollectionPostScanTask(
 32        ILibraryManager libraryManager,
 33        ICollectionManager collectionManager,
 34        ILogger<CollectionPostScanTask> logger)
 35    {
 2136        _libraryManager = libraryManager;
 2137        _collectionManager = collectionManager;
 2138        _logger = logger;
 2139    }
 40
 41    /// <summary>
 42    /// Runs the specified progress.
 43    /// </summary>
 44    /// <param name="progress">The progress.</param>
 45    /// <param name="cancellationToken">The cancellation token.</param>
 46    /// <returns>Task.</returns>
 47    public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
 48    {
 49        var collectionNameMoviesMap = new Dictionary<string, HashSet<Guid>>();
 50
 51        foreach (var library in _libraryManager.RootFolder.Children)
 52        {
 53            if (!_libraryManager.GetLibraryOptions(library).AutomaticallyAddToCollection)
 54            {
 55                continue;
 56            }
 57
 58            var startIndex = 0;
 59            var pagesize = 1000;
 60
 61            while (true)
 62            {
 63                var movies = _libraryManager.GetItemList(new InternalItemsQuery
 64                {
 65                    MediaTypes = [MediaType.Video],
 66                    IncludeItemTypes = [BaseItemKind.Movie],
 67                    IsVirtualItem = false,
 68                    OrderBy = [(ItemSortBy.SortName, SortOrder.Ascending)],
 69                    Parent = library,
 70                    StartIndex = startIndex,
 71                    Limit = pagesize,
 72                    Recursive = true
 73                });
 74
 75                foreach (var m in movies)
 76                {
 77                    if (m is Movie movie && !string.IsNullOrEmpty(movie.CollectionName))
 78                    {
 79                        if (collectionNameMoviesMap.TryGetValue(movie.CollectionName, out var movieList))
 80                        {
 81                            movieList.Add(movie.Id);
 82                        }
 83                        else
 84                        {
 85                            collectionNameMoviesMap[movie.CollectionName] = new HashSet<Guid> { movie.Id };
 86                        }
 87                    }
 88                }
 89
 90                if (movies.Count < pagesize)
 91                {
 92                    break;
 93                }
 94
 95                startIndex += pagesize;
 96            }
 97        }
 98
 99        var numComplete = 0;
 100        var count = collectionNameMoviesMap.Count;
 101
 102        if (count == 0)
 103        {
 104            progress.Report(100);
 105            return;
 106        }
 107
 108        var boxSets = _libraryManager.GetItemList(new InternalItemsQuery
 109        {
 110            IncludeItemTypes = [BaseItemKind.BoxSet],
 111            CollapseBoxSetItems = false,
 112            Recursive = true
 113        });
 114
 115        foreach (var (collectionName, movieIds) in collectionNameMoviesMap)
 116        {
 117            try
 118            {
 119                var boxSet = boxSets.FirstOrDefault(b => b?.Name == collectionName) as BoxSet;
 120                if (boxSet is null)
 121                {
 122                    // won't automatically create collection if only one movie in it
 123                    if (movieIds.Count >= 2)
 124                    {
 125                        boxSet = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions
 126                        {
 127                            Name = collectionName,
 128                            IsLocked = true
 129                        }).ConfigureAwait(false);
 130
 131                        await _collectionManager.AddToCollectionAsync(boxSet.Id, movieIds).ConfigureAwait(false);
 132                    }
 133                }
 134                else
 135                {
 136                    await _collectionManager.AddToCollectionAsync(boxSet.Id, movieIds).ConfigureAwait(false);
 137                }
 138
 139                numComplete++;
 140                double percent = numComplete;
 141                percent /= count;
 142                percent *= 100;
 143
 144                progress.Report(percent);
 145            }
 146            catch (Exception ex)
 147            {
 148                _logger.LogError(ex, "Error refreshing {CollectionName} with {@MovieIds}", collectionName, movieIds);
 149            }
 150        }
 151
 152        progress.Report(100);
 153    }
 154}