Fixed: Sabnzbd now verifies the category configuration.

This commit is contained in:
Taloth Saldono 2014-07-04 22:27:21 +02:00
parent 6941888832
commit 232a2b9422
10 changed files with 194 additions and 58 deletions

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers;
@ -19,11 +20,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
private readonly IHttpProvider _httpProvider;
public Nzbget(INzbgetProxy proxy,
IConfigService configService,
IParsingService parsingService,
IHttpProvider httpProvider,
IConfigService configService,
IDiskProvider diskProvider,
IParsingService parsingService,
Logger logger)
: base(configService, parsingService, logger)
: base(configService, diskProvider, parsingService, logger)
{
_proxy = proxy;
_httpProvider = httpProvider;
@ -259,11 +261,6 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
}
}
private String GetVersion(string host = null, int port = 0, string username = null, string password = null)
{
return _proxy.GetVersion(Settings);
}
public override ValidationResult Test()
{
var failures = new List<ValidationFailure>();
@ -271,6 +268,11 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
failures.AddIfNotNull(TestConnection());
failures.AddIfNotNull(TestCategory());
if (!Settings.TvCategoryLocalPath.IsNullOrWhiteSpace())
{
failures.AddIfNotNull(TestFolder(Settings.TvCategoryLocalPath, "TvCategoryLocalPath"));
}
return new ValidationResult(failures);
}

View File

