From 56c81696d3c26553a2b366f15c0d685837d4f0bd Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 30 Jul 2022 21:50:53 +0200 Subject: [PATCH] fix: remove Virtual episodes when their physical counterpart exists --- MediaBrowser.Controller/Entities/TV/Series.cs | 8 +-- .../TV/SeriesMetadataService.cs | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index a3c4a81fdc..d9efd6b736 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -258,14 +258,10 @@ namespace MediaBrowser.Controller.Entities.TV SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { BaseItemKind.Episode, BaseItemKind.Season }, OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, - DtoOptions = options + DtoOptions = options, + IsMissing = user?.DisplayMissingEpisodes }; - if (!user.DisplayMissingEpisodes) - { - query.IsMissing = false; - } - var allItems = LibraryManager.GetItemList(query); var allSeriesEpisodes = allItems.OfType().ToList(); diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index f49492f337..c09b6d8138 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -40,6 +41,7 @@ namespace MediaBrowser.Providers.TV { await base.AfterMetadataRefresh(item, refreshOptions, cancellationToken).ConfigureAwait(false); + RemoveObsoleteEpisodes(item); RemoveObsoleteSeasons(item); await FillInMissingSeasonsAsync(item, cancellationToken).ConfigureAwait(false); } @@ -121,6 +123,61 @@ namespace MediaBrowser.Providers.TV } } + private void RemoveObsoleteEpisodes(Series series) + { + var episodes = series.GetEpisodes(null, new DtoOptions()).OfType().ToList(); + var numberOfEpisodes = episodes.Count; + // TODO: O(n^2), but can it be done faster without overcomplicating it? + for (var i = 0; i < numberOfEpisodes; i++) + { + var currentEpisode = episodes[i]; + // The outer loop only examines virtual episodes + if (!currentEpisode.IsVirtualItem) + { + continue; + } + + // Virtual episodes without an episode number are practically orphaned and should be deleted + if (!currentEpisode.IndexNumber.HasValue) + { + DeleteEpisode(currentEpisode); + continue; + } + + for (var j = i + 1; j < numberOfEpisodes; j++) + { + var comparisonEpisode = episodes[j]; + // The inner loop is only for "physical" episodes + if (comparisonEpisode.IsVirtualItem + || currentEpisode.ParentIndexNumber != comparisonEpisode.ParentIndexNumber + || !comparisonEpisode.ContainsEpisodeNumber(currentEpisode.IndexNumber.Value)) + { + continue; + } + + DeleteEpisode(currentEpisode); + break; + } + } + } + + private void DeleteEpisode(Episode episode) + { + Logger.LogInformation( + "Removing virtual episode S{SeasonNumber}E{EpisodeNumber} in series {SeriesName}", + episode.ParentIndexNumber, + episode.IndexNumber, + episode.SeriesName); + + LibraryManager.DeleteItem( + episode, + new DeleteOptions + { + DeleteFileLocation = true + }, + false); + } + /// /// Creates seasons for all episodes that aren't in a season folder. /// If no season number can be determined, a dummy season will be created.