Fixed: QBittorrent imports when torrent name and folder name differ
closes #3346 fixes #3968 closes #4068
This commit is contained in:
parent
c75c546888
commit
813f886920
|
@ -44,6 +44,7 @@ namespace NzbDrone.Core.Test.Download.CompletedDownloadServiceTests
|
||||||
|
|
||||||
_trackedDownload = Builder<TrackedDownload>.CreateNew()
|
_trackedDownload = Builder<TrackedDownload>.CreateNew()
|
||||||
.With(c => c.State = TrackedDownloadState.Downloading)
|
.With(c => c.State = TrackedDownloadState.Downloading)
|
||||||
|
.With(c => c.ImportItem = completed)
|
||||||
.With(c => c.DownloadItem = completed)
|
.With(c => c.DownloadItem = completed)
|
||||||
.With(c => c.RemoteEpisode = remoteEpisode)
|
.With(c => c.RemoteEpisode = remoteEpisode)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
|
@ -50,6 +50,10 @@ namespace NzbDrone.Core.Test.Download.CompletedDownloadServiceTests
|
||||||
.Setup(c => c.Get(It.IsAny<int>()))
|
.Setup(c => c.Get(It.IsAny<int>()))
|
||||||
.Returns(Mocker.GetMock<IDownloadClient>().Object);
|
.Returns(Mocker.GetMock<IDownloadClient>().Object);
|
||||||
|
|
||||||
|
Mocker.GetMock<IProvideImportItemService>()
|
||||||
|
.Setup(c => c.ProvideImportItem(It.IsAny<DownloadClientItem>(), It.IsAny<DownloadClientItem>()))
|
||||||
|
.Returns((DownloadClientItem item, DownloadClientItem previous) => item);
|
||||||
|
|
||||||
Mocker.GetMock<IHistoryService>()
|
Mocker.GetMock<IHistoryService>()
|
||||||
.Setup(s => s.MostRecentForDownloadId(_trackedDownload.DownloadItem.DownloadId))
|
.Setup(s => s.MostRecentForDownloadId(_trackedDownload.DownloadItem.DownloadId))
|
||||||
.Returns(new EpisodeHistory());
|
.Returns(new EpisodeHistory());
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.MediaFiles.TorrentInfo;
|
using NzbDrone.Core.MediaFiles.TorrentInfo;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
@ -122,6 +124,24 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||||
Mocker.GetMock<IQBittorrentProxy>()
|
Mocker.GetMock<IQBittorrentProxy>()
|
||||||
.Setup(s => s.GetTorrents(It.IsAny<QBittorrentSettings>()))
|
.Setup(s => s.GetTorrents(It.IsAny<QBittorrentSettings>()))
|
||||||
.Returns(torrents);
|
.Returns(torrents);
|
||||||
|
|
||||||
|
foreach (var torrent in torrents)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IQBittorrentProxy>()
|
||||||
|
.Setup(s => s.GetTorrentProperties(torrent.Hash.ToLower(), It.IsAny<QBittorrentSettings>()))
|
||||||
|
.Returns(new QBittorrentTorrentProperties { SavePath = torrent.SavePath });
|
||||||
|
|
||||||
|
Mocker.GetMock<IQBittorrentProxy>()
|
||||||
|
.Setup(s => s.GetTorrentFiles(torrent.Hash.ToLower(), It.IsAny<QBittorrentSettings>()))
|
||||||
|
.Returns(new List<QBittorrentTorrentFile> { new QBittorrentTorrentFile { Name = torrent.Name } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTorrentFiles(string hash, List<QBittorrentTorrentFile> files)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IQBittorrentProxy>()
|
||||||
|
.Setup(s => s.GetTorrentFiles(hash.ToLower(), It.IsAny<QBittorrentSettings>()))
|
||||||
|
.Returns(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -256,6 +276,112 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||||
item.RemainingTime.Should().NotHaveValue();
|
item.RemainingTime.Should().NotHaveValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void single_file_torrent_outputpath_should_have_sanitised_name()
|
||||||
|
{
|
||||||
|
var torrent = new QBittorrentTorrent
|
||||||
|
{
|
||||||
|
Hash = "HASH",
|
||||||
|
Name = @"Droned.S01E01.Test\'s.1080p.WEB-DL-DRONE.mkv",
|
||||||
|
Size = 1000,
|
||||||
|
Progress = 0.7,
|
||||||
|
Eta = 8640000,
|
||||||
|
State = "stalledDL",
|
||||||
|
Label = "",
|
||||||
|
SavePath = @"C:\Torrents".AsOsAgnostic()
|
||||||
|
};
|
||||||
|
|
||||||
|
var file = new QBittorrentTorrentFile
|
||||||
|
{
|
||||||
|
Name = "Droned.S01E01.Tests.1080p.WEB-DL-DRONE.mkv"
|
||||||
|
};
|
||||||
|
|
||||||
|
GivenTorrents(new List<QBittorrentTorrent> { torrent });
|
||||||
|
GivenTorrentFiles(torrent.Hash, new List<QBittorrentTorrentFile> { file });
|
||||||
|
|
||||||
|
var item = new DownloadClientItem
|
||||||
|
{
|
||||||
|
DownloadId = torrent.Hash
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = Subject.GetImportItem(item, null);
|
||||||
|
|
||||||
|
result.OutputPath.FullPath.Should().Be(Path.Combine(torrent.SavePath, file.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void multi_file_torrent_outputpath_should_have_sanitised_name()
|
||||||
|
{
|
||||||
|
var torrent = new QBittorrentTorrent
|
||||||
|
{
|
||||||
|
Hash = "HASH",
|
||||||
|
Name = @"Droned.S01.\1/2",
|
||||||
|
Size = 1000,
|
||||||
|
Progress = 0.7,
|
||||||
|
Eta = 8640000,
|
||||||
|
State = "stalledDL",
|
||||||
|
Label = "",
|
||||||
|
SavePath = @"C:\Torrents".AsOsAgnostic()
|
||||||
|
};
|
||||||
|
|
||||||
|
var files = new List<QBittorrentTorrentFile>
|
||||||
|
{
|
||||||
|
new QBittorrentTorrentFile
|
||||||
|
{
|
||||||
|
Name = @"Droned.S01.12\E01.mkv".AsOsAgnostic()
|
||||||
|
},
|
||||||
|
new QBittorrentTorrentFile
|
||||||
|
{
|
||||||
|
Name = @"Droned.S01.12\E02.mkv".AsOsAgnostic()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GivenTorrents(new List<QBittorrentTorrent> { torrent });
|
||||||
|
GivenTorrentFiles(torrent.Hash, files);
|
||||||
|
|
||||||
|
var item = new DownloadClientItem
|
||||||
|
{
|
||||||
|
DownloadId = torrent.Hash
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = Subject.GetImportItem(item, null);
|
||||||
|
|
||||||
|
result.OutputPath.FullPath.Should().Be(Path.Combine(torrent.SavePath, "Droned.S01.12") + Path.DirectorySeparatorChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void api_261_should_use_content_path()
|
||||||
|
{
|
||||||
|
var torrent = new QBittorrentTorrent
|
||||||
|
{
|
||||||
|
Hash = "HASH",
|
||||||
|
Name = @"Droned.S01.\1/2",
|
||||||
|
Size = 1000,
|
||||||
|
Progress = 0.7,
|
||||||
|
Eta = 8640000,
|
||||||
|
State = "stalledDL",
|
||||||
|
Label = "",
|
||||||
|
SavePath = @"C:\Torrents".AsOsAgnostic(),
|
||||||
|
ContentPath = @"C:\Torrents\Droned.S01.12".AsOsAgnostic()
|
||||||
|
};
|
||||||
|
|
||||||
|
GivenTorrents(new List<QBittorrentTorrent> { torrent });
|
||||||
|
|
||||||
|
Mocker.GetMock<IQBittorrentProxy>()
|
||||||
|
.Setup(v => v.GetApiVersion(It.IsAny<QBittorrentSettings>()))
|
||||||
|
.Returns(new Version(2, 6, 1));
|
||||||
|
|
||||||
|
var item = new DownloadClientItem
|
||||||
|
{
|
||||||
|
DownloadId = torrent.Hash,
|
||||||
|
OutputPath = new OsPath(torrent.ContentPath)
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = Subject.GetImportItem(item, null);
|
||||||
|
|
||||||
|
result.OutputPath.FullPath.Should().Be(torrent.ContentPath);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Download_should_return_unique_id()
|
public void Download_should_return_unique_id()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using FluentValidation.Results;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.MediaFiles.TorrentInfo;
|
using NzbDrone.Core.MediaFiles.TorrentInfo;
|
||||||
using NLog;
|
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
using FluentValidation.Results;
|
|
||||||
using System.Net;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.RemotePathMappings;
|
using NzbDrone.Core.RemotePathMappings;
|
||||||
using NzbDrone.Common.Cache;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.QBittorrent
|
namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
{
|
{
|
||||||
|
@ -122,6 +122,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
public override IEnumerable<DownloadClientItem> GetItems()
|
public override IEnumerable<DownloadClientItem> GetItems()
|
||||||
{
|
{
|
||||||
|
var version = Proxy.GetApiVersion(Settings);
|
||||||
var config = Proxy.GetConfig(Settings);
|
var config = Proxy.GetConfig(Settings);
|
||||||
var torrents = Proxy.GetTorrents(Settings);
|
var torrents = Proxy.GetTorrents(Settings);
|
||||||
|
|
||||||
|
@ -138,19 +139,18 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this),
|
DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this),
|
||||||
RemainingSize = (long)(torrent.Size * (1.0 - torrent.Progress)),
|
RemainingSize = (long)(torrent.Size * (1.0 - torrent.Progress)),
|
||||||
RemainingTime = GetRemainingTime(torrent),
|
RemainingTime = GetRemainingTime(torrent),
|
||||||
SeedRatio = torrent.Ratio,
|
SeedRatio = torrent.Ratio
|
||||||
OutputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(torrent.SavePath)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (version >= new Version("2.6.1"))
|
||||||
|
{
|
||||||
|
item.OutputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(torrent.ContentPath));
|
||||||
|
}
|
||||||
|
|
||||||
// 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.CanMoveFiles = item.CanBeRemoved = (torrent.State == "pausedUP" && HasReachedSeedLimit(torrent, config));
|
item.CanMoveFiles = item.CanBeRemoved = (torrent.State == "pausedUP" && HasReachedSeedLimit(torrent, config));
|
||||||
|
|
||||||
if (!item.OutputPath.IsEmpty && item.OutputPath.FileName != torrent.Name)
|
|
||||||
{
|
|
||||||
item.OutputPath += torrent.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (torrent.State)
|
switch (torrent.State)
|
||||||
{
|
{
|
||||||
case "error": // some error occurred, applies to paused torrents
|
case "error": // some error occurred, applies to paused torrents
|
||||||
|
@ -218,6 +218,49 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
Proxy.RemoveTorrent(hash.ToLower(), deleteData, Settings);
|
Proxy.RemoveTorrent(hash.ToLower(), deleteData, Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override DownloadClientItem GetImportItem(DownloadClientItem item, DownloadClientItem previousImportAttempt)
|
||||||
|
{
|
||||||
|
// On API version >= 2.6.1 this is already set correctly
|
||||||
|
if (!item.OutputPath.IsEmpty)
|
||||||
|
{
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
var files = Proxy.GetTorrentFiles(item.DownloadId.ToLower(), Settings);
|
||||||
|
if (!files.Any())
|
||||||
|
{
|
||||||
|
_logger.Debug($"No files found for torrent {item.Title} in qBittorrent");
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
var properties = Proxy.GetTorrentProperties(item.DownloadId.ToLower(), Settings);
|
||||||
|
var savePath = new OsPath(properties.SavePath);
|
||||||
|
|
||||||
|
var result = item.Clone();
|
||||||
|
|
||||||
|
OsPath outputPath;
|
||||||
|
if (files.Count == 1)
|
||||||
|
{
|
||||||
|
outputPath = savePath + files[0].Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we have multiple files in the torrent so just get
|
||||||
|
// the first subdirectory
|
||||||
|
var relativePath = new OsPath(files[0].Name);
|
||||||
|
while (!relativePath.Directory.IsEmpty)
|
||||||
|
{
|
||||||
|
relativePath = relativePath.Directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPath = savePath + relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.OutputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, outputPath);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public override DownloadClientInfo GetStatus()
|
public override DownloadClientInfo GetStatus()
|
||||||
{
|
{
|
||||||
var config = Proxy.GetConfig(Settings);
|
var config = Proxy.GetConfig(Settings);
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
QBittorrentPreferences GetConfig(QBittorrentSettings settings);
|
QBittorrentPreferences GetConfig(QBittorrentSettings settings);
|
||||||
List<QBittorrentTorrent> GetTorrents(QBittorrentSettings settings);
|
List<QBittorrentTorrent> GetTorrents(QBittorrentSettings settings);
|
||||||
QBittorrentTorrentProperties GetTorrentProperties(string hash, QBittorrentSettings settings);
|
QBittorrentTorrentProperties GetTorrentProperties(string hash, QBittorrentSettings settings);
|
||||||
|
List<QBittorrentTorrentFile> GetTorrentFiles(string hash, QBittorrentSettings settings);
|
||||||
|
|
||||||
void AddTorrentFromUrl(string torrentUrl, QBittorrentSettings settings);
|
void AddTorrentFromUrl(string torrentUrl, QBittorrentSettings settings);
|
||||||
void AddTorrentFromFile(string fileName, Byte[] fileContent, QBittorrentSettings settings);
|
void AddTorrentFromFile(string fileName, Byte[] fileContent, QBittorrentSettings settings);
|
||||||
|
|
|
@ -106,6 +106,14 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<QBittorrentTorrentFile> GetTorrentFiles(string hash, QBittorrentSettings settings)
|
||||||
|
{
|
||||||
|
var request = BuildRequest(settings).Resource($"/query/propertiesFiles/{hash}");
|
||||||
|
var response = ProcessRequest<List<QBittorrentTorrentFile>>(request, settings);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
public void AddTorrentFromUrl(string torrentUrl, QBittorrentSettings settings)
|
public void AddTorrentFromUrl(string torrentUrl, QBittorrentSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings).Resource("/command/download")
|
var request = BuildRequest(settings).Resource("/command/download")
|
||||||
|
|
|
@ -110,6 +110,15 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<QBittorrentTorrentFile> GetTorrentFiles(string hash, QBittorrentSettings settings)
|
||||||
|
{
|
||||||
|
var request = BuildRequest(settings).Resource("/api/v2/torrents/files")
|
||||||
|
.AddQueryParam("hash", hash);
|
||||||
|
var response = ProcessRequest<List<QBittorrentTorrentFile>>(request, settings);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
public void AddTorrentFromUrl(string torrentUrl, QBittorrentSettings settings)
|
public void AddTorrentFromUrl(string torrentUrl, QBittorrentSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings).Resource("/api/v2/torrents/add")
|
var request = BuildRequest(settings).Resource("/api/v2/torrents/add")
|
||||||
|
|
|
@ -24,6 +24,9 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
[JsonProperty(PropertyName = "save_path")]
|
[JsonProperty(PropertyName = "save_path")]
|
||||||
public string SavePath { get; set; } // Torrent save path
|
public string SavePath { get; set; } // Torrent save path
|
||||||
|
|
||||||
|
[JsonProperty(PropertyName = "content_path")]
|
||||||
|
public string ContentPath { get; set; } // Torrent save path
|
||||||
|
|
||||||
public float Ratio { get; set; } // Torrent share ratio
|
public float Ratio { get; set; } // Torrent share ratio
|
||||||
|
|
||||||
[JsonProperty(PropertyName = "ratio_limit")] // Per torrent seeding ratio limit (-2 = use global, -1 = unlimited)
|
[JsonProperty(PropertyName = "ratio_limit")] // Per torrent seeding ratio limit (-2 = use global, -1 = unlimited)
|
||||||
|
@ -40,7 +43,15 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
{
|
{
|
||||||
public string Hash { get; set; } // Torrent hash
|
public string Hash { get; set; } // Torrent hash
|
||||||
|
|
||||||
|
[JsonProperty(PropertyName = "save_path")]
|
||||||
|
public string SavePath { get; set; }
|
||||||
|
|
||||||
[JsonProperty(PropertyName = "seeding_time")]
|
[JsonProperty(PropertyName = "seeding_time")]
|
||||||
public long SeedingTime { get; set; } // Torrent seeding time
|
public long SeedingTime { get; set; } // Torrent seeding time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class QBittorrentTorrentFile
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace NzbDrone.Core.Download
|
||||||
{
|
{
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IHistoryService _historyService;
|
private readonly IHistoryService _historyService;
|
||||||
|
private readonly IProvideImportItemService _importItemService;
|
||||||
private readonly IDownloadedEpisodesImportService _downloadedEpisodesImportService;
|
private readonly IDownloadedEpisodesImportService _downloadedEpisodesImportService;
|
||||||
private readonly IParsingService _parsingService;
|
private readonly IParsingService _parsingService;
|
||||||
private readonly ISeriesService _seriesService;
|
private readonly ISeriesService _seriesService;
|
||||||
|
@ -36,6 +37,7 @@ namespace NzbDrone.Core.Download
|
||||||
|
|
||||||
public CompletedDownloadService(IEventAggregator eventAggregator,
|
public CompletedDownloadService(IEventAggregator eventAggregator,
|
||||||
IHistoryService historyService,
|
IHistoryService historyService,
|
||||||
|
IProvideImportItemService importItemService,
|
||||||
IDownloadedEpisodesImportService downloadedEpisodesImportService,
|
IDownloadedEpisodesImportService downloadedEpisodesImportService,
|
||||||
IParsingService parsingService,
|
IParsingService parsingService,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
|
@ -44,6 +46,7 @@ namespace NzbDrone.Core.Download
|
||||||
{
|
{
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_historyService = historyService;
|
_historyService = historyService;
|
||||||
|
_importItemService = importItemService;
|
||||||
_downloadedEpisodesImportService = downloadedEpisodesImportService;
|
_downloadedEpisodesImportService = downloadedEpisodesImportService;
|
||||||
_parsingService = parsingService;
|
_parsingService = parsingService;
|
||||||
_seriesService = seriesService;
|
_seriesService = seriesService;
|
||||||
|
@ -58,6 +61,8 @@ namespace NzbDrone.Core.Download
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackedDownload.ImportItem = _importItemService.ProvideImportItem(trackedDownload.DownloadItem, trackedDownload.ImportItem);
|
||||||
|
|
||||||
// Only process tracked downloads that are still downloading
|
// Only process tracked downloads that are still downloading
|
||||||
if (trackedDownload.State != TrackedDownloadState.Downloading)
|
if (trackedDownload.State != TrackedDownloadState.Downloading)
|
||||||
{
|
{
|
||||||
|
@ -72,7 +77,7 @@ namespace NzbDrone.Core.Download
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var downloadItemOutputPath = trackedDownload.DownloadItem.OutputPath;
|
var downloadItemOutputPath = trackedDownload.ImportItem.OutputPath;
|
||||||
|
|
||||||
if (downloadItemOutputPath.IsEmpty)
|
if (downloadItemOutputPath.IsEmpty)
|
||||||
{
|
{
|
||||||
|
@ -110,7 +115,7 @@ namespace NzbDrone.Core.Download
|
||||||
{
|
{
|
||||||
trackedDownload.State = TrackedDownloadState.Importing;
|
trackedDownload.State = TrackedDownloadState.Importing;
|
||||||
|
|
||||||
var outputPath = trackedDownload.DownloadItem.OutputPath.FullPath;
|
var outputPath = trackedDownload.ImportItem.OutputPath.FullPath;
|
||||||
var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto,
|
var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto,
|
||||||
trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem);
|
trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem);
|
||||||
|
|
||||||
|
@ -185,7 +190,7 @@ namespace NzbDrone.Core.Download
|
||||||
.Property("SeriesId", trackedDownload.RemoteEpisode.Series.Id)
|
.Property("SeriesId", trackedDownload.RemoteEpisode.Series.Id)
|
||||||
.Property("DownloadId", trackedDownload.DownloadItem.DownloadId)
|
.Property("DownloadId", trackedDownload.DownloadItem.DownloadId)
|
||||||
.Property("Title", trackedDownload.DownloadItem.Title)
|
.Property("Title", trackedDownload.DownloadItem.Title)
|
||||||
.Property("Path", trackedDownload.DownloadItem.OutputPath.ToString())
|
.Property("Path", trackedDownload.ImportItem.OutputPath.ToString())
|
||||||
.WriteSentryWarn("DownloadHistoryIncomplete")
|
.WriteSentryWarn("DownloadHistoryIncomplete")
|
||||||
.Write();
|
.Write();
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,12 @@ namespace NzbDrone.Core.Download
|
||||||
|
|
||||||
public abstract string Download(RemoteEpisode remoteEpisode);
|
public abstract string Download(RemoteEpisode remoteEpisode);
|
||||||
public abstract IEnumerable<DownloadClientItem> GetItems();
|
public abstract IEnumerable<DownloadClientItem> GetItems();
|
||||||
|
|
||||||
|
public virtual DownloadClientItem GetImportItem(DownloadClientItem item, DownloadClientItem previousImportAttempt)
|
||||||
|
{
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void RemoveItem(string downloadId, bool deleteData);
|
public abstract void RemoveItem(string downloadId, bool deleteData);
|
||||||
public abstract DownloadClientInfo GetStatus();
|
public abstract DownloadClientInfo GetStatus();
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,11 @@ namespace NzbDrone.Core.Download
|
||||||
public bool CanMoveFiles { get; set; }
|
public bool CanMoveFiles { get; set; }
|
||||||
public bool CanBeRemoved { get; set; }
|
public bool CanBeRemoved { get; set; }
|
||||||
public bool Removed { get; set; }
|
public bool Removed { get; set; }
|
||||||
|
|
||||||
|
public DownloadClientItem Clone()
|
||||||
|
{
|
||||||
|
return MemberwiseClone() as DownloadClientItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DownloadClientItemClientInfo
|
public class DownloadClientItemClientInfo
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
@ -10,6 +11,7 @@ namespace NzbDrone.Core.Download
|
||||||
DownloadProtocol Protocol { get; }
|
DownloadProtocol Protocol { get; }
|
||||||
string Download(RemoteEpisode remoteEpisode);
|
string Download(RemoteEpisode remoteEpisode);
|
||||||
IEnumerable<DownloadClientItem> GetItems();
|
IEnumerable<DownloadClientItem> GetItems();
|
||||||
|
DownloadClientItem GetImportItem(DownloadClientItem item, DownloadClientItem previousImportAttempt);
|
||||||
void RemoveItem(string downloadId, bool deleteData);
|
void RemoveItem(string downloadId, bool deleteData);
|
||||||
DownloadClientInfo GetStatus();
|
DownloadClientInfo GetStatus();
|
||||||
void MarkItemAsImported(DownloadClientItem downloadClientItem);
|
void MarkItemAsImported(DownloadClientItem downloadClientItem);
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
namespace NzbDrone.Core.Download
|
||||||
|
{
|
||||||
|
public interface IProvideImportItemService
|
||||||
|
{
|
||||||
|
DownloadClientItem ProvideImportItem(DownloadClientItem item, DownloadClientItem previousImportAttempt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ProvideImportItemService : IProvideImportItemService
|
||||||
|
{
|
||||||
|
private readonly IProvideDownloadClient _downloadClientProvider;
|
||||||
|
|
||||||
|
public ProvideImportItemService(IProvideDownloadClient downloadClientProvider)
|
||||||
|
{
|
||||||
|
_downloadClientProvider = downloadClientProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DownloadClientItem ProvideImportItem(DownloadClientItem item, DownloadClientItem previousImportAttempt)
|
||||||
|
{
|
||||||
|
var client = _downloadClientProvider.Get(item.DownloadClientInfo.Id);
|
||||||
|
|
||||||
|
return client.GetImportItem(item, previousImportAttempt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
||||||
{
|
{
|
||||||
public int DownloadClient { get; set; }
|
public int DownloadClient { get; set; }
|
||||||
public DownloadClientItem DownloadItem { get; set; }
|
public DownloadClientItem DownloadItem { get; set; }
|
||||||
|
public DownloadClientItem ImportItem { get; set; }
|
||||||
public TrackedDownloadState State { get; set; }
|
public TrackedDownloadState State { get; set; }
|
||||||
public TrackedDownloadStatus Status { get; private set; }
|
public TrackedDownloadStatus Status { get; private set; }
|
||||||
public RemoteEpisode RemoteEpisode { get; set; }
|
public RemoteEpisode RemoteEpisode { get; set; }
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||||
return new List<ManualImportItem>();
|
return new List<ManualImportItem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
path = trackedDownload.DownloadItem.OutputPath.FullPath;
|
path = trackedDownload.ImportItem.OutputPath.FullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_diskProvider.FolderExists(path))
|
if (!_diskProvider.FolderExists(path))
|
||||||
|
@ -383,14 +383,15 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||||
{
|
{
|
||||||
var trackedDownload = groupedTrackedDownload.First().TrackedDownload;
|
var trackedDownload = groupedTrackedDownload.First().TrackedDownload;
|
||||||
var importedSeries = imported.First().ImportDecision.LocalEpisode.Series;
|
var importedSeries = imported.First().ImportDecision.LocalEpisode.Series;
|
||||||
|
var outputPath = trackedDownload.ImportItem.OutputPath.FullPath;
|
||||||
|
|
||||||
if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath.FullPath))
|
if (_diskProvider.FolderExists(outputPath))
|
||||||
{
|
{
|
||||||
if (_downloadedEpisodesImportService.ShouldDeleteFolder(
|
if (_downloadedEpisodesImportService.ShouldDeleteFolder(
|
||||||
new DirectoryInfo(trackedDownload.DownloadItem.OutputPath.FullPath), importedSeries) &&
|
new DirectoryInfo(outputPath), importedSeries) &&
|
||||||
trackedDownload.DownloadItem.CanMoveFiles)
|
trackedDownload.DownloadItem.CanMoveFiles)
|
||||||
{
|
{
|
||||||
_diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath.FullPath, true);
|
_diskProvider.DeleteFolder(outputPath, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue