using System; using System.Diagnostics.CodeAnalysis; using System.IO; using Emby.Naming.Common; using Jellyfin.Extensions; namespace Emby.Naming.Video { /// /// Resolves from file path. /// public static class VideoResolver { /// /// Resolves the directory. /// /// The path. /// The naming options. /// Whether to parse the name or use the filename. /// VideoFileInfo. public static VideoFileInfo? ResolveDirectory(string? path, NamingOptions namingOptions, bool parseName = true) { return Resolve(path, true, namingOptions, parseName); } /// /// Resolves the file. /// /// The path. /// The naming options. /// VideoFileInfo. public static VideoFileInfo? ResolveFile(string? path, NamingOptions namingOptions) { return Resolve(path, false, namingOptions); } /// /// Resolves the specified path. /// /// The path. /// if set to true [is folder]. /// The naming options. /// Whether or not the name should be parsed for info. /// VideoFileInfo. /// path is null. public static VideoFileInfo? Resolve(string? path, bool isDirectory, NamingOptions namingOptions, bool parseName = true) { if (string.IsNullOrEmpty(path)) { return null; } bool isStub = false; ReadOnlySpan container = ReadOnlySpan.Empty; string? stubType = null; if (!isDirectory) { var extension = Path.GetExtension(path.AsSpan()); // Check supported extensions if (!namingOptions.VideoFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) { // It's not supported. Check stub extensions if (!StubResolver.TryResolveFile(path, namingOptions, out stubType)) { return null; } isStub = true; } container = extension.TrimStart('.'); } var format3DResult = Format3DParser.Parse(path, namingOptions); var extraResult = ExtraRuleResolver.GetExtraInfo(path, namingOptions); var name = Path.GetFileNameWithoutExtension(path); int? year = null; if (parseName) { var cleanDateTimeResult = CleanDateTime(name, namingOptions); name = cleanDateTimeResult.Name; year = cleanDateTimeResult.Year; if (TryCleanString(name, namingOptions, out var newName)) { name = newName; } } return new VideoFileInfo( path: path, container: container.IsEmpty ? null : container.ToString(), isStub: isStub, name: name, year: year, stubType: stubType, is3D: format3DResult.Is3D, format3D: format3DResult.Format3D, extraType: extraResult.ExtraType, isDirectory: isDirectory, extraRule: extraResult.Rule); } /// /// Determines if path is video file based on extension. /// /// Path to file. /// The naming options. /// True if is video file. public static bool IsVideoFile(string path, NamingOptions namingOptions) { var extension = Path.GetExtension(path.AsSpan()); return namingOptions.VideoFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase); } /// /// Determines if path is video file stub based on extension. /// /// Path to file. /// The naming options. /// True if is video file stub. public static bool IsStubFile(string path, NamingOptions namingOptions) { var extension = Path.GetExtension(path.AsSpan()); return namingOptions.StubFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase); } /// /// Tries to clean name of clutter. /// /// Raw name. /// The naming options. /// Clean name. /// True if cleaning of name was successful. public static bool TryCleanString([NotNullWhen(true)] string? name, NamingOptions namingOptions, out string newName) { return CleanStringParser.TryClean(name, namingOptions.CleanStringRegexes, out newName); } /// /// Tries to get name and year from raw name. /// /// Raw name. /// The naming options. /// Returns with name and optional year. public static CleanDateTimeResult CleanDateTime(string name, NamingOptions namingOptions) { return CleanDateTimeParser.Clean(name, namingOptions.CleanDateTimeRegexes); } } }