Add more settings for the download client.
This commit is contained in:
parent
c4a985f8b5
commit
bc552612f5
7 changed files with 179 additions and 21 deletions
|
|
@ -17,6 +17,7 @@
|
||||||
>.
|
>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Download path</label>
|
<label class="label">Download path</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
|
|
@ -24,6 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
<p class="help">Path in the docker container to download files to (i.e. /data/downloads).</p>
|
<p class="help">Path in the docker container to download files to (i.e. /data/downloads).</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Mapped path</label>
|
<label class="label">Mapped path</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
|
|
@ -34,6 +36,18 @@
|
||||||
to find your downloads.
|
to find your downloads.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Temp path</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="text" maxlength="1000" [(ngModel)]="settingTempPath" />
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
Path in the docker container to temporarily download to (i.e. /data/temp). Make sure the docker container has
|
||||||
|
enough disk space if using a path inside the container.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Maximum parallel downloads</label>
|
<label class="label">Maximum parallel downloads</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
|
|
@ -41,6 +55,26 @@
|
||||||
</div>
|
</div>
|
||||||
<p class="help">Maximum amount of torrents that get downloaded to your host at the same time.</p>
|
<p class="help">Maximum amount of torrents that get downloaded to your host at the same time.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Parallel connections per download</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="number" max="100" min="0" [(ngModel)]="settingDownloadChunkCount" />
|
||||||
|
</div>
|
||||||
|
<p class="help">
|
||||||
|
Maximum amount of parallel threads that are used to download a single torrent to your host. If set to 1 no
|
||||||
|
parallel downloading will be done.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Download speed (in MB/s)</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="number" max="1000" min="0" [(ngModel)]="settingDownloadMaxSpeed" />
|
||||||
|
</div>
|
||||||
|
<p class="help">Maximum download speed in Megabytes per second. When set to 0 unlimited speed is used.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Maximum unpack processes</label>
|
<label class="label">Maximum unpack processes</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,10 @@ export class SettingsComponent implements OnInit {
|
||||||
public settingRealDebridApiKey: string;
|
public settingRealDebridApiKey: string;
|
||||||
public settingDownloadPath: string;
|
public settingDownloadPath: string;
|
||||||
public settingMappedPath: string;
|
public settingMappedPath: string;
|
||||||
|
public settingTempPath: string;
|
||||||
public settingDownloadLimit: number;
|
public settingDownloadLimit: number;
|
||||||
|
public settingDownloadChunkCount: number;
|
||||||
|
public settingDownloadMaxSpeed: number;
|
||||||
public settingUnpackLimit: number;
|
public settingUnpackLimit: number;
|
||||||
public settingMinFileSize: number;
|
public settingMinFileSize: number;
|
||||||
|
|
||||||
|
|
@ -55,7 +58,10 @@ export class SettingsComponent implements OnInit {
|
||||||
this.settingRealDebridApiKey = this.getSetting(results, 'RealDebridApiKey');
|
this.settingRealDebridApiKey = this.getSetting(results, 'RealDebridApiKey');
|
||||||
this.settingDownloadPath = this.getSetting(results, 'DownloadPath');
|
this.settingDownloadPath = this.getSetting(results, 'DownloadPath');
|
||||||
this.settingMappedPath = this.getSetting(results, 'MappedPath');
|
this.settingMappedPath = this.getSetting(results, 'MappedPath');
|
||||||
|
this.settingTempPath = this.getSetting(results, 'TempPath');
|
||||||
this.settingDownloadLimit = parseInt(this.getSetting(results, 'DownloadLimit'), 10);
|
this.settingDownloadLimit = parseInt(this.getSetting(results, 'DownloadLimit'), 10);
|
||||||
|
this.settingDownloadChunkCount = parseInt(this.getSetting(results, 'DownloadChunkCount'), 10);
|
||||||
|
this.settingDownloadMaxSpeed = parseInt(this.getSetting(results, 'DownloadMaxSpeed'), 10);
|
||||||
this.settingUnpackLimit = parseInt(this.getSetting(results, 'UnpackLimit'), 10);
|
this.settingUnpackLimit = parseInt(this.getSetting(results, 'UnpackLimit'), 10);
|
||||||
this.settingMinFileSize = parseInt(this.getSetting(results, 'MinFileSize'), 10);
|
this.settingMinFileSize = parseInt(this.getSetting(results, 'MinFileSize'), 10);
|
||||||
},
|
},
|
||||||
|
|
@ -82,10 +88,22 @@ export class SettingsComponent implements OnInit {
|
||||||
settingId: 'MappedPath',
|
settingId: 'MappedPath',
|
||||||
value: this.settingMappedPath,
|
value: this.settingMappedPath,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
settingId: 'TempPath',
|
||||||
|
value: this.settingTempPath,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
settingId: 'DownloadLimit',
|
settingId: 'DownloadLimit',
|
||||||
value: (this.settingDownloadLimit ?? 10).toString(),
|
value: (this.settingDownloadLimit ?? 10).toString(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
settingId: 'DownloadChunkCount',
|
||||||
|
value: (this.settingDownloadChunkCount ?? 8).toString(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
settingId: 'DownloadMaxSpeed',
|
||||||
|
value: (this.settingDownloadMaxSpeed ?? 0).toString(),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
settingId: 'UnpackLimit',
|
settingId: 'UnpackLimit',
|
||||||
value: (this.settingUnpackLimit ?? 1).toString(),
|
value: (this.settingUnpackLimit ?? 1).toString(),
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,16 @@ namespace RdtClient.Data.Data
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
new Setting
|
new Setting
|
||||||
|
{
|
||||||
|
SettingId = "TempPath",
|
||||||
|
Type = "String",
|
||||||
|
#if DEBUG
|
||||||
|
Value = @"C:\Temp\rdtclient"
|
||||||
|
#else
|
||||||
|
Value = "/data/downloads"
|
||||||
|
#endif
|
||||||
|
},
|
||||||
|
new Setting
|
||||||
{
|
{
|
||||||
SettingId = "MappedPath",
|
SettingId = "MappedPath",
|
||||||
Type = "String",
|
Type = "String",
|
||||||
|
|
@ -83,6 +93,18 @@ namespace RdtClient.Data.Data
|
||||||
SettingId = "MinFileSize",
|
SettingId = "MinFileSize",
|
||||||
Type = "Int32",
|
Type = "Int32",
|
||||||
Value = "0"
|
Value = "0"
|
||||||
|
},
|
||||||
|
new Setting
|
||||||
|
{
|
||||||
|
SettingId = "DownloadChunkCount",
|
||||||
|
Type = "Int32",
|
||||||
|
Value = "8"
|
||||||
|
},
|
||||||
|
new Setting
|
||||||
|
{
|
||||||
|
SettingId = "DownloadMaxSpeed",
|
||||||
|
Type = "Int32",
|
||||||
|
Value = "0"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
34
server/RdtClient.Service/Helpers/SettingsHelper.cs
Normal file
34
server/RdtClient.Service/Helpers/SettingsHelper.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using RdtClient.Data.Models.Data;
|
||||||
|
|
||||||
|
namespace RdtClient.Service.Helpers
|
||||||
|
{
|
||||||
|
public static class SettingsHelper
|
||||||
|
{
|
||||||
|
public static String GetString(this IList<Setting> settings, String key)
|
||||||
|
{
|
||||||
|
var setting = settings.FirstOrDefault(m => m.SettingId == key);
|
||||||
|
|
||||||
|
if (setting == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Setting with key {key} not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return setting.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32 GetNumber(this IList<Setting> settings, String key)
|
||||||
|
{
|
||||||
|
var setting = settings.FirstOrDefault(m => m.SettingId == key);
|
||||||
|
|
||||||
|
if (setting == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Setting with key {key} not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Int32.Parse(setting.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -34,9 +34,9 @@ namespace RdtClient.Service.Services
|
||||||
public Int64 BytesDone { get; private set; }
|
public Int64 BytesDone { get; private set; }
|
||||||
|
|
||||||
private static Int64 LastTick { get; set; }
|
private static Int64 LastTick { get; set; }
|
||||||
private static ConcurrentBag<Int64> AverageSpeed { get; } = new ConcurrentBag<Int64>();
|
private static ConcurrentBag<Double> AverageSpeed { get; } = new ConcurrentBag<Double>();
|
||||||
|
|
||||||
public async Task Start(Boolean writeToMemory)
|
public async Task Start(Boolean onTheFlyDownload, String tempDirectory, Int32 chunkCount, Int64 maximumBytesPerSecond)
|
||||||
{
|
{
|
||||||
BytesDone = 0;
|
BytesDone = 0;
|
||||||
BytesTotal = 0;
|
BytesTotal = 0;
|
||||||
|
|
@ -69,7 +69,7 @@ namespace RdtClient.Service.Services
|
||||||
|
|
||||||
await Task.Factory.StartNew(async delegate
|
await Task.Factory.StartNew(async delegate
|
||||||
{
|
{
|
||||||
await Download(filePath, writeToMemory);
|
await Download(filePath, onTheFlyDownload, tempDirectory, chunkCount, maximumBytesPerSecond);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -84,7 +84,7 @@ namespace RdtClient.Service.Services
|
||||||
_downloader?.CancelAsync();
|
_downloader?.CancelAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Download(String filePath, Boolean writeToMemory)
|
private async Task Download(String filePath, Boolean onTheFlyDownload, String tempDirectory, Int32 chunkCount, Int64 maximumBytesPerSecond)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -93,13 +93,13 @@ namespace RdtClient.Service.Services
|
||||||
var downloadOpt = new DownloadConfiguration
|
var downloadOpt = new DownloadConfiguration
|
||||||
{
|
{
|
||||||
MaxTryAgainOnFailover = Int32.MaxValue,
|
MaxTryAgainOnFailover = Int32.MaxValue,
|
||||||
ParallelDownload = true,
|
ParallelDownload = chunkCount > 1,
|
||||||
ChunkCount = 8,
|
ChunkCount = chunkCount,
|
||||||
Timeout = 100,
|
Timeout = 1000,
|
||||||
OnTheFlyDownload = writeToMemory,
|
OnTheFlyDownload = onTheFlyDownload,
|
||||||
BufferBlockSize = 1024 * 8,
|
BufferBlockSize = 1024 * 8,
|
||||||
MaximumBytesPerSecond = 100 * 1024 * 1024,
|
MaximumBytesPerSecond = maximumBytesPerSecond,
|
||||||
TempDirectory = @"C:\temp",
|
TempDirectory = tempDirectory,
|
||||||
RequestConfiguration =
|
RequestConfiguration =
|
||||||
{
|
{
|
||||||
Accept = "*/*",
|
Accept = "*/*",
|
||||||
|
|
@ -124,7 +124,7 @@ namespace RdtClient.Service.Services
|
||||||
}
|
}
|
||||||
|
|
||||||
Speed = (Int64) AverageSpeed.Average();
|
Speed = (Int64) AverageSpeed.Average();
|
||||||
BytesDone = args.BytesReceived;
|
BytesDone = args.ReceivedBytesSize;
|
||||||
BytesTotal = args.TotalBytesToReceive;
|
BytesTotal = args.TotalBytesToReceive;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ namespace RdtClient.Service.Services
|
||||||
public async Task<Double> TestDownloadSpeed(CancellationToken cancellationToken)
|
public async Task<Double> TestDownloadSpeed(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var downloadPath = await GetString("DownloadPath");
|
var downloadPath = await GetString("DownloadPath");
|
||||||
|
var tempPath = await GetString("TempPath");
|
||||||
|
|
||||||
var testFilePath = Path.Combine(downloadPath, "testDefault.rar");
|
var testFilePath = Path.Combine(downloadPath, "testDefault.rar");
|
||||||
|
|
||||||
|
|
@ -109,10 +110,11 @@ namespace RdtClient.Service.Services
|
||||||
|
|
||||||
var downloadClient = new DownloadClient(download, downloadPath);
|
var downloadClient = new DownloadClient(download, downloadPath);
|
||||||
|
|
||||||
await downloadClient.Start(true);
|
await downloadClient.Start(false, tempPath, 8, 0);
|
||||||
|
|
||||||
while (!downloadClient.Finished)
|
while (!downloadClient.Finished)
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once MethodSupportsCancellation
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
|
@ -120,7 +122,7 @@ namespace RdtClient.Service.Services
|
||||||
downloadClient.Cancel();
|
downloadClient.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloadClient.BytesDone > 1024 * 1024 * 100)
|
if (downloadClient.BytesDone > 1024 * 1024 * 50)
|
||||||
{
|
{
|
||||||
downloadClient.Cancel();
|
downloadClient.Cancel();
|
||||||
}
|
}
|
||||||
|
|
@ -131,6 +133,13 @@ namespace RdtClient.Service.Services
|
||||||
File.Delete(testFilePath);
|
File.Delete(testFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var files = Directory.GetFiles(tempPath, "*.dsc", SearchOption.TopDirectoryOnly);
|
||||||
|
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
|
||||||
return downloadClient.Speed;
|
return downloadClient.Speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using RdtClient.Data.Enums;
|
using RdtClient.Data.Enums;
|
||||||
|
using RdtClient.Service.Helpers;
|
||||||
|
|
||||||
namespace RdtClient.Service.Services
|
namespace RdtClient.Service.Services
|
||||||
{
|
{
|
||||||
|
|
@ -61,19 +62,59 @@ namespace RdtClient.Service.Services
|
||||||
|
|
||||||
public async Task Tick()
|
public async Task Tick()
|
||||||
{
|
{
|
||||||
var settingApiKey = await _settings.GetString("RealDebridApiKey");
|
var settings = await _settings.GetAll();
|
||||||
var settingMinFileSize = await _settings.GetNumber("MinFileSize");
|
|
||||||
var settingDownloadLimit = await _settings.GetNumber("DownloadLimit");
|
|
||||||
var settingUnpackLimit = await _settings.GetNumber("UnpackLimit");
|
|
||||||
var settingDownloadPath = await _settings.GetString("DownloadPath");
|
|
||||||
|
|
||||||
settingMinFileSize = settingMinFileSize * 1024 * 1024;
|
|
||||||
|
|
||||||
|
var settingApiKey = settings.GetString("RealDebridApiKey");
|
||||||
if (String.IsNullOrWhiteSpace(settingApiKey))
|
if (String.IsNullOrWhiteSpace(settingApiKey))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var settingMinFileSize = settings.GetNumber("MinFileSize");
|
||||||
|
if (settingMinFileSize <= 0)
|
||||||
|
{
|
||||||
|
settingMinFileSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
settingMinFileSize = settingMinFileSize * 1024 * 1024;
|
||||||
|
|
||||||
|
var settingDownloadLimit = settings.GetNumber("DownloadLimit");
|
||||||
|
if (settingDownloadLimit < 1)
|
||||||
|
{
|
||||||
|
settingDownloadLimit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var settingUnpackLimit = settings.GetNumber("UnpackLimit");
|
||||||
|
if (settingUnpackLimit < 1)
|
||||||
|
{
|
||||||
|
settingUnpackLimit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var settingDownloadPath = settings.GetString("DownloadPath");
|
||||||
|
if (String.IsNullOrWhiteSpace(settingDownloadPath))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var settingTempPath = settings.GetString("TempPath");
|
||||||
|
if (String.IsNullOrWhiteSpace(settingTempPath))
|
||||||
|
{
|
||||||
|
settingTempPath = Path.GetTempPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
var settingDownloadChunkCount = settings.GetNumber("DownloadChunkCount");
|
||||||
|
if (settingDownloadChunkCount <= 0)
|
||||||
|
{
|
||||||
|
settingDownloadChunkCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var settingDownloadMaxSpeed = settings.GetNumber("DownloadMaxSpeed");
|
||||||
|
if (settingDownloadMaxSpeed <= 0)
|
||||||
|
{
|
||||||
|
settingDownloadMaxSpeed = 0;
|
||||||
|
}
|
||||||
|
settingDownloadMaxSpeed = settingDownloadMaxSpeed * 1024 * 1024;
|
||||||
|
|
||||||
// Check if any torrents are finished downloading to the host, remove them from the active download list.
|
// Check if any torrents are finished downloading to the host, remove them from the active download list.
|
||||||
var completedActiveDownloads = ActiveDownloadClients.Where(m => m.Value.Finished).ToList();
|
var completedActiveDownloads = ActiveDownloadClients.Where(m => m.Value.Finished).ToList();
|
||||||
|
|
||||||
|
|
@ -172,7 +213,7 @@ namespace RdtClient.Service.Services
|
||||||
|
|
||||||
if (TorrentRunner.ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient))
|
if (TorrentRunner.ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient))
|
||||||
{
|
{
|
||||||
await downloadClient.Start(false);
|
await downloadClient.Start(false, settingTempPath, settingDownloadChunkCount, settingDownloadMaxSpeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue