Merge remote-tracking branch 'origin/develop' into develop

Leonardo Galli 7 years ago
commit d0174c7b7b

@ -115,10 +115,17 @@ Radarr is currently undergoing rapid development and pull requests are actively
> **Notice**
> Gulp must be running at all times while you are working with Radarr client source files.
### Build
* To build run `sh build.sh`
**Note:** Windows users must have bash available to do this. [cmder](http://cmder.net/) which is a console emulator for windows has bash as part of it's default installation.
### Development
* Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed
* Make sure `NzbDrone.Console` is set as the startup project
* Run `build.sh` before running
### License

@ -30,7 +30,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
Port = 2222,
Username = "admin",
Password = "pass",
TvCategory = "tv",
MovieCategory = "movie",
RecentTvPriority = (int)NzbgetPriority.High
};
@ -38,7 +38,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
{
FileSizeLo = 1000,
RemainingSizeLo = 10,
Category = "tv",
Category = "movie",
NzbName = "Droned.1998.1080p.WEB-DL-DRONE",
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } }
};
@ -46,7 +46,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
_failed = new NzbgetHistoryItem
{
FileSizeLo = 1000,
Category = "tv",
Category = "movie",
Name = "Droned.1998.1080p.WEB-DL-DRONE",
DestDir = "somedirectory",
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } },
@ -61,7 +61,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
_completed = new NzbgetHistoryItem
{
FileSizeLo = 1000,
Category = "tv",
Category = "movie",
Name = "Droned.1998.1080p.WEB-DL-DRONE",
DestDir = "/remote/mount/tv/Droned.1998.1080p.WEB-DL-DRONE",
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } },
@ -81,8 +81,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
});
var configItems = new Dictionary<string, string>();
configItems.Add("Category1.Name", "tv");
configItems.Add("Category1.DestDir", @"/remote/mount/tv");
configItems.Add("Category1.Name", "movie");
configItems.Add("Category1.DestDir", @"/remote/mount/movie");
Mocker.GetMock<INzbgetProxy>()
.Setup(v => v.GetConfig(It.IsAny<NzbgetSettings>()))

@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
ApiKey = "5c770e3197e4fe763423ee7c392c25d1",
Username = "admin",
Password = "pass",
TvCategory = "tv",
MovieCategory = "movie",
RecentTvPriority = (int)SabnzbdPriority.High
};
_queued = new SabnzbdQueue
@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
Size = 1000,
Sizeleft = 10,
Timeleft = TimeSpan.FromSeconds(10),
Category = "tv",
Category = "movie",
Id = "sabnzbd_nzb12345",
Title = "Droned.1998.1080p.WEB-DL-DRONE"
}
@ -66,7 +66,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
{
Status = SabnzbdDownloadStatus.Failed,
Size = 1000,
Category = "tv",
Category = "movie",
Id = "sabnzbd_nzb12345",
Title = "Droned.1998.1080p.WEB-DL-DRONE"
}
@ -81,7 +81,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
{
Status = SabnzbdDownloadStatus.Completed,
Size = 1000,
Category = "tv",
Category = "movie",
Id = "sabnzbd_nzb12345",
Title = "Droned.1998.1080p.WEB-DL-DRONE",
Storage = "/remote/mount/vv/Droned.1998.1080p.WEB-DL-DRONE"
@ -97,7 +97,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
},
Categories = new List<SabnzbdCategory>
{
new SabnzbdCategory { Name = "tv", Dir = "vv" }
new SabnzbdCategory { Name = "movie", Dir = "vv" }
}
};
@ -111,7 +111,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
_fullStatus = new SabnzbdFullStatus
{
CompleteDir = @"Y:\nzbget\root\complete".AsOsAgnostic()
CompleteDir = @"Y:\sabnzbd\root\complete".AsOsAgnostic()
};
Mocker.GetMock<ISabnzbdProxy>()
@ -408,10 +408,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
result.OutputPath.Should().Be(@"C:\sorted\somewhere\asdfasdf\asdfasdf.mkv".AsOsAgnostic());
}
[TestCase(@"Y:\nzbget\root", @"completed\downloads", @"vv", @"Y:\nzbget\root\completed\downloads", @"Y:\nzbget\root\completed\downloads\vv")]
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed", @"Y:\nzbget\root\completed\vv")]
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads", @"/nzbget/root/completed/downloads/vv")]
[TestCase(@"/nzbget/root", @"completed", @"vv", @"/nzbget/root/completed", @"/nzbget/root/completed/vv")]
[TestCase(@"Y:\sabnzbd\root", @"completed\downloads", @"vv", @"Y:\sabnzbd\root\completed\downloads", @"Y:\sabnzbd\root\completed\downloads\vv")]
[TestCase(@"Y:\sabnzbd\root", @"completed", @"vv", @"Y:\sabnzbd\root\completed", @"Y:\sabnzbd\root\completed\vv")]
[TestCase(@"/sabnzbd/root", @"completed/downloads", @"vv", @"/sabnzbd/root/completed/downloads", @"/sabnzbd/root/completed/downloads/vv")]
[TestCase(@"/sabnzbd/root", @"completed", @"vv", @"/sabnzbd/root/completed", @"/sabnzbd/root/completed/vv")]
public void should_return_status_with_outputdir_for_version_lt_2(string rootFolder, string completeDir, string categoryDir, string fullCompleteDir, string fullCategoryDir)
{
_fullStatus.CompleteDir = null;
@ -429,10 +429,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
result.OutputRootFolders.First().Should().Be(fullCategoryDir);
}
[TestCase(@"Y:\nzbget\root", @"completed\downloads", @"vv", @"Y:\nzbget\root\completed\downloads", @"Y:\nzbget\root\completed\downloads\vv")]
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed", @"Y:\nzbget\root\completed\vv")]
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads", @"/nzbget/root/completed/downloads/vv")]
[TestCase(@"/nzbget/root", @"completed", @"vv", @"/nzbget/root/completed", @"/nzbget/root/completed/vv")]
[TestCase(@"Y:\sabnzbd\root", @"completed\downloads", @"vv", @"Y:\sabnzbd\root\completed\downloads", @"Y:\sabnzbd\root\completed\downloads\vv")]
[TestCase(@"Y:\sabnzbd\root", @"completed", @"vv", @"Y:\sabnzbd\root\completed", @"Y:\sabnzbd\root\completed\vv")]
[TestCase(@"/sabnzbd/root", @"completed/downloads", @"vv", @"/sabnzbd/root/completed/downloads", @"/sabnzbd/root/completed/downloads/vv")]
[TestCase(@"/sabnzbd/root", @"completed", @"vv", @"/sabnzbd/root/completed", @"/sabnzbd/root/completed/vv")]
public void should_return_status_with_outputdir_for_version_gte_2(string rootFolder, string completeDir, string categoryDir, string fullCompleteDir, string fullCategoryDir)
{
_fullStatus.CompleteDir = fullCompleteDir;
@ -554,7 +554,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
[Test]
public void should_test_failed_if_tv_sorting_default_category()
{
Subject.Definition.Settings.As<SabnzbdSettings>().TvCategory = null;
Subject.Definition.Settings.As<SabnzbdSettings>().MovieCategory = null;
_config.Misc.enable_tv_sorting = true;
_config.Misc.tv_categories = new[] { "Default" };

@ -30,7 +30,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Port = 2222,
Username = "admin",
Password = "pass",
TvCategory = "tv"
MovieCategory = "movie"
};
_queued = new UTorrentTorrent
@ -41,7 +41,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Size = 1000,
Remaining = 1000,
Progress = 0,
Label = "tv",
Label = "movie",
DownloadUrl = _downloadUrl,
RootDownloadPath = "somepath"
};
@ -54,7 +54,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Size = 1000,
Remaining = 100,
Progress = 0.9,
Label = "tv",
Label = "movie",
DownloadUrl = _downloadUrl,
RootDownloadPath = "somepath"
};
@ -67,7 +67,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Size = 1000,
Remaining = 100,
Progress = 0.9,
Label = "tv",
Label = "movie",
DownloadUrl = _downloadUrl,
RootDownloadPath = "somepath"
};
@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
Size = 1000,
Remaining = 0,
Progress = 1.0,
Label = "tv",
Label = "movie",
DownloadUrl = _downloadUrl,
RootDownloadPath = "somepath"
};

