Revered back to subsonic

Added indexer configuration back-end
This commit is contained in:
Keivan 2011-04-18 17:12:06 -07:00
parent 129be92001
commit 6f2dcbf838
20 changed files with 368 additions and 478 deletions

View File

@ -17,25 +17,17 @@ namespace NzbDrone.Core.Test
public void AllItems()
{
//Setup
var indexer = new Indexer
{
Enabled = true,
IndexerId = 0,
IndexerName = "NzbMatrix",
Order = 1,
RssUrl = "http://www.nzbmatrix.com"
};
var series = new Series
{
SeriesId = 5656,
CleanTitle = "rock",
Monitored = true,
Overview = "Series Overview",
QualityProfileId = 1,
Title = "30 Rock",
Path = @"C:\Test\TV\30 Rock"
};
var season = new Season {SeasonId = 4321, SeasonNumber = 1, SeriesId = 5656, Monitored = true};
{
SeriesId = 5656,
CleanTitle = "rock",
Monitored = true,
Overview = "Series Overview",
QualityProfileId = 1,
Title = "30 Rock",
Path = @"C:\Test\TV\30 Rock"
};
var season = new Season { SeasonId = 4321, SeasonNumber = 1, SeriesId = 5656, Monitored = true };
var episode = new Episode
{
AirDate = DateTime.Today.AddDays(-1),
@ -56,7 +48,6 @@ namespace NzbDrone.Core.Test
Date = DateTime.Now,
IsProper = false,
Quality = QualityTypes.TV,
IndexerId = indexer.IndexerId,
EpisodeId = episode.EpisodeId
});
@ -78,13 +69,6 @@ namespace NzbDrone.Core.Test
{
//Todo: This test fails... Moq Setup doesn't return the expected value
//Setup
var indexer = new Indexer
{
Enabled = true,
IndexerName = "NzbMatrix",
Order = 1,
RssUrl = "http://www.nzbmatrix.com"
};
var series = new Series
{
SeriesId = 5656,
@ -95,7 +79,7 @@ namespace NzbDrone.Core.Test
Title = "30 Rock",
Path = @"C:\Test\TV\30 Rock"
};
var season = new Season {SeasonId = 4321, SeasonNumber = 1, SeriesId = 5656, Monitored = true};
var season = new Season { SeasonId = 4321, SeasonNumber = 1, SeriesId = 5656, Monitored = true };
var episode = new Episode
{
AirDate = DateTime.Today.AddDays(-1),
@ -116,7 +100,6 @@ namespace NzbDrone.Core.Test
Date = DateTime.Now,
IsProper = false,
Quality = QualityTypes.TV,
IndexerId = indexer.IndexerId,
EpisodeId = episode.EpisodeId
});
@ -142,24 +125,17 @@ namespace NzbDrone.Core.Test
//Todo: This test fails... Moq Setup doesn't return the expected value
//Setup
var indexer = new Indexer
{
Enabled = true,
IndexerName = "NzbMatrix",
Order = 1,
RssUrl = "http://www.nzbmatrix.com"
};
var series = new Series
{
SeriesId = 5656,
CleanTitle = "rock",
Monitored = true,
Overview = "Series Overview",
QualityProfileId = 1,
Title = "30 Rock",
Path = @"C:\Test\TV\30 Rock"
};
var season = new Season {SeasonId = 4321, SeasonNumber = 1, SeriesId = 5656, Monitored = true};
{
SeriesId = 5656,
CleanTitle = "rock",
Monitored = true,
Overview = "Series Overview",
QualityProfileId = 1,
Title = "30 Rock",
Path = @"C:\Test\TV\30 Rock"
};
var season = new Season { SeasonId = 4321, SeasonNumber = 1, SeriesId = 5656, Monitored = true };
var episode = new Episode
{
AirDate = DateTime.Today.AddDays(-1),
@ -180,7 +156,6 @@ namespace NzbDrone.Core.Test
Date = DateTime.Now,
IsProper = false,
Quality = QualityTypes.TV,
IndexerId = indexer.IndexerId,
EpisodeId = episode.EpisodeId
});

View File

@ -1,9 +1,15 @@
using System.Collections.Generic;
using System.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.ServiceModel.Syndication;
using System.Xml;
using AutoMoq;
using FizzWare.NBuilder;
using MbUnit.Framework;
using Moq;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Indexer;
using NzbDrone.Core.Repository;
using SubSonic.Repository;
@ -11,69 +17,65 @@ namespace NzbDrone.Core.Test
{
[TestFixture]
public class IndexerProviderTest
// ReSharper disable InconsistentNaming
{
[Test]
public void AllIndexers()
public void Download_feed_test()
{
//
// TODO: Add test logic here
//
var mocker = new AutoMoqer();
//Setup
var list = new List<Indexer>();
list.Add(new Indexer
{IndexerName = "Test1", RssUrl = "http://www.test1.com/rss.php", Enabled = true, Order = 1});
list.Add(new Indexer
{IndexerName = "Test2", RssUrl = "http://www.test2.com/rss.php", Enabled = false, Order = 4});
list.Add(new Indexer
{IndexerName = "Test3", RssUrl = "http://www.test3.com/rss.php", Enabled = true, Order = 3});
list.Add(new Indexer
{IndexerName = "Test4", RssUrl = "http://www.test4.com/rss.php", Enabled = false, Order = 2});
var xmlReader = XmlReader.Create(File.OpenRead(".\\Files\\Rss\\nzbsorg.xml"));
var repo = new Mock<IRepository>();
var config = new Mock<ConfigProvider>();
repo.Setup(r => r.All<Indexer>()).Returns(list.AsQueryable());
mocker.GetMock<HttpProvider>()
.Setup(h => h.DownloadXml(It.IsAny<String>()))
.Returns(xmlReader);
var target = new IndexerProvider(repo.Object, config.Object);
var fakeSettings = Builder<IndexerSetting>.CreateNew().Build();
mocker.GetMock<IndexerProvider>()
.Setup(c => c.GetSettings(It.IsAny<Type>()))
.Returns(fakeSettings);
//Act
var result = target.AllIndexers();
//Assert
Assert.AreEqual(result.Last().IndexerName, "Test2");
mocker.Resolve<MockIndexerProvider>().Fetch();
}
[Test]
public void EnabledIndexers()
public void Init_indexer_test()
{
//
// TODO: Add test logic here
//
var mocker = new AutoMoqer();
//Setup
var list = new List<Indexer>();
list.Add(new Indexer
{IndexerName = "Test1", RssUrl = "http://www.test1.com/rss.php", Enabled = true, Order = 1});
list.Add(new Indexer
{IndexerName = "Test2", RssUrl = "http://www.test2.com/rss.php", Enabled = false, Order = 4});
list.Add(new Indexer
{IndexerName = "Test3", RssUrl = "http://www.test3.com/rss.php", Enabled = true, Order = 3});
list.Add(new Indexer
{IndexerName = "Test4", RssUrl = "http://www.test4.com/rss.php", Enabled = false, Order = 2});
var repo = new Mock<IRepository>();
var config = new Mock<ConfigProvider>();
repo.Setup(r => r.All<Indexer>()).Returns(list.AsQueryable());
var target = new IndexerProvider(repo.Object, config.Object);
mocker.SetConstant(MockLib.GetEmptyRepository());
//Act
var result = target.EnabledIndexers();
var indexerProvider = mocker.Resolve<IndexerProvider>();
indexerProvider.InitializeIndexers(new List<IndexerProviderBase>() { mocker.Resolve<MockIndexerProvider>() });
var indexers = indexerProvider.AllIndexers();
//Assert
Assert.AreEqual(result.First().IndexerName, "Test1");
Assert.AreEqual(result.Last().IndexerName, "Test3");
Assert.Count(1, indexers);
}
}
public class MockIndexerProvider : IndexerProviderBase
{
public MockIndexerProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider, EpisodeProvider episodeProvider, ConfigProvider configProvider, HttpProvider httpProvider, IRepository repository, IndexerProvider indexerProvider)
: base(seriesProvider, seasonProvider, episodeProvider, configProvider, httpProvider, repository, indexerProvider)
{
}
protected override string[] Url
{
get { return new[] { "www.google.com" }; }
}
public override string Name
{
get { return "Mocked Indexer"; }
}
protected override string NzbDownloadUrl(SyndicationItem item)
{
return item.Links[0].Uri.ToString();
}
}
}

View File

@ -95,7 +95,7 @@
</Compile>
<Compile Include="SyncProviderTest.cs" />
<Compile Include="RootDirProviderTest.cs" />
<Compile Include="RssProviderTest.cs" />
<Compile Include="IndexerProviderTest.cs" />
<Compile Include="HistoryProviderTest.cs" />
<Compile Include="MediaFileProviderTests.cs" />
<Compile Include="DbConfigControllerTest.cs" />
@ -111,7 +111,6 @@
<Compile Include="RepoTest.cs" />
<Compile Include="SabControllerTest.cs" />
<Compile Include="SeriesProviderTest.cs" />
<Compile Include="IndexerProviderTest.cs" />
<Compile Include="TvDbControllerTest.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -65,9 +65,9 @@ namespace NzbDrone.Core.Test
}
[Test]
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, new[] {2, 3, 4, 5, 6})]
[Row("Two.and.a.Half.Me.103.104.720p.HDTV.X264-DIMENSION", 1, new[] {3, 4})]
[Row("The.Kennedys.Part.1.and.Part.2.DSR.XviD-SYS", 1, new[] {1, 2})]
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, new[] { 2, 3, 4, 5, 6 })]
//[Row("Two.and.a.Half.Men.103.104.720p.HDTV.X264-DIMENSION", 1, new[] {3, 4})]
//[Row("The.Kennedys.Part.1.and.Part.2.DSR.XviD-SYS", 1, new[] {1, 2})]
public void episode_multipart_parse(string path, int season, int[] episodes)
{
var result = Parser.ParseEpisodeInfo(path);

View File

@ -1,57 +0,0 @@
using System;
using System.IO;
using System.ServiceModel.Syndication;
using System.Xml;
using AutoMoq;
using MbUnit.Framework;
using Moq;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Feed;
namespace NzbDrone.Core.Test
{
[TestFixture]
public class RssProviderTest
// ReSharper disable InconsistentNaming
{
[Test]
public void Download_feed_test()
{
var mocker = new AutoMoqer();
var xmlReader = XmlReader.Create(File.OpenRead(".\\Files\\Rss\\nzbsorg.xml"));
mocker.GetMock<HttpProvider>()
.Setup(h => h.DownloadXml(It.IsAny<String>()))
.Returns(xmlReader);
mocker.Resolve<MockFeedProvider>().Fetch();
}
}
public class MockFeedProvider : FeedProviderBase
{
public MockFeedProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
EpisodeProvider episodeProvider, ConfigProvider configProvider,
HttpProvider httpProvider)
: base(seriesProvider, seasonProvider, episodeProvider, configProvider, httpProvider)
{
}
protected override string[] URL
{
get { return new[] {"www.google.com"}; }
}
protected override string Name
{
get { return "MyName"; }
}
protected override string NzbDownloadUrl(SyndicationItem item)
{
return item.Links[0].Uri.ToString();
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -8,6 +9,7 @@ using NLog;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Indexer;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using SubSonic.DataProviders;
@ -72,7 +74,7 @@ namespace NzbDrone.Core
_startupPath = AppPath;
//Sqlite
var AppDataPath = new DirectoryInfo(Path.Combine(AppPath, "App_Data", "nzbdrone.db"));
var AppDataPath = new DirectoryInfo(Path.Combine(AppPath, "App_Data"));
if (!AppDataPath.Exists) AppDataPath.Create();
string connectionString = String.Format("Data Source={0};Version=3;",
@ -109,12 +111,12 @@ namespace NzbDrone.Core
_kernel.Bind<PostProcessingProvider>().ToSelf().InSingletonScope();
_kernel.Bind<ConfigProvider>().To<ConfigProvider>().InSingletonScope();
_kernel.Bind<SyncProvider>().ToSelf().InSingletonScope();
_kernel.Bind<IndexerProvider>().ToSelf().InSingletonScope();
_kernel.Bind<RenameProvider>().ToSelf().InSingletonScope();
_kernel.Bind<NotificationProvider>().ToSelf().InSingletonScope();
_kernel.Bind<LogProvider>().ToSelf().InSingletonScope();
_kernel.Bind<MediaFileProvider>().ToSelf().InSingletonScope();
_kernel.Bind<TimerProvider>().ToSelf().InSingletonScope();
_kernel.Bind<IndexerProvider>().ToSelf().InSingletonScope();
_kernel.Bind<IRepository>().ToMethod(
c => new SimpleRepository(dbProvider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope();
@ -123,7 +125,6 @@ namespace NzbDrone.Core
_kernel.Bind<IRepository>().ToConstant(logRepository).WhenInjectedInto<LogProvider>().InSingletonScope();
ForceMigration(_kernel.Get<IRepository>());
SetupIndexers(_kernel.Get<IRepository>()); //Setup the default set of indexers on start-up
SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up
//Get the Timers going
@ -131,9 +132,18 @@ namespace NzbDrone.Core
var timer = _kernel.Get<TimerProvider>();
timer.SetRssSyncTimer(Convert.ToInt32(config.GetValue("SyncFrequency", "15", true)));
timer.StartRssSyncTimer();
BindIndexers();
}
}
private static void BindIndexers()
{
_kernel.Bind<IndexerProviderBase>().To<NzbsOrgProvider>().InSingletonScope();
var indexers = _kernel.GetAll<IndexerProviderBase>();
_kernel.Get<IndexerProvider>().InitializeIndexers(indexers.ToList());
}
private static void ForceMigration(IRepository repository)
{
repository.GetPaged<Series>(0, 1);
@ -141,7 +151,6 @@ namespace NzbDrone.Core
repository.GetPaged<Episode>(0, 1);
repository.GetPaged<Season>(0, 1);
repository.GetPaged<History>(0, 1);
repository.GetPaged<Indexer>(0, 1);
}
/// <summary>
@ -154,7 +163,7 @@ namespace NzbDrone.Core
Logger.Debug("Attaching to parent process for automatic termination.");
var pc = new PerformanceCounter("Process", "Creating Process ID",
Process.GetCurrentProcess().ProcessName);
var pid = (int) pc.NextValue();
var pid = (int)pc.NextValue();
var hostProcess = Process.GetProcessById(pid);
hostProcess.EnableRaisingEvents = true;
@ -178,104 +187,13 @@ namespace NzbDrone.Core
Process.GetCurrentProcess().Kill();
}
private static void SetupIndexers(IRepository repository)
{
//Setup the default providers in the Providers table
string nzbMatrixRss =
"http://rss.nzbmatrix.com/rss.php?page=download&username={USERNAME}&apikey={APIKEY}&subcat=6,41&english=1";
string nzbMatrixApi =
"http://rss.nzbmatrix.com/rss.php?page=download&username={USERNAME}&apikey={APIKEY}&subcat=6,41&english=1&age={AGE}&term={TERM}";
string nzbsOrgRss = "http://nzbs.org/rss.php?type=1&dl=1&num=100&i={UID}&h={HASH}";
string nzbsOrgApi = String.Empty;
string nzbsrusRss = "http://www.nzbsrus.com/rssfeed.php?cat=91,75&i={UID}&h={HASH}";
string nzbsrusApi = String.Empty;
var nzbMatrixIndexer = new Indexer
{
IndexerId = 1,
IndexerName = "NzbMatrix",
RssUrl = nzbMatrixRss,
ApiUrl = nzbMatrixApi,
Order = 1
};
var nzbsOrgIndexer = new Indexer
{
IndexerId = 2,
IndexerName = "NzbsOrg",
RssUrl = nzbsOrgRss,
ApiUrl = nzbsOrgApi,
Order = 2
};
var nzbsrusIndexer = new Indexer
{
IndexerId = 3,
IndexerName = "Nzbsrus",
RssUrl = nzbsrusRss,
ApiUrl = nzbsrusApi,
Order = 3
};
//NzbMatrix
Logger.Debug("Checking for NzbMatrix Indexer");
var nzbMatix = repository.Single<Indexer>(1);
if (nzbMatix == null)
{
Logger.Debug("Adding new Indexer: NzbMatrix");
repository.Add(nzbMatrixIndexer);
}
else
{
Logger.Debug("Updating Indexer: NzbMatrix");
nzbMatix.RssUrl = nzbMatrixIndexer.RssUrl;
nzbMatix.ApiUrl = nzbMatrixIndexer.ApiUrl;
repository.Update(nzbMatix);
}
//Nzbs.org
Logger.Debug("Checking for Nzbs.org");
var nzbsOrg = repository.Single<Indexer>(2);
if (nzbsOrg == null)
{
Logger.Debug("Adding new Indexer: Nzbs.org");
repository.Add(nzbsOrgIndexer);
}
else
{
Logger.Debug("Updating Indexer: Nzbs.org");
nzbsOrg.RssUrl = nzbsOrgIndexer.RssUrl;
nzbsOrg.ApiUrl = nzbsOrgIndexer.ApiUrl;
repository.Update(nzbsOrg);
}
//Nzbsrus
Logger.Debug("Checking for Nzbsrus");
var nzbsrus = repository.Single<Indexer>(3);
if (nzbsrus == null)
{
Logger.Debug("Adding new Indexer: Nzbsrus");
repository.Add(nzbsrusIndexer);
}
else
{
Logger.Debug("Updating Indexer: Nzbsrus");
nzbsrus.RssUrl = nzbsOrgIndexer.RssUrl;
nzbsrus.ApiUrl = nzbsOrgIndexer.ApiUrl;
repository.Update(nzbsrus);
}
}
private static void SetupDefaultQualityProfiles(IRepository repository)
{
var sd = new QualityProfile
{
Name = "SD",
Allowed = new List<QualityTypes> {QualityTypes.TV, QualityTypes.DVD},
Allowed = new List<QualityTypes> { QualityTypes.TV, QualityTypes.DVD },
Cutoff = QualityTypes.TV
};
@ -283,8 +201,7 @@ namespace NzbDrone.Core
{
Name = "HD",
Allowed =
new List<QualityTypes>
{QualityTypes.HDTV, QualityTypes.WEBDL, QualityTypes.BDRip, QualityTypes.Bluray720},
new List<QualityTypes> { QualityTypes.HDTV, QualityTypes.WEBDL, QualityTypes.BDRip, QualityTypes.Bluray720 },
Cutoff = QualityTypes.HDTV
};

View File

@ -139,6 +139,7 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>Libraries\NLog.Extended.dll</HintPath>
</Reference>
<Reference Include="NzbDrone.Core, Version=0.2.0.35870, Culture=neutral, processorArchitecture=MSIL" />
<Reference Include="SubSonic.Core, Version=3.0.0.3, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>Libraries\SubSonic.Core.dll</HintPath>
@ -168,6 +169,7 @@
<Compile Include="Instrumentation\SubsonicTarget.cs" />
<Compile Include="Instrumentation\ExceptioneerTarget.cs" />
<Compile Include="Instrumentation\NlogWriter.cs" />
<Compile Include="Repository\IndexerSetting.cs" />
<Compile Include="Model\EpisodeParseResult.cs" />
<Compile Include="Model\EpisodeRenameModel.cs" />
<Compile Include="Model\EpisodeSortingType.cs" />
@ -177,9 +179,9 @@
<Compile Include="Model\SceneNameModel.cs" />
<Compile Include="Model\SeasonParseResult.cs" />
<Compile Include="Model\UpcomingEpisodesModel.cs" />
<Compile Include="Providers\Feed\FeedProviderBase.cs" />
<Compile Include="Providers\Indexer\IndexerProviderBase.cs" />
<Compile Include="Providers\ExternalNotificationProvider.cs" />
<Compile Include="Providers\Feed\NzbsOrgFeedProvider.cs" />
<Compile Include="Providers\Indexer\NzbsOrgProvider.cs" />
<Compile Include="Providers\HistoryProvider.cs" />
<Compile Include="Providers\BacklogProvider.cs" />
<Compile Include="Providers\IndexerProvider.cs" />
@ -210,7 +212,6 @@
<Compile Include="Repository\Episode.cs" />
<Compile Include="Instrumentation\Log.cs" />
<Compile Include="Repository\History.cs" />
<Compile Include="Repository\Indexer.cs" />
<Compile Include="Repository\Config.cs" />
<Compile Include="Repository\Quality\QualityProfile.cs" />
<Compile Include="Repository\RootDir.cs" />

View File

@ -1,37 +0,0 @@
using System.ServiceModel.Syndication;
using NzbDrone.Core.Providers.Core;
namespace NzbDrone.Core.Providers.Feed
{
internal class NzbsOrgFeedProvider : FeedProviderBase
{
public NzbsOrgFeedProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
EpisodeProvider episodeProvider, ConfigProvider configProvider,
HttpProvider httpProvider)
: base(seriesProvider, seasonProvider, episodeProvider, configProvider, httpProvider)
{
}
protected override string[] URL
{
get
{
return new[]
{
string.Format("http://nzbs.org/rss.php?type=1&i={0}&h={1}", _configProvider.NzbsOrgUId,
_configProvider.NzbsOrgHash)
};
}
}
protected override string Name
{
get { return "Nzbs.Org"; }
}
protected override string NzbDownloadUrl(SyndicationItem item)
{
return item.Id.Replace("action=view", "action=getnzb");
}
}
}

View File

@ -2,39 +2,45 @@
using NLog;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using SubSonic.Repository;
namespace NzbDrone.Core.Providers.Feed
namespace NzbDrone.Core.Providers.Indexer
{
public abstract class FeedProviderBase
public abstract class IndexerProviderBase
{
protected static readonly Logger Logger = LogManager.GetCurrentClassLogger();
protected readonly ConfigProvider _configProvider;
protected readonly EpisodeProvider _episodeProvider;
private readonly HttpProvider _httpProvider;
protected readonly IRepository _repository;
private readonly IndexerProvider _indexerProvider;
protected readonly SeasonProvider _seasonProvider;
protected readonly SeriesProvider _seriesProvider;
public FeedProviderBase(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
public IndexerProviderBase(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
EpisodeProvider episodeProvider, ConfigProvider configProvider,
HttpProvider httpProvider)
HttpProvider httpProvider, IRepository repository, IndexerProvider indexerProvider)
{
_seriesProvider = seriesProvider;
_seasonProvider = seasonProvider;
_episodeProvider = episodeProvider;
_configProvider = configProvider;
_httpProvider = httpProvider;
_repository = repository;
_indexerProvider = indexerProvider;
}
/// <summary>
/// Gets the source URL for the feed
/// </summary>
protected abstract string[] URL { get; }
protected abstract string[] Url { get; }
/// <summary>
/// Gets the name for this feed
/// Gets the name for the feed
/// </summary>
protected abstract string Name { get; }
public abstract string Name { get; }
/// <summary>
@ -74,9 +80,9 @@ namespace NzbDrone.Core.Providers.Feed
/// </summary>
public void Fetch()
{
Logger.Info("Fetching feeds from " + Name);
Logger.Info("Fetching feeds from " + Settings.Name);
foreach (var url in URL)
foreach (var url in Url)
{
Logger.Debug("Downloading RSS " + url);
var feed = SyndicationFeed.Load(_httpProvider.DownloadXml(url)).Items;
@ -87,7 +93,7 @@ namespace NzbDrone.Core.Providers.Feed
}
}
Logger.Info("Finished processing feeds from " + Name);
Logger.Info("Finished processing feeds from " + Settings.Name);
}
private void ProcessItem(SyndicationItem feedItem)
@ -119,5 +125,17 @@ namespace NzbDrone.Core.Providers.Feed
}
}
}
protected IndexerSetting Settings
{
get
{
return _indexerProvider.GetSettings(GetType());
}
}
}
}

View File

@ -0,0 +1,38 @@
using System.ServiceModel.Syndication;
using NzbDrone.Core.Providers.Core;
using SubSonic.Repository;
namespace NzbDrone.Core.Providers.Indexer
{
public class NzbsOrgProvider : IndexerProviderBase
{
public NzbsOrgProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider, EpisodeProvider episodeProvider, ConfigProvider configProvider, HttpProvider httpProvider, IRepository repository, IndexerProvider indexerProvider)
: base(seriesProvider, seasonProvider, episodeProvider, configProvider, httpProvider, repository, indexerProvider)
{
}
protected override string[] Url
{
get
{
return new[]
{
string.Format("http://nzbs.org/rss.php?type=1&i={0}&h={1}", _configProvider.NzbsOrgUId, _configProvider.NzbsOrgHash)
};
}
}
public override string Name
{
get { return "Nzbs.org"; }
}
protected override string NzbDownloadUrl(SyndicationItem item)
{
return item.Id.Replace("action=view", "action=getnzb");
}
}
}

View File

@ -1,7 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Indexer;
using NzbDrone.Core.Repository;
using SubSonic.Repository;
@ -10,33 +12,70 @@ namespace NzbDrone.Core.Providers
public class IndexerProvider
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly ConfigProvider _configProvider;
private readonly IRepository _sonicRepo;
private readonly IRepository _repository;
public IndexerProvider(IRepository sonicRepo, ConfigProvider configProvider)
public IndexerProvider(IRepository repository)
{
_sonicRepo = sonicRepo;
_configProvider = configProvider;
_repository = repository;
}
public virtual List<Indexer> AllIndexers()
public IndexerProvider()
{
return _sonicRepo.All<Indexer>().OrderBy(i => i.Order).ToList();
}
public virtual List<Indexer> EnabledIndexers()
public virtual List<IndexerSetting> AllIndexers()
{
return _sonicRepo.All<Indexer>().Where(i => i.Enabled).OrderBy(i => i.Order).ToList();
return _repository.All<IndexerSetting>().ToList();
}
public virtual void Update(Indexer indexer)
public virtual void SaveSettings(IndexerSetting settings)
{
_sonicRepo.Update(indexer);
if (settings.Id == 0)
{
Logger.Debug("Adding Indexer settings for {0}", settings.Name);
_repository.Add(settings);
}
else
{
Logger.Debug("Updating Indexer settings for {0}", settings.Name);
_repository.Update(settings);
}
}
public virtual Indexer Single(int indexerId)
public virtual IndexerSetting GetSettings(Type type)
{
return _sonicRepo.Single<Indexer>(indexerId);
return _repository.Single<IndexerSetting>(s => s.IndexProviderType == type.ToString());
}
public IndexerSetting GetSettings(int id)
{
return _repository.Single<IndexerSetting>(s => s.Id == id);
}
public virtual void InitializeIndexers(IList<IndexerProviderBase> indexers)
{
Logger.Info("Initializing indexers. Count {0}", indexers.Count);
var currentIndexers = AllIndexers();
foreach (var feedProvider in indexers)
{
IndexerProviderBase indexerProviderLocal = feedProvider;
if (!currentIndexers.Exists(c => c.IndexProviderType == indexerProviderLocal.GetType().ToString()))
{
var settings = new IndexerSetting()
{
Enable = false,
IndexProviderType = indexerProviderLocal.GetType().ToString(),
Name = indexerProviderLocal.Name
};
SaveSettings(settings);
}
}
}
}
}

View File

@ -10,7 +10,6 @@ namespace NzbDrone.Core.Repository
public virtual int HistoryId { get; set; }
public virtual int EpisodeId { get; set; }
public virtual int IndexerId { get; set; }
public string NzbTitle { get; set; }
public QualityTypes Quality { get; set; }
public DateTime Date { get; set; }
@ -19,7 +18,5 @@ namespace NzbDrone.Core.Repository
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual Episode Episode { get; private set; }
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual Indexer Indexer { get; private set; }
}
}

View File

@ -1,25 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Repository
{
public class Indexer
{
[SubSonicPrimaryKey]
public virtual int IndexerId { get; set; }
public string IndexerName { get; set; }
public string RssUrl { get; set; }
[SubSonicNullStringAttribute]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string ApiUrl { get; set; }
public bool Enabled { get; set; }
public int Order { get; set; }
[SubSonicToManyRelation]
public virtual List<History> Histories { get; private set; }
}
}

View File

@ -0,0 +1,17 @@
using System;
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Repository
{
public class IndexerSetting
{
[SubSonicPrimaryKey(true)]
public int Id { get; set; }
public Boolean Enable { get; set; }
public String IndexProviderType { get; set; }
public String Name { get; set; }
}
}

View File

@ -7,6 +7,7 @@ using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model;
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.Web.Models;
@ -63,11 +64,15 @@ namespace NzbDrone.Web.Controllers
_configProvider.GetValue("NzbMatrixUsername", String.Empty, true),
NzbMatrixApiKey =
_configProvider.GetValue("NzbMatrixApiKey", String.Empty, true),
NzbsOrgUId = _configProvider.GetValue("NzbsOrgUId", String.Empty, true),
NzbsOrgHash = _configProvider.GetValue("NzbsOrgHash", String.Empty, true),
NzbsrusUId = _configProvider.GetValue("NzbsrusUId", String.Empty, true),
NzbsrusHash = _configProvider.GetValue("NzbsrusHash", String.Empty, true),
NzbsOrgHash = _configProvider.NzbsrusHash,
NzbsOrgUId = _configProvider.NzbsrusUId,
Indexers = _indexerProvider.AllIndexers()
});
}
@ -89,7 +94,7 @@ namespace NzbDrone.Web.Controllers
SabTvCategory = _configProvider.GetValue("SabTvCategory", String.Empty, true),
SabTvPriority =
(SabnzbdPriorityType)
Enum.Parse(typeof (SabnzbdPriorityType),
Enum.Parse(typeof(SabnzbdPriorityType),
_configProvider.GetValue("SabTvPriority", "Normal", true)),
UseBlackHole = Convert.ToBoolean(_configProvider.GetValue("UseBlackHole", true, true)),
BlackholeDirectory = _configProvider.GetValue("BlackholeDirectory", String.Empty, true)
@ -104,7 +109,7 @@ namespace NzbDrone.Web.Controllers
var qualityTypes = new List<QualityTypes>();
foreach (QualityTypes qual in Enum.GetValues(typeof (QualityTypes)))
foreach (QualityTypes qual in Enum.GetValues(typeof(QualityTypes)))
{
qualityTypes.Add(qual);
}
@ -192,14 +197,14 @@ namespace NzbDrone.Web.Controllers
{
var qualityTypes = new List<QualityTypes>();
foreach (QualityTypes qual in Enum.GetValues(typeof (QualityTypes)))
foreach (QualityTypes qual in Enum.GetValues(typeof(QualityTypes)))
{
qualityTypes.Add(qual);
}
ViewData["Qualities"] = qualityTypes;
return View("UserProfileSection", new QualityProfile {Name = "New Profile", UserProfile = true});
return View("UserProfileSection", new QualityProfile { Name = "New Profile", UserProfile = true });
}
public ViewResult AddRootDir()
@ -219,7 +224,7 @@ namespace NzbDrone.Web.Controllers
Convert.ToInt32(_configProvider.GetValue("DefaultQualityProfile", profiles[0].QualityProfileId, true));
var selectList = new SelectList(profiles, "QualityProfileId", "Name");
return new QualityModel {DefaultQualityProfileId = defaultQualityQualityProfileId, SelectList = selectList};
return new QualityModel { DefaultQualityProfileId = defaultQualityQualityProfileId, SelectList = selectList };
}
[HttpPost]
@ -263,17 +268,23 @@ namespace NzbDrone.Web.Controllers
{
if (ModelState.IsValid)
{
//Todo: Only allow indexers to be enabled if user information has been provided
foreach (var indexer in data.Indexers)
_indexerProvider.Update(indexer);
{
var setting =_indexerProvider.GetSettings(indexer.Id);
setting.Enable = indexer.Enable;
_indexerProvider.SaveSettings(setting);
}
_configProvider.NzbMatrixUsername = data.NzbMatrixUsername;
_configProvider.NzbMatrixApiKey = data.NzbMatrixApiKey;
_configProvider.NzbsOrgUId = data.NzbsOrgUId;
_configProvider.NzbsOrgHash = data.NzbsOrgHash;
_configProvider.NzbsrusUId = data.NzbsrusUId;
_configProvider.NzbsrusHash = data.NzbsrusHash;
var nzbsOrgSettings = _indexerProvider.GetSettings(typeof(NzbsOrgProvider));
_configProvider.NzbsrusHash = data.NzbsOrgHash;
_configProvider.NzbsOrgUId = data.NzbsOrgUId;
return Content(SETTINGS_SAVED);
}
@ -328,7 +339,7 @@ namespace NzbDrone.Web.Controllers
profile.Allowed = new List<QualityTypes>();
foreach (var quality in profile.AllowedString.Split(','))
{
var qType = (QualityTypes) Enum.Parse(typeof (QualityTypes), quality);
var qType = (QualityTypes)Enum.Parse(typeof(QualityTypes), quality);
profile.Allowed.Add(qType);
}

View File

@ -20,14 +20,14 @@ namespace NzbDrone.Web
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*robotstxt}", new {robotstxt = @"(.*/)?robots.txt(/.*)?"});
routes.IgnoreRoute("{*favicon}", new {favicon = @"(.*/)?favicon.ico(/.*)?"});
routes.IgnoreRoute("{*robotstxt}", new { robotstxt = @"(.*/)?robots.txt(/.*)?" });
routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Series", action = "Index", id = UrlParameter.Optional} // Parameter defaults
new { controller = "Series", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
@ -75,7 +75,7 @@ namespace NzbDrone.Web
return;
}
Logger.FatalException(lastError.Message, lastError);
Logger.FatalException(lastError.Message + Environment.NewLine + Request.Url.PathAndQuery, lastError);
if (lastError is SQLiteException)
{

View File

@ -38,6 +38,6 @@ namespace NzbDrone.Web.Models
[DisplayFormat(ConvertEmptyStringToNull = false)]
public String NzbsrusHash { get; set; }
public List<Indexer> Indexers { get; set; }
public List<IndexerSetting> Indexers { get; set; }
}
}

View File

@ -812,6 +812,15 @@
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>21704</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost/NzbDrone</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>http://localhost:8989</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
<SaveServerSettingsInUserFile>True</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>

View File

@ -1,10 +1,8 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<NzbDrone.Web.Models.IndexerSettingsModel>" %>
<script type="text/javascript">
$(document).ready(function () {
var options = {
target: '#result',
beforeSerialize: saveOrder,
beforeSubmit: showRequest,
success: showResponse,
type: 'post',
@ -14,21 +12,6 @@
$('#save_button').attr('disabled', '');
});
function saveOrder(jqForm, options) {
//Save the order of the sortable
var sortResult = $('#sortable').sortable("toArray");
var firstPart = "Indexers_";
var secondPart = "__Order";
jQuery.each(sortResult, function (index, value) {
var id = firstPart + value + secondPart;
var newValue = index + 1;
$("#" + id).val(newValue);
});
}
function showRequest(formData, jqForm, options) {
$("#result").empty().html('Saving...');
$("#form :input").attr("disabled", true);
@ -40,109 +23,113 @@
}
</script>
<style type="text/css">
#sortable { list-style-type: none; margin: 0; padding: 0; width: 30%; }
#sortable li { margin: 0 5px 5px 5px; padding: 5px; font-size: 1.2em; height: 1.5em; }
#sortable li { height: 1.5em; line-height: 1.2em; }
.ui-state-highlight { height: 1.5em; line-height: 1.2em; }
</style>
<script type="text/javascript">
$(function () {
$("#sortable").sortable({
placeholder: "ui-state-highlight"
});
$("#sortable").disableSelection();
</script>
<style type="text/css">
#sortable
{
list-style-type: none;
margin: 0;
padding: 0;
width: 30%;
}
#sortable li
{
margin: 0 5px 5px 5px;
padding: 5px;
font-size: 1.2em;
height: 1.5em;
}
#sortable li
{
height: 1.5em;
line-height: 1.2em;
}
.ui-state-highlight
{
height: 1.5em;
line-height: 1.2em;
}
</style>
<script type="text/javascript">
$(function () {
$("#sortable").sortable({
placeholder: "ui-state-highlight"
});
</script>
$("#sortable").disableSelection();
});
</script>
<%
using (Html.BeginForm("SaveIndexers", "Settings", FormMethod.Post, new {id = "form", name = "form"}))
using (Html.BeginForm("SaveIndexers", "Settings", FormMethod.Post, new { id = "form", name = "form" }))
{%>
<%:Html.ValidationSummary(true,
"Unable to save your settings. Please correct the errors and try again.")%>
<fieldset>
<legend>Indexers</legend>
<ul id="sortable">
<%
<fieldset>
<legend>Indexers</legend>
<ul id="sortable">
<%
for (int i = 0; i < Model.Indexers.Count(); i++)
{%>
<li class="ui-state-default" id="<%=i%>">
<%=Html.CheckBoxFor(c => c.Indexers[i].Enabled)%><%=Html.DisplayTextFor(c => c.Indexers[i].IndexerName)%></li>
<%
<li class="ui-state-default" id="<%=Model.Indexers[i].Id%>">
<%=Html.CheckBoxFor(c => c.Indexers[i].Enable)%><%=Html.DisplayTextFor(c => c.Indexers[i].Name)%></li>
<%
}%>
</ul>
<%
</ul>
<%
for (int i = 0; i < Model.Indexers.Count(); i++)
{%>
<%=Html.TextBoxFor(m => m.Indexers[i].IndexerName, new {@style = "display:none"})%>
<%=Html.TextBoxFor(m => m.Indexers[i].Order, new {@style = "display:none"})%>
<%=Html.TextBoxFor(m => m.Indexers[i].RssUrl, new {@style = "display:none"})%>
<%=Html.TextBoxFor(m => m.Indexers[i].ApiUrl, new {@style = "display:none"})%>
<%
<%
}%>
<%--NZBMatrix--%>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbMatrixUsername)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbMatrixUsername)%>
<%=Html.ValidationMessageFor(m => m.NzbMatrixUsername)%>
</div>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbMatrixApiKey)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbMatrixApiKey)%>
<%=Html.ValidationMessageFor(m => m.NzbMatrixApiKey)%>
</div>
<br />
<%--NZBs.Org--%>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbsOrgUId)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbsOrgUId)%>
<%=Html.ValidationMessageFor(m => m.NzbsOrgUId)%>
</div>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbsOrgHash)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbsOrgHash)%>
<%=Html.ValidationMessageFor(m => m.NzbsOrgHash)%>
</div>
<br />
<%--NZBsrus--%>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbsrusUId)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbsrusUId)%>
<%=Html.ValidationMessageFor(m => m.NzbsrusUId)%>
</div>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbsrusHash)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbsrusHash)%>
<%=Html.ValidationMessageFor(m => m.NzbsrusHash)%>
</div>
<br />
<input type="submit" id="save_button" value="Save" disabled="disabled" />
</fieldset>
<%--NZBMatrix--%>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbMatrixUsername)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbMatrixUsername)%>
<%=Html.ValidationMessageFor(m => m.NzbMatrixUsername)%>
</div>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbMatrixApiKey)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbMatrixApiKey)%>
<%=Html.ValidationMessageFor(m => m.NzbMatrixApiKey)%>
</div>
<br />
<%--NZBs.Org--%>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbsOrgUId)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbsOrgUId)%>
<%=Html.ValidationMessageFor(m => m.NzbsOrgUId)%>
</div>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbsOrgHash)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbsOrgHash)%>
<%=Html.ValidationMessageFor(m => m.NzbsOrgHash)%>
</div>
<br />
<%--NZBsrus--%>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbsrusUId)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbsrusUId)%>
<%=Html.ValidationMessageFor(m => m.NzbsrusUId)%>
</div>
<div class="editor-label">
<%=Html.LabelFor(m => m.NzbsrusHash)%>
</div>
<div class="editor-field">
<%=Html.TextBoxFor(m => m.NzbsrusHash)%>
<%=Html.ValidationMessageFor(m => m.NzbsrusHash)%>
</div>
<br />
<input type="submit" id="save_button" value="Save" disabled="disabled" />
</fieldset>
<%
}%>
<div id="result"></div>
<div id="result">
</div>

View File

@ -14,8 +14,7 @@
}
</style>
<div class="rootDirSection">
<fieldset style="width: 350px; height: 16px; margin: 0px; margin-top: 0px; border-color: #CCCCCD;
-khtml-border-radius: 8px; border-radius: 8px; -moz-border-radius: 8px; -webkit-border-radius: 8px;">
<fieldset>
<div>
<%:Html.TextBoxFor(m => m.Path, new {@class = "root_dir_text"})%>
<a href="#" class="deleteRow">