diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a32327..7582f96 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.9.7] - 2021-10-30
+### Added
+- Add AllDebrid support.
+
## [1.9.6] - 2021-10-30
### Added
- Improved handling of errors on the torrent itself
diff --git a/README.md b/README.md
index 59b00ab..cc131ca 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,20 @@
# Real-Debrid Torrent Client
-This is a web interface to manage your torrents on Real-Debrid. It supports the following features:
+This is a web interface to manage your torrents on Real-Debrid or AllDebrid. It supports the following features:
- Add new torrents through magnets or files
-- Download all files from Real Debrid to your local machine automatically
+- Download all files from Real Debrid or AllDebrid to your local machine automatically
- Unpack all files when finished downloading
- Implements a fake qBittorrent API so you can hook up other applications like Sonarr or Couchpotato.
- Built with Angular 11 and .NET 5
-**You will need a Premium service at Real-Debrid!**
+**You will need a Premium service at Real-Debrid or AllDebrid!**
-[Click here to sign up (referal link so I can get a few free premium days).](https://real-debrid.com/?id=1348683)
+[Click here to sign up at Real-Debrid.](https://real-debrid.com/?id=1348683)
+
+[Click here to sign up AllDebrid.](https://real-debrid.com/?id=1348683)
+
+(referal links so I can get a few free premium days)
## Docker Setup
diff --git a/client/src/app/add-new-torrent/add-new-torrent.component.html b/client/src/app/add-new-torrent/add-new-torrent.component.html
index 83fc19c..326378a 100644
--- a/client/src/app/add-new-torrent/add-new-torrent.component.html
+++ b/client/src/app/add-new-torrent/add-new-torrent.component.html
@@ -39,12 +39,29 @@
Download action
-
- Download all files above a certain size
- Download all available files on Real-Debrid above a certain size
- Pick files I want to download
+
+ Download all files
+ Download all available files
+ Manually pick files
+
+ This option is only available for RealDebrid. AllDebrid will always download the full torrent.
+
+
+
+ 0"
+ >
+ This torrent is available for immediate download.
+
+
+
+ This torrent is not available for immediate download.
@@ -59,6 +76,10 @@
+
+ When downloading with AllDebrid it cannot be guaranteed that only files above this limit will be download as
+ some files are grouped together in 1 large archive.
+
This setting does not apply to manually selected files.
@@ -93,28 +114,14 @@
-
+
Available files
These files are available for immediate download from Real-Debrid.
- It is possible that there are more files in the torrent, which are not shown here.
+ It is possible that there are more files in the torrent, which are not shown here.
diff --git a/client/src/app/navbar/navbar.component.ts b/client/src/app/navbar/navbar.component.ts
index 0aa7162..7f62035 100644
--- a/client/src/app/navbar/navbar.component.ts
+++ b/client/src/app/navbar/navbar.component.ts
@@ -13,12 +13,22 @@ export class NavbarComponent implements OnInit {
public showMobileMenu = false;
public profile: Profile;
+ public providerLink: string;
constructor(private settingsService: SettingsService, private authService: AuthService, private router: Router) {}
ngOnInit(): void {
this.settingsService.getProfile().subscribe((result) => {
this.profile = result;
+
+ switch (result.provider) {
+ case 'RealDebrid':
+ this.providerLink = 'https://real-debrid.com/?id=1348683';
+ break;
+ case 'AllDebrid':
+ this.providerLink = 'https://alldebrid.com/?uid=2v91l&lang=en';
+ break;
+ }
});
}
diff --git a/client/src/app/settings/settings.component.html b/client/src/app/settings/settings.component.html
index 00f612e..3c70271 100644
--- a/client/src/app/settings/settings.component.html
+++ b/client/src/app/settings/settings.component.html
@@ -3,6 +3,9 @@
General
+
+ Provider
+
Download Client
@@ -15,8 +18,26 @@
-
+
+
+
Log level
diff --git a/client/src/app/settings/settings.component.ts b/client/src/app/settings/settings.component.ts
index f01851a..28887bf 100644
--- a/client/src/app/settings/settings.component.ts
+++ b/client/src/app/settings/settings.component.ts
@@ -26,6 +26,7 @@ export class SettingsComponent implements OnInit {
public testAria2cConnectionSuccess: string = null;
public settingLogLevel: string;
+ public settingProvider: string;
public settingRealDebridApiKey: string;
public settingDownloadPath: string;
public settingMappedPath: string;
@@ -57,6 +58,7 @@ export class SettingsComponent implements OnInit {
this.settingsService.get().subscribe(
(results) => {
+ this.settingProvider = this.getSetting(results, 'Provider');
this.settingRealDebridApiKey = this.getSetting(results, 'RealDebridApiKey');
this.settingLogLevel = this.getSetting(results, 'LogLevel');
this.settingDownloadPath = this.getSetting(results, 'DownloadPath');
@@ -86,6 +88,10 @@ export class SettingsComponent implements OnInit {
this.saving = true;
const settings: Setting[] = [
+ {
+ settingId: 'Provider',
+ value: this.settingProvider,
+ },
{
settingId: 'RealDebridApiKey',
value: this.settingRealDebridApiKey,
diff --git a/client/src/app/setup/setup.component.html b/client/src/app/setup/setup.component.html
index cbe8fac..48d53bc 100644
--- a/client/src/app/setup/setup.component.html
+++ b/client/src/app/setup/setup.component.html
@@ -28,11 +28,7 @@
-
+
Setup
@@ -46,25 +42,46 @@
+
+
Provider
+
+
+ Real-Debrid
+ AllDebrid
+
+
API Private Token
-
+
{
this.step = 3;
this.working = false;
diff --git a/client/src/app/torrent.service.ts b/client/src/app/torrent.service.ts
index 830f6ed..22e607d 100644
--- a/client/src/app/torrent.service.ts
+++ b/client/src/app/torrent.service.ts
@@ -47,7 +47,7 @@ export class TorrentService {
public uploadFile(file: File, torrent: Torrent): Observable {
const formData: FormData = new FormData();
formData.append('file', file);
- formData.append('formData', JSON.stringify(torrent));
+ formData.append('formData', JSON.stringify({ torrent }));
return this.http.post(`/Api/Torrents/UploadFile`, formData);
}
diff --git a/client/src/app/users.service.ts b/client/src/app/users.service.ts
deleted file mode 100644
index 25f96f4..0000000
--- a/client/src/app/users.service.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Injectable } from '@angular/core';
-
-@Injectable({
- providedIn: 'root',
-})
-export class UsersService {
- constructor() {}
-
- public getLoggedInUser() {}
-}
diff --git a/package.json b/package.json
index 73bd61b..bb1f232 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "rdt-client",
- "version": "1.9.6",
+ "version": "1.9.7",
"description": "This is a web interface to manage your torrents on Real-Debrid.",
"main": "index.js",
"dependencies": {
diff --git a/server/RdtClient.Data/Data/DataContext.cs b/server/RdtClient.Data/Data/DataContext.cs
index 0a5ebc7..2c9ed11 100644
--- a/server/RdtClient.Data/Data/DataContext.cs
+++ b/server/RdtClient.Data/Data/DataContext.cs
@@ -40,6 +40,12 @@ namespace RdtClient.Data.Data
{
var seedSettings = new List
{
+ new Setting
+ {
+ SettingId = "Provider",
+ Type = "String",
+ Value = "RealDebrid"
+ },
new Setting
{
SettingId = "RealDebridApiKey",
diff --git a/server/RdtClient.Data/Data/SettingData.cs b/server/RdtClient.Data/Data/SettingData.cs
index a9c97c3..dbe1437 100644
--- a/server/RdtClient.Data/Data/SettingData.cs
+++ b/server/RdtClient.Data/Data/SettingData.cs
@@ -48,6 +48,7 @@ namespace RdtClient.Data.Data
Get = new DbSettings
{
+ Provider = GetString("Provider"),
RealDebridApiKey = GetString("RealDebridApiKey"),
DownloadPath = GetString("DownloadPath"),
DownloadClient = GetString("DownloadClient"),
diff --git a/server/RdtClient.Data/Enums/TorrentStatus.cs b/server/RdtClient.Data/Enums/TorrentStatus.cs
index 3ef4341..db40839 100644
--- a/server/RdtClient.Data/Enums/TorrentStatus.cs
+++ b/server/RdtClient.Data/Enums/TorrentStatus.cs
@@ -1,6 +1,6 @@
namespace RdtClient.Data.Enums
{
- public enum RealDebridStatus
+ public enum TorrentStatus
{
Processing = 0,
WaitingForFileSelection = 1,
diff --git a/server/RdtClient.Data/Models/Data/Torrent.cs b/server/RdtClient.Data/Models/Data/Torrent.cs
index d1305b5..475ef68 100644
--- a/server/RdtClient.Data/Models/Data/Torrent.cs
+++ b/server/RdtClient.Data/Models/Data/Torrent.cs
@@ -46,7 +46,7 @@ namespace RdtClient.Data.Models.Data
public String RdHost { get; set; }
public Int64 RdSplit { get; set; }
public Int64 RdProgress { get; set; }
- public RealDebridStatus RdStatus { get; set; }
+ public TorrentStatus RdStatus { get; set; }
public String RdStatusRaw { get; set; }
public DateTimeOffset RdAdded { get; set; }
public DateTimeOffset? RdEnded { get; set; }
diff --git a/server/RdtClient.Data/Models/Internal/DbSettings.cs b/server/RdtClient.Data/Models/Internal/DbSettings.cs
index 38a028f..b079dce 100644
--- a/server/RdtClient.Data/Models/Internal/DbSettings.cs
+++ b/server/RdtClient.Data/Models/Internal/DbSettings.cs
@@ -4,6 +4,7 @@ namespace RdtClient.Data.Models.Internal
{
public class DbSettings
{
+ public String Provider { get; set; }
public String RealDebridApiKey { get; set; }
public String DownloadPath { get; set; }
public String DownloadClient { get; set; }
diff --git a/server/RdtClient.Data/Models/Internal/Profile.cs b/server/RdtClient.Data/Models/Internal/Profile.cs
index 02ce009..df1baf9 100644
--- a/server/RdtClient.Data/Models/Internal/Profile.cs
+++ b/server/RdtClient.Data/Models/Internal/Profile.cs
@@ -4,6 +4,7 @@ namespace RdtClient.Data.Models.Internal
{
public class Profile
{
+ public String Provider { get; set; }
public String UserName { get; set; }
public DateTimeOffset? Expiration { get; set; }
}
diff --git a/server/RdtClient.Data/Models/TorrentClient/TorrentClientTorrent.cs b/server/RdtClient.Data/Models/TorrentClient/TorrentClientTorrent.cs
index a87fa41..a82985c 100644
--- a/server/RdtClient.Data/Models/TorrentClient/TorrentClientTorrent.cs
+++ b/server/RdtClient.Data/Models/TorrentClient/TorrentClientTorrent.cs
@@ -15,6 +15,7 @@ namespace RdtClient.Data.Models.TorrentClient
public Int64 Split { get; set; }
public Int64 Progress { get; set; }
public String Status { get; set; }
+ public Int64 StatusCode { get; set; }
public DateTimeOffset Added { get; set; }
public List Files { get; set; }
public List Links { get; set; }
diff --git a/server/RdtClient.Data/Models/TorrentClient/TorrentClientUser.cs b/server/RdtClient.Data/Models/TorrentClient/TorrentClientUser.cs
index 269dccf..cada3bc 100644
--- a/server/RdtClient.Data/Models/TorrentClient/TorrentClientUser.cs
+++ b/server/RdtClient.Data/Models/TorrentClient/TorrentClientUser.cs
@@ -5,6 +5,6 @@ namespace RdtClient.Data.Models.TorrentClient
public class TorrentClientUser
{
public String Username { get; set; }
- public DateTimeOffset Expiration { get; set; }
+ public DateTimeOffset? Expiration { get; set; }
}
}
diff --git a/server/RdtClient.Service/DiConfig.cs b/server/RdtClient.Service/DiConfig.cs
index 0309b5c..02ec4d4 100644
--- a/server/RdtClient.Service/DiConfig.cs
+++ b/server/RdtClient.Service/DiConfig.cs
@@ -8,6 +8,7 @@ namespace RdtClient.Service
{
public static void Config(IServiceCollection services)
{
+ services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
diff --git a/server/RdtClient.Service/RdtClient.Service.csproj b/server/RdtClient.Service/RdtClient.Service.csproj
index d15366e..6758277 100644
--- a/server/RdtClient.Service/RdtClient.Service.csproj
+++ b/server/RdtClient.Service/RdtClient.Service.csproj
@@ -6,7 +6,7 @@
-
+
diff --git a/server/RdtClient.Service/Services/QBittorrent.cs b/server/RdtClient.Service/Services/QBittorrent.cs
index a35b973..ffcb54e 100644
--- a/server/RdtClient.Service/Services/QBittorrent.cs
+++ b/server/RdtClient.Service/Services/QBittorrent.cs
@@ -307,7 +307,7 @@ namespace RdtClient.Service.Services
var allDownloadsComplete = torrent.Downloads.All(m => m.Completed.HasValue);
var hasDownloadsWithErrors = torrent.Downloads.Any(m => m.Error != null);
- if (torrent.Downloads.Count == 0 || hasDownloadsWithErrors || torrent.RdStatus == RealDebridStatus.Error)
+ if (torrent.Downloads.Count == 0 || hasDownloadsWithErrors || torrent.RdStatus == TorrentStatus.Error)
{
result.State = "error";
}
diff --git a/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs
index 9914c8c..92d2dcc 100644
--- a/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs
+++ b/server/RdtClient.Service/Services/TorrentClients/AllDebridTorrentClient.cs
@@ -4,16 +4,23 @@ using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using AllDebridNET;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RdtClient.Data.Enums;
+using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.TorrentClient;
+using RdtClient.Service.Helpers;
namespace RdtClient.Service.Services.TorrentClients
{
public class AllDebridTorrentClient : ITorrentClient
{
+ private readonly ILogger _logger;
private readonly IHttpClientFactory _httpClientFactory;
- public AllDebridTorrentClient(IHttpClientFactory httpClientFactory)
+ public AllDebridTorrentClient(ILogger logger, IHttpClientFactory httpClientFactory)
{
+ _logger = logger;
_httpClientFactory = httpClientFactory;
}
@@ -48,13 +55,14 @@ namespace RdtClient.Service.Services.TorrentClients
Split = 0,
Progress = torrent.ProcessingPerc,
Status = torrent.Status,
+ StatusCode = torrent.StatusCode,
Added = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.UploadDate),
- Files = (torrent.Links ?? new List ()).Select(m => new TorrentClientFile
+ Files = (torrent.Links ?? new List ()).Select((m, i) => new TorrentClientFile
{
Path = m.Filename,
Bytes = m.Size,
- Id = 0,
- Selected = true
+ Id = i,
+ Selected = true,
}).ToList(),
Links = (torrent.Links ?? new List ()).Select(m => m.LinkUrl.ToString()).ToList(),
Ended = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.CompletionDate),
@@ -76,7 +84,7 @@ namespace RdtClient.Service.Services.TorrentClients
return new TorrentClientUser
{
Username = user.Username,
- Expiration = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(user.PremiumUntil)
+ Expiration = user.PremiumUntil > 0 ? new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(user.PremiumUntil) : null
};
}
@@ -94,12 +102,26 @@ namespace RdtClient.Service.Services.TorrentClients
return result.Id.ToString();
}
- public Task> GetAvailableFiles(String hash)
+ public async Task> GetAvailableFiles(String hash)
{
- return Task.FromResult(new List());
+ var isAvailable = await GetClient().Magnet.InstantAvailabilityAsync(hash);
+
+ if (isAvailable)
+ {
+ return new List
+ {
+ new TorrentClientAvailableFile
+ {
+ Filename = "All files",
+ Filesize = 0
+ }
+ };
+ }
+
+ return new List();
}
- public Task SelectFiles(String torrentId, IList fileIds)
+ public Task SelectFiles(Torrent torrent)
{
return Task.CompletedTask;
}
@@ -122,5 +144,136 @@ namespace RdtClient.Service.Services.TorrentClients
return result.Link;
}
+
+ public async Task UpdateData(Torrent torrent, TorrentClientTorrent torrentClientTorrent)
+ {
+ try
+ {
+ torrentClientTorrent ??= await GetInfo(torrent.RdId);
+
+ if (!String.IsNullOrWhiteSpace(torrentClientTorrent.Filename))
+ {
+ torrent.RdName = torrentClientTorrent.Filename;
+ }
+
+ if (torrentClientTorrent.Bytes > 0)
+ {
+ torrent.RdSize = torrentClientTorrent.Bytes;
+ }
+
+ if (torrentClientTorrent.Files != null)
+ {
+ torrent.RdFiles = JsonConvert.SerializeObject(torrentClientTorrent.Files);
+ }
+
+ torrent.RdHost = torrentClientTorrent.Host;
+ torrent.RdSplit = torrentClientTorrent.Split;
+ torrent.RdProgress = torrentClientTorrent.Progress;
+ torrent.RdAdded = torrentClientTorrent.Added;
+ torrent.RdEnded = torrentClientTorrent.Ended;
+ torrent.RdSpeed = torrentClientTorrent.Speed;
+ torrent.RdSeeders = torrentClientTorrent.Seeders;
+ torrent.RdStatusRaw = torrentClientTorrent.Status;
+
+ torrent.RdStatus = torrentClientTorrent.StatusCode switch
+ {
+ 0 => TorrentStatus.Processing, // Processing In Queue.
+ 1 => TorrentStatus.Downloading, // Processing Downloading.
+ 2 => TorrentStatus.Downloading, // Processing Compressing / Moving.
+ 3 => TorrentStatus.Uploading, // Processing Uploading.
+ 4 => TorrentStatus.Finished, // Finished Ready.
+ 5 => TorrentStatus.Error, // Error Upload fail.
+ 6 => TorrentStatus.Error, // Error Internal error on unpacking.
+ 7 => TorrentStatus.Error, // Error Not downloaded in 20 min.
+ 8 => TorrentStatus.Error, // Error File too big.
+ 9 => TorrentStatus.Error, // Error Internal error.
+ 10 => TorrentStatus.Error, // Error Download took more than 72h.
+ 11 => TorrentStatus.Error, // Error Deleted on the hoster website
+ _ => TorrentStatus.Error
+ };
+ }
+ catch (Exception ex)
+ {
+ if (ex.Message == "Resource not found")
+ {
+ torrent.RdStatusRaw = "deleted";
+ }
+ else
+ {
+ throw;
+ }
+ }
+
+ return torrent;
+ }
+
+ public async Task> GetDownloadLinks(Torrent torrent)
+ {
+ var magnet = await GetClient().Magnet.StatusAsync(torrent.RdId);
+
+ var links = magnet.Links;
+
+ Log($"Getting download links", torrent);
+
+ if (torrent.DownloadMinSize > 0)
+ {
+ var minFileSize = torrent.DownloadMinSize * 1024 * 1024;
+
+ Log($"Determining which files are over {minFileSize} bytes", torrent);
+
+ links = links.Where(m => m.Size > minFileSize)
+ .ToList();
+
+ Log($"Found {links.Count} files that match the minimum file size criterea", torrent);
+ }
+
+ if (links.Count == 0)
+ {
+ Log($"Filtered all files out! Downloading ALL files instead!", torrent);
+
+ links = magnet.Links;
+ }
+
+ Log($"Selecting links:");
+
+ foreach (var link in links)
+ {
+ var fileList = link.Files.SelectMany(file => GetFiles(file));
+
+ Log($"{link.Filename} ({link.Size}b) {link.LinkUrl}, contains {String.Join(", ", fileList)}");
+ }
+
+ Log("", torrent);
+
+ return links.Select(m => m.LinkUrl.ToString()).ToList();
+ }
+
+ private static IList GetFiles(File file, String parent = null)
+ {
+ var result = new List
+ {
+ $"{parent}/{file.Name}"
+ };
+
+ if (file.Files != null && file.Files.Count > 0)
+ {
+ foreach (var subFile in file.Files)
+ {
+ result.AddRange(GetFiles(subFile, file.Name));
+ }
+ }
+
+ return result;
+ }
+
+ private void Log(String message, Torrent torrent = null)
+ {
+ if (torrent != null)
+ {
+ message = $"{message} {torrent.ToLog()}";
+ }
+
+ _logger.LogDebug(message);
+ }
}
}
diff --git a/server/RdtClient.Service/Services/TorrentClients/ITorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/ITorrentClient.cs
index 948ca56..8f0b2c9 100644
--- a/server/RdtClient.Service/Services/TorrentClients/ITorrentClient.cs
+++ b/server/RdtClient.Service/Services/TorrentClients/ITorrentClient.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.TorrentClient;
namespace RdtClient.Service.Services.TorrentClients
@@ -11,10 +12,12 @@ namespace RdtClient.Service.Services.TorrentClients
Task GetUser();
Task AddMagnet(String magnetLink);
Task AddFile(Byte[] bytes);
- Task> GetAvailableFiles(String hash);
- Task SelectFiles(String torrentId, IList fileIds);
+ Task> GetAvailableFiles(String hash);
+ Task SelectFiles(Torrent torrent);
Task GetInfo(String torrentId);
Task Delete(String torrentId);
Task Unrestrict(String link);
+ Task UpdateData(Torrent torrent, TorrentClientTorrent torrentClientTorrent);
+ Task> GetDownloadLinks(Torrent torrent);
}
}
diff --git a/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs b/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs
index 39f66bb..ec40d61 100644
--- a/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs
+++ b/server/RdtClient.Service/Services/TorrentClients/RealDebridTorrentClient.cs
@@ -3,17 +3,23 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
using RDNET;
+using RdtClient.Data.Enums;
using RdtClient.Data.Models.TorrentClient;
+using RdtClient.Service.Helpers;
namespace RdtClient.Service.Services.TorrentClients
{
public class RealDebridTorrentClient : ITorrentClient
{
+ private readonly ILogger _logger;
private readonly IHttpClientFactory _httpClientFactory;
- public RealDebridTorrentClient(IHttpClientFactory httpClientFactory)
+ public RealDebridTorrentClient(ILogger logger, IHttpClientFactory httpClientFactory)
{
+ _logger = logger;
_httpClientFactory = httpClientFactory;
}
@@ -93,7 +99,7 @@ namespace RdtClient.Service.Services.TorrentClients
return new TorrentClientUser
{
Username = user.Username,
- Expiration = user.Expiration
+ Expiration = user.Premium > 0 ? user.Expiration : null
};
}
@@ -111,7 +117,7 @@ namespace RdtClient.Service.Services.TorrentClients
return result.Id;
}
- public async Task> GetAvailableFiles(String hash)
+ public async Task> GetAvailableFiles(String hash)
{
var result = await GetClient().Torrents.GetAvailableFiles(hash);
@@ -128,9 +134,66 @@ namespace RdtClient.Service.Services.TorrentClients
return torrentClientAvailableFiles;
}
- public async Task SelectFiles(String torrentId, IList fileIds)
+ public async Task SelectFiles(Data.Models.Data.Torrent torrent)
{
- await GetClient().Torrents.SelectFilesAsync(torrentId, fileIds.ToArray());
+ var files = torrent.Files;
+
+ Log("Seleting files", torrent);
+
+ if (torrent.DownloadAction == TorrentDownloadAction.DownloadAvailableFiles)
+ {
+ Log($"Determining which files are already available on RealDebrid", torrent);
+
+ var availableFiles = await GetAvailableFiles(torrent.Hash);
+
+ Log($"Found {files.Count}/{torrent.Files.Count} available files on RealDebrid", torrent);
+
+ files = torrent.Files.Where(m => availableFiles.Any(f => m.Path.EndsWith(f.Filename))).ToList();
+ }
+ else if (torrent.DownloadAction == TorrentDownloadAction.DownloadAll)
+ {
+ Log("Selecting all files", torrent);
+ files = torrent.Files.ToList();
+ }
+ else if (torrent.DownloadAction == TorrentDownloadAction.DownloadManual)
+ {
+ Log("Selecting manual selected files", torrent);
+ files = torrent.Files.Where(m => torrent.ManualFiles.Any(f => m.Path.EndsWith(f))).ToList();
+ }
+
+ Log($"Selecting {files.Count}/{torrent.Files.Count} files", torrent);
+
+ if (torrent.DownloadAction != TorrentDownloadAction.DownloadManual && torrent.DownloadMinSize > 0)
+ {
+ var minFileSize = torrent.DownloadMinSize * 1024 * 1024;
+
+ Log($"Determining which files are over {minFileSize} bytes", torrent);
+
+ files = files.Where(m => m.Bytes > minFileSize)
+ .ToList();
+
+ Log($"Found {files.Count} files that match the minimum file size criterea", torrent);
+ }
+
+ if (files.Count == 0)
+ {
+ Log($"Filtered all files out! Downloading ALL files instead!", torrent);
+
+ files = torrent.Files;
+ }
+
+ var fileIds = files.Select(m => m.Id.ToString()).ToArray();
+
+ Log($"Selecting files:");
+
+ foreach (var file in files)
+ {
+ Log($"{file.Id}: {file.Path} ({file.Bytes}b)");
+ }
+
+ Log("", torrent);
+
+ await GetClient().Torrents.SelectFilesAsync(torrent.RdId, fileIds.ToArray());
}
public async Task GetInfo(String torrentId)
@@ -151,5 +214,104 @@ namespace RdtClient.Service.Services.TorrentClients
return result.Download;
}
+
+ public async Task UpdateData(Data.Models.Data.Torrent torrent, TorrentClientTorrent torrentClientTorrent)
+ {
+ try
+ {
+ var rdTorrent = await GetInfo(torrent.RdId);
+
+ if (!String.IsNullOrWhiteSpace(rdTorrent.Filename))
+ {
+ torrent.RdName = rdTorrent.Filename;
+ }
+
+ if (!String.IsNullOrWhiteSpace(rdTorrent.OriginalFilename))
+ {
+ torrent.RdName = rdTorrent.OriginalFilename;
+ }
+
+ if (rdTorrent.Bytes > 0)
+ {
+ torrent.RdSize = rdTorrent.Bytes;
+ }
+ else if (rdTorrent.OriginalBytes > 0)
+ {
+ torrent.RdSize = rdTorrent.OriginalBytes;
+ }
+
+ if (rdTorrent.Files != null)
+ {
+ torrent.RdFiles = JsonConvert.SerializeObject(rdTorrent.Files);
+ }
+
+ torrent.RdHost = rdTorrent.Host;
+ torrent.RdSplit = rdTorrent.Split;
+ torrent.RdProgress = rdTorrent.Progress;
+ torrent.RdAdded = rdTorrent.Added;
+ torrent.RdEnded = rdTorrent.Ended;
+ torrent.RdSpeed = rdTorrent.Speed;
+ torrent.RdSeeders = rdTorrent.Seeders;
+ torrent.RdStatusRaw = rdTorrent.Status;
+
+ torrent.RdStatus = rdTorrent.Status switch
+ {
+ "magnet_error" => TorrentStatus.Error,
+ "magnet_conversion" => TorrentStatus.Processing,
+ "waiting_files_selection" => TorrentStatus.WaitingForFileSelection,
+ "queued" => TorrentStatus.Downloading,
+ "downloading" => TorrentStatus.Downloading,
+ "downloaded" => TorrentStatus.Finished,
+ "error" => TorrentStatus.Error,
+ "virus" => TorrentStatus.Error,
+ "compressing" => TorrentStatus.Downloading,
+ "uploading" => TorrentStatus.Uploading,
+ "dead" => TorrentStatus.Error,
+ _ => TorrentStatus.Error
+ };
+ }
+ catch (Exception ex)
+ {
+ if (ex.Message == "Resource not found")
+ {
+ torrent.RdStatusRaw = "deleted";
+ }
+ else
+ {
+ throw;
+ }
+ }
+
+ return torrent;
+ }
+
+ public async Task> GetDownloadLinks(Data.Models.Data.Torrent torrent)
+ {
+ var rdTorrent = await GetInfo(torrent.RdId);
+
+ var torrentLinks = rdTorrent.Links.Where(m => !String.IsNullOrWhiteSpace(m)).ToList();
+
+ Log($"Found {torrentLinks} links", torrent);
+
+ // Sometimes RD will give you 1 rar with all files, sometimes it will give you 1 link per file.
+ if (torrent.Files.Count(m => m.Selected) != torrentLinks.Count &&
+ torrent.ManualFiles.Count != torrentLinks.Count &&
+ torrentLinks.Count != 1)
+ {
+ return null;
+ }
+
+ return torrentLinks;
+ }
+
+ private void Log(String message, Data.Models.Data.Torrent torrent = null)
+ {
+ if (torrent != null)
+ {
+ message = $"{message} {torrent.ToLog()}";
+ }
+
+ _logger.LogDebug(message);
+ }
}
}
diff --git a/server/RdtClient.Service/Services/TorrentRunner.cs b/server/RdtClient.Service/Services/TorrentRunner.cs
index fb41a06..afdf98a 100644
--- a/server/RdtClient.Service/Services/TorrentRunner.cs
+++ b/server/RdtClient.Service/Services/TorrentRunner.cs
@@ -473,7 +473,7 @@ namespace RdtClient.Service.Services
Log("Processing", torrent);
// If torrent is erroring out on the Real-Debrid side.
- if (torrent.RdStatus == RealDebridStatus.Error)
+ if (torrent.RdStatus == TorrentStatus.Error)
{
Log($"Torrent reported an error: {torrent.RdStatusRaw}", torrent);
Log($"Torrent retry count {torrent.RetryCount}/{torrent.TorrentRetryAttempts}", torrent);
@@ -486,75 +486,26 @@ namespace RdtClient.Service.Services
}
// Real-Debrid is waiting for file selection, select which files to download.
- if ((torrent.RdStatus == RealDebridStatus.WaitingForFileSelection || torrent.RdStatus == RealDebridStatus.Finished) &&
+ if ((torrent.RdStatus == TorrentStatus.WaitingForFileSelection || torrent.RdStatus == TorrentStatus.Finished) &&
torrent.FilesSelected == null &&
- torrent.Downloads.Count == 0 &&
- torrent.FilesSelected == null)
+ torrent.Downloads.Count == 0)
{
Log($"Selecting files", torrent);
- var files = torrent.Files;
-
- if (torrent.DownloadAction == TorrentDownloadAction.DownloadAvailableFiles)
- {
- Log($"Determining which files are already available on RealDebrid", torrent);
-
- var availableFiles = await _torrents.GetAvailableFiles(torrent.Hash);
-
- Log($"Found {files.Count}/{torrent.Files.Count} available files on RealDebrid", torrent);
-
- files = torrent.Files.Where(m => availableFiles.Any(f => m.Path.EndsWith(f.Filename))).ToList();
- }
- else if (torrent.DownloadAction == TorrentDownloadAction.DownloadAll)
- {
- Log("Selecting all files", torrent);
- files = torrent.Files.ToList();
- }
- else if (torrent.DownloadAction == TorrentDownloadAction.DownloadManual)
- {
- Log("Selecting manual selected files", torrent);
- files = torrent.Files.Where(m => torrent.ManualFiles.Any(f => m.Path.EndsWith(f))).ToList();
- }
-
- Log($"Selecting {files.Count}/{torrent.Files.Count} files", torrent);
-
- if (torrent.DownloadAction != TorrentDownloadAction.DownloadManual && torrent.DownloadMinSize > 0)
- {
- var minFileSize = torrent.DownloadMinSize * 1024 * 1024;
-
- Log($"Determining which files are over {minFileSize} bytes", torrent);
-
- files = files.Where(m => m.Bytes > minFileSize)
- .ToList();
-
- Log($"Found {files.Count} files that match the minimum file size criterea", torrent);
- }
-
- if (files.Count == 0)
- {
- Log($"Filtered all files out! Downloading ALL files instead!", torrent);
-
- files = torrent.Files;
- }
-
- var fileIds = files.Select(m => m.Id.ToString()).ToArray();
-
- Log($"Selecting files:{Environment.NewLine}{String.Join(Environment.NewLine, files.Select(m => m.Path))}", torrent);
-
- await _torrents.SelectFiles(torrent.TorrentId, fileIds);
+ await _torrents.SelectFiles(torrent.TorrentId);
await _torrents.UpdateFilesSelected(torrent.TorrentId, DateTime.UtcNow);
}
// Real-Debrid finished downloading the torrent, process the file to host.
- if (torrent.RdStatus == RealDebridStatus.Finished)
+ if (torrent.RdStatus == TorrentStatus.Finished)
{
// The files are selected but there are no downloads yet, check if Real-Debrid has generated links yet.
if (torrent.Downloads.Count == 0 && torrent.FilesSelected != null)
{
- Log($"Checking for links", torrent);
+ Log($"Creating downloads", torrent);
- await _torrents.CheckForLinks(torrent.TorrentId);
+ await _torrents.CreateDownloads(torrent.TorrentId);
}
}
diff --git a/server/RdtClient.Service/Services/Torrents.cs b/server/RdtClient.Service/Services/Torrents.cs
index 1adc1dd..ab3a511 100644
--- a/server/RdtClient.Service/Services/Torrents.cs
+++ b/server/RdtClient.Service/Services/Torrents.cs
@@ -8,7 +8,6 @@ using Microsoft.Extensions.Logging;
using MonoTorrent;
using Newtonsoft.Json;
using RdtClient.Data.Data;
-using RdtClient.Data.Enums;
using RdtClient.Data.Models.Internal;
using RdtClient.Data.Models.TorrentClient;
using RdtClient.Service.Helpers;
@@ -27,18 +26,24 @@ namespace RdtClient.Service.Services
private readonly ITorrentClient _torrentClient;
- public static readonly SemaphoreSlim TorrentResetLock = new(1, 1);
+ private static readonly SemaphoreSlim TorrentResetLock = new(1, 1);
public Torrents(ILogger logger,
TorrentData torrentData,
Downloads downloads,
+ AllDebridTorrentClient allDebridTorrentClient,
RealDebridTorrentClient realDebridTorrentClient)
{
_logger = logger;
_torrentData = torrentData;
_downloads = downloads;
- _torrentClient = realDebridTorrentClient;
+ _torrentClient = Settings.Get.Provider switch
+ {
+ "RealDebrid" => realDebridTorrentClient,
+ "AllDebrid" => allDebridTorrentClient,
+ _ => null
+ };
}
public async Task> Get()
@@ -73,7 +78,7 @@ namespace RdtClient.Service.Services
if (torrent != null)
{
- await UpdateRdData(torrent);
+ await UpdateTorrentClientData(torrent);
}
return torrent;
@@ -144,14 +149,14 @@ namespace RdtClient.Service.Services
return newTorrent;
}
- public async Task> GetAvailableFiles(String hash)
+ public async Task> GetAvailableFiles(String hash)
{
var result = await _torrentClient.GetAvailableFiles(hash);
return result;
}
- public async Task SelectFiles(Guid torrentId, IList fileIds)
+ public async Task SelectFiles(Guid torrentId)
{
var torrent = await GetById(torrentId);
@@ -160,10 +165,10 @@ namespace RdtClient.Service.Services
return;
}
- await _torrentClient.SelectFiles(torrent.RdId, fileIds);
+ await _torrentClient.SelectFiles(torrent);
}
- public async Task CheckForLinks(Guid torrentId)
+ public async Task CreateDownloads(Guid torrentId)
{
var torrent = await GetById(torrentId);
@@ -172,16 +177,9 @@ namespace RdtClient.Service.Services
return;
}
- var rdTorrent = await _torrentClient.GetInfo(torrent.RdId);
+ var torrentLinks = await _torrentClient.GetDownloadLinks(torrent);
- var torrentLinks = rdTorrent.Links.Where(m => !String.IsNullOrWhiteSpace(m)).ToList();
-
- Log($"Found {torrentLinks} links", torrent);
-
- // Sometimes RD will give you 1 rar with all files, sometimes it will give you 1 link per file.
- if (torrent.Files.Count(m => m.Selected) != torrentLinks.Count &&
- torrent.ManualFiles.Count != torrentLinks.Count &&
- torrentLinks.Count != 1)
+ if (torrentLinks == null)
{
return;
}
@@ -313,6 +311,7 @@ namespace RdtClient.Service.Services
var profile = new Profile
{
+ Provider = Settings.Get.Provider,
UserName = user.Username,
Expiration = user.Expiration
};
@@ -339,7 +338,7 @@ namespace RdtClient.Service.Services
continue;
}
- await UpdateRdData(torrent);
+ await UpdateTorrentClientData(torrent, rdTorrent);
}
foreach (var torrent in torrents)
@@ -509,7 +508,7 @@ namespace RdtClient.Service.Services
return null;
}
- await UpdateRdData(torrent);
+ await UpdateTorrentClientData(torrent);
foreach (var download in torrent.Downloads)
{
@@ -565,7 +564,7 @@ namespace RdtClient.Service.Services
isFile,
torrent);
- await UpdateRdData(newTorrent);
+ await UpdateTorrentClientData(newTorrent);
return newTorrent;
}
@@ -580,7 +579,7 @@ namespace RdtClient.Service.Services
await _torrentData.Update(torrent);
}
- private async Task UpdateRdData(Torrent torrent)
+ private async Task UpdateTorrentClientData(Torrent torrent, TorrentClientTorrent torrentClientTorrent = null)
{
var originalTorrent = JsonConvert.SerializeObject(torrent,
new JsonSerializerSettings
@@ -588,70 +587,7 @@ namespace RdtClient.Service.Services
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
- try
- {
- var rdTorrent = await _torrentClient.GetInfo(torrent.RdId);
-
- if (!String.IsNullOrWhiteSpace(rdTorrent.Filename))
- {
- torrent.RdName = rdTorrent.Filename;
- }
-
- if (!String.IsNullOrWhiteSpace(rdTorrent.OriginalFilename))
- {
- torrent.RdName = rdTorrent.OriginalFilename;
- }
-
- if (rdTorrent.Bytes > 0)
- {
- torrent.RdSize = rdTorrent.Bytes;
- }
- else if (rdTorrent.OriginalBytes > 0)
- {
- torrent.RdSize = rdTorrent.OriginalBytes;
- }
-
- if (rdTorrent.Files != null)
- {
- torrent.RdFiles = JsonConvert.SerializeObject(rdTorrent.Files);
- }
-
- torrent.RdHost = rdTorrent.Host;
- torrent.RdSplit = rdTorrent.Split;
- torrent.RdProgress = rdTorrent.Progress;
- torrent.RdAdded = rdTorrent.Added;
- torrent.RdEnded = rdTorrent.Ended;
- torrent.RdSpeed = rdTorrent.Speed;
- torrent.RdSeeders = rdTorrent.Seeders;
- torrent.RdStatusRaw = rdTorrent.Status;
-
- torrent.RdStatus = rdTorrent.Status switch
- {
- "magnet_error" => RealDebridStatus.Error,
- "magnet_conversion" => RealDebridStatus.Processing,
- "waiting_files_selection" => RealDebridStatus.WaitingForFileSelection,
- "queued" => RealDebridStatus.Downloading,
- "downloading" => RealDebridStatus.Downloading,
- "downloaded" => RealDebridStatus.Finished,
- "error" => RealDebridStatus.Error,
- "virus" => RealDebridStatus.Error,
- "compressing" => RealDebridStatus.Downloading,
- "uploading" => RealDebridStatus.Uploading,
- "dead" => RealDebridStatus.Error,
- _ => RealDebridStatus.Error
- };
- }
- catch (Exception ex)
- {
- if (ex.Message == "Resource not found")
- {
- torrent.RdStatusRaw = "deleted";
- }
- else
- {
- throw;
- }
- }
+ await _torrentClient.UpdateData(torrent, torrentClientTorrent);
var newTorrent = JsonConvert.SerializeObject(torrent,
new JsonSerializerSettings
diff --git a/server/RdtClient.Web/Controllers/TorrentsController.cs b/server/RdtClient.Web/Controllers/TorrentsController.cs
index d429293..ebfffe4 100644
--- a/server/RdtClient.Web/Controllers/TorrentsController.cs
+++ b/server/RdtClient.Web/Controllers/TorrentsController.cs
@@ -77,6 +77,15 @@ namespace RdtClient.Web.Controllers
[ModelBinder(BinderType = typeof(JsonModelBinder))]
TorrentControllerUploadFileRequest formData)
{
+ if (!ModelState.IsValid)
+ {
+ var errors = ModelState.Select(x => x.Value.Errors)
+ .Where(y => y.Count > 0)
+ .ToList();
+
+ return BadRequest(errors);
+ }
+
if (file == null || file.Length <= 0)
{
throw new Exception("Invalid torrent file");
@@ -99,6 +108,15 @@ namespace RdtClient.Web.Controllers
[Route("UploadMagnet")]
public async Task UploadMagnet([FromBody] TorrentControllerUploadMagnetRequest request)
{
+ if (!ModelState.IsValid)
+ {
+ var errors = ModelState.Select(x => x.Value.Errors)
+ .Where(y => y.Count > 0)
+ .ToList();
+
+ return BadRequest(errors);
+ }
+
await _torrents.UploadMagnet(request.MagnetLink, request.Torrent);
return Ok();
@@ -152,6 +170,7 @@ namespace RdtClient.Web.Controllers
[Route("Retry/{torrentId:guid}")]
public async Task Retry(Guid torrentId)
{
+ await _torrents.UpdateRetry(torrentId, DateTimeOffset.UtcNow, 0);
await _torrents.RetryTorrent(torrentId, 0);
return Ok();
diff --git a/server/RdtClient.Web/RdtClient.Web.csproj b/server/RdtClient.Web/RdtClient.Web.csproj
index 376a376..e1960d3 100644
--- a/server/RdtClient.Web/RdtClient.Web.csproj
+++ b/server/RdtClient.Web/RdtClient.Web.csproj
@@ -4,7 +4,7 @@
net5.0
Exe
94c24cba-f03f-4453-a671-3640b517c573
- 1.9.6
+ 1.9.7