From fd3d94c9b05a5ed853e375603b713c3c878df310 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 30 Mar 2011 08:42:36 -0700 Subject: [PATCH 1/3] ParseEpisodeInfo will now handle repeating Episode Naming Format (S01E01E02 or S01E01-02), It will not handle ranges (S01E01-06) Changed port back to 8989. --- IISExpress/AppServer/applicationhost.config | 2 +- NzbDrone.Core.Test/ParserTest.cs | 13 ++++++++++- NzbDrone.Core/Parser.cs | 24 ++++++++++++--------- NzbDrone/app.config | 2 +- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/IISExpress/AppServer/applicationhost.config b/IISExpress/AppServer/applicationhost.config index ffcf44ec6..6c56a7b72 100644 --- a/IISExpress/AppServer/applicationhost.config +++ b/IISExpress/AppServer/applicationhost.config @@ -148,7 +148,7 @@ - + diff --git a/NzbDrone.Core.Test/ParserTest.cs b/NzbDrone.Core.Test/ParserTest.cs index 7f332b1c5..46e4e34b4 100644 --- a/NzbDrone.Core.Test/ParserTest.cs +++ b/NzbDrone.Core.Test/ParserTest.cs @@ -13,7 +13,6 @@ namespace NzbDrone.Core.Test public class ParserTest { [Test] - [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1)] [Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)] [Row("Two.and.a.Half.Me.113.720p.HDTV.X264-DIMENSION", 1, 13)] [Row("Two.and.a.Half.Me.1013.720p.HDTV.X264-DIMENSION", 10, 13)] @@ -35,6 +34,18 @@ namespace NzbDrone.Core.Test Assert.AreEqual(episode, result[0].EpisodeNumber); } + [Test] + [Row("The.Office.US.S03E01E02.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1, 2)] + [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1, 6)] + public void episode_parse_multi(string path, int season, int episodeOne, int episodeTwo) + { + var result = Parser.ParseEpisodeInfo(path); + Assert.Count(2, result); + Assert.AreEqual(season, result[0].SeasonNumber); + Assert.AreEqual(episodeOne, result[0].EpisodeNumber); + Assert.AreEqual(episodeTwo, result[1].EpisodeNumber); + } + [Test] [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.BDRip)] [Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.BDRip)] diff --git a/NzbDrone.Core/Parser.cs b/NzbDrone.Core/Parser.cs index 8e1af4c82..5f348c232 100644 --- a/NzbDrone.Core/Parser.cs +++ b/NzbDrone.Core/Parser.cs @@ -18,7 +18,7 @@ namespace NzbDrone.Core private static readonly Regex[] ReportTitleRegex = new[] { - new Regex(@"(?.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)(?:\-|\.|[a-z])(?<episode>\d+)\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), + new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)((?:\-|\.|[a-z])(?<episode>\d+))+\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)(?<episode>\d{2})\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled) //Supports 103/113 naming }; @@ -58,18 +58,22 @@ namespace NzbDrone.Core foreach (Match matchGroup in match) { - var parsedEpisode = new EpisodeParseResult - { - SeriesTitle = seriesName, - SeasonNumber = Convert.ToInt32(matchGroup.Groups["season"].Value), - EpisodeNumber = Convert.ToInt32(matchGroup.Groups["episode"].Value), - Year = year - }; + var seasonNumber = Convert.ToInt32(matchGroup.Groups["season"].Value); + foreach (Capture episode in matchGroup.Groups["episode"].Captures) + { + var parsedEpisode = new EpisodeParseResult + { + SeriesTitle = seriesName, + SeasonNumber = seasonNumber, + EpisodeNumber = Convert.ToInt32(episode.Value), + Year = year + }; - result.Add(parsedEpisode); - Logger.Trace("Episode Parsed. {0}", parsedEpisode); + result.Add(parsedEpisode); + Logger.Trace("Episode Parsed. {0}", parsedEpisode); + } } break; //Break out of the for loop, we don't want to process every REGEX for each item otherwise we'll get duplicates } diff --git a/NzbDrone/app.config b/NzbDrone/app.config index c0e72973b..81d395705 100644 --- a/NzbDrone/app.config +++ b/NzbDrone/app.config @@ -4,6 +4,6 @@ <supportedRuntime version="v4.0" /> </startup> <appSettings> - <add key="port" value="8111" /> + <add key="port" value="8989" /> </appSettings> </configuration> \ No newline at end of file From 460e48d6a1941a7cb95472ff4a090c17c629af2c Mon Sep 17 00:00:00 2001 From: Mark McDowall <markus.mcd5@gmail.com> Date: Mon, 4 Apr 2011 19:48:46 -0700 Subject: [PATCH 2/3] Add GetBestMatch to TvDbProvider (Provides a way to get the best result from a list of results) Default value for Quality Dropbox in AddExisting is now the default value from Settings. --- NzbDrone.5.1.ReSharper | 153 ----- NzbDrone.Core.Test/ParserTest.cs | 17 +- NzbDrone.Core/Parser.cs | 526 +----------------- NzbDrone.Core/Providers/ITvDbProvider.cs | 1 + NzbDrone.Core/Providers/TvDbProvider.cs | 17 + .../Controllers/AddSeriesController.cs | 7 +- NzbDrone.Web/Views/AddSeries/AddExisting.aspx | 3 + .../Views/AddSeries/AddSeriesItem.cshtml | 4 +- 8 files changed, 32 insertions(+), 696 deletions(-) delete mode 100644 NzbDrone.5.1.ReSharper diff --git a/NzbDrone.5.1.ReSharper b/NzbDrone.5.1.ReSharper deleted file mode 100644 index f86d34090..000000000 --- a/NzbDrone.5.1.ReSharper +++ /dev/null @@ -1,153 +0,0 @@ -<Configuration> - <CodeStyleSettings> - <ExternalPath IsNull="False"> - </ExternalPath> - <Sharing>SOLUTION</Sharing> - <CSharp> - <FormatSettings> - <MODIFIERS_ORDER IsNull="False"> - <Item>public</Item> - <Item>protected</Item> - <Item>internal</Item> - <Item>private</Item> - <Item>new</Item> - <Item>abstract</Item> - <Item>virtual</Item> - <Item>override</Item> - <Item>sealed</Item> - <Item>static</Item> - <Item>readonly</Item> - <Item>extern</Item> - <Item>unsafe</Item> - <Item>volatile</Item> - </MODIFIERS_ORDER> - </FormatSettings> - <UsingsSettings /> - <Naming2> - <EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong> - <EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" /> - <PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" /> - <PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="LocalConstants" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PublicFields" /> - <PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" /> - <PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Constants" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateStaticReadonly" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" /> - </Naming2> - </CSharp> - <VB> - <FormatSettings> - <BLANK_LINES_AROUND_NAMESPACE>2</BLANK_LINES_AROUND_NAMESPACE> - <KEEP_USER_LINEBREAKS>False</KEEP_USER_LINEBREAKS> - <SPACE_AFTER_ATTRIBUTE_TARGET_COLON>False</SPACE_AFTER_ATTRIBUTE_TARGET_COLON> - <SPACE_BEFORE_INVOCATION_PARENTHESES>False</SPACE_BEFORE_INVOCATION_PARENTHESES> - <SPACE_BEFORE_METHOD_PARENTHESES>False</SPACE_BEFORE_METHOD_PARENTHESES> - <SPACE_BEFORE_TYPE_PARAMETER_PARENTHESES>False</SPACE_BEFORE_TYPE_PARAMETER_PARENTHESES> - <WRAP_ARGUMENTS_STYLE>CHOP_IF_LONG</WRAP_ARGUMENTS_STYLE> - <WRAP_EXTENDS_LIST_STYLE>CHOP_IF_LONG</WRAP_EXTENDS_LIST_STYLE> - <WRAP_LIMIT>200</WRAP_LIMIT> - <WRAP_PARAMETERS_STYLE>CHOP_IF_LONG</WRAP_PARAMETERS_STYLE> - </FormatSettings> - <ImportsSettings> - <AllowAlias>False</AllowAlias> - </ImportsSettings> - <Naming2> - <EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong> - <EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" /> - <PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" /> - <PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="LocalConstants" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PublicFields" /> - <PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" /> - <PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Constants" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateStaticReadonly" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" /> - </Naming2> - </VB> - <Web> - <Naming2> - <UserRule Name="ASP_TAG_NAME" Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <UserRule Name="ASP_TAG_PREFIX" Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <UserRule Name="ASP_FIELD" Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <UserRule Name="ASP_HTML_CONTROL" Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - </Naming2> - </Web> - <Xaml> - <Naming2> - <UserRule Name="XAML_FIELD" Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> - <UserRule Name="NAMESPACE_ALIAS" Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <UserRule Name="XAML_RESOURCE" Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - </Naming2> - </Xaml> - <XML> - <FormatSettings /> - </XML> - <FileHeader><![CDATA[' -' DotNetNuke® - http://www.dotnetnuke.com -' Copyright (c) 2002-2010 -' by DotNetNuke Corporation -' -' Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -' documentation files (the "Software"), to deal in the Software without restriction, including without limitation -' the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and -' to permit persons to whom the Software is furnished to do so, subject to the following conditions: -' -' The above copyright notice and this permission notice shall be included in all copies or substantial portions -' of the Software. -' -' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -' TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -' CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -' DEALINGS IN THE SOFTWARE. -']]></FileHeader> - <GenerateMemberBody /> - <Naming2> - <EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong> - <EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" /> - <PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" /> - <PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="LocalConstants" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" /> - <PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PublicFields" /> - <PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" /> - <PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AA_BB" ElementKind="Constants" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AA_BB" ElementKind="PrivateConstants" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateStaticReadonly" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" /> - <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" /> - <Abbreviation Text="IIS" /> - <Abbreviation Text="ID" /> - <Abbreviation Text="SHA" /> - <Abbreviation Text="WCF" /> - <Abbreviation Text="XML" /> - <Abbreviation Text="XSL" /> - <Abbreviation Text="AJAX" /> - <Abbreviation Text="GUID" /> - <Abbreviation Text="URL" /> - <Abbreviation Text="DNN" /> - </Naming2> - </CodeStyleSettings> -</Configuration> \ No newline at end of file diff --git a/NzbDrone.Core.Test/ParserTest.cs b/NzbDrone.Core.Test/ParserTest.cs index adb25142d..4b718ac9e 100644 --- a/NzbDrone.Core.Test/ParserTest.cs +++ b/NzbDrone.Core.Test/ParserTest.cs @@ -13,7 +13,8 @@ namespace NzbDrone.Core.Test public class ParserTest { [Test] - [Row("Sonny.With.a.Chance.S02E15", 2,15)] + [Row("Sonny.With.a.Chance.S02E15", 2, 15)] + [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1)] [Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)] [Row("Two.and.a.Half.Me.113.720p.HDTV.X264-DIMENSION", 1, 13)] [Row("Two.and.a.Half.Me.1013.720p.HDTV.X264-DIMENSION", 10, 13)] @@ -34,18 +35,6 @@ namespace NzbDrone.Core.Test Assert.AreEqual(episode, result.Episodes[0]); } - [Test] - [Row("The.Office.US.S03E01E02.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1, 2)] - [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1, 6)] - public void episode_parse_multi(string path, int season, int episodeOne, int episodeTwo) - { - var result = Parser.ParseEpisodeInfo(path); - Assert.Count(2, result); - Assert.AreEqual(season, result[0].SeasonNumber); - Assert.AreEqual(episodeOne, result[0].EpisodeNumber); - Assert.AreEqual(episodeTwo, result[1].EpisodeNumber); - } - [Test] [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.BDRip)] [Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.BDRip)] @@ -84,4 +73,4 @@ namespace NzbDrone.Core.Test Assert.AreEqual(clean, result); } } -} +} \ No newline at end of file diff --git a/NzbDrone.Core/Parser.cs b/NzbDrone.Core/Parser.cs index 9ba9a1f01..757eb546f 100644 --- a/NzbDrone.Core/Parser.cs +++ b/NzbDrone.Core/Parser.cs @@ -9,325 +9,6 @@ using NzbDrone.Core.Model; using NzbDrone.Core.Providers; using NzbDrone.Core.Repository.Quality; -namespace NzbDrone.Core -{ - internal static class Parser - { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - private static readonly Regex[] ReportTitleRegex = new[] - { - new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)((?:\-|\.|[a-z])(?<episode>\d+))+\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), - new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)(?<episode>\d{2})\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled) //Supports 103/113 naming - }; - - private static readonly Regex[] SeasonReportTitleRegex = new[] - { - new Regex(@"(?<title>.+?)?\W?(?<year>\d{4}?)?\W(?:S|Season)?\W?(?<season>\d+)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), - }; - - private static readonly Regex NormalizeRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled); - - /// <summary> - /// Parses a post title into list of episodes it contains - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns>List of episodes contained to the post</returns> - internal static EpisodeParseResult ParseEpisodeInfo(string title) - { - Logger.Trace("Parsing string '{0}'", title); - - foreach (var regex in ReportTitleRegex) - { - var match = regex.Matches(title); - - if (match.Count != 0) - { - var seriesName = NormalizeTitle(match[0].Groups["title"].Value); - var year = 0; - Int32.TryParse(match[0].Groups["year"].Value, out year); - - if (year < 1900 || year > DateTime.Now.Year + 1) - { - year = 0; - } - - var seasonNumber = Convert.ToInt32(matchGroup.Groups["season"].Value); - - foreach (Capture episode in matchGroup.Groups["episode"].Captures) - { -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using NLog; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Repository.Quality; - -namespace NzbDrone.Core -{ - internal static class Parser - { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - private static readonly Regex[] ReportTitleRegex = new[] - { - new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)(?:\-|\.|[a-z])(?<episode>\d+)\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), - new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)(?<episode>\d{2})\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled) //Supports 103/113 naming - }; - - private static readonly Regex[] SeasonReportTitleRegex = new[] - { - new Regex(@"(?<title>.+?)?\W?(?<year>\d{4}?)?\W(?:S|Season)?\W?(?<season>\d+)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), - }; - - private static readonly Regex NormalizeRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled); - - /// <summary> - /// Parses a post title into list of episodes it contains - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns>List of episodes contained to the post</returns> - internal static EpisodeParseResult ParseEpisodeInfo(string title) - { - Logger.Trace("Parsing string '{0}'", title); - - foreach (var regex in ReportTitleRegex) - { - var match = regex.Matches(title); - - if (match.Count != 0) - { - var seriesName = NormalizeTitle(match[0].Groups["title"].Value); - var year = 0; - Int32.TryParse(match[0].Groups["year"].Value, out year); - - if (year < 1900 || year > DateTime.Now.Year + 1) - { - year = 0; - } - - var parsedEpisode = new EpisodeParseResult - { - Proper = title.ToLower().Contains("proper"), - SeriesTitle = seriesName, - SeasonNumber = Convert.ToInt32(match[0].Groups["season"].Value), - Year = year, - Episodes = new List<int>() - }; - - foreach (Match matchGroup in match) - { - parsedEpisode.Episodes.Add(Convert.ToInt32(matchGroup.Groups["episode"].Value)); - - } - - parsedEpisode.Quality = ParseQuality(title); - - Logger.Trace("Episode Parsed. {0}", parsedEpisode); - - return parsedEpisode; - } - } - - return null; - } - - /// <summary> - /// Parses a post title into season it contains - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns>Season information contained in the post</returns> - internal static SeasonParseResult ParseSeasonInfo(string title) - { - Logger.Trace("Parsing string '{0}'", title); - - foreach (var regex in ReportTitleRegex) - { - var match = regex.Matches(title); - - if (match.Count != 0) - { - var seriesName = NormalizeTitle(match[0].Groups["title"].Value); - var year = 0; - Int32.TryParse(match[0].Groups["year"].Value, out year); - - if (year < 1900 || year > DateTime.Now.Year + 1) - { - year = 0; - } - - var seasonNumber = Convert.ToInt32(match[0].Groups["season"].Value); - - var result = new SeasonParseResult - { - SeriesTitle = seriesName, - SeasonNumber = seasonNumber, - Year = year - }; - - - result.Quality = ParseQuality(title); - - Logger.Trace("Season Parsed. {0}", result); - return result; - } - } - - return null; //Return null - } - - /// <summary> - /// Parses a post title to find the series that relates to it - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns>Normalized Series Name</returns> - internal static string ParseSeriesName(string title) - { - Logger.Trace("Parsing string '{0}'", title); - - foreach (var regex in ReportTitleRegex) - { - var match = regex.Matches(title); - - if (match.Count != 0) - { - var seriesName = NormalizeTitle(match[0].Groups["title"].Value); - var year = 0; - Int32.TryParse(match[0].Groups["year"].Value, out year); - - if (year < 1900 || year > DateTime.Now.Year + 1) - { - year = 0; - } - - Logger.Trace("Series Parsed. {0}", seriesName); - return seriesName; - } - } - - return String.Empty; - } - - /// <summary> - /// Parses proper status out of a report title - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns></returns> - internal static bool ParseProper(string title) - { - return title.ToLower().Contains("proper"); - } - - private static QualityTypes ParseQuality(string name) - { - Logger.Trace("Trying to parse quality for {0}", name); - - var result = QualityTypes.Unknown; - name = name.ToLowerInvariant(); - - if (name.Contains("dvd")) - return QualityTypes.DVD; - - if (name.Contains("bdrip") || name.Contains("brrip")) - { - return QualityTypes.BDRip; - } - - if (name.Contains("xvid") || name.Contains("divx")) - { - if (name.Contains("bluray")) - { - return QualityTypes.BDRip; - } - - return QualityTypes.TV; - } - - if (name.Contains("bluray")) - { - if (name.Contains("720p")) - return QualityTypes.Bluray720; - - if (name.Contains("1080p")) - return QualityTypes.Bluray1080; - - return QualityTypes.Bluray720; - } - if (name.Contains("web-dl")) - return QualityTypes.WEBDL; - if (name.Contains("x264") || name.Contains("h264") || name.Contains("720p")) - return QualityTypes.HDTV; - - //Based on extension - if (result == QualityTypes.Unknown) - { - switch (new FileInfo(name).Extension.ToLower()) - { - case ".avi": - case ".xvid": - case ".wmv": - { - result = QualityTypes.TV; - break; - } - case ".mkv": - { - result = QualityTypes.HDTV; - break; - } - } - } - - Logger.Trace("Quality Parsed:{0} Title:", result, name); - return result; - } - - /// <summary> - /// Normalizes the title. removing all non-word characters as well as common tokens - /// such as 'the' and 'and' - /// </summary> - /// <param name="title">title</param> - /// <returns></returns> - internal static string NormalizeTitle(string title) - { - return NormalizeRegex.Replace(title, String.Empty).ToLower(); - } - - //Note: changing case on path is a problem for running on mono/*nix - //Not going to change the casing any more... Looks Ugly in UI anyways :P - public static string NormalizePath(string path) - { - if (String.IsNullOrEmpty(path)) - throw new ArgumentException("Path can not be null or empty"); - - var info = new FileInfo(path); - - if (info.FullName.StartsWith(@"\\")) //UNC - { - return info.FullName.TrimEnd('/', '\\', ' '); - } - - return info.FullName.Trim('/', '\\', ' '); - } - - - } -} -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using NLog; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Repository.Quality; - namespace NzbDrone.Core { internal static class Parser @@ -575,211 +256,6 @@ namespace NzbDrone.Core return info.FullName.Trim('/', '\\', ' '); } - - } -} - - Proper = title.ToLower().Contains("proper"), - SeriesTitle = seriesName, - SeasonNumber = Convert.ToInt32(match[0].Groups["season"].Value), - Year = year, - Episodes = new List<int>() - }; - - foreach (Match matchGroup in match) - { - parsedEpisode.Episodes.Add(Convert.ToInt32(matchGroup.Groups["episode"].Value)); - - } - - parsedEpisode.Quality = ParseQuality(title); - Logger.Trace("Episode Parsed. {0}", parsedEpisode); - - return parsedEpisode; - } - } - - return null; - } - - /// <summary> - /// Parses a post title into season it contains - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns>Season information contained in the post</returns> - internal static SeasonParseResult ParseSeasonInfo(string title) - { - Logger.Trace("Parsing string '{0}'", title); - - foreach (var regex in ReportTitleRegex) - { - var match = regex.Matches(title); - - if (match.Count != 0) - { - var seriesName = NormalizeTitle(match[0].Groups["title"].Value); - var year = 0; - Int32.TryParse(match[0].Groups["year"].Value, out year); - - if (year < 1900 || year > DateTime.Now.Year + 1) - { - year = 0; - } - - var seasonNumber = Convert.ToInt32(match[0].Groups["season"].Value); - - var result = new SeasonParseResult - { - SeriesTitle = seriesName, - SeasonNumber = seasonNumber, - Year = year - }; - - - result.Quality = ParseQuality(title); - - Logger.Trace("Season Parsed. {0}", result); - return result; - } - } - - return null; //Return null - } - - /// <summary> - /// Parses a post title to find the series that relates to it - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns>Normalized Series Name</returns> - internal static string ParseSeriesName(string title) - { - Logger.Trace("Parsing string '{0}'", title); - - foreach (var regex in ReportTitleRegex) - { - var match = regex.Matches(title); - - if (match.Count != 0) - { - var seriesName = NormalizeTitle(match[0].Groups["title"].Value); - var year = 0; - Int32.TryParse(match[0].Groups["year"].Value, out year); - - if (year < 1900 || year > DateTime.Now.Year + 1) - { - year = 0; - } - - Logger.Trace("Series Parsed. {0}", seriesName); - return seriesName; - } - } - - return String.Empty; - } - - /// <summary> - /// Parses proper status out of a report title - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns></returns> - internal static bool ParseProper(string title) - { - return title.ToLower().Contains("proper"); - } - - private static QualityTypes ParseQuality(string name) - { - Logger.Trace("Trying to parse quality for {0}", name); - - var result = QualityTypes.Unknown; - name = name.ToLowerInvariant(); - - if (name.Contains("dvd")) - return QualityTypes.DVD; - - if (name.Contains("bdrip") || name.Contains("brrip")) - { - return QualityTypes.BDRip; - } - - if (name.Contains("xvid") || name.Contains("divx")) - { - if (name.Contains("bluray")) - { - return QualityTypes.BDRip; - } - - return QualityTypes.TV; - } - - if (name.Contains("bluray")) - { - if (name.Contains("720p")) - return QualityTypes.Bluray720; - - if (name.Contains("1080p")) - return QualityTypes.Bluray1080; - - return QualityTypes.Bluray720; - } - if (name.Contains("web-dl")) - return QualityTypes.WEBDL; - if (name.Contains("x264") || name.Contains("h264") || name.Contains("720p")) - return QualityTypes.HDTV; - - //Based on extension - if (result == QualityTypes.Unknown) - { - switch (new FileInfo(name).Extension.ToLower()) - { - case ".avi": - case ".xvid": - case ".wmv": - { - result = QualityTypes.TV; - break; - } - case ".mkv": - { - result = QualityTypes.HDTV; - break; - } - } - } - - Logger.Trace("Quality Parsed:{0} Title:", result, name); - return result; - } - - /// <summary> - /// Normalizes the title. removing all non-word characters as well as common tokens - /// such as 'the' and 'and' - /// </summary> - /// <param name="title">title</param> - /// <returns></returns> - internal static string NormalizeTitle(string title) - { - return NormalizeRegex.Replace(title, String.Empty).ToLower(); - } - - //Note: changing case on path is a problem for running on mono/*nix - //Not going to change the casing any more... Looks Ugly in UI anyways :P - public static string NormalizePath(string path) - { - if (String.IsNullOrEmpty(path)) - throw new ArgumentException("Path can not be null or empty"); - - var info = new FileInfo(path); - - if (info.FullName.StartsWith(@"\\")) //UNC - { - return info.FullName.TrimEnd('/', '\\', ' '); - } - - return info.FullName.Trim('/', '\\', ' '); - } - } -} +} \ No newline at end of file diff --git a/NzbDrone.Core/Providers/ITvDbProvider.cs b/NzbDrone.Core/Providers/ITvDbProvider.cs index 70a852a20..3746389ea 100644 --- a/NzbDrone.Core/Providers/ITvDbProvider.cs +++ b/NzbDrone.Core/Providers/ITvDbProvider.cs @@ -6,6 +6,7 @@ namespace NzbDrone.Core.Providers public interface ITvDbProvider { IList<TvdbSearchResult> SearchSeries(string name); + int GetBestMatch(List<TvdbSearchResult> searchResults, string searchString); TvdbSearchResult GetSeries(string title); TvdbSeries GetSeries(int id, bool loadEpisodes); } diff --git a/NzbDrone.Core/Providers/TvDbProvider.cs b/NzbDrone.Core/Providers/TvDbProvider.cs index 5651a5efc..6d5e2fdca 100644 --- a/NzbDrone.Core/Providers/TvDbProvider.cs +++ b/NzbDrone.Core/Providers/TvDbProvider.cs @@ -52,6 +52,23 @@ namespace NzbDrone.Core.Providers return null; } + public int GetBestMatch(List<TvdbSearchResult> searchResults, string title) + { + if (searchResults.Count == 0) + return 0; + + foreach (var tvdbSearchResult in searchResults) + { + if (IsTitleMatch(tvdbSearchResult.SeriesName, title)) + { + Logger.Debug("Search for '{0}' was successful", title); + return tvdbSearchResult.Id; + } + } + + return searchResults[0].Id; + } + public TvdbSeries GetSeries(int id, bool loadEpisodes) { Logger.Debug("Fetching SeriesId'{0}' from tvdb", id); diff --git a/NzbDrone.Web/Controllers/AddSeriesController.cs b/NzbDrone.Web/Controllers/AddSeriesController.cs index 0f4a4a6c1..d20e2ef26 100644 --- a/NzbDrone.Web/Controllers/AddSeriesController.cs +++ b/NzbDrone.Web/Controllers/AddSeriesController.cs @@ -80,12 +80,14 @@ namespace NzbDrone.Web.Controllers ViewData["path"] = path; ViewData["javaPath"] = path.Replace(Path.DirectorySeparatorChar, '|').Replace(Path.VolumeSeparatorChar, '^'); + var defaultQuality = _configProvider.DefaultQualityProfile; var qualityProfiles = _qualityProvider.GetAllProfiles(); + ViewData["quality"] = new SelectList( qualityProfiles, "QualityProfileId", "Name", - "HD"); + defaultQuality); ; return PartialView("AddSeriesItem", suggestions); @@ -117,8 +119,9 @@ namespace NzbDrone.Web.Controllers public SelectList GetSuggestionList(string searchString) { var dataVal = _tvDbProvider.SearchSeries(searchString); + var bestResult = _tvDbProvider.GetBestMatch(dataVal.ToList(), searchString); - return new SelectList(dataVal, "Id", "SeriesName"); + return new SelectList(dataVal, "Id", "SeriesName", bestResult); } } diff --git a/NzbDrone.Web/Views/AddSeries/AddExisting.aspx b/NzbDrone.Web/Views/AddSeries/AddExisting.aspx index fab8a8da8..de3aa9c21 100644 --- a/NzbDrone.Web/Views/AddSeries/AddExisting.aspx +++ b/NzbDrone.Web/Views/AddSeries/AddExisting.aspx @@ -7,6 +7,9 @@ </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <% + if (Model.Count() == 0) + Html.DisplayText("No Series to Add"); + foreach (var path in Model) { Html.RenderAction("RenderPartial", "AddSeries", new { path }); diff --git a/NzbDrone.Web/Views/AddSeries/AddSeriesItem.cshtml b/NzbDrone.Web/Views/AddSeries/AddSeriesItem.cshtml index 7fd70a03c..09458c69f 100644 --- a/NzbDrone.Web/Views/AddSeries/AddSeriesItem.cshtml +++ b/NzbDrone.Web/Views/AddSeries/AddSeriesItem.cshtml @@ -1,6 +1,6 @@ @using NzbDrone.Core.Repository.Quality @model SelectList -<div padding: 10px" id="div_@(ViewData["guid"])"> +<div style="padding:3px" id="div_@(ViewData["guid"])"> <fieldset> <legend>@ViewData["path"].ToString()</legend> <div> @@ -11,7 +11,7 @@ .Filterable(f => f.FilterMode(AutoCompleteFilterMode.Contains)) .HighlightFirstMatch(true) .HtmlAttributes(new { style = "width: 300px;" }) - .SelectedIndex(0).Render();} + .Render();} @Html.Telerik().DropDownList().Name("qualityList_" + ViewData["guid"].ToString()).BindTo((SelectList)ViewData["quality"]).HtmlAttributes(new { style = "width: 100px;" }) <button class="listButton" onclick="addSeries('@ViewData["guid"]','@ViewData["javaPath"].ToString()' )"> Add</button> From a30a62f824662683a8c1a288e438a79d9723ee4c Mon Sep 17 00:00:00 2001 From: Mark McDowall <markus.mcd5@gmail.com> Date: Mon, 4 Apr 2011 20:06:36 -0700 Subject: [PATCH 3/3] Removed orig files. --- NzbDrone.Core.Test/ParserTest.cs.orig | 91 --------- NzbDrone.Core/Parser.cs.orig | 282 -------------------------- 2 files changed, 373 deletions(-) delete mode 100644 NzbDrone.Core.Test/ParserTest.cs.orig delete mode 100644 NzbDrone.Core/Parser.cs.orig diff --git a/NzbDrone.Core.Test/ParserTest.cs.orig b/NzbDrone.Core.Test/ParserTest.cs.orig deleted file mode 100644 index 050d1b478..000000000 --- a/NzbDrone.Core.Test/ParserTest.cs.orig +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Gallio.Framework; -using MbUnit.Framework; -using MbUnit.Framework.ContractVerifiers; -using NzbDrone.Core.Repository.Quality; - -namespace NzbDrone.Core.Test -{ - [TestFixture] - // ReSharper disable InconsistentNaming - public class ParserTest - { - [Test] -<<<<<<< HEAD -======= - [Row("Sonny.With.a.Chance.S02E15", 2,15)] - [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1)] ->>>>>>> 2d9285eee29d96b6eedee98e358aa76c32c2998f - [Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)] - [Row("Two.and.a.Half.Me.113.720p.HDTV.X264-DIMENSION", 1, 13)] - [Row("Two.and.a.Half.Me.1013.720p.HDTV.X264-DIMENSION", 10, 13)] - [Row("Chuck.4x05.HDTV.XviD-LOL", 4, 5)] - [Row("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", 3, 6)] - [Row("Degrassi.S10E27.WS.DSR.XviD-2HD", 10, 27)] - [Row(@"z:\tv shows\battlestar galactica (2003)\Season 3\S03E05 - Collaborators.mkv", 3, 5)] - [Row(@"z:\tv shows\modern marvels\Season 16\S16E03 - The Potato.mkv", 16, 3)] - [Row(@"z:\tv shows\robot chicken\Specials\S00E16 - Dear Consumer - SD TV.avi", 0, 16)] - [Row(@"Parenthood.2010.S02E14.HDTV.XviD-LOL", 2, 14)] - [Row(@"Hawaii Five 0 S01E19 720p WEB DL DD5 1 H 264 NT", 1, 19)] - [Row(@"The Event S01E14 A Message Back 720p WEB DL DD5 1 H264 SURFER", 1, 14)] - [Row(@"Adam Hills In Gordon St Tonight S01E07 WS PDTV XviD FUtV", 1, 7)] - public void episode_parse(string path, int season, int episode) - { - var result = Parser.ParseEpisodeInfo(path); - Assert.AreEqual(season, result.SeasonNumber); - Assert.AreEqual(episode, result.Episodes[0]); - } - - [Test] - [Row("The.Office.US.S03E01E02.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1, 2)] - [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1, 6)] - public void episode_parse_multi(string path, int season, int episodeOne, int episodeTwo) - { - var result = Parser.ParseEpisodeInfo(path); - Assert.Count(2, result); - Assert.AreEqual(season, result[0].SeasonNumber); - Assert.AreEqual(episodeOne, result[0].EpisodeNumber); - Assert.AreEqual(episodeTwo, result[1].EpisodeNumber); - } - - [Test] - [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.BDRip)] - [Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.BDRip)] - [Row("Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", QualityTypes.HDTV)] - [Row("Chuck.S04E05.HDTV.XviD-LOL", QualityTypes.TV)] - [Row("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", QualityTypes.DVD)] - [Row("Degrassi.S10E27.WS.DSR.XviD-2HD", QualityTypes.TV)] - [Row("Sonny.With.a.Chance.S02E15.720p.WEB-DL.DD5.1.H.264-SURFER", QualityTypes.WEBDL)] - [Row("Sonny.With.a.Chance.S02E15.720p", QualityTypes.HDTV)] - [Row("Sonny.With.a.Chance.S02E15.mkv", QualityTypes.HDTV)] - [Row("Sonny.With.a.Chance.S02E15.avi", QualityTypes.TV)] - [Row("Sonny.With.a.Chance.S02E15.xvid", QualityTypes.TV)] - [Row("Sonny.With.a.Chance.S02E15.divx", QualityTypes.TV)] - [Row("Sonny.With.a.Chance.S02E15", QualityTypes.Unknown)] - [Row("Chuck - S01E04 - So Old - Playdate - 720p TV.mkv", QualityTypes.HDTV)] - [Row("Chuck - S22E03 - MoneyBART - HD TV.mkv", QualityTypes.HDTV)] - [Row("Chuck - S01E03 - Come Fly With Me - 720p BluRay.mkv", QualityTypes.Bluray720)] - [Row("Chuck - S01E03 - Come Fly With Me - 1080p BluRay.mkv", QualityTypes.Bluray1080)] - [Row("Chuck - S11E06 - D-Yikes! - 720p WEB-DL.mkv", QualityTypes.WEBDL)] - [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", QualityTypes.BDRip)] - public void quality_parse(string path, object quality) - { - var result = Parser.ParseEpisodeInfo(path).Quality; - Assert.AreEqual(quality, result); - } - - [Test] - [Row(@"c:\test\", @"c:\test")] - [Row(@"c:\\test\\", @"c:\test")] - [Row(@"C:\\Test\\", @"C:\Test")] - [Row(@"C:\\Test\\Test\", @"C:\Test\Test")] - [Row(@"\\Testserver\Test\", @"\\Testserver\Test")] - public void Normalize_Path(string dirty, string clean) - { - var result = Parser.NormalizePath(dirty); - Assert.AreEqual(clean, result); - } - } -} diff --git a/NzbDrone.Core/Parser.cs.orig b/NzbDrone.Core/Parser.cs.orig deleted file mode 100644 index 856d9b8c4..000000000 --- a/NzbDrone.Core/Parser.cs.orig +++ /dev/null @@ -1,282 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using NLog; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Repository.Quality; - -namespace NzbDrone.Core -{ - internal static class Parser - { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - private static readonly Regex[] ReportTitleRegex = new[] - { - new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)((?:\-|\.|[a-z])(?<episode>\d+))+\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), - new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)(?<episode>\d{2})\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled) //Supports 103/113 naming - }; - - private static readonly Regex[] SeasonReportTitleRegex = new[] - { - new Regex(@"(?<title>.+?)?\W?(?<year>\d{4}?)?\W(?:S|Season)?\W?(?<season>\d+)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), - }; - - private static readonly Regex NormalizeRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled); - - /// <summary> - /// Parses a post title into list of episodes it contains - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns>List of episodes contained to the post</returns> - internal static EpisodeParseResult ParseEpisodeInfo(string title) - { - Logger.Trace("Parsing string '{0}'", title); - - foreach (var regex in ReportTitleRegex) - { - var match = regex.Matches(title); - - if (match.Count != 0) - { - var seriesName = NormalizeTitle(match[0].Groups["title"].Value); - var year = 0; - Int32.TryParse(match[0].Groups["year"].Value, out year); - - if (year < 1900 || year > DateTime.Now.Year + 1) - { - year = 0; - } - - var parsedEpisode = new EpisodeParseResult - { - Proper = title.ToLower().Contains("proper"), - SeriesTitle = seriesName, - SeasonNumber = Convert.ToInt32(match[0].Groups["season"].Value), - Year = year, - Episodes = new List<int>() - }; - - foreach (Match matchGroup in match) - { - parsedEpisode.Episodes.Add(Convert.ToInt32(matchGroup.Groups["episode"].Value)); - -<<<<<<< HEAD - var seasonNumber = Convert.ToInt32(matchGroup.Groups["season"].Value); - - foreach (Capture episode in matchGroup.Groups["episode"].Captures) - { - var parsedEpisode = new EpisodeParseResult - { - SeriesTitle = seriesName, - SeasonNumber = seasonNumber, - EpisodeNumber = Convert.ToInt32(episode.Value), - Year = year - }; - - - result.Add(parsedEpisode); - Logger.Trace("Episode Parsed. {0}", parsedEpisode); - } - } - break; //Break out of the for loop, we don't want to process every REGEX for each item otherwise we'll get duplicates -======= - } - - parsedEpisode.Quality = ParseQuality(title); - - Logger.Trace("Episode Parsed. {0}", parsedEpisode); - - return parsedEpisode; ->>>>>>> 2d9285eee29d96b6eedee98e358aa76c32c2998f - } - } - - return null; - } - - /// <summary> - /// Parses a post title into season it contains - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns>Season information contained in the post</returns> - internal static SeasonParseResult ParseSeasonInfo(string title) - { - Logger.Trace("Parsing string '{0}'", title); - - foreach (var regex in ReportTitleRegex) - { - var match = regex.Matches(title); - - if (match.Count != 0) - { - var seriesName = NormalizeTitle(match[0].Groups["title"].Value); - var year = 0; - Int32.TryParse(match[0].Groups["year"].Value, out year); - - if (year < 1900 || year > DateTime.Now.Year + 1) - { - year = 0; - } - - var seasonNumber = Convert.ToInt32(match[0].Groups["season"].Value); - - var result = new SeasonParseResult - { - SeriesTitle = seriesName, - SeasonNumber = seasonNumber, - Year = year - }; - - - result.Quality = ParseQuality(title); - - Logger.Trace("Season Parsed. {0}", result); - return result; - } - } - - return null; //Return null - } - - /// <summary> - /// Parses a post title to find the series that relates to it - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns>Normalized Series Name</returns> - internal static string ParseSeriesName(string title) - { - Logger.Trace("Parsing string '{0}'", title); - - foreach (var regex in ReportTitleRegex) - { - var match = regex.Matches(title); - - if (match.Count != 0) - { - var seriesName = NormalizeTitle(match[0].Groups["title"].Value); - var year = 0; - Int32.TryParse(match[0].Groups["year"].Value, out year); - - if (year < 1900 || year > DateTime.Now.Year + 1) - { - year = 0; - } - - Logger.Trace("Series Parsed. {0}", seriesName); - return seriesName; - } - } - - return String.Empty; - } - - /// <summary> - /// Parses proper status out of a report title - /// </summary> - /// <param name="title">Title of the report</param> - /// <returns></returns> - internal static bool ParseProper(string title) - { - return title.ToLower().Contains("proper"); - } - - private static QualityTypes ParseQuality(string name) - { - Logger.Trace("Trying to parse quality for {0}", name); - - var result = QualityTypes.Unknown; - name = name.ToLowerInvariant(); - - if (name.Contains("dvd")) - return QualityTypes.DVD; - - if (name.Contains("bdrip") || name.Contains("brrip")) - { - return QualityTypes.BDRip; - } - - if (name.Contains("xvid") || name.Contains("divx")) - { - if (name.Contains("bluray")) - { - return QualityTypes.BDRip; - } - - return QualityTypes.TV; - } - - if (name.Contains("bluray")) - { - if (name.Contains("720p")) - return QualityTypes.Bluray720; - - if (name.Contains("1080p")) - return QualityTypes.Bluray1080; - - return QualityTypes.Bluray720; - } - if (name.Contains("web-dl")) - return QualityTypes.WEBDL; - if (name.Contains("x264") || name.Contains("h264") || name.Contains("720p")) - return QualityTypes.HDTV; - - //Based on extension - if (result == QualityTypes.Unknown) - { - switch (new FileInfo(name).Extension.ToLower()) - { - case ".avi": - case ".xvid": - case ".wmv": - { - result = QualityTypes.TV; - break; - } - case ".mkv": - { - result = QualityTypes.HDTV; - break; - } - } - } - - Logger.Trace("Quality Parsed:{0} Title:", result, name); - return result; - } - - /// <summary> - /// Normalizes the title. removing all non-word characters as well as common tokens - /// such as 'the' and 'and' - /// </summary> - /// <param name="title">title</param> - /// <returns></returns> - internal static string NormalizeTitle(string title) - { - return NormalizeRegex.Replace(title, String.Empty).ToLower(); - } - - //Note: changing case on path is a problem for running on mono/*nix - //Not going to change the casing any more... Looks Ugly in UI anyways :P - public static string NormalizePath(string path) - { - if (String.IsNullOrEmpty(path)) - throw new ArgumentException("Path can not be null or empty"); - - var info = new FileInfo(path); - - if (info.FullName.StartsWith(@"\\")) //UNC - { - return info.FullName.TrimEnd('/', '\\', ' '); - } - - return info.FullName.Trim('/', '\\', ' '); - } - - - } -}