| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.Globalization;
 
- using System.Linq;
 
- using Emby.Naming.Common;
 
- namespace Emby.Naming.TV
 
- {
 
-     /// <summary>
 
-     /// Used to parse information about episode from path.
 
-     /// </summary>
 
-     public class EpisodePathParser
 
-     {
 
-         private readonly NamingOptions _options;
 
-         /// <summary>
 
-         /// Initializes a new instance of the <see cref="EpisodePathParser"/> class.
 
-         /// </summary>
 
-         /// <param name="options"><see cref="NamingOptions"/> object containing EpisodeExpressions and MultipleEpisodeExpressions.</param>
 
-         public EpisodePathParser(NamingOptions options)
 
-         {
 
-             _options = options;
 
-         }
 
-         /// <summary>
 
-         /// Parses information about episode from path.
 
-         /// </summary>
 
-         /// <param name="path">Path.</param>
 
-         /// <param name="isDirectory">Is path for a directory or file.</param>
 
-         /// <param name="isNamed">Do we want to use IsNamed expressions.</param>
 
-         /// <param name="isOptimistic">Do we want to use Optimistic expressions.</param>
 
-         /// <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 Parse(
 
-             string path,
 
-             bool isDirectory,
 
-             bool? isNamed = null,
 
-             bool? isOptimistic = null,
 
-             bool? supportsAbsoluteNumbers = null,
 
-             bool fillExtendedInfo = true)
 
-         {
 
-             // Added to be able to use regex patterns which require a file extension.
 
-             // There were no failed tests without this block, but to be safe, we can keep it until
 
-             // the regex which require file extensions are modified so that they don't need them.
 
-             if (isDirectory)
 
-             {
 
-                 path += ".mp4";
 
-             }
 
-             EpisodePathParserResult? result = null;
 
-             foreach (var expression in _options.EpisodeExpressions)
 
-             {
 
-                 if (supportsAbsoluteNumbers.HasValue
 
-                     && expression.SupportsAbsoluteEpisodeNumbers != supportsAbsoluteNumbers.Value)
 
-                 {
 
-                     continue;
 
-                 }
 
-                 if (isNamed.HasValue && expression.IsNamed != isNamed.Value)
 
-                 {
 
-                     continue;
 
-                 }
 
-                 if (isOptimistic.HasValue && expression.IsOptimistic != isOptimistic.Value)
 
-                 {
 
-                     continue;
 
-                 }
 
-                 var currentResult = Parse(path, expression);
 
-                 if (currentResult.Success)
 
-                 {
 
-                     result = currentResult;
 
-                     break;
 
-                 }
 
-             }
 
-             if (result is not null && fillExtendedInfo)
 
-             {
 
-                 FillAdditional(path, result);
 
-                 if (!string.IsNullOrEmpty(result.SeriesName))
 
-                 {
 
-                     result.SeriesName = result.SeriesName
 
-                         .Trim()
 
-                         .Trim('_', '.', '-')
 
-                         .Trim();
 
-                 }
 
-             }
 
-             return result ?? new EpisodePathParserResult();
 
-         }
 
-         private static EpisodePathParserResult Parse(string name, EpisodeExpression expression)
 
-         {
 
-             var result = new EpisodePathParserResult();
 
-             // This is a hack to handle wmc naming
 
-             if (expression.IsByDate)
 
-             {
 
-                 name = name.Replace('_', '-');
 
-             }
 
-             var match = expression.Regex.Match(name);
 
-             // (Full)(Season)(Episode)(Extension)
 
-             if (match.Success && match.Groups.Count >= 3)
 
-             {
 
-                 if (expression.IsByDate)
 
-                 {
 
-                     DateTime date;
 
-                     if (expression.DateTimeFormats.Length > 0)
 
-                     {
 
-                         if (DateTime.TryParseExact(
 
-                             match.Groups[0].ValueSpan,
 
-                             expression.DateTimeFormats,
 
-                             CultureInfo.InvariantCulture,
 
-                             DateTimeStyles.None,
 
-                             out date))
 
-                         {
 
-                             result.Year = date.Year;
 
-                             result.Month = date.Month;
 
-                             result.Day = date.Day;
 
-                             result.Success = true;
 
-                         }
 
-                     }
 
-                     else if (DateTime.TryParse(match.Groups[0].ValueSpan, out date))
 
-                     {
 
-                         result.Year = date.Year;
 
-                         result.Month = date.Month;
 
-                         result.Day = date.Day;
 
-                         result.Success = true;
 
-                     }
 
-                     // TODO: Only consider success if date successfully parsed?
 
-                     result.Success = true;
 
-                 }
 
-                 else if (expression.IsNamed)
 
-                 {
 
-                     if (int.TryParse(match.Groups["seasonnumber"].ValueSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out var num))
 
-                     {
 
-                         result.SeasonNumber = num;
 
-                     }
 
-                     if (int.TryParse(match.Groups["epnumber"].ValueSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out num))
 
-                     {
 
-                         result.EpisodeNumber = num;
 
-                     }
 
-                     var endingNumberGroup = match.Groups["endingepnumber"];
 
-                     if (endingNumberGroup.Success)
 
-                     {
 
-                         // Will only set EndingEpisodeNumber if the captured number is not followed by additional numbers
 
-                         // or a 'p' or 'i' as what you would get with a pixel resolution specification.
 
-                         // It avoids erroneous parsing of something like "series-s09e14-1080p.mkv" as a multi-episode from E14 to E108
 
-                         int nextIndex = endingNumberGroup.Index + endingNumberGroup.Length;
 
-                         if (nextIndex >= name.Length
 
-                             || !"0123456789iIpP".Contains(name[nextIndex], StringComparison.Ordinal))
 
-                         {
 
-                             if (int.TryParse(endingNumberGroup.ValueSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out num))
 
-                             {
 
-                                 result.EndingEpisodeNumber = num;
 
-                             }
 
-                         }
 
-                     }
 
-                     result.SeriesName = match.Groups["seriesname"].Value;
 
-                     result.Success = result.EpisodeNumber.HasValue;
 
-                 }
 
-                 else
 
-                 {
 
-                     if (int.TryParse(match.Groups[1].ValueSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out var num))
 
-                     {
 
-                         result.SeasonNumber = num;
 
-                     }
 
-                     if (int.TryParse(match.Groups[2].ValueSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out num))
 
-                     {
 
-                         result.EpisodeNumber = num;
 
-                     }
 
-                     result.Success = result.EpisodeNumber.HasValue;
 
-                 }
 
-                 // Invalidate match when the season is 200 through 1927 or above 2500
 
-                 // because it is an error unless the TV show is intentionally using false season numbers.
 
-                 // It avoids erroneous parsing of something like "Series Special (1920x1080).mkv" as being season 1920 episode 1080.
 
-                 if ((result.SeasonNumber >= 200 && result.SeasonNumber < 1928)
 
-                     || result.SeasonNumber > 2500)
 
-                 {
 
-                     result.Success = false;
 
-                 }
 
-                 result.IsByDate = expression.IsByDate;
 
-             }
 
-             return result;
 
-         }
 
-         private void FillAdditional(string path, EpisodePathParserResult info)
 
-         {
 
-             var expressions = _options.MultipleEpisodeExpressions.Where(i => i.IsNamed).ToList();
 
-             if (string.IsNullOrEmpty(info.SeriesName))
 
-             {
 
-                 expressions.InsertRange(0, _options.EpisodeExpressions.Where(i => i.IsNamed));
 
-             }
 
-             FillAdditional(path, info, expressions);
 
-         }
 
-         private void FillAdditional(string path, EpisodePathParserResult info, IEnumerable<EpisodeExpression> expressions)
 
-         {
 
-             foreach (var i in expressions)
 
-             {
 
-                 var result = Parse(path, i);
 
-                 if (!result.Success)
 
-                 {
 
-                     continue;
 
-                 }
 
-                 if (string.IsNullOrEmpty(info.SeriesName))
 
-                 {
 
-                     info.SeriesName = result.SeriesName;
 
-                 }
 
-                 if (!info.EndingEpisodeNumber.HasValue && info.EpisodeNumber.HasValue)
 
-                 {
 
-                     info.EndingEpisodeNumber = result.EndingEpisodeNumber;
 
-                 }
 
-                 if (!string.IsNullOrEmpty(info.SeriesName)
 
-                     && (!info.EpisodeNumber.HasValue || info.EndingEpisodeNumber.HasValue))
 
-                 {
 
-                     break;
 
-                 }
 
-             }
 
-         }
 
-     }
 
- }
 
 
  |