mirror of
https://github.com/Radarr/Radarr.git
synced 2026-03-25 17:35:35 -04:00
Compare commits
60 Commits
v2.0.0.464
...
v2.0.0.468
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5613ab05e0 | ||
|
|
372442af2c | ||
|
|
28c45f941b | ||
|
|
ea1616586f | ||
|
|
e48600da42 | ||
|
|
5d9d2e684e | ||
|
|
2e392e0f5e | ||
|
|
83370ddbbb | ||
|
|
c20b152c28 | ||
|
|
bf5067466d | ||
|
|
ec7f749541 | ||
|
|
56ecbf4a31 | ||
|
|
1b39911135 | ||
|
|
6aaefae2d5 | ||
|
|
db9d601115 | ||
|
|
e7331539f0 | ||
|
|
58bd57bed6 | ||
|
|
7a58082cd7 | ||
|
|
2e08f195e4 | ||
|
|
a1a5e29c3e | ||
|
|
5033886b90 | ||
|
|
29419d6575 | ||
|
|
3c22f68f5a | ||
|
|
a0d98951aa | ||
|
|
70f7404499 | ||
|
|
abd70f5381 | ||
|
|
878e973081 | ||
|
|
2bf3b9e7dd | ||
|
|
2326db0dea | ||
|
|
3590fedeaf | ||
|
|
f4866cae69 | ||
|
|
149d191f62 | ||
|
|
bb9bd63382 | ||
|
|
34fda24124 | ||
|
|
c8d10829a0 | ||
|
|
ae2bdb757a | ||
|
|
714ad075fc | ||
|
|
87a05df2fd | ||
|
|
f3263efa52 | ||
|
|
1cad11d207 | ||
|
|
781df8b20a | ||
|
|
ebcce05588 | ||
|
|
bbf2134fe1 | ||
|
|
081c5fc332 | ||
|
|
47915d5e05 | ||
|
|
47e221d9a0 | ||
|
|
bf485f6f2c | ||
|
|
b365d8a537 | ||
|
|
fee8da88a6 | ||
|
|
cc0dbf1af4 | ||
|
|
836131ebb1 | ||
|
|
9a870a3709 | ||
|
|
afe05189da | ||
|
|
2abaef16f1 | ||
|
|
37d5a3f2ad | ||
|
|
be4d70e3a9 | ||
|
|
79043f2c64 | ||
|
|
1dab0aee6a | ||
|
|
9b162f2d5e | ||
|
|
5518cf5362 |
BIN
Logo/96-Outline-White.png
Normal file
BIN
Logo/96-Outline-White.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -22,7 +22,7 @@ Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS fee
|
||||
|
||||
* Visual Studio 2015 (https://www.visualstudio.com/vs/)
|
||||
* [Git](https://git-scm.com/downloads)
|
||||
* [NodeJS](https://nodejs.org/download/)
|
||||
* [NodeJS](https://nodejs.org/en/download/)
|
||||
|
||||
### Setup
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -52,8 +52,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.1\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NLog" version="4.4.1" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -42,17 +42,17 @@
|
||||
<HintPath>..\packages\NBuilder.4.0.0\lib\net40\FizzWare.NBuilder.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.5.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="Moq, Version=4.2.1510.2205, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.6.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.6.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="4.18.0" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="4.19.0" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NBuilder" version="4.0.0" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.6.0" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -20,6 +20,7 @@ namespace NzbDrone.Api.Config
|
||||
|
||||
public bool SkipFreeSpaceCheckWhenImporting { get; set; }
|
||||
public bool CopyUsingHardlinks { get; set; }
|
||||
public bool ImportExtraFiles { get; set; }
|
||||
public string ExtraFileExtensions { get; set; }
|
||||
public bool EnableMediaInfo { get; set; }
|
||||
}
|
||||
@@ -44,6 +45,7 @@ namespace NzbDrone.Api.Config
|
||||
|
||||
SkipFreeSpaceCheckWhenImporting = model.SkipFreeSpaceCheckWhenImporting,
|
||||
CopyUsingHardlinks = model.CopyUsingHardlinks,
|
||||
ImportExtraFiles = model.ImportExtraFiles,
|
||||
ExtraFileExtensions = model.ExtraFileExtensions,
|
||||
EnableMediaInfo = model.EnableMediaInfo
|
||||
};
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
@@ -16,6 +18,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||
IHandle<EpisodeFileAddedEvent>
|
||||
{
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IRecycleBinProvider _recycleBinProvider;
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
@@ -23,6 +26,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||
|
||||
public EpisodeFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMediaFileService mediaFileService,
|
||||
IDiskProvider diskProvider,
|
||||
IRecycleBinProvider recycleBinProvider,
|
||||
ISeriesService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
@@ -30,6 +34,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_mediaFileService = mediaFileService;
|
||||
_diskProvider = diskProvider;
|
||||
_recycleBinProvider = recycleBinProvider;
|
||||
_seriesService = seriesService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
@@ -74,9 +79,10 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||
var episodeFile = _mediaFileService.Get(id);
|
||||
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
||||
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
|
||||
var subfolder = _diskProvider.GetParentFolder(series.Path).GetRelativePath(_diskProvider.GetParentFolder(fullPath));
|
||||
|
||||
_logger.Info("Deleting episode file: {0}", fullPath);
|
||||
_recycleBinProvider.DeleteFile(fullPath);
|
||||
_recycleBinProvider.DeleteFile(fullPath, subfolder);
|
||||
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using Nancy;
|
||||
@@ -38,7 +38,7 @@ namespace NzbDrone.Api.Frontend.Mappers
|
||||
if (_diskProvider.FileExists(filePath, _caseSensitive))
|
||||
{
|
||||
var response = new StreamResponse(() => GetContentStream(filePath), MimeTypes.GetMimeType(filePath));
|
||||
return response;
|
||||
return new MaterialisingResponse(response);
|
||||
}
|
||||
|
||||
_logger.Warn("File {0} not found", filePath);
|
||||
|
||||
@@ -41,20 +41,17 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="antlr.runtime, Version=2.7.6.2, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Ical.Net.2.2.25\lib\net40\antlr.runtime.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Ical.Net.2.2.32\lib\net40\antlr.runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentValidation, Version=6.2.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentValidation.6.2.1.0\lib\portable-net40+sl50+wp80+win8+wpa81\FluentValidation.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Ical.Net, Version=2.1.0.30332, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Ical.Net.2.2.25\lib\net40\Ical.Net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="Ical.Net, Version=2.1.0.18776, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Ical.Net.2.2.32\lib\net40\Ical.Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ical.Net.Collections, Version=2.1.0.30331, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Ical.Net.2.2.25\lib\net40\Ical.Net.Collections.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="Ical.Net.Collections, Version=2.1.0.18775, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Ical.Net.2.2.32\lib\net40\Ical.Net.Collections.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Nancy, Version=1.4.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Nancy.1.4.3\lib\net40\Nancy.dll</HintPath>
|
||||
@@ -73,12 +70,10 @@
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.1\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NodaTime, Version=1.3.0.0, Culture=neutral, PublicKeyToken=4226afe0d9b296d1, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Ical.Net.2.2.25\lib\net40\NodaTime.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Ical.Net.2.2.32\lib\net40\NodaTime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace NzbDrone.Api.Series
|
||||
|
||||
public static List<Season> ToModel(this IEnumerable<SeasonResource> resources)
|
||||
{
|
||||
return resources.Select(ToModel).ToList();
|
||||
return resources?.Select(ToModel).ToList() ?? new List<Season>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,12 +29,14 @@ namespace NzbDrone.Api.Series
|
||||
|
||||
{
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly IAddSeriesService _addSeriesService;
|
||||
private readonly ISeriesStatisticsService _seriesStatisticsService;
|
||||
private readonly ISceneMappingService _sceneMappingService;
|
||||
private readonly IMapCoversToLocal _coverMapper;
|
||||
|
||||
public SeriesModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
ISeriesService seriesService,
|
||||
IAddSeriesService addSeriesService,
|
||||
ISeriesStatisticsService seriesStatisticsService,
|
||||
ISceneMappingService sceneMappingService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
@@ -48,6 +50,7 @@ namespace NzbDrone.Api.Series
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_seriesService = seriesService;
|
||||
_addSeriesService = addSeriesService;
|
||||
_seriesStatisticsService = seriesStatisticsService;
|
||||
_sceneMappingService = sceneMappingService;
|
||||
|
||||
@@ -74,7 +77,6 @@ namespace NzbDrone.Api.Series
|
||||
|
||||
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.Title).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.TvdbId).GreaterThan(0).SetValidator(seriesExistsValidator);
|
||||
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
@@ -114,7 +116,7 @@ namespace NzbDrone.Api.Series
|
||||
{
|
||||
var model = seriesResource.ToModel();
|
||||
|
||||
return _seriesService.AddSeries(model).Id;
|
||||
return _addSeriesService.AddSeries(model).Id;
|
||||
}
|
||||
|
||||
private void UpdateSeries(SeriesResource seriesResource)
|
||||
|
||||
@@ -207,19 +207,9 @@ namespace NzbDrone.Api.Series
|
||||
|
||||
public static Core.Tv.Series ToModel(this SeriesResource resource, Core.Tv.Series series)
|
||||
{
|
||||
series.TvdbId = resource.TvdbId;
|
||||
var updatedSeries = resource.ToModel();
|
||||
|
||||
series.Seasons = resource.Seasons.ToModel();
|
||||
series.Path = resource.Path;
|
||||
series.ProfileId = resource.ProfileId;
|
||||
|
||||
series.SeasonFolder = resource.SeasonFolder;
|
||||
series.Monitored = resource.Monitored;
|
||||
|
||||
series.SeriesType = resource.SeriesType;
|
||||
series.RootFolderPath = resource.RootFolderPath;
|
||||
series.Tags = resource.Tags;
|
||||
series.AddOptions = resource.AddOptions;
|
||||
series.ApplyChanges(updatedSeries);
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentValidation" version="6.2.1.0" targetFramework="net40" />
|
||||
<package id="Ical.Net" version="2.2.25" targetFramework="net40" />
|
||||
<package id="Ical.Net" version="2.2.32" targetFramework="net40" />
|
||||
<package id="Nancy" version="1.4.3" targetFramework="net40" />
|
||||
<package id="Nancy.Authentication.Basic" version="1.4.1" targetFramework="net40" />
|
||||
<package id="Nancy.Authentication.Forms" version="1.4.1" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.1" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -41,21 +41,17 @@
|
||||
<HintPath>..\packages\NBuilder.4.0.0\lib\net40\FizzWare.NBuilder.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.1\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.5.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="nunit.framework, Version=3.6.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.6.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="4.18.0" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="4.19.0" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NBuilder" version="4.0.0" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.1" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.6.0" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -38,21 +38,17 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FluentAssertions, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.1\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.5.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="nunit.framework, Version=3.6.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.6.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -62,13 +58,11 @@
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="WebDriver, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.WebDriver.3.0.1\lib\net40\WebDriver.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="WebDriver, Version=3.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.WebDriver.3.2.0\lib\net40\WebDriver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WebDriver.Support, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.Support.3.0.1\lib\net40\WebDriver.Support.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="WebDriver.Support, Version=3.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.Support.3.2.0\lib\net40\WebDriver.Support.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="4.18.0" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.1" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net40" />
|
||||
<package id="Selenium.Support" version="3.0.1" targetFramework="net40" />
|
||||
<package id="Selenium.WebDriver" version="3.0.1" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="4.19.0" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.6.0" targetFramework="net40" />
|
||||
<package id="Selenium.Support" version="3.2.0" targetFramework="net40" />
|
||||
<package id="Selenium.WebDriver" version="3.2.0" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -5,6 +5,7 @@ using System;
|
||||
using System.Text;
|
||||
using NzbDrone.Common.Http;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Common.Test.Http
|
||||
{
|
||||
@@ -36,5 +37,17 @@ namespace NzbDrone.Common.Test.Http
|
||||
Action action = () => httpheader.GetEncodingFromContentType();
|
||||
action.ShouldThrow<ArgumentException>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_cookie_with_trailing_semi_colon()
|
||||
{
|
||||
var cookies = HttpHeader.ParseCookies("uid=123456; pass=123456b2f3abcde42ac3a123f3f1fc9f;");
|
||||
|
||||
cookies.Count.Should().Be(2);
|
||||
cookies.First().Key.Should().Be("uid");
|
||||
cookies.First().Value.Should().Be("123456");
|
||||
cookies.Last().Key.Should().Be("pass");
|
||||
cookies.Last().Value.Should().Be("123456b2f3abcde42ac3a123f3f1fc9f");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,21 +37,17 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FluentAssertions, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.1\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.5.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="nunit.framework, Version=3.6.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.6.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="4.18.0" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="4.19.0" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NLog" version="4.4.1" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.6.0" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace NzbDrone.Common.Extensions
|
||||
{
|
||||
public static class Base64Extentions
|
||||
public static class Base64Extensions
|
||||
{
|
||||
public static string ToBase64(this byte[] bytes)
|
||||
{
|
||||
@@ -14,4 +14,4 @@ namespace NzbDrone.Common.Extensions
|
||||
return BitConverter.GetBytes(input).ToBase64();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,11 @@ using System.Xml.Linq;
|
||||
|
||||
namespace NzbDrone.Common.Extensions
|
||||
{
|
||||
public static class XmlExtentions
|
||||
public static class XmlExtensions
|
||||
{
|
||||
public static IEnumerable<XElement> FindDecendants(this XContainer container, string localName)
|
||||
{
|
||||
return container.Descendants().Where(c => c.Name.LocalName.Equals(localName, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
@@ -169,7 +169,7 @@ namespace NzbDrone.Common.Http
|
||||
|
||||
public static List<KeyValuePair<string, string>> ParseCookies(string cookies)
|
||||
{
|
||||
return cookies.Split(';')
|
||||
return cookies.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(v => v.Trim().Split('='))
|
||||
.Select(v => new KeyValuePair<string, string>(v[0], v[1]))
|
||||
.ToList();
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace NzbDrone.Common.Http
|
||||
public class JsonRpcRequestBuilder : HttpRequestBuilder
|
||||
{
|
||||
public static HttpAccept JsonRpcHttpAccept = new HttpAccept("application/json-rpc, application/json");
|
||||
public static string JsonRpcContentType = "application/json-rpc";
|
||||
public static string JsonRpcContentType = "application/json";
|
||||
|
||||
public string JsonMethod { get; private set; }
|
||||
public List<object> JsonParameters { get; private set; }
|
||||
|
||||
@@ -44,16 +44,14 @@
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.1\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Org.Mentalis, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DotNet4.SocksProxy.1.3.2.0\lib\net40\Org.Mentalis.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SharpRaven, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpRaven.2.1.0\lib\net40\SharpRaven.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="SharpRaven, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpRaven.2.2.0\lib\net40\SharpRaven.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SocksWebProxy, Version=1.3.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DotNet4.SocksProxy.1.3.2.0\lib\net40\SocksWebProxy.dll</HintPath>
|
||||
@@ -135,14 +133,14 @@
|
||||
<Compile Include="Expansive\Tree.cs" />
|
||||
<Compile Include="Expansive\TreeNode.cs" />
|
||||
<Compile Include="Expansive\TreeNodeList.cs" />
|
||||
<Compile Include="Extensions\Base64Extentions.cs" />
|
||||
<Compile Include="Extensions\Base64Extensions.cs" />
|
||||
<Compile Include="Extensions\DateTimeExtensions.cs" />
|
||||
<Compile Include="Crypto\HashConverter.cs" />
|
||||
<Compile Include="Extensions\Int64Extensions.cs" />
|
||||
<Compile Include="Extensions\ObjectExtensions.cs" />
|
||||
<Compile Include="Extensions\StreamExtensions.cs" />
|
||||
<Compile Include="Extensions\UrlExtensions.cs" />
|
||||
<Compile Include="Extensions\XmlExtentions.cs" />
|
||||
<Compile Include="Extensions\XmlExtensions.cs" />
|
||||
<Compile Include="HashUtil.cs" />
|
||||
<Compile Include="Http\Dispatchers\CurlHttpDispatcher.cs" />
|
||||
<Compile Include="Http\Dispatchers\FallbackHttpDispatcher.cs" />
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
<package id="DotNet4.SocksProxy" version="1.3.2.0" targetFramework="net40" />
|
||||
<package id="ICSharpCode.SharpZipLib.Patched" version="0.86.5" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.1" targetFramework="net40" />
|
||||
<package id="SharpRaven" version="2.1.0" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
<package id="SharpRaven" version="2.2.0" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -79,8 +79,7 @@
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.1\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
<package id="Microsoft.Owin" version="2.1.0" targetFramework="net40" />
|
||||
<package id="Microsoft.Owin.Hosting" version="2.1.0" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.1" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
<package id="Owin" version="1.0" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -0,0 +1,83 @@
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore.Migration;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore.Migration
|
||||
{
|
||||
[TestFixture]
|
||||
public class fix_extra_file_extensionsFixture : MigrationTest<fix_extra_file_extension>
|
||||
{
|
||||
[Test]
|
||||
public void should_extra_files_that_do_not_have_an_extension()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("ExtraFiles").Row(new
|
||||
{
|
||||
SeriesId = 1,
|
||||
SeasonNumber = 1,
|
||||
EpisodeFileId = 1,
|
||||
RelativePath = "Series.Title.S01E01",
|
||||
Added = "2016-05-30 20:23:02.3725923",
|
||||
LastUpdated = "2016-05-30 20:23:02.3725923",
|
||||
Extension = ""
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query("Select * from ExtraFiles");
|
||||
|
||||
items.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fix_double_extension()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("SubtitleFiles").Row(new
|
||||
{
|
||||
SeriesId = 1,
|
||||
SeasonNumber = 1,
|
||||
EpisodeFileId = 1,
|
||||
RelativePath = "Series.Title.S01E01.en.srt",
|
||||
Added = "2016-05-30 20:23:02.3725923",
|
||||
LastUpdated = "2016-05-30 20:23:02.3725923",
|
||||
Language = Language.English,
|
||||
Extension = "en.srt"
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query("Select * from SubtitleFiles");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First()["Extension"].Should().Be(".srt");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fix_extension_missing_a_leading_period()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("ExtraFiles").Row(new
|
||||
{
|
||||
SeriesId = 1,
|
||||
SeasonNumber = 1,
|
||||
EpisodeFileId = 1,
|
||||
RelativePath = "Series.Title.S01E01.nfo-orig",
|
||||
Added = "2016-05-30 20:23:02.3725923",
|
||||
LastUpdated = "2016-05-30 20:23:02.3725923",
|
||||
Extension = "nfo-orig"
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.Query("Select * from ExtraFiles");
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First()["Extension"].Should().Be(".nfo-orig");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore.Migration;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore.Migration
|
||||
{
|
||||
[TestFixture]
|
||||
public class import_extra_files_configFixture : MigrationTest<import_extra_files>
|
||||
{
|
||||
[Test]
|
||||
public void should_not_insert_if_missing()
|
||||
{
|
||||
var db = WithMigrationTestDb();
|
||||
|
||||
var items = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'importextrafiles'");
|
||||
items.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_insert_if_empty()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "extrafileextensions",
|
||||
Value = ""
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'importextrafiles'");
|
||||
items.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_insert_True_if_configured()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "extrafileextensions",
|
||||
Value = "srt"
|
||||
});
|
||||
});
|
||||
|
||||
var items = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'importextrafiles'");
|
||||
items.Should().Be("True");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore.Migration;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore.Migration
|
||||
{
|
||||
[TestFixture]
|
||||
public class fix_extra_files_configFixture : MigrationTest<fix_extra_files_config>
|
||||
{
|
||||
[Test]
|
||||
public void should_not_update_importextrafiles_disabled()
|
||||
{
|
||||
var db = WithMigrationTestDb();
|
||||
|
||||
var itemEnabled = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'importextrafiles'");
|
||||
itemEnabled.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fix_importextrafiles_if_wrong()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "importextrafiles",
|
||||
Value = 1
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var itemEnabled = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'importextrafiles'");
|
||||
itemEnabled.Should().Be("True");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fill_in_default_extensions()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "importextrafiles",
|
||||
Value = "False"
|
||||
});
|
||||
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "extrafileextensions",
|
||||
Value = ""
|
||||
});
|
||||
});
|
||||
|
||||
var itemEnabled = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'importextrafiles'");
|
||||
itemEnabled.Should().Be("False");
|
||||
|
||||
var itemExtensions = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'extrafileextensions'");
|
||||
itemExtensions.Should().Be("srt");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_fill_in_default_extensions()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "importextrafiles",
|
||||
Value = "True"
|
||||
});
|
||||
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "extrafileextensions",
|
||||
Value = ""
|
||||
});
|
||||
});
|
||||
|
||||
var itemEnabled = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'importextrafiles'");
|
||||
itemEnabled.Should().Be("True");
|
||||
|
||||
var itemExtensions = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'extrafileextensions'");
|
||||
itemExtensions.Should().Be("");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_fill_in_default_extensions_if_not_defined()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "importextrafiles",
|
||||
Value = "False"
|
||||
});
|
||||
});
|
||||
|
||||
var itemEnabled = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'importextrafiles'");
|
||||
itemEnabled.Should().Be("False");
|
||||
|
||||
var itemExtensions = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'extrafileextensions'");
|
||||
itemExtensions.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_fill_in_default_extensions_if_already_defined()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "importextrafiles",
|
||||
Value = "False"
|
||||
});
|
||||
|
||||
c.Insert.IntoTable("Config").Row(new
|
||||
{
|
||||
Key = "extrafileextensions",
|
||||
Value = "sub"
|
||||
});
|
||||
});
|
||||
|
||||
var itemEnabled = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'importextrafiles'");
|
||||
itemEnabled.Should().Be("False");
|
||||
|
||||
var itemExtensions = db.QueryScalar<string>("SELECT Value FROM Config WHERE Key = 'extrafileextensions'");
|
||||
itemExtensions.Should().Be("sub");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,5 +379,34 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||
qualifiedReports.First().RemoteEpisode.Release.Should().Be(remoteEpisode1.Release);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_prefer_quality_over_the_number_of_peers()
|
||||
{
|
||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.Bluray1080p));
|
||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.SDTV));
|
||||
|
||||
var torrentInfo1 = new TorrentInfo();
|
||||
torrentInfo1.PublishDate = DateTime.Now;
|
||||
torrentInfo1.DownloadProtocol = DownloadProtocol.Torrent;
|
||||
torrentInfo1.Seeders = 100;
|
||||
torrentInfo1.Peers = 10;
|
||||
torrentInfo1.Size = 200.Megabytes();
|
||||
|
||||
var torrentInfo2 = torrentInfo1.JsonClone();
|
||||
torrentInfo2.Seeders = 1100;
|
||||
torrentInfo2.Peers = 10;
|
||||
torrentInfo1.Size = 250.Megabytes();
|
||||
|
||||
remoteEpisode1.Release = torrentInfo1;
|
||||
remoteEpisode2.Release = torrentInfo2;
|
||||
|
||||
var decisions = new List<DownloadDecision>();
|
||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||
decisions.Add(new DownloadDecision(remoteEpisode2));
|
||||
|
||||
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||
((TorrentInfo)qualifiedReports.First().RemoteEpisode.Release).Should().Be(torrentInfo1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
|
||||
result.CanBeRemoved.Should().BeFalse();
|
||||
result.CanMoveFiles.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -77,6 +77,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
|
||||
result.CanBeRemoved.Should().BeTrue();
|
||||
result.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
protected DelugeTorrent _downloading;
|
||||
protected DelugeTorrent _failed;
|
||||
protected DelugeTorrent _completed;
|
||||
protected DelugeTorrent _seeding;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
@@ -75,7 +76,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
Size = 1000,
|
||||
BytesDownloaded = 1000,
|
||||
Progress = 100.0,
|
||||
DownloadPath = "somepath"
|
||||
DownloadPath = "somepath",
|
||||
IsAutoManaged = true,
|
||||
StopAtRatio = true,
|
||||
StopRatio = 1.0,
|
||||
Ratio = 1.5
|
||||
};
|
||||
|
||||
Mocker.GetMock<ITorrentFileInfoReader>()
|
||||
@@ -114,7 +119,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
.Returns("CBC2F069FE8BB2F544EAE707D75BCD3DE9DCF951".ToLower())
|
||||
.Callback(PrepareClientToReturnQueuedItem);
|
||||
}
|
||||
|
||||
|
||||
protected virtual void GivenTorrents(List<DelugeTorrent> torrents)
|
||||
{
|
||||
if (torrents == null)
|
||||
@@ -129,7 +134,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
|
||||
protected void PrepareClientToReturnQueuedItem()
|
||||
{
|
||||
GivenTorrents(new List<DelugeTorrent>
|
||||
GivenTorrents(new List<DelugeTorrent>
|
||||
{
|
||||
_queued
|
||||
});
|
||||
@@ -137,7 +142,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
|
||||
protected void PrepareClientToReturnDownloadingItem()
|
||||
{
|
||||
GivenTorrents(new List<DelugeTorrent>
|
||||
GivenTorrents(new List<DelugeTorrent>
|
||||
{
|
||||
_downloading
|
||||
});
|
||||
@@ -145,7 +150,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
|
||||
protected void PrepareClientToReturnFailedItem()
|
||||
{
|
||||
GivenTorrents(new List<DelugeTorrent>
|
||||
GivenTorrents(new List<DelugeTorrent>
|
||||
{
|
||||
_failed
|
||||
});
|
||||
@@ -189,6 +194,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
PrepareClientToReturnCompletedItem();
|
||||
var item = Subject.GetItems().Single();
|
||||
VerifyCompleted(item);
|
||||
|
||||
item.CanBeRemoved.Should().BeTrue();
|
||||
item.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -248,11 +256,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
item.Status.Should().Be(expectedItemStatus);
|
||||
}
|
||||
|
||||
[TestCase(DelugeTorrentStatus.Paused, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(DelugeTorrentStatus.Checking, DownloadItemStatus.Downloading, true)]
|
||||
[TestCase(DelugeTorrentStatus.Queued, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(DelugeTorrentStatus.Seeding, DownloadItemStatus.Completed, true)]
|
||||
public void GetItems_should_return_completed_item_as_downloadItemStatus(string apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly)
|
||||
[TestCase(DelugeTorrentStatus.Paused, DownloadItemStatus.Completed)]
|
||||
[TestCase(DelugeTorrentStatus.Checking, DownloadItemStatus.Downloading)]
|
||||
[TestCase(DelugeTorrentStatus.Queued, DownloadItemStatus.Completed)]
|
||||
[TestCase(DelugeTorrentStatus.Seeding, DownloadItemStatus.Completed)]
|
||||
public void GetItems_should_return_completed_item_as_downloadItemStatus(string apiStatus, DownloadItemStatus expectedItemStatus)
|
||||
{
|
||||
_completed.State = apiStatus;
|
||||
|
||||
@@ -261,24 +269,25 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
var item = Subject.GetItems().Single();
|
||||
|
||||
item.Status.Should().Be(expectedItemStatus);
|
||||
item.IsReadOnly.Should().Be(expectedReadOnly);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_check_share_ratio_for_readonly()
|
||||
[TestCase(0.5, false)]
|
||||
[TestCase(1.01, true)]
|
||||
public void GetItems_should_check_share_ratio_for_moveFiles_and_remove(double ratio, bool canBeRemoved)
|
||||
{
|
||||
_completed.State = DelugeTorrentStatus.Paused;
|
||||
_completed.IsAutoManaged = true;
|
||||
_completed.StopAtRatio = true;
|
||||
_completed.StopRatio = 1.0;
|
||||
_completed.Ratio = 1.01;
|
||||
_completed.Ratio = ratio;
|
||||
|
||||
PrepareClientToReturnCompletedItem();
|
||||
|
||||
var item = Subject.GetItems().Single();
|
||||
|
||||
item.Status.Should().Be(DownloadItemStatus.Completed);
|
||||
item.IsReadOnly.Should().BeFalse();
|
||||
item.CanMoveFiles.Should().Be(canBeRemoved);
|
||||
item.CanBeRemoved.Should().Be(canBeRemoved);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -275,7 +275,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
{ "default_destination", _defaultDestination },
|
||||
};
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationInfoProxy>()
|
||||
.Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>()))
|
||||
.Returns(_downloadStationConfigItems);
|
||||
}
|
||||
@@ -311,7 +311,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
torrents = new List<DownloadStationTask>();
|
||||
}
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>()))
|
||||
.Returns(torrents);
|
||||
}
|
||||
@@ -330,11 +330,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
.Setup(s => s.Get(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000]));
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Setup(s => s.AddTaskFromUrl(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
||||
.Callback(PrepareClientToReturnQueuedItem);
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
||||
.Callback(PrepareClientToReturnQueuedItem);
|
||||
}
|
||||
@@ -352,7 +352,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
{
|
||||
var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding };
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Setup(d => d.GetTasks(_settings))
|
||||
.Returns(tasks);
|
||||
|
||||
@@ -372,7 +372,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
@@ -405,7 +405,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
|
||||
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode));
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never());
|
||||
}
|
||||
|
||||
@@ -576,11 +576,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
items.Should().OnlyContain(v => !v.OutputPath.IsEmpty);
|
||||
}
|
||||
|
||||
[TestCase(DownloadStationTaskStatus.Downloading, DownloadItemStatus.Downloading, true)]
|
||||
[TestCase(DownloadStationTaskStatus.Finished, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(DownloadStationTaskStatus.Seeding, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(DownloadStationTaskStatus.Waiting, DownloadItemStatus.Queued, true)]
|
||||
public void GetItems_should_return_readonly_expected(DownloadStationTaskStatus apiStatus, DownloadItemStatus expectedItemStatus, bool readOnlyExpected)
|
||||
[TestCase(DownloadStationTaskStatus.Downloading, false, false)]
|
||||
[TestCase(DownloadStationTaskStatus.Finished, true, true)]
|
||||
[TestCase(DownloadStationTaskStatus.Seeding, true, false)]
|
||||
[TestCase(DownloadStationTaskStatus.Waiting, false, false)]
|
||||
public void GetItems_should_return_canBeMoved_and_canBeDeleted_as_expected(DownloadStationTaskStatus apiStatus, bool canMoveFilesExpected, bool canBeRemovedExpected)
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
@@ -592,7 +592,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
var items = Subject.GetItems();
|
||||
|
||||
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)]
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
{ "default_destination", _defaultDestination },
|
||||
};
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationInfoProxy>()
|
||||
.Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>()))
|
||||
.Returns(_downloadStationConfigItems);
|
||||
}
|
||||
@@ -213,7 +213,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
nzbs = new List<DownloadStationTask>();
|
||||
}
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>()))
|
||||
.Returns(nzbs);
|
||||
}
|
||||
@@ -233,7 +233,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000]));
|
||||
*/
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
||||
.Callback(PrepareClientToReturnQueuedItem);
|
||||
}
|
||||
@@ -242,7 +242,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
{
|
||||
var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding };
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Setup(d => d.GetTasks(_settings))
|
||||
.Returns(tasks);
|
||||
}
|
||||
@@ -260,7 +260,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
|
||||
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode));
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never());
|
||||
}
|
||||
|
||||
@@ -408,24 +408,6 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
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.Error, DownloadItemStatus.Failed)]
|
||||
[TestCase(DownloadStationTaskStatus.Extracting, DownloadItemStatus.Downloading)]
|
||||
|
||||
@@ -190,6 +190,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.HadoukenTests
|
||||
PrepareClientToReturnCompletedItem();
|
||||
var item = Subject.GetItems().Single();
|
||||
VerifyCompleted(item);
|
||||
|
||||
item.CanBeRemoved.Should().BeTrue();
|
||||
item.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -298,7 +301,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.HadoukenTests
|
||||
.Returns("hash");
|
||||
|
||||
var result = Subject.Download(remoteEpisode);
|
||||
|
||||
|
||||
Assert.IsFalse(result.Any(c => char.IsLower(c)));
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
|
||||
public void queued_item_should_have_required_properties()
|
||||
{
|
||||
GivenQueue(_queued);
|
||||
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyQueued(result);
|
||||
@@ -139,6 +139,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
|
||||
result.CanBeRemoved.Should().BeTrue();
|
||||
result.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
||||
|
||||
GivenQueue(_queued);
|
||||
GivenHistory(null);
|
||||
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyQueued(result);
|
||||
@@ -204,6 +204,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
|
||||
result.CanBeRemoved.Should().BeTrue();
|
||||
result.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -311,7 +311,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||
}
|
||||
|
||||
[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);
|
||||
|
||||
@@ -330,11 +330,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||
GivenTorrents(new List<QBittorrentTorrent> { torrent });
|
||||
|
||||
var item = Subject.GetItems().Single();
|
||||
item.IsReadOnly.Should().BeTrue();
|
||||
item.CanBeRemoved.Should().BeFalse();
|
||||
item.CanMoveFiles.Should().BeFalse();
|
||||
}
|
||||
|
||||
[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);
|
||||
|
||||
@@ -353,11 +354,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||
GivenTorrents(new List<QBittorrentTorrent> { torrent });
|
||||
|
||||
var item = Subject.GetItems().Single();
|
||||
item.IsReadOnly.Should().BeTrue();
|
||||
item.CanBeRemoved.Should().BeFalse();
|
||||
item.CanMoveFiles.Should().BeFalse();
|
||||
}
|
||||
|
||||
[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);
|
||||
|
||||
@@ -376,11 +378,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||
GivenTorrents(new List<QBittorrentTorrent> { torrent });
|
||||
|
||||
var item = Subject.GetItems().Single();
|
||||
item.IsReadOnly.Should().BeTrue();
|
||||
item.CanBeRemoved.Should().BeFalse();
|
||||
item.CanMoveFiles.Should().BeFalse();
|
||||
}
|
||||
|
||||
[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);
|
||||
|
||||
@@ -399,7 +402,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||
GivenTorrents(new List<QBittorrentTorrent> { torrent });
|
||||
|
||||
var item = Subject.GetItems().Single();
|
||||
item.IsReadOnly.Should().BeFalse();
|
||||
item.CanBeRemoved.Should().BeTrue();
|
||||
item.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -54,11 +54,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.RTorrentTests
|
||||
protected void GivenSuccessfulDownload()
|
||||
{
|
||||
Mocker.GetMock<IRTorrentProxy>()
|
||||
.Setup(s => s.AddTorrentFromUrl(It.IsAny<string>(), It.IsAny<RTorrentSettings>()))
|
||||
.Setup(s => s.AddTorrentFromUrl(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<RTorrentPriority>(), It.IsAny<string>(), It.IsAny<RTorrentSettings>()))
|
||||
.Callback(PrepareClientToReturnCompletedItem);
|
||||
|
||||
Mocker.GetMock<IRTorrentProxy>()
|
||||
.Setup(s => s.AddTorrentFromFile(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<RTorrentSettings>()))
|
||||
.Setup(s => s.AddTorrentFromFile(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<RTorrentPriority>(), It.IsAny<string>(), It.IsAny<RTorrentSettings>()))
|
||||
.Callback(PrepareClientToReturnCompletedItem);
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
||||
private SabnzbdHistory _failed;
|
||||
private SabnzbdHistory _completed;
|
||||
private SabnzbdConfig _config;
|
||||
private SabnzbdFullStatus _fullStatus;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
@@ -65,7 +66,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
||||
{
|
||||
Status = SabnzbdDownloadStatus.Failed,
|
||||
Size = 1000,
|
||||
Category = "tv",
|
||||
Category = "tv",
|
||||
Id = "sabnzbd_nzb12345",
|
||||
Title = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE"
|
||||
}
|
||||
@@ -80,7 +81,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
||||
{
|
||||
Status = SabnzbdDownloadStatus.Completed,
|
||||
Size = 1000,
|
||||
Category = "tv",
|
||||
Category = "tv",
|
||||
Id = "sabnzbd_nzb12345",
|
||||
Title = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
|
||||
Storage = "/remote/mount/vv/Droned.S01E01.Pilot.1080p.WEB-DL-DRONE"
|
||||
@@ -100,9 +101,29 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
||||
}
|
||||
};
|
||||
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(v => v.GetVersion(It.IsAny<SabnzbdSettings>()))
|
||||
.Returns("1.2.3");
|
||||
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(s => s.GetConfig(It.IsAny<SabnzbdSettings>()))
|
||||
.Returns(_config);
|
||||
|
||||
_fullStatus = new SabnzbdFullStatus
|
||||
{
|
||||
CompleteDir = @"Y:\nzbget\root\complete".AsOsAgnostic()
|
||||
};
|
||||
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(s => s.GetFullStatus(It.IsAny<SabnzbdSettings>()))
|
||||
.Returns(_fullStatus);
|
||||
}
|
||||
|
||||
protected void GivenVersion(string version)
|
||||
{
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(s => s.GetVersion(It.IsAny<SabnzbdSettings>()))
|
||||
.Returns(version);
|
||||
}
|
||||
|
||||
protected void GivenFailedDownload()
|
||||
@@ -166,7 +187,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
||||
|
||||
GivenQueue(_queued);
|
||||
GivenHistory(null);
|
||||
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyQueued(result);
|
||||
@@ -218,6 +239,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
|
||||
result.CanBeRemoved.Should().BeTrue();
|
||||
result.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -386,23 +410,46 @@ 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\vv")]
|
||||
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed\vv")]
|
||||
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads/vv")]
|
||||
[TestCase(@"/nzbget/root", @"completed", @"vv", @"/nzbget/root/completed/vv")]
|
||||
public void should_return_status_with_outputdir(string rootFolder, string completeDir, string categoryDir, string expectedDir)
|
||||
[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")]
|
||||
public void should_return_status_with_outputdir_for_version_lt_2(string rootFolder, string completeDir, string categoryDir, string fullCompleteDir, string fullCategoryDir)
|
||||
{
|
||||
_fullStatus.CompleteDir = null;
|
||||
_queued.DefaultRootFolder = rootFolder;
|
||||
_config.Misc.complete_dir = completeDir;
|
||||
_config.Categories.First().Dir = categoryDir;
|
||||
|
||||
|
||||
GivenVersion("1.2.1");
|
||||
GivenQueue(null);
|
||||
|
||||
var result = Subject.GetStatus();
|
||||
|
||||
result.IsLocalhost.Should().BeTrue();
|
||||
result.OutputRootFolders.Should().NotBeNull();
|
||||
result.OutputRootFolders.First().Should().Be(expectedDir);
|
||||
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")]
|
||||
public void should_return_status_with_outputdir_for_version_gte_2(string rootFolder, string completeDir, string categoryDir, string fullCompleteDir, string fullCategoryDir)
|
||||
{
|
||||
_fullStatus.CompleteDir = fullCompleteDir;
|
||||
_queued.DefaultRootFolder = null;
|
||||
_config.Misc.complete_dir = completeDir;
|
||||
_config.Categories.First().Dir = categoryDir;
|
||||
|
||||
GivenVersion("2.0.0beta1");
|
||||
GivenQueue(null);
|
||||
|
||||
var result = Subject.GetStatus();
|
||||
|
||||
result.IsLocalhost.Should().BeTrue();
|
||||
result.OutputRootFolders.Should().NotBeNull();
|
||||
result.OutputRootFolders.First().Should().Be(fullCategoryDir);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -450,5 +497,73 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
||||
result.IsValid.Should().BeTrue();
|
||||
result.HasWarnings.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_test_success_if_tv_sorting_disabled()
|
||||
{
|
||||
_config.Misc.enable_tv_sorting = false;
|
||||
_config.Misc.tv_categories = null;
|
||||
|
||||
var result = new NzbDroneValidationResult(Subject.Test());
|
||||
|
||||
result.IsValid.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_test_failed_if_tv_sorting_null()
|
||||
{
|
||||
_config.Misc.enable_tv_sorting = true;
|
||||
_config.Misc.tv_categories = null;
|
||||
|
||||
var result = new NzbDroneValidationResult(Subject.Test());
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_test_failed_if_tv_sorting_empty()
|
||||
{
|
||||
_config.Misc.enable_tv_sorting = true;
|
||||
_config.Misc.tv_categories = new string[0];
|
||||
|
||||
var result = new NzbDroneValidationResult(Subject.Test());
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_test_success_if_tv_sorting_contains_different_category()
|
||||
{
|
||||
_config.Misc.enable_tv_sorting = true;
|
||||
_config.Misc.tv_categories = new[] { "tv-custom" };
|
||||
|
||||
var result = new NzbDroneValidationResult(Subject.Test());
|
||||
|
||||
result.IsValid.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_test_failed_if_tv_sorting_contains_category()
|
||||
{
|
||||
_config.Misc.enable_tv_sorting = true;
|
||||
_config.Misc.tv_categories = new[] { "tv" };
|
||||
|
||||
var result = new NzbDroneValidationResult(Subject.Test());
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_test_failed_if_tv_sorting_default_category()
|
||||
{
|
||||
Subject.Definition.Settings.As<SabnzbdSettings>().TvCategory = null;
|
||||
|
||||
_config.Misc.enable_tv_sorting = true;
|
||||
_config.Misc.tv_categories = new[] { "Default" };
|
||||
|
||||
var result = new NzbDroneValidationResult(Subject.Test());
|
||||
|
||||
result.IsValid.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
||||
PrepareClientToReturnCompletedItem();
|
||||
var item = Subject.GetItems().Single();
|
||||
VerifyCompleted(item);
|
||||
|
||||
item.CanBeRemoved.Should().BeTrue();
|
||||
item.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -172,13 +175,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
||||
item.Status.Should().Be(expectedItemStatus);
|
||||
}
|
||||
|
||||
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, true)]
|
||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, true)]
|
||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, true)]
|
||||
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly)
|
||||
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, false)]
|
||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, false)]
|
||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, false)]
|
||||
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedValue)
|
||||
{
|
||||
_completed.Status = apiStatus;
|
||||
|
||||
@@ -187,7 +190,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
||||
var item = Subject.GetItems().Single();
|
||||
|
||||
item.Status.Should().Be(expectedItemStatus);
|
||||
item.IsReadOnly.Should().Be(expectedReadOnly);
|
||||
item.CanBeRemoved.Should().Be(expectedValue);
|
||||
item.CanMoveFiles.Should().Be(expectedValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -222,6 +222,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
|
||||
PrepareClientToReturnCompletedItem();
|
||||
var item = Subject.GetItems().Single();
|
||||
VerifyCompleted(item);
|
||||
|
||||
item.CanBeRemoved.Should().BeTrue();
|
||||
item.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -292,12 +295,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
|
||||
item.Status.Should().Be(expectedItemStatus);
|
||||
}
|
||||
|
||||
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checking, DownloadItemStatus.Queued, false)]
|
||||
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Queued, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Started, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Queued | UTorrentTorrentStatus.Paused, DownloadItemStatus.Completed, true)]
|
||||
public void GetItems_should_return_completed_item_as_downloadItemStatus(UTorrentTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly)
|
||||
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checking, DownloadItemStatus.Queued, true)]
|
||||
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Queued, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(UTorrentTorrentStatus.Loaded | UTorrentTorrentStatus.Checked | UTorrentTorrentStatus.Started, DownloadItemStatus.Completed, false)]
|
||||
[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 expectedValue)
|
||||
{
|
||||
_completed.Status = apiStatus;
|
||||
|
||||
@@ -306,7 +309,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
|
||||
var item = Subject.GetItems().Single();
|
||||
|
||||
item.Status.Should().Be(expectedItemStatus);
|
||||
item.IsReadOnly.Should().Be(expectedReadOnly);
|
||||
item.CanBeRemoved.Should().Be(expectedValue);
|
||||
item.CanMoveFiles.Should().Be(expectedValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -43,6 +43,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
||||
PrepareClientToReturnCompletedItem();
|
||||
var item = Subject.GetItems().Single();
|
||||
VerifyCompleted(item);
|
||||
|
||||
item.CanBeRemoved.Should().BeTrue();
|
||||
item.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -174,13 +177,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
||||
item.Status.Should().Be(expectedItemStatus);
|
||||
}
|
||||
|
||||
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, true)]
|
||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, true)]
|
||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, true)]
|
||||
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly)
|
||||
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, false)]
|
||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, false)]
|
||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, false)]
|
||||
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedValue)
|
||||
{
|
||||
_completed.Status = apiStatus;
|
||||
|
||||
@@ -189,7 +192,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
||||
var item = Subject.GetItems().Single();
|
||||
|
||||
item.Status.Should().Be(expectedItemStatus);
|
||||
item.IsReadOnly.Should().Be(expectedReadOnly);
|
||||
item.CanBeRemoved.Should().Be(expectedValue);
|
||||
item.CanMoveFiles.Should().Be(expectedValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -312,4 +316,4 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
281
src/NzbDrone.Core.Test/Files/Indexers/TorrentRss/AlphaRatio.xml
Normal file
281
src/NzbDrone.Core.Test/Files/Indexers/TorrentRss/AlphaRatio.xml
Normal file
@@ -0,0 +1,281 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<channel>
|
||||
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
|
||||
<meta xmlns="http://pipes.yahoo.com" name="pipes" content="noprocess" />
|
||||
<title>TV :: AlphaRatio</title>
|
||||
<link>https://alpharatio.cc/</link>
|
||||
<description>Personal RSS feed: TV</description>
|
||||
<language>en-us</language>
|
||||
<lastBuildDate>Tue, 29 Nov 2016 11:01:28 +0000</lastBuildDate>
|
||||
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
|
||||
<generator>Gazelle Feed Class</generator>
|
||||
|
||||
<item>
|
||||
<title><![CDATA[TvHD 465989 465960 Good.Behavior.S01E03.PROPER.720p.HDTV.x264-KILLERS]]></title>
|
||||
<description>
|
||||
<![CDATA[MB <br />
|
||||
@@@@: : <br />
|
||||
:7 :::.7:@.:u7:.X5LF <br />
|
||||
.LFq2 .B@B@B@B@B@B@B@ <br />
|
||||
.. i@r rB@B@B@B@B@B@B@@@: <br />
|
||||
: :B@B@B@B@: X@@@@@B@B@B@B@B@B@B@J .u@B. <br />
|
||||
:.YkuB@B@B@BM. @B@B@B@B@B@@@B@B@B@r 2B@B@B@B@i <br />
|
||||
@@@B@r@@@B@B: B@B@B@B@B@@@B@B@B@B@ i@B@B@B@BrO@@@@@ <br />
|
||||
@@@@B@B@BB, r:@B@B@@@B@@@B@q@@@BM @L:B.B, @@B@B@B@BO@@@@B@B@B <br />
|
||||
jB@B@B@B@N. 7 B@@@@@B@B@O 8B@. @F B@B@B@@@O@B@B@B@@@@@B. <br />
|
||||
i@B@B@B@: 7 @B@B@B@B@ B: B: i@B@B@B@BNB8B7 .B@@ <br />
|
||||
@B@B@. 1G @B@B@B@ @ , @B@:i @u @: 0EB@ <br />
|
||||
;ir , U@B@B .@ B@B L B@B <br />
|
||||
7 B@B@ q@Bv:@BP @B@ <br />
|
||||
i@Bu @ ,S@ @@ B@@@B@B@. BkU@B@ 5Ui @Y@B <br />
|
||||
@@B@v B :@iB B@@@B@B@M@ @B@@@B@BB @@7i iU 5i2vB@k B@ <br />
|
||||
@B@B@B7 i @ @B@B@B@B@B@B5 i@B@@@B@ r @ <br />
|
||||
@B@B@B@. @ B@B@B@B@B@B@B@. MB @Bu . U @Bi <br />
|
||||
k@P @@@OBi .@ @B@B@B@B@B@B@B. @MBB@@ @F @ 7B@B <br />
|
||||
@B @B@@@B@ 0B@B@B@B@B@B@B@B@ B@B@B@B@F B@B@B. B@B <br />
|
||||
B @B@B@B B: B@B@B@B@@@B@@@BM B@B@B@B@B@: @B@;:B@@@: F@B <br />
|
||||
@. B@@@B@ @Bu i. MX J B@B@B@ @B. @B@B@B@@ B@B@F Si k@@ B@BN <br />
|
||||
@@ @B@B@B@B@B B @B@BOr: .i0F7@B: B@B@ E@ @B@B@r@ B@B@B. @B@B@B5 <br />
|
||||
B@B@B@@@B@B@B: @B@B@B@Z: B@B@B@B@B@B@@@B, L@ @B@ B@B@B@B@B@B@B, <br />
|
||||
:@B@B@B@B@B@B@: Y@B@@@@@B@B@B@: 7B@@@0 :@ L@ ,@B@B@B@B@B@B@B@. <br />
|
||||
JB@B@B@B@B@B@B@ U@B@@J, @U.@@B@B@B B@F i@ PB @B@B@B@B@BG.@B@B@B, <br />
|
||||
r@B@B@B@B@B@B@B ; @B@B@ :. @ @J r@ G@ @@: .Z@@7 B@@@@@B@B@B@F <br />
|
||||
,B@B@B@B@B@B@B@B5 @B@@@ j@B5E@BXB@BvO rB OB B@ B@@@r B@B@B@B@B@B@B@B. <br />
|
||||
@B@B@B@B@B@@@B@i @@ .uO0 :v. @ @B@B @@@ L: ,@ .@ Z@ iB B@B @B@B@@@BNB@ :2@B@B@B@@@B@B <br />
|
||||
:@@B@B@B@B@@@B@B..@@@B@B@@. :YY B@@@: B, B .: u@ .@B@B r@ OB i@B@B@@@B@B <br />
|
||||
UB@B@B@B@B@@@B@B@B@B@B LJ, @B@B. @. @ Y @BP .rUB@B@B@B@Z7, B@B@B@B@B@ <br />
|
||||
,@B@@@B@B@B@B@B@@@ i17. @B@B@v O, B 1B@B@B@B@@@B@@@B@B@B@B@B@B@B@BiB@Bv<br />
|
||||
:B@B@B@B@B@B@B@2@B B@B@B@ k. .@ M@@BOB@B@B@B@B@B@B@B@B@B@B@B@B@P @@B<br />
|
||||
i@B@B@@@B@B@B@B M@B .7 @B@B@r B. 7B @ YB@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@@@<br />
|
||||
u@@B@B@B@@@B@B@ B@B@ 2U8. 5B@@E @, r@ M B@B@B@B@B@B@B@B@B@@@B@B@B@B@@@B@@@@@B<br />
|
||||
q@B@B@B@@@B@B@B. @@@i2 @JX :@B@ BY rB @ G@@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@<br />
|
||||
BB@B@B@B@B@B@Bi . B@@: @B @ @B@B@B@B@B@B@B@B@B@B@B@@@@@B@B@B@j<br />
|
||||
O@B@B@B@B@B@B@@@ u@B@@ Bu B @@B@B@B@BB8 0B@B@B <br />
|
||||
SB@B@B@B@B@B@B@B@B @@B@@@B @ .BS r @@@B@ <br />
|
||||
.@B@B@B@B@B@B@B@B@ B@B@@@B@Br XB@Br 7B u .vB B: B@B@B@B <br />
|
||||
@@@@B@B@B@B@B@B@B@B@B .@B@B@B@B@@M i..@. i i i P @,jB @@B <br />
|
||||
@B@B@B@B@B@B@B@B@B@B@B@i @N@@@B@@@B@B@B @ B@E <br />
|
||||
@B@B@B@@@B@B@B@B@B@B@B@B @ : @@B@B@@@Mi B . @@ <br />
|
||||
F@B@@@B@B@B@B@B@@@B@B@B@,@ M @.:v X i B :BM <br />
|
||||
i@B@B@B@B@@@B@B@B@@@@@B@B L ,r , ; B@. @B@, <br />
|
||||
,M@B@B @B@B@B@B@@@B@B@B@ rL B j :jr@B@@r @B@B@B <br />
|
||||
@B@B@B@B@B@B@B@B .: . .@ : , @@@@B@@ <br />
|
||||
,@B@B@B@B@B@B@B .@X r5BMB: r ,, 7 B B@B @B@B@B@@ <br />
|
||||
L@@B@B@B@ 8B@B@ BM:@B@B@B@B@B@@8X80Mu: FB@B@B@B@B@@@B@B@@@B@B q uO@GMFLv@B@B@B@B@ B@Bu <br />
|
||||
@B@B@B@B k@ MYM@@@B@B@F ,. :5@B@B7 Y@B@@@@@B@@@B@@@@@B@@@@@B@ B : B@B@B@ @@B@BL <br />
|
||||
B@@@@@@@ @@7 @EvB@BF B@B@B@@@@@B@BMB@B@B@B@@@B@B@B@ 7 . .@u, i@ B@B@77B@ <br />
|
||||
B@B@B@@@O@ : 7., :@B@@@B@B@B@, .LB@@@B@B@B@B@B@B@ @ r@: @::M @@B@B@M@B@ <br />
|
||||
:i @B@B@@@Bi5 :: v@B@@@B@B@B B@@@B@@@B@@@B@@ B@@@B@B@B@B@B@B@i<br />
|
||||
: B@B@B@B@B@ @B@B@B@@@B LB@B@@@B@B@B@B@B@@5 @B@B@B@B@B@@@B@ <br />
|
||||
.k@B@B@B@B@B@u. B@B@B@B@B2 @B@B@B@B@B@@@B@B@@@B@@@B@B@B@B@B@B@ <br />
|
||||
:Lur:F@@@B@B@B@B@@@B B@B@B@B@B@ @@@B@B@B@B@B@@@B@B@B@B@B@B@B@B@B@J <br />
|
||||
.vBMi :,,rB@B@B@B@BO @@@B@B@@@5 :i@@@B@B@B@@@B@B@B@B@@@B@@@B@B@B@@: <br />
|
||||
1r @B@B@B@B@B@ LB@B@B@B@Bq N@Bi rB@B@B@B@B@B@B@@@B@B@B@B@B@B@@@B@ <br />
|
||||
,L. @@B@B@B@G Li .@B@B@B@B@B@@@B@. B@B@viv@B@B@B@B@B@B@B@B@B@B@B@@@B@B@B@ <br />
|
||||
r, @@@@@B@@@B@: : B@B@B@B@B@B@@@B@ :B@ @S@B@B@B@B@B@B@@@B@B@B@@@B@B@B@ <br />
|
||||
.j iB@B@B@B@B@B@Bi:; G @@BrLk . i M@B@B@@@B@@@ GB@B@B@B@B@B@B@B@B@@@B@B@B@: <br />
|
||||
,: : BUB@B@B@B@@@@@N0r@B@B B@B@ : :@B@B@B@@@B @B@B@B@B@B@B@B@B@B@B@B@. B <br />
|
||||
@i ui M .. @B@: B.@@B@BB:O @. B @ i B@@@@@B@ @@@B@B@B@@@B @@B@B@B@@@B @ @ <br />
|
||||
E@ @7 ; .U i N@B@ B .@ @ @B@B@B@B@ v .GB @B@B@B@B@@@M: @B@B@B@B@BZ @ Y <br />
|
||||
Bu .@ M 7v7 @ :B@B@@@B@BU @B@B@B@B@ BB@B@B@B@B@Bi B@@@B@B@B@v <br />
|
||||
5@ @7 L S .q .N@B@@@B@BBB@B@B@B@B@B@kqqSB@B@B@B@B@ @B@B@B@B@@r <br />
|
||||
q : B Z .: 2@B@B@B@..L. . M@B@B@:@BiP @B B@@@B@B@B@ <br />
|
||||
; B@@@B@B. @@@B@: 2@B@B@ i @B@@@B@B@B <br />
|
||||
7@B@k@B@B@B@B@B@B@B@ B@B@@@@@Bi <br />
|
||||
jB@B@B@@@B@@O @B@B@B@B@ <br />
|
||||
B@B@B@B@k B@@@B@@@B <br />
|
||||
rPS: @B@ @B@B@ <br />
|
||||
. :: ,ui:,: vL:,:: B@B B@B@B <br />
|
||||
.B@B@B@B@i @B@@@B@5 @B@B :@@@@@ OB@@@ @B@ @B@@@ <br />
|
||||
@B@B@ FB@B@ 7@B@B@ .@@@B @B@B iMB@B@S .GB@B@.,B@@L vG0Sqv;:@ L@@ ..E@B <br />
|
||||
B@@@B@@@B@B@B .@B@@ :B@B@ B@B@ @B@B@..B@B@ @B@@@2.B@B@ @B@BBM S@1 S@. <br />
|
||||
@B@B@B. ,@B@B8 B@B@ .@B@@ @B@@ B@B@8:iii;Mv i@B@M .rr B@B@B@B k@r EJ <br />
|
||||
S@B@B@B@ EB@B@B@B. B@B@B@, r@B@B@1 @B@B@B: YB@@@r. 7@B@B@2 @@@@@@MB@B@ ,Bi <br />
|
||||
:r, .i ,: .i: :i ,:.i. i,:: :: :J@B@X7 i. i: r :,:. ,@ a <br />
|
||||
.B n <br />
|
||||
[ P R E S E N T S ] @ t <br />
|
||||
@ i <br />
|
||||
0 / <br />
|
||||
B 4 <br />
|
||||
@ 0 <br />
|
||||
. 4 <br />
|
||||
<br />
|
||||
Good.Behavior.S01E03.PROPER.720p.HDTV.x264-KILLERS<br />
|
||||
<br />
|
||||
<br />
|
||||
Day: 2016-11-29<br />
|
||||
Resolution: 1280x720<br />
|
||||
Size: 1.02 GiB<br />
|
||||
FrameRate: 23.976<br />
|
||||
Length: 00:49:02.144<br />
|
||||
Bitrate: 2 535 Kbps<br />
|
||||
Note: FLEET is missing the last seg<br />
|
||||
<br />
|
||||
<br />
|
||||
n***** We all miss you. Come back soon.]]>
|
||||
</description>
|
||||
<pubDate>Tue, 29 Nov 2016 10:55:58 +0000</pubDate>
|
||||
<link>https://alpharatio.cc/torrents.php?action=download&authkey=private_auth_key&torrent_pass=private_torrent_pass&id=465960</link>
|
||||
<guid>https://alpharatio.cc/torrents.php?action=download&authkey=private_auth_key&torrent_pass=private_torrent_pass&id=465960</guid>
|
||||
<comments>https://alpharatio.cc/torrents.php?id=465989</comments>
|
||||
<dc:creator>Anonymous</dc:creator>
|
||||
</item>
|
||||
<item>
|
||||
<title><![CDATA[TvHD 465860 465831 WWE.RAW.2016.11.28.720p.HDTV.x264-KYR]]></title>
|
||||
<description>
|
||||
<![CDATA[ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ<br />
|
||||
ÛÛÛÛÛÛÛÛÛÛÛß°° ÜÜÜÜÜÜ Ü° ßÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ<br />
|
||||
ÛÛÛÛÛÛÛßß°°Ü°ÛÛ²ßÜÛÛÜܲ Üß² ÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ<br />
|
||||
ÛÛÛÛÛß Üß°²°²ÛÛÝÛÛÛ±²² ÜÝ Þ ÞÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ<br />
|
||||
ÛÛÛÛ° ÛÛݲ޲ÛÛÛÞÛÛ±²ÝÝÞÛ ß ÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ<br />
|
||||
²ÛÛ°ÛÝÛÛÛݱÛÛÛ²ÛÛ°ÛÛÞ²Þ Ý ÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛßß ßßßÛÛÛÛÛÛÛÛÛÛ<br />
|
||||
ÛÛ°ÛÛÞÛÛÛÛ²ÛÛÛÛÛ°Û²ÛÞ² ݲ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛß ßÛÛÛÛÛÛÛ<br />
|
||||
Û°°ÛÛÛÛÛÛÛÛÛÛÛÛÝÝÛÛßݲ°ÞÞ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ² ²ÛÛÛÛÛ<br />
|
||||
°ÛÝÛÛÞÛÛÛ²ÛÛÛÞÛÞÞÞÜÛÛ°²ÝÞ ÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛ² ²ÛÛÛÛ<br />
|
||||
Û²ÝÛÛÝÛÛÛÛÛÛÛÞ°Û²ÞÛÛÛ Þ ² ÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ²ÛÛÛ<br />
|
||||
ÛÛÛÛÛÛÛÛÛÛÛÛÛÝÝÛÛÝÛÝÛ ² Ý ÛÛÛÛÛÛÛÛÛÛÛÛÛÝ ÛÛÛ<br />
|
||||
Û²ÛÛÛÝÛÛÛÛÛÝÛÝÛÞÛÛÞ²Þ ÝÝ ÜÜÜÜ ÛÛÛÛÛÛÛÛÛÛÛÛ ÜÜ Ü ÞÛÛ<br />
|
||||
ÛÛÛÛÛÝÛÛÛÛÛÛÞÛÞÛÛ²Þ°Þ ²Ý ßßßÛÛÛ² ÞÛÛÛÛÛÛÛÛÛÛ² ÛÛ²²ÛÛ² ÞÛÛ<br />
|
||||
ÛÛÛÛÛÛÞÛÛÛÝÛÞÛÝÛÛ±Þ ² ÝÞ ßÛÛÛÛÛÛ²Þ ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛÛÛÛ²± ÜÜ ß²ÛÛ<br />
|
||||
²ÛÛÛÛÛÛÛÛÛ²ÞÝÛÝÛÛ°Û ² Þ ² ÜßÛÛÛß ÞÞÛÛÛÛÛÛÛÛÛÝÝ ÛÛß ÜÜÜß² ÛÛ<br />
|
||||
ÛÛÛÛÝÛÛÛÛÛÛÛÝÛÞÞÛܲ Þ Ý Ý ßßß ßÛÛÛÛÛÛÛÛÛÝß ²ß ²ÞÝ ÞÛ<br />
|
||||
²ÛÛÛÝÛÛÛÛÛÞÝÛ²ÞÛÝÛÝ Ý Ý Þ ßÛÛÛÛÛÛÛß Þ ÞÝ ÞÛ<br />
|
||||
±ÛÛÛÛÞÛÛÛÛÞÞÛÝÛÛÝÞÛ ÝÞ ßÛÛÛÛÛ Ý ²ÛÜ ÛÛ<br />
|
||||
²ÛÛÛÛ°ÛÛÛÛÝÛÛÛÞÛÛ°Û ß Þ Ý Ý ÛÛÛÛÛ ÜÛÛÜ Ý Üß ßÛÛ<br />
|
||||
Û²ÛÛÝÝÝÛÛÛÞÛÛÛÛÛÞ²Þ Ý ²Ü²ÛÛ ÜÛÛÛÛÛÛßÛßßß ÜÜÜ²ß ÛÛ<br />
|
||||
ÛÝÛÛÞݰÛÛÛÝÛÛÝÛÛÝÛ²Ý Ý ßßÜÛÛÛÛÛÛÛÛÛ ° ß²ß ² ÞÛ<br />
|
||||
ÛÛ°ÛÞÛÞÞÛÛÛÞÛÛ°ÛÛ²ÞÛ Ý Ý ÜÜ ÞÞÛÛÛÛÛÛÛÛÜÛÜÜ ±°° ß Û<br />
|
||||
ÛÛÛÞÝÛÞÝÛÛÛÝÛÛÛÞÛÛ ²Ý Þ Þ°²ÛÛÛÛ ÞÛÛÛÛÛÛÛÛß ±²±± Þ<br />
|
||||
ÛÛÛÞÛÛÝÛÞÛÛݲÞÛÝÛÛÝÞÝ Ý ²ß ÜßݲÛÛÛÛÛÛÛÝÜ ÜܲÛÛÛ²² Þ<br />
|
||||
ÛÛÝÞÛÛÛÛÛÛÛÝÛ°Û²ÞÝÛ°ÛÞ ÝÝ ÜܲÞÛÛÛÛÛÛÛÛÝÛ²Ü ÜÛÛÛÛÛÛÛÛ±<br />
|
||||
ÛßÜÛÛÛÛÛÝÛÛÞÛÛÞÛ²ÞÝÝÛ ÝÝÝ ° ÝßÛ²ÝÞÛÛÛÛÛÛÛÛÛß ²ÛÛÛÛÛÛÛÛÛ<br />
|
||||
Ûßßß ßܲÞÛÛÛÛÛÞÛÞÛÛ°ÛÛÛ ²²±±Þ ßÜÛÛÛÛÛÛÛÛÛÛ ²ÛÛÛÛÛÛÛÛÛÛ<br />
|
||||
ÛÛÞÛÛÛÝÛÛÝÛÛÜßÛÞÛÛÛ²Ý²Ü ÛÛÛÛÛÛÛÛÛÝÞÜ ÜÜÛÛÛÛÛÛÛÛÛÛÛÛÝ Ü Þ<br />
|
||||
ß²ÛÞ²ÛÛÛ ÛÛÞÛÛÛÞÞÛÛ²Û²Þ²Ý ÞÛÛÛÛÛÛÛÛÝÞÛÛ²ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛß ÞÛ<br />
|
||||
ܲßÜÛÛÛÛÛÛÛÛÛÝÛÛÛÛÛÛÞ²ÛÜÛÛÛÛÛÛÛÛÛÛÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ² ÝÛ<br />
|
||||
ß ÜÜßßÜÛÛÛÛÛÛÞÛÛÛÛÛÛÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛÜÛßßÛÛÛÛÛÛÛÛÛÛÛÛÛ² Þ Û<br />
|
||||
ß ßÛÛÜÜÝÛÛÛ²ÛÛÛÛÛÛÝÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÜÜßÛÛÛÛÛÛÛ²ÜÜß ÝÞ²<br />
|
||||
ßÝÛÛÞÛÛÛÞÛÝÛÛÛÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ²Ü ² Û²<br />
|
||||
ÛÛÞÛÛÛÝÛÛÞÛÝÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÞÛÛÛÛÛß ² Þ²°<br />
|
||||
ß ²ÞÛÛÛÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÝÛÛÛ² ² ÜÛ²<br />
|
||||
ÞÛÛÝÛÛÛÛÛÛÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÝÛÛ ² ÜÛ²°<br />
|
||||
Üß ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛßÝß Üß ÜÛ²°<br />
|
||||
²ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛßܲ Üß ÜÛÛ²°<br />
|
||||
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û² Ü²ß ÜÛÛ²±°<br />
|
||||
²ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û² ÜÜßß ÜÛÛ²±°<br />
|
||||
ßÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û² ÜÜßß ÜÜÛÛÛ²±°<br />
|
||||
²ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û² ÜÜßß ÜÜÛÛÛÛ²²±°<br />
|
||||
ßÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÝÛ²ÜÜßß ÜÜÛÛÛÛ²²²±°<br />
|
||||
²ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ²ßßßÜÜÜÜÛÛÛÛ²²²±±°<br />
|
||||
²ÛÛÛÛÛÛÛÛÛÛÛÛß²ÛÛÛÛÛÛÛÛ²²²±±°<br />
|
||||
ßÛÛÛÛÛÛÛÛÛÛ °²ß²²²²±±°<br />
|
||||
ßÛÛÛÛÛÛÛÛ °²<br />
|
||||
²ÛÛÛÛÛÛÝ °±Ý<br />
|
||||
ßÛÛÛÛÛܰ°±²<br />
|
||||
²ÛÛ۲߲²ß<br />
|
||||
Û²Û<br />
|
||||
Þ²Ý<br />
|
||||
±<br />
|
||||
°<br />
|
||||
<br />
|
||||
ÜÜÜÜÜÜ ÜÜÜÜÜÜ ÜÜÜÜÜÜ<br />
|
||||
ÜßßÛÛß ßÛ² ÜßßÛÛß ßÛ² ÜÜÛÛÛÛÛß ßÛ²<br />
|
||||
ÛÛÛ°±ÛÝ ²ÛÜ ÛÛÛ°±ÛÝ ÜÛÛÛÛßßÛÛÛÛÛ°±ÛÝ<br />
|
||||
ÞÛÛÛ²ÛÛ ÛÛÝ ÞÛÛÛ²ÛÝÛÛÛß ÞÛÛÛÛ²ÛÛ<br />
|
||||
ÜÜ ÛÛÛÛÛÛ² ÞÛÛÝ ÞÛÛÛÛÛ ²ÛÝ ÛÛÛÛÛÛ²<br />
|
||||
ÞÛÛ ²ÛÛÛÛÛÛ ÛÛÛ ÞÛÛÛÛ² ÞÛÛ ²ÛÛÛÛÛÛ<br />
|
||||
ÛÛÝ ²ÛÛÛÛÛ² ÛÛÛ ÛÛÛÛÛÝ ÛÛÝ ²ÛÛÛÛÛ²<br />
|
||||
ÞÛ² ÜÜÛÛÛÛÛÛÜÜÜ ÞÛÛÝ ²ÛÛÛÛÛ ÞÛ² ÜÜÛÛÛÛÛÛÜÜÜ ß<br />
|
||||
ÛÛÛÛÛÛÛÛÛÛÛÛÛßßÛÜ ²ÛÛÜÜÜÛÛÛÛÛÛÝ ÛÛÛÛÛÛÛÛÛÛÛÛÛßßÛÜ<br />
|
||||
ÞÛÛÛßß ßÛÛÛ°ÞÛ ßÛÛÛÛÛÛÛÛÛ² ÞÛÛÛßß ßÛÛÛ°ÞÛ<br />
|
||||
²Û² ÛÛÛÜÛÝ ÛÛÛÛÛÝ ²ÛÛ ÛÛÛÜÛÝ<br />
|
||||
ÞÛÛÝ ÛÛÛÛÛ² ÞÛÛÛÛÛ ÞÛÛÝ ÛÛÛÛÛ²<br />
|
||||
ÛÛÛ ÛßÛÛÛÛ ÛßÛÛÛÝ ÛÛÛ ÛßÛÛÛÛ<br />
|
||||
ß Û°ÞÛÛÛÝ Û°ÞÛÛÛ ß Û°ÞÛÛÛÝ<br />
|
||||
Û±°ÛÛÛ² Û±°ÛÛÛ² Û±°ÛÛÛ²<br />
|
||||
Þ±±±°ÛÛ Þ±±±°ÛÛ Þ±±±°ÛÛ presents..<br />
|
||||
Þ²±±±±Ý Þ²±±±±Ý Þ²±±±±Ý<br />
|
||||
Û²²²ÛÜ Ü² Û²²²ÛÜ Ü² Û²²²ÛÜ Ü²<br />
|
||||
ßßßßßßßßßßß ßßßßßßßßßßßßßßßßßß ßßßßßßßßßß<br />
|
||||
k n o w y o u r r o l e<br />
|
||||
<br />
|
||||
ú úú--Ä-Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä-Ä--úú ú<br />
|
||||
WWE.RAW.2016.11.28.720p.HDTV.h264-KYR<br />
|
||||
ú úú--Ä-Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä-Ä--úú ú<br />
|
||||
ÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜ<br />
|
||||
ÛßܰÛßÜ°Û Û²Ûßܰ۰ÜßÛ ÜÜÛßÜ°Û ÛÜÛßܰÛßÜÜÛ°ÜßÛ<br />
|
||||
ÚÄÄÛ ßÜÛ ÜÛÛ Û²Û ÜÛÛ Ü ÛÜÜ°Û ÜÛßÄÄÛ Û Û Û ÜÛÛ Û ÛÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄúú ú<br />
|
||||
³ Û Û ÛÜßßÛÜßßÛÜßßÛÜÛ ÛÜß ÛÜßßÛ Û ÛÜÛ Û°Û²Û ß Û<br />
|
||||
³ ßßßßßßßßßßßßßßßßß ßßßßßßßßßßß ßßß ßßßßß ßßßßß<br />
|
||||
³<br />
|
||||
³ titleú[ WWE RAW ]ú<br />
|
||||
³ genreú[ Wrestling ]ú crfú[ 23 ]ú<br />
|
||||
³ rel. dateú[ 11.28.16 ]ú formatú[ x264 ]ú<br />
|
||||
³ air dateú[ 11.28.16 ]ú sourceú[ HDTV ]ú<br />
|
||||
³ runtimeú[ 2h 13m 48s ]ú bitrateú[ 4111kbps ]ú<br />
|
||||
³ filesizeú[ 4.28 GB ]ú resolu.ú[ 1280x720 ]ú<br />
|
||||
³ rar countú[ 93x50mb ]ú framesú[ 59.940 ]ú<br />
|
||||
³ ú[ audioú[ 384 kbps AC3 5.1 ]ú<br />
|
||||
³ ú[ locationú[ USA ]ú<br />
|
||||
³ ú[ ]ú<br />
|
||||
³ url ú[ http://www.wwe.com ]ú <br />
|
||||
³<br />
|
||||
³<br />
|
||||
³ ÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ<br />
|
||||
³ ÛßܰÛßÜ°Û Û²Ûßܰ۰ÜßÛ ÜÜÛßÜ°Û Ûßܰ۰ÜßÛÜ ÜÛßÜ°Û ÜÜÛ<br />
|
||||
³ ú úúÄÄÄÄÄ-Û ßÜÛ ÜÛÛ Û²Û ÜÛÛ Ü ÛÜÜ°Û ÜÛßÄÄÛ Û Û Û ÛÛ ÛÛ ÜÛÛÜܰÛÄÄ´<br />
|
||||
³ Û Û ÛÜßßÛÜßßÛÜßßÛÜÛ ÛÜß ÛÜßßÛ Û Û Û ß ÛÛ°ÛÛÜßßÛÜß Û ³<br />
|
||||
³ ßßßßßßßßßßßßßßßßß ßßßßßßßßßßß ßßßßßßßßßßßß ßßßßßßßß ³<br />
|
||||
³ ³<br />
|
||||
³ ³<br />
|
||||
³ Enjoy! ³<br />
|
||||
³ ³<br />
|
||||
³ ³<br />
|
||||
³ ÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ³<br />
|
||||
³ ÛßܰÛßܰ۰ÜßÛßÛ°ÛßÜ°Û ÛÜÛßܰÛßÜÜÛ°ÜßÛ ³<br />
|
||||
ÃÄÄÛ ÝßÛ ßÜÛ Û Û Û Û ß ÛÄÄÛ°Û Û Û ÜÛÛ Û ÛÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄúú ú ³<br />
|
||||
Û ß Û Û Û ß Û ß Û Ûßß Û Û Û Û°Û²Û ß Û ³<br />
|
||||
ßßßßßßßßßßßßßßßßßßß ßßßßßßßßß ßßßßß ³<br />
|
||||
³<br />
|
||||
group info ³<br />
|
||||
³<br />
|
||||
Know Your Role and Shut Your Mouth! ³<br />
|
||||
³<br />
|
||||
we are now looking for... ³<br />
|
||||
³<br />
|
||||
(a) capper(s) of cable, PPV, good upspeed advantageous ³<br />
|
||||
.. contact in the usual way. ³<br />
|
||||
³<br />
|
||||
KYR respects... ³<br />
|
||||
³<br />
|
||||
everyone keeping it real and oldschool. we love ya! ³<br />
|
||||
³<br />
|
||||
Ü ÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ³<br />
|
||||
ÜÜÜܲ ÜÜÜ Ûܲ ÜÜÜ ÜÜÜÜÜÜÜ ²Ý ³<br />
|
||||
ú úúÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÛ ÜÜ ÝÞÛÛÝÜÜ ÝÞÛÛÝßß ÞÛÛÝÞÛ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´<br />
|
||||
Û ÛÛ ÜÛÛß ÛÛ ÜÛÛ² ÛÛ ÜÛÛß ÛÝ K N O W ³<br />
|
||||
ascii crafted by Û ÛÛÛÛ²Ü ÞÛÛ²ß Ü ÛÛÛÛ²Ü ßÛ ³<br />
|
||||
Û ÛÛ ßÛÛ² ÛÛ Ü²Û ÛÛ ßÛÛ² ²Ý Y O U R ³<br />
|
||||
h8`!HiGHONASCii Û ÛÛ ÝÞÛÛÝ ÛÛ Û Û ÛÛ ÝÞÛÛÝÞÛ ³<br />
|
||||
Û Û² Û ÛÛ² Û² Û Û Û² Û ÛÛ² Û R O L E ³<br />
|
||||
ú úúÄ-Ä----ÄÄÄÄÄÄÄÄÄÄÄÄÛÜÜÜܲÜÜÜÜÜÜÜܲ ÛÜÜÜܲÜÜÜÜܲ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ<br />
|
||||
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜ ÜÜÜÜÜÜÜ<br />
|
||||
°±²Û ÜßÛ ÜßÛ ÜßÛ ÜßÛ²²ÛßܰÛßÜ°Û Û²Ûßܰ۰ÜßÛ ÜÜÛßÜ°Û ÜÜÛ²²Û°ÜßÛßܰ۰ÜßÛ²±°<br />
|
||||
° °±Û Û Û Û Û Û Û Û Û+±Û ßÜÛ ÜÛÛ Û±Û ÜÛÛ Ü ÛÜÜ°Û ÜÛÛÜܰ۱±Û Ü Û Û Û Û Û±° °<br />
|
||||
°±²ÛÜß°ÛÜß°ÛÜß°ÛÜß°Û²²Û Û ÛÜßßÛÜßßÛÜßßÛÜÛ ÛÜß ÛÜßßÛÜß Û²²ÛÜÛ ÛÜÛ Û ßÜÛ²±°<br />
|
||||
ßßßßßßßßßßßßßßßßß ßßßßßßßßßßßßßßßßß ßßßßßßßßßßßßßßß ßßß ßßßßßß<br />
|
||||
ÜÜÜÜÜÜÜ ÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ<br />
|
||||
°±²²ÛßÜ Û°ÜßÛßÛ°ÛßܰÛÜ ÜÛÜÛßܰÛßܰ۰۰۰۲²±°<br />
|
||||
° °±±Û ÛÛÛ Û Û Û Û Û ÛÛ ÛÛ°Û Û Û ÝßÛ Û Û Û±±° °<br />
|
||||
°±²²ÛÜß°Û ß Û ß ÛÜÛ ÛÛ°ÛÛ Û Û Û°ß ÛßÛßÛßÛ²²±°<br />
|
||||
ßßßßßßßßßßßß ßßßßßßßßßßßßßßßßßßßßßß]]>
|
||||
</description>
|
||||
<pubDate>Tue, 29 Nov 2016 05:08:18 +0000</pubDate>
|
||||
<link>https://alpharatio.cc/torrents.php?action=download&authkey=private_auth_key&torrent_pass=private_torrent_pass&id=465831</link>
|
||||
<guid>https://alpharatio.cc/torrents.php?action=download&authkey=private_auth_key&torrent_pass=private_torrent_pass&id=465831</guid>
|
||||
<comments>https://alpharatio.cc/torrents.php?id=465860</comments>
|
||||
<dc:creator>Anonymous</dc:creator>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
@@ -12,6 +12,7 @@ namespace NzbDrone.Core.Test.Framework
|
||||
{
|
||||
List<Dictionary<string, object>> Query(string sql);
|
||||
List<T> Query<T>(string sql) where T : new();
|
||||
T QueryScalar<T>(string sql);
|
||||
}
|
||||
|
||||
public class DirectDataMapper : IDirectDataMapper
|
||||
@@ -25,7 +26,7 @@ namespace NzbDrone.Core.Test.Framework
|
||||
_providerFactory = dataMapper.ProviderFactory;
|
||||
_connectionString = dataMapper.ConnectionString;
|
||||
}
|
||||
|
||||
|
||||
private DbConnection OpenConnection()
|
||||
{
|
||||
var connection = _providerFactory.CreateConnection();
|
||||
@@ -62,6 +63,13 @@ namespace NzbDrone.Core.Test.Framework
|
||||
return dataTable.Rows.Cast<DataRow>().Select(MapToObject<T>).ToList();
|
||||
}
|
||||
|
||||
public T QueryScalar<T>(string sql)
|
||||
{
|
||||
var dataTable = GetDataTable(sql);
|
||||
|
||||
return dataTable.Rows.Cast<DataRow>().Select(d => MapValue(d, 0, typeof(T))).Cast<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
protected Dictionary<string, object> MapToDictionary(DataRow dataRow)
|
||||
{
|
||||
var item = new Dictionary<string, object>();
|
||||
@@ -107,24 +115,29 @@ namespace NzbDrone.Core.Test.Framework
|
||||
propertyType = propertyType.GetGenericArguments()[0];
|
||||
}
|
||||
|
||||
object value;
|
||||
if (dataRow.ItemArray[i] == DBNull.Value)
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
else if (dataRow.Table.Columns[i].DataType == typeof(string) && propertyType != typeof(string))
|
||||
{
|
||||
value = Json.Deserialize((string)dataRow.ItemArray[i], propertyType);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = Convert.ChangeType(dataRow.ItemArray[i], propertyType);
|
||||
}
|
||||
object value = MapValue(dataRow, i, propertyType);
|
||||
|
||||
|
||||
propertyInfo.SetValue(item, value, null);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private object MapValue(DataRow dataRow, int i, Type targetType)
|
||||
{
|
||||
if (dataRow.ItemArray[i] == DBNull.Value)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (dataRow.Table.Columns[i].DataType == typeof(string) && targetType != typeof(string))
|
||||
{
|
||||
return Json.Deserialize((string)dataRow.ItemArray[i], targetType);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Convert.ChangeType(dataRow.ItemArray[i], targetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using FluentAssertions;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.HealthCheck;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
@@ -10,14 +11,24 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
result.Type.Should().Be(HealthCheckResult.Ok);
|
||||
}
|
||||
|
||||
public static void ShouldBeWarning(this Core.HealthCheck.HealthCheck result)
|
||||
public static void ShouldBeWarning(this Core.HealthCheck.HealthCheck result, string message = null)
|
||||
{
|
||||
result.Type.Should().Be(HealthCheckResult.Warning);
|
||||
|
||||
if (message.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
result.Message.Should().Contain(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShouldBeError(this Core.HealthCheck.HealthCheck result)
|
||||
public static void ShouldBeError(this Core.HealthCheck.HealthCheck result, string message = null)
|
||||
{
|
||||
result.Type.Should().Be(HealthCheckResult.Error);
|
||||
|
||||
if (message.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
result.Message.Should().Contain(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using System.Collections.Generic;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class IndexerRssCheckFixture : CoreTest<IndexerRssCheck>
|
||||
{
|
||||
private Mock<IIndexer> _indexerMock;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.GetAvailableProviders())
|
||||
.Returns(new List<IIndexer>());
|
||||
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.RssEnabled(It.IsAny<bool>()))
|
||||
.Returns(new List<IIndexer>());
|
||||
}
|
||||
|
||||
private void GivenIndexer(bool supportsRss, bool supportsSearch)
|
||||
{
|
||||
_indexerMock = Mocker.GetMock<IIndexer>();
|
||||
_indexerMock.SetupGet(s => s.SupportsRss).Returns(supportsRss);
|
||||
_indexerMock.SetupGet(s => s.SupportsSearch).Returns(supportsSearch);
|
||||
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.GetAvailableProviders())
|
||||
.Returns(new List<IIndexer> { _indexerMock.Object });
|
||||
}
|
||||
|
||||
private void GivenRssEnabled()
|
||||
{
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.RssEnabled(It.IsAny<bool>()))
|
||||
.Returns(new List<IIndexer> { _indexerMock.Object });
|
||||
}
|
||||
|
||||
private void GivenRssFiltered()
|
||||
{
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.RssEnabled(false))
|
||||
.Returns(new List<IIndexer> { _indexerMock.Object });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_error_when_no_indexer_present()
|
||||
{
|
||||
Subject.Check().ShouldBeError();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_error_when_no_rss_supported_indexer_present()
|
||||
{
|
||||
GivenIndexer(false, true);
|
||||
|
||||
Subject.Check().ShouldBeError();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_when_rss_is_enabled()
|
||||
{
|
||||
GivenIndexer(true, false);
|
||||
GivenRssEnabled();
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_error_if_rss_is_supported_but_disabled()
|
||||
{
|
||||
GivenIndexer(true, false);
|
||||
|
||||
Subject.Check().ShouldBeError();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_filter_warning_if_rss_is_enabled_but_filtered()
|
||||
{
|
||||
GivenIndexer(true, false);
|
||||
GivenRssFiltered();
|
||||
|
||||
Subject.Check().ShouldBeWarning("recent indexer errors");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,22 @@ using NzbDrone.Core.Test.Framework;
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class IndexerCheckFixture : CoreTest<IndexerCheck>
|
||||
public class IndexerSearchCheckFixture : CoreTest<IndexerSearchCheck>
|
||||
{
|
||||
private Mock<IIndexer> _indexerMock;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.GetAvailableProviders())
|
||||
.Returns(new List<IIndexer>());
|
||||
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.SearchEnabled(It.IsAny<bool>()))
|
||||
.Returns(new List<IIndexer>());
|
||||
}
|
||||
|
||||
private void GivenIndexer(bool supportsRss, bool supportsSearch)
|
||||
{
|
||||
_indexerMock = Mocker.GetMock<IIndexer>();
|
||||
@@ -21,42 +33,30 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.GetAvailableProviders())
|
||||
.Returns(new List<IIndexer> { _indexerMock.Object });
|
||||
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.RssEnabled())
|
||||
.Returns(new List<IIndexer>());
|
||||
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.SearchEnabled())
|
||||
.Returns(new List<IIndexer>());
|
||||
}
|
||||
|
||||
private void GivenRssEnabled()
|
||||
{
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.RssEnabled())
|
||||
.Returns(new List<IIndexer> { _indexerMock.Object });
|
||||
}
|
||||
|
||||
private void GivenSearchEnabled()
|
||||
{
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.SearchEnabled())
|
||||
.Setup(s => s.SearchEnabled(It.IsAny<bool>()))
|
||||
.Returns(new List<IIndexer> { _indexerMock.Object });
|
||||
}
|
||||
|
||||
private void GivenSearchFiltered()
|
||||
{
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.SearchEnabled(false))
|
||||
.Returns(new List<IIndexer> { _indexerMock.Object });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_error_when_not_indexers_are_enabled()
|
||||
public void should_return_warning_when_no_indexer_present()
|
||||
{
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.GetAvailableProviders())
|
||||
.Returns(new List<IIndexer>());
|
||||
|
||||
Subject.Check().ShouldBeError();
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_when_only_enabled_indexer_doesnt_support_search()
|
||||
public void should_return_warning_when_no_search_supported_indexer_present()
|
||||
{
|
||||
GivenIndexer(true, false);
|
||||
|
||||
@@ -64,7 +64,16 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_when_only_enabled_indexer_doesnt_support_rss()
|
||||
public void should_return_ok_when_search_is_enabled()
|
||||
{
|
||||
GivenIndexer(false, true);
|
||||
GivenSearchEnabled();
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_if_search_is_supported_but_disabled()
|
||||
{
|
||||
GivenIndexer(false, true);
|
||||
|
||||
@@ -72,52 +81,12 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_when_multiple_indexers_are_enabled()
|
||||
public void should_return_filter_warning_if_search_is_enabled_but_filtered()
|
||||
{
|
||||
GivenRssEnabled();
|
||||
GivenSearchEnabled();
|
||||
GivenIndexer(false, true);
|
||||
GivenSearchFiltered();
|
||||
|
||||
var indexer1 = Mocker.GetMock<IIndexer>();
|
||||
indexer1.SetupGet(s => s.SupportsRss).Returns(true);
|
||||
indexer1.SetupGet(s => s.SupportsSearch).Returns(true);
|
||||
|
||||
var indexer2 = new Moq.Mock<IIndexer>();
|
||||
indexer2.SetupGet(s => s.SupportsRss).Returns(true);
|
||||
indexer2.SetupGet(s => s.SupportsSearch).Returns(false);
|
||||
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.GetAvailableProviders())
|
||||
.Returns(new List<IIndexer> { indexer1.Object, indexer2.Object });
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_when_indexer_supports_rss_and_search()
|
||||
{
|
||||
GivenIndexer(true, true);
|
||||
GivenRssEnabled();
|
||||
GivenSearchEnabled();
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_if_rss_is_supported_but_disabled()
|
||||
{
|
||||
GivenIndexer(true, true);
|
||||
GivenSearchEnabled();
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_if_search_is_supported_but_disabled()
|
||||
{
|
||||
GivenIndexer(true, true);
|
||||
GivenRssEnabled();
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
Subject.Check().ShouldBeWarning("recent indexer errors");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,10 +81,10 @@ namespace NzbDrone.Core.Test.HistoryTests
|
||||
Path = @"C:\Test\Unsorted\Series.s01e01.mkv"
|
||||
};
|
||||
|
||||
Subject.Handle(new EpisodeImportedEvent(localEpisode, episodeFile, true, "sab", "abcd", true));
|
||||
Subject.Handle(new EpisodeImportedEvent(localEpisode, episodeFile, true, "sab", "abcd"));
|
||||
|
||||
Mocker.GetMock<IHistoryRepository>()
|
||||
.Verify(v => v.Insert(It.Is<History.History>(h => h.SourceTitle == Path.GetFileNameWithoutExtension(localEpisode.Path))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
|
||||
_mockIndexer.SetupGet(s => s.SupportsSearch).Returns(true);
|
||||
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(s => s.SearchEnabled())
|
||||
.Setup(s => s.SearchEnabled(true))
|
||||
.Returns(new List<IIndexer> { _mockIndexer.Object });
|
||||
|
||||
Mocker.GetMock<IMakeDownloadDecision>()
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
using FluentAssertions;
|
||||
using System;
|
||||
using System.Xml;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers.Newznab;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
||||
{
|
||||
@@ -64,5 +67,35 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
||||
caps.DefaultPageSize.Should().Be(100);
|
||||
caps.MaxPageSize.Should().Be(100);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_if_failed_to_get()
|
||||
{
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Get(It.IsAny<HttpRequest>()))
|
||||
.Throws<Exception>();
|
||||
|
||||
Assert.Throws<Exception>(() => Subject.GetCapabilities(_settings));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_if_xml_invalid()
|
||||
{
|
||||
GivenCapsResponse(_caps.Replace("<limits", "<>"));
|
||||
|
||||
Assert.Throws<XmlException>(() => Subject.GetCapabilities(_settings));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_throw_on_xml_data_unexpected()
|
||||
{
|
||||
GivenCapsResponse(_caps.Replace("5030", "asdf"));
|
||||
|
||||
var result = Subject.GetCapabilities(_settings);
|
||||
|
||||
result.Should().NotBeNull();
|
||||
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,5 +241,22 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
|
||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
torrentInfo.DownloadUrl.Should().Be("http://storage.animetosho.org/torrents/4b58360143d59a55cbd922397a3eaa378165f3ff/DAYS%20-%2005%20%281280x720%20HEVC2%20AAC%29.torrent");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_recent_feed_from_AlphaRatio()
|
||||
{
|
||||
GivenRecentFeedResponse("TorrentRss/AlphaRatio.xml");
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(2);
|
||||
releases.Last().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
var torrentInfo = releases.Last() as TorrentInfo;
|
||||
|
||||
torrentInfo.Title.Should().Be("TvHD 465860 465831 WWE.RAW.2016.11.28.720p.HDTV.x264-KYR");
|
||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
torrentInfo.DownloadUrl.Should().Be("https://alpharatio.cc/torrents.php?action=download&authkey=private_auth_key&torrent_pass=private_torrent_pass&id=465831");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,6 +200,26 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_detect_rss_settings_for_AlphaRatio()
|
||||
{
|
||||
_indexerSettings.AllowZeroSize = true;
|
||||
|
||||
GivenRecentFeedResponse("TorrentRss/AlphaRatio.xml");
|
||||
|
||||
var settings = Subject.Detect(_indexerSettings);
|
||||
|
||||
settings.ShouldBeEquivalentTo(new TorrentRssIndexerParserSettings
|
||||
{
|
||||
UseEZTVFormat = false,
|
||||
UseEnclosureUrl = false,
|
||||
UseEnclosureLength = false,
|
||||
ParseSizeInDescription = true,
|
||||
ParseSeedersInDescription = false,
|
||||
SizeElementName = null
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Cannot reliably reject unparseable titles")]
|
||||
public void should_reject_rss_settings_for_AwesomeHD()
|
||||
|
||||
@@ -5,6 +5,7 @@ using FizzWare.NBuilder;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
@@ -17,28 +18,50 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
public class ScanFixture : CoreTest<DiskScanService>
|
||||
{
|
||||
private Series _series;
|
||||
private string _rootFolder;
|
||||
private string _otherSeriesFolder;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_rootFolder = @"C:\Test\TV".AsOsAgnostic();
|
||||
_otherSeriesFolder = @"C:\Test\TV\OtherSeries".AsOsAgnostic();
|
||||
var seriesFolder = @"C:\Test\TV\Series".AsOsAgnostic();
|
||||
|
||||
_series = Builder<Series>.CreateNew()
|
||||
.With(s => s.Path = @"C:\Test\TV\Series".AsOsAgnostic())
|
||||
.With(s => s.Path = seriesFolder)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.FolderExists(It.IsAny<string>()))
|
||||
.Returns(false);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetParentFolder(It.IsAny<string>()))
|
||||
.Returns((string path) => Directory.GetParent(path).FullName);
|
||||
}
|
||||
|
||||
private void GivenParentFolderExists()
|
||||
private void GivenRootFolder(params string[] subfolders)
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.FolderExists(It.IsAny<string>()))
|
||||
.Setup(s => s.FolderExists(_rootFolder))
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetDirectories(It.IsAny<string>()))
|
||||
.Returns(new string[] { @"C:\Test\TV\Series2".AsOsAgnostic() });
|
||||
.Setup(s => s.GetDirectories(_rootFolder))
|
||||
.Returns(subfolders);
|
||||
|
||||
foreach (var folder in subfolders)
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.FolderExists(folder))
|
||||
.Returns(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenSeriesFolder()
|
||||
{
|
||||
GivenRootFolder(_series.Path);
|
||||
}
|
||||
|
||||
private void GivenFiles(IEnumerable<string> files)
|
||||
@@ -49,39 +72,124 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_scan_if_series_root_folder_does_not_exist()
|
||||
{
|
||||
public void should_not_scan_if_root_folder_does_not_exist()
|
||||
{
|
||||
Subject.Scan(_series);
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(v => v.FolderExists(_series.Path), Times.Never());
|
||||
|
||||
Mocker.GetMock<IMediaFileTableCleanupService>()
|
||||
.Verify(v => v.Clean(It.IsAny<Series>(), It.IsAny<List<string>>()), Times.Never());
|
||||
.Verify(v => v.Clean(It.IsAny<Series>(), It.IsAny<List<string>>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_scan_if_series_root_folder_is_empty()
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.FolderExists(It.IsAny<string>()))
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetDirectories(It.IsAny<string>()))
|
||||
.Returns(new string[0]);
|
||||
GivenRootFolder();
|
||||
|
||||
Subject.Scan(_series);
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(v => v.FolderExists(_series.Path), Times.Never());
|
||||
|
||||
Mocker.GetMock<IMediaFileTableCleanupService>()
|
||||
.Verify(v => v.Clean(It.IsAny<Series>(), new List<string>()), Times.Never());
|
||||
.Verify(v => v.Clean(It.IsAny<Series>(), It.IsAny<List<string>>()), Times.Never());
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Verify(v => v.GetImportDecisions(It.IsAny<List<string>>(), _series), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_create_if_series_folder_does_not_exist_but_create_folder_enabled()
|
||||
{
|
||||
GivenRootFolder(_otherSeriesFolder);
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.Setup(s => s.CreateEmptySeriesFolders)
|
||||
.Returns(true);
|
||||
|
||||
Subject.Scan(_series);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(v => v.CreateFolder(_series.Path), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_create_if_series_folder_does_not_exist_and_create_folder_disabled()
|
||||
{
|
||||
GivenRootFolder(_otherSeriesFolder);
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.Setup(s => s.CreateEmptySeriesFolders)
|
||||
.Returns(false);
|
||||
|
||||
Subject.Scan(_series);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(v => v.CreateFolder(_series.Path), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_clean_but_not_import_if_series_folder_does_not_exist()
|
||||
{
|
||||
GivenRootFolder(_otherSeriesFolder);
|
||||
|
||||
Subject.Scan(_series);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(v => v.FolderExists(_series.Path), Times.Once());
|
||||
|
||||
Mocker.GetMock<IMediaFileTableCleanupService>()
|
||||
.Verify(v => v.Clean(It.IsAny<Series>(), It.IsAny<List<string>>()), Times.Once());
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Verify(v => v.GetImportDecisions(It.IsAny<List<string>>(), _series), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_clean_but_not_import_if_series_folder_does_not_exist_and_create_folder_enabled()
|
||||
{
|
||||
GivenRootFolder(_otherSeriesFolder);
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.Setup(s => s.CreateEmptySeriesFolders)
|
||||
.Returns(true);
|
||||
|
||||
Subject.Scan(_series);
|
||||
|
||||
Mocker.GetMock<IMediaFileTableCleanupService>()
|
||||
.Verify(v => v.Clean(It.IsAny<Series>(), It.IsAny<List<string>>()), Times.Once());
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Verify(v => v.GetImportDecisions(It.IsAny<List<string>>(), _series), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_find_files_at_root_of_series_folder()
|
||||
{
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
Path.Combine(_series.Path, "file1.mkv").AsOsAgnostic(),
|
||||
Path.Combine(_series.Path, "s01e01.mkv").AsOsAgnostic()
|
||||
});
|
||||
|
||||
Subject.Scan(_series);
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Verify(v => v.GetImportDecisions(It.Is<List<string>>(l => l.Count == 2), _series), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_scan_extras_subfolder()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
@@ -94,6 +202,9 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
|
||||
Subject.Scan(_series);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(v => v.GetFiles(It.IsAny<string>(), It.IsAny<SearchOption>()), Times.Once());
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Verify(v => v.GetImportDecisions(It.Is<List<string>>(l => l.Count == 1), _series), Times.Once());
|
||||
}
|
||||
@@ -101,7 +212,7 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
[Test]
|
||||
public void should_not_scan_AppleDouble_subfolder()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
@@ -119,9 +230,10 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
[Test]
|
||||
public void should_scan_extras_series_and_subfolders()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
_series.Path = @"C:\Test\TV\Extras".AsOsAgnostic();
|
||||
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
Path.Combine(_series.Path, "Extras", "file1.mkv").AsOsAgnostic(),
|
||||
@@ -141,7 +253,7 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
[Test]
|
||||
public void should_not_scan_subfolders_that_start_with_period()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
@@ -160,7 +272,7 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
[Test]
|
||||
public void should_not_scan_subfolder_of_season_folder_that_starts_with_a_period()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
@@ -180,7 +292,7 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
[Test]
|
||||
public void should_not_scan_Synology_eaDir()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
@@ -197,7 +309,7 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
[Test]
|
||||
public void should_not_scan_thumb_folder()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
@@ -214,9 +326,10 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
[Test]
|
||||
public void should_scan_dotHack_folder()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
_series.Path = @"C:\Test\TV\.hack".AsOsAgnostic();
|
||||
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
Path.Combine(_series.Path, "Season 1", "file1.mkv").AsOsAgnostic(),
|
||||
@@ -229,27 +342,10 @@ namespace NzbDrone.Core.Test.MediaFiles.DiskScanServiceTests
|
||||
.Verify(v => v.GetImportDecisions(It.Is<List<string>>(l => l.Count == 2), _series), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_find_files_at_root_of_series_folder()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
Path.Combine(_series.Path, "file1.mkv").AsOsAgnostic(),
|
||||
Path.Combine(_series.Path, "s01e01.mkv").AsOsAgnostic()
|
||||
});
|
||||
|
||||
Subject.Scan(_series);
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Verify(v => v.GetImportDecisions(It.Is<List<string>>(l => l.Count == 2), _series), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_exclude_osx_metadata_files()
|
||||
{
|
||||
GivenParentFolderExists();
|
||||
GivenSeriesFolder();
|
||||
|
||||
GivenFiles(new List<string>
|
||||
{
|
||||
|
||||
@@ -224,9 +224,9 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||
}
|
||||
|
||||
[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>()
|
||||
.Verify(v => v.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), _approvedDecisions.First().LocalEpisode, true), Times.Once());
|
||||
@@ -235,7 +235,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||
[Test]
|
||||
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>()
|
||||
.Verify(v => v.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), _approvedDecisions.First().LocalEpisode, false), Times.Once());
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Marr.Data;
|
||||
@@ -31,10 +32,13 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||
.CreateNew()
|
||||
.Build();
|
||||
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.FileExists(It.IsAny<string>()))
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetParentFolder(It.IsAny<string>()))
|
||||
.Returns<string>(c => Path.GetDirectoryName(c));
|
||||
}
|
||||
|
||||
private void GivenSingleEpisodeWithSingleEpisodeFile()
|
||||
@@ -95,7 +99,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||
|
||||
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode);
|
||||
|
||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Once());
|
||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>(), It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -105,7 +109,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||
|
||||
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode);
|
||||
|
||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Once());
|
||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>(), It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -115,7 +119,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||
|
||||
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode);
|
||||
|
||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Exactly(2));
|
||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>(), It.IsAny<string>()), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -153,7 +157,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||
|
||||
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode);
|
||||
|
||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Never());
|
||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -48,13 +48,11 @@
|
||||
<HintPath>..\packages\NBuilder.4.0.0\lib\net40\FizzWare.NBuilder.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.18.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.18.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="FluentAssertions.Core, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentAssertions.4.19.0\lib\net40\FluentAssertions.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentMigrator, Version=1.6.2.0, Culture=neutral, PublicKeyToken=aacfc7de5acabf05, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FluentMigrator.1.6.2\lib\40\FluentMigrator.dll</HintPath>
|
||||
@@ -68,9 +66,8 @@
|
||||
<HintPath>..\packages\FluentValidation.6.2.1.0\lib\portable-net40+sl50+wp80+win8+wpa81\FluentValidation.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Unity, Version=2.1.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Unity.2.1.505.2\lib\NET35\Microsoft.Practices.Unity.dll</HintPath>
|
||||
@@ -89,12 +86,10 @@
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.1\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.5.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="nunit.framework, Version=3.6.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.6.0\lib\net40\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
@@ -124,6 +119,9 @@
|
||||
<Compile Include="Datastore\DatabaseRelationshipFixture.cs" />
|
||||
<Compile Include="Datastore\MappingExtentionFixture.cs" />
|
||||
<Compile Include="Datastore\MarrDataLazyLoadingFixture.cs" />
|
||||
<Compile Include="Datastore\Migration\108_fix_metadata_file_extensionsFixture.cs" />
|
||||
<Compile Include="Datastore\Migration\109_import_extra_files_configFixture.cs" />
|
||||
<Compile Include="Datastore\Migration\110_fix_extra_files_configFixture.cs" />
|
||||
<Compile Include="Datastore\Migration\106_update_btn_urlFixture.cs" />
|
||||
<Compile Include="Datastore\Migration\103_fix_metadata_file_extensionsFixture.cs" />
|
||||
<Compile Include="Datastore\Migration\099_extra_and_subtitle_filesFixture.cs" />
|
||||
@@ -215,9 +213,10 @@
|
||||
<Compile Include="HealthCheck\Checks\AppDataLocationFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\DownloadClientCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\DroneFactoryCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\HealthCheckFixtureExtentions.cs" />
|
||||
<Compile Include="HealthCheck\Checks\HealthCheckFixtureExtensions.cs" />
|
||||
<Compile Include="HealthCheck\Checks\ImportMechanismCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\IndexerCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\IndexerSearchCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\IndexerRssCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\MonoVersionCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\IndexerStatusCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\RootFolderCheckFixture.cs" />
|
||||
@@ -380,7 +379,7 @@
|
||||
<Compile Include="TvTests\RefreshSeriesServiceFixture.cs" />
|
||||
<Compile Include="TvTests\EpisodeMonitoredServiceTests\SetEpisodeMontitoredFixture.cs" />
|
||||
<Compile Include="TvTests\SeriesRepositoryTests\SeriesRepositoryFixture.cs" />
|
||||
<Compile Include="TvTests\SeriesServiceTests\AddSeriesFixture.cs" />
|
||||
<Compile Include="TvTests\AddSeriesFixture.cs" />
|
||||
<Compile Include="TvTests\SeriesServiceTests\UpdateMultipleSeriesFixture.cs" />
|
||||
<Compile Include="TvTests\SeriesServiceTests\UpdateSeriesFixture.cs" />
|
||||
<Compile Include="TvTests\SeriesTitleNormalizerFixture.cs" />
|
||||
@@ -420,6 +419,10 @@
|
||||
<Link>sqlite3.dll</Link>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Files\Indexers\TorrentRss\AlphaRatio.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Files\Indexers\TorrentRss\LimeTorrents.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
@@ -54,6 +54,8 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
|
||||
[TestCase("2 Broke Girls - S01E01 - Pilot.en.sub", Language.English)]
|
||||
[TestCase("2 Broke Girls - S01E01 - Pilot.eng.sub", Language.English)]
|
||||
[TestCase("2 Broke Girls - S01E01 - Pilot.English.sub", Language.English)]
|
||||
[TestCase("2 Broke Girls - S01E01 - Pilot.english.sub", Language.English)]
|
||||
[TestCase("2 Broke Girls - S01E01 - Pilot.sub", Language.Unknown)]
|
||||
public void should_parse_subtitle_language(string fileName, Language language)
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||
_parsedEpisodeInfo = new ParsedEpisodeInfo
|
||||
{
|
||||
SeriesTitle = _series.Title,
|
||||
SeriesTitleInfo = new SeriesTitleInfo(),
|
||||
SeasonNumber = 1,
|
||||
EpisodeNumbers = new[] { 1 }
|
||||
};
|
||||
@@ -150,6 +151,28 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_FindByTitle_using_year_when_FindByTitle_matching_fails()
|
||||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
_parsedEpisodeInfo.SeriesTitleInfo = new SeriesTitleInfo
|
||||
{
|
||||
Title = "Series Title 2017",
|
||||
TitleWithoutYear = "Series Title",
|
||||
Year = 2017
|
||||
};
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Setup(s => s.FindByTitle(_parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear, _parsedEpisodeInfo.SeriesTitleInfo.Year))
|
||||
.Returns(_series);
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>(), It.IsAny<int>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_FindByTvdbId_when_search_criteria_and_FindByTitle_matching_fails()
|
||||
{
|
||||
|
||||
@@ -127,6 +127,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
[TestCase("this.is.not.happening.2015.0308-yestv", "this is not happening 2015", 3, 8)]
|
||||
[TestCase("Jeopardy - S2016E231", "Jeopardy", 2016, 231)]
|
||||
[TestCase("Jeopardy - 2016x231", "Jeopardy", 2016, 231)]
|
||||
[TestCase("Shortland.Street.S26E022.HDTV.x264-FiHTV", "Shortland Street", 26, 22)]
|
||||
//[TestCase("", "", 0, 0)]
|
||||
public void should_parse_single_episode(string postTitle, string title, int seasonNumber, int episodeNumber)
|
||||
{
|
||||
|
||||
@@ -75,5 +75,17 @@ namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests
|
||||
|
||||
Mocker.GetMock<IDiskProvider>().Verify(v => v.FileSetLastWriteTime(@"C:\Test\Recycle Bin\S01E01.avi".AsOsAgnostic(), It.IsAny<DateTime>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_subfolder_when_passed_in()
|
||||
{
|
||||
WithRecycleBin();
|
||||
|
||||
var path = @"C:\Test\TV\30 Rock\S01E01.avi".AsOsAgnostic();
|
||||
|
||||
Mocker.Resolve<RecycleBinProvider>().DeleteFile(path, "30 Rock");
|
||||
|
||||
Mocker.GetMock<IDiskTransferService>().Verify(v => v.TransferFile(path, @"C:\Test\Recycle Bin\30 Rock\S01E01.avi".AsOsAgnostic(), TransferMode.Move, false, true), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
132
src/NzbDrone.Core.Test/TvTests/AddSeriesFixture.cs
Normal file
132
src/NzbDrone.Core.Test/TvTests/AddSeriesFixture.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.TvTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AddSeriesFixture : CoreTest<AddSeriesService>
|
||||
{
|
||||
private Series _fakeSeries;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_fakeSeries = Builder<Series>
|
||||
.CreateNew()
|
||||
.With(s => s.Path = null)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private void GivenValidSeries(int tvdbId)
|
||||
{
|
||||
Mocker.GetMock<IProvideSeriesInfo>()
|
||||
.Setup(s => s.GetSeriesInfo(tvdbId))
|
||||
.Returns(new Tuple<Series, List<Episode>>(_fakeSeries, new List<Episode>()));
|
||||
}
|
||||
|
||||
private void GivenValidPath()
|
||||
{
|
||||
Mocker.GetMock<IBuildFileNames>()
|
||||
.Setup(s => s.GetSeriesFolder(It.IsAny<Series>(), null))
|
||||
.Returns<Series, NamingConfig>((c, n) => c.Title);
|
||||
|
||||
Mocker.GetMock<IAddSeriesValidator>()
|
||||
.Setup(s => s.Validate(It.IsAny<Series>()))
|
||||
.Returns(new ValidationResult());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_add_a_series_without_passing_in_title()
|
||||
{
|
||||
var newSeries = new Series
|
||||
{
|
||||
TvdbId = 1,
|
||||
RootFolderPath = @"C:\Test\TV"
|
||||
};
|
||||
|
||||
GivenValidSeries(newSeries.TvdbId);
|
||||
GivenValidPath();
|
||||
|
||||
var series = Subject.AddSeries(newSeries);
|
||||
|
||||
series.Title.Should().Be(_fakeSeries.Title);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_have_proper_path()
|
||||
{
|
||||
var newSeries = new Series
|
||||
{
|
||||
TvdbId = 1,
|
||||
RootFolderPath = @"C:\Test\TV"
|
||||
};
|
||||
|
||||
GivenValidSeries(newSeries.TvdbId);
|
||||
GivenValidPath();
|
||||
|
||||
var series = Subject.AddSeries(newSeries);
|
||||
|
||||
series.Path.Should().Be(Path.Combine(newSeries.RootFolderPath, _fakeSeries.Title));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_if_series_validation_fails()
|
||||
{
|
||||
var newSeries = new Series
|
||||
{
|
||||
TvdbId = 1,
|
||||
Path = @"C:\Test\TV\Title1"
|
||||
};
|
||||
|
||||
GivenValidSeries(newSeries.TvdbId);
|
||||
|
||||
Mocker.GetMock<IAddSeriesValidator>()
|
||||
.Setup(s => s.Validate(It.IsAny<Series>()))
|
||||
.Returns(new ValidationResult(new List<ValidationFailure>
|
||||
{
|
||||
new ValidationFailure("Path", "Test validation failure")
|
||||
}));
|
||||
|
||||
Assert.Throws<ValidationException>(() => Subject.AddSeries(newSeries));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_if_series_cannot_be_found()
|
||||
{
|
||||
var newSeries = new Series
|
||||
{
|
||||
TvdbId = 1,
|
||||
Path = @"C:\Test\TV\Title1"
|
||||
};
|
||||
|
||||
Mocker.GetMock<IProvideSeriesInfo>()
|
||||
.Setup(s => s.GetSeriesInfo(newSeries.TvdbId))
|
||||
.Throws(new SeriesNotFoundException(newSeries.TvdbId));
|
||||
|
||||
Mocker.GetMock<IAddSeriesValidator>()
|
||||
.Setup(s => s.Validate(It.IsAny<Series>()))
|
||||
.Returns(new ValidationResult(new List<ValidationFailure>
|
||||
{
|
||||
new ValidationFailure("Path", "Test validation failure")
|
||||
}));
|
||||
|
||||
Assert.Throws<ValidationException>(() => Subject.AddSeries(newSeries));
|
||||
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AutoMoq" version="1.8.1.0" targetFramework="net40" />
|
||||
<package id="CommonServiceLocator" version="1.0" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="4.18.0" targetFramework="net40" />
|
||||
<package id="CommonServiceLocator" version="1.3" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="4.19.0" targetFramework="net40" />
|
||||
<package id="FluentMigrator" version="1.6.2" targetFramework="net40" />
|
||||
<package id="FluentMigrator.Runner" version="1.6.2" targetFramework="net40" />
|
||||
<package id="FluentValidation" version="6.2.1.0" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NBuilder" version="4.0.0" targetFramework="net40" />
|
||||
<package id="NCrunch.Framework" version="3.2.0.3" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.1" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.6.0" targetFramework="net40" />
|
||||
<package id="Prowlin" version="0.9.4456.26422" targetFramework="net40" />
|
||||
<package id="Unity" version="2.1.505.2" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -203,9 +203,16 @@ namespace NzbDrone.Core.Configuration
|
||||
set { SetValue("EnableMediaInfo", value); }
|
||||
}
|
||||
|
||||
public bool ImportExtraFiles
|
||||
{
|
||||
get { return GetValueBoolean("ImportExtraFiles", false); }
|
||||
|
||||
set { SetValue("ImportExtraFiles", value); }
|
||||
}
|
||||
|
||||
public string ExtraFileExtensions
|
||||
{
|
||||
get { return GetValue("ExtraFileExtensions", ""); }
|
||||
get { return GetValue("ExtraFileExtensions", "srt"); }
|
||||
|
||||
set { SetValue("ExtraFileExtensions", value); }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Common.Http.Proxy;
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace NzbDrone.Core.Configuration
|
||||
bool SkipFreeSpaceCheckWhenImporting { get; set; }
|
||||
bool CopyUsingHardlinks { get; set; }
|
||||
bool EnableMediaInfo { get; set; }
|
||||
bool ImportExtraFiles { get; set; }
|
||||
string ExtraFileExtensions { get; set; }
|
||||
|
||||
//Permissions (Media Management)
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(108)]
|
||||
public class fix_extra_file_extension : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
// Delete extraneous files without extensions that Sonarr found previously,
|
||||
// these will be blocked from importing as well.
|
||||
Execute.Sql("DELETE FROM ExtraFiles WHERE TRIM(Extension) = ''");
|
||||
|
||||
Execute.WithConnection(FixExtraFileExtension);
|
||||
}
|
||||
|
||||
private void FixExtraFileExtension(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
FixExtraFileExtensionForTable(conn, tran, "ExtraFiles");
|
||||
FixExtraFileExtensionForTable(conn, tran, "SubtitleFiles");
|
||||
}
|
||||
|
||||
private void FixExtraFileExtensionForTable(IDbConnection conn, IDbTransaction tran, string table)
|
||||
{
|
||||
|
||||
using (var cmd = conn.CreateCommand())
|
||||
{
|
||||
cmd.Transaction = tran;
|
||||
cmd.CommandText = $"SELECT Id, RelativePath FROM {table}";
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = reader.GetInt32(0);
|
||||
var relativePath = reader.GetString(1);
|
||||
var extension = relativePath.Substring(relativePath.LastIndexOf(".", StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
using (var updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = $"UPDATE {table} SET Extension = ? WHERE Id = ?";
|
||||
updateCmd.AddParameter(extension);
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(109)]
|
||||
public class import_extra_files : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(ImportExtraFiles);
|
||||
}
|
||||
|
||||
private void ImportExtraFiles(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
|
||||
using (var cmd = conn.CreateCommand())
|
||||
{
|
||||
cmd.Transaction = tran;
|
||||
cmd.CommandText = "SELECT Value from Config WHERE Key = 'extrafileextensions'";
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
var value = reader.GetString(0);
|
||||
|
||||
if (value.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
using (var insertCmd = conn.CreateCommand())
|
||||
{
|
||||
insertCmd.Transaction = tran;
|
||||
insertCmd.CommandText = "INSERT INTO Config (Key, Value) VALUES('importextrafiles', 'True')";
|
||||
insertCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(110)]
|
||||
public class fix_extra_files_config : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(FixExtraFilesConfig);
|
||||
}
|
||||
|
||||
private void FixExtraFilesConfig(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
string extraFileExtensions;
|
||||
string importExtraFiles;
|
||||
|
||||
using (var cmd = conn.CreateCommand())
|
||||
{
|
||||
cmd.Transaction = tran;
|
||||
cmd.CommandText = "SELECT Value FROM Config WHERE Key = 'extrafileextensions'";
|
||||
|
||||
extraFileExtensions = (string)cmd.ExecuteScalar();
|
||||
}
|
||||
|
||||
using (var cmd = conn.CreateCommand())
|
||||
{
|
||||
cmd.Transaction = tran;
|
||||
cmd.CommandText = "SELECT Value FROM Config WHERE Key = 'importextrafiles'";
|
||||
|
||||
importExtraFiles = (string)cmd.ExecuteScalar();
|
||||
}
|
||||
|
||||
if (importExtraFiles == "1" || importExtraFiles == "True")
|
||||
{
|
||||
using (var insertCmd = conn.CreateCommand())
|
||||
{
|
||||
insertCmd.Transaction = tran;
|
||||
insertCmd.CommandText = "UPDATE Config SET Value = 'True' WHERE Key = 'importextrafiles'";
|
||||
insertCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
else if (extraFileExtensions.IsNullOrWhiteSpace())
|
||||
{
|
||||
using (var insertCmd = conn.CreateCommand())
|
||||
{
|
||||
insertCmd.Transaction = tran;
|
||||
insertCmd.CommandText = "UPDATE Config SET Value = 'srt' WHERE Key = 'extrafileextensions'";
|
||||
insertCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
@@ -22,8 +22,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
||||
{
|
||||
_logger.Debug("Comparing file quality with report. Existing file is {0}", file.Quality);
|
||||
if (file == null)
|
||||
{
|
||||
_logger.Debug("File is no longer available, skipping this file.");
|
||||
continue;
|
||||
}
|
||||
|
||||
_logger.Debug("Comparing file quality with report. Existing file is {0}", file.Quality);
|
||||
|
||||
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Series.Profile, file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
@@ -22,6 +22,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
||||
{
|
||||
if(file == null)
|
||||
{
|
||||
_logger.Debug("File is no longer available, skipping this file.");
|
||||
continue;
|
||||
}
|
||||
|
||||
_logger.Debug("Comparing file quality with report. Existing file is {0}", file.Quality);
|
||||
|
||||
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.Profile, file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||
|
||||
@@ -103,7 +103,8 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
|
||||
Status = item.Status,
|
||||
|
||||
IsReadOnly = Settings.ReadOnly
|
||||
CanMoveFiles = !Settings.ReadOnly,
|
||||
CanBeRemoved = !Settings.ReadOnly
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,10 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
|
||||
OutputPath = item.OutputPath,
|
||||
|
||||
Status = item.Status
|
||||
Status = item.Status,
|
||||
|
||||
CanBeRemoved = true,
|
||||
CanMoveFiles = true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,14 +138,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.
|
||||
if (torrent.IsAutoManaged && torrent.StopAtRatio && torrent.Ratio >= torrent.StopRatio && torrent.State == DelugeTorrentStatus.Paused)
|
||||
{
|
||||
item.IsReadOnly = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.IsReadOnly = true;
|
||||
}
|
||||
item.CanMoveFiles = item.CanBeRemoved = (torrent.IsAutoManaged && torrent.StopAtRatio && torrent.Ratio >= torrent.StopRatio && torrent.State == DelugeTorrentStatus.Paused);
|
||||
|
||||
items.Add(item);
|
||||
}
|
||||
@@ -178,7 +171,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
{
|
||||
status.OutputRootFolders = new List<OsPath> { _remotePathMappingService.RemapRemoteToLocal(Settings.Host, destDir) };
|
||||
}
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
public class DiskStationApiInfo
|
||||
{
|
||||
{
|
||||
private string _path;
|
||||
|
||||
public int MaxVersion { get; set; }
|
||||
|
||||
public int MinVersion { get; set; }
|
||||
|
||||
public DiskStationApi Type { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public bool NeedsAuthentication { get; set; }
|
||||
|
||||
public string Path
|
||||
{
|
||||
get { return _path; }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
||||
|
||||
@@ -13,20 +14,19 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||
|
||||
public class DSMInfoProxy : DiskStationProxyBase, IDSMInfoProxy
|
||||
{
|
||||
public DSMInfoProxy(IHttpClient httpClient, Logger logger) :
|
||||
base(httpClient, logger)
|
||||
public DSMInfoProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger) :
|
||||
base(DiskStationApi.DSMInfo, "SYNO.DSM.Info", httpClient, cacheManager, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public string GetSerialNumber(DownloadStationSettings settings)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>() {
|
||||
{ "api", "SYNO.DSM.Info" },
|
||||
{ "version", "2" },
|
||||
{ "method", "getinfo" }
|
||||
};
|
||||
var info = GetApiInfo(settings);
|
||||
|
||||
var requestBuilder = BuildRequest(settings, "getinfo", info.MinVersion);
|
||||
|
||||
var response = ProcessRequest<DSMInfoResponse>(requestBuilder, "get serial number", settings);
|
||||
|
||||
var response = ProcessRequest<DSMInfoResponse>(DiskStationApi.DSMInfo, arguments, settings, "get serial number");
|
||||
return response.Data.SerialNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||
{
|
||||
public abstract class DiskStationProxyBase
|
||||
public interface IDiskStationProxy
|
||||
{
|
||||
private static readonly Dictionary<DiskStationApi, string> Resources;
|
||||
DiskStationApiInfo GetApiInfo(DownloadStationSettings settings);
|
||||
}
|
||||
|
||||
public abstract class DiskStationProxyBase : IDiskStationProxy
|
||||
{
|
||||
protected readonly Logger _logger;
|
||||
|
||||
private readonly IHttpClient _httpClient;
|
||||
protected readonly Logger _logger;
|
||||
private bool _authenticated;
|
||||
private readonly ICached<DiskStationApiInfo> _infoCache;
|
||||
private readonly ICached<string> _sessionCache;
|
||||
private readonly DiskStationApi _apiType;
|
||||
private readonly string _apiName;
|
||||
|
||||
private static readonly DiskStationApiInfo _apiInfo;
|
||||
|
||||
static DiskStationProxyBase()
|
||||
{
|
||||
Resources = new Dictionary<DiskStationApi, string>
|
||||
_apiInfo = new DiskStationApiInfo()
|
||||
{
|
||||
{ DiskStationApi.Info, "query.cgi" }
|
||||
Type = DiskStationApi.Info,
|
||||
Name = "SYNO.API.Info",
|
||||
Path = "query.cgi",
|
||||
MaxVersion = 1,
|
||||
MinVersion = 1,
|
||||
NeedsAuthentication = false
|
||||
};
|
||||
}
|
||||
|
||||
public DiskStationProxyBase(IHttpClient httpClient, Logger logger)
|
||||
public DiskStationProxyBase(DiskStationApi apiType,
|
||||
string apiName,
|
||||
IHttpClient httpClient,
|
||||
ICacheManager cacheManager,
|
||||
Logger logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_logger = logger;
|
||||
_infoCache = cacheManager.GetCache<DiskStationApiInfo>(typeof(DiskStationProxyBase), "apiInfo");
|
||||
_sessionCache = cacheManager.GetCache<string>(typeof(DiskStationProxyBase), "sessions");
|
||||
_apiType = apiType;
|
||||
_apiName = apiName;
|
||||
}
|
||||
|
||||
|
||||
protected DiskStationResponse<object> ProcessRequest(DiskStationApi api,
|
||||
Dictionary<string, object> arguments,
|
||||
DownloadStationSettings settings,
|
||||
string operation,
|
||||
HttpMethod method = HttpMethod.GET)
|
||||
private string GenerateSessionCacheKey(DownloadStationSettings settings)
|
||||
{
|
||||
return ProcessRequest<object>(api, arguments, settings, operation, method);
|
||||
return $"{settings.Username}@{settings.Host}:{settings.Port}";
|
||||
}
|
||||
|
||||
protected DiskStationResponse<T> ProcessRequest<T>(DiskStationApi api,
|
||||
Dictionary<string, object> arguments,
|
||||
DownloadStationSettings settings,
|
||||
string operation,
|
||||
HttpMethod method = HttpMethod.GET,
|
||||
int retries = 0) where T : new()
|
||||
protected DiskStationResponse<T> ProcessRequest<T>(HttpRequestBuilder requestBuilder,
|
||||
string operation,
|
||||
DownloadStationSettings settings) where T : new()
|
||||
{
|
||||
if (retries == 5)
|
||||
{
|
||||
throw new DownloadClientException("Try to process same request more than 5 times");
|
||||
}
|
||||
return ProcessRequest<T>(requestBuilder, operation, _apiType, settings);
|
||||
}
|
||||
|
||||
if (!_authenticated && api != DiskStationApi.Info && api != DiskStationApi.DSMInfo)
|
||||
{
|
||||
AuthenticateClient(settings);
|
||||
}
|
||||
|
||||
var request = BuildRequest(settings, api, arguments, method);
|
||||
private DiskStationResponse<T> ProcessRequest<T>(HttpRequestBuilder requestBuilder,
|
||||
string operation,
|
||||
DiskStationApi api,
|
||||
DownloadStationSettings settings) where T : new()
|
||||
{
|
||||
var request = requestBuilder.Build();
|
||||
var response = _httpClient.Execute(request);
|
||||
|
||||
_logger.Debug("Trying to {0}", operation);
|
||||
@@ -72,15 +86,19 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||
}
|
||||
else
|
||||
{
|
||||
if (responseContent.Error.SessionError)
|
||||
{
|
||||
_authenticated = false;
|
||||
return ProcessRequest<T>(api, arguments, settings, operation, method, retries++);
|
||||
}
|
||||
|
||||
var msg = $"Failed to {operation}. Reason: {responseContent.Error.GetMessage(api)}";
|
||||
_logger.Error(msg);
|
||||
|
||||
if (responseContent.Error.SessionError)
|
||||
{
|
||||
_sessionCache.Remove(GenerateSessionCacheKey(settings));
|
||||
|
||||
if (responseContent.Error.Code == 105)
|
||||
{
|
||||
throw new DownloadClientAuthenticationException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
throw new DownloadClientException(msg);
|
||||
}
|
||||
}
|
||||
@@ -90,124 +108,126 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||
}
|
||||
}
|
||||
|
||||
private void AuthenticateClient(DownloadStationSettings settings)
|
||||
private string AuthenticateClient(DownloadStationSettings settings)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>
|
||||
{
|
||||
{ "api", "SYNO.API.Auth" },
|
||||
{ "version", "1" },
|
||||
{ "method", "login" },
|
||||
{ "account", settings.Username },
|
||||
{ "passwd", settings.Password },
|
||||
{ "format", "cookie" },
|
||||
{ "session", "DownloadStation" },
|
||||
};
|
||||
var authInfo = GetApiInfo(DiskStationApi.Auth, settings);
|
||||
|
||||
var authLoginRequest = BuildRequest(settings, DiskStationApi.Auth, arguments, HttpMethod.GET);
|
||||
authLoginRequest.StoreResponseCookie = true;
|
||||
var requestBuilder = BuildRequest(settings, authInfo, "login", 2);
|
||||
requestBuilder.AddQueryParam("account", settings.Username);
|
||||
requestBuilder.AddQueryParam("passwd", settings.Password);
|
||||
requestBuilder.AddQueryParam("format", "sid");
|
||||
requestBuilder.AddQueryParam("session", "DownloadStation");
|
||||
|
||||
var response = _httpClient.Execute(authLoginRequest);
|
||||
var authResponse = ProcessRequest<DiskStationAuthResponse>(requestBuilder, "login", DiskStationApi.Auth, settings);
|
||||
|
||||
var downloadStationResponse = Json.Deserialize<DiskStationResponse<DiskStationAuthResponse>>(response.Content);
|
||||
|
||||
var authResponse = Json.Deserialize<DiskStationResponse<DiskStationAuthResponse>>(response.Content);
|
||||
|
||||
_authenticated = authResponse.Success;
|
||||
|
||||
if (!_authenticated)
|
||||
{
|
||||
throw new DownloadClientAuthenticationException(downloadStationResponse.Error.GetMessage(DiskStationApi.Auth));
|
||||
}
|
||||
return authResponse.Data.SId;
|
||||
}
|
||||
|
||||
private HttpRequest BuildRequest(DownloadStationSettings settings, DiskStationApi api, Dictionary<string, object> arguments, HttpMethod method)
|
||||
protected HttpRequestBuilder BuildRequest(DownloadStationSettings settings, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
|
||||
{
|
||||
if (!Resources.ContainsKey(api))
|
||||
{
|
||||
GetApiVersion(settings, api);
|
||||
}
|
||||
var info = GetApiInfo(_apiType, settings);
|
||||
|
||||
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{Resources[api]}");
|
||||
requestBuilder.Method = method;
|
||||
return BuildRequest(settings, info, methodName, apiVersion, httpVerb);
|
||||
}
|
||||
|
||||
private HttpRequestBuilder BuildRequest(DownloadStationSettings settings, DiskStationApiInfo apiInfo, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
|
||||
{
|
||||
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{apiInfo.Path}");
|
||||
requestBuilder.Method = httpVerb;
|
||||
requestBuilder.LogResponseContent = true;
|
||||
requestBuilder.SuppressHttpError = true;
|
||||
requestBuilder.AllowAutoRedirect = false;
|
||||
requestBuilder.Headers.ContentType = "application/json";
|
||||
|
||||
if (requestBuilder.Method == HttpMethod.POST)
|
||||
if (apiVersion < apiInfo.MinVersion || apiVersion > apiInfo.MaxVersion)
|
||||
{
|
||||
if (api == DiskStationApi.DownloadStationTask && arguments.ContainsKey("file"))
|
||||
{
|
||||
requestBuilder.Headers.ContentType = "multipart/form-data";
|
||||
throw new ArgumentOutOfRangeException(nameof(apiVersion));
|
||||
}
|
||||
|
||||
foreach (var arg in arguments)
|
||||
{
|
||||
if (arg.Key == "file")
|
||||
{
|
||||
Dictionary<string, object> file = (Dictionary<string, object>)arg.Value;
|
||||
requestBuilder.AddFormUpload(arg.Key, file["name"].ToString(), (byte[])file["data"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
requestBuilder.AddFormParameter(arg.Key, arg.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (httpVerb == HttpMethod.POST)
|
||||
{
|
||||
if (apiInfo.NeedsAuthentication)
|
||||
{
|
||||
requestBuilder.Headers.ContentType = "application/json";
|
||||
requestBuilder.AddFormParameter("_sid", _sessionCache.Get(GenerateSessionCacheKey(settings), () => AuthenticateClient(settings), TimeSpan.FromHours(6)));
|
||||
}
|
||||
|
||||
requestBuilder.AddFormParameter("api", apiInfo.Name);
|
||||
requestBuilder.AddFormParameter("version", apiVersion);
|
||||
requestBuilder.AddFormParameter("method", methodName);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var arg in arguments)
|
||||
if (apiInfo.NeedsAuthentication)
|
||||
{
|
||||
requestBuilder.AddQueryParam(arg.Key, arg.Value);
|
||||
requestBuilder.AddQueryParam("_sid", _sessionCache.Get(GenerateSessionCacheKey(settings), () => AuthenticateClient(settings), TimeSpan.FromHours(6)));
|
||||
}
|
||||
|
||||
requestBuilder.AddQueryParam("api", apiInfo.Name);
|
||||
requestBuilder.AddQueryParam("version", apiVersion);
|
||||
requestBuilder.AddQueryParam("method", methodName);
|
||||
}
|
||||
|
||||
return requestBuilder;
|
||||
}
|
||||
|
||||
private string GenerateInfoCacheKey(DownloadStationSettings settings, DiskStationApi api)
|
||||
{
|
||||
return $"{settings.Host}:{settings.Port}->{api}";
|
||||
}
|
||||
|
||||
private void UpdateApiInfo(DownloadStationSettings settings)
|
||||
{
|
||||
var apis = new Dictionary<string, DiskStationApi>()
|
||||
{
|
||||
{ "SYNO.API.Auth", DiskStationApi.Auth },
|
||||
{ _apiName, _apiType }
|
||||
};
|
||||
|
||||
var requestBuilder = BuildRequest(settings, _apiInfo, "query", _apiInfo.MinVersion);
|
||||
requestBuilder.AddQueryParam("query", string.Join(",", apis.Keys));
|
||||
|
||||
var infoResponse = ProcessRequest<DiskStationApiInfoResponse>(requestBuilder, "get api info", _apiInfo.Type, settings);
|
||||
|
||||
foreach (var data in infoResponse.Data)
|
||||
{
|
||||
if (apis.ContainsKey(data.Key))
|
||||
{
|
||||
data.Value.Name = data.Key;
|
||||
data.Value.Type = apis[data.Key];
|
||||
data.Value.NeedsAuthentication = apis[data.Key] != DiskStationApi.Auth;
|
||||
|
||||
_infoCache.Set(GenerateInfoCacheKey(settings, apis[data.Key]), data.Value, TimeSpan.FromHours(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DiskStationApiInfo GetApiInfo(DiskStationApi api, DownloadStationSettings settings)
|
||||
{
|
||||
if (api == DiskStationApi.Info)
|
||||
{
|
||||
return _apiInfo;
|
||||
}
|
||||
|
||||
var key = GenerateInfoCacheKey(settings, api);
|
||||
var info = _infoCache.Find(key);
|
||||
|
||||
if (info == null)
|
||||
{
|
||||
UpdateApiInfo(settings);
|
||||
info = _infoCache.Find(key);
|
||||
|
||||
if (info == null)
|
||||
{
|
||||
throw new DownloadClientException("Info of {0} not found on {1}:{2}", api, settings.Host, settings.Port);
|
||||
}
|
||||
}
|
||||
|
||||
return requestBuilder.Build();
|
||||
return info;
|
||||
}
|
||||
|
||||
protected IEnumerable<int> GetApiVersion(DownloadStationSettings settings, DiskStationApi api)
|
||||
public DiskStationApiInfo GetApiInfo(DownloadStationSettings settings)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>
|
||||
{
|
||||
{ "api", "SYNO.API.Info" },
|
||||
{ "version", "1" },
|
||||
{ "method", "query" },
|
||||
{ "query", "SYNO.API.Auth, SYNO.DownloadStation.Info, SYNO.DownloadStation.Task, SYNO.FileStation.List, SYNO.DSM.Info" },
|
||||
};
|
||||
|
||||
var infoResponse = ProcessRequest<DiskStationApiInfoResponse>(DiskStationApi.Info, arguments, settings, "Get api version");
|
||||
|
||||
//TODO: Refactor this into more elegant code
|
||||
var infoResponeDSAuth = infoResponse.Data["SYNO.API.Auth"];
|
||||
var infoResponeDSInfo = infoResponse.Data["SYNO.DownloadStation.Info"];
|
||||
var infoResponeDSTask = infoResponse.Data["SYNO.DownloadStation.Task"];
|
||||
var infoResponseFSList = infoResponse.Data["SYNO.FileStation.List"];
|
||||
var infoResponseDSMInfo = infoResponse.Data["SYNO.DSM.Info"];
|
||||
|
||||
Resources[DiskStationApi.Auth] = infoResponeDSAuth.Path;
|
||||
Resources[DiskStationApi.DownloadStationInfo] = infoResponeDSInfo.Path;
|
||||
Resources[DiskStationApi.DownloadStationTask] = infoResponeDSTask.Path;
|
||||
Resources[DiskStationApi.FileStationList] = infoResponseFSList.Path;
|
||||
Resources[DiskStationApi.DSMInfo] = infoResponseDSMInfo.Path;
|
||||
|
||||
switch (api)
|
||||
{
|
||||
case DiskStationApi.Auth:
|
||||
return Enumerable.Range(infoResponeDSAuth.MinVersion, infoResponeDSAuth.MaxVersion - infoResponeDSAuth.MinVersion + 1);
|
||||
case DiskStationApi.DownloadStationInfo:
|
||||
return Enumerable.Range(infoResponeDSInfo.MinVersion, infoResponeDSInfo.MaxVersion - infoResponeDSInfo.MinVersion + 1);
|
||||
case DiskStationApi.DownloadStationTask:
|
||||
return Enumerable.Range(infoResponeDSTask.MinVersion, infoResponeDSTask.MaxVersion - infoResponeDSTask.MinVersion + 1);
|
||||
case DiskStationApi.FileStationList:
|
||||
return Enumerable.Range(infoResponseFSList.MinVersion, infoResponseFSList.MaxVersion - infoResponseFSList.MinVersion + 1);
|
||||
case DiskStationApi.DSMInfo:
|
||||
return Enumerable.Range(infoResponseDSMInfo.MinVersion, infoResponseDSMInfo.MaxVersion - infoResponseDSMInfo.MinVersion + 1);
|
||||
default:
|
||||
throw new DownloadClientException("Api not implemented");
|
||||
}
|
||||
return GetApiInfo(_apiType, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Cache;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||
{
|
||||
public interface IDownloadStationInfoProxy : IDiskStationProxy
|
||||
{
|
||||
Dictionary<string, object> GetConfig(DownloadStationSettings settings);
|
||||
}
|
||||
|
||||
public class DownloadStationInfoProxy : DiskStationProxyBase, IDownloadStationInfoProxy
|
||||
{
|
||||
public DownloadStationInfoProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger) :
|
||||
base(DiskStationApi.DownloadStationInfo, "SYNO.DownloadStation.Info", httpClient, cacheManager, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public Dictionary<string, object> GetConfig(DownloadStationSettings settings)
|
||||
{
|
||||
var requestBuilder = BuildRequest(settings, "getConfig", 1);
|
||||
|
||||
var response = ProcessRequest<Dictionary<string, object>>(requestBuilder, "get config", settings);
|
||||
|
||||
return response.Data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||
{
|
||||
public interface IDownloadStationProxy
|
||||
{
|
||||
IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings);
|
||||
Dictionary<string, object> GetConfig(DownloadStationSettings settings);
|
||||
void RemoveTask(string downloadId, DownloadStationSettings settings);
|
||||
void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings);
|
||||
void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings);
|
||||
IEnumerable<int> GetApiVersion(DownloadStationSettings settings);
|
||||
}
|
||||
|
||||
public class DownloadStationProxy : DiskStationProxyBase, IDownloadStationProxy
|
||||
{
|
||||
public DownloadStationProxy(IHttpClient httpClient, Logger logger)
|
||||
: base(httpClient, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>
|
||||
{
|
||||
{ "api", "SYNO.DownloadStation.Task" },
|
||||
{ "version", "2" },
|
||||
{ "method", "create" }
|
||||
};
|
||||
|
||||
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
arguments.Add("destination", downloadDirectory);
|
||||
}
|
||||
|
||||
arguments.Add("file", new Dictionary<string, object>() { { "name", filename }, { "data", data } });
|
||||
|
||||
var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"add task from data {filename}", HttpMethod.POST);
|
||||
}
|
||||
|
||||
public void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>
|
||||
{
|
||||
{ "api", "SYNO.DownloadStation.Task" },
|
||||
{ "version", "3" },
|
||||
{ "method", "create" },
|
||||
{ "uri", url }
|
||||
};
|
||||
|
||||
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
arguments.Add("destination", downloadDirectory);
|
||||
}
|
||||
|
||||
var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"add task from url {url}");
|
||||
}
|
||||
|
||||
public IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>
|
||||
{
|
||||
{ "api", "SYNO.DownloadStation.Task" },
|
||||
{ "version", "1" },
|
||||
{ "method", "list" },
|
||||
{ "additional", "detail,transfer" }
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var response = ProcessRequest<DownloadStationTaskInfoResponse>(DiskStationApi.DownloadStationTask, arguments, settings, "get tasks");
|
||||
|
||||
return response.Data.Tasks;
|
||||
}
|
||||
catch (DownloadClientException e)
|
||||
{
|
||||
_logger.Error(e);
|
||||
return new List<DownloadStationTask>();
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, object> GetConfig(DownloadStationSettings settings)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>
|
||||
{
|
||||
{ "api", "SYNO.DownloadStation.Info" },
|
||||
{ "version", "1" },
|
||||
{ "method", "getconfig" }
|
||||
};
|
||||
|
||||
var response = ProcessRequest<Dictionary<string, object>>(DiskStationApi.DownloadStationInfo, arguments, settings, "get config");
|
||||
|
||||
return response.Data;
|
||||
}
|
||||
|
||||
public void RemoveTask(string downloadId, DownloadStationSettings settings)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>
|
||||
{
|
||||
{ "api", "SYNO.DownloadStation.Task" },
|
||||
{ "version", "1" },
|
||||
{ "method", "delete" },
|
||||
{ "id", downloadId },
|
||||
{ "force_complete", false }
|
||||
};
|
||||
|
||||
var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"remove item {downloadId}");
|
||||
}
|
||||
|
||||
public IEnumerable<int> GetApiVersion(DownloadStationSettings settings)
|
||||
{
|
||||
return base.GetApiVersion(settings, DiskStationApi.DownloadStationInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||
{
|
||||
public interface IDownloadStationTaskProxy : IDiskStationProxy
|
||||
{
|
||||
IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings);
|
||||
void RemoveTask(string downloadId, DownloadStationSettings settings);
|
||||
void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings);
|
||||
void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings);
|
||||
}
|
||||
|
||||
public class DownloadStationTaskProxy : DiskStationProxyBase, IDownloadStationTaskProxy
|
||||
{
|
||||
public DownloadStationTaskProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger)
|
||||
: base(DiskStationApi.DownloadStationTask, "SYNO.DownloadStation.Task", httpClient, cacheManager, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings)
|
||||
{
|
||||
var requestBuilder = BuildRequest(settings, "create", 2, HttpMethod.POST);
|
||||
|
||||
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder.AddFormParameter("destination", downloadDirectory);
|
||||
}
|
||||
|
||||
requestBuilder.AddFormUpload("file", filename, data);
|
||||
|
||||
var response = ProcessRequest<object>(requestBuilder, $"add task from data {filename}", settings);
|
||||
}
|
||||
|
||||
public void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings)
|
||||
{
|
||||
var requestBuilder = BuildRequest(settings, "create", 3);
|
||||
requestBuilder.AddQueryParam("uri", url);
|
||||
|
||||
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder.AddQueryParam("destination", downloadDirectory);
|
||||
}
|
||||
|
||||
var response = ProcessRequest<object>(requestBuilder, $"add task from url {url}", settings);
|
||||
}
|
||||
|
||||
public IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestBuilder = BuildRequest(settings, "list", 1);
|
||||
requestBuilder.AddQueryParam("additional", "detail,transfer");
|
||||
|
||||
var response = ProcessRequest<DownloadStationTaskInfoResponse>(requestBuilder, "get tasks", settings);
|
||||
|
||||
return response.Data.Tasks;
|
||||
}
|
||||
catch (DownloadClientException e)
|
||||
{
|
||||
_logger.Error(e);
|
||||
return new List<DownloadStationTask>();
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveTask(string downloadId, DownloadStationSettings settings)
|
||||
{
|
||||
var requestBuilder = BuildRequest(settings, "delete", 1);
|
||||
requestBuilder.AddQueryParam("id", downloadId);
|
||||
requestBuilder.AddQueryParam("force_complete", false);
|
||||
|
||||
var response = ProcessRequest<object>(requestBuilder, $"remove item {downloadId}", settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,31 +2,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||
{
|
||||
public interface IFileStationProxy
|
||||
public interface IFileStationProxy : IDiskStationProxy
|
||||
{
|
||||
SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings);
|
||||
IEnumerable<int> GetApiVersion(DownloadStationSettings settings);
|
||||
|
||||
FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings);
|
||||
}
|
||||
|
||||
public class FileStationProxy : DiskStationProxyBase, IFileStationProxy
|
||||
{
|
||||
public FileStationProxy(IHttpClient httpClient, Logger logger)
|
||||
: base(httpClient, logger)
|
||||
public FileStationProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger)
|
||||
: base(DiskStationApi.FileStationList, "SYNO.FileStation.List", httpClient, cacheManager, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<int> GetApiVersion(DownloadStationSettings settings)
|
||||
{
|
||||
return base.GetApiVersion(settings, DiskStationApi.FileStationList);
|
||||
}
|
||||
|
||||
|
||||
public SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings)
|
||||
{
|
||||
var info = GetInfoFileOrDirectory(sharedFolder, settings);
|
||||
@@ -38,16 +34,11 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||
|
||||
public FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>
|
||||
{
|
||||
{ "api", "SYNO.FileStation.List" },
|
||||
{ "version", "2" },
|
||||
{ "method", "getinfo" },
|
||||
{ "path", new [] { path }.ToJson() },
|
||||
{ "additional", $"[\"real_path\"]" }
|
||||
};
|
||||
var requestBuilder = BuildRequest(settings, "getinfo", 2);
|
||||
requestBuilder.AddQueryParam("path", new[] { path }.ToJson());
|
||||
requestBuilder.AddQueryParam("additional", "[\"real_path\"]");
|
||||
|
||||
var response = ProcessRequest<FileStationListResponse>(DiskStationApi.FileStationList, arguments, settings, $"get info of {path}");
|
||||
var response = ProcessRequest<FileStationListResponse>(requestBuilder, $"get info of {path}", settings);
|
||||
|
||||
return response.Data.Files.First();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
@@ -20,7 +19,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
public class TorrentDownloadStation : TorrentClientBase<DownloadStationSettings>
|
||||
{
|
||||
protected readonly IDownloadStationProxy _proxy;
|
||||
protected readonly IDownloadStationInfoProxy _dsInfoProxy;
|
||||
protected readonly IDownloadStationTaskProxy _dsTaskProxy;
|
||||
protected readonly ISharedFolderResolver _sharedFolderResolver;
|
||||
protected readonly ISerialNumberProvider _serialNumberProvider;
|
||||
protected readonly IFileStationProxy _fileStationProxy;
|
||||
@@ -28,7 +28,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
public TorrentDownloadStation(ISharedFolderResolver sharedFolderResolver,
|
||||
ISerialNumberProvider serialNumberProvider,
|
||||
IFileStationProxy fileStationProxy,
|
||||
IDownloadStationProxy proxy,
|
||||
IDownloadStationInfoProxy dsInfoProxy,
|
||||
IDownloadStationTaskProxy dsTaskProxy,
|
||||
ITorrentFileInfoReader torrentFileInfoReader,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
@@ -37,7 +38,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
Logger logger)
|
||||
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_dsInfoProxy = dsInfoProxy;
|
||||
_dsTaskProxy = dsTaskProxy;
|
||||
_fileStationProxy = fileStationProxy;
|
||||
_sharedFolderResolver = sharedFolderResolver;
|
||||
_serialNumberProvider = serialNumberProvider;
|
||||
@@ -47,7 +49,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
|
||||
protected IEnumerable<DownloadStationTask> GetTasks()
|
||||
{
|
||||
return _proxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.BT.ToString().ToLower());
|
||||
return _dsTaskProxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.BT.ToString().ToLower());
|
||||
}
|
||||
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
@@ -88,7 +90,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
RemainingTime = GetRemainingTime(torrent),
|
||||
Status = GetStatus(torrent),
|
||||
Message = GetMessage(torrent),
|
||||
IsReadOnly = !IsFinished(torrent)
|
||||
CanMoveFiles = IsCompleted(torrent),
|
||||
CanBeRemoved = IsFinished(torrent)
|
||||
};
|
||||
|
||||
if (item.Status == DownloadItemStatus.Completed || item.Status == DownloadItemStatus.Failed)
|
||||
@@ -129,7 +132,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
DeleteItemData(downloadId);
|
||||
}
|
||||
|
||||
_proxy.RemoveTask(ParseDownloadId(downloadId), Settings);
|
||||
_dsTaskProxy.RemoveTask(ParseDownloadId(downloadId), Settings);
|
||||
_logger.Debug("{0} removed correctly", downloadId);
|
||||
}
|
||||
|
||||
@@ -148,7 +151,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
|
||||
|
||||
_proxy.AddTaskFromUrl(magnetLink, GetDownloadDirectory(), Settings);
|
||||
_dsTaskProxy.AddTaskFromUrl(magnetLink, GetDownloadDirectory(), Settings);
|
||||
|
||||
var item = GetTasks().SingleOrDefault(t => t.Additional.Detail["uri"] == magnetLink);
|
||||
|
||||
@@ -167,7 +170,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
|
||||
|
||||
_proxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
|
||||
_dsTaskProxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
|
||||
|
||||
var items = GetTasks().Where(t => t.Additional.Detail["uri"] == Path.GetFileNameWithoutExtension(filename));
|
||||
|
||||
@@ -197,6 +200,11 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
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)
|
||||
{
|
||||
if (torrent.StatusExtra != null)
|
||||
@@ -272,7 +280,17 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
try
|
||||
{
|
||||
var downloadDir = GetDownloadDirectory();
|
||||
var downloadDir = GetDefaultDir();
|
||||
|
||||
if (downloadDir == null)
|
||||
{
|
||||
return new NzbDroneValidationFailure(nameof(Settings.TvDirectory), "No default destination")
|
||||
{
|
||||
DetailedDescription = $"You must login into your Diskstation as {Settings.Username} and manually set it up into DownloadStation settings under BT/HTTP/FTP/NZB -> Location."
|
||||
};
|
||||
}
|
||||
|
||||
downloadDir = GetDownloadDirectory();
|
||||
|
||||
if (downloadDir != null)
|
||||
{
|
||||
@@ -285,7 +303,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
return new NzbDroneValidationFailure(fieldName, $"Shared folder does not exist")
|
||||
{
|
||||
DetailedDescription = $"The DownloadStation does not have a Shared Folder with the name '{sharedFolder}', are you sure you specified it correctly?"
|
||||
DetailedDescription = $"The Diskstation does not have a Shared Folder with the name '{sharedFolder}', are you sure you specified it correctly?"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -300,6 +318,11 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (DownloadClientAuthenticationException ex) // User could not have permission to access to downloadstation
|
||||
{
|
||||
_logger.Error(ex);
|
||||
return new NzbDroneValidationFailure(string.Empty, ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex);
|
||||
@@ -343,13 +366,13 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
|
||||
protected ValidationFailure ValidateVersion()
|
||||
{
|
||||
var versionRange = _proxy.GetApiVersion(Settings);
|
||||
var info = _dsTaskProxy.GetApiInfo(Settings);
|
||||
|
||||
_logger.Debug("Download Station api version information: Min {0} - Max {1}", versionRange.Min(), versionRange.Max());
|
||||
_logger.Debug("Download Station api version information: Min {0} - Max {1}", info.MinVersion, info.MaxVersion);
|
||||
|
||||
if (!versionRange.Contains(2))
|
||||
if (info.MinVersion > 2 || info.MaxVersion < 2)
|
||||
{
|
||||
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {versionRange.Min()} to {versionRange.Max()}");
|
||||
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {info.MinVersion} to {info.MaxVersion}");
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -380,7 +403,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
|
||||
protected string GetDefaultDir()
|
||||
{
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
var config = _dsInfoProxy.GetConfig(Settings);
|
||||
|
||||
var path = config["default_destination"] as string;
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
public class UsenetDownloadStation : UsenetClientBase<DownloadStationSettings>
|
||||
{
|
||||
protected readonly IDownloadStationProxy _proxy;
|
||||
protected readonly IDownloadStationInfoProxy _dsInfoProxy;
|
||||
protected readonly IDownloadStationTaskProxy _dsTaskProxy;
|
||||
protected readonly ISharedFolderResolver _sharedFolderResolver;
|
||||
protected readonly ISerialNumberProvider _serialNumberProvider;
|
||||
protected readonly IFileStationProxy _fileStationProxy;
|
||||
@@ -25,7 +26,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
public UsenetDownloadStation(ISharedFolderResolver sharedFolderResolver,
|
||||
ISerialNumberProvider serialNumberProvider,
|
||||
IFileStationProxy fileStationProxy,
|
||||
IDownloadStationProxy proxy,
|
||||
IDownloadStationInfoProxy dsInfoProxy,
|
||||
IDownloadStationTaskProxy dsTaskProxy,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
IDiskProvider diskProvider,
|
||||
@@ -34,7 +36,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
)
|
||||
: base(httpClient, configService, diskProvider, remotePathMappingService, logger)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_dsInfoProxy = dsInfoProxy;
|
||||
_dsTaskProxy = dsTaskProxy;
|
||||
_fileStationProxy = fileStationProxy;
|
||||
_sharedFolderResolver = sharedFolderResolver;
|
||||
_serialNumberProvider = serialNumberProvider;
|
||||
@@ -44,7 +47,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
|
||||
protected IEnumerable<DownloadStationTask> GetTasks()
|
||||
{
|
||||
return _proxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.NZB.ToString().ToLower());
|
||||
return _dsTaskProxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.NZB.ToString().ToLower());
|
||||
}
|
||||
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
@@ -96,7 +99,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
RemainingSize = taskRemainingSize,
|
||||
Status = GetStatus(nzb),
|
||||
Message = GetMessage(nzb),
|
||||
IsReadOnly = !IsFinished(nzb)
|
||||
CanBeRemoved = true,
|
||||
CanMoveFiles = true
|
||||
};
|
||||
|
||||
if (item.Status != DownloadItemStatus.Paused)
|
||||
@@ -153,7 +157,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
DeleteItemData(downloadId);
|
||||
}
|
||||
|
||||
_proxy.RemoveTask(ParseDownloadId(downloadId), Settings);
|
||||
_dsTaskProxy.RemoveTask(ParseDownloadId(downloadId), Settings);
|
||||
_logger.Debug("{0} removed correctly", downloadId);
|
||||
}
|
||||
|
||||
@@ -161,7 +165,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
|
||||
|
||||
_proxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
|
||||
_dsTaskProxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
|
||||
|
||||
var items = GetTasks().Where(t => t.Additional.Detail["uri"] == filename);
|
||||
|
||||
@@ -190,7 +194,17 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
try
|
||||
{
|
||||
var downloadDir = GetDownloadDirectory();
|
||||
var downloadDir = GetDefaultDir();
|
||||
|
||||
if (downloadDir == null)
|
||||
{
|
||||
return new NzbDroneValidationFailure(nameof(Settings.TvDirectory), "No default destination")
|
||||
{
|
||||
DetailedDescription = $"You must login into your Diskstation as {Settings.Username} and manually set it up into DownloadStation settings under BT/HTTP/FTP/NZB -> Location."
|
||||
};
|
||||
}
|
||||
|
||||
downloadDir = GetDownloadDirectory();
|
||||
|
||||
if (downloadDir != null)
|
||||
{
|
||||
@@ -203,7 +217,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
{
|
||||
return new NzbDroneValidationFailure(fieldName, $"Shared folder does not exist")
|
||||
{
|
||||
DetailedDescription = $"The DownloadStation does not have a Shared Folder with the name '{sharedFolder}', are you sure you specified it correctly?"
|
||||
DetailedDescription = $"The Diskstation does not have a Shared Folder with the name '{sharedFolder}', are you sure you specified it correctly?"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -218,6 +232,11 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (DownloadClientAuthenticationException ex) // User could not have permission to access to downloadstation
|
||||
{
|
||||
_logger.Error(ex);
|
||||
return new NzbDroneValidationFailure(string.Empty, ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex);
|
||||
@@ -261,23 +280,18 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
|
||||
protected ValidationFailure ValidateVersion()
|
||||
{
|
||||
var versionRange = _proxy.GetApiVersion(Settings);
|
||||
var info = _dsTaskProxy.GetApiInfo(Settings);
|
||||
|
||||
_logger.Debug("Download Station api version information: Min {0} - Max {1}", versionRange.Min(), versionRange.Max());
|
||||
_logger.Debug("Download Station api version information: Min {0} - Max {1}", info.MinVersion, info.MaxVersion);
|
||||
|
||||
if (!versionRange.Contains(2))
|
||||
if (info.MinVersion > 2 || info.MaxVersion < 2)
|
||||
{
|
||||
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {versionRange.Min()} to {versionRange.Max()}");
|
||||
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {info.MinVersion} to {info.MaxVersion}");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected bool IsFinished(DownloadStationTask task)
|
||||
{
|
||||
return task.Status == DownloadStationTaskStatus.Finished;
|
||||
}
|
||||
|
||||
protected string GetMessage(DownloadStationTask task)
|
||||
{
|
||||
if (task.StatusExtra != null)
|
||||
@@ -379,7 +393,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
|
||||
protected string GetDefaultDir()
|
||||
{
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
var config = _dsInfoProxy.GetConfig(Settings);
|
||||
|
||||
var path = config["default_destination"] as string;
|
||||
|
||||
|
||||
@@ -97,14 +97,7 @@ namespace NzbDrone.Core.Download.Clients.Hadouken
|
||||
item.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
|
||||
if (torrent.IsFinished && torrent.State == HadoukenTorrentState.Paused)
|
||||
{
|
||||
item.IsReadOnly = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.IsReadOnly = true;
|
||||
}
|
||||
item.CanMoveFiles = item.CanBeRemoved = (torrent.IsFinished && torrent.State == HadoukenTorrentState.Paused);
|
||||
|
||||
items.Add(item);
|
||||
}
|
||||
@@ -170,7 +163,7 @@ namespace NzbDrone.Core.Download.Clients.Hadouken
|
||||
|
||||
if (version < new Version("5.1"))
|
||||
{
|
||||
return new ValidationFailure(string.Empty, "Old Hadouken client with unsupported API, need 5.1 or higher");
|
||||
return new ValidationFailure(string.Empty, "Old Hadouken client with unsupported API, need 5.1 or higher");
|
||||
}
|
||||
}
|
||||
catch (DownloadClientAuthenticationException ex)
|
||||
|
||||
@@ -72,7 +72,9 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
|
||||
queueItem.TotalSize = vortexQueueItem.TotalDownloadSize;
|
||||
queueItem.RemainingSize = vortexQueueItem.TotalDownloadSize - vortexQueueItem.DownloadedSize;
|
||||
queueItem.RemainingTime = null;
|
||||
|
||||
queueItem.CanBeRemoved = true;
|
||||
queueItem.CanMoveFiles = true;
|
||||
|
||||
if (vortexQueueItem.IsPaused)
|
||||
{
|
||||
queueItem.Status = DownloadItemStatus.Paused;
|
||||
@@ -132,7 +134,7 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
|
||||
{
|
||||
_proxy.Remove(queueItem.Id, deleteData, Settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected List<NzbVortexGroup> GetGroups()
|
||||
@@ -256,4 +258,4 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
|
||||
return new OsPath(Path.Combine(outputPath.FullPath, filesResponse.First().FileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +145,8 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
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}";
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
historyItem.RemainingTime = TimeSpan.Zero;
|
||||
historyItem.CanMoveFiles = true;
|
||||
historyItem.CanBeRemoved = true;
|
||||
|
||||
if (item.DeleteStatus == "MANUAL")
|
||||
{
|
||||
|
||||
@@ -77,6 +77,9 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
|
||||
DownloadId = GetDownloadClientId(file),
|
||||
Title = title,
|
||||
|
||||
CanBeRemoved = true,
|
||||
CanMoveFiles = true,
|
||||
|
||||
TotalSize = _diskProvider.GetFileSize(file),
|
||||
|
||||
OutputPath = new OsPath(file)
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
|
||||
// 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).
|
||||
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)
|
||||
{
|
||||
@@ -129,7 +129,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
item.Status = DownloadItemStatus.Queued;
|
||||
break;
|
||||
|
||||
case "pausedUP": // torrent is paused and has finished downloading
|
||||
case "pausedUP": // torrent is paused and has finished downloading:
|
||||
case "uploading": // torrent is being seeded and data is being transfered
|
||||
case "stalledUP": // torrent is being seeded, but no connection were made
|
||||
case "queuedUP": // queuing is enabled and torrent is queued for upload
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses
|
||||
{
|
||||
public class SabnzbdFullStatusResponse
|
||||
{
|
||||
public SabnzbdFullStatus Status { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -160,6 +160,8 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
else if (sabHistoryItem.Status == SabnzbdDownloadStatus.Completed)
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
historyItem.CanBeRemoved = true;
|
||||
historyItem.CanMoveFiles = true;
|
||||
}
|
||||
else // Verifying/Moving etc
|
||||
{
|
||||
@@ -220,10 +222,18 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
|
||||
if (!completeDir.IsRooted)
|
||||
{
|
||||
var queue = _proxy.GetQueue(0, 1, Settings);
|
||||
var defaultRootFolder = new OsPath(queue.DefaultRootFolder);
|
||||
if (HasVersion(2, 0))
|
||||
{
|
||||
var status = _proxy.GetFullStatus(Settings);
|
||||
completeDir = new OsPath(status.CompleteDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
var queue = _proxy.GetQueue(0, 1, Settings);
|
||||
var defaultRootFolder = new OsPath(queue.DefaultRootFolder);
|
||||
|
||||
completeDir = defaultRootFolder + completeDir;
|
||||
completeDir = defaultRootFolder + completeDir;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var category in config.Categories)
|
||||
@@ -443,50 +453,47 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (config.Misc.enable_tv_sorting)
|
||||
if (config.Misc.enable_tv_sorting && ContainsCategory(config.Misc.tv_categories, Settings.TvCategory))
|
||||
{
|
||||
if (!config.Misc.tv_categories.Any<string>() ||
|
||||
config.Misc.tv_categories.Contains(Settings.TvCategory) ||
|
||||
(Settings.TvCategory.IsNullOrWhiteSpace() && config.Misc.tv_categories.Contains("Default")))
|
||||
return new NzbDroneValidationFailure("TvCategory", "Disable TV Sorting")
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "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 Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||
};
|
||||
}
|
||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||
DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||
};
|
||||
}
|
||||
|
||||
if (config.Misc.enable_movie_sorting)
|
||||
if (config.Misc.enable_movie_sorting && ContainsCategory(config.Misc.movie_categories, Settings.TvCategory))
|
||||
{
|
||||
if (!config.Misc.movie_categories.Any<string>() ||
|
||||
config.Misc.movie_categories.Contains(Settings.TvCategory) ||
|
||||
(Settings.TvCategory.IsNullOrWhiteSpace() && config.Misc.movie_categories.Contains("Default")))
|
||||
return new NzbDroneValidationFailure("TvCategory", "Disable Movie Sorting")
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "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 Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||
};
|
||||
}
|
||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||
DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||
};
|
||||
}
|
||||
|
||||
if (config.Misc.enable_date_sorting)
|
||||
if (config.Misc.enable_date_sorting && ContainsCategory(config.Misc.date_categories, Settings.TvCategory))
|
||||
{
|
||||
if (!config.Misc.date_categories.Any<string>() ||
|
||||
config.Misc.date_categories.Contains(Settings.TvCategory) ||
|
||||
(Settings.TvCategory.IsNullOrWhiteSpace() && config.Misc.date_categories.Contains("Default")))
|
||||
return new NzbDroneValidationFailure("TvCategory", "Disable Date Sorting")
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "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 Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||
};
|
||||
}
|
||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||
DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool ContainsCategory(IEnumerable<string> categories, string category)
|
||||
{
|
||||
if (categories == null || categories.Empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (category.IsNullOrWhiteSpace())
|
||||
{
|
||||
category = "Default";
|
||||
}
|
||||
|
||||
return categories.Contains(category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public class SabnzbdFullStatus
|
||||
{
|
||||
// Added in Sabnzbd 2.0.0, my_home was previously in &mode=queue.
|
||||
// This is the already resolved completedir path.
|
||||
[JsonProperty(PropertyName = "completedir")]
|
||||
public string CompleteDir { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
void RemoveFrom(string source, string id,bool deleteData, SabnzbdSettings settings);
|
||||
string GetVersion(SabnzbdSettings settings);
|
||||
SabnzbdConfig GetConfig(SabnzbdSettings settings);
|
||||
SabnzbdFullStatus GetFullStatus(SabnzbdSettings settings);
|
||||
SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings);
|
||||
SabnzbdHistory GetHistory(int start, int limit, string category, SabnzbdSettings settings);
|
||||
string RetryDownload(string id, SabnzbdSettings settings);
|
||||
@@ -37,7 +38,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
|
||||
request.AddQueryParam("cat", category);
|
||||
request.AddQueryParam("priority", priority);
|
||||
|
||||
|
||||
request.AddFormUpload("name", filename, nzbData, "application/x-nzb");
|
||||
|
||||
SabnzbdAddResponse response;
|
||||
@@ -84,6 +85,16 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
return response.Config;
|
||||
}
|
||||
|
||||
public SabnzbdFullStatus GetFullStatus(SabnzbdSettings settings)
|
||||
{
|
||||
var request = BuildRequest("fullstatus", settings);
|
||||
request.AddQueryParam("skip_dashboard", "1");
|
||||
|
||||
var response = Json.Deserialize<SabnzbdFullStatusResponse>(ProcessRequest(request, settings));
|
||||
|
||||
return response.Status;
|
||||
}
|
||||
|
||||
public SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings)
|
||||
{
|
||||
var request = BuildRequest("queue", settings);
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public class SabnzbdQueue
|
||||
{
|
||||
// Removed in Sabnzbd 2.0.0, see mode=fullstatus instead.
|
||||
[JsonProperty(PropertyName = "my_home")]
|
||||
public string DefaultRootFolder { get; set; }
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
item.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
|
||||
item.IsReadOnly = torrent.Status != TransmissionTorrentStatus.Stopped;
|
||||
item.CanMoveFiles = item.CanBeRemoved = torrent.Status == TransmissionTorrentStatus.Stopped;
|
||||
|
||||
items.Add(item);
|
||||
}
|
||||
@@ -122,7 +122,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
{
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
var destDir = config.GetValueOrDefault("download-dir") as string;
|
||||
|
||||
|
||||
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
destDir = string.Format("{0}/.{1}", destDir, Settings.TvCategory);
|
||||
@@ -246,4 +246,4 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,59 +39,40 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
|
||||
{
|
||||
_proxy.AddTorrentFromUrl(magnetLink, Settings);
|
||||
|
||||
// Download the magnet to the appropriate directory.
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
SetPriority(remoteEpisode, hash);
|
||||
SetDownloadDirectory(hash);
|
||||
|
||||
// Once the magnet meta download finishes, rTorrent replaces it with the actual torrent download with default settings.
|
||||
// Schedule an event to apply the appropriate settings when that happens.
|
||||
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
|
||||
_proxy.SetDeferredMagnetProperties(hash, Settings.TvCategory, Settings.TvDirectory, priority, Settings);
|
||||
|
||||
_proxy.StartTorrent(hash, Settings);
|
||||
_proxy.AddTorrentFromUrl(magnetLink, Settings.TvCategory, priority, Settings.TvDirectory, Settings);
|
||||
|
||||
// Wait for the magnet to be resolved.
|
||||
var tries = 10;
|
||||
var retryDelay = 500;
|
||||
if (WaitForTorrent(hash, tries, retryDelay))
|
||||
{
|
||||
return hash;
|
||||
}
|
||||
else
|
||||
|
||||
// Wait a bit for the magnet to be resolved.
|
||||
if (!WaitForTorrent(hash, tries, retryDelay))
|
||||
{
|
||||
_logger.Warn("rTorrent could not resolve magnet within {0} seconds, download may remain stuck: {1}.", tries * retryDelay / 1000, magnetLink);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
|
||||
{
|
||||
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
||||
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
|
||||
|
||||
var tries = 5;
|
||||
var retryDelay = 200;
|
||||
if (WaitForTorrent(hash, tries, retryDelay))
|
||||
_proxy.AddTorrentFromFile(filename, fileContent, Settings.TvCategory, priority, Settings.TvDirectory, Settings);
|
||||
|
||||
var tries = 10;
|
||||
var retryDelay = 500;
|
||||
if (!WaitForTorrent(hash, tries, retryDelay))
|
||||
{
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
_logger.Debug("rTorrent didn't add the torrent within {0} seconds: {1}.", tries * retryDelay / 1000, filename);
|
||||
|
||||
SetPriority(remoteEpisode, hash);
|
||||
SetDownloadDirectory(hash);
|
||||
|
||||
_proxy.StartTorrent(hash, Settings);
|
||||
|
||||
return hash;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("rTorrent could not add file");
|
||||
|
||||
RemoveItem(hash, true);
|
||||
throw new ReleaseDownloadException(remoteEpisode.Release, "Downloading torrent failed");
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override string Name => "rTorrent";
|
||||
@@ -126,19 +107,31 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
item.RemainingSize = torrent.RemainingSize;
|
||||
item.Category = torrent.Category;
|
||||
|
||||
if (torrent.DownRate > 0) {
|
||||
if (torrent.DownRate > 0)
|
||||
{
|
||||
var secondsLeft = torrent.RemainingSize / torrent.DownRate;
|
||||
item.RemainingTime = TimeSpan.FromSeconds(secondsLeft);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
item.RemainingTime = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
if (torrent.IsFinished) item.Status = DownloadItemStatus.Completed;
|
||||
else if (torrent.IsActive) item.Status = DownloadItemStatus.Downloading;
|
||||
else if (!torrent.IsActive) item.Status = DownloadItemStatus.Paused;
|
||||
if (torrent.IsFinished)
|
||||
{
|
||||
item.Status = DownloadItemStatus.Completed;
|
||||
}
|
||||
else if (torrent.IsActive)
|
||||
{
|
||||
item.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
else if (!torrent.IsActive)
|
||||
{
|
||||
item.Status = DownloadItemStatus.Paused;
|
||||
}
|
||||
|
||||
// No stop ratio data is present, so do not delete
|
||||
item.IsReadOnly = true;
|
||||
item.CanMoveFiles = item.CanBeRemoved = false;
|
||||
|
||||
items.Add(item);
|
||||
}
|
||||
@@ -230,20 +223,6 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
return result.Errors.First();
|
||||
}
|
||||
|
||||
private void SetPriority(RemoteEpisode remoteEpisode, string hash)
|
||||
{
|
||||
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
|
||||
_proxy.SetTorrentPriority(hash, priority, Settings);
|
||||
}
|
||||
|
||||
private void SetDownloadDirectory(string hash)
|
||||
{
|
||||
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetTorrentDownloadDirectory(hash, Settings.TvDirectory, Settings);
|
||||
}
|
||||
}
|
||||
|
||||
private bool WaitForTorrent(string hash, int tries, int retryDelay)
|
||||
{
|
||||
for (var i = 0; i < tries; i++)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user