initial stage of indexer refactoring. things compile.

pull/4/head
kay.one 13 years ago
parent 7d7b37be5b
commit 9c1ff4af6b

@ -145,7 +145,7 @@
<virtualDirectory path="/" physicalPath="%NZBDRONE_PATH%\NZBDrone.Web" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:8989:" />
<binding protocol="http" bindingInformation="*:8980:" />
</bindings>
</site>
<siteDefaults>

@ -58,6 +58,9 @@ namespace NzbDrone.Core.Test
var series = Builder<Series>.CreateNew().Build();
series.QualityProfileId = profileId;
repo.Add(testProfile);
repo.Add(series);
var result = repo.All<Series>();
Assert.Count(1, result);

@ -1,7 +1,10 @@
using System.Linq;
using System;
using System.Linq;
using AutoMoq;
using MbUnit.Framework;
using Moq;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework;
using SubSonic.Repository;
@ -113,5 +116,30 @@ namespace NzbDrone.Core.Test
Assert.AreEqual(1, rootDir.Id);
Assert.AreEqual(path, rootDir.Path);
}
[Test]
public void None_existing_folder_returns_empty_list()
{
const string path = "d:\\bad folder";
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>(MockBehavior.Strict)
.Setup(m => m.FolderExists(path)).Returns(false);
var result = mocker.Resolve<RootDirProvider>().GetUnmappedFolders(path);
Assert.IsNotNull(result);
Assert.IsEmpty(result);
mocker.VerifyAllMocks();
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void empty_folder_path_throws()
{
var mocker = new AutoMoqer();
mocker.Resolve<RootDirProvider>().GetUnmappedFolders("");
}
}
}

@ -12,29 +12,6 @@ namespace NzbDrone.Core.Test
// ReSharper disable InconsistentNaming
public class SyncProviderTest : TestBase
{
[Test]
public void None_existing_folder_returns_empty_list()
{
const string path = "d:\\bad folder";
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>(MockBehavior.Strict)
.Setup(m => m.FolderExists(path)).Returns(false);
var result = mocker.Resolve<SyncProvider>().GetUnmappedFolders(path);
Assert.IsNotNull(result);
Assert.IsEmpty(result);
mocker.VerifyAllMocks();
}
[Test]
[ExpectedException(typeof (ArgumentException))]
public void empty_folder_path_throws()
{
var mocker = new AutoMoqer();
mocker.Resolve<SyncProvider>().GetUnmappedFolders("");
}
}
}

@ -7,11 +7,9 @@ namespace NzbDrone.Core.Model
public class EpisodeParseResult
{
internal string CleanTitle { get; set; }
public int SeriesId { get; set; }
public string FolderName { get; set; }
internal int SeasonNumber { get; set; }
internal List<int> Episodes { get; set; }
internal string EpisodeTitle { get; set; }

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Model
{
public enum IndexerType
{
Unknown = 0,
NzbsOrg = 1,
NzbMatrix = 2,
NzbsRus = 3,
Newzbin = 4
}
}

@ -168,11 +168,11 @@
<Compile Include="Instrumentation\NlogWriter.cs" />
<Compile Include="Model\ConnectionInfoModel.cs" />
<Compile Include="Model\ExternalNotificationType.cs" />
<Compile Include="Model\IndexerType.cs" />
<Compile Include="Model\LanguageType.cs" />
<Compile Include="Model\SabnzbdInfoModel.cs" />
<Compile Include="Providers\ExternalNotification\ExternalNotificationProviderBase.cs" />
<Compile Include="Providers\ExternalNotification\XbmcNotificationProvider.cs" />
<Compile Include="Providers\Indexer\IsNeededProvider.cs" />
<Compile Include="Providers\Indexer\SyndicationFeedXmlReader.cs" />
<Compile Include="Providers\AutoConfigureProvider.cs" />
<Compile Include="Providers\Indexer\NzbMatrixProvider.cs" />

@ -27,6 +27,11 @@ namespace NzbDrone.Core.Providers
{
}
public virtual int AddEpisode(Episode episode)
{
return (Int32)_repository.Add(episode);
}
public virtual Episode GetEpisode(long id)
{
return _repository.Single<Episode>(id);
@ -56,16 +61,6 @@ namespace NzbDrone.Core.Providers
return _repository.Find<Episode>(e => e.SeasonId == seasonId);
}
public virtual IList<Episode> GetEpisodeByParseResult(EpisodeParseResult parseResult)
{
var seasonEpisodes = _repository.All<Episode>().Where(e =>
e.SeriesId == parseResult.SeriesId &&
e.SeasonNumber == parseResult.SeasonNumber).ToList();
//Has to be done separately since subsonic doesn't support contain method
return seasonEpisodes.Where(c => parseResult.Episodes.Contains(c.EpisodeNumber)).ToList();
}
public virtual IList<Episode> EpisodesWithoutFiles(bool includeSpecials)
{
@ -80,73 +75,41 @@ namespace NzbDrone.Core.Providers
/// </summary>
/// <param name = "parsedReport">Episode that needs to be checked</param>
/// <returns></returns>
public virtual bool IsNeeded(EpisodeParseResult parsedReport)
public virtual bool IsNeeded(EpisodeParseResult parsedReport, Episode episodeInfo)
{
//Todo: Fix this so it properly handles multi-epsiode releases (Currently as long as the first episode is needed we download it)
//Todo: for small releases this is less of an issue, but for Full Season Releases this could be an issue if we only need the first episode (or first few)
foreach (var episode in parsedReport.Episodes)
var file = episodeInfo.EpisodeFile;
if (file != null)
{
var episodeInfo = GetEpisode(parsedReport.SeriesId, parsedReport.SeasonNumber, episode);
Logger.Debug("Existing file is {0} proper:{1}", file.Quality, file.Proper);
if (episodeInfo == null)
//There will never be a time when the episode quality is less than what we have and we want it... ever.... I think.
if (file.Quality > parsedReport.Quality)
{
Logger.Debug("Episode S{0:00}E{1:00} doesn't exist in db. adding it now.", parsedReport.SeasonNumber, episode);
//Todo: How do we want to handle this really? Episode could be released before information is on TheTvDB
//(Parks and Rec did this a lot in the first season, from experience)
//Keivan: Should automatically add the episode to db with minimal information. then update the description/title when available.
//Mark: Perhaps we should only add the epsiode if its the latest season, sometimes people name things completely wrong (duh!)
episodeInfo = new Episode
{
SeriesId = parsedReport.SeriesId,
AirDate = DateTime.Now.Date,
EpisodeNumber = episode,
SeasonNumber = parsedReport.SeasonNumber,
Title = String.Empty,
Overview = String.Empty,
Language = "en"
};
_repository.Add(episodeInfo);
Logger.Trace("file has better quality. skipping");
return false;
}
var file = episodeInfo.EpisodeFile;
if (file != null)
//If not null we need to see if this episode has the quality as the download (or if it is better)
if (file.Quality == parsedReport.Quality && file.Proper == parsedReport.Proper)
{
Logger.Debug("File is {0} Proper:{1}", file.Quality, file.Proper);
//There will never be a time when the episode quality is less than what we have and we want it... ever.... I think.
if (file.Quality > parsedReport.Quality)
{
Logger.Trace("file has better quality. skipping");
continue;
}
//If not null we need to see if this episode has the quality as the download (or if it is better)
if (file.Quality == parsedReport.Quality && file.Proper == parsedReport.Proper)
{
Logger.Trace("Same quality/proper. existing proper. skipping");
continue;
}
Logger.Trace("Same quality/proper. existing proper. skipping");
return false;
}
//Now we need to handle upgrades and actually pay attention to the Cut-off Value
if (file.Quality < parsedReport.Quality)
//Now we need to handle upgrades and actually pay attention to the Cut-off Value
if (file.Quality < parsedReport.Quality)
{
if (episodeInfo.Series.QualityProfile.Cutoff <= file.Quality)
{
if (episodeInfo.Series.QualityProfile.Cutoff <= file.Quality)
{
Logger.Trace("Quality is past cut-off skipping.");
continue;
}
Logger.Trace("Quality is past cut-off skipping.");
return false;
}
}
Logger.Debug("Episode {0} is needed", parsedReport);
return true; //If we get to this point and the file has not yet been rejected then accept it
}
Logger.Debug("Episode {0} is not needed", parsedReport);
return false;
Logger.Debug("Episode {0} is needed", parsedReport);
return true; //If we get to this point and the file has not yet been rejected then accept it
}
public virtual void RefreshEpisodeInfo(int seriesId)

@ -50,8 +50,10 @@ namespace NzbDrone.Core.Providers
{
//Looks for the existence of this episode in History
if (_repository.Exists<History>(h => h.EpisodeId == episodeId && h.Quality == quality && h.IsProper == proper))
{
Logger.Debug("Episode in History. ID:{0} Q:{1} Proper:{2}", episodeId, quality, proper);
return true;
}
Logger.Debug("Episode not in History. ID:{0} Q:{1} Proper:{2}", episodeId, quality, proper);
return false;
}

@ -1,14 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.ServiceModel.Syndication;
using System.Linq;
using NLog;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.ExternalNotification;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers.Indexer
@ -16,33 +12,16 @@ namespace NzbDrone.Core.Providers.Indexer
public abstract class IndexerProviderBase
{
protected readonly Logger _logger;
protected readonly ConfigProvider _configProvider;
protected readonly EpisodeProvider _episodeProvider;
private readonly HttpProvider _httpProvider;
protected readonly ConfigProvider _configProvider;
private readonly IndexerProvider _indexerProvider;
private readonly HistoryProvider _historyProvider;
protected readonly SeasonProvider _seasonProvider;
protected readonly SeriesProvider _seriesProvider;
protected readonly SabProvider _sabProvider;
protected readonly IEnumerable<ExternalNotificationProviderBase> _externalNotificationProvider;
protected IndexerProviderBase(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
EpisodeProvider episodeProvider, ConfigProvider configProvider,
HttpProvider httpProvider, IndexerProvider indexerProvider,
HistoryProvider historyProvider, SabProvider sabProvider,
IEnumerable<ExternalNotificationProviderBase> externalNotificationProvider)
protected IndexerProviderBase(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider)
{
_seriesProvider = seriesProvider;
_seasonProvider = seasonProvider;
_episodeProvider = episodeProvider;
_configProvider = configProvider;
_httpProvider = httpProvider;
_configProvider = configProvider;
_indexerProvider = indexerProvider;
_historyProvider = historyProvider;
_sabProvider = sabProvider;
//Todo: IEnumerable yields no results for some reason, yet yields results in other classes
_externalNotificationProvider = externalNotificationProvider;
_logger = LogManager.GetLogger(GetType().ToString());
}
@ -51,11 +30,6 @@ namespace NzbDrone.Core.Providers.Indexer
/// </summary>
public abstract string Name { get; }
/// <summary>
/// Gets a bool to determine if Backlog Searching is Supported
/// </summary>
public abstract bool SupportsBacklog { get; }
/// <summary>
/// Gets the source URL for the feed
/// </summary>
@ -80,10 +54,11 @@ namespace NzbDrone.Core.Providers.Indexer
/// <summary>
/// Fetches RSS feed and process each news item.
/// </summary>
public List<Exception> Fetch()
public List<EpisodeParseResult> Fetch()
{
_logger.Debug("Fetching feeds from " + Settings.Name);
var exeptions = new List<Exception>();
var result = new List<EpisodeParseResult>();
foreach (var url in Urls)
{
@ -98,11 +73,14 @@ namespace NzbDrone.Core.Providers.Indexer
{
try
{
ProcessItem(item);
var parsedEpisode = ParseFeed(item);
if (parsedEpisode != null)
{
result.Add(parsedEpisode);
}
}
catch (Exception itemEx)
{
exeptions.Add(itemEx);
_logger.ErrorException("An error occurred while processing feed item", itemEx);
}
@ -110,123 +88,24 @@ namespace NzbDrone.Core.Providers.Indexer
}
catch (Exception feedEx)
{
exeptions.Add(feedEx);
_logger.ErrorException("An error occurred while processing feed", feedEx);
}
}
_logger.Info("Finished processing feeds from " + Settings.Name);
return exeptions;
}
internal void ProcessItem(SyndicationItem feedItem)
{
_logger.Debug("Processing RSS feed item " + feedItem.Title.Text);
var parseResult = ParseFeed(feedItem);
if (parseResult != null && parseResult.SeriesId != 0)
{
if (!_seriesProvider.IsMonitored(parseResult.SeriesId))
{
_logger.Debug("{0} is present in the DB but not tracked. skipping.", parseResult.CleanTitle);
return;
}
if (!_seriesProvider.QualityWanted(parseResult.SeriesId, parseResult.Quality))
{
_logger.Debug("Post doesn't meet the quality requirements [{0}]. skipping.", parseResult.Quality);
return;
}
if (_seasonProvider.IsIgnored(parseResult.SeriesId, parseResult.SeasonNumber))
{
_logger.Debug("Season {0} is currently set to ignore. skipping.", parseResult.SeasonNumber);
return;
}
//Todo: How to handle full season files? Currently the episode list is completely empty for these releases
//Todo: Should we assume that the release contains all the episodes that belong to this season and add them from the DB?
if (!_episodeProvider.IsNeeded(parseResult))
{
_logger.Debug("Episode {0} is not needed. skipping.", parseResult);
return;
}
var episodes = _episodeProvider.GetEpisodeByParseResult(parseResult);
if (InHistory(episodes, parseResult, feedItem))
{
return;
}
parseResult.EpisodeTitle = episodes[0].Title;
var sabTitle = _sabProvider.GetSabTitle(parseResult);
if (_sabProvider.IsInQueue(sabTitle))
{
return;
}
if (!_sabProvider.AddByUrl(NzbDownloadUrl(feedItem), sabTitle))
{
_logger.Warn("Unable to add item to SAB queue. {0} {1}", NzbDownloadUrl(feedItem), sabTitle);
return;
}
foreach (var episode in episodes)
{
_historyProvider.Add(new History
{
Date = DateTime.Now,
EpisodeId = episode.EpisodeId,
IsProper = parseResult.Proper,
NzbTitle = feedItem.Title.Text,
Quality = parseResult.Quality,
Indexer = Name
});
}
//Notify!
foreach (var notification in _externalNotificationProvider.Where(n => n.Settings.Enabled))
{
notification.OnGrab(sabTitle);
}
}
return result;
}
/// <summary>
/// Parses the RSS feed item and.
/// Parses the RSS feed item
/// </summary>
/// <param name = "item">RSS feed item to parse</param>
/// <returns>Detailed episode info</returns>
public EpisodeParseResult ParseFeed(SyndicationItem item)
{
var episodeParseResult = Parser.ParseEpisodeInfo(item.Title.Text);
if (episodeParseResult == null) return null;
var seriesInfo = _seriesProvider.FindSeries(episodeParseResult.CleanTitle);
if (seriesInfo == null)
{
var seriesId = SceneNameHelper.FindByName(episodeParseResult.CleanTitle);
if (seriesId != 0)
seriesInfo = _seriesProvider.GetSeries(seriesId);
}
if (seriesInfo != null)
{
episodeParseResult.SeriesId = seriesInfo.SeriesId;
episodeParseResult.FolderName = new DirectoryInfo(seriesInfo.Path).Name; ;
episodeParseResult.CleanTitle = seriesInfo.Title;
return CustomParser(item, episodeParseResult);
}
_logger.Debug("Unable to map {0} to any of series in database", episodeParseResult.CleanTitle);
return null;
return CustomParser(item, episodeParseResult);
}
/// <summary>
@ -246,18 +125,5 @@ namespace NzbDrone.Core.Providers.Indexer
/// <param name = "item">RSS Feed item to generate the link for</param>
/// <returns>Download link URL</returns>
protected abstract string NzbDownloadUrl(SyndicationItem item);
private bool InHistory(IList<Episode> episodes, EpisodeParseResult parseResult, SyndicationItem feedItem)
{
foreach (var episode in episodes)
{
if (_historyProvider.Exists(episode.EpisodeId, parseResult.Quality, parseResult.Proper))
{
_logger.Debug("Episode in history: {0}", feedItem.Title.Text);
return true;
}
}
return false;
}
}
}

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using NLog;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository;
using System.ServiceModel.Syndication;
namespace NzbDrone.Core.Providers.Indexer
{
public class IsNeededProvider
{
private readonly SeriesProvider _seriesProvider;
private readonly SeasonProvider _seasonProvider;
private readonly EpisodeProvider _episodeProvider;
private readonly HistoryProvider _historyProvider;
private readonly SabProvider _sabProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public IsNeededProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider, EpisodeProvider episodeProvider, HistoryProvider historyProvider, SabProvider sabProvider)
{
_seriesProvider = seriesProvider;
_seasonProvider = seasonProvider;
_episodeProvider = episodeProvider;
_historyProvider = historyProvider;
_sabProvider = sabProvider;
}
internal bool IsNeeded(EpisodeParseResult parseResult, Series series)
{
foreach (var episodeNumber in parseResult.Episodes)
{
//Todo: How to handle full season files? Currently the episode list is completely empty for these releases
//Todo: Should we assume that the release contains all the episodes that belong to this season and add them from the DB?
//Todo: Fix this so it properly handles multi-epsiode releases (Currently as long as the first episode is needed we download it)
//Todo: for small releases this is less of an issue, but for Full Season Releases this could be an issue if we only need the first episode (or first few)
if (!series.Monitored)
{
Logger.Debug("{0} is present in the DB but not tracked. skipping.", parseResult.CleanTitle);
return false;
}
if (!_seriesProvider.QualityWanted(series.SeriesId, parseResult.Quality))
{
Logger.Debug("Post doesn't meet the quality requirements [{0}]. skipping.", parseResult.Quality);
return false;
}
if (_seasonProvider.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
{
Logger.Debug("Season {0} is currently set to ignore. skipping.", parseResult.SeasonNumber);
return false;
}
var episodeInfo = _episodeProvider.GetEpisode(series.SeriesId, parseResult.SeasonNumber, episodeNumber);
if (episodeInfo == null)
{
episodeInfo = _episodeProvider.GetEpisode(series.SeriesId, parseResult.AirDate);
}
//if still null we should add the temp episode
if (episodeInfo == null)
{
Logger.Debug("Episode {0} doesn't exist in db. adding it now.", parseResult);
episodeInfo = new Episode
{
SeriesId = series.SeriesId,
AirDate = DateTime.Now.Date,
EpisodeNumber = episodeNumber,
SeasonNumber = parseResult.SeasonNumber,
Title = parseResult.EpisodeTitle,
Overview = String.Empty,
Language = "en"
};
_episodeProvider.AddEpisode(episodeInfo);
}
if (!_episodeProvider.IsNeeded(parseResult, episodeInfo))
{
Logger.Debug("Episode {0} is not needed. skipping.", parseResult);
return false;
}
if (_historyProvider.Exists(episodeInfo.EpisodeId, parseResult.Quality, parseResult.Proper))
{
Logger.Debug("Episode {0} is in history. skipping.", parseResult);
return false;
}
parseResult.EpisodeTitle = episodeInfo.Title;
var sabTitle = _sabProvider.GetSabTitle(parseResult, new DirectoryInfo(series.Path).Name);
if (_sabProvider.IsInQueue(sabTitle))
{
Logger.Debug("Episode {0} is already in sab's queue. skipping.", parseResult);
return false;
}
//Congragulations younge feed item! you have made it this far. you are truly special!!!
return true;
}
return false;
}
}
}

@ -9,13 +9,7 @@ namespace NzbDrone.Core.Providers.Indexer
{
public class NewzbinProvider : IndexerProviderBase
{
public NewzbinProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
EpisodeProvider episodeProvider, ConfigProvider configProvider,
HttpProvider httpProvider, IndexerProvider indexerProvider,
HistoryProvider historyProvider, SabProvider sabProvider, IEnumerable<ExternalNotificationProviderBase> externalNotificationProvider)
: base(seriesProvider, seasonProvider, episodeProvider,
configProvider, httpProvider, indexerProvider, historyProvider,
sabProvider, externalNotificationProvider)
public NewzbinProvider(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider)
{
}
@ -40,11 +34,6 @@ namespace NzbDrone.Core.Providers.Indexer
get { return "Newzbin"; }
}
public override bool SupportsBacklog
{
get { return false; }
}
protected override string NzbDownloadUrl(SyndicationItem item)
{
return item.Id + "/nzb";

@ -11,13 +11,7 @@ namespace NzbDrone.Core.Providers.Indexer
{
public class NzbMatrixProvider : IndexerProviderBase
{
public NzbMatrixProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
EpisodeProvider episodeProvider, ConfigProvider configProvider,
HttpProvider httpProvider, IndexerProvider indexerProvider,
HistoryProvider historyProvider, SabProvider sabProvider, IEnumerable<ExternalNotificationProviderBase> externalNotificationProvider)
: base(seriesProvider, seasonProvider, episodeProvider,
configProvider, httpProvider, indexerProvider, historyProvider,
sabProvider, externalNotificationProvider)
public NzbMatrixProvider(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider)
{
}
@ -40,10 +34,6 @@ namespace NzbDrone.Core.Providers.Indexer
get { return "NzbMatrix"; }
}
public override bool SupportsBacklog
{
get { return true; }
}
protected override string NzbDownloadUrl(SyndicationItem item)
{

@ -10,13 +10,7 @@ namespace NzbDrone.Core.Providers.Indexer
{
public class NzbsOrgProvider : IndexerProviderBase
{
public NzbsOrgProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
EpisodeProvider episodeProvider, ConfigProvider configProvider,
HttpProvider httpProvider, IndexerProvider indexerProvider,
HistoryProvider historyProvider, SabProvider sabProvider, IEnumerable<ExternalNotificationProviderBase> externalNotificationProvider)
: base(seriesProvider, seasonProvider, episodeProvider,
configProvider, httpProvider, indexerProvider, historyProvider,
sabProvider, externalNotificationProvider)
public NzbsOrgProvider(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider)
{
}
@ -36,10 +30,6 @@ namespace NzbDrone.Core.Providers.Indexer
get { return "Nzbs.org"; }
}
public override bool SupportsBacklog
{
get { return false; }
}
protected override string NzbDownloadUrl(SyndicationItem item)
{

@ -10,13 +10,7 @@ namespace NzbDrone.Core.Providers.Indexer
{
public class NzbsRUsProvider : IndexerProviderBase
{
public NzbsRUsProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
EpisodeProvider episodeProvider, ConfigProvider configProvider,
HttpProvider httpProvider, IndexerProvider indexerProvider,
HistoryProvider historyProvider, SabProvider sabProvider, IEnumerable<ExternalNotificationProviderBase> externalNotificationProvider)
: base(seriesProvider, seasonProvider, episodeProvider,
configProvider, httpProvider, indexerProvider, historyProvider,
sabProvider, externalNotificationProvider)
public NzbsRUsProvider(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider)
{
}
@ -39,12 +33,7 @@ namespace NzbDrone.Core.Providers.Indexer
get { return "NzbsRUs"; }
}
public override bool SupportsBacklog
{
get { return false; }
}
protected override string NzbDownloadUrl(SyndicationItem item)
protected override string NzbDownloadUrl(SyndicationItem item)
{
return item.Links[0].Uri.ToString();
}

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NLog;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using SubSonic.Repository;
@ -9,10 +12,16 @@ namespace NzbDrone.Core.Providers
public class RootDirProvider
{
private readonly IRepository _sonioRepo;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly DiskProvider _diskProvider;
private readonly SeriesProvider _seriesProvider;
public RootDirProvider(IRepository sonicRepo)
public RootDirProvider(IRepository sonicRepo, SeriesProvider seriesProvider, DiskProvider diskProvider)
{
_sonioRepo = sonicRepo;
_diskProvider = diskProvider;
_seriesProvider = seriesProvider;
}
#region IRootDirProvider
@ -42,6 +51,33 @@ namespace NzbDrone.Core.Providers
return _sonioRepo.Single<RootDir>(rootDirId);
}
public List<String> GetUnmappedFolders(string path)
{
Logger.Debug("Generating list of unmapped folders");
if (String.IsNullOrEmpty(path))
throw new ArgumentException("Invalid path provided", "path");
var results = new List<String>();
if (!_diskProvider.FolderExists(path))
{
Logger.Debug("Path supplied does not exist: {0}", path);
return results;
}
foreach (string seriesFolder in _diskProvider.GetDirectories(path))
{
var cleanPath = Parser.NormalizePath(new DirectoryInfo(seriesFolder).FullName);
if (!_seriesProvider.SeriesPathExists(cleanPath))
results.Add(cleanPath);
}
Logger.Debug("{0} unmapped folders detected.", results.Count);
return results;
}
#endregion
}
}

@ -92,7 +92,7 @@ namespace NzbDrone.Core.Providers
_configProvider.SabPassword);
}
public String GetSabTitle(EpisodeParseResult parseResult)
public String GetSabTitle(EpisodeParseResult parseResult, String folderName)
{
//Show Name - 1x01-1x02 - Episode Name
//Show Name - 1x01 - Episode Name
@ -105,7 +105,7 @@ namespace NzbDrone.Core.Providers
var epNumberString = String.Join("-", episodeString);
var result = String.Format("{0} - {1} - {2} [{3}]", parseResult.FolderName, epNumberString, parseResult.EpisodeTitle, parseResult.Quality);
var result = String.Format("{0} - {1} - {2} [{3}]", folderName, epNumberString, parseResult.EpisodeTitle, parseResult.Quality);
if (parseResult.Proper)
{

@ -3,6 +3,7 @@ using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
@ -108,8 +109,14 @@ namespace NzbDrone.Core.Providers
public virtual Series FindSeries(string title)
{
//TODO:Add series alias support here. if a series is not found in the repo should be tried using its aliases
var normalizeTitle = Parser.NormalizeTitle(title);
var seriesId = SceneNameHelper.FindByName(normalizeTitle);
if (seriesId != 0)
{
return GetSeries(seriesId);
}
return _repository.Single<Series>(s => s.CleanTitle == normalizeTitle);
}

@ -11,41 +11,7 @@ namespace NzbDrone.Core.Providers
{
public class SyncProvider
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly DiskProvider _diskProvider;
private readonly SeriesProvider _seriesProvider;
public SyncProvider(SeriesProvider seriesProvider, DiskProvider diskProvider)
{
_seriesProvider = seriesProvider;
_diskProvider = diskProvider;
}
public List<String> GetUnmappedFolders(string path)
{
Logger.Debug("Generating list of unmapped folders");
if (String.IsNullOrEmpty(path))
throw new ArgumentException("Invalid path provided", "path");
var results = new List<String>();
if (!_diskProvider.FolderExists(path))
{
Logger.Debug("Path supplied does not exist: {0}", path);
return results;
}
foreach (string seriesFolder in _diskProvider.GetDirectories(path))
{
var cleanPath = Parser.NormalizePath(new DirectoryInfo(seriesFolder).FullName);
if (!_seriesProvider.SeriesPathExists(cleanPath))
results.Add(cleanPath);
}
Logger.Debug("{0} unmapped folders detected.", results.Count);
return results;
}
}
}

@ -72,7 +72,7 @@ namespace NzbDrone.Web.Controllers
foreach (var folder in _rootFolderProvider.GetAll())
{
unmappedList.AddRange(_syncProvider.GetUnmappedFolders(folder.Path));
unmappedList.AddRange(_rootFolderProvider.GetUnmappedFolders(folder.Path));
}
return View(unmappedList);

@ -4,6 +4,6 @@
<supportedRuntime version="v4.0" />
</startup>
<appSettings>
<add key="port" value="8989" />
<add key="port" value="8980" />
</appSettings>
</configuration>
Loading…
Cancel
Save