fully replaced TVDB with Trakt.tv

pull/23/head
kay.one 11 years ago
parent af3282630f
commit a052a9389e

@ -1,27 +1,24 @@
using System.Linq; using Nancy;
using Nancy;
using NzbDrone.Api.Extensions; using NzbDrone.Api.Extensions;
using NzbDrone.Api.QualityType;
using NzbDrone.Core.MetadataSource; using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Providers;
namespace NzbDrone.Api.Series namespace NzbDrone.Api.Series
{ {
public class SeriesLookupModule : NzbDroneApiModule public class SeriesLookupModule : NzbDroneApiModule
{ {
private readonly TvDbProxy _tvDbProxy; private readonly ISearchForNewSeries _searchProxy;
public SeriesLookupModule(TvDbProxy tvDbProxy) public SeriesLookupModule(ISearchForNewSeries searchProxy)
: base("/Series/lookup") : base("/Series/lookup")
{ {
_tvDbProxy = tvDbProxy; _searchProxy = searchProxy;
Get["/"] = x => GetQualityType(); Get["/"] = x => GetQualityType();
} }
private Response GetQualityType() private Response GetQualityType()
{ {
var tvDbResults = _tvDbProxy.SearchSeries((string)Request.Query.term); var tvDbResults = _searchProxy.SearchForNewSeries((string)Request.Query.term);
return tvDbResults.AsResponse(); return tvDbResults.AsResponse();
} }
} }

@ -1,15 +1,39 @@
using System.Text.RegularExpressions;
using System.Linq;
namespace NzbDrone.Common.EnsureThat namespace NzbDrone.Common.EnsureThat
{ {
internal static class StringExtensions public static class StringExtensions
{ {
internal static string Inject(this string format, params object[] formattingArgs) public static string Inject(this string format, params object[] formattingArgs)
{ {
return string.Format(format, formattingArgs); return string.Format(format, formattingArgs);
} }
internal static string Inject(this string format, params string[] formattingArgs) public static string Inject(this string format, params string[] formattingArgs)
{ {
return string.Format(format, formattingArgs); return string.Format(format, formattingArgs.Cast<object>());
}
private static readonly Regex InvalidCharRegex = new Regex(@"[^a-z0-9\s-]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex CollapseSpace = new Regex(@"\s+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static string ToSlug(this string phrase)
{
phrase = phrase.RemoveAccent().ToLower();
phrase = InvalidCharRegex.Replace(phrase, string.Empty);
phrase = CollapseSpace.Replace(phrase, " ").Trim();
phrase = phrase.Replace(" ", "-");
return phrase;
}
public static string RemoveAccent(this string txt)
{
var bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(txt);
return System.Text.Encoding.ASCII.GetString(bytes);
} }
} }
} }

@ -29,7 +29,6 @@ namespace NzbDrone.Common.Eventing
_logger.Debug("{0} <- {1}", message.GetType().Name, handler.GetType().Name); _logger.Debug("{0} <- {1}", message.GetType().Name, handler.GetType().Name);
} }
foreach (var handler in _handlers().OfType<IHandleAsync<TEvent>>()) foreach (var handler in _handlers().OfType<IHandleAsync<TEvent>>())
{ {
var handlerLocal = handler; var handlerLocal = handler;

@ -137,7 +137,6 @@
<Compile Include="UdpProvider.cs" /> <Compile Include="UdpProvider.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="EnsureThat\ve-3BAF.tmp" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -13,7 +13,7 @@ namespace NzbDrone.Core.Test.Datastore
[TestFixture] [TestFixture]
public class DatabaseRelationshipFixture : DbTest public class DatabaseRelationshipFixture : DbTest
{ {
[Test] /* [Test]
[Explicit] [Explicit]
public void benchmark() public void benchmark()
{ {
@ -70,7 +70,7 @@ namespace NzbDrone.Core.Test.Datastore
var loadedSeries = Db.Single<Series>(); var loadedSeries = Db.Single<Series>();
loadedSeries.Covers.Value.Should().HaveSameCount(covers); loadedSeries.Covers.Value.Should().HaveSameCount(covers);
} }*/
[Test] [Test]
public void one_to_one() public void one_to_one()

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Results>0</Results>

@ -1,420 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Results>
<show>
<showid>6753</showid>
<name>Top Gear</name>
<link>http://www.tvrage.com/Top_Gear</link>
<country>UK</country>
<started>Oct/20/2002</started>
<ended></ended>
<seasons>18</seasons>
<status>Returning Series</status>
<runtime>60</runtime>
<classification>Reality</classification>
<genres>
<genre></genre>
<genre>Automobiles</genre>
<genre>Comedy</genre>
</genres>
<network country="UK">BBC TWO</network>
<airtime>20:00</airtime>
<airday>Sunday</airday>
</show>
<show>
<showid>19321</showid>
<name>Top Gear (1978)</name>
<link>http://www.tvrage.com/shows/id-19321</link>
<country>UK</country>
<started>Jul/13/1978</started>
<ended>Dec/17/2001</ended>
<seasons>24</seasons>
<status>Canceled/Ended</status>
<runtime>30</runtime>
<classification>Reality</classification>
<genres>
<genre>Automobiles</genre>
</genres>
<network country="UK">BBC TWO</network>
<airtime>12:00</airtime>
<airday>Sunday</airday>
<akas>
<aka country="UK">Top Gear Xtra</aka>
</akas>
</show>
<show>
<showid>20568</showid>
<name>Top Gear (US)</name>
<link>http://www.tvrage.com/Top_Gear_US</link>
<country>US</country>
<started>Nov/21/2010</started>
<ended></ended>
<seasons>3</seasons>
<status>Returning Series</status>
<runtime>60</runtime>
<classification>Documentary</classification>
<genres>
<genre>Automobiles</genre>
<genre>Comedy</genre>
</genres>
<network country="US">History Channel</network>
<airtime>21:00</airtime>
<airday>Tuesday</airday>
<akas>
<aka attr="Unofficial Working Title">Top Gear USA</aka>
</akas>
</show>
<show>
<showid>20324</showid>
<name>Top Gear Australia</name>
<link>http://www.tvrage.com/shows/id-20324</link>
<country>AU</country>
<started>Sep/29/2008</started>
<ended></ended>
<seasons>4</seasons>
<status>Returning Series</status>
<runtime>60</runtime>
<classification>Documentary</classification>
<genres>
<genre>Automobiles</genre>
<genre>Comedy</genre>
</genres>
<network country="AU">GEM</network>
<airtime>18:30</airtime>
<airday>Saturday</airday>
</show>
<show>
<showid>20569</showid>
<name>Top Gear Motorsport</name>
<link>http://www.tvrage.com/shows/id-20569</link>
<country>UK</country>
<started>Mar/24/1995</started>
<ended>1998</ended>
<seasons>3</seasons>
<status>Canceled/Ended</status>
<runtime>30</runtime>
<classification>Sports</classification>
<genres>
<genre>Educational</genre>
<genre>Family</genre>
<genre>How To/Do It Yourself</genre>
</genres>
<network country="UK">BBC TWO</network>
<airtime>12:00</airtime>
<airday>Wednesday</airday>
</show>
<show>
<showid>6249</showid>
<name>Top Secret Life of Edgar Briggs</name>
<link>http://www.tvrage.com/shows/id-6249</link>
<country>UK</country>
<started>Sep/15/1974</started>
<ended>Dec/20/1974</ended>
<seasons>1</seasons>
<status>Canceled/Ended</status>
<runtime>30</runtime>
<classification>Scripted</classification>
<genres>
<genre>Comedy</genre>
</genres>
<network country="UK">ITV</network>
<airtime>19:00</airtime>
<airday>Friday</airday>
</show>
<show>
<showid>25253</showid>
<name>Popstar Wesley: Op weg naar de Top</name>
<link>http://www.tvrage.com/shows/id-25253</link>
<country>NL</country>
<started>Feb/06/2010</started>
<ended>Feb/27/2010</ended>
<seasons>1</seasons>
<status>Canceled/Ended</status>
<runtime>15</runtime>
<classification>Reality</classification>
<genres>
<genre>How To/Do It Yourself</genre>
<genre>Music</genre>
<genre>Talent</genre>
</genres>
<network country="NL">SBS 6</network>
<airtime>23:15</airtime>
<airday>Saturday</airday>
</show>
<show>
<showid>19649</showid>
<name>Top Chef: Masters</name>
<link>http://www.tvrage.com/Top_Chef-Masters</link>
<country>US</country>
<started>Jun/10/2009</started>
<ended></ended>
<seasons>4</seasons>
<status>Returning Series</status>
<runtime>60</runtime>
<classification>Reality</classification>
<genres>
<genre>Cooking/Food</genre>
<genre>Family</genre>
<genre>Talent</genre>
</genres>
<network country="US">Bravo</network>
<airtime>22:00</airtime>
<airday>Wednesday</airday>
</show>
<show>
<showid>26212</showid>
<name>Top Chef: Just Desserts</name>
<link>http://www.tvrage.com/Top_Chef-Just_Desserts</link>
<country>US</country>
<started>Sep/15/2010</started>
<ended></ended>
<seasons>2</seasons>
<status>New Series</status>
<runtime>60</runtime>
<classification>Reality</classification>
<genres>
<genre>Celebrities</genre>
<genre>Cooking/Food</genre>
<genre>Educational</genre>
<genre>Family</genre>
<genre>How To/Do It Yourself</genre>
<genre>Talent</genre>
</genres>
<network country="US">Bravo</network>
<airtime>22:00</airtime>
<airday>Wednesday</airday>
</show>
<show>
<showid>11210</showid>
<name>Top Design</name>
<link>http://www.tvrage.com/shows/id-11210</link>
<country>US</country>
<started>Jan/31/2007</started>
<ended>Nov/05/2008</ended>
<seasons>2</seasons>
<status>Canceled/Ended</status>
<runtime>60</runtime>
<classification>Reality</classification>
<genres>
<genre>Celebrities</genre>
<genre>Educational</genre>
<genre>Family</genre>
<genre>Housing/Building</genre>
<genre>How To/Do It Yourself</genre>
</genres>
<network country="US">Bravo</network>
<airtime>22:00</airtime>
<airday>Wednesday</airday>
<akas>
<aka attr="Working Title">Top Decorator</aka>
<aka attr="Working Title">Top Designer</aka>
</akas>
</show>
<show>
<showid>15390</showid>
<name>Air Gear</name>
<link>http://www.tvrage.com/shows/id-15390</link>
<country>AJ</country>
<started>Apr/04/2006</started>
<ended>Sep/26/2006</ended>
<seasons>1</seasons>
<status>Canceled/Ended</status>
<runtime>30</runtime>
<classification>Animation</classification>
<genres>
<genre>Anime</genre>
<genre>Adventure</genre>
<genre>Sci-Fi</genre>
<genre>Tech/Gaming</genre>
</genres>
<network country="JP">TV Tokyo</network>
<airtime>12:00</airtime>
<airday>Wednesday</airday>
</show>
<show>
<showid>30933</showid>
<name>Top Guns</name>
<link>http://www.tvrage.com/shows/id-30933</link>
<country>US</country>
<started>Feb/15/2012</started>
<ended></ended>
<seasons>1</seasons>
<status>New Series</status>
<runtime>60</runtime>
<classification>Reality</classification>
<genres>
<genre>Action</genre>
<genre>Family</genre>
<genre>How To/Do It Yourself</genre>
<genre>Talent</genre>
</genres>
<network country="US">H2 TV</network>
<airtime>22:00</airtime>
<airday>Wednesday</airday>
</show>
<show>
<showid>28150</showid>
<name>Top Chef Canada</name>
<link>http://www.tvrage.com/shows/id-28150</link>
<country>CA</country>
<started>Apr/11/2011</started>
<ended></ended>
<seasons>2</seasons>
<status>New Series</status>
<runtime>60</runtime>
<classification>Reality</classification>
<genres>
<genre>Cooking/Food</genre>
<genre>Family</genre>
<genre>Talent</genre>
</genres>
<network country="CA">Food Network Canada</network>
<airtime>21:00</airtime>
<airday>Monday</airday>
</show>
<show>
<showid>6386</showid>
<name>Top of the Pops Saturday</name>
<link>http://www.tvrage.com/shows/id-6386</link>
<country>UK</country>
<started>Sep/20/2003</started>
<ended>Mar/26/2005</ended>
<seasons>2</seasons>
<status>Canceled/Ended</status>
<runtime>60</runtime>
<classification>Variety</classification>
<genres>
<genre>Children</genre>
</genres>
<network country="UK">BBC One</network>
<airtime>23:00</airtime>
<airday>Saturday</airday>
</show>
<show>
<showid>29633</showid>
<name>Top Secret Recipe</name>
<link>http://www.tvrage.com/shows/id-29633</link>
<country>US</country>
<started>Oct/07/2011</started>
<ended></ended>
<seasons>1</seasons>
<status>New Series</status>
<runtime>60</runtime>
<classification>Reality</classification>
<genres>
<genre>Cooking/Food</genre>
<genre>How To/Do It Yourself</genre>
</genres>
<network country="US">CMT</network>
<airtime>21:00</airtime>
<airday>Thursday</airday>
</show>
<show>
<showid>26650</showid>
<name>The Top 100: NFL's Greatest Players</name>
<link>http://www.tvrage.com/shows/id-26650</link>
<country>US</country>
<started>Sep/03/2010</started>
<ended>Nov/04/2010</ended>
<seasons>1</seasons>
<status>New Series</status>
<runtime>60</runtime>
<classification>Sports</classification>
<genres>
<genre>Sports</genre>
</genres>
<network country="US">NFL Network</network>
<airtime>21:00</airtime>
<airday>Thursday</airday>
</show>
<show>
<showid>7047</showid>
<name>Top of the Pops Reloaded</name>
<link>http://www.tvrage.com/shows/id-7047</link>
<country>UK</country>
<started>Sep/2005</started>
<ended>Mar/2006</ended>
<seasons>2</seasons>
<status>Canceled/Ended</status>
<runtime>45</runtime>
<classification>Variety</classification>
<genres>
<genre>Children</genre>
<genre>Music</genre>
<genre>Sketch/Improv</genre>
</genres>
<network country="UK">CBBC</network>
<airtime>11:00</airtime>
<airday>Saturday</airday>
</show>
<show>
<showid>19475</showid>
<name>Top Model Ghana</name>
<link>http://www.tvrage.com/shows/id-19475</link>
<country>GH</country>
<started>Aug/26/2006</started>
<ended>Oct/16/2006</ended>
<seasons>1</seasons>
<status>Canceled/Ended</status>
<runtime>60</runtime>
<classification>Reality</classification>
<genres>
<genre>Celebrities</genre>
<genre>Family</genre>
<genre>Fashion/Make-up</genre>
<genre>Talent</genre>
<genre>Travel</genre>
</genres>
<network country="GH">GTV</network>
<airtime>21:00</airtime>
<airday>Monday</airday>
<akas>
<aka attr="Alternate title" country="US">Ghana's Next Top Model</aka>
<aka attr="Abbreviated title" country="GH">TMG</aka>
<aka attr="1st Season title" country="GH">Top Model Ghana, Cycle</aka>
</akas>
</show>
<show>
<showid>31823</showid>
<name>Top 100 Video Games of All Time</name>
<link>http://www.tvrage.com/shows/id-31823</link>
<country>US</country>
<started>Jun/11/2012</started>
<ended></ended>
<seasons>1</seasons>
<status>New Series</status>
<runtime>60</runtime>
<classification>Mini-Series</classification>
<genres>
<genre>Family</genre>
<genre>Teens</genre>
</genres>
<network country="US">G4</network>
<airtime>20:00</airtime>
<airday>Weekdays</airday>
</show>
<show>
<showid>25003</showid>
<name>Cantore Stories: On Top of the World</name>
<link>http://www.tvrage.com/Cantore_Stories-On_Top_of_the_World</link>
<country>US</country>
<started>Jan/24/2010</started>
<ended></ended>
<seasons>1</seasons>
<status>New Series</status>
<runtime>60</runtime>
<classification>Reality</classification>
<genres>
<genre>Adventure</genre>
<genre>Educational</genre>
<genre>Family</genre>
<genre>Travel</genre>
</genres>
<network country="US">The Weather Channel</network>
<airtime>22:00</airtime>
<airday>Sunday</airday>
<akas>
<aka attr="Short title" country="US">Cantore Stories</aka>
</akas>
</show>
</Results>

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Results>
<show>
<showid>27518</showid>
<name>Suits</name>
<link>http://www.tvrage.com/Suits</link>
<country>US</country>
<started>Jun/23/2011</started>
<ended></ended>
<seasons>2</seasons>
<status>Returning Series</status>
<runtime>60</runtime>
<classification>Scripted</classification>
<genres>
<genre>Drama</genre>
<genre>Financial/Business</genre>
</genres>
<network country="US">USA</network>
<airtime>22:00</airtime>
<airday>Thursday</airday>
<akas>
<aka attr="Working title" country="US">A Legal Mind</aka>
</akas>
</show>
</Results>

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Showinfo></Showinfo>

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Showinfo>
<showid>29999</showid>
<showname>Anger Management</showname>
<showlink>http://tvrage.com/shows/id-29999</showlink>
<seasons>2</seasons>
<started>2012</started>
<startdate>Jun/28/2012</startdate>
<ended></ended>
<origin_country>US</origin_country>
<status>Returning Series</status>
<classification>Scripted</classification>
<genres>
<genre>Comedy</genre>
</genres>
<runtime>30</runtime>
<network country="US">FX</network>
<airtime>21:30</airtime>
<airday>Thursday</airday>
<timezone>GMT-5 -DST</timezone>
</Showinfo>

@ -5,19 +5,17 @@ using NUnit.Framework;
using NzbDrone.Core.MetadataSource; using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ProviderTests namespace NzbDrone.Core.Test.MetadataSourceTests
{ {
[TestFixture] [TestFixture]
public class TraktProxyFixture : CoreTest<TraktProxy>
public class TvDbProxyFixture : CoreTest<TvDbProxy>
{ {
[TestCase("The Simpsons")] [TestCase("The Simpsons")]
[TestCase("Family Guy")]
[TestCase("South Park")] [TestCase("South Park")]
[TestCase("Franklin & Bash")] [TestCase("Franklin & Bash")]
public void successful_search(string title) public void successful_search(string title)
{ {
var result = Subject.SearchSeries(title); var result = Subject.SearchForNewSeries(title);
result.Should().NotBeEmpty(); result.Should().NotBeEmpty();
result[0].Title.Should().Be(title); result[0].Title.Should().Be(title);
@ -27,14 +25,23 @@ namespace NzbDrone.Core.Test.ProviderTests
[Test] [Test]
public void no_search_result() public void no_search_result()
{ {
var result = Subject.SearchSeries(Guid.NewGuid().ToString()); var result = Subject.SearchForNewSeries(Guid.NewGuid().ToString());
result.Should().BeEmpty(); result.Should().BeEmpty();
} }
[Test]
public void should_be_able_to_get_series_detail()
{
var details = Subject.GetSeriesInfo(75978);
details.Should().NotBeNull();
details.Images.Should().NotBeEmpty();
}
[Test] [Test]
public void none_unique_season_episode_number() public void none_unique_season_episode_number()
{ {
var result = Subject.GetEpisodes(75978);//Family guy var result = Subject.GetEpisodeInfo(75978);//Family guy
result.GroupBy(e => e.SeasonNumber.ToString("000") + e.EpisodeNumber.ToString("000")) result.GroupBy(e => e.SeasonNumber.ToString("000") + e.EpisodeNumber.ToString("000"))
.Max(e => e.Count()).Should().Be(1); .Max(e => e.Count()).Should().Be(1);
@ -42,20 +49,13 @@ namespace NzbDrone.Core.Test.ProviderTests
result.Select(c => c.TvDbEpisodeId).Should().OnlyHaveUniqueItems(); result.Select(c => c.TvDbEpisodeId).Should().OnlyHaveUniqueItems();
} }
[Test]
public void should_be_able_to_get_series_detail()
{
var details = Subject.GetSeries(75978);
details.Should().NotBeNull();
details.Covers.Value.Should().NotBeEmpty();
}
[Test] [Test]
public void should_be_able_to_get_list_of_episodes() public void should_be_able_to_get_list_of_episodes()
{ {
var details = Subject.GetEpisodes(75978); var details = Subject.GetEpisodeInfo(75978);
details.Should().NotBeEmpty(); details.Should().NotBeEmpty();
} }
} }
} }

@ -155,16 +155,12 @@
<Compile Include="MediaFileTests\GhostFileCleanupFixture.cs" /> <Compile Include="MediaFileTests\GhostFileCleanupFixture.cs" />
<Compile Include="MediaFileTests\MediaFileRepositoryFixture.cs" /> <Compile Include="MediaFileTests\MediaFileRepositoryFixture.cs" />
<Compile Include="MediaFileTests\EpisodeFileMoverFixture.cs" /> <Compile Include="MediaFileTests\EpisodeFileMoverFixture.cs" />
<Compile Include="MetadataSourceTests\TracktProxyFixture.cs" />
<Compile Include="ProviderTests\DownloadClientTests\NzbgetProviderTests\DownloadNzbFixture.cs" /> <Compile Include="ProviderTests\DownloadClientTests\NzbgetProviderTests\DownloadNzbFixture.cs" />
<Compile Include="ProviderTests\DownloadClientTests\NzbgetProviderTests\QueueFixture.cs" /> <Compile Include="ProviderTests\DownloadClientTests\NzbgetProviderTests\QueueFixture.cs" />
<Compile Include="ProviderTests\DownloadProviderTests\ContainsRecentEpisode.cs" /> <Compile Include="ProviderTests\DownloadProviderTests\ContainsRecentEpisode.cs" />
<Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" /> <Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" />
<Compile Include="ProviderTests\TvRageMappingProviderTests\FindMatchingTvRageSeriesFixture.cs" />
<Compile Include="ProviderTests\TvRageMappingProviderTests\ProcessResultsFixture.cs" />
<Compile Include="ProviderTests\TvRageProviderTests\GetSeriesFixture.cs" />
<Compile Include="HelperTests\XElementHelperTests\ConvertToDayOfWeekFixture.cs" /> <Compile Include="HelperTests\XElementHelperTests\ConvertToDayOfWeekFixture.cs" />
<Compile Include="ProviderTests\TvRageProviderTests\GetUtcOffsetFixture.cs" />
<Compile Include="ProviderTests\TvRageProviderTests\SearchSeriesFixture.cs" />
<Compile Include="Qualities\QualityFixture.cs" /> <Compile Include="Qualities\QualityFixture.cs" />
<Compile Include="EpisodeParseResultTest.cs" /> <Compile Include="EpisodeParseResultTest.cs" />
<Compile Include="JobTests\BacklogSearchJobTest.cs" /> <Compile Include="JobTests\BacklogSearchJobTest.cs" />
@ -245,7 +241,6 @@
<Compile Include="ProviderTests\DownloadClientTests\SabProviderTests\SabProviderFixture.cs" /> <Compile Include="ProviderTests\DownloadClientTests\SabProviderTests\SabProviderFixture.cs" />
<Compile Include="ProviderTests\SceneMappingProviderTest.cs" /> <Compile Include="ProviderTests\SceneMappingProviderTest.cs" />
<Compile Include="TvTests\SeriesProviderTest.cs" /> <Compile Include="TvTests\SeriesProviderTest.cs" />
<Compile Include="ProviderTests\TvDbProxyFixture.cs" />
<Compile Include="XbmcVersionTests.cs" /> <Compile Include="XbmcVersionTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -355,21 +350,6 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<Content Include="Files\TvRage\SeriesInfo_empty.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\TvRage\SeriesInfo_one.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\TvRage\SearchResults_one.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\TvRage\SearchResults_many.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\TvRage\SearchResults_empty.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\Xem\Ids.txt"> <Content Include="Files\Xem\Ids.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>

@ -1,96 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.ReferenceData;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Model.TvRage;
using NzbDrone.Core.Providers;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ProviderTests.TvRageMappingProviderTests
{
public class FindMatchingTvRageSeriesFixture : TestBase
{
private IList<TvRageSearchResult> _searchResults;
private Series _series;
private Episode _episode;
private TvRageSeries _tvRageSeries;
[SetUp]
public void Setup()
{
_searchResults = Builder<TvRageSearchResult>
.CreateListOfSize(5)
.Build();
_series = Builder<Series>
.CreateNew()
.With(s => s.TvRageId = 0)
.With(s => s.TvRageTitle = null)
.With(s => s.UtcOffset = 0)
.With(s => s.FirstAired = DateTime.Today.AddDays(-180))
.Build();
_episode = Builder<Episode>
.CreateNew()
.With(e => e.AirDate = DateTime.Today.AddDays(-365))
.Build();
_tvRageSeries = Builder<TvRageSeries>
.CreateNew()
.With(s => s.UtcOffset = -8)
.Build();
Mocker.GetMock<IEpisodeService>()
.Setup(s => s.GetEpisode(_series.Id, 1, 1))
.Returns(_episode);
Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetCleanName(_series.Id))
.Returns("");
Mocker.GetMock<TvRageProxy>()
.Setup(s => s.SearchSeries(_series.Title))
.Returns(_searchResults);
Mocker.GetMock<TvRageProxy>()
.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<TvRageMappingProvider>()
.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<TvRageMappingProvider>()
.FindMatchingTvRageSeries(_series);
result.TvRageId.Should().Be(_searchResults.First().ShowId);
result.TvRageTitle.Should().Be(_searchResults.First().Name);
result.UtcOffset.Should().Be(_tvRageSeries.UtcOffset);
}
}
}

@ -1,92 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Model.TvRage;
using NzbDrone.Core.Providers;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ProviderTests.TvRageMappingProviderTests
{
public class ProcessResultsFixture : TestBase
{
private IList<TvRageSearchResult> _searchResults;
private Series _series;
private Episode _episode;
[SetUp]
public void Setup()
{
_searchResults = Builder<TvRageSearchResult>
.CreateListOfSize(5)
.Build();
_series = Builder<Series>
.CreateNew()
.With(s => s.FirstAired = DateTime.Today.AddDays(-180))
.Build();
_episode = Builder<Episode>
.CreateNew()
.With(e => e.AirDate = DateTime.Today.AddDays(-365))
.Build();
}
[Test]
public void should_return_null_if_no_match_is_found()
{
Mocker.Resolve<TvRageMappingProvider>()
.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<TvRageMappingProvider>()
.ProcessResults(_searchResults, _series, "nomatchhere", _episode)
.Should()
.Be(_searchResults.First());
}
[Test]
public void should_return_result_if_scene_clean_name_matches()
{
Mocker.Resolve<TvRageMappingProvider>()
.ProcessResults(_searchResults, _series, Parser.NormalizeTitle(_searchResults.First().Name), _episode)
.Should()
.Be(_searchResults.First());
}
[Test]
public void should_return_result_if_series_firstAired_matches()
{
_series.FirstAired = _searchResults.Last().Started;
Mocker.Resolve<TvRageMappingProvider>()
.ProcessResults(_searchResults, _series, "nomatchhere", _episode)
.Should()
.Be(_searchResults.Last());
}
[Test]
public void should_return_result_if_episode_firstAired_matches()
{
_episode.AirDate = _searchResults.Last().Started;
Mocker.Resolve<TvRageMappingProvider>()
.ProcessResults(_searchResults, _series, "nomatchhere", _episode)
.Should()
.Be(_searchResults.Last());
}
}
}

@ -1,56 +0,0 @@

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ProviderTests.TvRageProviderTests
{
[TestFixture]
public class GetSeriesFixture : CoreTest
{
private const string showinfo = "http://services.tvrage.com/feeds/showinfo.php?key=NW4v0PSmQIoVmpbASLdD&sid=";
private void WithEmptyResults()
{
Mocker.GetMock<HttpProvider>()
.Setup(s => s.DownloadStream(It.Is<String>(u => u.StartsWith(showinfo)), null))
.Returns(OpenRead("Files", "TVRage", "SeriesInfo_empty.xml"));
}
private void WithOneResult()
{
Mocker.GetMock<HttpProvider>()
.Setup(s => s.DownloadStream(It.Is<String>(u => u.StartsWith(showinfo)), null))
.Returns(OpenRead("Files", "TVRage", "SeriesInfo_one.xml"));
}
[Test]
public void should_be_null_when_no_showinfo_is_returned()
{
WithEmptyResults();
Mocker.Resolve<TvRageProxy>().GetSeries(100).Should().BeNull();
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_return_series_when_showinfo_is_valid()
{
WithOneResult();
var result = Mocker.Resolve<TvRageProxy>().GetSeries(29999);
result.ShowId.Should().Be(29999);
result.Name.Should().Be("Anger Management");
}
}
}

@ -1,48 +0,0 @@

using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ProviderTests.TvRageProviderTests
{
[TestFixture]
public class GetUtcOffsetFixture : CoreTest
{
[Test]
public void should_return_zero_if_timeZone_is_empty()
{
Mocker.Resolve<TvRageProxy>().GetUtcOffset("").Should().Be(0);
}
[Test]
public void should_return_zero_if_cannot_be_coverted_to_int()
{
Mocker.Resolve<TvRageProxy>().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<TvRageProxy>().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<TvRageProxy>().GetUtcOffset(timezone).Should().Be(expected);
}
}
}

@ -1,80 +0,0 @@

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ProviderTests.TvRageProviderTests
{
[TestFixture]
public class SearchSeriesFixture : CoreTest
{
private const string search = "http://services.tvrage.com/feeds/full_search.php?show=";
private void WithEmptyResults()
{
Mocker.GetMock<HttpProvider>()
.Setup(s => s.DownloadStream(It.Is<String>(u => u.StartsWith(search)), null))
.Returns(OpenRead("Files", "TVRage", "SearchResults_empty.xml"));
}
private void WithManyResults()
{
Mocker.GetMock<HttpProvider>()
.Setup(s => s.DownloadStream(It.Is<String>(u => u.StartsWith(search)), null))
.Returns(OpenRead("Files", "TVRage", "SearchResults_many.xml"));
}
private void WithOneResult()
{
Mocker.GetMock<HttpProvider>()
.Setup(s => s.DownloadStream(It.Is<String>(u => u.StartsWith(search)), null))
.Returns(OpenRead("Files", "TVRage", "earchResults_one.xml"));
}
[Test]
public void should_be_empty_when_no_results_are_found()
{
WithEmptyResults();
Mocker.Resolve<TvRageProxy>().SearchSeries("asdasdasdasdas").Should().BeEmpty();
}
[Test]
public void should_be_have_more_than_one_when_multiple_results_are_returned()
{
WithManyResults();
Mocker.Resolve<TvRageProxy>().SearchSeries("top+gear").Should().NotBeEmpty();
}
[Test]
public void should_have_one_when_only_one_result_is_found()
{
WithOneResult();
Mocker.Resolve<TvRageProxy>().SearchSeries("suits").Should().HaveCount(1);
}
[Test]
public void ended_should_not_have_a_value_when_series_has_not_ended()
{
WithOneResult();
Mocker.Resolve<TvRageProxy>().SearchSeries("suits").First().Ended.HasValue.Should().BeFalse();
}
[Test]
public void started_should_match_series()
{
WithOneResult();
Mocker.Resolve<TvRageProxy>().SearchSeries("suits").First().Started.Should().Be(new DateTime(2011, 6, 23));
}
}
}

@ -5,6 +5,7 @@ using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using Marr.Data; using Marr.Data;
using Marr.Data.QGen; using Marr.Data.QGen;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Datastore namespace NzbDrone.Core.Datastore

@ -122,6 +122,7 @@ namespace NzbDrone.Core.Datastore.Migration
.WithColumn("Status").AsInt32().NotNullable() .WithColumn("Status").AsInt32().NotNullable()
.WithColumn("Overview").AsString().Nullable() .WithColumn("Overview").AsString().Nullable()
.WithColumn("AirTime").AsString().Nullable() .WithColumn("AirTime").AsString().Nullable()
.WithColumn("Images").AsString()
.WithColumn("Language").AsString().NotNullable() .WithColumn("Language").AsString().NotNullable()
.WithColumn("Path").AsString().NotNullable() .WithColumn("Path").AsString().NotNullable()
.WithColumn("Monitored").AsBoolean().NotNullable() .WithColumn("Monitored").AsBoolean().NotNullable()

@ -39,17 +39,13 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings"); Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings");
Mapper.Entity<History.History>().RegisterModel("History") Mapper.Entity<History.History>().RegisterModel("History")
.HasOne<History.History, Episode>(h => h.Episode, h => h.EpisodeId); .HasOne(h => h.Episode, h => h.EpisodeId);
Mapper.Entity<Series>().RegisterModel("Series") Mapper.Entity<Series>().RegisterModel("Series");
.Relationships.AutoMapComplexTypeProperties<ILazyLoaded>()
.For(c => c.Covers)
.LazyLoad((db, series) => db.Query<MediaCover.MediaCover>().Where(cover => cover.SeriesId == series.Id).ToList());
Mapper.Entity<Season>().RegisterModel("Seasons"); Mapper.Entity<Season>().RegisterModel("Seasons");
Mapper.Entity<Episode>().RegisterModel("Episodes"); Mapper.Entity<Episode>().RegisterModel("Episodes");
Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles"); Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles");
Mapper.Entity<MediaCover.MediaCover>().RegisterModel("MediaCovers");
Mapper.Entity<QualityProfile>().RegisterModel("QualityProfiles").For(q => q.DbAllowed).SetColumnName("Allowed").Ignore(q => q.Allowed); Mapper.Entity<QualityProfile>().RegisterModel("QualityProfiles").For(q => q.DbAllowed).SetColumnName("Allowed").Ignore(q => q.Allowed);
Mapper.Entity<QualitySize>().RegisterModel("QualitySizes"); Mapper.Entity<QualitySize>().RegisterModel("QualitySizes");
@ -63,6 +59,7 @@ namespace NzbDrone.Core.Datastore
MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(QualityModel), new EmbeddedDocumentConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(QualityModel), new EmbeddedDocumentConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(MediaCover.MediaCover), new EmbeddedDocumentConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(Quality), new QualityIntConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(Quality), new QualityIntConverter());
} }
} }

@ -1,4 +1,3 @@
using System.Linq;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.MediaCover namespace NzbDrone.Core.MediaCover
@ -11,10 +10,9 @@ namespace NzbDrone.Core.MediaCover
Fanart = 2 Fanart = 2
} }
public class MediaCover : ModelBase public class MediaCover : IEmbeddedDocument
{ {
public MediaCoverTypes CoverType { get; set; } public MediaCoverTypes CoverType { get; set; }
public string Url { get; set; } public string Url { get; set; }
public int SeriesId { get; set; }
} }
} }

@ -37,7 +37,7 @@ namespace NzbDrone.Core.MediaCover
private void EnsureCovers(Series series) private void EnsureCovers(Series series)
{ {
foreach (var cover in series.Covers.Value) foreach (var cover in series.Images)
{ {
var fileName = GetCoverPath(series.Id, cover.CoverType); var fileName = GetCoverPath(series.Id, cover.CoverType);
if (!_diskProvider.FileExists(fileName)) if (!_diskProvider.FileExists(fileName))

@ -0,0 +1,10 @@
using System.Collections.Generic;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.MetadataSource
{
public interface IProvideEpisodeInfo
{
IList<Episode> GetEpisodeInfo(int tvDbSeriesId);
}
}

@ -0,0 +1,9 @@
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.MetadataSource
{
public interface IProvideSeriesInfo
{
Series GetSeriesInfo(int tvDbSeriesId);
}
}

@ -0,0 +1,10 @@
using System.Collections.Generic;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.MetadataSource
{
public interface ISearchForNewSeries
{
List<Series> SearchForNewSeries(string title);
}
}

@ -0,0 +1,8 @@
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class Actor
{
public string name { get; set; }
public string character { get; set; }
}
}

@ -0,0 +1,18 @@
using System;
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class Episode
{
public int season { get; set; }
public int episode { get; set; }
public int number { get; set; }
public int tvdb_id { get; set; }
public string title { get; set; }
public string overview { get; set; }
public DateTime? first_aired { get; set; }
public string url { get; set; }
public string screen { get; set; }
public Ratings ratings { get; set; }
}
}

@ -0,0 +1,9 @@
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class Images
{
public string poster { get; set; }
public string fanart { get; set; }
public string banner { get; set; }
}
}

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class People
{
public List<Actor> actors { get; set; }
}
}

@ -0,0 +1,10 @@
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class Ratings
{
public int percentage { get; set; }
public int votes { get; set; }
public int loved { get; set; }
public int hated { get; set; }
}
}

@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class Season
{
public int season { get; set; }
public List<Episode> episodes { get; set; }
public string url { get; set; }
public string poster { get; set; }
}
}

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class Show
{
public string title { get; set; }
public int year { get; set; }
public string url { get; set; }
public DateTime? first_aired { get; set; }
public string country { get; set; }
public string overview { get; set; }
public int runtime { get; set; }
public string status { get; set; }
public string network { get; set; }
public string air_day { get; set; }
public string air_time { get; set; }
public string certification { get; set; }
public string imdb_id { get; set; }
public int tvdb_id { get; set; }
public int tvrage_id { get; set; }
public int last_updated { get; set; }
public string poster { get; set; }
public Images images { get; set; }
public List<TopWatcher> top_watchers { get; set; }
public List<TopEpisode> top_episodes { get; set; }
public Ratings ratings { get; set; }
public Stats stats { get; set; }
public People people { get; set; }
public List<string> genres { get; set; }
public List<Season> seasons { get; set; }
}
}

@ -0,0 +1,14 @@
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class Stats
{
public int watchers { get; set; }
public int plays { get; set; }
public int scrobbles { get; set; }
public int scrobbles_unique { get; set; }
public int checkins { get; set; }
public int checkins_unique { get; set; }
public int collection { get; set; }
public int collection_unique { get; set; }
}
}

@ -0,0 +1,12 @@
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class TopEpisode
{
public int plays { get; set; }
public int season { get; set; }
public int number { get; set; }
public string title { get; set; }
public string url { get; set; }
public int first_aired { get; set; }
}
}

@ -0,0 +1,17 @@
namespace NzbDrone.Core.MetadataSource.Trakt
{
public class TopWatcher
{
public int plays { get; set; }
public string username { get; set; }
public bool @protected { get; set; }
public object full_name { get; set; }
public object gender { get; set; }
public string age { get; set; }
public object location { get; set; }
public object about { get; set; }
public int joined { get; set; }
public string avatar { get; set; }
public string url { get; set; }
}
}

@ -0,0 +1,82 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MetadataSource.Trakt;
using NzbDrone.Core.Tv;
using RestSharp;
using NzbDrone.Common.EnsureThat;
using Episode = NzbDrone.Core.Tv.Episode;
namespace NzbDrone.Core.MetadataSource
{
public class TraktProxy : ISearchForNewSeries, IProvideSeriesInfo, IProvideEpisodeInfo
{
public List<Series> SearchForNewSeries(string title)
{
var client = BuildClient("search", "shows");
var restRequest = new RestRequest(title.ToSlug().Replace("-", "+"));
var response = client.Execute<List<Show>>(restRequest);
return response.Data.Select(MapSeries).ToList();
}
public Series GetSeriesInfo(int tvDbSeriesId)
{
var client = BuildClient("show", "summary");
var restRequest = new RestRequest(tvDbSeriesId.ToString());
var response = client.Execute<Show>(restRequest);
return MapSeries(response.Data);
}
public IList<Episode> GetEpisodeInfo(int tvDbSeriesId)
{
var client = BuildClient("show", "summary");
var restRequest = new RestRequest(tvDbSeriesId.ToString() + "/extended");
var response = client.Execute<Show>(restRequest);
return response.Data.seasons.SelectMany(c => c.episodes).Select(MapEpisode).ToList();
}
private static IRestClient BuildClient(string resource, string method)
{
return new RestClient(string.Format("http://api.trakt.tv/{0}/{1}.json/6fc98f83c6a02decd17eb7e13d00e89c", resource, method));
}
private static Series MapSeries(Show show)
{
var series = new Series();
series.TvDbId = show.tvdb_id;
series.TvRageId = show.tvrage_id;
series.Title = show.title;
series.FirstAired = show.first_aired;
series.Overview = show.overview;
series.Runtime = show.runtime;
series.Network = show.network;
series.AirTime = show.air_time;
series.Images.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner, Url = show.images.banner });
series.Images.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Poster, Url = show.images.poster });
series.Images.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Fanart, Url = show.images.fanart });
return series;
}
private static Episode MapEpisode(Trakt.Episode traktEpisode)
{
var episode = new Episode();
episode.Overview = traktEpisode.overview;
episode.SeasonNumber = traktEpisode.season;
episode.EpisodeNumber = traktEpisode.episode;
episode.EpisodeNumber = traktEpisode.number;
episode.TvDbEpisodeId = traktEpisode.tvdb_id;
episode.Title = traktEpisode.title;
episode.AirDate = traktEpisode.first_aired;
return episode;
}
}
}

@ -1,160 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.Tv;
using NzbDrone.Common;
namespace NzbDrone.Core.MetadataSource
{
public class TvDbProxy
{
public const string TVDB_APIKEY = "5D2D188E86E07F4F";
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private readonly Tvdb.Tvdb _handlerV2;
public TvDbProxy()
{
_handlerV2 = new Tvdb.Tvdb(TVDB_APIKEY);
}
public virtual List<Series> SearchSeries(string title)
{
logger.Debug("Searching TVDB for '{0}'", title);
if (title.Contains(" & "))
{
title = title.Replace(" & ", " ");
}
var searchResult = _handlerV2.SearchSeries(title).Select(tvdbSeriesSearchItem => new Series
{
TvDbId = tvdbSeriesSearchItem.seriesid,
Title = tvdbSeriesSearchItem.SeriesName,
FirstAired = tvdbSeriesSearchItem.FirstAired,
Overview = tvdbSeriesSearchItem.Overview
}).ToList();
logger.Debug("Search for '{0}' returned {1} possible results", title, searchResult.Count);
return searchResult;
}
public virtual Series GetSeries(int tvDbSeriesId)
{
var tvDbSeries = _handlerV2.GetSeriesBaseRecord("http://thetvdb.com", tvDbSeriesId);
var series = new Series();
series.Title = tvDbSeries.SeriesName;
series.AirTime = CleanAirsTime(tvDbSeries.Airs_Time);
series.Overview = tvDbSeries.Overview;
series.Status = tvDbSeries.Status == "Continuing" ? SeriesStatusType.Continuing : SeriesStatusType.Ended;
series.Language = tvDbSeries.Language ?? string.Empty;
series.CleanTitle = Parser.NormalizeTitle(tvDbSeries.SeriesName);
series.LastInfoSync = DateTime.Now;
if (tvDbSeries.Runtime.HasValue)
{
series.Runtime = Convert.ToInt32(tvDbSeries.Runtime);
}
if (!string.IsNullOrWhiteSpace(tvDbSeries.banner))
{
series.Covers.Value.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner, Url = tvDbSeries.banner, SeriesId = series.Id });
}
if (!string.IsNullOrWhiteSpace(tvDbSeries.fanart))
{
series.Covers.Value.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Fanart, Url = tvDbSeries.fanart, SeriesId = series.Id });
}
if (!string.IsNullOrWhiteSpace(tvDbSeries.poster))
{
series.Covers.Value.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Poster, Url = tvDbSeries.poster, SeriesId = series.Id });
}
series.Network = tvDbSeries.Network;
if (tvDbSeries.FirstAired.HasValue && tvDbSeries.FirstAired.Value.Year > 1900)
{
series.FirstAired = tvDbSeries.FirstAired.Value.Date;
}
else
{
series.FirstAired = null;
}
return series;
}
public virtual IList<Episode> GetEpisodes(int tvDbSeriesId)
{
var seriesRecord = _handlerV2.GetSeriesFullRecord("http://thetvdb.com", tvDbSeriesId);
var tvdbEpisodes = seriesRecord.Episodes.OrderByDescending(e => e.FirstAired).ThenByDescending(e => e.EpisodeName)
.GroupBy(e => e.seriesid.ToString("000000") + e.SeasonNumber.ToString("000") + e.EpisodeNumber.ToString("000"))
.Select(e => e.First());
var episodes = new List<Episode>();
foreach (var tvDbEpisode in tvdbEpisodes)
{
var episode = new Episode();
episode.TvDbEpisodeId = tvDbEpisode.id;
episode.EpisodeNumber = tvDbEpisode.EpisodeNumber;
episode.SeasonNumber = tvDbEpisode.SeasonNumber;
episode.AbsoluteEpisodeNumber = tvDbEpisode.absolute_number.ParseInt32();
episode.Title = tvDbEpisode.EpisodeName;
episode.Overview = tvDbEpisode.Overview;
if (tvDbEpisode.FirstAired.Year > 1900)
{
episode.AirDate = tvDbEpisode.FirstAired.Date;
}
else
{
episode.AirDate = null;
}
episodes.Add(episode);
}
return episodes;
}
/// <summary>
/// Cleans up the AirsTime Component from TheTVDB since it can be garbage that comes in.
/// </summary>
/// <param name = "rawTime">The TVDB AirsTime</param>
/// <returns>String that contains the AirTimes</returns>
private static readonly Regex timeRegex = new Regex(@"^(?<time>\d+:?\d*)\W*(?<meridiem>am|pm)?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static string CleanAirsTime(string rawTime)
{
var match = timeRegex.Match(rawTime);
var time = match.Groups["time"].Value;
var meridiem = match.Groups["meridiem"].Value;
//Lets assume that a string that doesn't contain a Merideim is aired at night... So we'll add it
if (String.IsNullOrEmpty(meridiem))
meridiem = "PM";
DateTime dateTime;
if (String.IsNullOrEmpty(time) || !DateTime.TryParse(time + " " + meridiem.ToUpper(), out dateTime))
return String.Empty;
return dateTime.ToString("hh:mm tt");
}
}
}

@ -1,71 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Providers;
using NzbDrone.Core.ReferenceData;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Model.TvRage;
namespace NzbDrone.Core.MetadataSource
{
public class TvRageMappingProvider
{
private readonly ISceneMappingService _sceneMappingService;
private readonly TvRageProxy _tvRageProxy;
private readonly IEpisodeService _episodeService;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public TvRageMappingProvider(ISceneMappingService sceneMappingService,
TvRageProxy tvRageProxy, IEpisodeService episodeService)
{
_sceneMappingService = sceneMappingService;
_tvRageProxy = tvRageProxy;
_episodeService = episodeService;
}
public TvRageMappingProvider()
{
}
public Series FindMatchingTvRageSeries(Series series)
{
var firstEpisode = _episodeService.GetEpisode(series.Id, 1, 1);
var cleanName = _sceneMappingService.GetCleanName(series.Id);
var results = _tvRageProxy.SearchSeries(series.Title);
var result = ProcessResults(results, series, cleanName, firstEpisode);
if (result != null)
{
logger.Trace("TV Rage: {0} matches TVDB: {1}", result.Name, series.Title);
series.TvRageId = result.ShowId;
series.TvRageTitle = result.Name;
series.UtcOffset = _tvRageProxy.GetSeries(result.ShowId).UtcOffset;
}
return series;
}
public TvRageSearchResult ProcessResults(IList<TvRageSearchResult> searchResults, Series series, string sceneCleanName, Episode firstEpisode)
{
foreach (var result in searchResults)
{
if (Parser.NormalizeTitle(result.Name).Equals(series.CleanTitle))
return result;
if (!String.IsNullOrWhiteSpace(sceneCleanName) && Parser.NormalizeTitle(result.Name).Equals(sceneCleanName))
return result;
if (series.FirstAired.HasValue && result.Started == series.FirstAired.Value)
return result;
if (firstEpisode != null && firstEpisode.AirDate.HasValue && result.Started == firstEpisode.AirDate.Value)
return result;
}
return null;
}
}
}

@ -1,166 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model.TvRage;
namespace NzbDrone.Core.MetadataSource
{
public class TvRageProxy
{
private readonly HttpProvider _httpProvider;
private const string TVRAGE_APIKEY = "NW4v0PSmQIoVmpbASLdD";
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public TvRageProxy(HttpProvider httpProvider)
{
_httpProvider = httpProvider;
}
public TvRageProxy()
{
}
public virtual IList<TvRageSearchResult> SearchSeries(string title)
{
var searchResults = new List<TvRageSearchResult>();
var xmlStream = _httpProvider.DownloadStream("http://services.tvrage.com/feeds/full_search.php?show=" + title, null);
var xml = XDocument.Load(xmlStream);
var shows = xml.Descendants("Results").Descendants("show");
foreach (var s in shows)
{
try
{
var show = new TvRageSearchResult();
show.ShowId = s.Element("showid").ConvertTo<Int32>();
show.Name = s.Element("name").Value;
show.Link = s.Element("link").Value;
show.Country = s.Element("country").Value;
show.Started = s.Element("started").ConvertTo<DateTime>();
show.Ended = s.Element("ended").ConvertTo<DateTime>();
if (show.Ended < new DateTime(1900, 1, 1))
show.Ended = null;
show.Seasons = s.Element("seasons").ConvertTo<Int32>();
show.Status = s.Element("status").Value;
show.RunTime = s.Element("seasons").ConvertTo<Int32>();
show.AirTime = s.Element("airtime").ConvertTo<DateTime>();
show.AirDay = s.Element("airday").ConvertToDayOfWeek();
searchResults.Add(show);
}
catch (Exception ex)
{
logger.DebugException("Failed to parse TvRage Search Result. Search Term : " + title, ex);
}
}
return searchResults;
}
public virtual TvRageSeries GetSeries(int id)
{
var url = string.Format("http://services.tvrage.com/feeds/showinfo.php?key={0}&sid={1}", TVRAGE_APIKEY, id);
var xmlStream = _httpProvider.DownloadStream(url, null);
var xml = XDocument.Load(xmlStream);
var s = xml.Descendants("Showinfo").First();
try
{
if(s.Element("showid") == null)
{
logger.Warn("TvRage did not return valid series info for id: {0}", id);
return null;
}
var show = new TvRageSeries();
show.ShowId = s.Element("showid").ConvertTo<Int32>();
show.Name = s.Element("showname").Value;
show.Link = s.Element("showlink").Value;
show.Seasons = s.Element("seasons").ConvertTo<Int32>();
show.Started = s.Element("started").ConvertTo<Int32>();
show.StartDate = s.Element("startdate").ConvertTo<DateTime>();
show.Ended = s.Element("ended").ConvertTo<DateTime>();
show.OriginCountry = s.Element("origin_country").Value;
show.Status = s.Element("status").Value;
show.RunTime = s.Element("runtime").ConvertTo<Int32>();
show.Network = s.Element("network").Value;
show.AirTime = s.Element("airtime").ConvertTo<DateTime>();
show.AirDay = s.Element("airday").ConvertToDayOfWeek();
show.UtcOffset = GetUtcOffset(s.Element("timezone").Value);
return show;
}
catch (Exception ex)
{
logger.DebugException("Failed to parse ShowInfo for ID: " + id, ex);
return null;
}
}
public virtual List<TvRageEpisode> GetEpisodes(int id)
{
var url = String.Format("http://services.tvrage.com/feeds/episode_list.php?key={0}&sid={1}", TVRAGE_APIKEY, id);
var xmlStream = _httpProvider.DownloadStream(url, null);
var xml = XDocument.Load(xmlStream);
var show = xml.Descendants("Show");
var seasons = show.Descendants("Season");
var episodes = new List<TvRageEpisode>();
foreach (var season in seasons)
{
var eps = season.Descendants("episode");
foreach (var e in eps)
{
try
{
var episode = new TvRageEpisode();
episode.EpisodeNumber = e.Element("epnum").ConvertTo<Int32>();
episode.SeasonNumber = e.Element("seasonnum").ConvertTo<Int32>();
episode.ProductionCode = e.Element("prodnum").Value;
episode.AirDate = e.Element("airdate").ConvertTo<DateTime>();
episode.Link = e.Element("link").Value;
episode.Title = e.Element("title").Value;
episodes.Add(episode);
}
catch (Exception ex)
{
logger.DebugException("Failed to parse TV Rage episode", ex);
}
}
}
return episodes;
}
internal int GetUtcOffset(string timeZone)
{
if (String.IsNullOrWhiteSpace(timeZone))
return 0;
var offsetString = timeZone.Substring(3, 2);
int offset;
if (!Int32.TryParse(offsetString, out offset))
return 0;
if (timeZone.IndexOf("+DST", StringComparison.CurrentCultureIgnoreCase) > 0)
offset++;
return offset;
}
}
}

@ -1,17 +0,0 @@
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; }
}
}

@ -1,22 +0,0 @@
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; }
}
}

@ -1,25 +0,0 @@
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; }
}
}

@ -274,6 +274,20 @@
<Compile Include="MediaFiles\Events\EpisodeFileDeletedEvent.cs" /> <Compile Include="MediaFiles\Events\EpisodeFileDeletedEvent.cs" />
<Compile Include="MediaFiles\GhostFileCleanupService.cs" /> <Compile Include="MediaFiles\GhostFileCleanupService.cs" />
<Compile Include="MediaFiles\MediaFileRepository.cs" /> <Compile Include="MediaFiles\MediaFileRepository.cs" />
<Compile Include="MetadataSource\IProvideEpisodeInfo.cs" />
<Compile Include="MetadataSource\IProvideSeriesInfo.cs" />
<Compile Include="MetadataSource\ISearchForNewSeries.cs" />
<Compile Include="MetadataSource\TraktProxy.cs" />
<Compile Include="MetadataSource\Trakt\Actor.cs" />
<Compile Include="MetadataSource\Trakt\Episode.cs" />
<Compile Include="MetadataSource\Trakt\Images.cs" />
<Compile Include="MetadataSource\Trakt\People.cs" />
<Compile Include="MetadataSource\Trakt\Ratings.cs" />
<Compile Include="MetadataSource\Trakt\Season.cs" />
<Compile Include="MetadataSource\Trakt\Show.cs" />
<Compile Include="MetadataSource\Trakt\Stats.cs" />
<Compile Include="MetadataSource\Trakt\TopEpisode.cs" />
<Compile Include="MetadataSource\Trakt\TopWatcher.cs" />
<Compile Include="Organizer\EpisodeSortingType.cs" /> <Compile Include="Organizer\EpisodeSortingType.cs" />
<Compile Include="Organizer\FileNameBuilder.cs" /> <Compile Include="Organizer\FileNameBuilder.cs" />
<Compile Include="Model\DownloadClientType.cs" /> <Compile Include="Model\DownloadClientType.cs" />
@ -322,9 +336,6 @@
<Compile Include="Download\Clients\Sabnzbd\SabQueueItem.cs" /> <Compile Include="Download\Clients\Sabnzbd\SabQueueItem.cs" />
<Compile Include="Download\Clients\Sabnzbd\SabVersionModel.cs" /> <Compile Include="Download\Clients\Sabnzbd\SabVersionModel.cs" />
<Compile Include="Model\StatsModel.cs" /> <Compile Include="Model\StatsModel.cs" />
<Compile Include="Model\TvRage\TvRageEpisode.cs" />
<Compile Include="Model\TvRage\TvRageSearchResult.cs" />
<Compile Include="Model\TvRage\TvRageSeries.cs" />
<Compile Include="Model\Twitter\TwitterAuthorizationModel.cs" /> <Compile Include="Model\Twitter\TwitterAuthorizationModel.cs" />
<Compile Include="Model\UpdatePackage.cs" /> <Compile Include="Model\UpdatePackage.cs" />
<Compile Include="Model\Xbmc\ActionType.cs" /> <Compile Include="Model\Xbmc\ActionType.cs" />
@ -356,8 +367,6 @@
<Compile Include="Model\Xbmc\TvShowResponse.cs" /> <Compile Include="Model\Xbmc\TvShowResponse.cs" />
<Compile Include="Model\Xbmc\TvShow.cs" /> <Compile Include="Model\Xbmc\TvShow.cs" />
<Compile Include="Model\Xbmc\VersionResult.cs" /> <Compile Include="Model\Xbmc\VersionResult.cs" />
<Compile Include="MetadataSource\TvRageMappingProvider.cs" />
<Compile Include="MetadataSource\TvRageProxy.cs" />
<Compile Include="Providers\XemCommunicationProvider.cs" /> <Compile Include="Providers\XemCommunicationProvider.cs" />
<Compile Include="Providers\XemProvider.cs" /> <Compile Include="Providers\XemProvider.cs" />
<Compile Include="Qualities\Quality.cs" /> <Compile Include="Qualities\Quality.cs" />
@ -481,9 +490,6 @@
<Compile Include="Providers\SmtpProvider.cs"> <Compile Include="Providers\SmtpProvider.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="MetadataSource\TvDbProxy.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\TwitterProvider.cs"> <Compile Include="Providers\TwitterProvider.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
@ -519,21 +525,6 @@
<Compile Include="ReferenceData\SceneMapping.cs" /> <Compile Include="ReferenceData\SceneMapping.cs" />
<Compile Include="Tv\Series.cs" /> <Compile Include="Tv\Series.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tvdb\Tvdb.cs" />
<Compile Include="Tvdb\Tvdb.Sync.cs" />
<Compile Include="Tvdb\TvdbActor.cs" />
<Compile Include="Tvdb\TvdbAsyncResult.cs" />
<Compile Include="Tvdb\TvdbBanner.cs" />
<Compile Include="Tvdb\TvdbEpisodes.cs" />
<Compile Include="Tvdb\TvdbLanguages.cs" />
<Compile Include="Tvdb\TvdbMirrors.cs" />
<Compile Include="Tvdb\TvdbSeriesBase.cs" />
<Compile Include="Tvdb\TvdbSeriesFull.cs" />
<Compile Include="Tvdb\TvdbSeriesSearch.cs" />
<Compile Include="Tvdb\TvdbSeriesSearchItem.cs" />
<Compile Include="Tvdb\TvdbServerTime.cs" />
<Compile Include="Tvdb\TvdbUpdate.cs" />
<Compile Include="Tvdb\TvdbUpdateItems.cs" />
<Compile Include="Tv\SeriesStatusType.cs" /> <Compile Include="Tv\SeriesStatusType.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -46,16 +46,16 @@ namespace NzbDrone.Core.Tv
private static readonly Logger logger = LogManager.GetCurrentClassLogger(); private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private readonly TvDbProxy _tvDbProxy; private readonly IProvideEpisodeInfo _episodeInfoProxy;
private readonly ISeasonRepository _seasonRepository; private readonly ISeasonRepository _seasonRepository;
private readonly IEpisodeRepository _episodeRepository; private readonly IEpisodeRepository _episodeRepository;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly Logger _logger; private readonly Logger _logger;
public EpisodeService(TvDbProxy tvDbProxyProxy, ISeasonRepository seasonRepository, IEpisodeRepository episodeRepository, IEventAggregator eventAggregator, IConfigService configService, Logger logger) public EpisodeService(IProvideEpisodeInfo episodeInfoProxy, ISeasonRepository seasonRepository, IEpisodeRepository episodeRepository, IEventAggregator eventAggregator, IConfigService configService, Logger logger)
{ {
_tvDbProxy = tvDbProxyProxy; _episodeInfoProxy = episodeInfoProxy;
_seasonRepository = seasonRepository; _seasonRepository = seasonRepository;
_episodeRepository = episodeRepository; _episodeRepository = episodeRepository;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
@ -193,7 +193,7 @@ namespace NzbDrone.Core.Tv
var successCount = 0; var successCount = 0;
var failCount = 0; var failCount = 0;
var tvdbEpisodes = _tvDbProxy.GetEpisodes(series.TvDbId); var tvdbEpisodes = _episodeInfoProxy.GetEpisodeInfo(series.TvDbId);
var seriesEpisodes = GetEpisodeBySeries(series.Id); var seriesEpisodes = GetEpisodeBySeries(series.Id);
var updateList = new List<Episode>(); var updateList = new List<Episode>();

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.MetadataSource.Trakt;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
using NzbDrone.Core.Qualities; using NzbDrone.Core.Qualities;
@ -17,7 +19,7 @@ namespace NzbDrone.Core.Tv
{ {
public Series() public Series()
{ {
Covers = new LazyList<MediaCover.MediaCover>(); Images =new List<MediaCover.MediaCover>();
} }
public int TvDbId { get; set; } public int TvDbId { get; set; }
@ -34,7 +36,7 @@ namespace NzbDrone.Core.Tv
public DateTime? LastInfoSync { get; set; } public DateTime? LastInfoSync { get; set; }
public DateTime? LastDiskSync { get; set; } public DateTime? LastDiskSync { get; set; }
public int Runtime { get; set; } public int Runtime { get; set; }
public LazyList<MediaCover.MediaCover> Covers { get; set; } public List<MediaCover.MediaCover> Images { get; set; }
public SeriesTypes SeriesType { get; set; } public SeriesTypes SeriesType { get; set; }
public BacklogSettingType BacklogSetting { get; set; } public BacklogSettingType BacklogSetting { get; set; }
public string Network { get; set; } public string Network { get; set; }

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Linq; using System.Linq;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
@ -12,6 +11,7 @@ namespace NzbDrone.Core.Tv
Series GetByTitle(string cleanTitle); Series GetByTitle(string cleanTitle);
Series FindByTvdbId(int tvdbId); Series FindByTvdbId(int tvdbId);
void SetSeriesType(int seriesId, SeriesTypes seriesTypes); void SetSeriesType(int seriesId, SeriesTypes seriesTypes);
void SetTvRageId(int seriesId, int tvRageId);
} }
public class SeriesRepository : BasicRepository<Series>, ISeriesRepository public class SeriesRepository : BasicRepository<Series>, ISeriesRepository
@ -45,5 +45,10 @@ namespace NzbDrone.Core.Tv
{ {
SetFields(new Series { Id = seriesId, SeriesType = seriesType }, s => s.SeriesType); SetFields(new Series { Id = seriesId, SeriesType = seriesType }, s => s.SeriesType);
} }
public void SetTvRageId(int seriesId, int tvRageId)
{
SetFields(new Series { Id = seriesId, TvRageId = tvRageId }, s => s.TvRageId);
}
} }
} }

@ -30,8 +30,7 @@ namespace NzbDrone.Core.Tv
{ {
private readonly ISeriesRepository _seriesRepository; private readonly ISeriesRepository _seriesRepository;
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly TvDbProxy _tvDbProxy; private readonly IProvideSeriesInfo _seriesInfoProxy;
private readonly TvRageMappingProvider _tvRageMappingProvider;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IQualityProfileService _qualityProfileService; private readonly IQualityProfileService _qualityProfileService;
private readonly Logger _logger; private readonly Logger _logger;
@ -40,14 +39,13 @@ namespace NzbDrone.Core.Tv
private readonly ISceneMappingService _sceneNameMappingService; private readonly ISceneMappingService _sceneNameMappingService;
public SeriesService(ISeriesRepository seriesRepository, IConfigService configServiceService, public SeriesService(ISeriesRepository seriesRepository, IConfigService configServiceService,
TvDbProxy tvDbProxyProxy, ISceneMappingService sceneNameMappingService, IProvideSeriesInfo seriesInfoProxy, ISceneMappingService sceneNameMappingService,
TvRageMappingProvider tvRageMappingProvider, IEventAggregator eventAggregator, IQualityProfileService qualityProfileService, Logger logger) IEventAggregator eventAggregator, IQualityProfileService qualityProfileService, Logger logger)
{ {
_seriesRepository = seriesRepository; _seriesRepository = seriesRepository;
_configService = configServiceService; _configService = configServiceService;
_tvDbProxy = tvDbProxyProxy; _seriesInfoProxy = seriesInfoProxy;
_sceneNameMappingService = sceneNameMappingService; _sceneNameMappingService = sceneNameMappingService;
_tvRageMappingProvider = tvRageMappingProvider;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_qualityProfileService = qualityProfileService; _qualityProfileService = qualityProfileService;
_logger = logger; _logger = logger;
@ -63,7 +61,7 @@ namespace NzbDrone.Core.Tv
public Series UpdateSeriesInfo(int seriesId) public Series UpdateSeriesInfo(int seriesId)
{ {
var series = _seriesRepository.Get(seriesId); var series = _seriesRepository.Get(seriesId);
var tvDbSeries = _tvDbProxy.GetSeries(series.TvDbId); var tvDbSeries = _seriesInfoProxy.GetSeriesInfo(series.TvDbId);
series.Title = tvDbSeries.Title; series.Title = tvDbSeries.Title;
series.AirTime = tvDbSeries.AirTime; series.AirTime = tvDbSeries.AirTime;
@ -73,23 +71,9 @@ namespace NzbDrone.Core.Tv
series.CleanTitle = tvDbSeries.CleanTitle; series.CleanTitle = tvDbSeries.CleanTitle;
series.LastInfoSync = DateTime.Now; series.LastInfoSync = DateTime.Now;
series.Runtime = tvDbSeries.Runtime; series.Runtime = tvDbSeries.Runtime;
series.Covers = tvDbSeries.Covers; series.Images = tvDbSeries.Images;
series.Network = tvDbSeries.Network; series.Network = tvDbSeries.Network;
series.FirstAired = tvDbSeries.FirstAired; series.FirstAired = tvDbSeries.FirstAired;
try
{
if (series.TvRageId == 0)
{
series = _tvRageMappingProvider.FindMatchingTvRageSeries(series);
}
}
catch (Exception ex)
{
_logger.ErrorException("Error getting TvRage information for series: " + series.Title, ex);
}
_seriesRepository.Update(series); _seriesRepository.Update(series);
_eventAggregator.Publish(new SeriesUpdatedEvent(series)); _eventAggregator.Publish(new SeriesUpdatedEvent(series));
@ -164,6 +148,11 @@ namespace NzbDrone.Core.Tv
} }
public void SetTvRageId(int seriesId, int tvRageId)
{
_seriesRepository.SetTvRageId(seriesId, tvRageId);
}
public Series FindByTvdbId(int tvdbId) public Series FindByTvdbId(int tvdbId)
{ {
return _seriesRepository.FindByTvdbId(tvdbId); return _seriesRepository.FindByTvdbId(tvdbId);

@ -1,223 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RestSharp;
using RestSharp.Deserializers;
namespace NzbDrone.Core.Tvdb
{
public partial class Tvdb
{
private T ProcessRequest <T>(RestRequest request)
where T: new()
{
return ProcessRequest<T>(BASE_URL, request);
}
private T ProcessRequest <T>(string url, RestRequest request)
where T: new()
{
var client = new RestClient(url);
client.AddHandler("text/xml", new DotNetXmlDeserializer());
if(Timeout.HasValue)
client.Timeout = Timeout.Value;
#if !WINDOWS_PHONE
if(Proxy != null)
client.Proxy = Proxy;
#endif
Error = null;
//var resp = client.Execute(request);
IRestResponse<T> resp = client.Execute<T>(request);
ResponseContent = resp.Content;
ResponseHeaders = resp.Headers.ToDictionary(k => k.Name, v => v.Value);
if(resp.ResponseStatus == ResponseStatus.Completed)
{
return resp.Data;
// Manual deserialization
//TextReader r = new StringReader(resp.Content);
//XmlSerializer s = new XmlSerializer(typeof(T));
//return (T)s.Deserialize(r);
}
else
{
if(resp.ErrorException != null)
throw resp.ErrorException;
else
Error = resp.ErrorMessage;
}
return default(T);
}
public TvdbMirrors GetMirrors()
{
return ProcessRequest<TvdbMirrors>(BuildGetMirrorsRequest());
}
/// <summary>
/// http://www.thetvdb.com/api/Updates.php?type=none
/// </summary>
/// <returns></returns>
public TvdbServerTime GetServerTime()
{
return ProcessRequest<TvdbServerTime>(BuildGetServerTimeRequest());
}
/// <summary>
/// http://www.thetvdb.com/api/{apikey}/languages.xml
/// </summary>
/// <returns></returns>
public List<TvdbLanguage> GetLanguages()
{
var root = ProcessRequest<TvdbLanguagesRoot>(BuildGetLanguagesRequest());
if(root != null)
return root.Languages;
return null;
}
/// <summary>
/// http://www.thetvdb.com/api/GetSeries.php?seriesname={series}
/// </summary>
/// <param name="search"></param>
/// <returns></returns>
public List<TvdbSeriesSearchItem> SearchSeries(string search)
{
var root = ProcessRequest<TvdbSeriesSearchRoot>(BuildGetSearchSeriesRequest(search));
if(root != null)
return root.Series;
return null;
}
/// <summary>
/// http://thetvdb.com/api/{apikey}/series/79349/en.xml
/// </summary>
/// <param name="XMLMirror"></param>
/// <param name="SeriesId"></param>
/// <param name="Language"></param>
/// <returns></returns>
public TvdbSeriesBase GetSeriesBaseRecord(string XMLMirror, int SeriesId, string Language)
{
if(string.IsNullOrEmpty(Language))
Language = "en";
var root = ProcessRequest<TvdbSeriesRecordRoot>(XMLMirror,
BuildGetSeriesBaseRecordRequest(SeriesId, Language));
if(root != null)
return root.Series;
return null;
}
public TvdbSeriesBase GetSeriesBaseRecord(string XMLMirror, int SeriesId)
{
return GetSeriesBaseRecord(XMLMirror, SeriesId, null);
}
/// <summary>
/// http://thetvdb.com/api/{apikey}/series/79349/all/en.xml
/// </summary>
/// <param name="XMLMirror"></param>
/// <param name="SeriesId"></param>
/// <param name="Language"></param>
/// <returns></returns>
public TvdbSeriesFull GetSeriesFullRecord(string XMLMirror, int SeriesId, string Language)
{
if(string.IsNullOrEmpty(Language))
Language = "en";
return ProcessRequest<TvdbSeriesFull>(XMLMirror, BuildGetSeriesFullRecordRequest(SeriesId, Language));
}
public TvdbSeriesFull GetSeriesFullRecord(string MirrorPath, int SeriesId)
{
return GetSeriesFullRecord(MirrorPath, SeriesId, null);
}
/// <summary>
/// http://thetvdb.com/api/{apikey}/series/79349/banners.xml
/// </summary>
/// <param name="XMLMirror"></param>
/// <param name="SeriesId"></param>
/// <returns></returns>
public List<TvdbBanner> GetSeriesBanners(string XMLMirror, int SeriesId)
{
var root = ProcessRequest<TvdbBannerRoot>(XMLMirror, BuildGetSeriesBannersRequest(SeriesId));
if(root != null)
return root.Banners;
return null;
}
/// <summary>
/// http://thetvdb.com/api/{apikey}/series/79349/actors.xml
/// </summary>
/// <param name="XMLMirror"></param>
/// <param name="SeriesId"></param>
/// <returns></returns>
public List<TvdbActor> GetSeriesActors(string XMLMirror, int SeriesId)
{
var root = ProcessRequest<TvdbActorRoot>(XMLMirror, BuildGetSeriesActorsRequest(SeriesId));
if(root != null)
return root.Actors;
return null;
}
public TvdbEpisode GetEpisode(string XMLMirror, int EpisodeId, string Language)
{
if(string.IsNullOrEmpty(Language))
Language = "en";
var root = ProcessRequest<TvdbEpisodeRoot>(XMLMirror, BuildGetEpisodeRequest(EpisodeId, Language));
if(root != null)
return root.Episode;
return null;
}
public TvdbEpisode GetEpisode(string XMLMirror, int EpisodeId)
{
return GetEpisode(XMLMirror, EpisodeId, null);
}
public TvdbEpisode GetSeriesEpisode(string XMLMirror, int SeriesId, int SeasonNum, int EpisodeNum,
string Language)
{
if(string.IsNullOrEmpty(Language))
Language = "en";
var root = ProcessRequest<TvdbEpisodeRoot>(XMLMirror,
BuildGetSeriesEpisodeRequest(SeriesId, SeasonNum, EpisodeNum,
Language));
if(root != null)
return root.Episode;
return null;
}
public TvdbEpisode GetSeriesEpisode(string XMLMirror, int SeriesId, int SeasonNum, int EpisodeNum)
{
return GetSeriesEpisode(XMLMirror, SeriesId, SeasonNum, EpisodeNum, null);
}
public TvdbUpdates GetUpdates(string XMLMirror, TvdbUpdatePeriod Period)
{
return ProcessRequest<TvdbUpdates>(XMLMirror, BuildGetUpdatesRequest(Period));
}
public TvdbUpdateItems GetUpdatesSince(string XMLMirror, Int64 LastTime)
{
return ProcessRequest<TvdbUpdateItems>(XMLMirror, BuildGetUpdatesSinceRequest(LastTime));
}
}
}

@ -1,205 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using RestSharp;
namespace NzbDrone.Core.Tvdb
{
public partial class Tvdb
{
private const string BASE_URL = "http://www.thetvdb.com/api";
public string ApiKey { get; set; }
public string Error { get; set; }
/// <summary>
/// String representation of response content
/// </summary>
public string ResponseContent { get; set; }
/// <summary>
/// Dictionary of Header values in response
/// http://help.themoviedb.org/kb/api/content-versioning
/// </summary>
public Dictionary<string, object> ResponseHeaders { get; set; }
#if !WINDOWS_PHONE
/// <summary>
/// Proxy to use for requests made. Passed on to underying WebRequest if set.
/// </summary>
public IWebProxy Proxy { get; set; }
#endif
/// <summary>
/// Timeout in milliseconds to use for requests made.
/// </summary>
public int? Timeout { get; set; }
public Tvdb(string apiKey)
{
ApiKey = apiKey;
Error = null;
Timeout = null;
}
#region Helper methods
public static string GetImageUrl(string BannerMirror, string filename)
{
return string.Format("{0}/banners/{1}", BannerMirror, filename);
}
#if !WINDOWS_PHONE
public static byte[] GetImage(string BannerMirror, string filename)
{
return GetImage(GetImageUrl(BannerMirror, filename));
}
public static byte[] GetImage(string url)
{
return new WebClient().DownloadData(url);
}
#endif
#endregion
#region Build Requests
private RestRequest BuildGetMirrorsRequest(object UserState = null)
{
var request = new RestRequest("{apikey}/mirrors.xml", Method.GET);
request.AddUrlSegment("apikey", ApiKey);
if(UserState != null)
request.UserState = UserState;
return request;
}
private static RestRequest BuildGetServerTimeRequest(object UserState = null)
{
var request = new RestRequest("Updates.php", Method.GET);
request.AddParameter("type", "none");
if(UserState != null)
request.UserState = UserState;
return request;
}
private RestRequest BuildGetLanguagesRequest(object UserState = null)
{
var request = new RestRequest("{apikey}/languages.xml", Method.GET);
request.AddUrlSegment("apikey", ApiKey);
if(UserState != null)
request.UserState = UserState;
return request;
}
private static RestRequest BuildGetSearchSeriesRequest(string search, object UserState = null)
{
var request = new RestRequest("GetSeries.php", Method.GET);
request.AddParameter("seriesname", search);
if(UserState != null)
request.UserState = UserState;
return request;
}
private RestRequest BuildGetSeriesBaseRecordRequest(int SeriesId, string Language, object UserState = null)
{
var request = new RestRequest("api/{apikey}/series/{id}/{lang}.xml");
request.AddUrlSegment("apikey", ApiKey);
request.AddUrlSegment("id", SeriesId.ToString());
request.AddUrlSegment("lang", Language);
if(UserState != null)
request.UserState = UserState;
return request;
}
private RestRequest BuildGetSeriesFullRecordRequest(int SeriesId, string Language, object UserState = null)
{
var request = new RestRequest("api/{apikey}/series/{id}/all/{lang}.xml");
request.AddUrlSegment("apikey", ApiKey);
request.AddUrlSegment("id", SeriesId.ToString());
request.AddUrlSegment("lang", Language);
if(UserState != null)
request.UserState = UserState;
return request;
}
private RestRequest BuildGetSeriesBannersRequest(int SeriesId, object UserState = null)
{
var request = new RestRequest("api/{apikey}/series/{id}/banners.xml");
request.AddUrlSegment("apikey", ApiKey);
request.AddUrlSegment("id", SeriesId.ToString());
if(UserState != null)
request.UserState = UserState;
return request;
}
private RestRequest BuildGetSeriesActorsRequest(int SeriesId, object UserState = null)
{
var request = new RestRequest("api/{apikey}/series/{id}/actors.xml");
request.AddUrlSegment("apikey", ApiKey);
request.AddUrlSegment("id", SeriesId.ToString());
if(UserState != null)
request.UserState = UserState;
return request;
}
private RestRequest BuildGetEpisodeRequest(int EpisodeId, string Language, object UserState = null)
{
var request = new RestRequest("api/{apikey}/episodes/{id}/{lang}.xml");
request.AddUrlSegment("apikey", ApiKey);
request.AddUrlSegment("id", EpisodeId.ToString());
request.AddUrlSegment("lang", Language);
if(UserState != null)
request.UserState = UserState;
return request;
}
private RestRequest BuildGetSeriesEpisodeRequest(int SeriesId, int SeasonNum, int EpisodeNum, string Language,
object UserState = null)
{
var request = new RestRequest("api/{apikey}/series/{id}/default/{season}/{episode}/{lang}.xml");
request.AddUrlSegment("apikey", ApiKey);
request.AddUrlSegment("id", SeriesId.ToString());
request.AddUrlSegment("season", SeasonNum.ToString());
request.AddUrlSegment("episode", EpisodeNum.ToString());
request.AddUrlSegment("lang", Language);
if(UserState != null)
request.UserState = UserState;
return request;
}
private RestRequest BuildGetUpdatesRequest(TvdbUpdatePeriod Period, object UserState = null)
{
var request = new RestRequest("api/{apikey}/updates/updates_{period}.xml");
request.AddUrlSegment("apikey", ApiKey);
request.AddUrlSegment("period", Period.ToString());
if(UserState != null)
request.UserState = UserState;
return request;
}
private static RestRequest BuildGetUpdatesSinceRequest(Int64 LastTime, object UserState = null)
{
var request = new RestRequest("api/Updates.php?type=all&time={time}");
request.AddUrlSegment("time", LastTime.ToString());
if(UserState != null)
request.UserState = UserState;
return request;
}
#endregion
}
}

@ -1,36 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Actors")]
public class TvdbActorRoot
{
public TvdbActorRoot()
{
Actors = new List<TvdbActor>();
}
[XmlElement(ElementName = "Actor")]
public List<TvdbActor> Actors { get; set; }
}
public class TvdbActor
{
[XmlElement]
public int id { get; set; }
[XmlElement]
public string Image { get; set; }
[XmlElement]
public string Name { get; set; }
[XmlElement]
public string Role { get; set; }
[XmlElement]
public int SortOrder { get; set; }
}
}

@ -1,10 +0,0 @@
using System.Linq;
namespace NzbDrone.Core.Tvdb
{
public class TvdbAsyncResult <T>
{
public T Data { get; set; }
public object UserState { get; set; }
}
}

@ -1,86 +0,0 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Banners")]
public class TvdbBannerRoot
{
public TvdbBannerRoot()
{
Banners = new List<TvdbBanner>();
}
[XmlElement(ElementName = "Banner")]
public List<TvdbBanner> Banners { get; set; }
}
public class TvdbBanner
{
[XmlElement]
public int id { get; set; }
[XmlElement]
public string BannerPath { get; set; }
[XmlElement]
public string BannerType { get; set; }
[XmlElement]
public string BannerType2 { get; set; }
[XmlElement]
public string Colors { get; set; }
[XmlElement]
public string Language { get; set; }
[XmlElement("Rating")]
public string RatingString
{
get { return Rating.HasValue ? Rating.Value.ToString() : null; }
set
{
double d;
if(double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out d))
Rating = d;
else
Rating = null;
}
}
[XmlIgnore]
public double? Rating { get; set; }
[XmlElement]
public int? RatingCount { get; set; }
[XmlElement(ElementName = "SeriesName")]
public string SeriesNameString
{
get { return SeriesName.HasValue ? SeriesName.Value.ToString() : null; }
set
{
bool b;
if(bool.TryParse(value, out b))
SeriesName = b;
else
SeriesName = null;
}
}
[XmlIgnore]
public bool? SeriesName { get; set; }
[XmlElement]
public string ThumbnailPath { get; set; }
[XmlElement]
public string VignettePath { get; set; }
[XmlElement]
public string Season { get; set; }
}
}

@ -1,132 +0,0 @@
using System;
using System.Globalization;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Data")]
public class TvdbEpisodeRoot
{
[XmlElement]
public TvdbEpisode Episode { get; set; }
}
public class TvdbEpisode
{
[XmlElement]
public int id { get; set; }
[XmlElement]
public string Combined_episodenumber { get; set; }
[XmlElement]
public string Combined_season { get; set; }
[XmlElement]
public string DVD_chapter { get; set; }
[XmlElement]
public string DVD_discid { get; set; }
[XmlElement]
public string DVD_episodenumber { get; set; }
[XmlElement]
public string DVD_season { get; set; }
[XmlElement]
public string Director { get; set; }
[XmlElement(ElementName = "EpImgFlag")]
public string EpImgFlagString
{
get { return EpImgFlag.HasValue ? EpImgFlag.Value.ToString() : null; }
set
{
int i;
if(int.TryParse(value, out i))
EpImgFlag = i;
else
EpImgFlag = null;
}
}
[XmlIgnore]
public int? EpImgFlag { get; set; }
[XmlElement]
public string EpisodeName { get; set; }
[XmlElement]
public int EpisodeNumber { get; set; }
[XmlElement]
public DateTime FirstAired { get; set; }
[XmlElement]
public string GuestStars { get; set; }
[XmlElement]
public string IMDB_ID { get; set; }
[XmlElement]
public string Language { get; set; }
[XmlElement]
public string Overview { get; set; }
[XmlElement]
public string ProductionCode { get; set; }
[XmlElement("Rating")]
public string RatingString
{
get { return Rating.HasValue ? Rating.Value.ToString() : null; }
set
{
double d;
if(double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out d))
Rating = d;
else
Rating = null;
}
}
[XmlIgnore]
public double? Rating { get; set; }
[XmlElement]
public int? RatingCount { get; set; }
[XmlElement]
public int SeasonNumber { get; set; }
[XmlElement]
public string Writer { get; set; }
[XmlElement]
public string absolute_number { get; set; }
[XmlElement]
public string airsafter_season { get; set; }
[XmlElement]
public string airsbefore_episode { get; set; }
[XmlElement]
public string airsbefore_season { get; set; }
[XmlElement]
public string filename { get; set; }
[XmlElement]
public Int64 lastupdated { get; set; }
[XmlElement]
public int? seasonid { get; set; }
[XmlElement]
public int seriesid { get; set; }
}
}

@ -1,30 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Languages")]
public class TvdbLanguagesRoot
{
public TvdbLanguagesRoot()
{
Languages = new List<TvdbLanguage>();
}
[XmlElement(ElementName = "Language")]
public List<TvdbLanguage> Languages { get; set; }
}
public class TvdbLanguage
{
[XmlElement]
public int id { get; set; }
[XmlElement]
public string name { get; set; }
[XmlElement]
public string abbreviation { get; set; }
}
}

