diff --git a/NzbDrone.Core.Test/IndexerProviderTest.cs b/NzbDrone.Core.Test/IndexerProviderTest.cs index b0ac3cae6..79d1ae665 100644 --- a/NzbDrone.Core.Test/IndexerProviderTest.cs +++ b/NzbDrone.Core.Test/IndexerProviderTest.cs @@ -42,7 +42,7 @@ namespace NzbDrone.Core.Test .Returns(fakeSettings); var mockIndexer = mocker.Resolve(); - var parseResults = mockIndexer.Fetch(); + var parseResults = mockIndexer.FetchRss(); foreach (var episodeParseResult in parseResults) { @@ -77,7 +77,7 @@ namespace NzbDrone.Core.Test .Returns(fakeSettings); var newzbinProvider = mocker.Resolve(); - var parseResults = newzbinProvider.Fetch(); + var parseResults = newzbinProvider.FetchRss(); foreach (var episodeParseResult in parseResults) { @@ -163,7 +163,7 @@ namespace NzbDrone.Core.Test .Setup(c => c.GetSettings(It.IsAny())) .Returns(fakeSettings); - mocker.Resolve().Fetch(); + mocker.Resolve().FetchRss(); ExceptionVerification.IgnoreWarns(); } @@ -195,12 +195,39 @@ namespace NzbDrone.Core.Test var indexer = mocker.Resolve(); //indexer.ProcessItem(new SyndicationItem { Title = new TextSyndicationContent("Adventure.Inc.S01E18.DVDRip.XviD-OSiTV") }); } + + + [Test] + public void nzbsorg_search_returns_valid_results() + { + var mocker = new AutoMoqer(); + + mocker.GetMock() + .SetupGet(c => c.NzbsOrgUId) + .Returns("43516"); + + mocker.GetMock() + .SetupGet(c => c.NzbsOrgHash) + .Returns("bc8edb4cc49d4ae440775adec5ac001f"); + + + mocker.Resolve(); + + var result = mocker.Resolve().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)); + + + } } public class MockIndexer : IndexerBase { - public MockIndexer(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) - : base(httpProvider, configProvider, indexerProvider) + public MockIndexer(HttpProvider httpProvider, ConfigProvider configProvider) + : base(httpProvider, configProvider) { } @@ -209,6 +236,11 @@ namespace NzbDrone.Core.Test get { return new[] { "www.google.com" }; } } + protected override IList GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber) + { + throw new NotImplementedException(); + } + protected override NetworkCredential Credentials { get { return null; } @@ -228,8 +260,8 @@ namespace NzbDrone.Core.Test public class TestUrlIndexer : IndexerBase { - public TestUrlIndexer(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) - : base(httpProvider, configProvider, indexerProvider) + public TestUrlIndexer(HttpProvider httpProvider, ConfigProvider configProvider) + : base(httpProvider, configProvider) { } @@ -243,6 +275,11 @@ namespace NzbDrone.Core.Test get { return new[] { "http://rss.nzbmatrix.com/rss.php?cat=TV" }; } } + protected override IList GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber) + { + throw new NotImplementedException(); + } + protected override string NzbDownloadUrl(SyndicationItem item) { return "http://google.com"; @@ -251,8 +288,8 @@ namespace NzbDrone.Core.Test public class CustomParserIndexer : IndexerBase { - public CustomParserIndexer(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) - : base(httpProvider, configProvider, indexerProvider) + public CustomParserIndexer(HttpProvider httpProvider, ConfigProvider configProvider) + : base(httpProvider, configProvider) { } @@ -268,6 +305,11 @@ namespace NzbDrone.Core.Test get { return new[] { "http://www.google.com" }; } } + protected override IList GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber) + { + throw new NotImplementedException(); + } + protected override string NzbDownloadUrl(SyndicationItem item) { return "http://www.google.com"; diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 636beec98..76661d1f4 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -171,7 +171,7 @@ - + diff --git a/NzbDrone.Core/Providers/Indexer/IndexerBase.cs b/NzbDrone.Core/Providers/Indexer/IndexerBase.cs index aeee9d96e..da70331b6 100644 --- a/NzbDrone.Core/Providers/Indexer/IndexerBase.cs +++ b/NzbDrone.Core/Providers/Indexer/IndexerBase.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Net; using System.ServiceModel.Syndication; +using System.Web; using NLog; using NzbDrone.Core.Model; using NzbDrone.Core.Providers.Core; @@ -14,13 +15,11 @@ namespace NzbDrone.Core.Providers.Indexer protected readonly Logger _logger; private readonly HttpProvider _httpProvider; protected readonly ConfigProvider _configProvider; - private readonly IndexerProvider _indexerProvider; - protected IndexerBase(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) + protected IndexerBase(HttpProvider httpProvider, ConfigProvider configProvider) { _httpProvider = httpProvider; _configProvider = configProvider; - _indexerProvider = indexerProvider; _logger = LogManager.GetLogger(GetType().ToString()); } @@ -35,6 +34,16 @@ namespace NzbDrone.Core.Providers.Indexer /// protected abstract string[] Urls { get; } + + /// + /// Gets the rss url for specific episode search + /// + /// The series title. + /// The season number. + /// The episode number. + /// + protected abstract IList GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber); + /// /// Gets the credential. /// @@ -43,59 +52,80 @@ namespace NzbDrone.Core.Providers.Indexer get { return null; } } - public IndexerSetting Settings - { - get - { - return _indexerProvider.GetSettings(GetType()); - } - } /// /// Fetches RSS feed and process each news item. /// - public List Fetch() + public IList FetchRss() { - _logger.Debug("Fetching feeds from " + Settings.Name); + _logger.Debug("Fetching feeds from " + Name); var result = new List(); foreach (var url in Urls) { - try - { - _logger.Trace("Downloading RSS " + url); + result.AddRange(Fetch(url)); + } - var reader = new SyndicationFeedXmlReader(_httpProvider.DownloadStream(url, Credentials)); - var feed = SyndicationFeed.Load(reader).Items; + _logger.Info("Finished processing feeds from " + Name); + return result; + } + + + public IList FetchEpisode(string seriesTitle, int seasonNumber, int episodeNumber) + { + _logger.Debug("Searching {0} for {1}-S{2}E{3:00}", Name, seriesTitle, seasonNumber, episodeNumber); + + var result = new List(); + + var searchUrls = GetSearchUrls(HttpUtility.UrlDecode(seriesTitle), seasonNumber, episodeNumber); + + foreach (var url in searchUrls) + { + result.AddRange(Fetch(url)); + } - foreach (var item in feed) + _logger.Info("Finished searching {0} for {1}-S{2}E{3:00}, Found {4}", Name, seriesTitle, seasonNumber, episodeNumber, result.Count); + return result; + + } + + private IList Fetch(string url) + { + var result = new List(); + + try + { + _logger.Trace("Downloading RSS " + url); + + var reader = new SyndicationFeedXmlReader(_httpProvider.DownloadStream(url, Credentials)); + var feed = SyndicationFeed.Load(reader).Items; + + foreach (var item in feed) + { + try { - try + var parsedEpisode = ParseFeed(item); + if (parsedEpisode != null) { - var parsedEpisode = ParseFeed(item); - if (parsedEpisode != null) - { - parsedEpisode.NzbUrl = NzbDownloadUrl(item); - parsedEpisode.Indexer = Name; - parsedEpisode.NzbTitle = item.Title.Text; - result.Add(parsedEpisode); - } + parsedEpisode.NzbUrl = NzbDownloadUrl(item); + parsedEpisode.Indexer = Name; + parsedEpisode.NzbTitle = item.Title.Text; + result.Add(parsedEpisode); } - catch (Exception itemEx) - { - _logger.ErrorException("An error occurred while processing feed item", itemEx); - } - } + catch (Exception itemEx) + { + _logger.ErrorException("An error occurred while processing feed item", itemEx); + } + } - catch (Exception feedEx) - { - _logger.ErrorException("An error occurred while processing feed", feedEx); - } + } + catch (Exception feedEx) + { + _logger.ErrorException("An error occurred while processing feed", feedEx); } - _logger.Info("Finished processing feeds from " + Settings.Name); return result; } diff --git a/NzbDrone.Core/Providers/Indexer/Newzbin.cs b/NzbDrone.Core/Providers/Indexer/Newzbin.cs index 06a3d2de8..4c96228ca 100644 --- a/NzbDrone.Core/Providers/Indexer/Newzbin.cs +++ b/NzbDrone.Core/Providers/Indexer/Newzbin.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Net; using System.ServiceModel.Syndication; using NzbDrone.Core.Model; @@ -9,8 +10,7 @@ namespace NzbDrone.Core.Providers.Indexer { public class Newzbin : IndexerBase { - public Newzbin(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) - : base(httpProvider, configProvider, indexerProvider) + public Newzbin(HttpProvider httpProvider, ConfigProvider configProvider) : base(httpProvider, configProvider) { } @@ -25,11 +25,19 @@ namespace NzbDrone.Core.Providers.Indexer } } + + + protected override NetworkCredential Credentials { get { return new NetworkCredential(_configProvider.NewzbinUsername, _configProvider.NewzbinPassword); } } + protected override IList GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber) + { + return new List(); + } + public override string Name { get { return "Newzbin"; } diff --git a/NzbDrone.Core/Providers/Indexer/NzbMatrix.cs b/NzbDrone.Core/Providers/Indexer/NzbMatrix.cs index fca68090c..72e5e1313 100644 --- a/NzbDrone.Core/Providers/Indexer/NzbMatrix.cs +++ b/NzbDrone.Core/Providers/Indexer/NzbMatrix.cs @@ -11,7 +11,7 @@ namespace NzbDrone.Core.Providers.Indexer { public class NzbMatrix : IndexerBase { - public NzbMatrix(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider) + public NzbMatrix(HttpProvider httpProvider, ConfigProvider configProvider) : base(httpProvider, configProvider) { } @@ -40,5 +40,10 @@ namespace NzbDrone.Core.Providers.Indexer return item.Links[0].Uri.ToString(); } + protected override IList GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber) + { + return new List(); + } + } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/Indexer/NzbsOrg.cs b/NzbDrone.Core/Providers/Indexer/NzbsOrg.cs index a323c6e42..a9ed732bb 100644 --- a/NzbDrone.Core/Providers/Indexer/NzbsOrg.cs +++ b/NzbDrone.Core/Providers/Indexer/NzbsOrg.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Net; using System.ServiceModel.Syndication; using NzbDrone.Core.Model; @@ -10,7 +11,7 @@ namespace NzbDrone.Core.Providers.Indexer { public class NzbsOrg : IndexerBase { - public NzbsOrg(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider) + public NzbsOrg(HttpProvider httpProvider, ConfigProvider configProvider) : base(httpProvider, configProvider) { } @@ -36,5 +37,17 @@ namespace NzbDrone.Core.Providers.Indexer return item.Id; } + protected override IList GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber) + { + var searchUrls = new List(); + + foreach (var url in Urls) + { + searchUrls.Add(String.Format("{0}&action=search&q={1}+s{2}e{3:00}", url, seriesTitle, seasonNumber, episodeNumber)); + } + + return searchUrls; + } + } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/Indexer/NzbsRUs.cs b/NzbDrone.Core/Providers/Indexer/NzbsRUs.cs index 766490b6e..65c7c3316 100644 --- a/NzbDrone.Core/Providers/Indexer/NzbsRUs.cs +++ b/NzbDrone.Core/Providers/Indexer/NzbsRUs.cs @@ -10,7 +10,7 @@ namespace NzbDrone.Core.Providers.Indexer { public class NzbsRUs : IndexerBase { - public NzbsRUs(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider) + public NzbsRUs(HttpProvider httpProvider, ConfigProvider configProvider) : base(httpProvider, configProvider) { } @@ -27,16 +27,20 @@ namespace NzbDrone.Core.Providers.Indexer }; } } - + public override string Name { get { return "NzbsRUs"; } } - protected override string NzbDownloadUrl(SyndicationItem item) + protected override string NzbDownloadUrl(SyndicationItem item) { return item.Links[0].Uri.ToString(); } + protected override IList GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber) + { + return new List(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/IndexerProvider.cs b/NzbDrone.Core/Providers/IndexerProvider.cs index 0cac8eeef..75d04441a 100644 --- a/NzbDrone.Core/Providers/IndexerProvider.cs +++ b/NzbDrone.Core/Providers/IndexerProvider.cs @@ -2,7 +2,6 @@ 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; diff --git a/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs b/NzbDrone.Core/Providers/InventoryProvider.cs similarity index 98% rename from NzbDrone.Core/Providers/Indexer/InventoryProvider.cs rename to NzbDrone.Core/Providers/InventoryProvider.cs index 363a3332a..bcab33f26 100644 --- a/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs +++ b/NzbDrone.Core/Providers/InventoryProvider.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; -using System.IO; using NLog; using NzbDrone.Core.Model; using NzbDrone.Core.Repository; -namespace NzbDrone.Core.Providers.Indexer +namespace NzbDrone.Core.Providers { public class InventoryProvider { diff --git a/NzbDrone.Core/Providers/Jobs/RssSyncJob.cs b/NzbDrone.Core/Providers/Jobs/RssSyncJob.cs index 053b2daab..5ad822003 100644 --- a/NzbDrone.Core/Providers/Jobs/RssSyncJob.cs +++ b/NzbDrone.Core/Providers/Jobs/RssSyncJob.cs @@ -13,15 +13,17 @@ namespace NzbDrone.Core.Providers.Jobs private readonly IEnumerable _indexers; private readonly InventoryProvider _inventoryProvider; private readonly DownloadProvider _downloadProvider; + private readonly IndexerProvider _indexerProvider; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public RssSyncJob(IEnumerable indexers, InventoryProvider inventoryProvider, DownloadProvider downloadProvider) + public RssSyncJob(IEnumerable indexers, InventoryProvider inventoryProvider, DownloadProvider downloadProvider, IndexerProvider indexerProvider) { _indexers = indexers; _inventoryProvider = inventoryProvider; _downloadProvider = downloadProvider; + _indexerProvider = indexerProvider; } public string Name @@ -38,12 +40,12 @@ namespace NzbDrone.Core.Providers.Jobs { var reports = new List(); - foreach (var indexer in _indexers.Where(i => i.Settings.Enable)) + foreach (var indexer in _indexers.Where(i => _indexerProvider.GetSettings(i.GetType()).Enable)) { try { notification.CurrentMessage = "Fetching RSS from " + indexer.Name; - reports.AddRange(indexer.Fetch()); + reports.AddRange(indexer.FetchRss()); } catch (Exception e) {