Fixed import new series being stuck in a loop if an update failed

Seperated IndexerProviderTest from ProviderTests
Fixed some ToString() issues
Refactored IndexerBase/IndexerProvider
pull/6/head
kay.one 13 years ago
parent 474f17c5e6
commit a6ad977114

@ -20,10 +20,8 @@ namespace NzbDrone.Core.Test
public class ImportNewSeriesJobTest : TestBase public class ImportNewSeriesJobTest : TestBase
{ {
[Test] [Test]
public void series_specific_scan_should_scan_series() public void import_new_series_succesfull()
{ {
var series = Builder<Series>.CreateListOfSize(2) var series = Builder<Series>.CreateListOfSize(2)
.WhereAll().Have(s => s.Episodes = Builder<Episode>.CreateListOfSize(10).Build()) .WhereAll().Have(s => s.Episodes = Builder<Episode>.CreateListOfSize(10).Build())
.WhereAll().Have(s => s.LastInfoSync = null) .WhereAll().Have(s => s.LastInfoSync = null)
@ -37,21 +35,38 @@ namespace NzbDrone.Core.Test
mocker.GetMock<SeriesProvider>() mocker.GetMock<SeriesProvider>()
.Setup(p => p.GetAllSeries()) .Setup(p => p.GetAllSeries())
.Returns(series.AsQueryable()) .Returns(series.AsQueryable());
.Callback(() => series.ToList().ForEach(c => c.LastInfoSync = DateTime.Now));//Set the last scan time on the collection
mocker.GetMock<DiskScanJob>() mocker.GetMock<DiskScanJob>()
.Setup(j => j.Start(notification, series[0].SeriesId)); .Setup(j => j.Start(notification, series[0].SeriesId))
.Callback(() => series[0].LastDiskSync = DateTime.Now)
.AtMostOnce();
mocker.GetMock<DiskScanJob>() mocker.GetMock<DiskScanJob>()
.Setup(j => j.Start(notification, series[1].SeriesId)); .Setup(j => j.Start(notification, series[1].SeriesId))
.Callback(() => series[1].LastDiskSync = DateTime.Now)
.AtMostOnce();
mocker.GetMock<UpdateInfoJob>() mocker.GetMock<UpdateInfoJob>()
.Setup(j => j.Start(notification, series[0].SeriesId)); .Setup(j => j.Start(notification, series[0].SeriesId))
.Callback(() => series[0].LastInfoSync = DateTime.Now)
.AtMostOnce();
mocker.GetMock<UpdateInfoJob>() mocker.GetMock<UpdateInfoJob>()
.Setup(j => j.Start(notification, series[1].SeriesId)); .Setup(j => j.Start(notification, series[1].SeriesId))
.Callback(() => series[1].LastInfoSync = DateTime.Now)
.AtMostOnce();
mocker.GetMock<SeriesProvider>()
.Setup(s => s.GetSeries(series[0].SeriesId)).Returns(series[0]);
mocker.GetMock<SeriesProvider>()
.Setup(s => s.GetSeries(series[1].SeriesId)).Returns(series[1]);
mocker.GetMock<MediaFileProvider>()
.Setup(s => s.GetSeriesFiles(It.IsAny<int>())).Returns(new List<EpisodeFile>());
//Act //Act
mocker.Resolve<ImportNewSeriesJob>().Start(notification, 0); mocker.Resolve<ImportNewSeriesJob>().Start(notification, 0);
@ -61,35 +76,20 @@ namespace NzbDrone.Core.Test
} }
[Test]
public void series_with_no_episodes_should_skip_scan()
{
var series = Builder<Series>.CreateNew()
.With(s => s.SeriesId = 12)
.With(s => s.Episodes = new List<Episode>())
.Build();
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<SeriesProvider>()
.Setup(p => p.GetSeries(series.SeriesId))
.Returns(series);
//Act
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), series.SeriesId);
//Assert
mocker.VerifyAllMocks();
}
[Test] [Test]
public void job_with_no_target_should_scan_all_series() [Timeout(3)]
public void failed_import_should_not_be_stuck_in_loop()
{ {
var series = Builder<Series>.CreateListOfSize(2) var series = Builder<Series>.CreateListOfSize(2)
.WhereTheFirst(1).Has(s => s.SeriesId = 12) .WhereAll().Have(s => s.Episodes = Builder<Episode>.CreateListOfSize(10).Build())
.AndTheNext(1).Has(s => s.SeriesId = 15) .WhereAll().Have(s => s.LastInfoSync = null)
.WhereAll().Have(s => s.Episodes = Builder<Episode>.CreateListOfSize(10).Build()) .WhereTheFirst(1).Has(s => s.SeriesId = 12)
.Build(); .AndTheNext(1).Has(s => s.SeriesId = 15)
.Build();
var notification = new ProgressNotification("Test");
var mocker = new AutoMoqer(MockBehavior.Strict); var mocker = new AutoMoqer(MockBehavior.Strict);
@ -97,45 +97,36 @@ namespace NzbDrone.Core.Test
.Setup(p => p.GetAllSeries()) .Setup(p => p.GetAllSeries())
.Returns(series.AsQueryable()); .Returns(series.AsQueryable());
mocker.GetMock<MediaFileProvider>() mocker.GetMock<UpdateInfoJob>()
.Setup(s => s.Scan(series[0])) .Setup(j => j.Start(notification, series[0].SeriesId))
.Returns(new List<EpisodeFile>()); .Callback(() => series[0].LastInfoSync = DateTime.Now)
.AtMostOnce();
mocker.GetMock<MediaFileProvider>()
.Setup(s => s.Scan(series[1]))
.Returns(new List<EpisodeFile>());
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), 0);
mocker.VerifyAllMocks(); mocker.GetMock<UpdateInfoJob>()
} .Setup(j => j.Start(notification, series[1].SeriesId))
.Throws(new InvalidOperationException())
.AtMostOnce();
[Test] mocker.GetMock<DiskScanJob>()
public void job_with_no_target_should_scan_series_with_episodes() .Setup(j => j.Start(notification, series[0].SeriesId))
{ .Callback(() => series[0].LastDiskSync = DateTime.Now)
var series = Builder<Series>.CreateListOfSize(2) .AtMostOnce();
.WhereTheFirst(1).Has(s => s.SeriesId = 12)
.And(s => s.Episodes = Builder<Episode>.CreateListOfSize(10).Build())
.AndTheNext(1).Has(s => s.SeriesId = 15)
.And(s => s.Episodes = new List<Episode>())
.Build();
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<SeriesProvider>() mocker.GetMock<SeriesProvider>()
.Setup(p => p.GetAllSeries()) .Setup(s => s.GetSeries(series[0].SeriesId)).Returns(series[0]);
.Returns(series.AsQueryable());
mocker.GetMock<MediaFileProvider>() mocker.GetMock<MediaFileProvider>()
.Setup(s => s.Scan(series[0])) .Setup(s => s.GetSeriesFiles(It.IsAny<int>())).Returns(new List<EpisodeFile>());
.Returns(new List<EpisodeFile>());
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), 0);
//Act
mocker.Resolve<ImportNewSeriesJob>().Start(notification, 0);
//Assert
mocker.VerifyAllMocks(); mocker.VerifyAllMocks();
ExceptionVerification.ExcpectedErrors(1);
} }
} }
} }

@ -23,151 +23,6 @@ namespace NzbDrone.Core.Test
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
public class IndexerProviderTest : TestBase public class IndexerProviderTest : TestBase
{ {
[Test]
[Row("nzbsorg.xml", 0)]
[Row("nzbsrus.xml", 6)]
[Row("newzbin.xml", 1)]
[Row("nzbmatrix.xml", 1)]
public void parse_feed_xml(string fileName, int warns)
{
var mocker = new AutoMoqer();
mocker.GetMock<HttpProvider>()
.Setup(h => h.DownloadStream(It.IsAny<String>(), It.IsAny<NetworkCredential>()))
.Returns(File.OpenRead(".\\Files\\Rss\\" + fileName));
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
var mockIndexer = mocker.Resolve<MockIndexer>();
var parseResults = mockIndexer.FetchRss();
foreach (var episodeParseResult in parseResults)
{
var Uri = new Uri(episodeParseResult.NzbUrl);
Assert.DoesNotContain(Uri.PathAndQuery, "//");
}
Assert.IsNotEmpty(parseResults);
Assert.ForAll(parseResults, s => Assert.AreEqual(mockIndexer.Name, s.Indexer));
Assert.ForAll(parseResults, s => Assert.AreNotEqual("", s.NzbTitle));
Assert.ForAll(parseResults, s => Assert.AreNotEqual(null, s.NzbTitle));
ExceptionVerification.ExcpectedWarns(warns);
}
[Test]
public void newzbin()
{
var mocker = new AutoMoqer();
mocker.GetMock<HttpProvider>()
.Setup(h => h.DownloadStream(It.IsAny<String>(), It.IsAny<NetworkCredential>()))
.Returns(File.OpenRead(".\\Files\\Rss\\newzbin.xml"));
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
var newzbinProvider = mocker.Resolve<Newzbin>();
var parseResults = newzbinProvider.FetchRss();
foreach (var episodeParseResult in parseResults)
{
var Uri = new Uri(episodeParseResult.NzbUrl);
Assert.DoesNotContain(Uri.PathAndQuery, "//");
}
Assert.IsNotEmpty(parseResults);
Assert.ForAll(parseResults, s => Assert.AreEqual(newzbinProvider.Name, s.Indexer));
Assert.ForAll(parseResults, s => Assert.AreNotEqual("", s.NzbTitle));
Assert.ForAll(parseResults, s => Assert.AreNotEqual(null, s.NzbTitle));
ExceptionVerification.ExcpectedWarns(1);
}
[Test]
[Row("Adventure.Inc.S03E19.DVDRip.XviD-OSiTV", 3, 19, QualityTypes.DVD)]
public void custome_parser_partial_success(string title, int season, int episode, QualityTypes quality)
{
var mocker = new AutoMoqer();
const string summary = "My fake summary";
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
var fakeRssItem = Builder<SyndicationItem>.CreateNew()
.With(c => c.Title = new TextSyndicationContent(title))
.With(c => c.Summary = new TextSyndicationContent(summary))
.Build();
var result = mocker.Resolve<CustomParserIndexer>().ParseFeed(fakeRssItem);
Assert.IsNotNull(result);
Assert.AreEqual(summary, result.EpisodeTitle);
Assert.AreEqual(season, result.SeasonNumber);
Assert.AreEqual(episode, result.EpisodeNumbers[0]);
Assert.AreEqual(quality, result.Quality);
}
[Test]
[Row("Adventure.Inc.DVDRip.XviD-OSiTV")]
public void custome_parser_full_parse(string title)
{
var mocker = new AutoMoqer();
const string summary = "My fake summary";
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
var fakeRssItem = Builder<SyndicationItem>.CreateNew()
.With(c => c.Title = new TextSyndicationContent(title))
.With(c => c.Summary = new TextSyndicationContent(summary))
.Build();
var result = mocker.Resolve<CustomParserIndexer>().ParseFeed(fakeRssItem);
Assert.IsNotNull(result);
Assert.AreEqual(summary, result.EpisodeTitle);
ExceptionVerification.ExcpectedWarns(1);
}
[Test]
public void downloadFeed()
{
var mocker = new AutoMoqer();
mocker.SetConstant(new HttpProvider());
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
mocker.Resolve<TestUrlIndexer>().FetchRss();
ExceptionVerification.IgnoreWarns();
}
[Test] [Test]
public void Init_indexer_test() public void Init_indexer_test()
{ {
@ -178,49 +33,32 @@ namespace NzbDrone.Core.Test
//Act //Act
var indexerProvider = mocker.Resolve<IndexerProvider>(); var indexerProvider = mocker.Resolve<IndexerProvider>();
indexerProvider.InitializeIndexers(new List<IndexerBase> { mocker.Resolve<MockIndexer>() }); indexerProvider.InitializeIndexers(new List<IndexerBase> { mocker.Resolve<MockIndexer>() });
var indexers = indexerProvider.All(); var settings = indexerProvider.GetSettings(typeof(MockIndexer));
settings.Enable = true;
indexerProvider.SaveSettings(settings);
//Assert //Assert
Assert.Count(1, indexers); Assert.Count(1, indexerProvider.GetAllISettings());
} Assert.Count(1, indexerProvider.GetEnabledIndexers());
[Test]
public void unmapped_series_shouldnt_call_any_providers()
{
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<SeriesProvider>()
.Setup(c => c.FindSeries(It.IsAny<String>()))
.Returns<Series>(null);
var indexer = mocker.Resolve<MockIndexer>();
//indexer.ProcessItem(new SyndicationItem { Title = new TextSyndicationContent("Adventure.Inc.S01E18.DVDRip.XviD-OSiTV") });
} }
[Test] [Test]
public void nzbsorg_search_returns_valid_results() public void Init_indexer_with_disabled_job()
{ {
var mocker = new AutoMoqer(); var mocker = new AutoMoqer();
mocker.GetMock<ConfigProvider>() mocker.SetConstant(MockLib.GetEmptyRepository());
.SetupGet(c => c.NzbsOrgUId)
.Returns("43516");
mocker.GetMock<ConfigProvider>()
.SetupGet(c => c.NzbsOrgHash)
.Returns("bc8edb4cc49d4ae440775adec5ac001f");
mocker.Resolve<HttpProvider>();
var result = mocker.Resolve<NzbsOrg>().FetchEpisode("Simpsons", 21, 23);
Assert.IsNotEmpty(result); //Act
Assert.ForAll(result, r => r.CleanTitle == "simpsons"); var indexerProvider = mocker.Resolve<IndexerProvider>();
Assert.ForAll(result, r => r.SeasonNumber == 21); indexerProvider.InitializeIndexers(new List<IndexerBase> { mocker.Resolve<MockIndexer>() });
Assert.ForAll(result, r => r.EpisodeNumbers.Contains(23)); var settings = indexerProvider.GetSettings(typeof(MockIndexer));
settings.Enable = false;
indexerProvider.SaveSettings(settings);
//Assert
Assert.Count(1, indexerProvider.GetAllISettings());
Assert.IsEmpty(indexerProvider.GetEnabledIndexers());
} }
} }

@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.ServiceModel.Syndication;
using System.Text;
using AutoMoq;
using FizzWare.NBuilder;
using Gallio.Framework;
using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers;
using Moq;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Indexer;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class IndexerTests : TestBase
{
[Test]
[Row("nzbsorg.xml", 0)]
[Row("nzbsrus.xml", 6)]
[Row("newzbin.xml", 1)]
[Row("nzbmatrix.xml", 1)]
public void parse_feed_xml(string fileName, int warns)
{
var mocker = new AutoMoqer();
mocker.GetMock<HttpProvider>()
.Setup(h => h.DownloadStream(It.IsAny<String>(), It.IsAny<NetworkCredential>()))
.Returns(File.OpenRead(".\\Files\\Rss\\" + fileName));
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
var mockIndexer = mocker.Resolve<MockIndexer>();
var parseResults = mockIndexer.FetchRss();
foreach (var episodeParseResult in parseResults)
{
var Uri = new Uri(episodeParseResult.NzbUrl);
Assert.DoesNotContain(Uri.PathAndQuery, "//");
}
Assert.IsNotEmpty(parseResults);
Assert.ForAll(parseResults, s => Assert.AreEqual(mockIndexer.Name, s.Indexer));
Assert.ForAll(parseResults, s => Assert.AreNotEqual("", s.NzbTitle));
Assert.ForAll(parseResults, s => Assert.AreNotEqual(null, s.NzbTitle));
ExceptionVerification.ExcpectedWarns(warns);
}
[Test]
public void newzbin()
{
var mocker = new AutoMoqer();
mocker.GetMock<HttpProvider>()
.Setup(h => h.DownloadStream(It.IsAny<String>(), It.IsAny<NetworkCredential>()))
.Returns(File.OpenRead(".\\Files\\Rss\\newzbin.xml"));
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
var newzbinProvider = mocker.Resolve<Newzbin>();
var parseResults = newzbinProvider.FetchRss();
foreach (var episodeParseResult in parseResults)
{
var Uri = new Uri(episodeParseResult.NzbUrl);
Assert.DoesNotContain(Uri.PathAndQuery, "//");
}
Assert.IsNotEmpty(parseResults);
Assert.ForAll(parseResults, s => Assert.AreEqual(newzbinProvider.Name, s.Indexer));
Assert.ForAll(parseResults, s => Assert.AreNotEqual("", s.NzbTitle));
Assert.ForAll(parseResults, s => Assert.AreNotEqual(null, s.NzbTitle));
ExceptionVerification.ExcpectedWarns(1);
}
[Test]
[Row("Adventure.Inc.S03E19.DVDRip.XviD-OSiTV", 3, 19, QualityTypes.DVD)]
public void custome_parser_partial_success(string title, int season, int episode, QualityTypes quality)
{
var mocker = new AutoMoqer();
const string summary = "My fake summary";
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
var fakeRssItem = Builder<SyndicationItem>.CreateNew()
.With(c => c.Title = new TextSyndicationContent(title))
.With(c => c.Summary = new TextSyndicationContent(summary))
.Build();
var result = mocker.Resolve<CustomParserIndexer>().ParseFeed(fakeRssItem);
Assert.IsNotNull(result);
Assert.AreEqual(summary, result.EpisodeTitle);
Assert.AreEqual(season, result.SeasonNumber);
Assert.AreEqual(episode, result.EpisodeNumbers[0]);
Assert.AreEqual(quality, result.Quality);
}
[Test]
[Row("Adventure.Inc.DVDRip.XviD-OSiTV")]
public void custome_parser_full_parse(string title)
{
var mocker = new AutoMoqer();
const string summary = "My fake summary";
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
var fakeRssItem = Builder<SyndicationItem>.CreateNew()
.With(c => c.Title = new TextSyndicationContent(title))
.With(c => c.Summary = new TextSyndicationContent(summary))
.Build();
var result = mocker.Resolve<CustomParserIndexer>().ParseFeed(fakeRssItem);
Assert.IsNotNull(result);
Assert.AreEqual(summary, result.EpisodeTitle);
ExceptionVerification.ExcpectedWarns(1);
}
[Test]
public void downloadFeed()
{
var mocker = new AutoMoqer();
mocker.SetConstant(new HttpProvider());
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
mocker.Resolve<TestUrlIndexer>().FetchRss();
ExceptionVerification.IgnoreWarns();
}
[Test]
public void nzbsorg_search_returns_valid_results()
{
var mocker = new AutoMoqer();
mocker.GetMock<ConfigProvider>()
.SetupGet(c => c.NzbsOrgUId)
.Returns("43516");
mocker.GetMock<ConfigProvider>()
.SetupGet(c => c.NzbsOrgHash)
.Returns("bc8edb4cc49d4ae440775adec5ac001f");
mocker.Resolve<HttpProvider>();
var result = mocker.Resolve<NzbsOrg>().FetchEpisode("Simpsons", 21, 23);
Assert.IsNotEmpty(result);
Assert.ForAll(result, r => r.CleanTitle == "simpsons");
Assert.ForAll(result, r => r.SeasonNumber == 21);
Assert.ForAll(result, r => r.EpisodeNumbers.Contains(23));
}
}
}

@ -114,13 +114,13 @@ namespace NzbDrone.Core.Test
var timerProvider = mocker.Resolve<JobProvider>(); var timerProvider = mocker.Resolve<JobProvider>();
timerProvider.Initialize(); timerProvider.Initialize();
var firstRun = timerProvider.QueueJob(typeof(SlowJob),1); var firstRun = timerProvider.QueueJob(typeof(SlowJob), 1);
var secondRun = timerProvider.QueueJob(typeof(SlowJob),2); var secondRun = timerProvider.QueueJob(typeof(SlowJob), 2);
var third = timerProvider.QueueJob(typeof(SlowJob),3); var third = timerProvider.QueueJob(typeof(SlowJob), 3);
Thread.Sleep(10000); Thread.Sleep(10000);
//Asserts are done in ExceptionVerification
} }

@ -89,6 +89,7 @@
<Compile Include="EpisodeStatusTest.cs" /> <Compile Include="EpisodeStatusTest.cs" />
<Compile Include="ImportNewSeriesJobTest.cs" /> <Compile Include="ImportNewSeriesJobTest.cs" />
<Compile Include="DiskScanJobTest.cs" /> <Compile Include="DiskScanJobTest.cs" />
<Compile Include="IndexerTests.cs" />
<Compile Include="InventoryProviderTest.cs" /> <Compile Include="InventoryProviderTest.cs" />
<Compile Include="Framework\AutoMoq\AutoMoqer.cs" /> <Compile Include="Framework\AutoMoq\AutoMoqer.cs" />
<Compile Include="Framework\AutoMoq\AutoMoqerTest.cs" /> <Compile Include="Framework\AutoMoq\AutoMoqerTest.cs" />

@ -63,6 +63,9 @@ namespace NzbDrone.Core.Test
public void enteties_toString() public void enteties_toString()
{ {
Console.WriteLine(new Episode().ToString()); Console.WriteLine(new Episode().ToString());
Console.WriteLine(new Season().ToString());
Console.WriteLine(new Series().ToString());
Console.WriteLine(new EpisodeFile().ToString());
} }
[Test] [Test]

@ -53,12 +53,12 @@ namespace NzbDrone.Core
private static void InitializeApp() private static void InitializeApp()
{ {
BindKernel(); BindKernel();
LogConfiguration.Setup(); LogConfiguration.Setup();
Migrations.Run(); Migrations.Run();
ForceMigration(_kernel.Get<IRepository>()); ForceMigration(_kernel.Get<IRepository>());
SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up
BindIndexers(); BindIndexers();
@ -110,8 +110,6 @@ namespace NzbDrone.Core
_kernel.Bind<IndexerBase>().To<NzbMatrix>().InSingletonScope(); _kernel.Bind<IndexerBase>().To<NzbMatrix>().InSingletonScope();
_kernel.Bind<IndexerBase>().To<NzbsRUs>().InSingletonScope(); _kernel.Bind<IndexerBase>().To<NzbsRUs>().InSingletonScope();
_kernel.Bind<IndexerBase>().To<Newzbin>().InSingletonScope(); _kernel.Bind<IndexerBase>().To<Newzbin>().InSingletonScope();
var indexers = _kernel.GetAll<IndexerBase>();
_kernel.Get<IndexerProvider>().InitializeIndexers(indexers.ToList());
} }
private static void BindJobs() private static void BindJobs()

@ -96,7 +96,7 @@
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>Properties\AnalysisRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules> <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
@ -264,6 +264,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="Properties\AnalysisRules.ruleset" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Migrator.net\Migrator.Framework\Migrator.Framework.csproj"> <ProjectReference Include="..\Migrator.net\Migrator.Framework\Migrator.Framework.csproj">

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Copy of Microsoft Basic Correctness Rules" Description="These rules focus on logic errors and common mistakes made in the usage of framework APIs. Include this rule set to expand on the list of warnings reported by the minimum recommended rules." ToolsVersion="10.0">
<Include Path="minimumrecommendedrules.ruleset" Action="Default" />
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
<Rule Id="CA1008" Action="Warning" />
<Rule Id="CA1013" Action="Warning" />
<Rule Id="CA1301" Action="None" />
<Rule Id="CA1806" Action="Warning" />
<Rule Id="CA1816" Action="Warning" />
<Rule Id="CA1819" Action="Warning" />
<Rule Id="CA1820" Action="Warning" />
<Rule Id="CA1903" Action="Warning" />
<Rule Id="CA2004" Action="Warning" />
<Rule Id="CA2006" Action="Warning" />
<Rule Id="CA2101" Action="None" />
<Rule Id="CA2102" Action="Warning" />
<Rule Id="CA2105" Action="Warning" />
<Rule Id="CA2106" Action="Warning" />
<Rule Id="CA2115" Action="Warning" />
<Rule Id="CA2119" Action="Warning" />
<Rule Id="CA2120" Action="Warning" />
<Rule Id="CA2121" Action="Warning" />
<Rule Id="CA2122" Action="None" />
<Rule Id="CA2130" Action="Warning" />
<Rule Id="CA2205" Action="Warning" />
<Rule Id="CA2215" Action="Warning" />
<Rule Id="CA2221" Action="Warning" />
<Rule Id="CA2222" Action="Warning" />
<Rule Id="CA2223" Action="Warning" />
<Rule Id="CA2224" Action="Warning" />
<Rule Id="CA2226" Action="Warning" />
<Rule Id="CA2231" Action="Warning" />
<Rule Id="CA2239" Action="Warning" />
</Rules>
</RuleSet>

@ -6,7 +6,6 @@ using System.Web;
using NLog; using NLog;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers.Indexer namespace NzbDrone.Core.Providers.Indexer
{ {
@ -35,6 +34,15 @@ namespace NzbDrone.Core.Providers.Indexer
protected abstract string[] Urls { get; } protected abstract string[] Urls { get; }
/// <summary>
/// Gets the credential.
/// </summary>
protected virtual NetworkCredential Credentials
{
get { return null; }
}
/// <summary> /// <summary>
/// Gets the rss url for specific episode search /// Gets the rss url for specific episode search
/// </summary> /// </summary>
@ -45,13 +53,22 @@ namespace NzbDrone.Core.Providers.Indexer
protected abstract IList<String> GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber); protected abstract IList<String> GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber);
/// <summary> /// <summary>
/// Gets the credential. /// This method can be overwritten to provide indexer specific info parsing
/// </summary> /// </summary>
protected virtual NetworkCredential Credentials /// <param name="item">RSS item that needs to be parsed</param>
/// <param name="currentResult">Result of the built in parse function.</param>
/// <returns></returns>
protected virtual EpisodeParseResult CustomParser(SyndicationItem item, EpisodeParseResult currentResult)
{ {
get { return null; } return currentResult;
} }
/// <summary>
/// Generates direct link to download an NZB
/// </summary>
/// <param name = "item">RSS Feed item to generate the link for</param>
/// <returns>Download link URL</returns>
protected abstract string NzbDownloadUrl(SyndicationItem item);
/// <summary> /// <summary>
/// Fetches RSS feed and process each news item. /// Fetches RSS feed and process each news item.
@ -90,7 +107,7 @@ namespace NzbDrone.Core.Providers.Indexer
} }
private IList<EpisodeParseResult> Fetch(string url) private IEnumerable<EpisodeParseResult> Fetch(string url)
{ {
var result = new List<EpisodeParseResult>(); var result = new List<EpisodeParseResult>();
@ -140,23 +157,5 @@ namespace NzbDrone.Core.Providers.Indexer
return CustomParser(item, episodeParseResult); return CustomParser(item, episodeParseResult);
} }
/// <summary>
/// This method can be overwritten to provide indexer specific info parsing
/// </summary>
/// <param name="item">RSS item that needs to be parsed</param>
/// <param name="currentResult">Result of the built in parse function.</param>
/// <returns></returns>
protected virtual EpisodeParseResult CustomParser(SyndicationItem item, EpisodeParseResult currentResult)
{
return currentResult;
}
/// <summary>
/// Generates direct link to download an NZB
/// </summary>
/// <param name = "item">RSS Feed item to generate the link for</param>
/// <returns>Download link URL</returns>
protected abstract string NzbDownloadUrl(SyndicationItem item);
} }
} }

@ -13,6 +13,8 @@ namespace NzbDrone.Core.Providers
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly IRepository _repository; private readonly IRepository _repository;
private IList<IndexerBase> _indexers = new List<IndexerBase>();
public IndexerProvider(IRepository repository) public IndexerProvider(IRepository repository)
{ {
_repository = repository; _repository = repository;
@ -23,7 +25,13 @@ namespace NzbDrone.Core.Providers
} }
public virtual List<IndexerSetting> All() public virtual IList<IndexerBase> GetEnabledIndexers()
{
var all = GetAllISettings();
return _indexers.Where(i => all.Exists(c => c.IndexProviderType == i.GetType().ToString() && c.Enable)).ToList();
}
public virtual List<IndexerSetting> GetAllISettings()
{ {
return _repository.All<IndexerSetting>().ToList(); return _repository.All<IndexerSetting>().ToList();
} }
@ -47,23 +55,20 @@ namespace NzbDrone.Core.Providers
return _repository.Single<IndexerSetting>(s => s.IndexProviderType == type.ToString()); return _repository.Single<IndexerSetting>(s => s.IndexProviderType == type.ToString());
} }
public virtual IndexerSetting GetSettings(int id)
{
return _repository.Single<IndexerSetting>(s => s.Id == id);
}
public virtual void InitializeIndexers(IList<IndexerBase> indexers) public virtual void InitializeIndexers(IList<IndexerBase> indexers)
{ {
Logger.Info("Initializing indexers. Count {0}", indexers.Count); Logger.Info("Initializing indexers. Count {0}", indexers.Count);
var currentIndexers = All(); _indexers = indexers;
var currentIndexers = GetAllISettings();
foreach (var feedProvider in indexers) foreach (var feedProvider in indexers)
{ {
IndexerBase indexerLocal = feedProvider; IndexerBase indexerLocal = feedProvider;
if (!currentIndexers.Exists(c => c.IndexProviderType == indexerLocal.GetType().ToString())) if (!currentIndexers.Exists(c => c.IndexProviderType == indexerLocal.GetType().ToString()))
{ {
var settings = new IndexerSetting() var settings = new IndexerSetting
{ {
Enable = false, Enable = false,
IndexProviderType = indexerLocal.GetType().ToString(), IndexProviderType = indexerLocal.GetType().ToString(),

@ -5,12 +5,12 @@ using NLog;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
using NzbDrone.Core.Model.Notification; using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers.Indexer; using NzbDrone.Core.Providers.Indexer;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers.Jobs namespace NzbDrone.Core.Providers.Jobs
{ {
public class EpisodeSearchJob : IJob public class EpisodeSearchJob : IJob
{ {
private readonly IEnumerable<IndexerBase> _indexers;
private readonly InventoryProvider _inventoryProvider; private readonly InventoryProvider _inventoryProvider;
private readonly DownloadProvider _downloadProvider; private readonly DownloadProvider _downloadProvider;
private readonly IndexerProvider _indexerProvider; private readonly IndexerProvider _indexerProvider;
@ -19,9 +19,8 @@ namespace NzbDrone.Core.Providers.Jobs
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public EpisodeSearchJob(IEnumerable<IndexerBase> indexers, InventoryProvider inventoryProvider, DownloadProvider downloadProvider, IndexerProvider indexerProvider, EpisodeProvider episodeProvider) public EpisodeSearchJob(InventoryProvider inventoryProvider, DownloadProvider downloadProvider, IndexerProvider indexerProvider, EpisodeProvider episodeProvider)
{ {
_indexers = indexers;
_inventoryProvider = inventoryProvider; _inventoryProvider = inventoryProvider;
_downloadProvider = downloadProvider; _downloadProvider = downloadProvider;
_indexerProvider = indexerProvider; _indexerProvider = indexerProvider;
@ -42,9 +41,9 @@ namespace NzbDrone.Core.Providers.Jobs
{ {
var reports = new List<EpisodeParseResult>(); var reports = new List<EpisodeParseResult>();
var episode = _episodeProvider.GetEpisode(targetId); var episode = _episodeProvider.GetEpisode(targetId);
var indexers = _indexerProvider.GetEnabledIndexers();
foreach (var indexer in indexers)
foreach (var indexer in _indexers.Where(i => _indexerProvider.GetSettings(i.GetType()).Enable))
{ {
try try
{ {
@ -53,13 +52,18 @@ namespace NzbDrone.Core.Providers.Jobs
} }
catch (Exception e) catch (Exception e)
{ {
Logger.ErrorException("An error has occured while fetching items from " + indexer.Name, e); Logger.ErrorException("An error has occurred while fetching items from " + indexer.Name, e);
} }
} }
Logger.Debug("Finished searching all indexers. Total {0}", reports.Count); Logger.Debug("Finished searching all indexers. Total {0}", reports.Count);
notification.CurrentMessage = "Proccessing search results"; notification.CurrentMessage = "Processing search results";
ProcessResults(notification, episode, reports);
}
public void ProcessResults(ProgressNotification notification, Episode episode, IEnumerable<EpisodeParseResult> reports)
{
foreach (var episodeParseResult in reports.OrderBy(c => c.Quality).ThenBy(c => c.Proper)) foreach (var episodeParseResult in reports.OrderBy(c => c.Quality).ThenBy(c => c.Proper))
{ {
try try
@ -73,13 +77,11 @@ namespace NzbDrone.Core.Providers.Jobs
} }
catch (Exception e) catch (Exception e)
{ {
Logger.ErrorException("An error has occured while processing parse result items from " + episodeParseResult, e); Logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e);
} }
} }
Logger.Warn("Unable to find {0} in any of indexers.", episode); Logger.Warn("Unable to find {0} in any of indexers.", episode);
} }
} }
} }

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using NLog; using NLog;
@ -21,6 +22,8 @@ namespace NzbDrone.Core.Providers.Jobs
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private List<int> _attemptedSeries;
public ImportNewSeriesJob(SeriesProvider seriesProvider, SeasonProvider seasonProvider, public ImportNewSeriesJob(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
MediaFileProvider mediaFileProvider, UpdateInfoJob updateInfoJob, DiskScanJob diskScanJob) MediaFileProvider mediaFileProvider, UpdateInfoJob updateInfoJob, DiskScanJob diskScanJob)
{ {
@ -43,12 +46,13 @@ namespace NzbDrone.Core.Providers.Jobs
public void Start(ProgressNotification notification, int targetId) public void Start(ProgressNotification notification, int targetId)
{ {
_attemptedSeries = new List<int>();
ScanSeries(notification); ScanSeries(notification);
} }
private void ScanSeries(ProgressNotification notification) private void ScanSeries(ProgressNotification notification)
{ {
var syncList = _seriesProvider.GetAllSeries().Where(s => s.LastInfoSync == null).ToList(); var syncList = _seriesProvider.GetAllSeries().Where(s => s.LastInfoSync == null && !_attemptedSeries.Contains(s.SeriesId)).ToList();
if (syncList.Count == 0) if (syncList.Count == 0)
{ {
return; return;
@ -58,6 +62,7 @@ namespace NzbDrone.Core.Providers.Jobs
{ {
try try
{ {
_attemptedSeries.Add(currentSeries.SeriesId);
notification.CurrentMessage = String.Format("Searching for '{0}'", new DirectoryInfo(currentSeries.Path).Name); notification.CurrentMessage = String.Format("Searching for '{0}'", new DirectoryInfo(currentSeries.Path).Name);
_updateInfoJob.Start(notification, currentSeries.SeriesId); _updateInfoJob.Start(notification, currentSeries.SeriesId);

@ -72,10 +72,12 @@ namespace NzbDrone.Core.Repository
public override string ToString() public override string ToString()
{ {
var seriesTitle = Series == null ? "[NULL]" : Series.Title;
if (EpisodeNumber == 0) if (EpisodeNumber == 0)
return string.Format("{0} - {1}", Series.Title, AirDate.Date); return string.Format("{0} - {1}", seriesTitle, AirDate.Date);
return string.Format("{0} - S{1:00}E{2}", Series.Title, SeasonNumber, EpisodeNumber); return string.Format("{0} - S{1:00}E{2}", seriesTitle, SeasonNumber, EpisodeNumber);
} }
} }

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace NzbDrone.Web.Controllers
{
public class StreamController : Controller
{
//
// GET: /Stream/
public ActionResult Index()
{
return File(@"Z:\Clone High\Season 1\S01E02 - Episode Two- Election Blu-Galoo.avi", "video/divx");
//return File(@"Z:\30 Rock\Season 5\S05E04 - Live Show (East Coast Taping) - HD TV.mkv", "video/divx");
}
}
}

@ -26,7 +26,7 @@ namespace NzbDrone.Web.Controllers
public ActionResult Indexers() public ActionResult Indexers()
{ {
return View(_indexerProvider.All()); return View(_indexerProvider.GetAllISettings());
} }

@ -31,6 +31,7 @@
<MvcBuildViews>true</MvcBuildViews> <MvcBuildViews>true</MvcBuildViews>
<EnableUpdateable>false</EnableUpdateable> <EnableUpdateable>false</EnableUpdateable>
<ExcludeApp_Data>true</ExcludeApp_Data> <ExcludeApp_Data>true</ExcludeApp_Data>
<CodeAnalysisRuleSet>BasicCorrectnessRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
@ -223,6 +224,7 @@
<Compile Include="Controllers\SeriesController.cs" /> <Compile Include="Controllers\SeriesController.cs" />
<Compile Include="Controllers\SettingsController.cs" /> <Compile Include="Controllers\SettingsController.cs" />
<Compile Include="Controllers\SharedController.cs" /> <Compile Include="Controllers\SharedController.cs" />
<Compile Include="Controllers\StreamController.cs" />
<Compile Include="Controllers\SystemController.cs" /> <Compile Include="Controllers\SystemController.cs" />
<Compile Include="Controllers\UpcomingController.cs" /> <Compile Include="Controllers\UpcomingController.cs" />
<Compile Include="Global.asax.cs"> <Compile Include="Global.asax.cs">

@ -39,6 +39,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<UseVSHostingProcess>true</UseVSHostingProcess> <UseVSHostingProcess>true</UseVSHostingProcess>
<CodeAnalysisRuleSet>BasicCorrectnessRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>

Loading…
Cancel
Save