mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-12-06 14:32:56 +01:00
Backport pull request #15404 from jellyfin/release-10.11.z
Improve season folder parsing
Original-merge: 2e5ced5098
Merged-by: crobibero <cody@robibe.ro>
Backported-by: Bond_009 <bond.009@outlook.com>
This commit is contained in:
parent
f848b8f12c
commit
6c5f448787
2 changed files with 31 additions and 30 deletions
|
|
@ -10,12 +10,17 @@ namespace Emby.Naming.TV
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static partial class SeasonPathParser
|
public static partial class SeasonPathParser
|
||||||
{
|
{
|
||||||
|
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)*|[tT](?:emporada)*|[kK](?:ausi)*|[Сс](?:езон)*)\s*(?<rightpart>.*)$", RegexOptions.IgnoreCase)]
|
[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)*|[tT](?:emporada)*|[kK](?:ausi)*|[Сс](?:езон)*)\s*(?<rightpart>.*)$", RegexOptions.IgnoreCase)]
|
||||||
private static partial Regex ProcessPre();
|
private static partial Regex ProcessPre();
|
||||||
|
|
||||||
[GeneratedRegex(@"^\s*(?:[[시즌]*|[シーズン]*|[sS](?:eason|æson|aison|taffel|eries|tagione|äsong|eizoen|easong|ezon|ezona|ezóna|ezonul)*|[tT](?:emporada)*|[kK](?:ausi)*|[Сс](?:езон)*)\s*(?<seasonnumber>(?>\d+)(?!\s*[Ee]\d+))(?<rightpart>.*)$", RegexOptions.IgnoreCase)]
|
[GeneratedRegex(@"^\s*(?:[[시즌]*|[シーズン]*|[sS](?:eason|æson|aison|taffel|eries|tagione|äsong|eizoen|easong|ezon|ezona|ezóna|ezonul)*|[tT](?:emporada)*|[kK](?:ausi)*|[Сс](?:езон)*)\s*(?<seasonnumber>\d+?)(?=\d{3,4}p|[^\d]|$)(?!\s*[Ee]\d)(?<rightpart>.*)$", RegexOptions.IgnoreCase)]
|
||||||
private static partial Regex ProcessPost();
|
private static partial Regex ProcessPost();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"[sS](\d{1,4})(?!\d|[eE]\d)(?=\.|_|-|\[|\]|\s|$)", RegexOptions.None)]
|
||||||
|
private static partial Regex SeasonPrefix();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to parse season number from path.
|
/// Attempts to parse season number from path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -56,44 +61,34 @@ namespace Emby.Naming.TV
|
||||||
bool supportSpecialAliases,
|
bool supportSpecialAliases,
|
||||||
bool supportNumericSeasonFolders)
|
bool supportNumericSeasonFolders)
|
||||||
{
|
{
|
||||||
string filename = Path.GetFileName(path);
|
var fileName = Path.GetFileName(path);
|
||||||
filename = Regex.Replace(filename, "[ ._-]", string.Empty);
|
|
||||||
|
var seasonPrefixMatch = SeasonPrefix().Match(fileName);
|
||||||
|
if (seasonPrefixMatch.Success &&
|
||||||
|
int.TryParse(seasonPrefixMatch.Groups[1].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
|
||||||
|
{
|
||||||
|
return (val, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
string filename = CleanNameRegex.Replace(fileName, string.Empty);
|
||||||
|
|
||||||
if (parentFolderName is not null)
|
if (parentFolderName is not null)
|
||||||
{
|
{
|
||||||
parentFolderName = Regex.Replace(parentFolderName, "[ ._-]", string.Empty);
|
var cleanParent = CleanNameRegex.Replace(parentFolderName, string.Empty);
|
||||||
filename = filename.Replace(parentFolderName, string.Empty, StringComparison.OrdinalIgnoreCase);
|
filename = filename.Replace(cleanParent, string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supportSpecialAliases)
|
if (supportSpecialAliases &&
|
||||||
|
(filename.Equals("specials", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
filename.Equals("extras", StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
if (string.Equals(filename, "specials", StringComparison.OrdinalIgnoreCase))
|
return (0, true);
|
||||||
{
|
|
||||||
return (0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(filename, "extras", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return (0, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supportNumericSeasonFolders)
|
if (supportNumericSeasonFolders &&
|
||||||
|
int.TryParse(filename, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
|
||||||
{
|
{
|
||||||
if (int.TryParse(filename, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
|
return (val, true);
|
||||||
{
|
|
||||||
return (val, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename.Length > 0 && (filename[0] == 'S' || filename[0] == 's'))
|
|
||||||
{
|
|
||||||
var testFilename = filename.AsSpan()[1..];
|
|
||||||
|
|
||||||
if (int.TryParse(testFilename, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
|
|
||||||
{
|
|
||||||
return (val, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var preMatch = ProcessPre().Match(filename);
|
var preMatch = ProcessPre().Match(filename);
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,12 @@ public class SeasonPathParserTests
|
||||||
[InlineData("/media/YouTube/Devyn Johnston/2024-01-24 4070 Ti SUPER in under 7 minutes", "/media/YouTube/Devyn Johnston", null, false)]
|
[InlineData("/media/YouTube/Devyn Johnston/2024-01-24 4070 Ti SUPER in under 7 minutes", "/media/YouTube/Devyn Johnston", null, false)]
|
||||||
[InlineData("/media/YouTube/Devyn Johnston/2025-01-28 5090 vs 2 SFF Cases", "/media/YouTube/Devyn Johnston", null, false)]
|
[InlineData("/media/YouTube/Devyn Johnston/2025-01-28 5090 vs 2 SFF Cases", "/media/YouTube/Devyn Johnston", null, false)]
|
||||||
[InlineData("/Drive/202401244070", "/Drive", null, false)]
|
[InlineData("/Drive/202401244070", "/Drive", null, false)]
|
||||||
|
[InlineData("/Drive/Drive.S01.2160p.WEB-DL.DDP5.1.H.265-XXXX", "/Drive", 1, true)]
|
||||||
|
[InlineData("The Wonder Years/The.Wonder.Years.S04.1080p.PDTV.x264-JCH", "/The Wonder Years", 4, true)]
|
||||||
|
[InlineData("The Wonder Years/[The.Wonder.Years.S04.1080p.PDTV.x264-JCH]", "/The Wonder Years", 4, true)]
|
||||||
|
[InlineData("The Wonder Years/The.Wonder.Years [S04][1080p.PDTV.x264-JCH]", "/The Wonder Years", 4, true)]
|
||||||
|
[InlineData("The Wonder Years/The Wonder Years Season 01 1080p", "/The Wonder Years", 1, true)]
|
||||||
|
|
||||||
public void GetSeasonNumberFromPathTest(string path, string? parentPath, int? seasonNumber, bool isSeasonDirectory)
|
public void GetSeasonNumberFromPathTest(string path, string? parentPath, int? seasonNumber, bool isSeasonDirectory)
|
||||||
{
|
{
|
||||||
var result = SeasonPathParser.Parse(path, parentPath, true, true);
|
var result = SeasonPathParser.Parse(path, parentPath, true, true);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue