diff --git a/NzbDrone.Core.Test/Files/TvRage/SearchResults_empty.xml b/NzbDrone.Core.Test/Files/TvRage/SearchResults_empty.xml
new file mode 100644
index 000000000..4f8843778
--- /dev/null
+++ b/NzbDrone.Core.Test/Files/TvRage/SearchResults_empty.xml
@@ -0,0 +1,3 @@
+
+
+0
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/Files/TvRage/SearchResults_many.xml b/NzbDrone.Core.Test/Files/TvRage/SearchResults_many.xml
new file mode 100644
index 000000000..31206736b
--- /dev/null
+++ b/NzbDrone.Core.Test/Files/TvRage/SearchResults_many.xml
@@ -0,0 +1,420 @@
+
+
+
+
+ 6753
+ Top Gear
+ http://www.tvrage.com/Top_Gear
+ UK
+ Oct/20/2002
+
+ 18
+ Returning Series
+ 60
+ Reality
+
+
+ Automobiles
+ Comedy
+
+ BBC TWO
+ 20:00
+ Sunday
+
+
+ 19321
+ Top Gear (1978)
+ http://www.tvrage.com/shows/id-19321
+ UK
+ Jul/13/1978
+ Dec/17/2001
+ 24
+ Canceled/Ended
+ 30
+ Reality
+
+ Automobiles
+
+ BBC TWO
+ 12:00
+ Sunday
+
+ Top Gear Xtra
+
+
+
+ 20568
+ Top Gear (US)
+ http://www.tvrage.com/Top_Gear_US
+ US
+ Nov/21/2010
+
+ 3
+ Returning Series
+ 60
+ Documentary
+
+ Automobiles
+ Comedy
+
+ History Channel
+ 21:00
+ Tuesday
+
+ Top Gear USA
+
+
+
+ 20324
+ Top Gear Australia
+ http://www.tvrage.com/shows/id-20324
+ AU
+ Sep/29/2008
+
+ 4
+ Returning Series
+ 60
+ Documentary
+
+ Automobiles
+ Comedy
+
+ GEM
+ 18:30
+ Saturday
+
+
+ 20569
+ Top Gear Motorsport
+ http://www.tvrage.com/shows/id-20569
+ UK
+ Mar/24/1995
+ 1998
+ 3
+ Canceled/Ended
+ 30
+ Sports
+
+ Educational
+ Family
+ How To/Do It Yourself
+
+ BBC TWO
+ 12:00
+ Wednesday
+
+
+ 6249
+ Top Secret Life of Edgar Briggs
+ http://www.tvrage.com/shows/id-6249
+ UK
+ Sep/15/1974
+ Dec/20/1974
+ 1
+ Canceled/Ended
+ 30
+ Scripted
+
+ Comedy
+
+ ITV
+ 19:00
+ Friday
+
+
+ 25253
+ Popstar Wesley: Op weg naar de Top
+ http://www.tvrage.com/shows/id-25253
+ NL
+ Feb/06/2010
+ Feb/27/2010
+ 1
+ Canceled/Ended
+ 15
+ Reality
+
+ How To/Do It Yourself
+ Music
+ Talent
+
+ SBS 6
+ 23:15
+ Saturday
+
+
+ 19649
+ Top Chef: Masters
+ http://www.tvrage.com/Top_Chef-Masters
+ US
+ Jun/10/2009
+
+ 4
+ Returning Series
+ 60
+ Reality
+
+ Cooking/Food
+ Family
+ Talent
+
+ Bravo
+ 22:00
+ Wednesday
+
+
+ 26212
+ Top Chef: Just Desserts
+ http://www.tvrage.com/Top_Chef-Just_Desserts
+ US
+ Sep/15/2010
+
+ 2
+ New Series
+ 60
+ Reality
+
+ Celebrities
+ Cooking/Food
+ Educational
+ Family
+ How To/Do It Yourself
+ Talent
+
+ Bravo
+ 22:00
+ Wednesday
+
+
+ 11210
+ Top Design
+ http://www.tvrage.com/shows/id-11210
+ US
+ Jan/31/2007
+ Nov/05/2008
+ 2
+ Canceled/Ended
+ 60
+ Reality
+
+ Celebrities
+ Educational
+ Family
+ Housing/Building
+ How To/Do It Yourself
+
+ Bravo
+ 22:00
+ Wednesday
+
+ Top Decorator
+ Top Designer
+
+
+
+ 15390
+ Air Gear
+ http://www.tvrage.com/shows/id-15390
+ AJ
+ Apr/04/2006
+ Sep/26/2006
+ 1
+ Canceled/Ended
+ 30
+ Animation
+
+ Anime
+ Adventure
+ Sci-Fi
+ Tech/Gaming
+
+ TV Tokyo
+ 12:00
+ Wednesday
+
+
+ 30933
+ Top Guns
+ http://www.tvrage.com/shows/id-30933
+ US
+ Feb/15/2012
+
+ 1
+ New Series
+ 60
+ Reality
+
+ Action
+ Family
+ How To/Do It Yourself
+ Talent
+
+ H2 TV
+ 22:00
+ Wednesday
+
+
+ 28150
+ Top Chef Canada
+ http://www.tvrage.com/shows/id-28150
+ CA
+ Apr/11/2011
+
+ 2
+ New Series
+ 60
+ Reality
+
+ Cooking/Food
+ Family
+ Talent
+
+ Food Network Canada
+ 21:00
+ Monday
+
+
+ 6386
+ Top of the Pops Saturday
+ http://www.tvrage.com/shows/id-6386
+ UK
+ Sep/20/2003
+ Mar/26/2005
+ 2
+ Canceled/Ended
+ 60
+ Variety
+
+ Children
+
+ BBC One
+ 23:00
+ Saturday
+
+
+ 29633
+ Top Secret Recipe
+ http://www.tvrage.com/shows/id-29633
+ US
+ Oct/07/2011
+
+ 1
+ New Series
+ 60
+ Reality
+
+ Cooking/Food
+ How To/Do It Yourself
+
+ CMT
+ 21:00
+ Thursday
+
+
+ 26650
+ The Top 100: NFL's Greatest Players
+ http://www.tvrage.com/shows/id-26650
+ US
+ Sep/03/2010
+ Nov/04/2010
+ 1
+ New Series
+ 60
+ Sports
+
+ Sports
+
+ NFL Network
+ 21:00
+ Thursday
+
+
+ 7047
+ Top of the Pops Reloaded
+ http://www.tvrage.com/shows/id-7047
+ UK
+ Sep/2005
+ Mar/2006
+ 2
+ Canceled/Ended
+ 45
+ Variety
+
+ Children
+ Music
+ Sketch/Improv
+
+ CBBC
+ 11:00
+ Saturday
+
+
+ 19475
+ Top Model Ghana
+ http://www.tvrage.com/shows/id-19475
+ GH
+ Aug/26/2006
+ Oct/16/2006
+ 1
+ Canceled/Ended
+ 60
+ Reality
+
+ Celebrities
+ Family
+ Fashion/Make-up
+ Talent
+ Travel
+
+ GTV
+ 21:00
+ Monday
+
+ Ghana's Next Top Model
+ TMG
+ Top Model Ghana, Cycle
+
+
+
+ 31823
+ Top 100 Video Games of All Time
+ http://www.tvrage.com/shows/id-31823
+ US
+ Jun/11/2012
+
+ 1
+ New Series
+ 60
+ Mini-Series
+
+ Family
+ Teens
+
+ G4
+ 20:00
+ Weekdays
+
+
+ 25003
+ Cantore Stories: On Top of the World
+ http://www.tvrage.com/Cantore_Stories-On_Top_of_the_World
+ US
+ Jan/24/2010
+
+ 1
+ New Series
+ 60
+ Reality
+
+ Adventure
+ Educational
+ Family
+ Travel
+
+ The Weather Channel
+ 22:00
+ Sunday
+
+ Cantore Stories
+
+
+
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/Files/TvRage/SearchResults_one.xml b/NzbDrone.Core.Test/Files/TvRage/SearchResults_one.xml
new file mode 100644
index 000000000..4517c22bc
--- /dev/null
+++ b/NzbDrone.Core.Test/Files/TvRage/SearchResults_one.xml
@@ -0,0 +1,26 @@
+
+
+
+
+ 27518
+ Suits
+ http://www.tvrage.com/Suits
+ US
+ Jun/23/2011
+
+ 2
+ Returning Series
+ 60
+ Scripted
+
+ Drama
+ Financial/Business
+
+ USA
+ 22:00
+ Thursday
+
+ A Legal Mind
+
+
+
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/Files/TvRage/SeriesInfo_empty.xml b/NzbDrone.Core.Test/Files/TvRage/SeriesInfo_empty.xml
new file mode 100644
index 000000000..52671b237
--- /dev/null
+++ b/NzbDrone.Core.Test/Files/TvRage/SeriesInfo_empty.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/Files/TvRage/SeriesInfo_one.xml b/NzbDrone.Core.Test/Files/TvRage/SeriesInfo_one.xml
new file mode 100644
index 000000000..f5eddca5b
--- /dev/null
+++ b/NzbDrone.Core.Test/Files/TvRage/SeriesInfo_one.xml
@@ -0,0 +1,22 @@
+
+
+
+ 29999
+ Anger Management
+ http://tvrage.com/shows/id-29999
+ 2
+ 2012
+ Jun/28/2012
+
+ US
+ Returning Series
+ Scripted
+
+ Comedy
+
+ 30
+ FX
+ 21:30
+ Thursday
+ GMT-5 -DST
+
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index 347380962..e9f2fe1a7 100644
--- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
+++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
@@ -139,6 +139,12 @@
+
+
+
+
+
+
@@ -328,6 +334,21 @@
Designer
Always
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
Always
diff --git a/NzbDrone.Core.Test/ProviderTests/TvRageMappingProviderTests/FindMatchingTvRageSeriesFixture.cs b/NzbDrone.Core.Test/ProviderTests/TvRageMappingProviderTests/FindMatchingTvRageSeriesFixture.cs
new file mode 100644
index 000000000..b6f4eafa1
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/TvRageMappingProviderTests/FindMatchingTvRageSeriesFixture.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using FizzWare.NBuilder;
+using FluentAssertions;
+using NUnit.Framework;
+using NzbDrone.Core.Model.TvRage;
+using NzbDrone.Core.Providers;
+using NzbDrone.Core.Repository;
+using NzbDrone.Test.Common;
+
+namespace NzbDrone.Core.Test.ProviderTests.TvRageMappingProviderTests
+{
+ public class FindMatchingTvRageSeriesFixture : TestBase
+ {
+ private IList _searchResults;
+ private Series _series;
+ private Episode _episode;
+ private TvRageSeries _tvRageSeries;
+
+ [SetUp]
+ public void Setup()
+ {
+ _searchResults = Builder
+ .CreateListOfSize(5)
+ .Build();
+
+ _series = Builder
+ .CreateNew()
+ .With(s => s.TvRageId = 0)
+ .With(s => s.TvRageTitle = null)
+ .With(s => s.UtcOffset = 0)
+ .Build();
+
+ _episode = Builder
+ .CreateNew()
+ .With(e => e.AirDate = DateTime.Today.AddDays(-365))
+ .Build();
+
+ _tvRageSeries = Builder
+ .CreateNew()
+ .With(s => s.UtcOffset = -8)
+ .Build();
+
+ Mocker.GetMock()
+ .Setup(s => s.GetEpisode(_series.SeriesId, 1, 1))
+ .Returns(_episode);
+
+ Mocker.GetMock()
+ .Setup(s => s.GetCleanName(_series.SeriesId))
+ .Returns("");
+
+ Mocker.GetMock()
+ .Setup(s => s.SearchSeries(_series.Title))
+ .Returns(_searchResults);
+
+ Mocker.GetMock()
+ .Setup(s => s.GetSeries(_searchResults.First().ShowId))
+ .Returns(_tvRageSeries);
+ }
+
+ private void WithMatchingResult()
+ {
+ _series.CleanTitle = Parser.NormalizeTitle(_searchResults.First().Name);
+ }
+
+ [Test]
+ public void should_not_set_tvRage_info_when_result_is_null()
+ {
+ var result = Mocker.Resolve()
+ .FindMatchingTvRageSeries(_series);
+
+ result.TvRageId.Should().Be(0);
+ result.TvRageTitle.Should().Be(null);
+ result.UtcOffset.Should().Be(0);
+ }
+
+ [Test]
+ public void should_set_tvRage_info_when_result_is_returned()
+ {
+ WithMatchingResult();
+
+ var result = Mocker.Resolve()
+ .FindMatchingTvRageSeries(_series);
+
+ result.TvRageId.Should().Be(_searchResults.First().ShowId);
+ result.TvRageTitle.Should().Be(_searchResults.First().Name);
+ result.UtcOffset.Should().Be(_tvRageSeries.UtcOffset);
+ }
+ }
+}
diff --git a/NzbDrone.Core.Test/ProviderTests/TvRageMappingProviderTests/ProcessResultsFixture.cs b/NzbDrone.Core.Test/ProviderTests/TvRageMappingProviderTests/ProcessResultsFixture.cs
new file mode 100644
index 000000000..afd8e0779
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/TvRageMappingProviderTests/ProcessResultsFixture.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using FizzWare.NBuilder;
+using FluentAssertions;
+using NUnit.Framework;
+using NzbDrone.Core.Model.TvRage;
+using NzbDrone.Core.Providers;
+using NzbDrone.Core.Repository;
+using NzbDrone.Test.Common;
+
+namespace NzbDrone.Core.Test.ProviderTests.TvRageMappingProviderTests
+{
+ public class ProcessResultsFixture : TestBase
+ {
+ private IList _searchResults;
+ private Series _series;
+ private Episode _episode;
+
+ [SetUp]
+ public void Setup()
+ {
+ _searchResults = Builder
+ .CreateListOfSize(5)
+ .Build();
+
+ _series = Builder.CreateNew().Build();
+
+ _episode = Builder
+ .CreateNew()
+ .With(e => e.AirDate = DateTime.Today.AddDays(-365))
+ .Build();
+ }
+
+ [Test]
+ public void should_return_null_if_no_match_is_found()
+ {
+ Mocker.Resolve()
+ .ProcessResults(_searchResults, _series, "nomatchhere", _episode)
+ .Should()
+ .BeNull();
+ }
+
+ [Test]
+ public void should_return_result_if_series_clean_name_matches()
+ {
+ _series.CleanTitle = Parser.NormalizeTitle(_searchResults.First().Name);
+
+ Mocker.Resolve()
+ .ProcessResults(_searchResults, _series, "nomatchhere", _episode)
+ .Should()
+ .Be(_searchResults.First());
+ }
+
+ [Test]
+ public void should_return_result_if_scene_clean_name_matches()
+ {
+ Mocker.Resolve()
+ .ProcessResults(_searchResults, _series, Parser.NormalizeTitle(_searchResults.First().Name), _episode)
+ .Should()
+ .Be(_searchResults.First());
+ }
+
+ [Test]
+ public void should_return_result_if_firstAired_matches()
+ {
+ _episode.AirDate = _searchResults.Last().Started;
+
+ Mocker.Resolve()
+ .ProcessResults(_searchResults, _series, "nomatchhere", _episode)
+ .Should()
+ .Be(_searchResults.Last());
+ }
+ }
+}
diff --git a/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/GetSeriesFixture.cs b/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/GetSeriesFixture.cs
new file mode 100644
index 000000000..d5adac66a
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/GetSeriesFixture.cs
@@ -0,0 +1,59 @@
+// ReSharper disable RedundantUsingDirective
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using FluentAssertions;
+using Moq;
+using NUnit.Framework;
+using Ninject;
+using NzbDrone.Common;
+using NzbDrone.Core.Providers;
+using NzbDrone.Core.Test.Framework;
+using NzbDrone.Test.Common;
+using TvdbLib.Data;
+using TvdbLib.Exceptions;
+
+namespace NzbDrone.Core.Test.ProviderTests.TvRageProviderTests
+{
+ [TestFixture]
+ // ReSharper disable InconsistentNaming
+ public class GetSeriesFixture : CoreTest
+ {
+ private const string showinfo = "http://services.tvrage.com/feeds/showinfo.php?key=NW4v0PSmQIoVmpbASLdD&sid=";
+
+ private void WithEmptyResults()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadStream(It.Is(u => u.StartsWith(showinfo)), null))
+ .Returns(new FileStream(@".\Files\TVRage\SeriesInfo_empty.xml", FileMode.Open, FileAccess.Read, FileShare.Read));
+ }
+
+ private void WithOneResult()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadStream(It.Is(u => u.StartsWith(showinfo)), null))
+ .Returns(new FileStream(@".\Files\TVRage\SeriesInfo_one.xml", FileMode.Open, FileAccess.Read, FileShare.Read));
+ }
+
+ [Test]
+ public void should_be_null_when_no_showinfo_is_returned()
+ {
+ WithEmptyResults();
+ Mocker.Resolve().GetSeries(100).Should().BeNull();
+
+ ExceptionVerification.ExpectedWarns(1);
+ }
+
+ [Test]
+ public void should_return_series_when_showinfo_is_valid()
+ {
+ WithOneResult();
+ var result = Mocker.Resolve().GetSeries(29999);
+
+ result.ShowId.Should().Be(29999);
+ result.Name.Should().Be("Anger Management");
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/GetUtcOffsetFixture.cs b/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/GetUtcOffsetFixture.cs
new file mode 100644
index 000000000..8c55feaef
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/GetUtcOffsetFixture.cs
@@ -0,0 +1,50 @@
+// ReSharper disable RedundantUsingDirective
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using FluentAssertions;
+using NUnit.Framework;
+using Ninject;
+using NzbDrone.Common;
+using NzbDrone.Core.Providers;
+using NzbDrone.Core.Test.Framework;
+using NzbDrone.Test.Common;
+using TvdbLib.Data;
+using TvdbLib.Exceptions;
+
+namespace NzbDrone.Core.Test.ProviderTests.TvRageProviderTests
+{
+ [TestFixture]
+ // ReSharper disable InconsistentNaming
+ public class GetUtcOffsetFixture : CoreTest
+ {
+ [Test]
+ public void should_return_zero_if_timeZone_is_empty()
+ {
+ Mocker.Resolve().GetUtcOffset("").Should().Be(0);
+ }
+
+ [Test]
+ public void should_return_zero_if_cannot_be_coverted_to_int()
+ {
+ Mocker.Resolve().GetUtcOffset("adfhadfhdjaf").Should().Be(0);
+ }
+
+ [TestCase("GMT-5", -5)]
+ [TestCase("GMT+0", 0)]
+ [TestCase("GMT+8", 8)]
+ public void should_return_offset_when_not_dst(string timezone, int expected)
+ {
+ Mocker.Resolve().GetUtcOffset(timezone).Should().Be(expected);
+ }
+
+ [TestCase("GMT-5 +DST", -4)]
+ [TestCase("GMT+0 +DST", 1)]
+ [TestCase("GMT+8 +DST", 9)]
+ public void should_return_offset_plus_one_when_dst(string timezone, int expected)
+ {
+ Mocker.Resolve().GetUtcOffset(timezone).Should().Be(expected);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/ParseDayOfWeekFixture.cs b/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/ParseDayOfWeekFixture.cs
new file mode 100644
index 000000000..95cf3699d
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/ParseDayOfWeekFixture.cs
@@ -0,0 +1,65 @@
+// ReSharper disable RedundantUsingDirective
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+using FluentAssertions;
+using NUnit.Framework;
+using Ninject;
+using NzbDrone.Common;
+using NzbDrone.Core.Providers;
+using NzbDrone.Core.Test.Framework;
+using NzbDrone.Test.Common;
+using TvdbLib.Data;
+using TvdbLib.Exceptions;
+
+namespace NzbDrone.Core.Test.ProviderTests.TvRageProviderTests
+{
+ [TestFixture]
+ // ReSharper disable InconsistentNaming
+ public class ParseDayOfWeekFixture : CoreTest
+ {
+ [Test]
+ public void should_return_null_if_xelement_is_null()
+ {
+ Mocker.Resolve().ParseDayOfWeek(null).Should().Be(null);
+ }
+
+ [Test]
+ public void should_return_null_if_value_is_null()
+ {
+ Mocker.Resolve().ParseDayOfWeek(new XElement("airday", null)).Should().Be(null);
+ }
+
+ [Test]
+ public void should_return_null_if_value_is_empty()
+ {
+ Mocker.Resolve().ParseDayOfWeek(new XElement("airday", "")).Should().Be(null);
+ }
+
+ [Test]
+ public void should_return_null_if_value_is_daily()
+ {
+ Mocker.Resolve().ParseDayOfWeek(new XElement("airday", "Daily")).Should().Be(null);
+ }
+
+ [Test]
+ public void should_return_null_if_value_is_weekdays()
+ {
+ Mocker.Resolve().ParseDayOfWeek(new XElement("airday", "Weekdays")).Should().Be(null);
+ }
+
+ [TestCase("Sunday", DayOfWeek.Sunday)]
+ [TestCase("Monday", DayOfWeek.Monday)]
+ [TestCase("Tuesday", DayOfWeek.Tuesday)]
+ [TestCase("Wednesday", DayOfWeek.Wednesday)]
+ [TestCase("Thursday", DayOfWeek.Thursday)]
+ [TestCase("Friday", DayOfWeek.Friday)]
+ [TestCase("Saturday", DayOfWeek.Saturday)]
+ public void should_return_dayOfWeek_when_it_is_valid(string value, DayOfWeek expected)
+ {
+ Mocker.Resolve().ParseDayOfWeek(new XElement("airday", value)).Should().Be(expected);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/SearchSeriesFixture.cs b/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/SearchSeriesFixture.cs
new file mode 100644
index 000000000..1d64de299
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/TvRageProviderTests/SearchSeriesFixture.cs
@@ -0,0 +1,82 @@
+// ReSharper disable RedundantUsingDirective
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using FluentAssertions;
+using Moq;
+using NUnit.Framework;
+using Ninject;
+using NzbDrone.Common;
+using NzbDrone.Core.Providers;
+using NzbDrone.Core.Test.Framework;
+using NzbDrone.Test.Common;
+using TvdbLib.Data;
+using TvdbLib.Exceptions;
+
+namespace NzbDrone.Core.Test.ProviderTests.TvRageProviderTests
+{
+ [TestFixture]
+ // ReSharper disable InconsistentNaming
+ public class SearchSeriesFixture : CoreTest
+ {
+ private const string search = "http://services.tvrage.com/feeds/full_search.php?show=";
+
+ private void WithEmptyResults()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadStream(It.Is(u => u.StartsWith(search)), null))
+ .Returns(new FileStream(@".\Files\TVRage\SearchResults_empty.xml", FileMode.Open, FileAccess.Read, FileShare.Read));
+ }
+
+ private void WithManyResults()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadStream(It.Is(u => u.StartsWith(search)), null))
+ .Returns(new FileStream(@".\Files\TVRage\SearchResults_many.xml", FileMode.Open, FileAccess.Read, FileShare.Read));
+ }
+
+ private void WithOneResult()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.DownloadStream(It.Is(u => u.StartsWith(search)), null))
+ .Returns(new FileStream(@".\Files\TVRage\SearchResults_one.xml", FileMode.Open, FileAccess.Read, FileShare.Read));
+ }
+
+ [Test]
+ public void should_be_empty_when_no_results_are_found()
+ {
+ WithEmptyResults();
+ Mocker.Resolve().SearchSeries("asdasdasdasdas").Should().BeEmpty();
+ }
+
+ [Test]
+ public void should_be_have_more_than_one_when_multiple_results_are_returned()
+ {
+ WithManyResults();
+ Mocker.Resolve().SearchSeries("top+gear").Should().NotBeEmpty();
+ }
+
+ [Test]
+ public void should_have_one_when_only_one_result_is_found()
+ {
+ WithOneResult();
+ Mocker.Resolve().SearchSeries("suits").Should().HaveCount(1);
+ }
+
+ [Test]
+ public void ended_should_not_have_a_value_when_series_has_not_ended()
+ {
+ WithOneResult();
+ Mocker.Resolve().SearchSeries("suits").First().Ended.HasValue.Should().BeFalse();
+ }
+
+ [Test]
+ public void started_should_match_series()
+ {
+ WithOneResult();
+ Mocker.Resolve().SearchSeries("suits").First().Started.Should().Be(new DateTime(2011, 6, 23));
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Datastore/Migrations/Migration20121218.cs b/NzbDrone.Core/Datastore/Migrations/Migration20121218.cs
new file mode 100644
index 000000000..00061a9e1
--- /dev/null
+++ b/NzbDrone.Core/Datastore/Migrations/Migration20121218.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Data;
+using Migrator.Framework;
+using NzbDrone.Common;
+
+namespace NzbDrone.Core.Datastore.Migrations
+{
+ [Migration(20121218)]
+ public class Migration20121218 : NzbDroneMigration
+ {
+ protected override void MainDbUpgrade()
+ {
+ Database.AddColumn("Series", new Column("TvRageId", DbType.Int32, ColumnProperty.Null));
+ Database.AddColumn("Series", new Column("TvRageTitle", DbType.String, ColumnProperty.Null));
+ Database.AddColumn("Series", new Column("UtcOffset", DbType.Int32, ColumnProperty.Null));
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Model/TvRage/TvRageEpisode.cs b/NzbDrone.Core/Model/TvRage/TvRageEpisode.cs
new file mode 100644
index 000000000..e7149fb11
--- /dev/null
+++ b/NzbDrone.Core/Model/TvRage/TvRageEpisode.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NzbDrone.Core.Model.TvRage
+{
+ public class TvRageEpisode
+ {
+ public int EpisodeNumber { get; set; }
+ public int SeasonNumber { get; set; }
+ public string ProductionCode { get; set; }
+ public DateTime AirDate { get; set; }
+ public string Link { get; set; }
+ public string Title { get; set; }
+ }
+}
diff --git a/NzbDrone.Core/Model/TvRage/TvRageSearchResult.cs b/NzbDrone.Core/Model/TvRage/TvRageSearchResult.cs
new file mode 100644
index 000000000..9d7c6a8b6
--- /dev/null
+++ b/NzbDrone.Core/Model/TvRage/TvRageSearchResult.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NzbDrone.Core.Model.TvRage
+{
+ public class TvRageSearchResult
+ {
+ public int ShowId { get; set; }
+ public string Name { get; set; }
+ public string Link { get; set; }
+ public string Country { get; set; }
+ public DateTime Started { get; set; }
+ public DateTime? Ended { get; set; }
+ public int Seasons { get; set; }
+ public string Status { get; set; }
+ public int RunTime { get; set; }
+ public DateTime AirTime { get; set; }
+ public DayOfWeek? AirDay { get; set; }
+ }
+}
diff --git a/NzbDrone.Core/Model/TvRage/TvRageSeries.cs b/NzbDrone.Core/Model/TvRage/TvRageSeries.cs
new file mode 100644
index 000000000..ebc69f022
--- /dev/null
+++ b/NzbDrone.Core/Model/TvRage/TvRageSeries.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NzbDrone.Core.Model.TvRage
+{
+ public class TvRageSeries
+ {
+ public int ShowId { get; set; }
+ public string Name { get; set; }
+ public string Link { get; set; }
+ public int Seasons { get; set; }
+ public int Started { get; set; }
+ public DateTime StartDate { get; set; }
+ public DateTime Ended { get; set; }
+ public string OriginCountry { get; set; }
+ public string Status { get; set; }
+ public int RunTime { get; set; }
+ public string Network { get; set; }
+ public DateTime AirTime { get; set; }
+ public DayOfWeek? AirDay { get; set; }
+ public int UtcOffset { get; set; }
+ }
+}
diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj
index 26db534af..402f146d9 100644
--- a/NzbDrone.Core/NzbDrone.Core.csproj
+++ b/NzbDrone.Core/NzbDrone.Core.csproj
@@ -228,6 +228,7 @@
+
@@ -291,6 +292,9 @@
+
+
+
@@ -343,6 +347,8 @@
+
+
diff --git a/NzbDrone.Core/Providers/SceneMappingProvider.cs b/NzbDrone.Core/Providers/SceneMappingProvider.cs
index ad70a6d65..d4f119d80 100644
--- a/NzbDrone.Core/Providers/SceneMappingProvider.cs
+++ b/NzbDrone.Core/Providers/SceneMappingProvider.cs
@@ -99,5 +99,15 @@ namespace NzbDrone.Core.Providers
return false;
}
+
+ public virtual string GetCleanName(int seriesId)
+ {
+ var item = _database.FirstOrDefault("WHERE SeriesId = @0", seriesId);
+
+ if (item == null)
+ return null;
+
+ return item.CleanTitle;
+ }
}
}
diff --git a/NzbDrone.Core/Providers/SeriesProvider.cs b/NzbDrone.Core/Providers/SeriesProvider.cs
index ecbded829..70d167ae9 100644
--- a/NzbDrone.Core/Providers/SeriesProvider.cs
+++ b/NzbDrone.Core/Providers/SeriesProvider.cs
@@ -14,18 +14,23 @@ namespace NzbDrone.Core.Providers
{
public class SeriesProvider
{
- private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+
private readonly ConfigProvider _configProvider;
private readonly TvDbProvider _tvDbProvider;
private readonly IDatabase _database;
private readonly SceneMappingProvider _sceneNameMappingProvider;
private readonly BannerProvider _bannerProvider;
private readonly MetadataProvider _metadataProvider;
+ private readonly TvRageMappingProvider _tvRageMappingProvider;
+
+ private static readonly Logger logger = LogManager.GetCurrentClassLogger();
+
private static readonly Regex TimeRegex = new Regex(@"^(?