@ -17,17 +17,15 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
public class Pneumatic : DownloadClientBase<PneumaticSettings>
{
private readonly IHttpProvider _httpProvider;
private readonly IDiskProvider _diskProvider;
public Pneumatic(IHttpProvider httpProvider,
IDiskProvider diskProvider,
IConfigService configService,
IDiskProvider diskProvider,
IParsingService parsingService,
Logger logger)
: base(configService, parsingService, logger)
: base(configService, diskProvider, parsingService, logger)
{
_httpProvider = httpProvider;
_diskProvider = diskProvider;
}
public override DownloadProtocol Protocol

View File

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses
{
public class SabnzbdConfigResponse
{
public SabnzbdConfig Config { get; set; }
}
}

View File

@ -5,6 +5,7 @@ using System.Linq;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers;
@ -18,15 +19,16 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
private readonly IHttpProvider _httpProvider;
private readonly ISabnzbdProxy _proxy;
public Sabnzbd(IHttpProvider httpProvider,
ISabnzbdProxy proxy,
public Sabnzbd(ISabnzbdProxy proxy,
IHttpProvider httpProvider,
IConfigService configService,
IDiskProvider diskProvider,
IParsingService parsingService,
Logger logger)
: base(configService, parsingService, logger)
: base(configService, diskProvider, parsingService, logger)
{
_httpProvider = httpProvider;
_proxy = proxy;
_httpProvider = httpProvider;
}
public override DownloadProtocol Protocol
@ -207,13 +209,67 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
_proxy.RetryDownload(id, Settings);
}
protected IEnumerable<SabnzbdCategory> GetCategories(SabnzbdConfig config)
{
var completeDir = config.Misc.complete_dir.TrimEnd('\\', '/');
foreach (var category in config.Categories)
{
var relativeDir = category.Dir.TrimEnd('*');
if (relativeDir.IsNullOrWhiteSpace())
{
category.FullPath = completeDir;
}
else if (completeDir.StartsWith("/"))
{ // Process remote Linux paths irrespective of our own OS.
if (relativeDir.StartsWith("/"))
{
category.FullPath = relativeDir;
}
else
{
category.FullPath = completeDir + "/" + relativeDir;
}
}
else
{ // Process remote Windows paths irrespective of our own OS.
if (relativeDir.StartsWith("\\") || relativeDir.Contains(':'))
{
category.FullPath = relativeDir;
}
else
{
category.FullPath = completeDir + "\\" + relativeDir;
}
}
yield return category;
}
}
public override DownloadClientStatus GetStatus()
{
var config = _proxy.GetConfig(Settings);
var categories = GetCategories(config).ToArray();
var category = categories.FirstOrDefault(v => v.Name == Settings.TvCategory);
if (category == null)
{
category = categories.FirstOrDefault(v => v.Name == "*");
}
var status = new DownloadClientStatus
{
IsLocalhost = Settings.Host == "127.0.0.1" || Settings.Host == "localhost"
};
if (category != null)
{
status.OutputRootFolders = new List<String> { category.FullPath };
}
return status;
}
@ -224,6 +280,11 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
failures.AddIfNotNull(TestConnection());
failures.AddIfNotNull(TestCategory());
if (!Settings.TvCategoryLocalPath.IsNullOrWhiteSpace())
{
failures.AddIfNotNull(TestFolder(Settings.TvCategoryLocalPath, "TvCategoryLocalPath"));
}
return new ValidationResult(failures);
}
@ -231,7 +292,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
try
{
_proxy.GetCategories(Settings);
_proxy.GetVersion(Settings);
}
catch (Exception ex)
{
@ -244,11 +305,32 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
private ValidationFailure TestCategory()
{
var categories = _proxy.GetCategories(Settings);
var config = this._proxy.GetConfig(Settings);
var category = GetCategories(config).FirstOrDefault((SabnzbdCategory v) => v.Name == Settings.TvCategory);
if (!Settings.TvCategory.IsNullOrWhiteSpace() && !categories.Any(v => v == Settings.TvCategory))
if (category != null)
{
return new ValidationFailure("TvCategory", "Category does not exist");
if (category.Dir.EndsWith("*"))
{
return new ValidationFailure(String.Empty, String.Format("Remove * from Sabnzbd <a class=\"no-router\" target=\"_blank\" href=\"http://{0}:{1}/sabnzbd/config/categories/\">'{2}' category</a> Folder/Path so job folders will be created", Settings.Host, Settings.Port, Settings.TvCategory));
}
}
else
{
if (!Settings.TvCategory.IsNullOrWhiteSpace())
{
return new ValidationFailure("TvCategory", String.Format("<a class=\"no-router\" target=\"_blank\" href=\"http://{0}:{1}/sabnzbd/config/categories/\">Category</a> does not exist", Settings.Host, Settings.Port));
}
}
if (config.Misc.enable_tv_sorting)
{
if (!config.Misc.tv_categories.Any<string>() ||
config.Misc.tv_categories.Contains(Settings.TvCategory) ||
(Settings.TvCategory.IsNullOrWhiteSpace() && config.Misc.tv_categories.Contains("Default")))
{
return new ValidationFailure(String.Empty, String.Format("Disable <a class=\"no-router\" target=\"_blank\" href=\"http://{0}:{1}/sabnzbd/config/sorting/\">TV Sorting</a> for the '{2}' category", Settings.Host, Settings.Port, Settings.TvCategory));
}
}
return null;

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
public class SabnzbdConfig
{
public SabnzbdConfigMisc Misc { get; set; }
public List<SabnzbdCategory> Categories { get; set; }
public List<Object> Servers { get; set; }
}
public class SabnzbdConfigMisc
{
public String complete_dir { get; set; }
public String[] tv_categories { get; set; }
public Boolean enable_tv_sorting { get; set; }
}
public class SabnzbdCategory
{
public Int32 Priority { get; set; }
public String PP { get; set; }
public String Name { get; set; }
public String Script { get; set; }
public String Dir { get; set; }
public String FullPath { get; set; }
}
}

View File

@ -18,7 +18,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
void RemoveFrom(string source, string id, SabnzbdSettings settings);
string ProcessRequest(IRestRequest restRequest, string action, SabnzbdSettings settings);
SabnzbdVersionResponse GetVersion(SabnzbdSettings settings);
List<String> GetCategories(SabnzbdSettings settings);
SabnzbdConfig GetConfig(SabnzbdSettings settings);
SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings);
SabnzbdHistory GetHistory(int start, int limit, SabnzbdSettings settings);
void RetryDownload(string id, SabnzbdSettings settings);
@ -85,14 +85,14 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
return response;
}
public List<String> GetCategories(SabnzbdSettings settings)
public SabnzbdConfig GetConfig(SabnzbdSettings settings)
{
var request = new RestRequest();
var action = "mode=get_cats";
var action = "mode=get_config";
var response = Json.Deserialize<SabnzbdCategoryResponse>(ProcessRequest(request, action, settings)).Categories;
var response = Json.Deserialize<SabnzbdConfigResponse>(ProcessRequest(request, action, settings));
return response;
return response.Config;
}
public SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings)

View File

