From 9aa40f546ff27226d68ceef6f0d885d6e11ed0cd Mon Sep 17 00:00:00 2001 From: Qstick Date: Wed, 18 Jul 2018 19:05:01 -0400 Subject: [PATCH] New: Added optional UrlBase to Nzbget, Sabnzbd, and Subsonic settings (#428) * New: Added optional UrlBase to Nzbget, Sabnzbd, and Subsonic settings Fixes #386 * fixup! Remove commented code --- src/NzbDrone.Common/Http/HttpUri.cs | 2 +- .../Download/Clients/Nzbget/Nzbget.cs | 6 +++--- .../Download/Clients/Nzbget/NzbgetProxy.cs | 17 ++++++++++++---- .../Download/Clients/Nzbget/NzbgetSettings.cs | 20 ++++++++++++------- .../Download/Clients/Sabnzbd/Sabnzbd.cs | 12 +++++------ .../Download/Clients/Sabnzbd/SabnzbdProxy.cs | 14 +++++++++---- .../Clients/Sabnzbd/SabnzbdSettings.cs | 19 +++++++++++------- .../Subsonic/SubsonicServerProxy.cs | 14 ++++++++++--- .../Notifications/Subsonic/SubsonicService.cs | 2 +- .../Subsonic/SubsonicSettings.cs | 19 ++++++++++-------- 10 files changed, 81 insertions(+), 44 deletions(-) diff --git a/src/NzbDrone.Common/Http/HttpUri.cs b/src/NzbDrone.Common/Http/HttpUri.cs index 27794e307..a62933e82 100644 --- a/src/NzbDrone.Common/Http/HttpUri.cs +++ b/src/NzbDrone.Common/Http/HttpUri.cs @@ -135,7 +135,7 @@ namespace NzbDrone.Common.Http return new HttpUri(Scheme, Host, Port, CombinePath(Path, path), Query, Fragment); } - private static string CombinePath(string basePath, string relativePath) + public static string CombinePath(string basePath, string relativePath) { if (relativePath.IsNullOrWhiteSpace()) { diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs index 81ef232b0..9c5a205f3 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs @@ -286,7 +286,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { return new NzbDroneValidationFailure("MusicCategory", "Category does not exist") { - InfoLink = string.Format("http://{0}:{1}/", Settings.Host, Settings.Port), + InfoLink = _proxy.GetBaseUrl(Settings), DetailedDescription = "The Category your entered doesn't exist in NzbGet. Go to NzbGet to create it." }; } @@ -304,7 +304,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { return new NzbDroneValidationFailure(string.Empty, "NzbGet setting KeepHistory should be greater than 0") { - InfoLink = string.Format("http://{0}:{1}/", Settings.Host, Settings.Port), + InfoLink = _proxy.GetBaseUrl(Settings), DetailedDescription = "NzbGet setting KeepHistory is set to 0. Which prevents Lidarr from seeing completed downloads." }; } @@ -312,7 +312,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { return new NzbDroneValidationFailure(string.Empty, "NzbGet setting KeepHistory should be less than 25000") { - InfoLink = string.Format("http://{0}:{1}/", Settings.Host, Settings.Port), + InfoLink = _proxy.GetBaseUrl(Settings), DetailedDescription = "NzbGet setting KeepHistory is set too high." }; } diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs index 129d48450..d79108532 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs @@ -11,6 +11,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { public interface INzbgetProxy { + string GetBaseUrl(NzbgetSettings settings, string relativePath = null); string DownloadNzb(byte[] nzbData, string title, string category, int priority, bool addpaused, NzbgetSettings settings); NzbgetGlobalStatus GetGlobalStatus(NzbgetSettings settings); List GetQueue(NzbgetSettings settings); @@ -36,9 +37,17 @@ namespace NzbDrone.Core.Download.Clients.Nzbget _versionCache = cacheManager.GetCache(GetType(), "versions"); } + public string GetBaseUrl(NzbgetSettings settings, string relativePath = null) + { + var baseUrl = HttpRequestBuilder.BuildBaseUrl(settings.UseSsl, settings.Host, settings.Port, settings.UrlBase); + baseUrl = HttpUri.CombinePath(baseUrl, relativePath); + + return baseUrl; + } + private bool HasVersion(int minimumVersion, NzbgetSettings settings) { - var versionString = _versionCache.Find(settings.Host + ":" + settings.Port) ?? GetVersion(settings); + var versionString = _versionCache.Find(GetBaseUrl(settings)) ?? GetVersion(settings); var version = int.Parse(versionString.Split(new[] { '.', '-' })[0]); @@ -139,7 +148,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { var response = ProcessRequest(settings, "version"); - _versionCache.Set(settings.Host + ":" + settings.Port, response, TimeSpan.FromDays(1)); + _versionCache.Set(GetBaseUrl(settings), response, TimeSpan.FromDays(1)); return response; } @@ -170,7 +179,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget queueItem = queue.SingleOrDefault(h => h.Parameters.Any(p => p.Name == "drone" && id == (p.Value as string))); historyItem = history.SingleOrDefault(h => h.Parameters.Any(p => p.Name == "drone" && id == (p.Value as string))); } - + if (queueItem != null) { if (!EditQueue("GroupFinalDelete", 0, "", queueItem.NzbId, settings)) @@ -218,7 +227,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget private T ProcessRequest(NzbgetSettings settings, string method, params object[] parameters) { - var baseUrl = HttpRequestBuilder.BuildBaseUrl(settings.UseSsl, settings.Host, settings.Port, "jsonrpc"); + var baseUrl = GetBaseUrl(settings, "jsonrpc"); var requestBuilder = new JsonRpcRequestBuilder(baseUrl, method, parameters); requestBuilder.LogResponseContent = true; diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs index ea211d2c5..8b8607798 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs @@ -1,4 +1,5 @@ using FluentValidation; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.Validation; @@ -11,6 +12,8 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { RuleFor(c => c.Host).ValidHost(); RuleFor(c => c.Port).InclusiveBetween(1, 65535); + RuleFor(c => c.UrlBase).ValidUrlBase().When(c => c.UrlBase.IsNotNullOrWhiteSpace()); + RuleFor(c => c.Username).NotEmpty().When(c => !string.IsNullOrWhiteSpace(c.Password)); RuleFor(c => c.Password).NotEmpty().When(c => !string.IsNullOrWhiteSpace(c.Username)); @@ -39,25 +42,28 @@ namespace NzbDrone.Core.Download.Clients.Nzbget [FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)] public int Port { get; set; } - [FieldDefinition(2, Label = "Username", Type = FieldType.Textbox)] + [FieldDefinition(2, Label = "Url Base", Type = FieldType.Textbox, Advanced = true, HelpText = "Adds a prefix to the nzbget url, e.g. http://[host]:[port]/[urlBase]/jsonrpc")] + public string UrlBase { get; set; } + + [FieldDefinition(3, Label = "Username", Type = FieldType.Textbox)] public string Username { get; set; } - [FieldDefinition(3, Label = "Password", Type = FieldType.Password)] + [FieldDefinition(4, Label = "Password", Type = FieldType.Password)] public string Password { get; set; } - [FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Lidarr avoids conflicts with unrelated downloads, but it's optional")] + [FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Lidarr avoids conflicts with unrelated downloads, but it's optional")] public string MusicCategory { get; set; } - [FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing albums released within the last 14 days")] + [FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing albums released within the last 14 days")] public int RecentTvPriority { get; set; } - [FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing albums released over 14 days ago")] + [FieldDefinition(7, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing albums released over 14 days ago")] public int OlderTvPriority { get; set; } - [FieldDefinition(7, Label = "Add Paused", Type = FieldType.Checkbox, HelpText = "This option requires at least NzbGet version 16.0")] + [FieldDefinition(8, Label = "Add Paused", Type = FieldType.Checkbox, HelpText = "This option requires at least NzbGet version 16.0")] public bool AddPaused { get; set; } - [FieldDefinition(8, Label = "Use SSL", Type = FieldType.Checkbox)] + [FieldDefinition(9, Label = "Use SSL", Type = FieldType.Checkbox)] public bool UseSsl { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs index 1d0539165..3d20eae70 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs @@ -418,7 +418,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { return new NzbDroneValidationFailure("", "Disable 'Check before download' option in Sabnbzd") { - InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/switches/", Settings.Host, Settings.Port), + InfoLink = _proxy.GetBaseUrl(Settings, "config/switches/"), DetailedDescription = "Using Check before download affects Lidarr ability to track new downloads. Also Sabnzbd recommends 'Abort jobs that cannot be completed' instead since it's more effective." }; } @@ -437,7 +437,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { return new NzbDroneValidationFailure("MusicCategory", "Enable Job folders") { - InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/categories/", Settings.Host, Settings.Port), + InfoLink = _proxy.GetBaseUrl(Settings, "config/categories/"), DetailedDescription = "Lidarr prefers each download to have a separate folder. With * appended to the Folder/Path Sabnzbd will not create these job folders. Go to Sabnzbd to fix it." }; } @@ -448,7 +448,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { return new NzbDroneValidationFailure("MusicCategory", "Category does not exist") { - InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/categories/", Settings.Host, Settings.Port), + InfoLink = _proxy.GetBaseUrl(Settings, "config/categories/"), DetailedDescription = "The Category your entered doesn't exist in Sabnzbd. Go to Sabnzbd to create it." }; } @@ -457,7 +457,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { return new NzbDroneValidationFailure("MusicCategory", "Disable TV Sorting") { - InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port), + InfoLink = _proxy.GetBaseUrl(Settings, "config/sorting/"), DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Lidarr uses to prevent import issues. Go to Sabnzbd to fix it." }; } @@ -465,7 +465,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { return new NzbDroneValidationFailure("MusicCategory", "Disable Movie Sorting") { - InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port), + InfoLink = _proxy.GetBaseUrl(Settings, "config/sorting/"), DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Lidarr uses to prevent import issues. Go to Sabnzbd to fix it." }; } @@ -473,7 +473,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { return new NzbDroneValidationFailure("MusicCategory", "Disable Date Sorting") { - InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port), + InfoLink = _proxy.GetBaseUrl(Settings, "config/sorting/"), DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Lidarr uses to prevent import issues. Go to Sabnzbd to fix it." }; } diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs index 26185cf44..cd103cf1b 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs @@ -11,6 +11,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { public interface ISabnzbdProxy { + string GetBaseUrl(SabnzbdSettings settings, string relativePath = null); SabnzbdAddResponse DownloadNzb(byte[] nzbData, string filename, string category, int priority, SabnzbdSettings settings); void RemoveFrom(string source, string id,bool deleteData, SabnzbdSettings settings); string GetVersion(SabnzbdSettings settings); @@ -32,6 +33,14 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd _logger = logger; } + public string GetBaseUrl(SabnzbdSettings settings, string relativePath = null) + { + var baseUrl = HttpRequestBuilder.BuildBaseUrl(settings.UseSsl, settings.Host, settings.Port, settings.UrlBase); + baseUrl = HttpUri.CombinePath(baseUrl, relativePath); + + return baseUrl; + } + public SabnzbdAddResponse DownloadNzb(byte[] nzbData, string filename, string category, int priority, SabnzbdSettings settings) { var request = BuildRequest("addfile", settings).Post(); @@ -140,10 +149,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd private HttpRequestBuilder BuildRequest(string mode, SabnzbdSettings settings) { - var baseUrl = string.Format(@"{0}://{1}:{2}/api", - settings.UseSsl ? "https" : "http", - settings.Host, - settings.Port); + var baseUrl = GetBaseUrl(settings, "api"); var requestBuilder = new HttpRequestBuilder(baseUrl) .Accept(HttpAccept.Json) diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdSettings.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdSettings.cs index b062eeda8..18be6319d 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdSettings.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdSettings.cs @@ -1,4 +1,5 @@ using FluentValidation; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.Validation; @@ -11,6 +12,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { RuleFor(c => c.Host).ValidHost(); RuleFor(c => c.Port).InclusiveBetween(1, 65535); + RuleFor(c => c.UrlBase).ValidUrlBase().When(c => c.UrlBase.IsNotNullOrWhiteSpace()); RuleFor(c => c.ApiKey).NotEmpty() .WithMessage("API Key is required when username/password are not configured") @@ -49,25 +51,28 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd [FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)] public int Port { get; set; } - [FieldDefinition(2, Label = "API Key", Type = FieldType.Textbox)] + [FieldDefinition(2, Label = "Url Base", Type = FieldType.Textbox, Advanced = true, HelpText = "Adds a prefix to the Sabnzbd url, e.g. http://[host]:[port]/[urlBase]/api")] + public string UrlBase { get; set; } + + [FieldDefinition(3, Label = "API Key", Type = FieldType.Textbox)] public string ApiKey { get; set; } - [FieldDefinition(3, Label = "Username", Type = FieldType.Textbox)] + [FieldDefinition(4, Label = "Username", Type = FieldType.Textbox)] public string Username { get; set; } - [FieldDefinition(4, Label = "Password", Type = FieldType.Password)] + [FieldDefinition(5, Label = "Password", Type = FieldType.Password)] public string Password { get; set; } - [FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Lidarr avoids conflicts with unrelated downloads, but it's optional")] + [FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Lidarr avoids conflicts with unrelated downloads, but it's optional")] public string MusicCategory { get; set; } - [FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing albums released within the last 14 days")] + [FieldDefinition(7, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing albums released within the last 14 days")] public int RecentTvPriority { get; set; } - [FieldDefinition(7, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing albums released over 14 days ago")] + [FieldDefinition(8, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing albums released over 14 days ago")] public int OlderTvPriority { get; set; } - [FieldDefinition(8, Label = "Use SSL", Type = FieldType.Checkbox)] + [FieldDefinition(9, Label = "Use SSL", Type = FieldType.Checkbox)] public bool UseSsl { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Subsonic/SubsonicServerProxy.cs b/src/NzbDrone.Core/Notifications/Subsonic/SubsonicServerProxy.cs index dbd16738a..741701fd1 100644 --- a/src/NzbDrone.Core/Notifications/Subsonic/SubsonicServerProxy.cs +++ b/src/NzbDrone.Core/Notifications/Subsonic/SubsonicServerProxy.cs @@ -1,5 +1,6 @@ using NLog; using NzbDrone.Common.Extensions; +using NzbDrone.Common.Http; using NzbDrone.Core.Rest; using RestSharp; using System.IO; @@ -9,6 +10,7 @@ namespace NzbDrone.Core.Notifications.Subsonic { public interface ISubsonicServerProxy { + string GetBaseUrl(SubsonicSettings settings, string relativePath = null); void Notify(SubsonicSettings settings, string message); void Update(SubsonicSettings settings); string Version(SubsonicSettings settings); @@ -23,6 +25,14 @@ namespace NzbDrone.Core.Notifications.Subsonic _logger = logger; } + public string GetBaseUrl(SubsonicSettings settings, string relativePath = null) + { + var baseUrl = HttpRequestBuilder.BuildBaseUrl(settings.UseSsl, settings.Host, settings.Port, settings.UrlBase); + baseUrl = HttpUri.CombinePath(baseUrl, relativePath); + + return baseUrl; + } + public void Notify(SubsonicSettings settings, string message) { var resource = "addChatMessage"; @@ -68,9 +78,7 @@ namespace NzbDrone.Core.Notifications.Subsonic private RestClient GetSubsonicServerClient(SubsonicSettings settings) { - var protocol = settings.UseSsl ? "https" : "http"; - - return RestClientFactory.BuildClient(string.Format("{0}://{1}:{2}/rest", protocol, settings.Host, settings.Port)); + return RestClientFactory.BuildClient(GetBaseUrl(settings, "rest")); } private RestRequest GetSubsonicServerRequest(string resource, Method method, SubsonicSettings settings) diff --git a/src/NzbDrone.Core/Notifications/Subsonic/SubsonicService.cs b/src/NzbDrone.Core/Notifications/Subsonic/SubsonicService.cs index a2f5b09e5..523b3c77d 100644 --- a/src/NzbDrone.Core/Notifications/Subsonic/SubsonicService.cs +++ b/src/NzbDrone.Core/Notifications/Subsonic/SubsonicService.cs @@ -47,7 +47,7 @@ namespace NzbDrone.Core.Notifications.Subsonic { try { - _logger.Debug("Determining version of Host: {0}", settings.Address); + _logger.Debug("Determining version of Host: {0}", _proxy.GetBaseUrl(settings)); var version = GetVersion(settings); _logger.Debug("Version is: {0}", version); } diff --git a/src/NzbDrone.Core/Notifications/Subsonic/SubsonicSettings.cs b/src/NzbDrone.Core/Notifications/Subsonic/SubsonicSettings.cs index 614e5357c..4fbae8f33 100644 --- a/src/NzbDrone.Core/Notifications/Subsonic/SubsonicSettings.cs +++ b/src/NzbDrone.Core/Notifications/Subsonic/SubsonicSettings.cs @@ -1,5 +1,6 @@ using FluentValidation; using Newtonsoft.Json; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.Validation; @@ -11,6 +12,8 @@ namespace NzbDrone.Core.Notifications.Subsonic public SubsonicSettingsValidator() { RuleFor(c => c.Host).ValidHost(); + RuleFor(c => c.Port).InclusiveBetween(1, 65535); + RuleFor(c => c.UrlBase).ValidUrlBase().When(c => c.UrlBase.IsNotNullOrWhiteSpace()); } } @@ -29,24 +32,24 @@ namespace NzbDrone.Core.Notifications.Subsonic [FieldDefinition(1, Label = "Port")] public int Port { get; set; } - [FieldDefinition(2, Label = "Username")] + [FieldDefinition(2, Label = "Url Base", Type = FieldType.Textbox, Advanced = true, HelpText = "Adds a prefix to the Subsonic url, e.g. http://[host]:[port]/[urlBase]/rest")] + public string UrlBase { get; set; } + + [FieldDefinition(3, Label = "Username")] public string Username { get; set; } - [FieldDefinition(3, Label = "Password", Type = FieldType.Password)] + [FieldDefinition(4, Label = "Password", Type = FieldType.Password)] public string Password { get; set; } - [FieldDefinition(4, Label = "Notify with Chat Message", Type = FieldType.Checkbox)] + [FieldDefinition(5, Label = "Notify with Chat Message", Type = FieldType.Checkbox)] public bool Notify { get; set; } - [FieldDefinition(5, Label = "Update Library", HelpText = "Update Library on Download & Rename?", Type = FieldType.Checkbox)] + [FieldDefinition(6, Label = "Update Library", HelpText = "Update Library on Download & Rename?", Type = FieldType.Checkbox)] public bool UpdateLibrary { get; set; } - [FieldDefinition(6, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Connect to Subsonic over HTTPS instead of HTTP")] + [FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Connect to Subsonic over HTTPS instead of HTTP")] public bool UseSsl { get; set; } - [JsonIgnore] - public string Address => string.Format("{0}:{1}", Host, Port); - public NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this));