diff options
| author | Shadowghost <Ghost_of_Stone@web.de> | 2022-02-07 18:36:07 +0100 |
|---|---|---|
| committer | Shadowghost <Ghost_of_Stone@web.de> | 2022-02-18 22:19:33 +0100 |
| commit | 719b707281b078405daeea90811c2b4d7b40d624 (patch) | |
| tree | 0b0f5249aca4e54ea272c19025ad8bd742b688e8 /Emby.Naming/ExternalFiles | |
| parent | f1878c43a4c0e0ff054c81c67ea28b910eab3a1b (diff) | |
feat(external-media): refactor to generic provider, extend tests and file recognition, consolidate and extend NamingOptions
Diffstat (limited to 'Emby.Naming/ExternalFiles')
| -rw-r--r-- | Emby.Naming/ExternalFiles/ExternalPathParser.cs | 116 | ||||
| -rw-r--r-- | Emby.Naming/ExternalFiles/ExternalPathParserResult.cs | 51 |
2 files changed, 167 insertions, 0 deletions
diff --git a/Emby.Naming/ExternalFiles/ExternalPathParser.cs b/Emby.Naming/ExternalFiles/ExternalPathParser.cs new file mode 100644 index 000000000..7b5767b67 --- /dev/null +++ b/Emby.Naming/ExternalFiles/ExternalPathParser.cs @@ -0,0 +1,116 @@ +using System; +using System.IO; +using System.Linq; +using Emby.Naming.Common; +using Jellyfin.Extensions; +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Globalization; + +namespace Emby.Naming.ExternalFiles +{ + /// <summary> + /// External file parser class. + /// </summary> + public class ExternalPathParser + { + private readonly NamingOptions _namingOptions; + private readonly DlnaProfileType _type; + private readonly ILocalizationManager _localizationManager; + + /// <summary> + /// Initializes a new instance of the <see cref="ExternalPathParser"/> class. + /// </summary> + /// <param name="localizationManager">The localization manager.</param> + /// <param name="namingOptions">The <see cref="NamingOptions"/> object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters.</param> + /// <param name="type">The <see cref="DlnaProfileType"/> of the parsed file.</param> + public ExternalPathParser(NamingOptions namingOptions, ILocalizationManager localizationManager, DlnaProfileType type) + { + _localizationManager = localizationManager; + _namingOptions = namingOptions; + _type = type; + } + + /// <summary> + /// Parse filename and extract information. + /// </summary> + /// <param name="path">Path to file.</param> + /// <param name="extraString">Part of the filename only containing the extra information.</param> + /// <returns>Returns null or an <see cref="ExternalPathParserResult"/> object if parsing is successful.</returns> + public ExternalPathParserResult? ParseFile(string path, string? extraString) + { + if (path.Length == 0) + { + return null; + } + + var extension = Path.GetExtension(path); + if (!((_type == DlnaProfileType.Subtitle && _namingOptions.SubtitleFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) + || (_type == DlnaProfileType.Audio && _namingOptions.AudioFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) + || (_type == DlnaProfileType.Video && _namingOptions.VideoFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)))) + { + return null; + } + + var pathInfo = new ExternalPathParserResult(path); + + if (string.IsNullOrEmpty(extraString)) + { + return pathInfo; + } + + foreach (var separator in _namingOptions.MediaFlagDelimiters) + { + var languageString = extraString; + var titleString = string.Empty; + int separatorLength = separator.Length; + + while (languageString.Length > 0) + { + var lastSeparator = languageString.LastIndexOf(separator, StringComparison.OrdinalIgnoreCase); + + if (lastSeparator == -1) + { + break; + } + + string currentSlice = languageString[lastSeparator..]; + + if (_namingOptions.MediaDefaultFlags.Any(s => currentSlice[separatorLength..].Contains(s, StringComparison.OrdinalIgnoreCase))) + { + pathInfo.IsDefault = true; + extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase); + languageString = languageString[..lastSeparator]; + continue; + } + + if (_namingOptions.MediaForcedFlags.Any(s => currentSlice[separatorLength..].Contains(s, StringComparison.OrdinalIgnoreCase))) + { + pathInfo.IsForced = true; + extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase); + languageString = languageString[..lastSeparator]; + continue; + } + + // Try to translate to three character code + var culture = _localizationManager.FindLanguageInfo(currentSlice[separatorLength..]); + + if (culture != null && pathInfo.Language == null) + { + pathInfo.Language = culture.ThreeLetterISOLanguageName; + extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase); + } + else + { + titleString = currentSlice + titleString; + } + + languageString = languageString[..lastSeparator]; + } + + pathInfo.Title = separatorLength <= titleString.Length ? titleString[separatorLength..] : null; + } + + return pathInfo; + } + } +} diff --git a/Emby.Naming/ExternalFiles/ExternalPathParserResult.cs b/Emby.Naming/ExternalFiles/ExternalPathParserResult.cs new file mode 100644 index 000000000..1cc773a2e --- /dev/null +++ b/Emby.Naming/ExternalFiles/ExternalPathParserResult.cs @@ -0,0 +1,51 @@ +namespace Emby.Naming.ExternalFiles +{ + /// <summary> + /// Class holding information about external files. + /// </summary> + public class ExternalPathParserResult + { + /// <summary> + /// Initializes a new instance of the <see cref="ExternalPathParserResult"/> class. + /// </summary> + /// <param name="path">Path to file.</param> + /// <param name="isDefault">Is default.</param> + /// <param name="isForced">Is forced.</param> + public ExternalPathParserResult(string path, bool isDefault = false, bool isForced = false) + { + Path = path; + IsDefault = isDefault; + IsForced = isForced; + } + + /// <summary> + /// Gets or sets the path. + /// </summary> + /// <value>The path.</value> + public string Path { get; set; } + + /// <summary> + /// Gets or sets the language. + /// </summary> + /// <value>The language.</value> + public string? Language { get; set; } + + /// <summary> + /// Gets or sets the title. + /// </summary> + /// <value>The title.</value> + public string? Title { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this instance is default. + /// </summary> + /// <value><c>true</c> if this instance is default; otherwise, <c>false</c>.</value> + public bool IsDefault { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this instance is forced. + /// </summary> + /// <value><c>true</c> if this instance is forced; otherwise, <c>false</c>.</value> + public bool IsForced { get; set; } + } +} |
