Fixed: Handling of unknown status types in DownloadStation and Import from torrent Download Station should move since DS maintains an internal copy for seeding. (#2420)

Fixes #2000
pull/2696/merge
Marcelo Castagna 7 years ago committed by Leonardo Galli
parent 39346b6127
commit ed4add85b8

@ -217,6 +217,7 @@
<Compile Include="Serializer\HttpUriConverter.cs" /> <Compile Include="Serializer\HttpUriConverter.cs" />
<Compile Include="Serializer\IntConverter.cs" /> <Compile Include="Serializer\IntConverter.cs" />
<Compile Include="Serializer\Json.cs" /> <Compile Include="Serializer\Json.cs" />
<Compile Include="Serializer\UnderscoreStringEnumConverter.cs" />
<Compile Include="ServiceFactory.cs" /> <Compile Include="ServiceFactory.cs" />
<Compile Include="ServiceProvider.cs" /> <Compile Include="ServiceProvider.cs" />
<Compile Include="Extensions\StringExtensions.cs" /> <Compile Include="Extensions\StringExtensions.cs" />
@ -254,11 +255,11 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
</Target> </Target>
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>

@ -0,0 +1,58 @@
using System;
using System.Text;
using Newtonsoft.Json;
namespace NzbDrone.Common.Serializer
{
public class UnderscoreStringEnumConverter : JsonConverter
{
public object UnknownValue { get; set; }
public UnderscoreStringEnumConverter(object unknownValue)
{
UnknownValue = unknownValue;
}
public override bool CanConvert(Type objectType)
{
return objectType.IsEnum;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var enumString = reader.Value.ToString().Replace("_", string.Empty);
try
{
return Enum.Parse(objectType, enumString, true);
}
catch
{
if (UnknownValue == null)
{
throw;
}
return UnknownValue;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var enumText = value.ToString();
var builder = new StringBuilder(enumText.Length + 4);
builder.Append(char.ToLower(enumText[0]));
for (int i = 1; i < enumText.Length; i++)
{
if (char.IsUpper(enumText[i]))
{
builder.Append('_');
}
builder.Append(char.ToLower(enumText[i]));
}
enumText = builder.ToString();
writer.WriteValue(enumText);
}
}
}

@ -19,6 +19,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
protected DelugeTorrent _downloading; protected DelugeTorrent _downloading;
protected DelugeTorrent _failed; protected DelugeTorrent _failed;
protected DelugeTorrent _completed; protected DelugeTorrent _completed;
protected DelugeTorrent _seeding;
[SetUp] [SetUp]
public void Setup() public void Setup()
@ -75,7 +76,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
Size = 1000, Size = 1000,
BytesDownloaded = 1000, BytesDownloaded = 1000,
Progress = 100.0, Progress = 100.0,
DownloadPath = "somepath" DownloadPath = "somepath",
IsAutoManaged = true,
StopAtRatio = true,
StopRatio = 1.0,
Ratio = 1.5
}; };
Mocker.GetMock<ITorrentFileInfoReader>() Mocker.GetMock<ITorrentFileInfoReader>()
@ -189,6 +194,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
PrepareClientToReturnCompletedItem(); PrepareClientToReturnCompletedItem();
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
VerifyCompleted(item); VerifyCompleted(item);
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -248,11 +256,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
} }
[TestCase(DelugeTorrentStatus.Paused, DownloadItemStatus.Completed, true)] [TestCase(DelugeTorrentStatus.Paused, DownloadItemStatus.Completed)]
[TestCase(DelugeTorrentStatus.Checking, DownloadItemStatus.Downloading, true)] [TestCase(DelugeTorrentStatus.Checking, DownloadItemStatus.Downloading)]
[TestCase(DelugeTorrentStatus.Queued, DownloadItemStatus.Completed, true)] [TestCase(DelugeTorrentStatus.Queued, DownloadItemStatus.Completed)]
[TestCase(DelugeTorrentStatus.Seeding, DownloadItemStatus.Completed, true)] [TestCase(DelugeTorrentStatus.Seeding, DownloadItemStatus.Completed)]
public void GetItems_should_return_completed_item_as_downloadItemStatus(string apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly) public void GetItems_should_return_completed_item_as_downloadItemStatus(string apiStatus, DownloadItemStatus expectedItemStatus)
{ {
_completed.State = apiStatus; _completed.State = apiStatus;
@ -261,24 +269,25 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
item.IsReadOnly.Should().Be(expectedReadOnly);
} }
[Test] [TestCase(0.5, false)]
public void GetItems_should_check_share_ratio_for_readonly() [TestCase(1.01, true)]
public void GetItems_should_check_share_ratio_for_moveFiles_and_remove(double ratio, bool canBeRemoved)
{ {
_completed.State = DelugeTorrentStatus.Paused; _completed.State = DelugeTorrentStatus.Paused;
_completed.IsAutoManaged = true; _completed.IsAutoManaged = true;
_completed.StopAtRatio = true; _completed.StopAtRatio = true;
_completed.StopRatio = 1.0; _completed.StopRatio = 1.0;
_completed.Ratio = 1.01; _completed.Ratio = ratio;
PrepareClientToReturnCompletedItem(); PrepareClientToReturnCompletedItem();
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.Status.Should().Be(DownloadItemStatus.Completed); item.Status.Should().Be(DownloadItemStatus.Completed);
item.IsReadOnly.Should().BeFalse(); item.CanMoveFiles.Should().Be(canBeRemoved);
item.CanBeRemoved.Should().Be(canBeRemoved);
} }
[Test] [Test]

@ -0,0 +1,49 @@
using FluentAssertions;
using Newtonsoft.Json;
using NUnit.Framework;
using NzbDrone.Core.Download.Clients.DownloadStation;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
{
[TestFixture]
public class DownloadStationsTaskStatusJsonConverterFixture
{
[TestCase("captcha_needed", DownloadStationTaskStatus.CaptchaNeeded)]
[TestCase("filehosting_waiting", DownloadStationTaskStatus.FilehostingWaiting)]
[TestCase("hash_checking", DownloadStationTaskStatus.HashChecking)]
[TestCase("error", DownloadStationTaskStatus.Error)]
[TestCase("downloading", DownloadStationTaskStatus.Downloading)]
public void should_parse_enum_correctly(string value, DownloadStationTaskStatus expected)
{
var task = "{\"Status\": \"" + value + "\"}";
var item = JsonConvert.DeserializeObject<DownloadStationTask>(task);
item.Status.Should().Be(expected);
}
[TestCase("captcha_needed", DownloadStationTaskStatus.CaptchaNeeded)]
[TestCase("filehosting_waiting", DownloadStationTaskStatus.FilehostingWaiting)]
[TestCase("hash_checking", DownloadStationTaskStatus.HashChecking)]
[TestCase("error", DownloadStationTaskStatus.Error)]
[TestCase("downloading", DownloadStationTaskStatus.Downloading)]
public void should_serialize_enum_correctly(string expected, DownloadStationTaskStatus value)
{
var task = new DownloadStationTask { Status = value };
var item = JsonConvert.SerializeObject(task);
item.Should().Contain(expected);
}
[Test]
public void should_return_unknown_if_unknown_enum_value()
{
var task = "{\"Status\": \"some_unknown_value\"}";
var item = JsonConvert.DeserializeObject<DownloadStationTask>(task);
item.Status.Should().Be(DownloadStationTaskStatus.Unknown);
}
}
}