@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
@ -38,7 +38,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContents)
{
var category = Settings.TvCategory; // TODO: Update this to MovieCategory?
var category = Settings.MovieCategory;
var priority = Settings.RecentTvPriority;
@ -204,7 +204,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
public override IEnumerable<DownloadClientItem> GetItems()
{
return GetQueue().Concat(GetHistory()).Where(downloadClientItem => downloadClientItem.Category == Settings.TvCategory);
return GetQueue().Concat(GetHistory()).Where(downloadClientItem => downloadClientItem.Category == Settings.MovieCategory);
}
public override void RemoveItem(string downloadId, bool deleteData)
@ -221,7 +221,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
var config = _proxy.GetConfig(Settings);
var category = GetCategories(config).FirstOrDefault(v => v.Name == Settings.TvCategory);
var category = GetCategories(config).FirstOrDefault(v => v.Name == Settings.MovieCategory);
var status = new DownloadClientStatus
{
@ -283,7 +283,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
if (Version.Parse(version) < Version.Parse("12.0"))
{
return new ValidationFailure(string.Empty, "Nzbget version too low, need 12.0 or higher");
return new ValidationFailure(string.Empty, "NZBGet version too low, need 12.0 or higher");
}
}
catch (Exception ex)
@ -304,12 +304,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
var config = _proxy.GetConfig(Settings);
var categories = GetCategories(config);
if (!Settings.TvCategory.IsNullOrWhiteSpace() && !categories.Any(v => v.Name == Settings.TvCategory))
if (!Settings.MovieCategory.IsNullOrWhiteSpace() && !categories.Any(v => v.Name == Settings.MovieCategory))
{
return new NzbDroneValidationFailure("TvCategory", "Category does not exist")
return new NzbDroneValidationFailure("MovieCategory", "Category does not exist")
{
InfoLink = string.Format("http://{0}:{1}/", Settings.Host, Settings.Port),
DetailedDescription = "The Category your entered doesn't exist in NzbGet. Go to NzbGet to create it."
DetailedDescription = "The category you entered doesn't exist in NZBGet. Go to NZBGet to create it."
};
}
@ -323,10 +323,10 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
var keepHistory = config.GetValueOrDefault("KeepHistory");
if (keepHistory == "0")
{
return new NzbDroneValidationFailure(string.Empty, "NzbGet setting KeepHistory should be greater than 0")
return new NzbDroneValidationFailure(string.Empty, "NZBGet setting KeepHistory should be greater than 0")
{
InfoLink = string.Format("http://{0}:{1}/", Settings.Host, Settings.Port),
DetailedDescription = "NzbGet setting KeepHistory is set to 0. Which prevents Radarr from seeing completed downloads."
DetailedDescription = "NZBGet setting KeepHistory is set to 0. Which prevents Radarr from seeing completed downloads."
};
}

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
@ -88,7 +88,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
var editResult = EditQueue("GroupSetParameter", 0, "drone=" + droneId, item.NzbId, settings);
if (editResult)
{
_logger.Debug("Nzbget download drone parameter set to: {0}", droneId);
_logger.Debug("NZBGet download drone parameter set to: {0}", droneId);
}
return droneId;
@ -114,7 +114,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
if (editResult)
{
_logger.Debug("Nzbget download drone parameter set to: {0}", droneId);
_logger.Debug("NZBGet download drone parameter set to: {0}", droneId);
}
return droneId;
@ -175,7 +175,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
if (!EditQueue("GroupFinalDelete", 0, "", queueItem.NzbId, settings))
{
_logger.Warn("Failed to remove item from nzbget queue, {0} [{1}]", queueItem.NzbName, queueItem.NzbId);
_logger.Warn("Failed to remove item from NZBGet, {0} [{1}]", queueItem.NzbName, queueItem.NzbId);
}
}
@ -183,13 +183,13 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
if (!EditQueue("HistoryDelete", 0, "", historyItem.Id, settings))
{
_logger.Warn("Failed to remove item from nzbget history, {0} [{1}]", historyItem.Name, historyItem.Id);
_logger.Warn("Failed to remove item from NZBGet history, {0} [{1}]", historyItem.Name, historyItem.Id);
}
}
else
{
_logger.Warn("Unable to remove item from nzbget, Unknown ID: {0}", id);
_logger.Warn("Unable to remove item from NZBGet, Unknown ID: {0}", id);
return;
}
}
@ -235,21 +235,21 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
{
throw new DownloadClientException("Authentication failed for NzbGet, please check your settings", ex);
throw new DownloadClientException("Authentication failed for NZBGet, please check your settings", ex);
}
throw new DownloadClientException("Unable to connect to NzbGet. " + ex.Message, ex);
throw new DownloadClientException("Unable to connect to NZBGet. " + ex.Message, ex);
}
catch (WebException ex)
{
throw new DownloadClientException("Unable to connect to NzbGet. " + ex.Message, ex);
throw new DownloadClientException("Unable to connect to NZBGet. " + ex.Message, ex);
}
var result = Json.Deserialize<JsonRpcResponse<T>>(response.Content);
if (result.Error != null)
{
throw new DownloadClientException("Error response received from nzbget: {0}", result.Error.ToString());
throw new DownloadClientException("Error response received from NZBGet: {0}", result.Error.ToString());
}
return result.Result;

