Merge pull request #16259 from theguymadmax/fix-season-in-mixed-library
Some checks failed
Stale PR Check / Check PRs with merge conflicts (push) Has been cancelled
CodeQL / Analyze (csharp) (push) Has been cancelled
Format / format-check (push) Has been cancelled
Tests / run-tests (macos-latest) (push) Has been cancelled
Tests / run-tests (ubuntu-latest) (push) Has been cancelled
Tests / run-tests (windows-latest) (push) Has been cancelled
OpenAPI Publish / OpenAPI - Publish Artifact (push) Has been cancelled
OpenAPI Publish / OpenAPI - Publish Unstable Spec (push) Has been cancelled
OpenAPI Publish / OpenAPI - Publish Stable Spec (push) Has been cancelled
Project Automation / Project board (push) Has been cancelled
Merge Conflict Labeler / Labeling (push) Has been cancelled
Stale Issue Labeler / Check for stale issues (push) Has been cancelled

Fix folders being identified as seasons in mixed libraries
This commit is contained in:
Bond-009
2026-05-31 19:18:44 +02:00
committed by GitHub
2 changed files with 43 additions and 2 deletions

View File

@@ -10,17 +10,25 @@ namespace Emby.Naming.TV
/// </summary>
public static partial class SeasonPathParser
{
private const string SeasonKeywordPattern =
@"시즌|シーズン|сезон" +
@"|season|sæson|saison|staffel|series|stagione|säsong|seizoen|seasong" +
@"|sezon|sezona|sezóna|sezonul|série|séria|serie|seria|temporada|kausi";
private static readonly Regex CleanNameRegex = new(@"[ ._\-\[\]]", RegexOptions.Compiled);
[GeneratedRegex(@"^\s*((?<seasonnumber>(?>\d+))(?:st|nd|rd|th|\.)*(?!\s*[Ee]\d+))\s*(?:[[]*|[]*|[sS](?:eason|æson|aison|taffel|eries|tagione|äsong|eizoen|easong|ezon|ezona|ezóna|ezonul|érie|éria|erie|eria)*|[tT](?:emporada)*|[kK](?:ausi)*|[Сс](?:езон)*)\s*(?<rightpart>.*)$", RegexOptions.IgnoreCase)]
[GeneratedRegex(@"^\s*((?<seasonnumber>(?>\d+))(?:st|nd|rd|th|\.)*(?!\s*[Ee]\d+))\s*(?:" + SeasonKeywordPattern + @")\s*(?<rightpart>.*)$", RegexOptions.IgnoreCase)]
private static partial Regex ProcessPre();
[GeneratedRegex(@"^\s*(?:[[]*|[]*|[sS](?:eason|æson|aison|taffel|eries|tagione|äsong|eizoen|easong|ezon|ezona|ezóna|ezonul|érie|éria|erie|eria)*|[tT](?:emporada)*|[kK](?:ausi)*|[Сс](?:езон)*)\s*(?<seasonnumber>\d+?)(?=\d{3,4}p|[^\d]|$)(?!\s*[Ee]\d)(?<rightpart>.*)$", RegexOptions.IgnoreCase)]
[GeneratedRegex(@"^\s*(?:" + SeasonKeywordPattern + @")\s*(?<seasonnumber>\d+?)(?=\d{3,4}p|[^\d]|$)(?!\s*[Ee]\d)(?<rightpart>.*)$", RegexOptions.IgnoreCase)]
private static partial Regex ProcessPost();
[GeneratedRegex(@"[sS](\d{1,4})(?!\d|[eE]\d)(?=\.|_|-|\[|\]|\s|$)", RegexOptions.None)]
private static partial Regex SeasonPrefix();
[GeneratedRegex(SeasonKeywordPattern, RegexOptions.IgnoreCase)]
private static partial Regex SeasonKeyword();
/// <summary>
/// Attempts to parse season number from path.
/// </summary>
@@ -91,14 +99,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);
}
}

View File

@@ -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);
}
}