From 4f2f5a3d71d77ccc81c17f77a7c66d606de36c08 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Mon, 21 Mar 2011 20:51:03 -0700 Subject: [PATCH] HttpProvider - Added Download File. SabProvider - Added AddById (Newzbin) Fixes to RssItemProcessingProvider Can either download NZB to file or send to SAB... --- NzbDrone.Core/Providers/HttpProvider.cs | 35 +++++ NzbDrone.Core/Providers/IDownloadProvider.cs | 1 + NzbDrone.Core/Providers/IHttpProvider.cs | 2 + .../Providers/IRssItemProcessingProvider.cs | 2 +- .../Providers/RssItemProcessingProvider.cs | 66 ++++++-- NzbDrone.Core/Providers/RssSyncProvider.cs | 2 +- NzbDrone.Core/Providers/SabProvider.cs | 32 +++- .../Controllers/SettingsController.cs | 8 +- NzbDrone.Web/Models/DownloadSettingsModel.cs | 18 ++- NzbDrone.Web/NzbDrone.Web.csproj | 2 + NzbDrone.Web/Views/Settings/Downloads.ascx | 147 ++++++++++++------ 11 files changed, 240 insertions(+), 75 deletions(-) diff --git a/NzbDrone.Core/Providers/HttpProvider.cs b/NzbDrone.Core/Providers/HttpProvider.cs index ec6352c2f..8fc7b587e 100644 --- a/NzbDrone.Core/Providers/HttpProvider.cs +++ b/NzbDrone.Core/Providers/HttpProvider.cs @@ -39,5 +39,40 @@ namespace NzbDrone.Core.Providers return String.Empty; } + + public bool DownloadFile(string request, string filename) + { + try + { + var webClient = new WebClient(); + webClient.DownloadFile(request, filename); + return true; + } + catch (Exception ex) + { + Logger.Warn("Failed to get response from: {0}", request); + Logger.TraceException(ex.Message, ex); + } + + return false; + } + + public bool DownloadFile(string request, string filename, string username, string password) + { + try + { + var webClient = new WebClient(); + webClient.Credentials = new NetworkCredential(username, password); + webClient.DownloadFile(request, filename); + return true; + } + catch (Exception ex) + { + Logger.Warn("Failed to get response from: {0}", request); + Logger.TraceException(ex.Message, ex); + } + + return false; + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/IDownloadProvider.cs b/NzbDrone.Core/Providers/IDownloadProvider.cs index 8b6c52a7c..8cd36844a 100644 --- a/NzbDrone.Core/Providers/IDownloadProvider.cs +++ b/NzbDrone.Core/Providers/IDownloadProvider.cs @@ -4,5 +4,6 @@ { bool AddByUrl(string url, string title); //Should accept something other than string (NzbInfo?) returns success or failure bool IsInQueue(string title); //Should accept something other than string (Episode?) returns bool + bool AddById(string id, string title); } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/IHttpProvider.cs b/NzbDrone.Core/Providers/IHttpProvider.cs index 485f8a312..3b8d78702 100644 --- a/NzbDrone.Core/Providers/IHttpProvider.cs +++ b/NzbDrone.Core/Providers/IHttpProvider.cs @@ -4,5 +4,7 @@ { string DownloadString(string request); string DownloadString(string request, string username, string password); + bool DownloadFile(string request, string filename); + bool DownloadFile(string request, string filename, string username, string password); } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/IRssItemProcessingProvider.cs b/NzbDrone.Core/Providers/IRssItemProcessingProvider.cs index c57fb2c81..fa536ddae 100644 --- a/NzbDrone.Core/Providers/IRssItemProcessingProvider.cs +++ b/NzbDrone.Core/Providers/IRssItemProcessingProvider.cs @@ -11,7 +11,7 @@ namespace NzbDrone.Core.Providers { //This interface will contain methods to process individual RSS Feed Items (Queue if wanted) - void QueueIfWanted(NzbInfoModel nzb, Indexer indexer); + bool DownloadIfWanted(NzbInfoModel nzb, Indexer indexer); string GetTitleFix(List episodes, int seriesId); } } diff --git a/NzbDrone.Core/Providers/RssItemProcessingProvider.cs b/NzbDrone.Core/Providers/RssItemProcessingProvider.cs index 4b6bc0506..6630c14ad 100644 --- a/NzbDrone.Core/Providers/RssItemProcessingProvider.cs +++ b/NzbDrone.Core/Providers/RssItemProcessingProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using NLog; @@ -17,12 +18,15 @@ namespace NzbDrone.Core.Providers private IHistoryProvider _historyProvider; private IDownloadProvider _sabProvider; private IConfigProvider _configProvider; + private IHttpProvider _httpProvider; + private IDiskProvider _diskProvider; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public RssItemProcessingProvider(ISeriesProvider seriesProvider, ISeasonProvider seasonProvider, IEpisodeProvider episodeProvider, IHistoryProvider historyProvider, - IDownloadProvider sabProvider, IConfigProvider configProvider) + IDownloadProvider sabProvider, IConfigProvider configProvider, + IHttpProvider httpProvider, IDiskProvider diskProvider) { _seriesProvider = seriesProvider; _seasonProvider = seasonProvider; @@ -30,11 +34,13 @@ namespace NzbDrone.Core.Providers _historyProvider = historyProvider; _sabProvider = sabProvider; _configProvider = configProvider; + _httpProvider = httpProvider; + _diskProvider = diskProvider; } #region IRssItemProcessingProvider Members - public void QueueIfWanted(NzbInfoModel nzb, Indexer indexer) + public bool DownloadIfWanted(NzbInfoModel nzb, Indexer indexer) { //Do we want this item? try @@ -42,7 +48,7 @@ namespace NzbDrone.Core.Providers if (nzb.IsPassworded()) { Logger.Debug("Skipping Passworded Report {0}", nzb.Title); - return; + return false; } var episodeParseResults = Parser.ParseEpisodeInfo(nzb.Title); @@ -50,15 +56,15 @@ namespace NzbDrone.Core.Providers if (episodeParseResults.Count() > 1) { ProcessStandardItem(nzb, indexer, episodeParseResults); - return; + return false; } - //Try to handle Season X style naming + //Todo: Try to handle Season X style naming if (episodeParseResults.Count() < 1) { Logger.Debug("Unsupported Title: {0}", nzb.Title); - return; + return false; } } @@ -66,6 +72,7 @@ namespace NzbDrone.Core.Providers { Logger.ErrorException("Error Parsing NZB: " + ex.Message, ex); } + return false; } public string GetTitleFix(List episodes, int seriesId) @@ -142,25 +149,50 @@ namespace NzbDrone.Core.Providers var titleFix = GetTitleFix(new List { episode }, episodeModel.SeriesId); titleFix = String.Format("{0} [{1}]", titleFix, nzb.Quality); //Add Quality to the titleFix - if (_sabProvider.IsInQueue(titleFix)) - return; + if (Convert.ToBoolean(_configProvider.GetValue("UseBlackhole", true, true))) + if (_sabProvider.IsInQueue(titleFix)) + return; } //If their is more than one episode in this NZB check to see if it has been added as a single NZB - if (episodeParseResults.Count > 1) + + //Do we want to download the NZB Directly or Send to SABnzbd? + + if (Convert.ToBoolean(_configProvider.GetValue("UseBlackHole", true, true))) { - if (_sabProvider.IsInQueue(nzb.TitleFix)) - return; + var path = _configProvider.GetValue("BlackholeDirectory", String.Empty, true); + + if (String.IsNullOrEmpty(path)) + { + //Use the NZBDrone root Directory + /NZBs + path = CentralDispatch.AppPath + Path.DirectorySeparatorChar + "NZBs"; + } + + if (_diskProvider.FolderExists(path)) + _httpProvider.DownloadFile(nzb.Link.ToString(), path); + + else + Logger.Error("Blackhole Directory doesn't exist, not saving NZB: '{0}'", path); } - - //Only add to history if it was added to properly sent to SABnzbd - if (indexer.IndexerName != "Newzbin") - AddByUrl(episodeParseResults, series, nzb, indexer); - + + //Send it to SABnzbd else { - //AddById(episodeParseResults, series, nzb, indexer); + if (episodeParseResults.Count > 1) + { + if (_sabProvider.IsInQueue(nzb.TitleFix)) + return; + } + + if (indexer.IndexerName != "Newzbin") + AddByUrl(episodeParseResults, series, nzb, indexer); + + else + { + //AddById(episodeParseResults, series, nzb, indexer); + } } + } private void AddByUrl(List episodeParseResults, Series series, NzbInfoModel nzb, Indexer indexer) diff --git a/NzbDrone.Core/Providers/RssSyncProvider.cs b/NzbDrone.Core/Providers/RssSyncProvider.cs index f86ddb0be..d73e73024 100644 --- a/NzbDrone.Core/Providers/RssSyncProvider.cs +++ b/NzbDrone.Core/Providers/RssSyncProvider.cs @@ -118,7 +118,7 @@ namespace NzbDrone.Core.Providers foreach (RssItem item in feedItems) { NzbInfoModel nzb = Parser.ParseNzbInfo(indexer, item); - _rssItemProcessor.QueueIfWanted(nzb, i); + _rssItemProcessor.DownloadIfWanted(nzb, i); } } _rssSyncNotification.CurrentStatus = "RSS Sync Completed"; diff --git a/NzbDrone.Core/Providers/SabProvider.cs b/NzbDrone.Core/Providers/SabProvider.cs index 08ec288e1..1b60d60f3 100644 --- a/NzbDrone.Core/Providers/SabProvider.cs +++ b/NzbDrone.Core/Providers/SabProvider.cs @@ -24,9 +24,9 @@ namespace NzbDrone.Core.Providers public bool AddByUrl(string url, string title) { const string mode = "addurl"; - //string cat = _config.GetValue("SabTvCategory", String.Empty, true); - string cat = "tv"; - string priority = _config.GetValue("SabPriority", String.Empty, false); + string cat = _config.GetValue("SabTvCategory", String.Empty, true); + //string cat = "tv"; + string priority = _config.GetValue("SabTvPriority", String.Empty, false); string name = url.Replace("&", "%26"); string nzbName = HttpUtility.UrlEncode(title); @@ -70,6 +70,32 @@ namespace NzbDrone.Core.Providers return false; //Not in Queue } + public bool AddById(string id, string title) + { + //mode=addid&name=333333&pp=3&script=customscript.cmd&cat=Example&priority=-1 + + const string mode = "addid"; + string cat = _config.GetValue("SabTvCategory", String.Empty, true); + //string cat = "tv"; + string priority = _config.GetValue("SabTvPriority", String.Empty, false); + string nzbName = HttpUtility.UrlEncode(title); + + string action = string.Format("mode={0}&name={1}&priority={2}&cat={3}&nzbname={4}", mode, id, priority, cat, nzbName); + string request = GetSabRequest(action); + + Logger.Debug("Adding report [{0}] to the queue.", nzbName); + + string response = _http.DownloadString(request).Replace("\n", String.Empty); + Logger.Debug("Queue Repsonse: [{0}]", response); + + if (response == "ok") + return true; + + return false; + + throw new NotImplementedException(); + } + #endregion private string GetSabRequest(string action) diff --git a/NzbDrone.Web/Controllers/SettingsController.cs b/NzbDrone.Web/Controllers/SettingsController.cs index 97dab51fd..af85a78bd 100644 --- a/NzbDrone.Web/Controllers/SettingsController.cs +++ b/NzbDrone.Web/Controllers/SettingsController.cs @@ -87,7 +87,9 @@ namespace NzbDrone.Web.Controllers SabUsername = _configProvider.GetValue("SabUsername", String.Empty, true), SabPassword = _configProvider.GetValue("SabPassword", String.Empty, true), SabTvCategory = _configProvider.GetValue("SabTvCategory", String.Empty, true), - SabPriority = (SabnzbdPriorityType)Enum.Parse(typeof(SabnzbdPriorityType), _configProvider.GetValue("SabPriority", "Normal", true)), + SabTvPriority = (SabnzbdPriorityType)Enum.Parse(typeof(SabnzbdPriorityType), _configProvider.GetValue("SabTvPriority", "Normal", true)), + UseBlackHole = Convert.ToBoolean(_configProvider.GetValue("UseBlackHole", true, true)), + BlackholeDirectory = _configProvider.GetValue("BlackholeDirectory", String.Empty, true) }; return View("Index", model); @@ -275,7 +277,9 @@ namespace NzbDrone.Web.Controllers _configProvider.SetValue("SabUsername", data.SabUsername); _configProvider.SetValue("SabPassword", data.SabPassword); _configProvider.SetValue("SabTvCategory", data.SabTvCategory); - _configProvider.SetValue("SabPriority", data.SabPriority.ToString()); + _configProvider.SetValue("SabTvPriority", data.SabTvPriority.ToString()); + _configProvider.SetValue("UseBlackhole", data.UseBlackHole.ToString()); + _configProvider.SetValue("BlackholeDirectory", data.BlackholeDirectory); return Content(_settingsSaved); } diff --git a/NzbDrone.Web/Models/DownloadSettingsModel.cs b/NzbDrone.Web/Models/DownloadSettingsModel.cs index 91298e2fb..368aaf9fd 100644 --- a/NzbDrone.Web/Models/DownloadSettingsModel.cs +++ b/NzbDrone.Web/Models/DownloadSettingsModel.cs @@ -93,7 +93,23 @@ namespace NzbDrone.Web.Models [Required(ErrorMessage = "Please select a valid priority")] [DisplayName("SABnzbd Priority")] - public SabnzbdPriorityType SabPriority + public SabnzbdPriorityType SabTvPriority + { + get; + set; + } + + [DisplayName("Use Blackhole")] + public bool UseBlackHole + { + get; + set; + } + + [DataType(DataType.Text)] + [DisplayFormat(ConvertEmptyStringToNull = false)] + [DisplayName("Blackhole Directory")] + public String BlackholeDirectory { get; set; diff --git a/NzbDrone.Web/NzbDrone.Web.csproj b/NzbDrone.Web/NzbDrone.Web.csproj index 6d3d0db21..a2577afe1 100644 --- a/NzbDrone.Web/NzbDrone.Web.csproj +++ b/NzbDrone.Web/NzbDrone.Web.csproj @@ -78,6 +78,7 @@ + @@ -276,6 +277,7 @@ + diff --git a/NzbDrone.Web/Views/Settings/Downloads.ascx b/NzbDrone.Web/Views/Settings/Downloads.ascx index a0999d93a..1763d6021 100644 --- a/NzbDrone.Web/Views/Settings/Downloads.ascx +++ b/NzbDrone.Web/Views/Settings/Downloads.ascx @@ -10,9 +10,24 @@ resetForm: false }; $('#form').ajaxForm(options); + selectDownloadOption(); //Load either SAB or Blackhole div $('#save_button').attr('disabled', ''); }); + function selectDownloadOption() { + var selected = $("input[name='UseBlackHole']:checked").val(); + + if (selected == "True") { + document.getElementById('blackhole').style.display = 'block'; + document.getElementById('sab').style.display = 'none'; + } + + else { + document.getElementById('sab').style.display = 'block'; + document.getElementById('blackhole').style.display = 'none'; + } + } + function showRequest(formData, jqForm, options) { $("#result").empty().html('Saving...'); $("#form :input").attr("disabled", true); @@ -21,7 +36,11 @@ function showResponse(responseText, statusText, xhr, $form) { $("#result").empty().html(responseText); $("#form :input").attr("disabled", false); - } + } + + $(".blackhole_radio").live("change", function () { + selectDownloadOption(); //Load either SAB or Blackhole div + }); <% Html.EnableClientValidation(); %> @@ -72,65 +91,93 @@ -
- SABnzbd - -
-
-
<%= Html.LabelFor(m => m.SabHost)%>
-
<%= Html.TextBoxFor(m => m.SabHost)%>
-
-
<%= Html.ValidationMessageFor(m => m.SabHost)%>
+
+
+ <%= Html.LabelFor(m => m.UseBlackHole) %>
- -
-
-
<%= Html.LabelFor(m => m.SabPort)%>
-
<%= Html.TextBoxFor(m => m.SabPort)%>
-
-
<%= Html.ValidationMessageFor(m => m.SabPort)%>
+
+ <%= Html.RadioButtonFor(m => m.UseBlackHole, true, new { @class = "blackhole_radio" }) %>Blackhole
- -
-
-
<%= Html.LabelFor(m => m.SabApiKey)%>
-
<%= Html.TextBoxFor(m => m.SabApiKey)%>
-
-
<%= Html.ValidationMessageFor(m => m.SabApiKey)%>
+
+ <%= Html.RadioButtonFor(m => m.UseBlackHole, false, new { @class = "blackhole_radio" })%>SABnzbd
+
-
-
-
<%= Html.LabelFor(m => m.SabUsername)%>
-
<%= Html.TextBoxFor(m => m.SabUsername)%>
-
-
<%= Html.ValidationMessageFor(m => m.SabUsername)%>
-
+
+ + +