@ -1,4 +1,4 @@
namespace NzbDrone.Core.Download.Clients.Nzbget
namespace NzbDrone.Core.Download.Clients.Nzbget
{
public class NzbgetResponse<T>
{

@ -1,4 +1,4 @@
using FluentValidation;
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
@ -14,7 +14,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
RuleFor(c => c.Username).NotEmpty().When(c => !string.IsNullOrWhiteSpace(c.Password));
RuleFor(c => c.Password).NotEmpty().When(c => !string.IsNullOrWhiteSpace(c.Username));
RuleFor(c => c.TvCategory).NotEmpty().WithMessage("A category is recommended").AsWarning();
RuleFor(c => c.MovieCategory).NotEmpty().WithMessage("A category is recommended").AsWarning();
}
}
@ -26,7 +26,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
Host = "localhost";
Port = 6789;
TvCategory = "Movies";
MovieCategory = "Movies";
Username = "nzbget";
Password = "tegbzn6789";
RecentTvPriority = (int)NzbgetPriority.Normal;
@ -46,7 +46,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
public string Password { get; set; }
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing releases that aired within the last 14 days")]
public int RecentTvPriority { get; set; }
@ -57,7 +57,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
public bool UseSsl { get; set; }
[FieldDefinition(8, 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; }
public NzbDroneValidationResult Validate()

@ -21,7 +21,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
public QBittorrentSettings()
{
Host = "localhost";
Port = 9091;
Port = 8080;
MovieCategory = "radarr";
}

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
@ -39,7 +39,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContents)
{
var category = Settings.TvCategory;
var category = Settings.MovieCategory;
var priority = Settings.RecentTvPriority;
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, Settings);
@ -119,7 +119,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
try
{
sabHistory = _proxy.GetHistory(0, _configService.DownloadClientHistoryLimit, Settings.TvCategory, Settings);
sabHistory = _proxy.GetHistory(0, _configService.DownloadClientHistoryLimit, Settings.MovieCategory, Settings);
}
catch (DownloadClientException ex)
{
@ -200,7 +200,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
foreach (var downloadClientItem in GetQueue().Concat(GetHistory()))
{
if (downloadClientItem.Category == Settings.TvCategory || downloadClientItem.Category == "*" && Settings.TvCategory.IsNullOrWhiteSpace())
if (downloadClientItem.Category == Settings.MovieCategory || downloadClientItem.Category == "*" && Settings.MovieCategory.IsNullOrWhiteSpace())
{
yield return downloadClientItem;
}
@ -254,7 +254,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
var config = _proxy.GetConfig(Settings);
var categories = GetCategories(config).ToArray();
var category = categories.FirstOrDefault(v => v.Name == Settings.TvCategory);
var category = categories.FirstOrDefault(v => v.Name == Settings.MovieCategory);
if (category == null)
{
@ -366,7 +366,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
if (rawVersion.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
{
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
return new NzbDroneValidationFailure("Version", "SABnzbd develop version, assuming version 1.1.0 or higher.")
{
IsWarning = true,
DetailedDescription = "Radarr may not be able to support new features added to SABnzbd when running develop versions."
@ -419,10 +419,10 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
var config = _proxy.GetConfig(Settings);
if (config.Misc.pre_check && !HasVersion(1, 1))
{
return new NzbDroneValidationFailure("", "Disable 'Check before download' option in Sabnbzd")
return new NzbDroneValidationFailure("", "Disable 'Check before download' option in SABnzbd")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/switches/", Settings.Host, Settings.Port),
DetailedDescription = "Using Check before download affects Radarr ability to track new downloads. Also Sabnzbd recommends 'Abort jobs that cannot be completed' instead since it's more effective."
DetailedDescription = "Using Check before download affects Radarr ability to track new downloads. Also SABnzbd recommends 'Abort jobs that cannot be completed' instead since it's more effective."
};
}
@ -432,52 +432,52 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
private ValidationFailure TestCategory()
{
var config = _proxy.GetConfig(Settings);
var category = GetCategories(config).FirstOrDefault((SabnzbdCategory v) => v.Name == Settings.TvCategory);
var category = GetCategories(config).FirstOrDefault((SabnzbdCategory v) => v.Name == Settings.MovieCategory);
if (category != null)
{
if (category.Dir.EndsWith("*"))
{
return new NzbDroneValidationFailure("TvCategory", "Enable Job folders")
return new NzbDroneValidationFailure("MovieCategory", "Enable Job folders")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/categories/", Settings.Host, Settings.Port),
DetailedDescription = "Radarr 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."
DetailedDescription = "Radarr 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."
};
}
}
else
{
if (!Settings.TvCategory.IsNullOrWhiteSpace())
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
{
return new NzbDroneValidationFailure("TvCategory", "Category does not exist")
return new NzbDroneValidationFailure("MovieCategory", "Category does not exist")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/categories/", Settings.Host, Settings.Port),
DetailedDescription = "The Category your entered doesn't exist in Sabnzbd. Go to Sabnzbd to create it."
DetailedDescription = "The category you entered doesn't exist in SABnzbd. Go to SABnzbd to create it."
};
}
}
if (config.Misc.enable_tv_sorting && ContainsCategory(config.Misc.tv_categories, Settings.TvCategory))
if (config.Misc.enable_tv_sorting && ContainsCategory(config.Misc.tv_categories, Settings.MovieCategory))
{
return new NzbDroneValidationFailure("TvCategory", "Disable TV Sorting")
return new NzbDroneValidationFailure("MovieCategory", "Disable TV Sorting")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
DetailedDescription = "You must disable SABnzbd TV Sorting for the category Radarr uses to prevent import issues. Go to SABnzbd to fix it."
};
}
if (config.Misc.enable_movie_sorting && ContainsCategory(config.Misc.movie_categories, Settings.TvCategory))
if (config.Misc.enable_movie_sorting && ContainsCategory(config.Misc.movie_categories, Settings.MovieCategory))
{
return new NzbDroneValidationFailure("TvCategory", "Disable Movie Sorting")
return new NzbDroneValidationFailure("MovieCategory", "Disable Movie Sorting")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
DetailedDescription = "You must disable SABnzbd Movie Sorting for the category Radarr uses to prevent import issues. Go to SABnzbd to fix it."
};
}
if (config.Misc.enable_date_sorting && ContainsCategory(config.Misc.date_categories, Settings.TvCategory))
if (config.Misc.enable_date_sorting && ContainsCategory(config.Misc.date_categories, Settings.MovieCategory))
{
return new NzbDroneValidationFailure("TvCategory", "Disable Date Sorting")
return new NzbDroneValidationFailure("MovieCategory", "Disable Date Sorting")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
DetailedDescription = "You must disable SABnzbd Date Sorting for the category Radarr uses to prevent import issues. Go to SABnzbd to fix it."
};
}

@ -1,4 +1,4 @@
using FluentValidation;
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
@ -24,7 +24,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
.WithMessage("Password is required when API key is not configured")
.When(c => string.IsNullOrWhiteSpace(c.ApiKey));
RuleFor(c => c.TvCategory).NotEmpty()
RuleFor(c => c.MovieCategory).NotEmpty()
.WithMessage("A category is recommended")
.AsWarning();
}
@ -38,7 +38,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
Host = "localhost";
Port = 8080;
TvCategory = "movies";
MovieCategory = "movies";
RecentTvPriority = (int)SabnzbdPriority.Default;
OlderTvPriority = (int)SabnzbdPriority.Default;
}
@ -59,7 +59,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
public string Password { get; set; }
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
[FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing releases that aired within the last 14 days")]
public int RecentTvPriority { get; set; }

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Collections.Generic;
using NzbDrone.Common.Disk;
@ -49,7 +49,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
@ -59,13 +59,15 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}*/
_proxy.SetState(hash, (UTorrentState)Settings.IntialState, Settings);
return hash;
}
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
@ -75,6 +77,8 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}*/
_proxy.SetState(hash, (UTorrentState)Settings.IntialState, Settings);
return hash;
}
@ -86,7 +90,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
try
{
var cacheKey = string.Format("{0}:{1}:{2}", Settings.Host, Settings.Port, Settings.TvCategory);
var cacheKey = string.Format("{0}:{1}:{2}", Settings.Host, Settings.Port, Settings.MovieCategory);
var cache = _torrentCache.Find(cacheKey);
var response = _proxy.GetTorrents(cache == null ? null : cache.CacheID, Settings);
@ -123,7 +127,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
foreach (var torrent in torrents)
{
if (torrent.Label != Settings.TvCategory)
if (torrent.Label != Settings.MovieCategory)
{
continue;
}
@ -205,7 +209,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
if (config.GetValueOrDefault("dir_add_label") == "true")
{
destDir = destDir + Settings.TvCategory;
destDir = destDir + Settings.MovieCategory;
}
}

@ -22,6 +22,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
void RemoveTorrent(string hash, bool removeData, UTorrentSettings settings);
void SetTorrentLabel(string hash, string label, UTorrentSettings settings);
void MoveTorrentToTopInQueue(string hash, UTorrentSettings settings);
void SetState(string hash, UTorrentState state, UTorrentSettings settings);
}
public class UTorrentProxy : IUTorrentProxy
@ -157,6 +158,15 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
ProcessRequest(requestBuilder, settings);
}
public void SetState(string hash, UTorrentState state, UTorrentSettings settings)
{
var requestBuilder = BuildRequest(settings)
.AddQueryParam("action", state.ToString().ToLowerInvariant())
.AddQueryParam("hash", hash);
ProcessRequest(requestBuilder, settings);
}
private HttpRequestBuilder BuildRequest(UTorrentSettings settings)
{
var requestBuilder = new HttpRequestBuilder(false, settings.Host, settings.Port)

@ -11,7 +11,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
{
RuleFor(c => c.Host).ValidHost();
RuleFor(c => c.Port).InclusiveBetween(1, 65535);
RuleFor(c => c.TvCategory).NotEmpty();
RuleFor(c => c.MovieCategory).NotEmpty();
}
}
@ -22,8 +22,8 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
public UTorrentSettings()
{
Host = "localhost";
Port = 9091;
TvCategory = "radarr";
Port = 8080;
MovieCategory = "radarr";
}
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
@ -39,7 +39,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
public string Password { get; set; }
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(UTorrentPriority), HelpText = "Priority to use when grabbing releases that aired within the last 14 days")]
public int RecentTvPriority { get; set; }
@ -47,6 +47,9 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(UTorrentPriority), HelpText = "Priority to use when grabbing releases that aired over 14 days ago")]
public int OlderTvPriority { get; set; }
[FieldDefinition(7, Label = "Initial State", Type = FieldType.Select, SelectOptions = typeof(UTorrentState), HelpText = "Initial state for torrents added to uTorrent")]
public int IntialState { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

@ -0,0 +1,10 @@
namespace NzbDrone.Core.Download.Clients.UTorrent
{
public enum UTorrentState
{
Start = 0,
ForceStart = 1,
Pause = 2,
Stop = 3
}
}

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
@ -31,6 +31,7 @@ namespace NzbDrone.Core.Notifications.CustomScript
{
var movie = message.Movie;
var remoteMovie = message.RemoteMovie;
var quality = message.Quality;
var environmentVariables = new StringDictionary();
environmentVariables.Add("Radarr_EventType", "Grab");
@ -42,6 +43,8 @@ namespace NzbDrone.Core.Notifications.CustomScript
environmentVariables.Add("Radarr_Release_Indexer", remoteMovie.Release.Indexer);
environmentVariables.Add("Radarr_Release_Size", remoteMovie.Release.Size.ToString());
environmentVariables.Add("Radarr_Release_ReleaseGroup", remoteMovie.ParsedMovieInfo.ReleaseGroup ?? string.Empty);
environmentVariables.Add("Radarr_Release_Quality", quality.Quality.Name);
environmentVariables.Add("Radarr_Release_QualityVersion", quality.Revision.Version.ToString());
ExecuteScript(environmentVariables);
}
@ -54,6 +57,7 @@ namespace NzbDrone.Core.Notifications.CustomScript
var environmentVariables = new StringDictionary();
environmentVariables.Add("Radarr_EventType", "Download");
environmentVariables.Add("Radarr_IsUpgrade", message.OldMovieFiles.Any().ToString());
environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString());
environmentVariables.Add("Radarr_Movie_Title", movie.Title);
environmentVariables.Add("Radarr_Movie_Path", movie.Path);
@ -69,6 +73,11 @@ namespace NzbDrone.Core.Notifications.CustomScript
environmentVariables.Add("Radarr_MovieFile_SourcePath", sourcePath);
environmentVariables.Add("Radarr_MovieFile_SourceFolder", Path.GetDirectoryName(sourcePath));
if (message.OldMovieFiles.Any())
{
environmentVariables.Add("Radarr_DeletedRelativePaths", string.Join("|", message.OldMovieFiles.Select(e => e.RelativePath)));
environmentVariables.Add("Radarr_DeletedPaths", string.Join("|", message.OldMovieFiles.Select(e => Path.Combine(movie.Path, e.RelativePath))));
}
ExecuteScript(environmentVariables);
}