@ -576,11 +576,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
items.Should().OnlyContain(v => !v.OutputPath.IsEmpty); items.Should().OnlyContain(v => !v.OutputPath.IsEmpty);
} }
[TestCase(DownloadStationTaskStatus.Downloading, DownloadItemStatus.Downloading, true)] [TestCase(DownloadStationTaskStatus.Downloading, false, false)]
[TestCase(DownloadStationTaskStatus.Finished, DownloadItemStatus.Completed, false)] [TestCase(DownloadStationTaskStatus.Finished, true, true)]
[TestCase(DownloadStationTaskStatus.Seeding, DownloadItemStatus.Completed, true)] [TestCase(DownloadStationTaskStatus.Seeding, true, false)]
[TestCase(DownloadStationTaskStatus.Waiting, DownloadItemStatus.Queued, true)] [TestCase(DownloadStationTaskStatus.Waiting, false, false)]
public void GetItems_should_return_readonly_expected(DownloadStationTaskStatus apiStatus, DownloadItemStatus expectedItemStatus, bool readOnlyExpected) public void GetItems_should_return_canBeMoved_and_canBeDeleted_as_expected(DownloadStationTaskStatus apiStatus, bool canMoveFilesExpected, bool canBeRemovedExpected)
{ {
GivenSerialNumber(); GivenSerialNumber();
GivenSharedFolder(); GivenSharedFolder();
@ -592,7 +592,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
var items = Subject.GetItems(); var items = Subject.GetItems();
items.Should().HaveCount(1); items.Should().HaveCount(1);
items.First().IsReadOnly.Should().Be(readOnlyExpected);
var item = items.First();
item.CanBeRemoved.Should().Be(canBeRemovedExpected);
item.CanMoveFiles.Should().Be(canMoveFilesExpected);
} }
[TestCase(DownloadStationTaskStatus.Downloading, DownloadItemStatus.Downloading)] [TestCase(DownloadStationTaskStatus.Downloading, DownloadItemStatus.Downloading)]
@ -601,9 +605,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
[TestCase(DownloadStationTaskStatus.Finished, DownloadItemStatus.Completed)] [TestCase(DownloadStationTaskStatus.Finished, DownloadItemStatus.Completed)]
[TestCase(DownloadStationTaskStatus.Finishing, DownloadItemStatus.Downloading)] [TestCase(DownloadStationTaskStatus.Finishing, DownloadItemStatus.Downloading)]
[TestCase(DownloadStationTaskStatus.HashChecking, DownloadItemStatus.Downloading)] [TestCase(DownloadStationTaskStatus.HashChecking, DownloadItemStatus.Downloading)]
[TestCase(DownloadStationTaskStatus.CaptchaNeeded, DownloadItemStatus.Downloading)]
[TestCase(DownloadStationTaskStatus.Paused, DownloadItemStatus.Paused)] [TestCase(DownloadStationTaskStatus.Paused, DownloadItemStatus.Paused)]
[TestCase(DownloadStationTaskStatus.Seeding, DownloadItemStatus.Completed)] [TestCase(DownloadStationTaskStatus.Seeding, DownloadItemStatus.Completed)]
[TestCase(DownloadStationTaskStatus.FilehostingWaiting, DownloadItemStatus.Queued)]
[TestCase(DownloadStationTaskStatus.Waiting, DownloadItemStatus.Queued)] [TestCase(DownloadStationTaskStatus.Waiting, DownloadItemStatus.Queued)]
[TestCase(DownloadStationTaskStatus.Unknown, DownloadItemStatus.Queued)]
public void GetItems_should_return_item_as_downloadItemStatus(DownloadStationTaskStatus apiStatus, DownloadItemStatus expectedItemStatus) public void GetItems_should_return_item_as_downloadItemStatus(DownloadStationTaskStatus apiStatus, DownloadItemStatus expectedItemStatus)
{ {
GivenSerialNumber(); GivenSerialNumber();

@ -408,32 +408,18 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
items.Should().OnlyContain(v => !v.OutputPath.IsEmpty); items.Should().OnlyContain(v => !v.OutputPath.IsEmpty);
} }
[TestCase(DownloadStationTaskStatus.Downloading, DownloadItemStatus.Downloading, true)]
[TestCase(DownloadStationTaskStatus.Finished, DownloadItemStatus.Completed, false)]
[TestCase(DownloadStationTaskStatus.Waiting, DownloadItemStatus.Queued, true)]
public void GetItems_should_return_readonly_expected(DownloadStationTaskStatus apiStatus, DownloadItemStatus expectedItemStatus, bool readOnlyExpected)
{
GivenSerialNumber();
GivenSharedFolder();
_queued.Status = apiStatus;
GivenTasks(new List<DownloadStationTask>() { _queued });
var items = Subject.GetItems();
items.Should().HaveCount(1);
items.First().IsReadOnly.Should().Be(readOnlyExpected);
}
[TestCase(DownloadStationTaskStatus.Downloading, DownloadItemStatus.Downloading)] [TestCase(DownloadStationTaskStatus.Downloading, DownloadItemStatus.Downloading)]
[TestCase(DownloadStationTaskStatus.Error, DownloadItemStatus.Failed)] [TestCase(DownloadStationTaskStatus.Error, DownloadItemStatus.Failed)]
[TestCase(DownloadStationTaskStatus.Extracting, DownloadItemStatus.Downloading)] [TestCase(DownloadStationTaskStatus.Extracting, DownloadItemStatus.Downloading)]
[TestCase(DownloadStationTaskStatus.Finished, DownloadItemStatus.Completed)] [TestCase(DownloadStationTaskStatus.Finished, DownloadItemStatus.Completed)]
[TestCase(DownloadStationTaskStatus.Finishing, DownloadItemStatus.Downloading)] [TestCase(DownloadStationTaskStatus.Finishing, DownloadItemStatus.Downloading)]
[TestCase(DownloadStationTaskStatus.HashChecking, DownloadItemStatus.Downloading)] [TestCase(DownloadStationTaskStatus.HashChecking, DownloadItemStatus.Downloading)]
[TestCase(DownloadStationTaskStatus.CaptchaNeeded, DownloadItemStatus.Downloading)]
[TestCase(DownloadStationTaskStatus.Paused, DownloadItemStatus.Paused)] [TestCase(DownloadStationTaskStatus.Paused, DownloadItemStatus.Paused)]
[TestCase(DownloadStationTaskStatus.Seeding, DownloadItemStatus.Completed)]
[TestCase(DownloadStationTaskStatus.FilehostingWaiting, DownloadItemStatus.Queued)]
[TestCase(DownloadStationTaskStatus.Waiting, DownloadItemStatus.Queued)] [TestCase(DownloadStationTaskStatus.Waiting, DownloadItemStatus.Queued)]
[TestCase(DownloadStationTaskStatus.Unknown, DownloadItemStatus.Queued)]
public void GetItems_should_return_item_as_downloadItemStatus(DownloadStationTaskStatus apiStatus, DownloadItemStatus expectedItemStatus) public void GetItems_should_return_item_as_downloadItemStatus(DownloadStationTaskStatus apiStatus, DownloadItemStatus expectedItemStatus)
{ {
GivenSerialNumber(); GivenSerialNumber();

@ -311,7 +311,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
} }
[Test] [Test]
public void should_be_read_only_if_max_ratio_not_reached() public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_not_reached()
{ {
GivenMaxRatio(1.0f); GivenMaxRatio(1.0f);
@ -330,11 +330,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
GivenTorrents(new List<QBittorrentTorrent> { torrent }); GivenTorrents(new List<QBittorrentTorrent> { torrent });
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.IsReadOnly.Should().BeTrue(); item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
} }
[Test] [Test]
public void should_be_read_only_if_max_ratio_reached_and_not_paused() public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_reached_and_not_paused()
{ {
GivenMaxRatio(1.0f); GivenMaxRatio(1.0f);
@ -353,11 +354,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
GivenTorrents(new List<QBittorrentTorrent> { torrent }); GivenTorrents(new List<QBittorrentTorrent> { torrent });
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.IsReadOnly.Should().BeTrue(); item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
} }
[Test] [Test]
public void should_be_read_only_if_max_ratio_is_not_set() public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_is_not_set()
{ {
GivenMaxRatio(1.0f, false); GivenMaxRatio(1.0f, false);
@ -376,11 +378,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
GivenTorrents(new List<QBittorrentTorrent> { torrent }); GivenTorrents(new List<QBittorrentTorrent> { torrent });
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.IsReadOnly.Should().BeTrue(); item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
} }
[Test] [Test]
public void should_not_be_read_only_if_max_ratio_reached_and_paused() public void should_be_removable_and_should_allow_move_files_if_max_ratio_reached_and_paused()
{ {
GivenMaxRatio(1.0f); GivenMaxRatio(1.0f);
@ -399,7 +402,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
GivenTorrents(new List<QBittorrentTorrent> { torrent }); GivenTorrents(new List<QBittorrentTorrent> { torrent });
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.IsReadOnly.Should().BeFalse(); item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]

@ -41,6 +41,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
PrepareClientToReturnCompletedItem(); PrepareClientToReturnCompletedItem();
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
VerifyCompleted(item); VerifyCompleted(item);
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -172,13 +175,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
} }
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, false)] [TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, true)]
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, true)] [TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, false)]
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, true)] [TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, false)]
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, true)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, false)]
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, true)] [TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, false)]
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, true)] [TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, false)]
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly) public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedValue)
{ {
_completed.Status = apiStatus; _completed.Status = apiStatus;
@ -187,7 +190,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
item.IsReadOnly.Should().Be(expectedReadOnly); item.CanBeRemoved.Should().Be(expectedValue);
item.CanMoveFiles.Should().Be(expectedValue);
} }
[Test] [Test]