@ -18,19 +18,17 @@ namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
{
public class UsenetBlackhole : DownloadClientBase<UsenetBlackholeSettings>
{
private readonly IDiskProvider _diskProvider;
private readonly IDiskScanService _diskScanService;
private readonly IHttpProvider _httpProvider;
public UsenetBlackhole(IDiskProvider diskProvider,
IDiskScanService diskScanService,
public UsenetBlackhole(IDiskScanService diskScanService,
IHttpProvider httpProvider,
IConfigService configService,
IDiskProvider diskProvider,
IParsingService parsingService,
Logger logger)
: base(configService, parsingService, logger)
: base(configService, diskProvider, parsingService, logger)
{
_diskProvider = diskProvider;
_diskScanService = diskScanService;
_httpProvider = httpProvider;
}
@ -149,32 +147,10 @@ namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
{
var failures = new List<ValidationFailure>();
failures.AddIfNotNull(TestWrite(Settings.NzbFolder, "NzbFolder"));
failures.AddIfNotNull(TestWrite(Settings.WatchFolder, "WatchFolder"));
failures.AddIfNotNull(TestFolder(Settings.NzbFolder, "NzbFolder"));
failures.AddIfNotNull(TestFolder(Settings.WatchFolder, "WatchFolder"));
return new ValidationResult(failures);
}
private ValidationFailure TestWrite(String folder, String propertyName)
{
if (!_diskProvider.FolderExists(folder))
{
return new ValidationFailure(propertyName, "Folder does not exist");
}
try
{
var testPath = Path.Combine(folder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
}
catch (Exception ex)
{
_logger.ErrorException(ex.Message, ex);
return new ValidationFailure(propertyName, "Unable to write to folder");
}
return null;
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using FluentValidation.Results;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
@ -14,7 +15,8 @@ namespace NzbDrone.Core.Download
where TSettings : IProviderConfig, new()
{
protected readonly IConfigService _configService;
private readonly IParsingService _parsingService;
protected readonly IDiskProvider _diskProvider;
protected readonly IParsingService _parsingService;
protected readonly Logger _logger;
public Type ConfigContract
@ -44,9 +46,10 @@ namespace NzbDrone.Core.Download
}
}
protected DownloadClientBase(IConfigService configService, IParsingService parsingService, Logger logger)
protected DownloadClientBase(IConfigService configService, IDiskProvider diskProvider, IParsingService parsingService, Logger logger)
{
_configService = configService;
_diskProvider = diskProvider;
_parsingService = parsingService;
_logger = logger;
}
@ -77,5 +80,30 @@ namespace NzbDrone.Core.Download
return remoteEpisode;
}
protected ValidationFailure TestFolder(String folder, String propertyName, Boolean mustBeWritable = true)
{
if (!_diskProvider.FolderExists(folder))
{
return new ValidationFailure(propertyName, "Folder does not exist");
}
if (mustBeWritable)
{
try
{
var testPath = Path.Combine(folder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
}
catch (Exception ex)
{
_logger.ErrorException(ex.Message, ex);
return new ValidationFailure(propertyName, "Unable to write to folder");
}
}
return null;
}
}
}

View File

@ -42,7 +42,11 @@ namespace NzbDrone.Core.HealthCheck.Checks
if (downloadClients.All(v => v.downloadClient is Sabnzbd))
{
// With Sabnzbd we cannot check the category settings.
// With Sabnzbd we can check if the category should be changed.
if (downloadClientOutputInDroneFactory)
{
return new HealthCheck(GetType(), HealthCheckResult.Warning, "Enable Completed Download Handling if possible (Sabnzbd - Conflicting Category)", "Migrating-to-Completed-Download-Handling#sabnzbd-conflicting-download-client-category");
}
return new HealthCheck(GetType(), HealthCheckResult.Warning, "Enable Completed Download Handling if possible (Sabnzbd)", "Migrating-to-Completed-Download-Handling#sabnzbd-enable-completed-download-handling");
}

View File

@ -251,7 +251,6 @@
<Compile Include="Download\Clients\Nzbget\NzbgetConfigItem.cs" />
<Compile Include="Download\Clients\Nzbget\NzbgetGlobalStatus.cs" />
<Compile Include="Download\Clients\Nzbget\NzbgetPostQueueItem.cs" />
<Compile Include="Download\Clients\Sabnzbd\SabnzbdDownloadStatus.cs" />
<Compile Include="Download\Clients\UsenetBlackhole\UsenetBlackhole.cs" />
<Compile Include="Download\Clients\UsenetBlackhole\UsenetBlackholeSettings.cs" />
<Compile Include="Download\Clients\DownloadClientException.cs" />
@ -262,8 +261,11 @@
<Compile Include="Download\Clients\Pneumatic\Pneumatic.cs" />
<Compile Include="Download\Clients\Sabnzbd\Responses\SabnzbdAddResponse.cs" />
<Compile Include="Download\Clients\Sabnzbd\Responses\SabnzbdCategoryResponse.cs" />
<Compile Include="Download\Clients\Sabnzbd\Responses\SabnzbdConfigResponse.cs" />
<Compile Include="Download\Clients\Sabnzbd\Responses\SabnzbdVersionResponse.cs" />
<Compile Include="Download\Clients\Sabnzbd\SabnzbdSettings.cs" />
<Compile Include="Download\Clients\Sabnzbd\SabnzbdCategory.cs" />
<Compile Include="Download\Clients\Sabnzbd\SabnzbdDownloadStatus.cs" />
<Compile Include="Download\CompletedDownloadService.cs" />
<Compile Include="Download\DownloadClientBase.cs" />
<Compile Include="Download\DownloadClientDefinition.cs" />