@ -1,35 +1,64 @@

using System.Collections.Generic;
using System.Linq;
using FluentValidation.Results;
using NzbDrone.Core.Tv;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Notifications.Webhook
{
public class Webhook : NotificationBase<WebhookSettings>
{
private readonly IWebhookService _service;
private readonly IWebhookProxy _proxy;
public Webhook(IWebhookService service)
public Webhook(IWebhookProxy proxy)
{
_service = service;
_proxy = proxy;
}
public override string Link => "https://github.com/Radarr/Radarr/wiki/Webhook";
public override void OnGrab(GrabMessage message)
{
_service.OnGrab(message.Movie, message.RemoteMovie, message.Quality, Settings);
var remoteMovie = message.RemoteMovie;
var quality = message.Quality;
var payload = new WebhookGrabPayload
{
EventType = "Grab",
Movie = new WebhookMovie(message.Movie),
RemoteMovie = new WebhookRemoteMovie(remoteMovie),
Release = new WebhookRelease(quality, remoteMovie)
};
_proxy.SendWebhook(payload, Settings);
}
public override void OnDownload(DownloadMessage message)
{
_service.OnDownload(message.Movie, message.MovieFile, Settings);
var movieFile = message.MovieFile;
var payload = new WebhookImportPayload
{
EventType = "Download",
Movie = new WebhookMovie(message.Movie),
RemoteMovie = new WebhookRemoteMovie(message.Movie),
MovieFile = new WebhookMovieFile(movieFile),
IsUpgrade = message.OldMovieFiles.Any()
};
_proxy.SendWebhook(payload, Settings);
}
public override void OnMovieRename(Movie movie)
{
_service.OnRename(movie, Settings);
var payload = new WebhookPayload
{
EventType = "Rename",
Movie = new WebhookMovie(movie)
};
_proxy.SendWebhook(payload, Settings);
}
public override void OnRename(Series series)
@ -42,9 +71,51 @@ namespace NzbDrone.Core.Notifications.Webhook
{
var failures = new List<ValidationFailure>();
failures.AddIfNotNull(_service.Test(Settings));
failures.AddIfNotNull(SendWebhookTest());
return new ValidationResult(failures);
}
private ValidationFailure SendWebhookTest()
{
try
{
var payload = new WebhookGrabPayload
{
EventType = "Test",
Movie = new WebhookMovie
{
Id = 1,
Title = "Test Title",
FilePath = "C:\\testpath",
ReleaseDate = "1970-01-01"
},
RemoteMovie = new WebhookRemoteMovie
{
TmdbId = 1234,
ImdbId = "5678",
Title = "Test title",
Year = 1970
},
Release = new WebhookRelease
{
Indexer = "Test Indexer",
Quality = "Test Quality",
QualityVersion = 1,
ReleaseGroup = "Test Group",
ReleaseTitle = "Test Title",
Size = 9999999
}
};
_proxy.SendWebhook(payload, Settings);
}
catch (WebhookException ex)
{
return new NzbDroneValidationFailure("Url", ex.Message);
}
return null;
}
}
}

