using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.IO; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; namespace Jellyfin.Plugin.SmartPlaylist.ScheduledTasks { public class GenerateCollection: Common, IScheduledTask { private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IProviderManager _providerManager; private readonly IFileSystem _fileSystem; private readonly ICollectionManager _collectionManager; private readonly IStore _store; public GenerateCollection( ILogger logger, ILibraryManager libraryManager, IUserManager userManager, IProviderManager providerManager, IFileSystem fileSystem, ICollectionManager collectionManager, IServerApplicationPaths serverApplicationPaths ) : base(logger) { _libraryManager = libraryManager; _userManager = userManager; _providerManager = providerManager; _fileSystem = fileSystem; _collectionManager = collectionManager; _store = new Store(new SmartFileSystem(serverApplicationPaths)); } public string Category => "Library"; public string Name => "(re)generate Smart Collections"; public string Description => "Generate or regenerate all Smart Collections"; public string Key => nameof(GenerateCollection); public IEnumerable GetDefaultTriggers() { return new[] { new TaskTriggerInfo { IntervalTicks = TimeSpan.FromHours(24).Ticks, Type = TaskTriggerInfo.TriggerInterval, } }; } private async Task CreateNewCollection(string name) { _logger.LogDebug("Creating collection '{0}'", name); return (await _collectionManager.CreateCollectionAsync( new CollectionCreationOptions { Name = name, } )).Id; } private IEnumerable GetAllMedia() { var req = new InternalItemsQuery() { IncludeItemTypes = AvailableFilterItems, Recursive = true, }; return _libraryManager.GetItemsResult(req).Items; } public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { _logger.LogInformation("Started regenerate Smart Collections"); _logger.LogDebug("Loaded Assemblies:"); foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { _logger.LogDebug("- {0}", asm); } var i = 0; var smartCollections = await _store.GetAllSmartCollectionsAsync(); foreach (SmartCollectionDto dto in smartCollections) { if (!dto.Enabled) { progress.Report(100 * ((double)i)/smartCollections.Count()); i += 1; continue; } if (dto.CollectionId == Guid.Empty) { dto.CollectionId = await CreateNewCollection(dto.Name); _store.DeleteSmartCollection(dto); // delete in case the file was not the canonical one. await _store.SaveSmartCollectionAsync(dto); } var insertItems = FilterCollectionItems(GetAllMedia(), null, dto.Name, dto.Program, dto.SortProgram).ToArray(); await ClearCollection(dto.CollectionId); await _collectionManager.AddToCollectionAsync(dto.CollectionId, insertItems); i += 1; progress.Report(100 * ((double)i)/smartCollections.Count()); } } private async Task ClearCollection(CollectionId collectionId) { // fuck if I know if (_libraryManager.GetItemById(collectionId) is not BoxSet collection) { throw new ArgumentException(""); } var existingItems = collection.Children; await _collectionManager.RemoveFromCollectionAsync(collectionId, existingItems.Select(x => x.Id)); } } }