From f6ac1d9f3837c9fda7bf101ed98128e13427d390 Mon Sep 17 00:00:00 2001 From: theguymadmax Date: Thu, 19 Feb 2026 11:25:00 -0500 Subject: [PATCH] Fix folders being identified as seasons in mixed libraries --- Emby.Naming/TV/SeasonPathParser.cs | 14 ++++++++++++ .../TV/SeasonPathParserTests.cs | 22 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/Emby.Naming/TV/SeasonPathParser.cs b/Emby.Naming/TV/SeasonPathParser.cs index ea4875e00a..58c000ede3 100644 --- a/Emby.Naming/TV/SeasonPathParser.cs +++ b/Emby.Naming/TV/SeasonPathParser.cs @@ -21,6 +21,9 @@ namespace Emby.Naming.TV [GeneratedRegex(@"[sS](\d{1,4})(?!\d|[eE]\d)(?=\.|_|-|\[|\]|\s|$)", RegexOptions.None)] private static partial Regex SeasonPrefix(); + [GeneratedRegex(@"(season|staffel|stagione|sæson|temporada|series|kausi|säsong|seizoen|seasong|sezon|sezona|sezóna|sezonul|시즌|シーズン|сезон)", RegexOptions.IgnoreCase)] + private static partial Regex SeasonKeyword(); + /// /// Attempts to parse season number from path. /// @@ -91,14 +94,25 @@ namespace Emby.Naming.TV return (val, true); } + bool isMixedLibrary = !supportNumericSeasonFolders && !supportSpecialAliases; var preMatch = ProcessPre().Match(filename); if (preMatch.Success) { + if (isMixedLibrary && !SeasonKeyword().IsMatch(fileName)) + { + return (null, false); + } + return CheckMatch(preMatch); } else { var postMatch = ProcessPost().Match(filename); + if (postMatch.Success && isMixedLibrary && !SeasonKeyword().IsMatch(fileName)) + { + return (null, false); + } + return CheckMatch(postMatch); } } diff --git a/tests/Jellyfin.Naming.Tests/TV/SeasonPathParserTests.cs b/tests/Jellyfin.Naming.Tests/TV/SeasonPathParserTests.cs index 4dbe769bf4..2035140f00 100644 --- a/tests/Jellyfin.Naming.Tests/TV/SeasonPathParserTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/SeasonPathParserTests.cs @@ -83,4 +83,26 @@ public class SeasonPathParserTests Assert.Equal(seasonNumber, result.SeasonNumber); Assert.Equal(isSeasonDirectory, result.IsSeasonFolder); } + + [Theory] + [InlineData("/Drive/300 Collection/300 (2006)", "/Drive/300 Collection", null, false)] + [InlineData("/Drive/300 Collection/300 Rise of an Empire", "/Drive/300 Collection", null, false)] + [InlineData("/Drive/300 Collection/1", "/Drive/300 Collection", null, false)] + [InlineData("/Drive/300 Collection/300 Disc 1", "/Drive/300 Collection", null, false)] + [InlineData("/Drive/28 Years Later Collection/28 Days Later", "/Drive/28 Years Later Collection", null, false)] + [InlineData("/Drive/28 Years Later Collection/28 Weeks Later (2007)", "/Drive/28 Years Later Collection", null, false)] + [InlineData("/Drive/28 Years Later Collection/28 Years Later 2025", "/Drive/28 Years Later Collection", null, false)] + [InlineData("/Drive/300 Collection/Season 1", "/Drive/300 Collection", 1, true)] + [InlineData("/Drive/28 Years Later Collection/Season 01", "/Drive/28 Years Later Collection", 1, true)] + [InlineData("/Drive/300 Collection/S01", "/Drive/300 Collection", 1, true)] + [InlineData("/Drive/300 Collection/S1", "/Drive/300 Collection", 1, true)] + + public void GetSeasonNumberFromPathMixedLibraryTest(string path, string? parentPath, int? seasonNumber, bool isSeasonDirectory) + { + var result = SeasonPathParser.Parse(path, parentPath, false, false); + + Assert.Equal(result.SeasonNumber is not null, result.Success); + Assert.Equal(seasonNumber, result.SeasonNumber); + Assert.Equal(isSeasonDirectory, result.IsSeasonFolder); + } }