diff options
| author | theguymadmax <theguymadmax@proton.me> | 2026-02-13 11:52:10 -0500 |
|---|---|---|
| committer | theguymadmax <theguymadmax@proton.me> | 2026-02-13 11:52:10 -0500 |
| commit | 2757c18312943cbc17ce01b100f73b411f596a98 (patch) | |
| tree | 1d337eed04744ec3fd4bb148409753b8d4958f58 | |
| parent | 8b5914001d63de809122997a9bb6d9253bfef850 (diff) | |
Fix episodes appearing in Season Unknown incorrectly and prevent unnecessary virtual season creation
| -rw-r--r-- | MediaBrowser.Controller/Entities/TV/Series.cs | 3 | ||||
| -rw-r--r-- | MediaBrowser.Providers/TV/SeriesMetadataService.cs | 33 |
2 files changed, 35 insertions, 1 deletions
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 6396631f9..b3956c823 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -451,7 +451,8 @@ namespace MediaBrowser.Controller.Entities.TV if (!currentSeasonNumber.HasValue && !seasonNumber.HasValue && parentSeason.LocationType == LocationType.Virtual) { - return true; + var episodeSeason = episodeItem.Season; + return episodeSeason is null || episodeSeason.LocationType == LocationType.Virtual; } var season = episodeItem.Season; diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index c3a6ddd6a..61a31fbfd 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -201,6 +202,26 @@ public class SeriesMetadataService : MetadataService<Series, SeriesInfo> false); } + private static bool NeedsVirtualSeason(Episode episode, HashSet<Guid> physicalSeasonIds, HashSet<string> physicalSeasonPaths) + { + // Episode has a known season number, needs a season + if (episode.ParentIndexNumber.HasValue) + { + return true; + } + + // Not yet processed + if (episode.SeasonId.IsEmpty()) + { + return false; + } + + // Episode has been processed, only needs a virtual season if it isn't + // already linked to a known physical season by ID or path + return !physicalSeasonIds.Contains(episode.SeasonId) + && !physicalSeasonPaths.Contains(System.IO.Path.GetDirectoryName(episode.Path) ?? string.Empty); + } + /// <summary> /// Creates seasons for all episodes if they don't exist. /// If no season number can be determined, a dummy season will be created. @@ -212,8 +233,20 @@ public class SeriesMetadataService : MetadataService<Series, SeriesInfo> { var seriesChildren = series.GetRecursiveChildren(i => i is Episode || i is Season); var seasons = seriesChildren.OfType<Season>().ToList(); + + var physicalSeasonIds = seasons + .Where(e => e.LocationType != LocationType.Virtual) + .Select(e => e.Id) + .ToHashSet(); + + var physicalSeasonPathSet = seasons + .Where(e => e.LocationType != LocationType.Virtual && !string.IsNullOrEmpty(e.Path)) + .Select(e => e.Path) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + var uniqueSeasonNumbers = seriesChildren .OfType<Episode>() + .Where(e => NeedsVirtualSeason(e, physicalSeasonIds, physicalSeasonPathSet)) .Select(e => e.ParentIndexNumber >= 0 ? e.ParentIndexNumber : null) .Distinct(); |