@ -222,6 +222,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
PrepareClientToReturnCompletedItem(); PrepareClientToReturnCompletedItem();
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
VerifyCompleted(item); VerifyCompleted(item);
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -292,12 +295,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
} }
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checking, DownloadItemStatus.Queued, false)] [TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checking, DownloadItemStatus.Queued, true)]
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked, DownloadItemStatus.Completed, false)] [TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked, DownloadItemStatus.Completed, true)]
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Queued, DownloadItemStatus.Completed, true)] [TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Queued, DownloadItemStatus.Completed, false)]
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Started, DownloadItemStatus.Completed, true)] [TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Started, DownloadItemStatus.Completed, false)]
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Queued | UTorrentTorrentStatus.Paused, DownloadItemStatus.Completed, true)] [TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Queued | UTorrentTorrentStatus.Paused, DownloadItemStatus.Completed, false)]
public void GetItems_should_return_completed_item_as_downloadItemStatus(UTorrentTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly) public void GetItems_should_return_completed_item_as_downloadItemStatus(UTorrentTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedValue)
{ {
_completed.Status = apiStatus; _completed.Status = apiStatus;
@ -306,7 +309,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
item.IsReadOnly.Should().Be(expectedReadOnly); item.CanBeRemoved.Should().Be(expectedValue);
item.CanMoveFiles.Should().Be(expectedValue);
} }
[Test] [Test]

@ -181,12 +181,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
} }
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, false)] [TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, true)]
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, true)] [TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, false)]
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, true)] [TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, false)]
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued, true)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued, false)]
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, true)] [TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, false)]
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, true)] [TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, false)]
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly) public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly)
{ {
_completed.Status = apiStatus; _completed.Status = apiStatus;
@ -196,7 +196,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
item.IsReadOnly.Should().Be(expectedReadOnly); item.CanBeRemoved.Should().Be(expectedReadOnly);
item.CanMoveFiles.Should().Be(expectedReadOnly);
} }
[Test] [Test]

@ -81,7 +81,7 @@ namespace NzbDrone.Core.Test.HistoryTests
Path = @"C:\Test\Unsorted\Movie.2011.mkv" Path = @"C:\Test\Unsorted\Movie.2011.mkv"
}; };
Subject.Handle(new MovieImportedEvent(localMovie, movieFile, true, "sab", "abcd", true)); Subject.Handle(new MovieImportedEvent(localMovie, movieFile, true, "sab", "abcd"));
Mocker.GetMock<IHistoryRepository>() Mocker.GetMock<IHistoryRepository>()
.Verify(v => v.Insert(It.Is<History.History>(h => h.SourceTitle == Path.GetFileNameWithoutExtension(localMovie.Path)))); .Verify(v => v.Insert(It.Is<History.History>(h => h.SourceTitle == Path.GetFileNameWithoutExtension(localMovie.Path))));

@ -218,9 +218,9 @@ namespace NzbDrone.Core.Test.MediaFiles
} }
[Test] [Test]
public void should_copy_readonly_downloads() public void should_copy_when_cannot_move_files_downloads()
{ {
Subject.Import(new List<ImportDecision> { _approvedDecisions.First() }, true, new DownloadClientItem { Title = "30.Rock.S01E01", IsReadOnly = true }); Subject.Import(new List<ImportDecision> { _approvedDecisions.First() }, true, new DownloadClientItem { Title = "30.Rock.S01E01", CanMoveFiles = false});
Mocker.GetMock<IUpgradeMediaFiles>() Mocker.GetMock<IUpgradeMediaFiles>()
.Verify(v => v.UpgradeMovieFile(It.IsAny<MovieFile>(), _approvedDecisions.First().LocalMovie, true), Times.Once()); .Verify(v => v.UpgradeMovieFile(It.IsAny<MovieFile>(), _approvedDecisions.First().LocalMovie, true), Times.Once());
@ -229,7 +229,7 @@ namespace NzbDrone.Core.Test.MediaFiles
[Test] [Test]
public void should_use_override_importmode() public void should_use_override_importmode()
{ {
Subject.Import(new List<ImportDecision> { _approvedDecisions.First() }, true, new DownloadClientItem { Title = "30.Rock.S01E01", IsReadOnly = true }, ImportMode.Move); Subject.Import(new List<ImportDecision> { _approvedDecisions.First() }, true, new DownloadClientItem { Title = "30.Rock.S01E01", CanMoveFiles = false }, ImportMode.Move);
Mocker.GetMock<IUpgradeMediaFiles>() Mocker.GetMock<IUpgradeMediaFiles>()
.Verify(v => v.UpgradeMovieFile(It.IsAny<MovieFile>(), _approvedDecisions.First().LocalMovie, false), Times.Once()); .Verify(v => v.UpgradeMovieFile(It.IsAny<MovieFile>(), _approvedDecisions.First().LocalMovie, false), Times.Once());

@ -165,6 +165,7 @@
<Compile Include="Download\DownloadClientTests\Blackhole\UsenetBlackholeFixture.cs" /> <Compile Include="Download\DownloadClientTests\Blackhole\UsenetBlackholeFixture.cs" />
<Compile Include="Download\DownloadClientTests\DelugeTests\DelugeFixture.cs" /> <Compile Include="Download\DownloadClientTests\DelugeTests\DelugeFixture.cs" />
<Compile Include="Download\DownloadClientTests\DownloadClientFixtureBase.cs" /> <Compile Include="Download\DownloadClientTests\DownloadClientFixtureBase.cs" />
<Compile Include="Download\DownloadClientTests\DownloadStationTests\DownloadStationsTaskStatusJsonConverterFixture.cs" />
<Compile Include="Download\DownloadClientTests\HadoukenTests\HadoukenFixture.cs" /> <Compile Include="Download\DownloadClientTests\HadoukenTests\HadoukenFixture.cs" />
<Compile Include="Download\DownloadClientTests\NzbgetTests\NzbgetFixture.cs" /> <Compile Include="Download\DownloadClientTests\NzbgetTests\NzbgetFixture.cs" />
<Compile Include="Download\DownloadClientTests\NzbVortexTests\NzbVortexFixture.cs" /> <Compile Include="Download\DownloadClientTests\NzbVortexTests\NzbVortexFixture.cs" />

@ -103,7 +103,8 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
Status = item.Status, Status = item.Status,
IsReadOnly = Settings.ReadOnly CanMoveFiles = !Settings.ReadOnly,
CanBeRemoved = !Settings.ReadOnly
}; };
} }
} }

