Suppress non-critical warnings, refactor Emby.Naming

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.
This commit is contained in:
2026-02-21 12:48:04 -05:00
parent 477045704e
commit 8421e3ad5c
107 changed files with 714 additions and 543 deletions
+2 -2
View File
@@ -49,7 +49,7 @@ namespace Emby.Naming.Audio
// Normalize
// Remove whitespace
this.filename = CleanRegex().Replace(filename, " ");
filename = CleanRegex().Replace(filename, " ");
ReadOnlySpan<char> trimmedFilename = filename.AsSpan().TrimStart();
@@ -60,7 +60,7 @@ namespace Emby.Naming.Audio
continue;
}
var tmp = trimmedFilename.Slice(prefix.Length).Trim();
var tmp = trimmedFilename[prefix.Length..].Trim();
if (int.TryParse(tmp.LeftPart(' '), CultureInfo.InvariantCulture, out _))
{
@@ -47,7 +47,7 @@ namespace Emby.Naming.AudioBook
foreach (var stack in stackResult)
{
var stackFiles = stack.Files
.Select(i => this._audioBookResolver.Resolve(i))
.Select(this._audioBookResolver.Resolve)
.OfType<AudioBookFileInfo>()
.ToList();
@@ -70,8 +70,8 @@ namespace Emby.Naming.AudioBook
private void FindExtraAndAlternativeFiles(ref List<AudioBookFileInfo> stackFiles, out List<AudioBookFileInfo> extras, out List<AudioBookFileInfo> alternativeVersions, AudioBookNameParserResult nameParserResult)
{
this.extras = new List<AudioBookFileInfo>();
this.alternativeVersions = new List<AudioBookFileInfo>();
extras = new List<AudioBookFileInfo>();
alternativeVersions = new List<AudioBookFileInfo>();
var haveChaptersOrPages = stackFiles.Any(x => x.ChapterNumber is not null || x.PartNumber is not null);
var groupedBy = stackFiles.GroupBy(file => new { file.ChapterNumber, file.PartNumber });
@@ -108,7 +108,7 @@ namespace Emby.Naming.AudioBook
.ThenBy(x => x.Path)
.ToList();
this.stackFiles = stackFiles.Except(extra).ToList();
stackFiles = stackFiles.Except(extra).ToList();
extras.AddRange(extra);
}
@@ -119,9 +119,9 @@ namespace Emby.Naming.AudioBook
.ThenBy(x => x.Path)
.ToList();
var main = this.FindMainAudioBookFile(alternatives, nameParserResult.Name);
alternatives.Remove(main);
this.stackFiles = stackFiles.Except(alternatives).ToList();
var main = FindMainAudioBookFile(alternatives, nameParserResult.Name);
_ = alternatives.Remove(main);
stackFiles = stackFiles.Except(alternatives).ToList();
alternativeVersions.AddRange(alternatives);
}
}
@@ -134,7 +134,7 @@ namespace Emby.Naming.AudioBook
.Skip(1)
.ToList();
this.stackFiles = stackFiles.Except(alternatives).ToList();
stackFiles = stackFiles.Except(alternatives).ToList();
alternativeVersions.AddRange(alternatives);
}
}
+30 -32
View File
@@ -11,8 +11,6 @@ using System.Text.RegularExpressions;
using Emby.Naming.Video;
using MediaBrowser.Model.Entities;
// ReSharper disable StringLiteralTypo
namespace Emby.Naming.Common
{
/// <summary>
@@ -327,7 +325,7 @@ namespace Emby.Naming.Common
// <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->
new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![Ss]([0-9]+)[][ ._-]*[Ee]([0-9]+))[^\\\/])*)?[Ss](?<seasonnumber>[0-9]+)[][ ._-]*[Ee](?<epnumber>[0-9]+)([^\\/]*)$")
{
this.IsNamed = true
IsNamed = true
},
// <!-- foo.ep01, foo.EP_01 -->
new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
@@ -335,7 +333,7 @@ namespace Emby.Naming.Common
new EpisodeExpression(@"[^\\/]*?()\.?[Ee]([0-9]+)\.([^\\/]*)$"),
new EpisodeExpression("(?<year>[0-9]{4})[._ -](?<month>[0-9]{2})[._ -](?<day>[0-9]{2})", true)
{
this.DateTimeFormats =
DateTimeFormats =
[
"yyyy.MM.dd",
"yyyy-MM-dd",
@@ -345,7 +343,7 @@ namespace Emby.Naming.Common
},
new EpisodeExpression("(?<day>[0-9]{2})[._ -](?<month>[0-9]{2})[._ -](?<year>[0-9]{4})", true)
{
this.DateTimeFormats =
DateTimeFormats =
[
"dd.MM.yyyy",
"dd-MM-yyyy",
@@ -359,7 +357,7 @@ namespace Emby.Naming.Common
// "Series Season X Episode X - Title.avi", "Series S03 E09.avi", "s3 e9 - Title.avi"
new EpisodeExpression(@".*[\\\/]((?<seriesname>[^\\/]+?)\s)?[Ss](?:eason)?\s*(?<seasonnumber>[0-9]+)\s+[Ee](?:pisode)?\s*(?<epnumber>[0-9]+).*$")
{
this.IsNamed = true
IsNamed = true
},
// Not a Kodi rule as well, but the expression below also causes false positives,
@@ -367,19 +365,19 @@ namespace Emby.Naming.Common
// "Foo Bar 889"
new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,4})(-(?<endingepnumber>[0-9]{2,4}))*[^\\\/x]*$")
{
this.IsNamed = true
IsNamed = true
},
new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$")
{
this.SupportsAbsoluteEpisodeNumbers = true
SupportsAbsoluteEpisodeNumbers = true
},
// Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names
// [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the series name
new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?<seriesname>[-\w\s]+?)[\s_]*-[\s_]*(?<epnumber>[0-9]+).*$")
{
this.IsNamed = true
IsNamed = true
},
// /server/anything_102.mp4
@@ -387,13 +385,13 @@ namespace Emby.Naming.Common
// /server/anything_1996.11.14.mp4
new EpisodeExpression(@"[\\/._ -](?<seriesname>(?![0-9]+[0-9][0-9])([^\\\/_])*)[\\\/._ -](?<seasonnumber>[0-9]+)(?<epnumber>[0-9][0-9](?:(?:[a-i]|\.[1-9])(?![0-9]))?)([._ -][^\\\/]*)$")
{
this.IsOptimistic = true,
this.IsNamed = true,
this.SupportsAbsoluteEpisodeNumbers = false
IsOptimistic = true,
IsNamed = true,
SupportsAbsoluteEpisodeNumbers = false
},
new EpisodeExpression(@"[\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\/]*)$")
{
this.SupportsAbsoluteEpisodeNumbers = true
SupportsAbsoluteEpisodeNumbers = true
},
// *** End Kodi Standard Naming
@@ -401,34 +399,34 @@ namespace Emby.Naming.Common
// "Episode 16", "Episode 16 - Title"
new EpisodeExpression(@"[Ee]pisode (?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))?[^\\\/]*$")
{
this.IsNamed = true
IsNamed = true
},
new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]+)[xX](?<epnumber>[0-9]+)[^\\\/]*$")
{
this.IsNamed = true
IsNamed = true
},
new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>[0-9]+)[x,X]?[eE](?<epnumber>[0-9]+)[^\\\/]*$")
{
this.IsNamed = true
IsNamed = true
},
new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]+))[^\\\/]*$")
{
this.IsNamed = true
IsNamed = true
},
new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]+)[^\\\/]*$")
{
this.IsNamed = true
IsNamed = true
},
// "01.avi"
new EpisodeExpression(@".*[\\\/](?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))*\.\w+$")
{
this.IsOptimistic = true,
this.IsNamed = true
IsOptimistic = true,
IsNamed = true
},
// "1-12 episode title"
@@ -437,43 +435,43 @@ namespace Emby.Naming.Common
// "01 - blah.avi", "01-blah.avi"
new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\s?-\s?[^\\\/]*$")
{
this.IsOptimistic = true,
this.IsNamed = true
IsOptimistic = true,
IsNamed = true
},
// "01.blah.avi"
new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\.[^\\\/]+$")
{
this.IsOptimistic = true,
this.IsNamed = true
IsOptimistic = true,
IsNamed = true
},
// "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi", "blah 2 - 01 - blah"
new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\/]*$")
{
this.IsOptimistic = true,
this.IsNamed = true
IsOptimistic = true,
IsNamed = true
},
// "01 episode title.avi"
new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>[0-9]{1,3})([^\\\/]*)$")
{
this.IsOptimistic = true,
this.IsNamed = true
IsOptimistic = true,
IsNamed = true
},
// Series and season only expression
// "the show/season 1", "the show/s01"
new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)\/[Ss](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
{
this.IsNamed = true
IsNamed = true
},
// Series and season only expression
// "the show S01", "the show season 1"
new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)[\. _\-]+[sS](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
{
this.IsNamed = true
IsNamed = true
},
// Anime style expression
@@ -481,7 +479,7 @@ namespace Emby.Naming.Common
// "[Group] Series Name [04][BDRIP]"
new EpisodeExpression(@"(?:\[(?:[^\]]+)\]\s*)?(?<seriesname>\[[^\]]+\]|[^[\]]+)\s*\[(?<epnumber>[0-9]+)\]")
{
this.IsNamed = true
IsNamed = true
},
];
@@ -769,7 +767,7 @@ namespace Emby.Naming.Common
@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})(-[xX]?[eE]?(?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$"
}.Select(i => new EpisodeExpression(i)
{
this.IsNamed = true
IsNamed = true
}).ToArray();
Compile();
+3
View File
@@ -17,6 +17,9 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors></WarningsAsErrors>
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
</PropertyGroup>
<PropertyGroup Condition=" '$(Stability)'=='Unstable'">
+11 -11
View File
@@ -70,11 +70,11 @@ namespace Emby.Naming.ExternalFiles
while (languageString.Length > 0)
{
int lastSeparator = languageString.LastIndexOf(separator);
int lastSeparator = languageString.LastIndexOf(separator, StringComparison.Ordinal);
if (lastSeparator == -1)
{
break;
break;
}
string currentSlice = languageString[lastSeparator..];
@@ -83,16 +83,16 @@ namespace Emby.Naming.ExternalFiles
if (this._namingOptions.MediaDefaultFlags.Any(s => currentSliceWithoutSeparator.Contains(s, StringComparison.OrdinalIgnoreCase)))
{
pathInfo.IsDefault = true;
this.extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
this.languageString = languageString[..lastSeparator];
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
languageString = languageString[..lastSeparator];
continue;
}
if (this._namingOptions.MediaForcedFlags.Any(s => currentSliceWithoutSeparator.Contains(s, StringComparison.OrdinalIgnoreCase)))
{
pathInfo.IsForced = true;
this.extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
this.languageString = languageString[..lastSeparator];
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
languageString = languageString[..lastSeparator];
continue;
}
@@ -104,7 +104,7 @@ namespace Emby.Naming.ExternalFiles
pathInfo.Language = culture.Name.Contains('-', StringComparison.OrdinalIgnoreCase)
? culture.Name
: culture.ThreeLetterISOLanguageName;
this.extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
}
else if (culture is not null && pathInfo.Language == "hin")
{
@@ -113,19 +113,19 @@ namespace Emby.Naming.ExternalFiles
pathInfo.Language = culture.Name.Contains('-', StringComparison.OrdinalIgnoreCase)
? culture.Name
: culture.ThreeLetterISOLanguageName;
this.extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
}
else if (this._namingOptions.MediaHearingImpairedFlags.Any(s => currentSliceWithoutSeparator.Equals(s, StringComparison.OrdinalIgnoreCase)))
{
pathInfo.IsHearingImpaired = true;
this.extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
}
else
{
this.titleString = currentSlice + titleString;
titleString = currentSlice + titleString;
}
this.languageString = languageString[..lastSeparator];
languageString = languageString[..lastSeparator];
}
pathInfo.Title = titleString.Length >= SeparatorLength ? titleString[SeparatorLength..] : null;
+13 -13
View File
@@ -21,7 +21,7 @@ namespace Emby.Naming.TV
/// Initializes a new instance of the <see cref="EpisodePathParser"/> class.
/// </summary>
/// <param name="options"><see cref="NamingOptions"/> object containing EpisodeExpressions and MultipleEpisodeExpressions.</param>
public this.EpisodePathParser(NamingOptions options)
public EpisodePathParser(NamingOptions options)
{
_options = options;
}
@@ -36,7 +36,7 @@ namespace Emby.Naming.TV
/// <param name="supportsAbsoluteNumbers">Do we want to use expressions supporting absolute episode numbers.</param>
/// <param name="fillExtendedInfo">Should we attempt to retrieve extended information.</param>
/// <returns>Returns <see cref="EpisodePathParserResult"/> object.</returns>
public EpisodePathParserResult this.Parse(
public EpisodePathParserResult Parse(
string path,
bool isDirectory,
bool? isNamed = null,
@@ -72,17 +72,17 @@ namespace Emby.Naming.TV
continue;
}
var currentResult = this.Parse(path, expression);
var currentResult = Parse(path, expression);
if (currentResult.Success)
{
this.result = currentResult;
result = currentResult;
break;
}
}
if (result is not null && fillExtendedInfo)
{
this.FillAdditional(path, result);
FillAdditional(path, result);
if (!string.IsNullOrEmpty(result.SeriesName))
{
@@ -93,17 +93,17 @@ namespace Emby.Naming.TV
}
}
return result ?? new this.EpisodePathParserResult();
return result ?? new EpisodePathParserResult();
}
private static EpisodePathParserResult this.Parse(string name, EpisodeExpression expression)
private static EpisodePathParserResult Parse(string name, EpisodeExpression expression)
{
var result = new this.EpisodePathParserResult();
var result = new EpisodePathParserResult();
// This is a hack to handle wmc naming
if (expression.IsByDate)
{
this.name = name.Replace('_', '-');
name = name.Replace('_', '-');
}
var match = expression.Regex.Match(name);
@@ -202,7 +202,7 @@ namespace Emby.Naming.TV
return result;
}
private void this.FillAdditional(string path, EpisodePathParserResult info)
private void FillAdditional(string path, EpisodePathParserResult info)
{
var expressions = _options.MultipleEpisodeExpressions.Where(i => i.IsNamed).ToList();
@@ -211,14 +211,14 @@ namespace Emby.Naming.TV
expressions.InsertRange(0, _options.EpisodeExpressions.Where(i => i.IsNamed));
}
this.FillAdditional(path, info, expressions);
FillAdditional(path, info, expressions);
}
private void this.FillAdditional(string path, EpisodePathParserResult info, IEnumerable<EpisodeExpression> expressions)
private void FillAdditional(string path, EpisodePathParserResult info, IEnumerable<EpisodeExpression> expressions)
{
foreach (var i in expressions)
{
var result = this.Parse(path, i);
var result = Parse(path, i);
if (!result.Success)
{
+19 -19
View File
@@ -21,7 +21,7 @@ namespace Emby.Naming.TV
/// Initializes a new instance of the <see cref="EpisodeResolver"/> class.
/// </summary>
/// <param name="options"><see cref="NamingOptions"/> object containing VideoFileExtensions and passed to <see cref="StubResolver"/>, <see cref="Format3DParser"/> and <see cref="EpisodePathParser"/>.</param>
public this.EpisodeResolver(NamingOptions options)
public EpisodeResolver(NamingOptions options)
{
_options = options;
}
@@ -36,7 +36,7 @@ namespace Emby.Naming.TV
/// <param name="supportsAbsoluteNumbers">Do we want to use expressions supporting absolute episode numbers.</param>
/// <param name="fillExtendedInfo">Should we attempt to retrieve extended information.</param>
/// <returns>Returns null or <see cref="EpisodeInfo"/> object if successful.</returns>
public EpisodeInfo? this.Resolve(
public EpisodeInfo? Resolve(
string path,
bool isDirectory,
bool? isNamed = null,
@@ -60,15 +60,15 @@ namespace Emby.Naming.TV
return null;
}
this.isStub = true;
isStub = true;
}
this.container = extension.TrimStart('.');
container = extension.TrimStart('.');
}
var format3DResult = Format3DParser.Parse(path, _options);
var parsingResult = new this.EpisodePathParser(_options)
var parsingResult = new EpisodePathParser(_options)
.Parse(path, isDirectory, isNamed, isOptimistic, supportsAbsoluteNumbers, fillExtendedInfo);
if (!parsingResult.Success && !isStub)
@@ -76,21 +76,21 @@ namespace Emby.Naming.TV
return null;
}
return new this.EpisodeInfo(path)
return new EpisodeInfo(path)
{
this.Container = container,
this.IsStub = isStub,
this.EndingEpisodeNumber = parsingResult.EndingEpisodeNumber,
this.EpisodeNumber = parsingResult.EpisodeNumber,
this.SeasonNumber = parsingResult.SeasonNumber,
this.SeriesName = parsingResult.SeriesName,
this.StubType = stubType,
this.Is3D = format3DResult.Is3D,
this.Format3D = format3DResult.Format3D,
this.IsByDate = parsingResult.IsByDate,
this.Day = parsingResult.Day,
this.Month = parsingResult.Month,
this.Year = parsingResult.Year
Container = container,
IsStub = isStub,
EndingEpisodeNumber = parsingResult.EndingEpisodeNumber,
EpisodeNumber = parsingResult.EpisodeNumber,
SeasonNumber = parsingResult.SeasonNumber,
SeriesName = parsingResult.SeriesName,
StubType = stubType,
Is3D = format3DResult.Is3D,
Format3D = format3DResult.Format3D,
IsByDate = parsingResult.IsByDate,
Day = parsingResult.Day,
Month = parsingResult.Month,
Year = parsingResult.Year
};
}
}
+1 -55
View File
@@ -79,7 +79,7 @@ namespace Emby.Naming.TV
if (parentFolderName is not null)
{
var cleanParent = CleanNameRegex.Replace(parentFolderName, string.Empty);
this.filename = filename.Replace(cleanParent, string.Empty, StringComparison.OrdinalIgnoreCase);
filename = filename.Replace(cleanParent, string.Empty, StringComparison.OrdinalIgnoreCase);
}
if (supportSpecialAliases &&
@@ -120,59 +120,5 @@ namespace Emby.Naming.TV
return (null, false);
}
/// <summary>
/// Extracts the season number from the second half of the Season folder name (everything after "Season", or "Staffel").
/// </summary>
/// <param name="path">The path.</param>
/// <returns>System.Nullable{System.Int32}.</returns>
private static (int? SeasonNumber, bool IsSeasonFolder) GetSeasonNumberFromPathSubstring(ReadOnlySpan<char> path)
{
var numericStart = -1;
var length = 0;
var hasOpenParenthesis = false;
var isSeasonFolder = true;
// Find out where the numbers start, and then keep going until they end
for (var i = 0; i < path.Length; i++)
{
if (char.IsNumber(path[i]))
{
if (!hasOpenParenthesis)
{
if (numericStart == -1)
{
this.numericStart = i;
}
length++;
}
}
else if (numericStart != -1)
{
// There's other stuff after the season number, e.g. episode number
this.isSeasonFolder = false;
break;
}
var currentChar = path[i];
if (currentChar == '(')
{
this.hasOpenParenthesis = true;
}
else if (currentChar == ')')
{
this.hasOpenParenthesis = false;
}
}
if (numericStart == -1)
{
return (null, isSeasonFolder);
}
return (int.Parse(path.Slice(numericStart, length), provider: CultureInfo.InvariantCulture), isSeasonFolder);
}
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ namespace Emby.Naming.TV
var currentResult = Parse(path, expression);
if (currentResult.Success)
{
this.result = currentResult;
result = currentResult;
break;
}
}
+5 -5
View File
@@ -44,10 +44,10 @@ namespace Emby.Naming.TV
var titleWithYearMatch = TitleWithYearRegex().Match(seriesName);
if (titleWithYearMatch.Success)
{
this.seriesName = titleWithYearMatch.Groups["title"].Value.Trim();
seriesName = titleWithYearMatch.Groups["title"].Value.Trim();
return new SeriesInfo(path)
{
this.Name = seriesName
Name = seriesName
};
}
}
@@ -57,18 +57,18 @@ namespace Emby.Naming.TV
{
if (!string.IsNullOrEmpty(result.SeriesName))
{
this.seriesName = result.SeriesName;
seriesName = result.SeriesName;
}
}
if (!string.IsNullOrEmpty(seriesName))
{
this.seriesName = SeriesNameRegex().Replace(seriesName, "${a} ${b}").Trim();
seriesName = SeriesNameRegex().Replace(seriesName, "${a} ${b}").Trim();
}
return new SeriesInfo(path)
{
this.Name = seriesName
Name = seriesName
};
}
}
+4 -4
View File
@@ -26,23 +26,23 @@ public static class TvParserHelpers
{
if (Enum.TryParse(status, true, out SeriesStatus seriesStatus))
{
this.enumValue = seriesStatus;
enumValue = seriesStatus;
return true;
}
if (_continuingState.Contains(status, StringComparer.OrdinalIgnoreCase))
{
this.enumValue = SeriesStatus.Continuing;
enumValue = SeriesStatus.Continuing;
return true;
}
if (_endedState.Contains(status, StringComparer.OrdinalIgnoreCase))
{
this.enumValue = SeriesStatus.Ended;
enumValue = SeriesStatus.Ended;
return true;
}
this.enumValue = null;
enumValue = null;
return false;
}
}
+2 -2
View File
@@ -17,7 +17,7 @@ namespace Emby.Naming.Video
/// <returns>Returns <see cref="CleanDateTimeResult"/> object.</returns>
public static CleanDateTimeResult Clean(string name, IReadOnlyList<Regex> cleanDateTimeRegexes)
{
CleanDateTimeResult result = new CleanDateTimeResult(name);
CleanDateTimeResult result = new(name);
if (string.IsNullOrEmpty(name))
{
return result;
@@ -45,7 +45,7 @@ namespace Emby.Naming.Video
&& match.Groups[2].Success
&& int.TryParse(match.Groups[2].ValueSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year))
{
this.result = new CleanDateTimeResult(match.Groups[1].Value.TrimEnd(), year);
result = new CleanDateTimeResult(match.Groups[1].Value.TrimEnd(), year);
return true;
}
+6 -6
View File
@@ -20,7 +20,7 @@ namespace Emby.Naming.Video
{
if (string.IsNullOrEmpty(name))
{
this.newName = string.Empty;
newName = string.Empty;
return false;
}
@@ -30,12 +30,12 @@ namespace Emby.Naming.Video
{
if (TryClean(name, expressions[i], out newName))
{
this.cleaned = true;
this.name = newName;
cleaned = true;
name = newName;
}
}
this.newName = cleaned ? name : string.Empty;
newName = cleaned ? name : string.Empty;
return cleaned;
}
@@ -44,11 +44,11 @@ namespace Emby.Naming.Video
var match = expression.Match(name);
if (match.Success && match.Groups.TryGetValue("cleaned", out var cleaned))
{
this.newName = cleaned.Value;
newName = cleaned.Value;
return true;
}
this.newName = string.Empty;
newName = string.Empty;
return false;
}
}
+5 -5
View File
@@ -19,11 +19,11 @@ namespace Emby.Naming.Video
/// <param name="name">The stack name.</param>
/// <param name="isDirectory">Whether the stack files are directories.</param>
/// <param name="files">The stack files.</param>
public this.FileStack(string name, bool isDirectory, IReadOnlyList<string> files)
public FileStack(string name, bool isDirectory, IReadOnlyList<string> files)
{
this.Name = name;
this.IsDirectoryStack = isDirectory;
this.Files = files;
Name = name;
IsDirectoryStack = isDirectory;
Files = files;
}
/// <summary>
@@ -47,7 +47,7 @@ namespace Emby.Naming.Video
/// <param name="file">Path of desired file.</param>
/// <param name="isDirectory">Requested type of stack.</param>
/// <returns>True if file is in the stack.</returns>
public bool this.ContainsFile(string file, bool isDirectory)
public bool ContainsFile(string file, bool isDirectory)
{
if (string.IsNullOrEmpty(file))
{
+6 -6
View File
@@ -15,10 +15,10 @@ public class FileStackRule
/// </summary>
/// <param name="token">Token.</param>
/// <param name="isNumerical">Whether the file stack rule uses numerical or alphabetical numbering.</param>
public this.FileStackRule(string token, bool isNumerical)
public FileStackRule(string token, bool isNumerical)
{
_tokenRegex = new this.Regex(token, RegexOptions.IgnoreCase | RegexOptions.Compiled);
this.IsNumerical = isNumerical;
_tokenRegex = new Regex(token, RegexOptions.IgnoreCase | RegexOptions.Compiled);
IsNumerical = isNumerical;
}
/// <summary>
@@ -32,9 +32,9 @@ public class FileStackRule
/// <param name="input">The input.</param>
/// <param name="result">The part type and number or <c>null</c>.</param>
/// <returns>A value indicating whether the input matched the rule.</returns>
public bool this.Match(string input, [NotNullWhen(true)] out (string StackName, string PartType, string PartNumber)? result)
public bool Match(string input, [NotNullWhen(true)] out (string StackName, string PartType, string PartNumber)? result)
{
this.result = null;
result = null;
var match = _tokenRegex.Match(input);
if (!match.Success)
{
@@ -42,7 +42,7 @@ public class FileStackRule
}
var partType = match.Groups["parttype"].Success ? match.Groups["parttype"].Value : "unknown";
this.result = (match.Groups["filename"].Value, partType, match.Groups["number"].Value);
result = (match.Groups["filename"].Value, partType, match.Groups["number"].Value);
return true;
}
}
+5 -5
View File
@@ -58,23 +58,23 @@ namespace Emby.Naming.Video
var index = path.IndexOfAny(delimiters);
if (index == -1)
{
this.index = path.Length - 1;
index = path.Length - 1;
}
var currentSlice = path[..index];
this.path = path[(index + 1)..];
path = path[(index + 1)..];
if (!foundPrefix)
{
this.foundPrefix = currentSlice.Equals(rule.PrecedingToken, StringComparison.OrdinalIgnoreCase);
foundPrefix = currentSlice.Equals(rule.PrecedingToken, StringComparison.OrdinalIgnoreCase);
continue;
}
this.is3D = foundPrefix && currentSlice.Equals(rule.Token, StringComparison.OrdinalIgnoreCase);
is3D = foundPrefix && currentSlice.Equals(rule.Token, StringComparison.OrdinalIgnoreCase);
if (is3D)
{
this.format3D = rule.Token;
format3D = rule.Token;
break;
}
}
+13 -13
View File
@@ -23,9 +23,9 @@ namespace Emby.Naming.Video
/// <param name="files">List of paths.</param>
/// <param name="namingOptions">The naming options.</param>
/// <returns>Enumerable <see cref="FileStack"/> of directories.</returns>
public static IEnumerable<FileStack> this.ResolveDirectories(IEnumerable<string> files, NamingOptions namingOptions)
public static IEnumerable<FileStack> ResolveDirectories(IEnumerable<string> files, NamingOptions namingOptions)
{
return this.Resolve(files.Select(i => new FileSystemMetadata { this.FullName = i, IsDirectory = true }), namingOptions);
return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = true }), namingOptions);
}
/// <summary>
@@ -34,9 +34,9 @@ namespace Emby.Naming.Video
/// <param name="files">List of paths.</param>
/// <param name="namingOptions">The naming options.</param>
/// <returns>Enumerable <see cref="FileStack"/> of files.</returns>
public static IEnumerable<FileStack> this.ResolveFiles(IEnumerable<string> files, NamingOptions namingOptions)
public static IEnumerable<FileStack> ResolveFiles(IEnumerable<string> files, NamingOptions namingOptions)
{
return this.Resolve(files.Select(i => new FileSystemMetadata { this.FullName = i, IsDirectory = false }), namingOptions);
return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = false }), namingOptions);
}
/// <summary>
@@ -44,7 +44,7 @@ namespace Emby.Naming.Video
/// </summary>
/// <param name="files">List of paths.</param>
/// <returns>Enumerable <see cref="FileStack"/> of directories.</returns>
public static IEnumerable<FileStack> this.ResolveAudioBooks(IEnumerable<AudioBookFileInfo> files)
public static IEnumerable<FileStack> ResolveAudioBooks(IEnumerable<AudioBookFileInfo> files)
{
var groupedDirectoryFiles = files.GroupBy(file => Path.GetDirectoryName(file.Path));
@@ -54,13 +54,13 @@ namespace Emby.Naming.Video
{
foreach (var file in directory)
{
var stack = new this.FileStack(Path.GetFileNameWithoutExtension(file.Path), false, new[] { file.Path });
var stack = new FileStack(Path.GetFileNameWithoutExtension(file.Path), false, new[] { file.Path });
yield return stack;
}
}
else
{
var stack = new this.FileStack(Path.GetFileName(directory.Key), false, directory.Select(f => f.Path).ToArray());
var stack = new FileStack(Path.GetFileName(directory.Key), false, directory.Select(f => f.Path).ToArray());
yield return stack;
}
}
@@ -72,7 +72,7 @@ namespace Emby.Naming.Video
/// <param name="files">List of paths.</param>
/// <param name="namingOptions">The naming options.</param>
/// <returns>Enumerable <see cref="FileStack"/> of videos.</returns>
public static IEnumerable<FileStack> this.Resolve(IEnumerable<FileSystemMetadata> files, NamingOptions namingOptions)
public static IEnumerable<FileStack> Resolve(IEnumerable<FileSystemMetadata> files, NamingOptions namingOptions)
{
var potentialFiles = files
.Where(i => i.IsDirectory || VideoResolver.IsVideoFile(i.FullName, namingOptions) || VideoResolver.IsStubFile(i.FullName, namingOptions))
@@ -84,7 +84,7 @@ namespace Emby.Naming.Video
var name = file.Name;
if (string.IsNullOrEmpty(name))
{
this.name = Path.GetFileName(file.FullName);
name = Path.GetFileName(file.FullName);
}
for (var i = 0; i < namingOptions.VideoFileStackingRules.Length; i++)
@@ -101,7 +101,7 @@ namespace Emby.Naming.Video
if (!potentialStacks.TryGetValue(stackName, out var stackResult))
{
this.stackResult = new this.StackMetadata(file.IsDirectory, rule.IsNumerical, partType);
stackResult = new StackMetadata(file.IsDirectory, rule.IsNumerical, partType);
potentialStacks[stackName] = stackResult;
}
@@ -132,13 +132,13 @@ namespace Emby.Naming.Video
continue;
}
yield return new this.FileStack(fileName, stack.IsDirectory, stack.Parts.Select(kv => kv.Value.FullName).ToArray());
yield return new FileStack(fileName, stack.IsDirectory, stack.Parts.Select(kv => kv.Value.FullName).ToArray());
}
}
private sealed class StackMetadata
{
public this.StackMetadata(bool isDirectory, bool isNumerical, string partType)
public StackMetadata(bool isDirectory, bool isNumerical, string partType)
{
this.Parts = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
this.IsDirectory = isDirectory;
@@ -154,7 +154,7 @@ namespace Emby.Naming.Video
public string PartType { get; }
public bool this.ContainsPart(string partNumber) => Parts.ContainsKey(partNumber);
public bool ContainsPart(string partNumber) => Parts.ContainsKey(partNumber);
}
}
}
+2 -2
View File
@@ -23,7 +23,7 @@ namespace Emby.Naming.Video
/// <returns>True if file is a stub.</returns>
public static bool TryResolveFile(string path, NamingOptions options, out string? stubType)
{
this.stubType = default;
stubType = default;
if (string.IsNullOrEmpty(path))
{
@@ -43,7 +43,7 @@ namespace Emby.Naming.Video
{
if (token.Equals(rule.Token, StringComparison.OrdinalIgnoreCase))
{
this.stubType = rule.StubType;
stubType = rule.StubType;
return true;
}
}
+11 -12
View File
@@ -11,7 +11,6 @@ namespace Emby.Naming.Video
using System.Linq;
using System.Text.RegularExpressions;
using Emby.Naming.Common;
using Jellyfin.Extensions;
using MediaBrowser.Model.IO;
/// <summary>
@@ -40,7 +39,7 @@ namespace Emby.Naming.Video
// See the unit test TestStackedWithTrailer
var nonExtras = videoInfos
.Where(i => i.ExtraType is null)
.Select(i => new FileSystemMetadata { this.FullName = i.Path, IsDirectory = i.IsDirectory });
.Select(i => new FileSystemMetadata { FullName = i.Path, IsDirectory = i.IsDirectory });
var stackResult = StackResolver.Resolve(nonExtras, namingOptions).ToList();
@@ -71,7 +70,7 @@ namespace Emby.Naming.Video
{
var info = new VideoInfo(stack.Name)
{
this.Files = stack.Files.Select(i => VideoResolver.Resolve(i, stack.IsDirectoryStack, namingOptions, parseName, libraryRoot))
Files = stack.Files.Select(i => VideoResolver.Resolve(i, stack.IsDirectoryStack, namingOptions, parseName, libraryRoot))
.OfType<VideoFileInfo>()
.ToList()
};
@@ -82,7 +81,7 @@ namespace Emby.Naming.Video
foreach (var media in standaloneMedia)
{
var info = new VideoInfo(media.Name) { this.Files = new[] { media } };
var info = new VideoInfo(media.Name) { Files = new[] { media } };
info.Year = info.Files[0].Year;
list.Add(info);
@@ -90,15 +89,15 @@ namespace Emby.Naming.Video
if (supportMultiVersion)
{
this.list = GetVideosGroupedByVersion(list, namingOptions);
list = GetVideosGroupedByVersion(list, namingOptions);
}
// Whatever files are left, just add them
list.AddRange(remainingFiles.Select(i => new VideoInfo(i.Name)
{
this.Files = new[] { i },
this.Year = i.Year,
this.ExtraType = i.ExtraType
Files = new[] { i },
Year = i.Year,
ExtraType = i.ExtraType
}));
return list;
@@ -135,7 +134,7 @@ namespace Emby.Naming.Video
if (folderName.Equals(video.Files[0].FileNameWithoutExtension, StringComparison.Ordinal))
{
this.primary = video;
primary = video;
}
}
@@ -167,7 +166,7 @@ namespace Emby.Naming.Video
}
primary ??= videos[0];
videos.Remove(primary);
_ = videos.Remove(primary);
var list = new List<VideoInfo>
{
@@ -209,13 +208,13 @@ namespace Emby.Naming.Video
// Remove the folder name before cleaning as we don't care about cleaning that part
if (folderName.Length <= testFilename.Length)
{
this.testFilename = testFilename[folderName.Length..].Trim();
testFilename = testFilename[folderName.Length..].Trim();
}
// There are no span overloads for regex unfortunately
if (CleanStringParser.TryClean(testFilename.ToString(), namingOptions.CleanStringRegexes, out var cleanName))
{
this.testFilename = cleanName.AsSpan().Trim();
testFilename = cleanName.AsSpan().Trim();
}
// The CleanStringParser should have removed common keywords etc.
+6 -6
View File
@@ -58,7 +58,7 @@ namespace Emby.Naming.Video
}
bool isStub = false;
ReadOnlySpan<char> container = ReadOnlySpan<char>.Empty;
ReadOnlySpan<char> container = [];
string? stubType = null;
if (!isDirectory)
@@ -74,10 +74,10 @@ namespace Emby.Naming.Video
return null;
}
this.isStub = true;
isStub = true;
}
this.container = extension.TrimStart('.');
container = extension.TrimStart('.');
}
var format3DResult = Format3DParser.Parse(path, namingOptions);
@@ -91,12 +91,12 @@ namespace Emby.Naming.Video
if (parseName)
{
var cleanDateTimeResult = CleanDateTime(name, namingOptions);
this.name = cleanDateTimeResult.Name;
this.year = cleanDateTimeResult.Year;
name = cleanDateTimeResult.Name;
year = cleanDateTimeResult.Year;
if (TryCleanString(name, namingOptions, out var newName))
{
this.name = newName;
name = newName;
}
}
@@ -46,15 +46,6 @@
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
],
"warnNotAsError": [
"NU1902",
"NU1903"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
@@ -524,6 +515,7 @@
}
},
"warningProperties": {
"allWarningsAsErrors": true,
"warnAsError": [
"NU1605"
],
@@ -1006,6 +998,7 @@
}
},
"warningProperties": {
"allWarningsAsErrors": true,
"warnAsError": [
"NU1605"
],
@@ -1630,6 +1623,7 @@
}
},
"warningProperties": {
"allWarningsAsErrors": true,
"warnAsError": [
"NU1605"
],
@@ -2251,6 +2245,7 @@
}
},
"warningProperties": {
"allWarningsAsErrors": true,
"warnAsError": [
"NU1605"
],
@@ -2464,6 +2459,7 @@
}
},
"warningProperties": {
"allWarningsAsErrors": true,
"warnAsError": [
"NU1605"
],
@@ -2957,6 +2953,7 @@
}
},
"warningProperties": {
"allWarningsAsErrors": true,
"noWarn": [
"NU5104"
],
-9
View File
@@ -1499,15 +1499,6 @@
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
],
"warnNotAsError": [
"NU1902",
"NU1903"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"version": 2,
"dgSpecHash": "S7HnncDFxpo=",
"dgSpecHash": "M3eEjXrprD8=",
"success": true,
"projectFilePath": "E:\\Projects\\pgsql-jellyfin\\Emby.Naming\\Emby.Naming.csproj",
"expectedPackageFiles": [