From 7785b51f572cf48a62dfc2ee60fc1db0ccedf1a2 Mon Sep 17 00:00:00 2001 From: Sven Cazier Date: Sat, 26 Jul 2025 23:24:58 +0200 Subject: Enhance extra rules for video and audio file naming; update tests for new naming conventions --- Emby.Naming/Common/NamingOptions.cs | 28 ++++++------ Emby.Naming/Video/ExtraRuleResolver.cs | 78 ++++++++++++---------------------- 2 files changed, 42 insertions(+), 64 deletions(-) (limited to 'Emby.Naming') diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 192235baeb..1c518f0cca 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -572,6 +572,18 @@ namespace Emby.Naming.Common "trailer", MediaType.Video), + new ExtraRule( + ExtraType.Sample, + ExtraRuleType.Filename, + "sample", + MediaType.Video), + + new ExtraRule( + ExtraType.ThemeSong, + ExtraRuleType.Filename, + "theme", + MediaType.Audio), + new ExtraRule( ExtraType.Trailer, ExtraRuleType.Suffix, @@ -593,13 +605,7 @@ namespace Emby.Naming.Common new ExtraRule( ExtraType.Trailer, ExtraRuleType.Suffix, - " trailer", - MediaType.Video), - - new ExtraRule( - ExtraType.Sample, - ExtraRuleType.Filename, - "sample", + "- trailer", MediaType.Video), new ExtraRule( @@ -623,15 +629,9 @@ namespace Emby.Naming.Common new ExtraRule( ExtraType.Sample, ExtraRuleType.Suffix, - " sample", + "- sample", MediaType.Video), - new ExtraRule( - ExtraType.ThemeSong, - ExtraRuleType.Filename, - "theme", - MediaType.Audio), - new ExtraRule( ExtraType.Scene, ExtraRuleType.Suffix, diff --git a/Emby.Naming/Video/ExtraRuleResolver.cs b/Emby.Naming/Video/ExtraRuleResolver.cs index 5289065898..2e0caa612f 100644 --- a/Emby.Naming/Video/ExtraRuleResolver.cs +++ b/Emby.Naming/Video/ExtraRuleResolver.cs @@ -22,67 +22,45 @@ namespace Emby.Naming.Video /// Returns object. public static ExtraResult GetExtraInfo(string path, NamingOptions namingOptions, string? libraryRoot = "") { - var result = new ExtraResult(); + ExtraResult result = new ExtraResult(); - for (var i = 0; i < namingOptions.VideoExtraRules.Length; i++) + bool isAudioFile = AudioFileParser.IsAudioFile(path, namingOptions); + bool isVideoFile = VideoResolver.IsVideoFile(path, namingOptions); + + ReadOnlySpan pathSpan = path.AsSpan(); + ReadOnlySpan fileName = Path.GetFileName(pathSpan); + ReadOnlySpan fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pathSpan); + // Trim the digits from the end of the filename so we can recognize things like -trailer2 + ReadOnlySpan trimmedFileNameWithoutExtension = fileNameWithoutExtension.TrimEnd(_digits); + ReadOnlySpan directoryName = Path.GetFileName(Path.GetDirectoryName(pathSpan)); + string fullDirectory = Path.GetDirectoryName(pathSpan).ToString(); + + foreach (ExtraRule rule in namingOptions.VideoExtraRules) { - var rule = namingOptions.VideoExtraRules[i]; - if ((rule.MediaType == MediaType.Audio && !AudioFileParser.IsAudioFile(path, namingOptions)) - || (rule.MediaType == MediaType.Video && !VideoResolver.IsVideoFile(path, namingOptions))) + if ((rule.MediaType == MediaType.Audio && !isAudioFile) + || (rule.MediaType == MediaType.Video && !isVideoFile)) { continue; } - var pathSpan = path.AsSpan(); - if (rule.RuleType == ExtraRuleType.Filename) + bool isMatch = rule.RuleType switch { - var filename = Path.GetFileNameWithoutExtension(pathSpan); + ExtraRuleType.Filename => fileNameWithoutExtension.Equals(rule.Token, StringComparison.OrdinalIgnoreCase), + ExtraRuleType.Suffix => trimmedFileNameWithoutExtension.EndsWith(rule.Token, StringComparison.OrdinalIgnoreCase), + ExtraRuleType.Regex => Regex.IsMatch(fileName, rule.Token, RegexOptions.IgnoreCase | RegexOptions.Compiled), + ExtraRuleType.DirectoryName => directoryName.Equals(rule.Token, StringComparison.OrdinalIgnoreCase) + && !string.Equals(fullDirectory, libraryRoot, StringComparison.OrdinalIgnoreCase), + _ => false, + }; - if (filename.Equals(rule.Token, StringComparison.OrdinalIgnoreCase)) - { - result.ExtraType = rule.ExtraType; - result.Rule = rule; - } - } - else if (rule.RuleType == ExtraRuleType.Suffix) + if (!isMatch) { - // Trim the digits from the end of the filename so we can recognize things like -trailer2 - var filename = Path.GetFileNameWithoutExtension(pathSpan).TrimEnd(_digits); - - if (filename.EndsWith(rule.Token, StringComparison.OrdinalIgnoreCase)) - { - result.ExtraType = rule.ExtraType; - result.Rule = rule; - } - } - else if (rule.RuleType == ExtraRuleType.Regex) - { - var filename = Path.GetFileName(path.AsSpan()); - - var isMatch = Regex.IsMatch(filename, rule.Token, RegexOptions.IgnoreCase | RegexOptions.Compiled); - - if (isMatch) - { - result.ExtraType = rule.ExtraType; - result.Rule = rule; - } - } - else if (rule.RuleType == ExtraRuleType.DirectoryName) - { - var directoryName = Path.GetFileName(Path.GetDirectoryName(pathSpan)); - string fullDirectory = Path.GetDirectoryName(pathSpan).ToString(); - if (directoryName.Equals(rule.Token, StringComparison.OrdinalIgnoreCase) - && !string.Equals(fullDirectory, libraryRoot, StringComparison.OrdinalIgnoreCase)) - { - result.ExtraType = rule.ExtraType; - result.Rule = rule; - } + continue; } - if (result.ExtraType is not null) - { - return result; - } + result.ExtraType = rule.ExtraType; + result.Rule = rule; + return result; } return result; -- cgit v1.2.3