@ -122,14 +122,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
} }
// Here we detect if Deluge is managing the torrent and whether the seed criteria has been met. This allows drone to delete the torrent as appropriate. // Here we detect if Deluge is managing the torrent and whether the seed criteria has been met. This allows drone to delete the torrent as appropriate.
if (torrent.IsAutoManaged && torrent.StopAtRatio && torrent.Ratio >= torrent.StopRatio && torrent.State == DelugeTorrentStatus.Paused) item.CanMoveFiles = item.CanBeRemoved = (torrent.IsAutoManaged && torrent.StopAtRatio && torrent.Ratio >= torrent.StopRatio && torrent.State == DelugeTorrentStatus.Paused);
{
item.IsReadOnly = false;
}
else
{
item.IsReadOnly = true;
}
items.Add(item); items.Add(item);
} }

@ -1,7 +1,6 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using NzbDrone.Common.Serializer;
namespace NzbDrone.Core.Download.Clients.DownloadStation namespace NzbDrone.Core.Download.Clients.DownloadStation
{ {
@ -23,7 +22,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
[JsonProperty(PropertyName = "status_extra")] [JsonProperty(PropertyName = "status_extra")]
public Dictionary<string, string> StatusExtra { get; set; } public Dictionary<string, string> StatusExtra { get; set; }
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(UnderscoreStringEnumConverter), DownloadStationTaskStatus.Unknown)]
public DownloadStationTaskStatus Status { get; set; } public DownloadStationTaskStatus Status { get; set; }
public DownloadStationTaskAdditional Additional { get; set; } public DownloadStationTaskAdditional Additional { get; set; }
@ -41,6 +40,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
public enum DownloadStationTaskStatus public enum DownloadStationTaskStatus
{ {
Unknown,
Waiting, Waiting,
Downloading, Downloading,
Paused, Paused,
@ -48,9 +48,10 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
Finished, Finished,
HashChecking, HashChecking,
Seeding, Seeding,
FileHostingWaiting, FilehostingWaiting,
Extracting, Extracting,
Error Error,
CaptchaNeeded
} }
public enum DownloadStationPriority public enum DownloadStationPriority

@ -72,7 +72,20 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
DownloadStationSettings settings) where T : new() DownloadStationSettings settings) where T : new()
{ {
var request = requestBuilder.Build(); var request = requestBuilder.Build();
var response = _httpClient.Execute(request); HttpResponse response;
try
{
response = _httpClient.Execute(request);
}
catch (HttpException ex)
{
throw new DownloadClientException("Unable to connect to Diskstation, please check your settings", ex);
}
catch (WebException ex)
{
throw new DownloadClientException("Unable to connect to Diskstation, please check your settings", ex);
}
_logger.Debug("Trying to {0}", operation); _logger.Debug("Trying to {0}", operation);

@ -90,7 +90,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
RemainingTime = GetRemainingTime(torrent), RemainingTime = GetRemainingTime(torrent),
Status = GetStatus(torrent), Status = GetStatus(torrent),
Message = GetMessage(torrent), Message = GetMessage(torrent),
IsReadOnly = !IsFinished(torrent) CanMoveFiles = IsCompleted(torrent),
CanBeRemoved = IsFinished(torrent)
}; };
if (item.Status == DownloadItemStatus.Completed || item.Status == DownloadItemStatus.Failed) if (item.Status == DownloadItemStatus.Completed || item.Status == DownloadItemStatus.Failed)
@ -199,6 +200,11 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
return torrent.Status == DownloadStationTaskStatus.Finished; return torrent.Status == DownloadStationTaskStatus.Finished;
} }
protected bool IsCompleted(DownloadStationTask torrent)
{
return torrent.Status == DownloadStationTaskStatus.Seeding || IsFinished(torrent) || (torrent.Status == DownloadStationTaskStatus.Waiting && torrent.Size != 0 && GetRemainingSize(torrent) <= 0);
}
protected string GetMessage(DownloadStationTask torrent) protected string GetMessage(DownloadStationTask torrent)
{ {
if (torrent.StatusExtra != null) if (torrent.StatusExtra != null)
@ -221,7 +227,9 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
{ {
switch (torrent.Status) switch (torrent.Status)
{ {
case DownloadStationTaskStatus.Unknown:
case DownloadStationTaskStatus.Waiting: case DownloadStationTaskStatus.Waiting:
case DownloadStationTaskStatus.FilehostingWaiting:
return torrent.Size == 0 || GetRemainingSize(torrent) > 0 ? DownloadItemStatus.Queued : DownloadItemStatus.Completed; return torrent.Size == 0 || GetRemainingSize(torrent) > 0 ? DownloadItemStatus.Queued : DownloadItemStatus.Completed;
case DownloadStationTaskStatus.Paused: case DownloadStationTaskStatus.Paused:
return DownloadItemStatus.Paused; return DownloadItemStatus.Paused;
@ -314,12 +322,12 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
} }
catch (DownloadClientAuthenticationException ex) // User could not have permission to access to downloadstation catch (DownloadClientAuthenticationException ex) // User could not have permission to access to downloadstation
{ {
_logger.Error(ex); _logger.Error(ex, ex.Message);
return new NzbDroneValidationFailure(string.Empty, ex.Message); return new NzbDroneValidationFailure(string.Empty, ex.Message);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error(ex); _logger.Error(ex, "Error testing Torrent Download Station");
return new NzbDroneValidationFailure(string.Empty, $"Unknown exception: {ex.Message}"); return new NzbDroneValidationFailure(string.Empty, $"Unknown exception: {ex.Message}");
} }
} }
@ -340,7 +348,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
} }
catch (WebException ex) catch (WebException ex)
{ {
_logger.Error(ex); _logger.Error(ex, "Unable to connect to Torrent Download Station");
if (ex.Status == WebExceptionStatus.ConnectFailure) if (ex.Status == WebExceptionStatus.ConnectFailure)
{ {
@ -353,7 +361,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error(ex); _logger.Error(ex, "Error testing Torrent Download Station");
return new NzbDroneValidationFailure(string.Empty, $"Unknown exception: {ex.Message}"); return new NzbDroneValidationFailure(string.Empty, $"Unknown exception: {ex.Message}");
} }
} }

