| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 | 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 media 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.AsSpan());            if (!(_type == DlnaProfileType.Subtitle && _namingOptions.SubtitleFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))                && !(_type == DlnaProfileType.Audio && _namingOptions.AudioFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))                && !(_type == DlnaProfileType.Lyric && _namingOptions.LyricFileExtensions.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;                const int SeparatorLength = 1;                while (languageString.Length > 0)                {                    int lastSeparator = languageString.LastIndexOf(separator);                    if (lastSeparator == -1)                    {                          break;                    }                    string currentSlice = languageString[lastSeparator..];                    string currentSliceWithoutSeparator = currentSlice[SeparatorLength..];                    if (_namingOptions.MediaDefaultFlags.Any(s => currentSliceWithoutSeparator.Contains(s, StringComparison.OrdinalIgnoreCase)))                    {                        pathInfo.IsDefault = true;                        extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);                        languageString = languageString[..lastSeparator];                        continue;                    }                    if (_namingOptions.MediaForcedFlags.Any(s => currentSliceWithoutSeparator.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(currentSliceWithoutSeparator);                    if (culture is not null && pathInfo.Language is null)                    {                        pathInfo.Language = culture.Name.Contains('-', StringComparison.OrdinalIgnoreCase)                                          ? culture.Name                                          : culture.ThreeLetterISOLanguageName;                        extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);                    }                    else if (culture is not null && pathInfo.Language == "hin")                    {                        // Hindi language code "hi" collides with a hearing impaired flag - use as Hindi only if no other language is set                        pathInfo.IsHearingImpaired = true;                        pathInfo.Language = culture.Name.Contains('-', StringComparison.OrdinalIgnoreCase)                                          ? culture.Name                                          : culture.ThreeLetterISOLanguageName;                        extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);                    }                    else if (_namingOptions.MediaHearingImpairedFlags.Any(s => currentSliceWithoutSeparator.Equals(s, StringComparison.OrdinalIgnoreCase)))                    {                        pathInfo.IsHearingImpaired = true;                        extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);                    }                    else                    {                        titleString = currentSlice + titleString;                    }                    languageString = languageString[..lastSeparator];                }                pathInfo.Title = titleString.Length >= SeparatorLength ? titleString[SeparatorLength..] : null;            }            return pathInfo;        }    }}
 |