| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 | using System;using System.Collections.Generic;using System.Linq;using System.Threading;using System.Threading.Tasks;using Jellyfin.Data.Enums;using Jellyfin.Database.Implementations.Enums;using MediaBrowser.Controller.Collections;using MediaBrowser.Controller.Entities;using MediaBrowser.Controller.Entities.Movies;using MediaBrowser.Controller.Library;using Microsoft.Extensions.Logging;namespace Emby.Server.Implementations.Library.Validators;/// <summary>/// Class CollectionPostScanTask./// </summary>public class CollectionPostScanTask : ILibraryPostScanTask{    private readonly ILibraryManager _libraryManager;    private readonly ICollectionManager _collectionManager;    private readonly ILogger<CollectionPostScanTask> _logger;    /// <summary>    /// Initializes a new instance of the <see cref="CollectionPostScanTask" /> class.    /// </summary>    /// <param name="libraryManager">The library manager.</param>    /// <param name="collectionManager">The collection manager.</param>    /// <param name="logger">The logger.</param>    public CollectionPostScanTask(        ILibraryManager libraryManager,        ICollectionManager collectionManager,        ILogger<CollectionPostScanTask> logger)    {        _libraryManager = libraryManager;        _collectionManager = collectionManager;        _logger = logger;    }    /// <summary>    /// Runs the specified progress.    /// </summary>    /// <param name="progress">The progress.</param>    /// <param name="cancellationToken">The cancellation token.</param>    /// <returns>Task.</returns>    public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)    {        var collectionNameMoviesMap = new Dictionary<string, HashSet<Guid>>();        foreach (var library in _libraryManager.RootFolder.Children)        {            if (!_libraryManager.GetLibraryOptions(library).AutomaticallyAddToCollection)            {                continue;            }            var startIndex = 0;            var pagesize = 1000;            while (true)            {                var movies = _libraryManager.GetItemList(new InternalItemsQuery                {                    MediaTypes = [MediaType.Video],                    IncludeItemTypes = [BaseItemKind.Movie],                    IsVirtualItem = false,                    OrderBy = [(ItemSortBy.SortName, SortOrder.Ascending)],                    Parent = library,                    StartIndex = startIndex,                    Limit = pagesize,                    Recursive = true                });                foreach (var m in movies)                {                    if (m is Movie movie && !string.IsNullOrEmpty(movie.CollectionName))                    {                        if (collectionNameMoviesMap.TryGetValue(movie.CollectionName, out var movieList))                        {                            movieList.Add(movie.Id);                        }                        else                        {                            collectionNameMoviesMap[movie.CollectionName] = new HashSet<Guid> { movie.Id };                        }                    }                }                if (movies.Count < pagesize)                {                    break;                }                startIndex += pagesize;            }        }        var numComplete = 0;        var count = collectionNameMoviesMap.Count;        if (count == 0)        {            progress.Report(100);            return;        }        var boxSets = _libraryManager.GetItemList(new InternalItemsQuery        {            IncludeItemTypes = [BaseItemKind.BoxSet],            CollapseBoxSetItems = false,            Recursive = true        });        foreach (var (collectionName, movieIds) in collectionNameMoviesMap)        {            try            {                var boxSet = boxSets.FirstOrDefault(b => b?.Name == collectionName) as BoxSet;                if (boxSet is null)                {                    // won't automatically create collection if only one movie in it                    if (movieIds.Count >= 2)                    {                        boxSet = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions                        {                            Name = collectionName,                        }).ConfigureAwait(false);                        await _collectionManager.AddToCollectionAsync(boxSet.Id, movieIds).ConfigureAwait(false);                    }                }                else                {                    await _collectionManager.AddToCollectionAsync(boxSet.Id, movieIds).ConfigureAwait(false);                }                numComplete++;                double percent = numComplete;                percent /= count;                percent *= 100;                progress.Report(percent);            }            catch (Exception ex)            {                _logger.LogError(ex, "Error refreshing {CollectionName} with {@MovieIds}", collectionName, movieIds);            }        }        progress.Report(100);    }}
 |