@ -99,7 +99,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
RemainingSize = taskRemainingSize, RemainingSize = taskRemainingSize,
Status = GetStatus(nzb), Status = GetStatus(nzb),
Message = GetMessage(nzb), Message = GetMessage(nzb),
IsReadOnly = !IsFinished(nzb) CanBeRemoved = true,
CanMoveFiles = true
}; };
if (item.Status != DownloadItemStatus.Paused) if (item.Status != DownloadItemStatus.Paused)
@ -233,12 +234,12 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
} }
catch (DownloadClientAuthenticationException ex) // User could not have permission to access to downloadstation catch (DownloadClientAuthenticationException ex) // User could not have permission to access to downloadstation
{ {
_logger.Error(ex); _logger.Error(ex, ex.Message);
return new NzbDroneValidationFailure(string.Empty, ex.Message); return new NzbDroneValidationFailure(string.Empty, ex.Message);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error(ex); _logger.Error(ex, "Error testing Usenet Download Station");
return new NzbDroneValidationFailure(string.Empty, $"Unknown exception: {ex.Message}"); return new NzbDroneValidationFailure(string.Empty, $"Unknown exception: {ex.Message}");
} }
} }
@ -259,7 +260,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
} }
catch (WebException ex) catch (WebException ex)
{ {
_logger.Error(ex); _logger.Error(ex, "Unable to connect to Usenet Download Station");
if (ex.Status == WebExceptionStatus.ConnectFailure) if (ex.Status == WebExceptionStatus.ConnectFailure)
{ {
@ -272,7 +273,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error(ex); _logger.Error(ex, "Error testing Torrent Download Station");
return new NzbDroneValidationFailure(string.Empty, "Unknown exception: " + ex.Message); return new NzbDroneValidationFailure(string.Empty, "Unknown exception: " + ex.Message);
} }
} }
@ -291,11 +292,6 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
return null; return null;
} }
protected bool IsFinished(DownloadStationTask task)
{
return task.Status == DownloadStationTaskStatus.Finished;
}
protected string GetMessage(DownloadStationTask task) protected string GetMessage(DownloadStationTask task)
{ {
if (task.StatusExtra != null) if (task.StatusExtra != null)
@ -318,7 +314,9 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
{ {
switch (task.Status) switch (task.Status)
{ {
case DownloadStationTaskStatus.Unknown:
case DownloadStationTaskStatus.Waiting: case DownloadStationTaskStatus.Waiting:
case DownloadStationTaskStatus.FilehostingWaiting:
return task.Size == 0 || GetRemainingSize(task) > 0 ? DownloadItemStatus.Queued : DownloadItemStatus.Completed; return task.Size == 0 || GetRemainingSize(task) > 0 ? DownloadItemStatus.Queued : DownloadItemStatus.Completed;
case DownloadStationTaskStatus.Paused: case DownloadStationTaskStatus.Paused:
return DownloadItemStatus.Paused; return DownloadItemStatus.Paused;

@ -97,14 +97,7 @@ namespace NzbDrone.Core.Download.Clients.Hadouken
item.Status = DownloadItemStatus.Downloading; item.Status = DownloadItemStatus.Downloading;
} }
if (torrent.IsFinished && torrent.State == HadoukenTorrentState.Paused) item.CanMoveFiles = item.CanBeRemoved = (torrent.IsFinished && torrent.State == HadoukenTorrentState.Paused);
{
item.IsReadOnly = false;
}
else
{
item.IsReadOnly = true;
}
items.Add(item); items.Add(item);
} }

@ -72,7 +72,9 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
queueItem.TotalSize = vortexQueueItem.TotalDownloadSize; queueItem.TotalSize = vortexQueueItem.TotalDownloadSize;
queueItem.RemainingSize = vortexQueueItem.TotalDownloadSize - vortexQueueItem.DownloadedSize; queueItem.RemainingSize = vortexQueueItem.TotalDownloadSize - vortexQueueItem.DownloadedSize;
queueItem.RemainingTime = null; queueItem.RemainingTime = null;
queueItem.CanBeRemoved = true;
queueItem.CanMoveFiles = true;
if (vortexQueueItem.IsPaused) if (vortexQueueItem.IsPaused)
{ {
queueItem.Status = DownloadItemStatus.Paused; queueItem.Status = DownloadItemStatus.Paused;

@ -77,14 +77,15 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone"); var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone");
var queueItem = new DownloadClientItem() var queueItem = new DownloadClientItem();
{ queueItem.DownloadId = droneParameter == null ? item.NzbId.ToString() : droneParameter.Value.ToString();
DownloadId = droneParameter == null ? item.NzbId.ToString() : droneParameter.Value.ToString(), queueItem.Title = item.NzbName;
Title = item.NzbName, queueItem.TotalSize = totalSize;
TotalSize = totalSize, queueItem.Category = item.Category;
Category = item.Category, queueItem.DownloadClient = Definition.Name;
DownloadClient = Definition.Name queueItem.CanMoveFiles = true;
}; queueItem.CanBeRemoved = true;
if (globalStatus.DownloadPaused || remainingSize == pausedSize && remainingSize != 0) if (globalStatus.DownloadPaused || remainingSize == pausedSize && remainingSize != 0)
{ {
queueItem.Status = DownloadItemStatus.Paused; queueItem.Status = DownloadItemStatus.Paused;
@ -136,18 +137,19 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone"); var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone");
var historyItem = new DownloadClientItem() var historyItem = new DownloadClientItem();
{ historyItem.DownloadClient = Definition.Name;
DownloadClient = Definition.Name, historyItem.DownloadId = droneParameter == null ? item.Id.ToString() : droneParameter.Value.ToString();
DownloadId = droneParameter == null ? item.Id.ToString() : droneParameter.Value.ToString(), historyItem.Title = item.Name;
Title = item.Name, historyItem.TotalSize = MakeInt64(item.FileSizeHi, item.FileSizeLo);
TotalSize = MakeInt64(item.FileSizeHi, item.FileSizeLo), historyItem.OutputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(item.DestDir));
OutputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(item.DestDir)), historyItem.Category = item.Category;
Category = item.Category, historyItem.Message = $"PAR Status: {item.ParStatus} - Unpack Status: {item.UnpackStatus} - Move Status: {item.MoveStatus} - Script Status: {item.ScriptStatus} - Delete Status: {item.DeleteStatus} - Mark Status: {item.MarkStatus}";
Message = $"PAR Status: {item.ParStatus} - Unpack Status: {item.UnpackStatus} - Move Status: {item.MoveStatus} - Script Status: {item.ScriptStatus} - Delete Status: {item.DeleteStatus} - Mark Status: {item.MarkStatus}", historyItem.Status = DownloadItemStatus.Completed;
Status = DownloadItemStatus.Completed, historyItem.RemainingTime = TimeSpan.Zero;
RemainingTime = TimeSpan.Zero historyItem.CanMoveFiles = true;
}; historyItem.CanBeRemoved = true;
if (item.DeleteStatus == "MANUAL") if (item.DeleteStatus == "MANUAL")
{ {
continue; continue;

@ -78,6 +78,9 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
DownloadId = GetDownloadClientId(file), DownloadId = GetDownloadClientId(file),
Title = title, Title = title,
CanBeRemoved = true,
CanMoveFiles = true,
TotalSize = _diskProvider.GetFileSize(file), TotalSize = _diskProvider.GetFileSize(file),
OutputPath = new OsPath(file) OutputPath = new OsPath(file)

@ -94,7 +94,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
// Avoid removing torrents that haven't reached the global max ratio. // Avoid removing torrents that haven't reached the global max ratio.
// Removal also requires the torrent to be paused, in case a higher max ratio was set on the torrent itself (which is not exposed by the api). // Removal also requires the torrent to be paused, in case a higher max ratio was set on the torrent itself (which is not exposed by the api).
item.IsReadOnly = (config.MaxRatioEnabled && config.MaxRatio > torrent.Ratio) || torrent.State != "pausedUP"; item.CanMoveFiles = item.CanBeRemoved = (!config.MaxRatioEnabled || config.MaxRatio <= torrent.Ratio) && torrent.State == "pausedUP";
if (!item.OutputPath.IsEmpty && item.OutputPath.FileName != torrent.Name) if (!item.OutputPath.IsEmpty && item.OutputPath.FileName != torrent.Name)
{ {

@ -78,6 +78,8 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
queueItem.TotalSize = (long)(sabQueueItem.Size * 1024 * 1024); queueItem.TotalSize = (long)(sabQueueItem.Size * 1024 * 1024);
queueItem.RemainingSize = (long)(sabQueueItem.Sizeleft * 1024 * 1024); queueItem.RemainingSize = (long)(sabQueueItem.Sizeleft * 1024 * 1024);
queueItem.RemainingTime = sabQueueItem.Timeleft; queueItem.RemainingTime = sabQueueItem.Timeleft;
queueItem.CanBeRemoved = true;
queueItem.CanMoveFiles = true;
if (sabQueue.Paused || sabQueueItem.Status == SabnzbdDownloadStatus.Paused) if (sabQueue.Paused || sabQueueItem.Status == SabnzbdDownloadStatus.Paused)
{ {
@ -142,7 +144,10 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
RemainingSize = 0, RemainingSize = 0,
RemainingTime = TimeSpan.Zero, RemainingTime = TimeSpan.Zero,
Message = sabHistoryItem.FailMessage Message = sabHistoryItem.FailMessage,
CanBeRemoved = true,
CanMoveFiles = true
}; };
if (sabHistoryItem.Status == SabnzbdDownloadStatus.Failed) if (sabHistoryItem.Status == SabnzbdDownloadStatus.Failed)

@ -106,7 +106,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
item.Status = DownloadItemStatus.Downloading; item.Status = DownloadItemStatus.Downloading;
} }
item.IsReadOnly = torrent.Status != TransmissionTorrentStatus.Stopped; item.CanMoveFiles = item.CanBeRemoved = torrent.Status == TransmissionTorrentStatus.Stopped;
items.Add(item); items.Add(item);
} }

@ -115,7 +115,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
else if (!torrent.IsActive) item.Status = DownloadItemStatus.Paused; else if (!torrent.IsActive) item.Status = DownloadItemStatus.Paused;
// No stop ratio data is present, so do not delete // No stop ratio data is present, so do not delete
item.IsReadOnly = true; item.CanMoveFiles = item.CanBeRemoved = false;
items.Add(item); items.Add(item);
} }

