From a223b413eae876d6ca61cf245756330e6c7cbfe7 Mon Sep 17 00:00:00 2001 From: morski Date: Wed, 15 May 2024 00:14:18 +0300 Subject: [PATCH 1/2] Refactored MergeVersionManager. Fixed issue #19. --- .../Api/MergeVersionsController.cs | 33 +- .../MergeVersionsManager.cs | 334 ++++++++---------- .../ScheduledTasks/RefreshLibraryTask.cs | 43 ++- 3 files changed, 196 insertions(+), 214 deletions(-) diff --git a/Jellyfin.Plugin.MergeVersions/Api/MergeVersionsController.cs b/Jellyfin.Plugin.MergeVersions/Api/MergeVersionsController.cs index 83720af..5c5c75a 100644 --- a/Jellyfin.Plugin.MergeVersions/Api/MergeVersionsController.cs +++ b/Jellyfin.Plugin.MergeVersions/Api/MergeVersionsController.cs @@ -1,18 +1,16 @@ - -using MediaBrowser.Controller.Library; -using Microsoft.Extensions.Logging; - using System.Net.Mime; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.IO; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System.Threading.Tasks; -using MediaBrowser.Model.IO; -using System.Threading; +using Microsoft.Extensions.Logging; namespace Jellyfin.Plugin.MergeVersions.Api -{ - /// +{ + /// /// The Merge Versions api controller. /// [ApiController] @@ -27,18 +25,17 @@ public class MergeVersionsController : ControllerBase /// /// Initializes a new instance of . - public MergeVersionsController (ILibraryManager libraryManager, ILogger logger, - IFileSystem fileSystem) + public MergeVersionsController( + ILibraryManager libraryManager, + ILogger logger, + IFileSystem fileSystem + ) { - _mergeVersionsManager = new MergeVersionsManager( - libraryManager, - logger, - fileSystem); + _mergeVersionsManager = new MergeVersionsManager(libraryManager, logger, fileSystem); _logger = logger; } - /// /// Scans all movies and merges repeated ones. /// @@ -69,7 +66,6 @@ public ActionResult SplitMoviesRequest() return NoContent(); } - /// /// Scans all episodes and merge repeated ones. /// @@ -85,7 +81,6 @@ public async Task MergeEpisodesRequestAsync() return NoContent(); } - /// /// Scans all episodes and splits merged ones. /// @@ -101,4 +96,4 @@ public async Task SplitEpisodesRequestAsync() return NoContent(); } } -} \ No newline at end of file +} diff --git a/Jellyfin.Plugin.MergeVersions/MergeVersionsManager.cs b/Jellyfin.Plugin.MergeVersions/MergeVersionsManager.cs index ec722a8..9496c94 100644 --- a/Jellyfin.Plugin.MergeVersions/MergeVersionsManager.cs +++ b/Jellyfin.Plugin.MergeVersions/MergeVersionsManager.cs @@ -1,22 +1,20 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.IO; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Session; -using Microsoft.Extensions.Logging; -using Jellyfin.Data.Enums; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; using Microsoft.AspNetCore.Mvc; -using System.ComponentModel.DataAnnotations; -using System.Globalization; - - +using Microsoft.Extensions.Logging; namespace Jellyfin.Plugin.MergeVersions { @@ -28,195 +26,146 @@ public class MergeVersionsManager : IDisposable private readonly SessionInfo _session; private readonly IFileSystem _fileSystem; - - public MergeVersionsManager(ILibraryManager libraryManager, ILogger logger, - IFileSystem fileSystem) + public MergeVersionsManager( + ILibraryManager libraryManager, + ILogger logger, + IFileSystem fileSystem + ) { - _libraryManager = libraryManager; _logger = logger; _fileSystem = fileSystem; _timer = new Timer(_ => OnTimerElapsed(), null, Timeout.Infinite, Timeout.Infinite); - - } - - - - private IEnumerable GetMoviesFromLibrary() - { - var movies = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { BaseItemKind.Movie }, - IsVirtualItem = false, - Recursive = true, - HasTmdbId = true, - - - - }).Select(m => m as Movie); - - return movies.ToList(); } - private IEnumerable GetEpisodesFromLibrary() - { - var episodes = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { BaseItemKind.Episode}, - IsVirtualItem = false, - Recursive = true, - - }).Select(m => m as Episode); - - return episodes.ToList(); - - } - public void MergeMovies(IProgress progress) { - var movies = GetMoviesFromLibrary().ToArray(); - - - _logger.LogInformation("Scanning for repeated movies"); - //Group by Tmdb Id, then select those with more than 1 in the group - var duplications = movies.GroupBy(x => new { V = x.ProviderIds["Tmdb"]}).Where(x => x.Count() > 1).ToList(); - var total = duplications.Count(); - var current = 0; - //foreach grouping, merge - Parallel.ForEach(duplications, async m => - { - current++; - var percent = ((double) current / (double) total) * 100; - progress?.Report((int)percent); + var duplicateMovies = GetMoviesFromLibrary() + .GroupBy(x => x.ProviderIds["Tmdb"]) + .Where(x => x.Count() > 1) + .ToList(); - await MergeVideosAsync(m.Where(m => m.PrimaryVersionId == null && m.GetLinkedAlternateVersions().Count() == 0).ToList());//We only want non merged movies - - } - ); - //foreach (var m in duplications) - progress?.Report(100); - } - public void SplitMovies(IProgress progress) - { - var movies = GetMoviesFromLibrary().ToArray(); - movies = movies.Where(isElegible).ToArray(); - var total = movies.Count(); var current = 0; - //foreach grouping, merge - Parallel.ForEach(movies, async m => - { - current++; - var percent = ((double)current / (double)total) * 100; - progress?.Report((int)percent); - - _logger.LogInformation($"Spliting {m.Name} ({m.ProductionYear})"); - await SplitVideoAsync(m); - } + Parallel.ForEach( + duplicateMovies, + async m => + { + current++; + var percent = current / (double)duplicateMovies.Count * 100; + progress?.Report((int)percent); + _logger.LogInformation( + $"Merging {m.ElementAt(0).Name} ({m.ElementAt(0).ProductionYear})" + ); + await MergeVersions(m.Select(e => e.Id).ToList()); + } ); progress?.Report(100); - } - private async Task SplitVideoAsync(BaseItem v) - { - await DeleteAlternateSources(v.Id); - - } - - private async Task MergeVideosAsync(IEnumerable videos) + public void SplitMovies(IProgress progress) { - List elegibleToMerge = new List(); - - foreach (var video in videos) - { - if (isElegible(video)) - { - elegibleToMerge.Add(video); - } - } - - Guid[] ids = new Guid[elegibleToMerge.Count]; - for (int i = 0; i < elegibleToMerge.Count; i++) - { - ids[i] = elegibleToMerge.ElementAt(i).Id; - } - if (elegibleToMerge.Count() > 1) - { - _logger.LogInformation($"Merging {videos.ElementAt(0).Name} ({videos.ElementAt(0).ProductionYear})"); - _logger.LogDebug($"ids are " + printIds(ids) + " Merging..."); - try + var movies = GetMoviesFromLibrary(); + var current = 0; + Parallel.ForEach( + movies, + async m => { - await MergeVersions(ids); + current++; + var percent = current / (double)movies.Count * 100; + progress?.Report((int)percent); - }catch( Exception e) - { - _logger.LogError("Error merging " + e.Message); + _logger.LogInformation($"Spliting {m.Name} ({m.ProductionYear})"); + await DeleteAlternateSources(m.Id); } - _logger.LogDebug("merged"); - } + ); + progress?.Report(100); } - private String printIds(Guid[] ids) - { - String aux = ""; - foreach(Guid id in ids) - { - aux += id; - aux += " , "; - } - return aux; - - } - public async Task MergeEpisodesAsync(IProgress progress) { - var episodes = GetEpisodesFromLibrary().ToArray(); - _logger.LogInformation("Scanning for repeated episodes"); - //Group by the Series name, Season name , episode name, episode number and year, then select those with more than 1 in the group - var duplications = episodes.GroupBy(x => new {x.SeriesName,x.SeasonName, x.Name,x.IndexNumber, x.ProductionYear }).Where(x => x.Count() > 1).ToList(); + var duplicateEpisodes = GetEpisodesFromLibrary() + .GroupBy(x => new + { + x.SeriesName, + x.SeasonName, + x.Name, + x.IndexNumber, + x.ProductionYear + }) + .Where(x => x.Count() > 1) + .ToList(); - var total = duplications.Count(); var current = 0; - //foreach grouping, merge - foreach (var e in duplications) + foreach (var e in duplicateEpisodes) { current++; - var percent = ((double)current / (double)total) * 100; + var percent = current / (double)duplicateEpisodes.Count * 100; progress?.Report((int)percent); - - _logger.LogInformation($"Merging {e.Key.IndexNumber} ({e.Key.SeriesName})"); - await MergeVideosAsync(e.ToList().Where(e => e.PrimaryVersionId == null && e.GetLinkedAlternateVersions().Count()==0));//We only want non merged movies + _logger.LogInformation( + $"Merging {e.ElementAt(0).Name} ({e.ElementAt(0).ProductionYear})" + ); + await MergeVersions(e.Select(e => e.Id).ToList()); } progress?.Report(100); } public async Task SplitEpisodesAsync(IProgress progress) { - var episodes = GetEpisodesFromLibrary().ToArray(); - var total = episodes.Count(); + var episodes = GetEpisodesFromLibrary(); var current = 0; - //foreach grouping, merge + foreach (var e in episodes) { current++; - var percent = ((double)current / (double)total) * 100; + var percent = current / (double)episodes.Count * 100; progress?.Report((int)percent); _logger.LogInformation($"Spliting {e.IndexNumber} ({e.SeriesName})"); - await SplitVideoAsync(e); + await DeleteAlternateSources(e.Id); } progress?.Report(100); + } + + private List GetMoviesFromLibrary() + { + return _libraryManager + .GetItemList( + new InternalItemsQuery + { + IncludeItemTypes = [BaseItemKind.Movie], + IsVirtualItem = false, + Recursive = true, + HasTmdbId = true, + } + ) + .Select(m => m as Movie) + .Where(IsElegible) + .ToList(); + } + private List GetEpisodesFromLibrary() + { + return _libraryManager + .GetItemList( + new InternalItemsQuery + { + IncludeItemTypes = [BaseItemKind.Episode], + IsVirtualItem = false, + Recursive = true, + } + ) + .Select(m => m as Episode) + .Where(IsElegible) + .ToList(); } - public async Task MergeVersions(Guid[] ids) + private async Task MergeVersions(List ids) { - var items = ids - .Select(i => _libraryManager.GetItemById(i, null)) + var items = ids.Select(i => _libraryManager.GetItemById(i, null)) .OfType