@ -1,32 +0,0 @@
using NzbDrone.Core.Tv;
using System;
namespace NzbDrone.Core.Notifications.Webhook
{
public class WebhookEpisode
{
public WebhookEpisode() { }
public WebhookEpisode(Episode episode)
{
Id = episode.Id;
SeasonNumber = episode.SeasonNumber;
EpisodeNumber = episode.EpisodeNumber;
Title = episode.Title;
AirDate = episode.AirDate;
AirDateUtc = episode.AirDateUtc;
}
public int Id { get; set; }
public int EpisodeNumber { get; set; }
public int SeasonNumber { get; set; }
public string Title { get; set; }
public string AirDate { get; set; }
public DateTime? AirDateUtc { get; set; }
public string Quality { get; set; }
public int QualityVersion { get; set; }
public string ReleaseGroup { get; set; }
public string SceneName { get; set; }
}
}

@ -0,0 +1,8 @@
namespace NzbDrone.Core.Notifications.Webhook
{
class WebhookGrabPayload : WebhookPayload
{
public WebhookRemoteMovie RemoteMovie { get; set; }
public WebhookRelease Release { get; set; }
}
}

@ -0,0 +1,9 @@
namespace NzbDrone.Core.Notifications.Webhook
{
class WebhookImportPayload : WebhookPayload
{
public WebhookRemoteMovie RemoteMovie { get; set; }
public WebhookMovieFile MovieFile { get; set; }
public bool IsUpgrade { get; set; }
}
}

