8421e3ad5c
Expanded .editorconfig to silence non-critical IDE/StyleCop warnings and updated Emby.Naming.csproj to prevent warnings-as-errors in Debug. Refactored codebase for modern C# style, removed unused code and unnecessary usings, and fixed formatting and StringComparison issues. Added detailed documentation on code style and warning suppression. Project now builds cleanly with only critical issues surfaced.
125 lines
5.3 KiB
C#
125 lines
5.3 KiB
C#
// <copyright file="SeasonPathParser.cs" company="PlaceholderCompany">
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
// </copyright>
|
|
|
|
namespace Emby.Naming.TV
|
|
{
|
|
using System;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
|
|
/// <summary>
|
|
/// Class to parse season paths.
|
|
/// </summary>
|
|
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)]
|
|
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+?)(?=\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();
|
|
|
|
/// <summary>
|
|
/// Attempts to parse season number from path.
|
|
/// </summary>
|
|
/// <param name="path">Path to season.</param>
|
|
/// <param name="parentPath">Folder name of the parent.</param>
|
|
/// <param name="supportSpecialAliases">Support special aliases when parsing.</param>
|
|
/// <param name="supportNumericSeasonFolders">Support numeric season folders when parsing.</param>
|
|
/// <returns>Returns <see cref="SeasonPathParserResult"/> object.</returns>
|
|
public static SeasonPathParserResult Parse(string path, string? parentPath, bool supportSpecialAliases, bool supportNumericSeasonFolders)
|
|
{
|
|
var result = new SeasonPathParserResult();
|
|
var parentFolderName = parentPath is null ? null : new DirectoryInfo(parentPath).Name;
|
|
|
|
var (seasonNumber, isSeasonFolder) = GetSeasonNumberFromPath(path, parentFolderName, supportSpecialAliases, supportNumericSeasonFolders);
|
|
|
|
result.SeasonNumber = seasonNumber;
|
|
|
|
if (result.SeasonNumber.HasValue)
|
|
{
|
|
result.Success = true;
|
|
result.IsSeasonFolder = isSeasonFolder;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the season number from path.
|
|
/// </summary>
|
|
/// <param name="path">The path.</param>
|
|
/// <param name="parentFolderName">The parent folder name.</param>
|
|
/// <param name="supportSpecialAliases">if set to <c>true</c> [support special aliases].</param>
|
|
/// <param name="supportNumericSeasonFolders">if set to <c>true</c> [support numeric season folders].</param>
|
|
/// <returns>System.Nullable{System.Int32}.</returns>
|
|
private static (int? SeasonNumber, bool IsSeasonFolder) GetSeasonNumberFromPath(
|
|
string path,
|
|
string? parentFolderName,
|
|
bool supportSpecialAliases,
|
|
bool supportNumericSeasonFolders)
|
|
{
|
|
var fileName = Path.GetFileName(path);
|
|
|
|
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)
|
|
{
|
|
var cleanParent = CleanNameRegex.Replace(parentFolderName, string.Empty);
|
|
filename = filename.Replace(cleanParent, string.Empty, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
if (supportSpecialAliases &&
|
|
(filename.Equals("specials", StringComparison.OrdinalIgnoreCase) ||
|
|
filename.Equals("extras", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
return (0, true);
|
|
}
|
|
|
|
if (supportNumericSeasonFolders &&
|
|
int.TryParse(filename, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
|
|
{
|
|
return (val, true);
|
|
}
|
|
|
|
var preMatch = ProcessPre().Match(filename);
|
|
if (preMatch.Success)
|
|
{
|
|
return CheckMatch(preMatch);
|
|
}
|
|
else
|
|
{
|
|
var postMatch = ProcessPost().Match(filename);
|
|
return CheckMatch(postMatch);
|
|
}
|
|
}
|
|
|
|
private static (int? SeasonNumber, bool IsSeasonFolder) CheckMatch(Match match)
|
|
{
|
|
var numberString = match.Groups["seasonnumber"];
|
|
if (numberString.Success)
|
|
{
|
|
if (int.TryParse(numberString.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var seasonNumber))
|
|
{
|
|
return (seasonNumber, true);
|
|
}
|
|
}
|
|
|
|
return (null, false);
|
|
}
|
|
}
|
|
}
|