@ -1,40 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Mirrors")]
public class TvdbMirrors
{
[XmlElement(ElementName = "Mirror")]
public List<TvdbMirror> Mirrors { get; set; }
}
public class TvdbMirror
{
[XmlElement]
public int id { get; set; }
[XmlElement]
public string mirrorpath { get; set; }
[XmlElement]
public int typemask { get; set; }
public bool IsXMLMirror
{
get { return (typemask & 1) != 0; }
}
public bool IsBannerMirror
{
get { return (typemask & 2) != 0; }
}
public bool IsZipMirror
{
get { return (typemask & 4) != 0; }
}
}
}

@ -1,131 +0,0 @@
using System;
using System.Globalization;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Data")]
public class TvdbSeriesRecordRoot
{
[XmlElement]
public TvdbSeriesBase Series { get; set; }
}
public class TvdbSeriesBase
{
[XmlElement]
public int id { get; set; }
[XmlElement]
public string Actors { get; set; }
[XmlElement]
public string Airs_DayOfWeek { get; set; }
[XmlElement]
public string Airs_Time { get; set; }
[XmlElement]
public string ContentRating { get; set; }
[XmlElement(ElementName = "FirstAired")]
public string FirstAiredString
{
get { return FirstAired.HasValue ? FirstAired.Value.ToString("yyyy-MM-dd") : null; }
set
{
DateTime d;
if(DateTime.TryParse(value, out d))
FirstAired = d;
else
FirstAired = null;
}
}
[XmlIgnore]
public DateTime? FirstAired { get; set; }
[XmlElement]
public string Genre { get; set; }
[XmlElement]
public string IMDB_ID { get; set; }
[XmlElement]
public string Language { get; set; }
[XmlElement]
public string Network { get; set; }
[XmlElement]
public string Overview { get; set; }
[XmlElement("Rating")]
public string RatingString
{
get { return Rating.HasValue ? Rating.Value.ToString() : null; }
set
{
double d;
if(double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out d))
Rating = d;
else
Rating = null;
}
}
[XmlIgnore]
public double? Rating { get; set; }
[XmlElement]
public int? RatingCount { get; set; }
[XmlElement]
public int? Runtime { get; set; }
[XmlElement]
public string SeriesIDString
{
get { return SeriesID.HasValue ? SeriesID.Value.ToString() : null; }
set
{
int i;
if(int.TryParse(value, out i))
SeriesID = i;
else
SeriesID = null;
}
}
[XmlIgnore]
public int? SeriesID { get; set; }
[XmlElement]
public string SeriesName { get; set; }
[XmlElement]
public string Status { get; set; }
[XmlElement]
public string added { get; set; }
[XmlElement]
public string addedBy { get; set; }
[XmlElement]
public string banner { get; set; }
[XmlElement]
public string fanart { get; set; }
[XmlElement]
public Int64 lastupdated { get; set; }
[XmlElement]
public string poster { get; set; }
[XmlElement]
public string zap2it_id { get; set; }
}
}

@ -1,21 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Data")]
public class TvdbSeriesFull
{
public TvdbSeriesFull()
{
Episodes = new List<TvdbEpisode>();
}
[XmlElement]
public TvdbSeriesBase Series { get; set; }
[XmlElement(ElementName = "Episode")]
public List<TvdbEpisode> Episodes { get; set; }
}
}

@ -1,18 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Data")]
public class TvdbSeriesSearchRoot
{
public TvdbSeriesSearchRoot()
{
Series = new List<TvdbSeriesSearchItem>();
}
[XmlElement(ElementName = "Series")]
public List<TvdbSeriesSearchItem> Series { get; set; }
}
}

@ -1,50 +0,0 @@
using System;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
public class TvdbSeriesSearchItem
{
[XmlElement]
public int id { get; set; }
[XmlElement]
public int seriesid { get; set; }
[XmlElement]
public string language { get; set; }
[XmlElement]
public string SeriesName { get; set; }
[XmlElement]
public string banner { get; set; }
[XmlElement]
public string Overview { get; set; }
[XmlElement(ElementName = "FirstAired")]
public string FirstAiredString
{
get { return FirstAired.HasValue ? FirstAired.Value.ToString("yyyy-MM-dd") : null; }
set
{
DateTime d;
if(DateTime.TryParse(value, out d))
FirstAired = d;
else
FirstAired = null;
}
}
[XmlIgnore]
public DateTime? FirstAired { get; set; }
[XmlElement]
public string IMDB_ID { get; set; }
[XmlElement]
public string zap2it_id { get; set; }
}
}

@ -1,13 +0,0 @@
using System;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Items")]
public class TvdbServerTime
{
[XmlElement]
public Int64 Time { get; set; }
}
}

@ -1,86 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
public enum TvdbUpdatePeriod
{
day,
week,
month
};
[XmlRoot(ElementName = "Data")]
public class TvdbUpdates
{
public TvdbUpdates()
{
Series = new List<TvdbUpdateSeries>();
}
[XmlAttribute]
public Int64 time { get; set; }
[XmlElement(ElementName = "Series")]
public List<TvdbUpdateSeries> Series { get; set; }
[XmlElement(ElementName = "Episode")]
public List<TvdbUpdateEpisode> Episodes { get; set; }
[XmlElement(ElementName = "Banner")]
public List<TvdbUpdateBanner> Banners { get; set; }
}
public class TvdbUpdateSeries
{
[XmlElement]
public int id { get; set; }
[XmlElement]
public Int64 time { get; set; }
}
public class TvdbUpdateEpisode
{
[XmlElement]
public int id { get; set; }
[XmlElement]
public int Series { get; set; }
[XmlElement]
public Int64 time { get; set; }
}
public class TvdbUpdateBanner
{
/// <summary>
/// fanart, poster, season, series, episode, actors
/// </summary>
[XmlElement]
public string type { get; set; }
[XmlElement]
public string format { get; set; }
[XmlElement]
public int Series { get; set; }
/// <summary>
/// Only appears for season banners
/// </summary>
[XmlElement]
public int? SeasonNum { get; set; }
[XmlElement]
public string language { get; set; }
[XmlElement]
public string path { get; set; }
[XmlElement]
public Int64 time { get; set; }
}
}

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
namespace NzbDrone.Core.Tvdb
{
[XmlRoot(ElementName = "Items")]
public class TvdbUpdateItems
{
public TvdbUpdateItems()
{
Series = new List<int>();
Episodes = new List<int>();
}
[XmlElement]
public Int64 Time { get; set; }
[XmlElement(ElementName = "Series")]
public List<int> Series { get; set; }
[XmlElement(ElementName = "Episode")]
public List<int> Episodes { get; set; }
}
}

@ -4,6 +4,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToReturnStatement/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToReturnStatement/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertNullableToShortForm/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertNullableToShortForm/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FunctionRecursiveOnAllPaths/@EntryIndexedValue">ERROR</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FunctionRecursiveOnAllPaths/@EntryIndexedValue">ERROR</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseObjectOrCollectionInitializer/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/Environment/Editor/MatchingBraceHighlighting/Position/@EntryValue">BOTH_SIDES</s:String> <s:String x:Key="/Default/Environment/Editor/MatchingBraceHighlighting/Position/@EntryValue">BOTH_SIDES</s:String>

Loading…
Cancel
Save