@ -1,8 +1,10 @@
namespace NzbDrone.Core.Notifications.Webhook
using NzbDrone.Common.Http;
namespace NzbDrone.Core.Notifications.Webhook
{
public enum WebhookMethod
{
POST = RestSharp.Method.POST,
PUT = RestSharp.Method.PUT
POST = HttpMethod.POST,
PUT = HttpMethod.PUT
}
}
}

@ -9,6 +9,7 @@ namespace NzbDrone.Core.Notifications.Webhook
public int Id { get; set; }
public string Title { get; set; }
public string FilePath { get; set; }
public string ReleaseDate { get; set; }
public WebhookMovie() { }
@ -16,12 +17,11 @@ namespace NzbDrone.Core.Notifications.Webhook
{
Id = movie.Id;
Title = movie.Title;
ReleaseDate = movie.PhysicalReleaseDate().ToString("yyyy-MM-dd");
}
public WebhookMovie(Movie movie, MovieFile movieFile)
public WebhookMovie(Movie movie, MovieFile movieFile) : this(movie)
{
Id = movie.Id;
Title = movie.Title;
FilePath = Path.Combine(movie.Path, movieFile.RelativePath);
}
}

@ -0,0 +1,28 @@
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.Notifications.Webhook
{
class WebhookMovieFile
{
public WebhookMovieFile() { }
public WebhookMovieFile(MovieFile movieFile)
{
Id = movieFile.Id;
RelativePath = movieFile.RelativePath;
Path = movieFile.Path;
Quality = movieFile.Quality.Quality.Name;
QualityVersion = movieFile.Quality.Revision.Version;
ReleaseGroup = movieFile.ReleaseGroup;
SceneName = movieFile.SceneName;
}
public int Id { get; set; }
public string RelativePath { get; set; }
public string Path { get; set; }
public string Quality { get; set; }
public int QualityVersion { get; set; }
public string ReleaseGroup { get; set; }
public string SceneName { get; set; }
}
}