@ -169,7 +169,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
} }
// 'Started' without 'Queued' is when the torrent is 'forced seeding' // 'Started' without 'Queued' is when the torrent is 'forced seeding'
item.IsReadOnly = torrent.Status.HasFlag(UTorrentTorrentStatus.Queued) || torrent.Status.HasFlag(UTorrentTorrentStatus.Started); item.CanMoveFiles = item.CanBeRemoved = (!torrent.Status.HasFlag(UTorrentTorrentStatus.Queued) && !torrent.Status.HasFlag(UTorrentTorrentStatus.Started));
queueItems.Add(item); queueItems.Add(item);
} }

@ -21,7 +21,9 @@ namespace NzbDrone.Core.Download
public DownloadItemStatus Status { get; set; } public DownloadItemStatus Status { get; set; }
public bool IsEncrypted { get; set; } public bool IsEncrypted { get; set; }
public bool IsReadOnly { get; set; }
public bool CanMoveFiles { get; set; }
public bool CanBeRemoved { get; set; }
public bool Removed { get; set; } public bool Removed { get; set; }
} }

@ -37,7 +37,7 @@ namespace NzbDrone.Core.Download
{ {
if (!_configService.RemoveCompletedDownloads || if (!_configService.RemoveCompletedDownloads ||
message.TrackedDownload.DownloadItem.Removed || message.TrackedDownload.DownloadItem.Removed ||
message.TrackedDownload.DownloadItem.IsReadOnly || !message.TrackedDownload.DownloadItem.CanBeRemoved ||
message.TrackedDownload.DownloadItem.Status == DownloadItemStatus.Downloading) message.TrackedDownload.DownloadItem.Status == DownloadItemStatus.Downloading)
{ {
return; return;
@ -50,7 +50,7 @@ namespace NzbDrone.Core.Download
{ {
var trackedDownload = message.TrackedDownload; var trackedDownload = message.TrackedDownload;
if (trackedDownload == null || trackedDownload.DownloadItem.IsReadOnly || _configService.RemoveFailedDownloads == false) if (trackedDownload == null || !trackedDownload.DownloadItem.CanBeRemoved || _configService.RemoveFailedDownloads == false)
{ {
return; return;
} }

@ -107,7 +107,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
private void RemoveCompletedDownloads(List<TrackedDownload> trackedDownloads) private void RemoveCompletedDownloads(List<TrackedDownload> trackedDownloads)
{ {
foreach (var trackedDownload in trackedDownloads.Where(c => !c.DownloadItem.IsReadOnly && c.State == TrackedDownloadStage.Imported)) foreach (var trackedDownload in trackedDownloads.Where(c => c.DownloadItem.CanBeRemoved && c.State == TrackedDownloadStage.Imported))
{ {
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload)); _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
} }

@ -191,7 +191,7 @@ namespace NzbDrone.Core.MediaFiles
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, null, folderInfo, true, false); var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, null, folderInfo, true, false);
var importResults = _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode); var importResults = _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
if ((downloadClientItem == null || !downloadClientItem.IsReadOnly) && if ((downloadClientItem == null || downloadClientItem.CanBeRemoved) &&
importResults.Any(i => i.Result == ImportResultType.Imported) && importResults.Any(i => i.Result == ImportResultType.Imported) &&
ShouldDeleteFolder(directoryInfo, movie)) ShouldDeleteFolder(directoryInfo, movie))
{ {

@ -9,8 +9,7 @@ namespace NzbDrone.Core.MediaFiles.Events
public MovieFile ImportedMovie { get; private set; } public MovieFile ImportedMovie { get; private set; }
public bool NewDownload { get; private set; } public bool NewDownload { get; private set; }
public string DownloadClient { get; private set; } public string DownloadClient { get; private set; }
public string DownloadId { get; private set; } public string DownloadId { get; private set; }
public bool IsReadOnly { get; set; }
public MovieImportedEvent(LocalMovie movieInfo, MovieFile importedMovie, bool newDownload) public MovieImportedEvent(LocalMovie movieInfo, MovieFile importedMovie, bool newDownload)
{ {
@ -19,14 +18,13 @@ namespace NzbDrone.Core.MediaFiles.Events
NewDownload = newDownload; NewDownload = newDownload;
} }
public MovieImportedEvent(LocalMovie movieInfo, MovieFile importedMovie, bool newDownload, string downloadClient, string downloadId, bool isReadOnly) public MovieImportedEvent(LocalMovie movieInfo, MovieFile importedMovie, bool newDownload, string downloadClient, string downloadId)
{ {
MovieInfo = movieInfo; MovieInfo = movieInfo;
ImportedMovie = importedMovie; ImportedMovie = importedMovie;
NewDownload = newDownload; NewDownload = newDownload;
DownloadClient = downloadClient; DownloadClient = downloadClient;
DownloadId = downloadId; DownloadId = downloadId;
IsReadOnly = isReadOnly;
} }
} }
} }

@ -93,7 +93,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
{ {
default: default:
case ImportMode.Auto: case ImportMode.Auto:
copyOnly = downloadClientItem != null && downloadClientItem.IsReadOnly; copyOnly = downloadClientItem != null && !downloadClientItem.CanMoveFiles;
break; break;
case ImportMode.Move: case ImportMode.Move:
copyOnly = false; copyOnly = false;
@ -125,7 +125,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
if (downloadClientItem != null) if (downloadClientItem != null)
{ {
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, movieFile, newDownload, downloadClientItem.DownloadClient, downloadClientItem.DownloadId, downloadClientItem.IsReadOnly)); _eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, movieFile, newDownload, downloadClientItem.DownloadClient, downloadClientItem.DownloadId));
} }
else else
{ {

@ -268,7 +268,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
{ {
if (_downloadedMovieImportService.ShouldDeleteFolder( if (_downloadedMovieImportService.ShouldDeleteFolder(
new DirectoryInfo(trackedDownload.DownloadItem.OutputPath.FullPath), new DirectoryInfo(trackedDownload.DownloadItem.OutputPath.FullPath),
trackedDownload.RemoteMovie.Movie) && !trackedDownload.DownloadItem.IsReadOnly) trackedDownload.RemoteMovie.Movie) && trackedDownload.DownloadItem.CanMoveFiles)
{ {
_diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath.FullPath, true); _diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath.FullPath, true);
} }

Loading…
Cancel
Save