private EpisodePathParserResult Parse(string name, EpisodeExpression expression) { var result = new EpisodePathParserResult(); var match = _iRegexProvider.GetRegex(expression.Expression, RegexOptions.IgnoreCase).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].Value, expression.DateTimeFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out date)) { result.Year = date.Year; result.Month = date.Month; result.Day = date.Day; } } else { if (DateTime.TryParse(match.Groups[0].Value, out date)) { result.Year = date.Year; result.Month = date.Month; result.Day = date.Day; } } } else { int num; if (int.TryParse(match.Groups[1].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { result.SeasonNumber = num; } if (int.TryParse(match.Groups[2].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { result.EpsiodeNumber = num; } } result.IsByDate = expression.IsByDate; result.Success = true; return(result); } return(result); }
public void TestNamingOptionsEpisodeExpressions() { var exp = new EpisodeExpression(string.Empty); Assert.False(exp.IsOptimistic); exp.IsOptimistic = true; Assert.True(exp.IsOptimistic); Assert.Equal(string.Empty, exp.Expression); Assert.NotNull(exp.Regex); exp.Expression = "test"; Assert.Equal("test", exp.Expression); Assert.NotNull(exp.Regex); }
private static SeriesPathParserResult Parse(string name, EpisodeExpression expression) { var result = new SeriesPathParserResult(); var match = expression.Regex.Match(name); if (match.Success && match.Groups.Count >= 3) { if (expression.IsNamed) { result.SeriesName = match.Groups["seriesname"].Value; result.Success = !string.IsNullOrEmpty(result.SeriesName) && !string.IsNullOrEmpty(match.Groups["seasonnumber"]?.Value); } } return(result); }
private 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].Value, 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].Value, 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) { int num; if (int.TryParse(match.Groups["seasonnumber"].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num)) { result.SeasonNumber = num; } if (int.TryParse(match.Groups["epnumber"].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num)) { result.EpisodeNumber = num; } Group endingNumberGroup = match.Groups["endingepnumber"]; if (endingNumberGroup.Success) { // Will only set EndingEpsiodeNumber 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".IndexOf(name[nextIndex]) == -1) { if (int.TryParse(endingNumberGroup.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num)) { result.EndingEpsiodeNumber = num; } } } result.SeriesName = match.Groups["seriesname"].Value; result.Success = result.EpisodeNumber.HasValue; } else { int num; if (int.TryParse(match.Groups[1].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num)) { result.SeasonNumber = num; } if (int.TryParse(match.Groups[2].Value, 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 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].Value, 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].Value, 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"].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var num)) { result.SeasonNumber = num; } else if (!string.IsNullOrEmpty(match.Groups["seasonnumber"].Value)) { // 很少有一个番剧能活十个季( ̄▽ ̄;) // 所以并没有在正则中匹配十以上更复杂的复合汉字数字和罗马数字 result.SeasonNumber = match.Groups["seasonnumber"].Value switch { "二" or "Ⅱ" => 1, "三" or "Ⅲ" => 1, "四" or "Ⅳ" => 1, "五" or "Ⅴ" => 1, "六" or "Ⅵ" => 1, "七" or "Ⅶ" => 1, "八" or "Ⅷ" => 1, "九" or "Ⅸ" => 1, "十" or "Ⅹ" => 1, "一" or "Ⅰ" => 1, _ => null }; } if (!string.IsNullOrEmpty(match.Groups["specialSeason"].Value)) { if (match.Groups["specialSeason"].Value.Contains("剧场版")) { // 剧场版属于 Movie result = new EpisodePathParserResult(); return(result); } else { // OVA、OAD、SP result.SeasonNumber = 0; } } if (int.TryParse(match.Groups["epnumber"].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num)) { result.EpisodeNumber = num; } else if (float.TryParse(match.Groups["epnumber"].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out float numF)) { // 小数点剧集 result.SeasonNumber = 0; result.EpisodeNumber = 1; } 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.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num)) { result.EndingEpisodeNumber = num; } } } result.SeriesName = match.Groups["seriesname"].Value; // 如果以是否拿到集数来判断,没有识别到TmDB集号的小数点集、OVA、OAD、SP等都会失败 // result.Success = result.EpisodeNumber.HasValue; result.Success = true; } else { if (int.TryParse(match.Groups[1].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var num)) { result.SeasonNumber = num; } if (int.TryParse(match.Groups[2].Value, 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 EpisodePathParserResult Parse(string name, EpisodeExpression expression) { var result = new EpisodePathParserResult(); var match = _iRegexProvider.GetRegex(expression.Expression, RegexOptions.IgnoreCase).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].Value, expression.DateTimeFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out date)) { result.Year = date.Year; result.Month = date.Month; result.Day = date.Day; } } else { if (DateTime.TryParse(match.Groups[0].Value, out date)) { result.Year = date.Year; result.Month = date.Month; result.Day = date.Day; } } result.Success = true; } else if (expression.IsNamed) { int num; if (int.TryParse(match.Groups["seasonnumber"].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { result.SeasonNumber = num; } if (int.TryParse(match.Groups["epnumber"].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { result.EpisodeNumber = num; } var endingNumberGroup = match.Groups["endingepnumber"]; if (endingNumberGroup != null) { bool bEndingNumberValid = true; int nextIndex = endingNumberGroup.Index + endingNumberGroup.Length; string nextChar = name.Substring(nextIndex, 1).ToLower(); if (("0123456789".Contains(nextChar))) { // The regex expressions look for a number with a length of 2 or 3 charachters // if the following character is another digit, the parsed ending number would be incorrect anyway // This will fix erroneous parsing of something like "series-s09e14-1080p.mkv" // as a multi-episode from E14 to E108 bEndingNumberValid = false; } if (nextChar == "p" || nextChar == "i") { // This will fix erroneous parsing of something like "series-s09e14-720p.mkv" // as a multi-episode from E14 to E720 // It should be safe to assume that a _real_ ending episode number will never be followed by those letters bEndingNumberValid = false; } if (bEndingNumberValid && int.TryParse(endingNumberGroup.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { result.EndingEpsiodeNumber = num; } } var seriesGroup = match.Groups["seriesname"]; result.SeriesName = seriesGroup == null ? null : seriesGroup.Value; result.Success = result.EpisodeNumber.HasValue; } else { int num; if (int.TryParse(match.Groups[1].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { result.SeasonNumber = num; } if (int.TryParse(match.Groups[2].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { result.EpisodeNumber = num; } result.Success = result.EpisodeNumber.HasValue; } result.IsByDate = expression.IsByDate; } return(result); }