@ -1,11 +1,8 @@
using System.Collections.Generic;
namespace NzbDrone.Core.Notifications.Webhook
{
public class WebhookPayload
{
public string EventType { get; set; }
public WebhookMovie Movie { get; set; }
public WebhookRemoteMovie RemoteMovie { get; set; }
}
}

@ -0,0 +1,41 @@
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Rest;
namespace NzbDrone.Core.Notifications.Webhook
{
public interface IWebhookProxy
{
void SendWebhook(WebhookPayload payload, WebhookSettings settings);
}
class WebhookProxy : IWebhookProxy
{
private readonly IHttpClient _httpClient;
public WebhookProxy(IHttpClient httpClient)
{
_httpClient = httpClient;
}
public void SendWebhook(WebhookPayload body, WebhookSettings settings)
{
try
{
var request = new HttpRequestBuilder(settings.Url)
.Accept(HttpAccept.Json)
.Build();
request.Method = (HttpMethod)settings.Method;
request.Headers.ContentType = "application/json";
request.SetContent(body.ToJson());
_httpClient.Execute(request);
}
catch (RestException ex)
{
throw new WebhookException("Unable to post to webhook: {0}", ex, ex.Message);
}
}
}
}

@ -0,0 +1,27 @@
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.Notifications.Webhook
{
public class WebhookRelease
{
public WebhookRelease() { }
public WebhookRelease(QualityModel quality, RemoteMovie remoteMovie)
{
Quality = quality.Quality.Name;
QualityVersion = quality.Revision.Version;
ReleaseGroup = remoteMovie.ParsedMovieInfo.ReleaseGroup;
ReleaseTitle = remoteMovie.Release.Title;
Indexer = remoteMovie.Release.Indexer;
Size = remoteMovie.Release.Size;
}
public string Quality { get; set; }
public int QualityVersion { get; set; }
public string ReleaseGroup { get; set; }
public string ReleaseTitle { get; set; }
public string Indexer { get; set; }
public long Size { get; set; }
}
}

@ -1,22 +0,0 @@
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Notifications.Webhook
{
public class WebhookSeries
{
public int Id { get; set; }
public string Title { get; set; }
public string Path { get; set; }
public int TvdbId { get; set; }
public WebhookSeries() { }
public WebhookSeries(Series series)
{
Id = series.Id;
Title = series.Title;
Path = series.Path;
TvdbId = series.TvdbId;
}
}
}

@ -1,103 +0,0 @@
using FluentValidation.Results;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Validation;
using NzbDrone.Core.Rest;
using RestSharp;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Parser.Model;
using System.Collections.Generic;
namespace NzbDrone.Core.Notifications.Webhook
{
public interface IWebhookService
{
void OnDownload(Movie movie, MovieFile movieFile, WebhookSettings settings);
void OnRename(Movie movie, WebhookSettings settings);
void OnGrab(Movie movie, RemoteMovie remoteMovie, QualityModel quality, WebhookSettings settings);
ValidationFailure Test(WebhookSettings settings);
}
public class WebhookService : IWebhookService
{
public void OnDownload(Movie movie, MovieFile movieFile, WebhookSettings settings)
{
var payload = new WebhookPayload
{
EventType = "Download",
Movie = new WebhookMovie(movie, movieFile),
RemoteMovie = new WebhookRemoteMovie(movie)
};
NotifyWebhook(payload, settings);
}
public void OnRename(Movie movie, WebhookSettings settings)
{
var payload = new WebhookPayload
{
EventType = "Rename",
Movie = new WebhookMovie(movie)
};
NotifyWebhook(payload, settings);
}
public void OnGrab(Movie movie, RemoteMovie remoteMovie, QualityModel quality, WebhookSettings settings)
{
var payload = new WebhookPayload
{
EventType = "Grab",
Movie = new WebhookMovie(movie),
RemoteMovie = new WebhookRemoteMovie(remoteMovie)
};
NotifyWebhook(payload, settings);
}
public void NotifyWebhook(WebhookPayload body, WebhookSettings settings)
{
try {
var client = RestClientFactory.BuildClient(settings.Url);
var request = new RestRequest((Method) settings.Method);
request.RequestFormat = DataFormat.Json;
request.AddBody(body);
client.ExecuteAndValidate(request);
}
catch (RestException ex)
{
throw new WebhookException("Unable to post to webhook: {0}", ex, ex.Message);
}
}
public ValidationFailure Test(WebhookSettings settings)
{
try
{
NotifyWebhook(
new WebhookPayload
{
EventType = "Test",
Movie = new WebhookMovie()
{
Id = 1,
Title = "Test Title",
FilePath = "C:\\testpath",
},
RemoteMovie = new WebhookRemoteMovie(){
ImdbId = "tt012345",
Title = "My Awesome Movie!"
}
},
settings
);
}
catch (WebhookException ex)
{
return new NzbDroneValidationFailure("Url", ex.Message);
}
return null;
}
}
}

