| | | 1 | | using Emby.Naming.Common; |
| | | 2 | | |
| | | 3 | | namespace Emby.Naming.TV |
| | | 4 | | { |
| | | 5 | | /// <summary> |
| | | 6 | | /// Used to parse information about series from paths containing more information that only the series name. |
| | | 7 | | /// Uses the same regular expressions as the EpisodePathParser but have different success criteria. |
| | | 8 | | /// </summary> |
| | | 9 | | public static class SeriesPathParser |
| | | 10 | | { |
| | | 11 | | /// <summary> |
| | | 12 | | /// Parses information about series from path. |
| | | 13 | | /// </summary> |
| | | 14 | | /// <param name="options"><see cref="NamingOptions"/> object containing EpisodeExpressions and MultipleEpisodeEx |
| | | 15 | | /// <param name="path">Path.</param> |
| | | 16 | | /// <returns>Returns <see cref="SeriesPathParserResult"/> object.</returns> |
| | | 17 | | public static SeriesPathParserResult Parse(NamingOptions options, string path) |
| | | 18 | | { |
| | 42 | 19 | | SeriesPathParserResult? result = null; |
| | | 20 | | |
| | 2109 | 21 | | foreach (var expression in options.EpisodeExpressions) |
| | | 22 | | { |
| | | 23 | | // Optimistic expressions (bare numbers, "01.blah", etc.) are only meant for |
| | | 24 | | // episode parsing and produce false series names on release folder names like |
| | | 25 | | // "Silo.S03.1080p.WEB-DL..." (e.g. reading "264" as S02E64). Skip them here. |
| | 1022 | 26 | | if (expression.IsOptimistic) |
| | | 27 | | { |
| | | 28 | | continue; |
| | | 29 | | } |
| | | 30 | | |
| | 782 | 31 | | var currentResult = Parse(path, expression); |
| | 782 | 32 | | if (currentResult.Success) |
| | | 33 | | { |
| | 19 | 34 | | result = currentResult; |
| | 19 | 35 | | break; |
| | | 36 | | } |
| | | 37 | | } |
| | | 38 | | |
| | 42 | 39 | | if (result is not null) |
| | | 40 | | { |
| | 19 | 41 | | if (!string.IsNullOrEmpty(result.SeriesName)) |
| | | 42 | | { |
| | 19 | 43 | | result.SeriesName = result.SeriesName.Trim(' ', '_', '.', '-'); |
| | | 44 | | } |
| | | 45 | | } |
| | | 46 | | |
| | 42 | 47 | | return result ?? new SeriesPathParserResult(); |
| | | 48 | | } |
| | | 49 | | |
| | | 50 | | private static SeriesPathParserResult Parse(string name, EpisodeExpression expression) |
| | | 51 | | { |
| | 782 | 52 | | var result = new SeriesPathParserResult(); |
| | | 53 | | |
| | 782 | 54 | | var match = expression.Regex.Match(name); |
| | | 55 | | |
| | 782 | 56 | | if (match.Success && match.Groups.Count >= 3) |
| | | 57 | | { |
| | 25 | 58 | | if (expression.IsNamed) |
| | | 59 | | { |
| | | 60 | | // Reject implausible season numbers (e.g. resolutions like 1280x720 |
| | | 61 | | // read as S1280E720), mirroring EpisodePathParser. |
| | 23 | 62 | | var seasonNumberGroup = match.Groups["seasonnumber"]; |
| | 23 | 63 | | if (seasonNumberGroup.Success |
| | 23 | 64 | | && int.TryParse(seasonNumberGroup.ValueSpan, System.Globalization.NumberStyles.Integer, System.G |
| | 23 | 65 | | && ((seasonNumber >= 200 && seasonNumber < 1928) || seasonNumber > 2500)) |
| | | 66 | | { |
| | 2 | 67 | | return result; |
| | | 68 | | } |
| | | 69 | | |
| | 21 | 70 | | result.SeriesName = match.Groups["seriesname"].Value; |
| | 21 | 71 | | result.Success = !string.IsNullOrEmpty(result.SeriesName) && !seasonNumberGroup.ValueSpan.IsEmpty; |
| | | 72 | | } |
| | | 73 | | } |
| | | 74 | | |
| | 780 | 75 | | return result; |
| | | 76 | | } |
| | | 77 | | } |
| | | 78 | | } |