From 5eb1fde88cb32e05ea51f26e1577b20bb4c60bd6 Mon Sep 17 00:00:00 2001 From: "Petrus.Z" Date: Mon, 15 Nov 2021 22:26:42 +0800 Subject: [PATCH] Add Collection Validator, create collection based on nfo Based on nfo's set element, automatically add movie to collection. Signed-off-by: Petrus.Z --- .../Validators/CollectionPostScanTask.cs | 50 ++++++ .../Library/Validators/CollectionValidator.cs | 166 ++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs create mode 100644 Emby.Server.Implementations/Library/Validators/CollectionValidator.cs diff --git a/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs new file mode 100644 index 0000000000..bc204b788b --- /dev/null +++ b/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs @@ -0,0 +1,50 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Collections; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using Microsoft.Extensions.Logging; + +namespace Emby.Server.Implementations.Library.Validators +{ + /// + /// Class CollectionPostScanTask. + /// + public class CollectionPostScanTask : ILibraryPostScanTask + { + /// + /// The _library manager. + /// + private readonly ILibraryManager _libraryManager; + private readonly ICollectionManager _collectionManager; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// The library manager. + /// The collection manager. + /// The logger. + public CollectionPostScanTask( + ILibraryManager libraryManager, + ILogger logger, + ICollectionManager collectionManager) + { + _libraryManager = libraryManager; + _collectionManager = collectionManager; + _logger = logger; + } + + /// + /// Runs the specified progress. + /// + /// The progress. + /// The cancellation token. + /// Task. + public Task Run(IProgress progress, CancellationToken cancellationToken) + { + return new CollectionValidator(_libraryManager, _collectionManager, _logger).Run(progress, cancellationToken); + } + } +} diff --git a/Emby.Server.Implementations/Library/Validators/CollectionValidator.cs b/Emby.Server.Implementations/Library/Validators/CollectionValidator.cs new file mode 100644 index 0000000000..439fc1da10 --- /dev/null +++ b/Emby.Server.Implementations/Library/Validators/CollectionValidator.cs @@ -0,0 +1,166 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using MediaBrowser.Controller.Collections; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Querying; +using Microsoft.Extensions.Logging; +using Jellyfin.Data.Enums; + +namespace Emby.Server.Implementations.Library.Validators +{ + /// + /// Class CollectionValidator. + /// + public class CollectionValidator + { + /// + /// The library manager. + /// + private readonly ILibraryManager _libraryManager; + + /// + /// The collection manager. + /// + private readonly ICollectionManager _collectionManager; + + /// + /// The logger. + /// + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// The library manager. + /// The collection manager. + /// The logger. + public CollectionValidator(ILibraryManager libraryManager, ICollectionManager collectionManager, ILogger logger) + { + _libraryManager = libraryManager; + _collectionManager = collectionManager; + _logger = logger; + } + + /// + /// Runs the specified progress. + /// + /// The progress. + /// The cancellation token. + /// Task. + public async Task Run(IProgress progress, CancellationToken cancellationToken) + { + var movies = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new[] { nameof(Movie) }, + IsVirtualItem = false, + OrderBy = new List> + { + new ValueTuple(ItemSortBy.SortName, SortOrder.Ascending) + }, + Recursive = true + }).Select(m => m as Movie).ToList(); + + var boxSets = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new[] { nameof(BoxSet) }, + CollapseBoxSetItems = false, + Recursive = true + }).Select(b => b as BoxSet).ToList(); + + var numComplete = 0; + var count = movies.Count; + + var map = new Dictionary>(); + foreach (var movie in movies) + { + if (movie != null && movie.CollectionName != null) + { + var movieList = new List(); + if (map.TryGetValue(movie.CollectionName, out movieList)) + { + if (!movieList.Where(m => m.Id == movie.Id).Any()) + { + movieList.Add(movie); + map[movie.CollectionName] = movieList; + } + } + else + { + map[movie.CollectionName] = new List { movie }; + } + + } + + numComplete++; + double percent = numComplete; + percent /= count * 2; + percent *= 100; + + progress.Report(percent); + } + + foreach (var pair in map) + { + try + { + var collectionName = pair.Key; + var movieList = pair.Value; + + var boxSet = boxSets.FirstOrDefault(b => b != null ? b.Name == collectionName : false); + if (boxSet == null) + { + // won't automatically create collection if only one movie in it + if (movieList.Count >= 2) + { + boxSet = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions + { + Name = collectionName, + IsLocked = true + }); + + AddMovieToCollection(boxSet.Id, boxSet, movieList); + } + } + else + { + AddMovieToCollection(boxSet.Id, boxSet, movieList); + } + + numComplete++; + double percent = numComplete; + percent /= count * 2; + percent *= 100; + + progress.Report(percent); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error refreshing {0}, {1}", pair.Key, pair.Value.ToString()); + } + } + + progress.Report(100); + } + + private async void AddMovieToCollection(Guid boxSetId, BoxSet boxSet, List movieList) + { + + var movieIds = new List(); + foreach (var movie in movieList) + { + if (!boxSet.ContainsLinkedChildByItemId(movie.Id)) + { + movieIds.Add(movie.Id); + } + } + if (movieIds.Any()) { + await _collectionManager.AddToCollectionAsync(boxSetId, movieIds); + } + } + } +}