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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }