mirror of https://github.com/Sonarr/Sonarr
initial stage of indexer refactoring. things compile.
This commit is contained in:
parent
7d7b37be5b
commit
9c1ff4af6b
|
@ -145,7 +145,7 @@
|
||||||
<virtualDirectory path="/" physicalPath="%NZBDRONE_PATH%\NZBDrone.Web" />
|
<virtualDirectory path="/" physicalPath="%NZBDRONE_PATH%\NZBDrone.Web" />
|
||||||
</application>
|
</application>
|
||||||
<bindings>
|
<bindings>
|
||||||
<binding protocol="http" bindingInformation="*:8989:" />
|
<binding protocol="http" bindingInformation="*:8980:" />
|
||||||
</bindings>
|
</bindings>
|
||||||
</site>
|
</site>
|
||||||
<siteDefaults>
|
<siteDefaults>
|
||||||
|
|
|
@ -58,6 +58,9 @@ namespace NzbDrone.Core.Test
|
||||||
var series = Builder<Series>.CreateNew().Build();
|
var series = Builder<Series>.CreateNew().Build();
|
||||||
series.QualityProfileId = profileId;
|
series.QualityProfileId = profileId;
|
||||||
|
|
||||||
|
repo.Add(testProfile);
|
||||||
|
repo.Add(series);
|
||||||
|
|
||||||
var result = repo.All<Series>();
|
var result = repo.All<Series>();
|
||||||
|
|
||||||
Assert.Count(1, result);
|
Assert.Count(1, result);
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using AutoMoq;
|
using AutoMoq;
|
||||||
using MbUnit.Framework;
|
using MbUnit.Framework;
|
||||||
|
using Moq;
|
||||||
using NzbDrone.Core.Providers;
|
using NzbDrone.Core.Providers;
|
||||||
|
using NzbDrone.Core.Providers.Core;
|
||||||
using NzbDrone.Core.Repository;
|
using NzbDrone.Core.Repository;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using SubSonic.Repository;
|
using SubSonic.Repository;
|
||||||
|
@ -113,5 +116,30 @@ namespace NzbDrone.Core.Test
|
||||||
Assert.AreEqual(1, rootDir.Id);
|
Assert.AreEqual(1, rootDir.Id);
|
||||||
Assert.AreEqual(path, rootDir.Path);
|
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
|
// ReSharper disable InconsistentNaming
|
||||||
public class SyncProviderTest : TestBase
|
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
|
public class EpisodeParseResult
|
||||||
{
|
{
|
||||||
internal string CleanTitle { get; set; }
|
internal string CleanTitle { get; set; }
|
||||||
public int SeriesId { get; set; }
|
|
||||||
|
|
||||||
public string FolderName { get; set; }
|
|
||||||
|
|
||||||
internal int SeasonNumber { get; set; }
|
internal int SeasonNumber { get; set; }
|
||||||
|
|
||||||
internal List<int> Episodes { get; set; }
|
internal List<int> Episodes { get; set; }
|
||||||
|
|
||||||
internal string EpisodeTitle { 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="Instrumentation\NlogWriter.cs" />
|
||||||
<Compile Include="Model\ConnectionInfoModel.cs" />
|
<Compile Include="Model\ConnectionInfoModel.cs" />
|
||||||
<Compile Include="Model\ExternalNotificationType.cs" />
|
<Compile Include="Model\ExternalNotificationType.cs" />
|
||||||
<Compile Include="Model\IndexerType.cs" />
|
|
||||||
<Compile Include="Model\LanguageType.cs" />
|
<Compile Include="Model\LanguageType.cs" />
|
||||||
<Compile Include="Model\SabnzbdInfoModel.cs" />
|
<Compile Include="Model\SabnzbdInfoModel.cs" />
|
||||||
<Compile Include="Providers\ExternalNotification\ExternalNotificationProviderBase.cs" />
|
<Compile Include="Providers\ExternalNotification\ExternalNotificationProviderBase.cs" />
|
||||||
<Compile Include="Providers\ExternalNotification\XbmcNotificationProvider.cs" />
|
<Compile Include="Providers\ExternalNotification\XbmcNotificationProvider.cs" />
|
||||||
|
<Compile Include="Providers\Indexer\IsNeededProvider.cs" />
|
||||||
<Compile Include="Providers\Indexer\SyndicationFeedXmlReader.cs" />
|
<Compile Include="Providers\Indexer\SyndicationFeedXmlReader.cs" />
|
||||||
<Compile Include="Providers\AutoConfigureProvider.cs" />
|
<Compile Include="Providers\AutoConfigureProvider.cs" />
|
||||||
<Compile Include="Providers\Indexer\NzbMatrixProvider.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)
|
public virtual Episode GetEpisode(long id)
|
||||||
{
|
{
|
||||||
return _repository.Single<Episode>(id);
|
return _repository.Single<Episode>(id);
|
||||||
|
@ -56,16 +61,6 @@ namespace NzbDrone.Core.Providers
|
||||||
return _repository.Find<Episode>(e => e.SeasonId == seasonId);
|
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)
|
public virtual IList<Episode> EpisodesWithoutFiles(bool includeSpecials)
|
||||||
{
|
{
|
||||||
|
@ -80,73 +75,41 @@ namespace NzbDrone.Core.Providers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name = "parsedReport">Episode that needs to be checked</param>
|
/// <param name = "parsedReport">Episode that needs to be checked</param>
|
||||||
/// <returns></returns>
|
/// <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)
|
var file = episodeInfo.EpisodeFile;
|
||||||
//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)
|
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);
|
Logger.Trace("file has better quality. skipping");
|
||||||
//Todo: How do we want to handle this really? Episode could be released before information is on TheTvDB
|
return false;
|
||||||
//(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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var file = episodeInfo.EpisodeFile;
|
//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)
|
||||||
if (file != null)
|
|
||||||
{
|
{
|
||||||
Logger.Debug("File is {0} Proper:{1}", file.Quality, file.Proper);
|
Logger.Trace("Same quality/proper. existing proper. skipping");
|
||||||
|
return false;
|
||||||
//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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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)
|
|
||||||
{
|
|
||||||
Logger.Trace("Quality is past cut-off skipping.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Debug("Episode {0} is needed", parsedReport);
|
//Now we need to handle upgrades and actually pay attention to the Cut-off Value
|
||||||
return true; //If we get to this point and the file has not yet been rejected then accept it
|
if (file.Quality < parsedReport.Quality)
|
||||||
|
{
|
||||||
|
if (episodeInfo.Series.QualityProfile.Cutoff <= file.Quality)
|
||||||
|
{
|
||||||
|
Logger.Trace("Quality is past cut-off skipping.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Debug("Episode {0} is not needed", parsedReport);
|
Logger.Debug("Episode {0} is needed", parsedReport);
|
||||||
return false;
|
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)
|
public virtual void RefreshEpisodeInfo(int seriesId)
|
||||||
|
|
|
@ -50,8 +50,10 @@ namespace NzbDrone.Core.Providers
|
||||||
{
|
{
|
||||||
//Looks for the existence of this episode in History
|
//Looks for the existence of this episode in History
|
||||||
if (_repository.Exists<History>(h => h.EpisodeId == episodeId && h.Quality == quality && h.IsProper == proper))
|
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;
|
return true;
|
||||||
|
}
|
||||||
Logger.Debug("Episode not in History. ID:{0} Q:{1} Proper:{2}", episodeId, quality, proper);
|
Logger.Debug("Episode not in History. ID:{0} Q:{1} Proper:{2}", episodeId, quality, proper);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.ServiceModel.Syndication;
|
using System.ServiceModel.Syndication;
|
||||||
using System.Linq;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Helpers;
|
|
||||||
using NzbDrone.Core.Model;
|
using NzbDrone.Core.Model;
|
||||||
using NzbDrone.Core.Providers.Core;
|
using NzbDrone.Core.Providers.Core;
|
||||||
using NzbDrone.Core.Providers.ExternalNotification;
|
|
||||||
using NzbDrone.Core.Repository;
|
using NzbDrone.Core.Repository;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Providers.Indexer
|
namespace NzbDrone.Core.Providers.Indexer
|
||||||
|
@ -16,33 +12,16 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
public abstract class IndexerProviderBase
|
public abstract class IndexerProviderBase
|
||||||
{
|
{
|
||||||
protected readonly Logger _logger;
|
protected readonly Logger _logger;
|
||||||
protected readonly ConfigProvider _configProvider;
|
|
||||||
protected readonly EpisodeProvider _episodeProvider;
|
|
||||||
private readonly HttpProvider _httpProvider;
|
private readonly HttpProvider _httpProvider;
|
||||||
|
protected readonly ConfigProvider _configProvider;
|
||||||
private readonly IndexerProvider _indexerProvider;
|
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,
|
protected IndexerProviderBase(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider)
|
||||||
EpisodeProvider episodeProvider, ConfigProvider configProvider,
|
|
||||||
HttpProvider httpProvider, IndexerProvider indexerProvider,
|
|
||||||
HistoryProvider historyProvider, SabProvider sabProvider,
|
|
||||||
IEnumerable<ExternalNotificationProviderBase> externalNotificationProvider)
|
|
||||||
{
|
{
|
||||||
_seriesProvider = seriesProvider;
|
|
||||||
_seasonProvider = seasonProvider;
|
|
||||||
_episodeProvider = episodeProvider;
|
|
||||||
_configProvider = configProvider;
|
|
||||||
_httpProvider = httpProvider;
|
_httpProvider = httpProvider;
|
||||||
|
_configProvider = configProvider;
|
||||||
_indexerProvider = indexerProvider;
|
_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());
|
_logger = LogManager.GetLogger(GetType().ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,11 +30,6 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract string Name { get; }
|
public abstract string Name { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a bool to determine if Backlog Searching is Supported
|
|
||||||
/// </summary>
|
|
||||||
public abstract bool SupportsBacklog { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the source URL for the feed
|
/// Gets the source URL for the feed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -80,10 +54,11 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fetches RSS feed and process each news item.
|
/// Fetches RSS feed and process each news item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Exception> Fetch()
|
public List<EpisodeParseResult> Fetch()
|
||||||
{
|
{
|
||||||
_logger.Debug("Fetching feeds from " + Settings.Name);
|
_logger.Debug("Fetching feeds from " + Settings.Name);
|
||||||
var exeptions = new List<Exception>();
|
|
||||||
|
var result = new List<EpisodeParseResult>();
|
||||||
|
|
||||||
foreach (var url in Urls)
|
foreach (var url in Urls)
|
||||||
{
|
{
|
||||||
|
@ -98,11 +73,14 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ProcessItem(item);
|
var parsedEpisode = ParseFeed(item);
|
||||||
|
if (parsedEpisode != null)
|
||||||
|
{
|
||||||
|
result.Add(parsedEpisode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception itemEx)
|
catch (Exception itemEx)
|
||||||
{
|
{
|
||||||
exeptions.Add(itemEx);
|
|
||||||
_logger.ErrorException("An error occurred while processing feed item", itemEx);
|
_logger.ErrorException("An error occurred while processing feed item", itemEx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,123 +88,24 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
}
|
}
|
||||||
catch (Exception feedEx)
|
catch (Exception feedEx)
|
||||||
{
|
{
|
||||||
exeptions.Add(feedEx);
|
|
||||||
_logger.ErrorException("An error occurred while processing feed", feedEx);
|
_logger.ErrorException("An error occurred while processing feed", feedEx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Info("Finished processing feeds from " + Settings.Name);
|
_logger.Info("Finished processing feeds from " + Settings.Name);
|
||||||
return exeptions;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parses the RSS feed item and.
|
/// Parses the RSS feed item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name = "item">RSS feed item to parse</param>
|
/// <param name = "item">RSS feed item to parse</param>
|
||||||
/// <returns>Detailed episode info</returns>
|
/// <returns>Detailed episode info</returns>
|
||||||
public EpisodeParseResult ParseFeed(SyndicationItem item)
|
public EpisodeParseResult ParseFeed(SyndicationItem item)
|
||||||
{
|
{
|
||||||
var episodeParseResult = Parser.ParseEpisodeInfo(item.Title.Text);
|
var episodeParseResult = Parser.ParseEpisodeInfo(item.Title.Text);
|
||||||
if (episodeParseResult == null) return null;
|
|
||||||
|
|
||||||
var seriesInfo = _seriesProvider.FindSeries(episodeParseResult.CleanTitle);
|
return CustomParser(item, episodeParseResult);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -246,18 +125,5 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
/// <param name = "item">RSS Feed item to generate the link for</param>
|
/// <param name = "item">RSS Feed item to generate the link for</param>
|
||||||
/// <returns>Download link URL</returns>
|
/// <returns>Download link URL</returns>
|
||||||
protected abstract string NzbDownloadUrl(SyndicationItem item);
|
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 class NewzbinProvider : IndexerProviderBase
|
||||||
{
|
{
|
||||||
public NewzbinProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
|
public NewzbinProvider(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,11 +34,6 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
get { return "Newzbin"; }
|
get { return "Newzbin"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool SupportsBacklog
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string NzbDownloadUrl(SyndicationItem item)
|
protected override string NzbDownloadUrl(SyndicationItem item)
|
||||||
{
|
{
|
||||||
return item.Id + "/nzb";
|
return item.Id + "/nzb";
|
||||||
|
|
|
@ -11,13 +11,7 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
{
|
{
|
||||||
public class NzbMatrixProvider : IndexerProviderBase
|
public class NzbMatrixProvider : IndexerProviderBase
|
||||||
{
|
{
|
||||||
public NzbMatrixProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
|
public NzbMatrixProvider(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,10 +34,6 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
get { return "NzbMatrix"; }
|
get { return "NzbMatrix"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool SupportsBacklog
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string NzbDownloadUrl(SyndicationItem item)
|
protected override string NzbDownloadUrl(SyndicationItem item)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,13 +10,7 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
{
|
{
|
||||||
public class NzbsOrgProvider : IndexerProviderBase
|
public class NzbsOrgProvider : IndexerProviderBase
|
||||||
{
|
{
|
||||||
public NzbsOrgProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
|
public NzbsOrgProvider(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,10 +30,6 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
get { return "Nzbs.org"; }
|
get { return "Nzbs.org"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool SupportsBacklog
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string NzbDownloadUrl(SyndicationItem item)
|
protected override string NzbDownloadUrl(SyndicationItem item)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,13 +10,7 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
{
|
{
|
||||||
public class NzbsRUsProvider : IndexerProviderBase
|
public class NzbsRUsProvider : IndexerProviderBase
|
||||||
{
|
{
|
||||||
public NzbsRUsProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
|
public NzbsRUsProvider(HttpProvider httpProvider, ConfigProvider configProvider, IndexerProvider indexerProvider) : base(httpProvider, configProvider, indexerProvider)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,12 +33,7 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
get { return "NzbsRUs"; }
|
get { return "NzbsRUs"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool SupportsBacklog
|
protected override string NzbDownloadUrl(SyndicationItem item)
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string NzbDownloadUrl(SyndicationItem item)
|
|
||||||
{
|
{
|
||||||
return item.Links[0].Uri.ToString();
|
return item.Links[0].Uri.ToString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Providers.Core;
|
||||||
using NzbDrone.Core.Repository;
|
using NzbDrone.Core.Repository;
|
||||||
using SubSonic.Repository;
|
using SubSonic.Repository;
|
||||||
|
|
||||||
|
@ -9,10 +12,16 @@ namespace NzbDrone.Core.Providers
|
||||||
public class RootDirProvider
|
public class RootDirProvider
|
||||||
{
|
{
|
||||||
private readonly IRepository _sonioRepo;
|
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;
|
_sonioRepo = sonicRepo;
|
||||||
|
_diskProvider = diskProvider;
|
||||||
|
_seriesProvider = seriesProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IRootDirProvider
|
#region IRootDirProvider
|
||||||
|
@ -42,6 +51,33 @@ namespace NzbDrone.Core.Providers
|
||||||
return _sonioRepo.Single<RootDir>(rootDirId);
|
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
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -92,7 +92,7 @@ namespace NzbDrone.Core.Providers
|
||||||
_configProvider.SabPassword);
|
_configProvider.SabPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String GetSabTitle(EpisodeParseResult parseResult)
|
public String GetSabTitle(EpisodeParseResult parseResult, String folderName)
|
||||||
{
|
{
|
||||||
//Show Name - 1x01-1x02 - Episode Name
|
//Show Name - 1x01-1x02 - Episode Name
|
||||||
//Show Name - 1x01 - Episode Name
|
//Show Name - 1x01 - Episode Name
|
||||||
|
@ -105,7 +105,7 @@ namespace NzbDrone.Core.Providers
|
||||||
|
|
||||||
var epNumberString = String.Join("-", episodeString);
|
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)
|
if (parseResult.Proper)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Core.Helpers;
|
||||||
using NzbDrone.Core.Providers.Core;
|
using NzbDrone.Core.Providers.Core;
|
||||||
using NzbDrone.Core.Repository;
|
using NzbDrone.Core.Repository;
|
||||||
using NzbDrone.Core.Repository.Quality;
|
using NzbDrone.Core.Repository.Quality;
|
||||||
|
@ -108,8 +109,14 @@ namespace NzbDrone.Core.Providers
|
||||||
|
|
||||||
public virtual Series FindSeries(string title)
|
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 normalizeTitle = Parser.NormalizeTitle(title);
|
||||||
|
|
||||||
|
var seriesId = SceneNameHelper.FindByName(normalizeTitle);
|
||||||
|
if (seriesId != 0)
|
||||||
|
{
|
||||||
|
return GetSeries(seriesId);
|
||||||
|
}
|
||||||
|
|
||||||
return _repository.Single<Series>(s => s.CleanTitle == normalizeTitle);
|
return _repository.Single<Series>(s => s.CleanTitle == normalizeTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,41 +11,7 @@ namespace NzbDrone.Core.Providers
|
||||||
{
|
{
|
||||||
public class SyncProvider
|
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())
|
foreach (var folder in _rootFolderProvider.GetAll())
|
||||||
{
|
{
|
||||||
unmappedList.AddRange(_syncProvider.GetUnmappedFolders(folder.Path));
|
unmappedList.AddRange(_rootFolderProvider.GetUnmappedFolders(folder.Path));
|
||||||
}
|
}
|
||||||
|
|
||||||
return View(unmappedList);
|
return View(unmappedList);
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
<supportedRuntime version="v4.0" />
|
<supportedRuntime version="v4.0" />
|
||||||
</startup>
|
</startup>
|
||||||
<appSettings>
|
<appSettings>
|
||||||
<add key="port" value="8989" />
|
<add key="port" value="8980" />
|
||||||
</appSettings>
|
</appSettings>
|
||||||
</configuration>
|
</configuration>
|
Loading…
Reference in New Issue