@ -556,6 +556,7 @@
<Compile Include="Download\Clients\uTorrent\UTorrentProxy.cs" />
<Compile Include="Download\Clients\uTorrent\UTorrentResponse.cs" />
<Compile Include="Download\Clients\uTorrent\UTorrentSettings.cs" />
<Compile Include="Download\Clients\uTorrent\UtorrentState.cs" />
<Compile Include="Download\Clients\uTorrent\UTorrentTorrent.cs" />
<Compile Include="Download\Clients\uTorrent\UTorrentTorrentCache.cs" />
<Compile Include="Download\Clients\uTorrent\UTorrentTorrentStatus.cs" />
@ -985,14 +986,16 @@
<Compile Include="Notifications\Telegram\TelegramSettings.cs" />
<Compile Include="Notifications\Twitter\OAuthToken.cs" />
<Compile Include="Notifications\Twitter\TwitterException.cs" />
<Compile Include="Notifications\Webhook\WebhookEpisode.cs" />
<Compile Include="Notifications\Webhook\WebhookException.cs" />
<Compile Include="Notifications\Webhook\WebhookGrabPayload.cs" />
<Compile Include="Notifications\Webhook\WebhookImportPayload.cs" />
<Compile Include="Notifications\Webhook\WebhookMethod.cs" />
<Compile Include="Notifications\Webhook\WebhookMovieFile.cs" />
<Compile Include="Notifications\Webhook\WebhookPayload.cs" />
<Compile Include="Notifications\Webhook\WebhookSeries.cs" />
<Compile Include="Notifications\Webhook\WebhookProxy.cs" />
<Compile Include="Notifications\Webhook\WebhookRelease.cs" />
<Compile Include="Notifications\Webhook\WebhookMovie.cs" />
<Compile Include="Notifications\Webhook\WebhookRemoteMovie.cs" />
<Compile Include="Notifications\Webhook\WebhookService.cs" />
<Compile Include="Notifications\Webhook\WebhookSettings.cs" />
<Compile Include="Notifications\Webhook\Webhook.cs" />
<Compile Include="Organizer\NamingConfigRepository.cs" />
@ -1390,4 +1393,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

@ -1,27 +1,27 @@
using FluentValidation.Validators;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Validation.Paths
{
public class MoviePathValidator : PropertyValidator
{
private readonly IMovieService _seriesService;
public MoviePathValidator(IMovieService seriesService)
: base("Path is already configured for another series")
{
_seriesService = seriesService;
}
protected override bool IsValid(PropertyValidatorContext context)
{
if (context.PropertyValue == null) return true;
dynamic instance = context.ParentContext.InstanceToValidate;
var instanceId = (int)instance.Id;
return (!_seriesService.GetAllMovies().Exists(s => s.Path.PathEquals(context.PropertyValue.ToString()) && s.Id != instanceId));
}
}
using FluentValidation.Validators;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Validation.Paths
{
public class MoviePathValidator : PropertyValidator
{
private readonly IMovieService _moviesService;
public MoviePathValidator(IMovieService moviesService)
: base("Path is already configured for another movie")
{
_moviesService = moviesService;
}
protected override bool IsValid(PropertyValidatorContext context)
{
if (context.PropertyValue == null) return true;
dynamic instance = context.ParentContext.InstanceToValidate;
var instanceId = (int)instance.Id;
return (!_moviesService.GetAllMovies().Exists(s => s.Path.PathEquals(context.PropertyValue.ToString()) && s.Id != instanceId));
}
}
}

@ -41,8 +41,7 @@
.help-inline {
display : inline-block;
margin-top : 8px;
padding-left : 0;
padding-left : 0px;
@media (max-width: @screen-xs-max) {
margin-left: 0;

@ -1,7 +1,7 @@
.hotkeys-modal {
h3 {
margin-top : 0;
margin-botton : 0;
margin-bottom : 0;
}
.hotkey-group {
@ -20,4 +20,4 @@
font-size : 22px;
}
}
}
}

@ -86,7 +86,7 @@ var Collection = PageableCollection.extend({
return {};
}
if (this.state.pageSize == -1) {
if (this.state.pageSize === -1) {
return this.state;
}
@ -98,7 +98,7 @@ var Collection = PageableCollection.extend({
},
parseRecords : function(resp) {
if (resp && this.mode !== 'client' && this.state.pageSize != 0 && this.state.pageSize != -1) {
if (resp && this.mode !== 'client' && this.state.pageSize !== 0 && this.state.pageSize !== -1) {
return resp.records;
}
@ -252,7 +252,7 @@ var Collection = PageableCollection.extend({
},
add : function(model, options) {
if (this.length >= this.state.pageSize && this.state.pageSize != -1) {
if (this.length >= this.state.pageSize && this.state.pageSize !== -1) {
return;
}
this.origAdd.call(this, model, options);

@ -1,4 +1,8 @@
<div id="x-toolbar"/>
<div class="alert alert-warning alert-dismissable">
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
If the log viewer table does not load, please disable your adblocker and refresh the page.
</div>
<div class="row">
<div class="col-md-12">
<div id="x-grid" class="table-responsive"/>

Loading…
Cancel
Save