Add UI elements for TorBox, fix downloads.

This commit is contained in:
Sam Heinz 2024-08-28 17:05:56 +10:00
parent 395f83847e
commit c34f91fc27
12 changed files with 92 additions and 32 deletions

View file

@ -74,7 +74,10 @@
<div class="field"> <div class="field">
<label class="label">Post Torrent Download Action</label> <label class="label">Post Torrent Download Action</label>
<div class="control select is-fullwidth"> <div class="control select is-fullwidth">
<select [(ngModel)]="downloadAction" [disabled]="provider === 'AllDebrid' || provider === 'Premiumize'"> <select
[(ngModel)]="downloadAction"
[disabled]="provider === 'AllDebrid' || provider === 'Premiumize' || provider === 'TorBox'"
>
<option [ngValue]="0">Download all files</option> <option [ngValue]="0">Download all files</option>
<option [ngValue]="1">Download all available files</option> <option [ngValue]="1">Download all available files</option>
<option [ngValue]="2">Manually pick files</option> <option [ngValue]="2">Manually pick files</option>
@ -82,7 +85,7 @@
</div> </div>
<p class="help">When a torrent is fully downloaded on the provider, perform this action.</p> <p class="help">When a torrent is fully downloaded on the provider, perform this action.</p>
<p class="help" *ngIf="provider === 'AllDebrid'"> <p class="help" *ngIf="provider === 'AllDebrid'">
This option is only available for RealDebrid. AllDebrid and Premiumize will always download the full torrent. This option is only available for RealDebrid. AllDebrid, Premiumize, and Torbox will always download the full torrent.
</p> </p>
</div> </div>

View file

@ -15,7 +15,11 @@ export class NavbarComponent implements OnInit {
public profile: Profile; public profile: Profile;
public providerLink: string; public providerLink: string;
constructor(private settingsService: SettingsService, private authService: AuthService, private router: Router) {} constructor(
private settingsService: SettingsService,
private authService: AuthService,
private router: Router,
) {}
ngOnInit(): void { ngOnInit(): void {
this.settingsService.getProfile().subscribe((result) => { this.settingsService.getProfile().subscribe((result) => {
@ -31,6 +35,9 @@ export class NavbarComponent implements OnInit {
case 'Premiumize': case 'Premiumize':
this.providerLink = 'https://www.premiumize.me/'; this.providerLink = 'https://www.premiumize.me/';
break; break;
case 'TorBox':
this.providerLink = 'https://torbox.app/';
break;
} }
}); });
} }
@ -40,7 +47,7 @@ export class NavbarComponent implements OnInit {
() => { () => {
this.router.navigate(['/login']); this.router.navigate(['/login']);
}, },
(err) => {} (err) => {},
); );
} }
} }

View file

@ -42,7 +42,7 @@
<div class="notification is-primary"> <div class="notification is-primary">
To be able to use the Real-Debrid Client you need a premium subscription to download torrents. To be able to use the Real-Debrid Client you need a premium subscription to download torrents.
<br /><br /> <br /><br />
Not premium yet? You have the choice of 2 providers: Not premium yet? You have the choice of 4 providers:
<br /> <br />
<a href="https://real-debrid.com/?id=1348683" target="_blank" rel="noopener" <a href="https://real-debrid.com/?id=1348683" target="_blank" rel="noopener"
>Use this link to sign up to Real-Debrid.</a >Use this link to sign up to Real-Debrid.</a
@ -55,6 +55,7 @@
<a href="https://www.premiumize.me/" target="_blank" rel="noopener" <a href="https://www.premiumize.me/" target="_blank" rel="noopener"
>Use this link to sign up to Premiumize.</a >Use this link to sign up to Premiumize.</a
> >
<a href="https://torbox.app/" target="_blank" rel="noopener">Use this link to sign up to Premiumize.</a>
<br /> <br />
<small>(Referal links)</small> <small>(Referal links)</small>
</div> </div>
@ -65,6 +66,7 @@
<option [ngValue]="0">Real-Debrid</option> <option [ngValue]="0">Real-Debrid</option>
<option [ngValue]="1">AllDebrid</option> <option [ngValue]="1">AllDebrid</option>
<option [ngValue]="2">Premiumize</option> <option [ngValue]="2">Premiumize</option>
<option [ngValue]="3">TorBox</option>
</select> </select>
</div> </div>
</div> </div>
@ -91,6 +93,10 @@
>https://www.premiumize.me/account</a >https://www.premiumize.me/account</a
>. >.
</p> </p>
<p class="help" *ngIf="provider === 3">
You can find your API key here:
<a href="https://torbox.app/settings" target="_blank" rel="noopener">https://torbox.app/settings</a>.
</p>
</div> </div>
<div class="field"> <div class="field">

View file

@ -11,5 +11,8 @@ public enum Provider
AllDebrid, AllDebrid,
[Description("Premiumize")] [Description("Premiumize")]
Premiumize Premiumize,
[Description("TorBox")]
TorBox
} }

View file

@ -140,10 +140,11 @@ http://127.0.0.1:6800/jsonrpc.")]
public class DbSettingsProvider public class DbSettingsProvider
{ {
[DisplayName("Provider")] [DisplayName("Provider")]
[Description(@"The following 3 providers are supported: [Description(@"The following 4 providers are supported:
<a href=""https://real-debrid.com/?id=1348683"" target=""_blank"" rel=""noopener"">https://real-debrid.com</a> <a href=""https://real-debrid.com/?id=1348683"" target=""_blank"" rel=""noopener"">https://real-debrid.com</a>
<a href=""https://alldebrid.com/?uid=2v91l&lang=en"" target=""_blank"" rel=""noopener"">https://alldebrid.com</a> <a href=""https://alldebrid.com/?uid=2v91l&lang=en"" target=""_blank"" rel=""noopener"">https://alldebrid.com</a>
<a href=""https://www.premiumize.me/"" target=""_blank"" rel=""noopener"">https://www.premiumize.me/</a> <a href=""https://www.premiumize.me/"" target=""_blank"" rel=""noopener"">https://www.premiumize.me/</a>
<a href=""https://torbox.app/"" target=""_blank"" rel=""noopener"">https://torbox.app/</a>
At this point only 1 provider can be used at the time.")] At this point only 1 provider can be used at the time.")]
public Provider Provider { get; set; } = Provider.RealDebrid; public Provider Provider { get; set; } = Provider.RealDebrid;
@ -153,7 +154,9 @@ At this point only 1 provider can be used at the time.")]
or or
<a href=""""https://alldebrid.com/apikeys/"""" target=""""_blank"""" rel=""""noopener"""">https://alldebrid.com/apikeys/</a> <a href=""""https://alldebrid.com/apikeys/"""" target=""""_blank"""" rel=""""noopener"""">https://alldebrid.com/apikeys/</a>
or or
<a href=""https://www.premiumize.me/account/"" target=""_blank"" rel=""noopener"">https://www.premiumize.me/account/</a>")] <a href=""https://www.premiumize.me/account/"" target=""_blank"" rel=""noopener"">https://www.premiumize.me/account/</a>
or
<a href=""""https://torbox.app/settings/"""" target=""""_blank"""" rel=""""noopener"""">https://torbox.app/settings/</a>")]
public String ApiKey { get; set; } = ""; public String ApiKey { get; set; } = "";
[DisplayName("Automatically import and process torrents added to provider")] [DisplayName("Automatically import and process torrents added to provider")]

View file

@ -24,6 +24,7 @@ public static class DiConfig
services.AddScoped<RemoteService>(); services.AddScoped<RemoteService>();
services.AddScoped<RealDebridTorrentClient>(); services.AddScoped<RealDebridTorrentClient>();
services.AddScoped<Settings>(); services.AddScoped<Settings>();
services.AddScoped<TorBoxTorrentClient>();
services.AddScoped<Torrents>(); services.AddScoped<Torrents>();
services.AddScoped<TorrentRunner>(); services.AddScoped<TorrentRunner>();

View file

@ -1,11 +1,14 @@
using System.Web; using System;
using System.Web;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
using RdtClient.Service.Services;
namespace RdtClient.Service.Helpers; namespace RdtClient.Service.Helpers;
public static class DownloadHelper public static class DownloadHelper
{ {
public static String? GetDownloadPath(String downloadPath, Torrent torrent, Download download) public static async Task<String?> GetDownloadPath(String downloadPath, Torrent torrent, Download download)
{ {
var fileUrl = download.Link; var fileUrl = download.Link;
@ -21,6 +24,20 @@ public static class DownloadHelper
var fileName = uri.Segments.Last(); var fileName = uri.Segments.Last();
if (Settings.Get.Provider.Provider == Provider.TorBox)
{
using (HttpClient client = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Head, uri);
HttpResponseMessage response = await client.SendAsync(request);
if (response.Content.Headers.ContentDisposition != null)
{
fileName = response.Content.Headers.ContentDisposition.FileName!.Trim('"');
}
}
}
fileName = HttpUtility.UrlDecode(fileName); fileName = HttpUtility.UrlDecode(fileName);
fileName = FileHelper.RemoveInvalidFileNameChars(fileName); fileName = FileHelper.RemoveInvalidFileNameChars(fileName);
@ -48,10 +65,12 @@ public static class DownloadHelper
var filePath = Path.Combine(torrentPath, fileName); var filePath = Path.Combine(torrentPath, fileName);
Console.WriteLine($"FILEPATH HERE {filePath}");
return filePath; return filePath;
} }
public static String? GetDownloadPath(Torrent torrent, Download download) public static async Task<String?> GetDownloadPath(Torrent torrent, Download download)
{ {
var fileUrl = download.Link; var fileUrl = download.Link;
@ -65,6 +84,20 @@ public static class DownloadHelper
var fileName = uri.Segments.Last(); var fileName = uri.Segments.Last();
if (Settings.Get.Provider.Provider == Provider.TorBox)
{
using (HttpClient client = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Head, uri);
HttpResponseMessage response = await client.SendAsync(request);
if (response.Content.Headers.ContentDisposition != null)
{
fileName = response.Content.Headers.ContentDisposition.FileName!.Trim('"');
}
}
}
fileName = HttpUtility.UrlDecode(fileName); fileName = HttpUtility.UrlDecode(fileName);
fileName = FileHelper.RemoveInvalidFileNameChars(fileName); fileName = FileHelper.RemoveInvalidFileNameChars(fileName);

View file

@ -22,7 +22,7 @@
<PackageReference Include="Serilog" Version="4.0.0" /> <PackageReference Include="Serilog" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="SharpCompress" Version="0.37.2" /> <PackageReference Include="SharpCompress" Version="0.37.2" />
<PackageReference Include="TorBox.NET" Version="1.0.0" /> <PackageReference Include="TorBox.NET" Version="1.0.0.20" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -39,16 +39,16 @@ public class DownloadClient(Download download, Torrent torrent, String destinati
throw new("Invalid download path"); throw new("Invalid download path");
} }
await FileHelper.Delete(filePath); await FileHelper.Delete(filePath.Result!);
Type = torrent.DownloadClient; Type = torrent.DownloadClient;
Downloader = Type switch Downloader = Type switch
{ {
Data.Enums.DownloadClient.Internal => new InternalDownloader(download.Link, filePath), Data.Enums.DownloadClient.Internal => new InternalDownloader(download.Link, filePath.Result!),
Data.Enums.DownloadClient.Bezzad => new BezzadDownloader(download.Link, filePath), Data.Enums.DownloadClient.Bezzad => new BezzadDownloader(download.Link, filePath.Result!),
Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(download.RemoteId, download.Link, filePath, downloadPath, category), Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(download.RemoteId, download.Link, filePath.Result!, downloadPath.Result!, category),
Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(download.Link, filePath, downloadPath), Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(download.Link, filePath.Result!, downloadPath.Result!),
_ => throw new($"Unknown download client {Type}") _ => throw new($"Unknown download client {Type}")
}; };

View file

@ -1,12 +1,10 @@
using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using TorBoxNET; using TorBoxNET;
using RdtClient.Data.Enums; using RdtClient.Data.Enums;
using RdtClient.Data.Models.TorrentClient; using RdtClient.Data.Models.TorrentClient;
using RdtClient.Service.Helpers; using RdtClient.Service.Helpers;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Routing.Constraints;
using System.Diagnostics.Eventing.Reader;
namespace RdtClient.Service.Services.TorrentClients; namespace RdtClient.Service.Services.TorrentClients;
@ -80,7 +78,7 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
Added = ChangeTimeZone(torrent.CreatedAt)!.Value, Added = ChangeTimeZone(torrent.CreatedAt)!.Value,
Files = (torrent.Files ?? []).Select(m => new TorrentClientFile Files = (torrent.Files ?? []).Select(m => new TorrentClientFile
{ {
Path = m.S3Path.Replace(m.Hash + "/", string.Empty), Path = string.Join("/", m.Name.Split('/').Skip(1)),
Bytes = m.Size, Bytes = m.Size,
Id = m.Id, Id = m.Id,
Selected = true Selected = true
@ -125,14 +123,14 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
public async Task<String> AddMagnet(String magnetLink) public async Task<String> AddMagnet(String magnetLink)
{ {
var result = await GetClient().Torrents.AddMagnetAsync(magnetLink); var result = await GetClient().Torrents.AddMagnetAsync(magnetLink, seeding: 3);
return result.Data?.Hash?.ToString()!; return result.Data?.Hash?.ToString()!;
} }
public async Task<String> AddFile(Byte[] bytes) public async Task<String> AddFile(Byte[] bytes)
{ {
var result = await GetClient().Torrents.AddFileAsync(bytes); var result = await GetClient().Torrents.AddFileAsync(bytes, seeding: 3);
return result.Data?.Hash?.ToString()!; return result.Data?.Hash?.ToString()!;
} }
@ -155,7 +153,10 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
public async Task<String> Unrestrict(String link) public async Task<String> Unrestrict(String link)
{ {
var result = await GetClient().Unrestrict.LinkAsync(link); var torrentFile = new List<string>(link.Split('/'));
var torrentID = torrentFile[4];
var fileID = torrentFile[5];
var result = await GetClient().Unrestrict.LinkAsync(torrentID, fileID);
if (result.Error != null) if (result.Error != null)
{ {
@ -219,12 +220,13 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
{ {
"queued" => TorrentStatus.Processing, "queued" => TorrentStatus.Processing,
"metaDL" => TorrentStatus.Processing, "metaDL" => TorrentStatus.Processing,
"checking" => TorrentStatus.Processing,
"checkingResumeData" => TorrentStatus.Processing, "checkingResumeData" => TorrentStatus.Processing,
"paused" => TorrentStatus.Downloading, "paused" => TorrentStatus.Downloading,
"downloading" => TorrentStatus.Downloading, "downloading" => TorrentStatus.Downloading,
"completed" => TorrentStatus.Downloading, "completed" => TorrentStatus.Downloading,
"uploading" => TorrentStatus.Downloading, "uploading" => TorrentStatus.Finished,
"uploading (no peers)" => TorrentStatus.Downloading, "uploading (no peers)" => TorrentStatus.Finished,
"stalled" => TorrentStatus.Downloading, "stalled" => TorrentStatus.Downloading,
"stalled (no seeds)" => TorrentStatus.Downloading, "stalled (no seeds)" => TorrentStatus.Downloading,
"cached" => TorrentStatus.Finished, "cached" => TorrentStatus.Finished,
@ -263,8 +265,8 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
{ {
foreach (var file in rdTorrent.Files!) foreach (var file in rdTorrent.Files!)
{ {
var newFile = new List<String> { rdTorrent.Id, file.Id.ToString() }; var newFile = $"https://torbox.app/fakedl/{rdTorrent.Id}/{file.Id}";
files.Add(newFile.ToString()!); files.Add(newFile);
} }
} }
@ -283,7 +285,7 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
private async Task<TorrentClientTorrent> GetInfo(String torrentHash) private async Task<TorrentClientTorrent> GetInfo(String torrentHash)
{ {
var result = await GetClient().Torrents.GetInfoAsync(torrentHash); var result = await GetClient().Torrents.GetInfoAsync(torrentHash, skipCache: true);
return Map(result!); return Map(result!);
} }

View file

@ -22,7 +22,8 @@ public class Torrents(
Downloads downloads, Downloads downloads,
AllDebridTorrentClient allDebridTorrentClient, AllDebridTorrentClient allDebridTorrentClient,
PremiumizeTorrentClient premiumizeTorrentClient, PremiumizeTorrentClient premiumizeTorrentClient,
RealDebridTorrentClient realDebridTorrentClient) RealDebridTorrentClient realDebridTorrentClient,
TorBoxTorrentClient torBoxTorrentClient)
{ {
private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1); private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1);
@ -40,6 +41,7 @@ public class Torrents(
Provider.Premiumize => premiumizeTorrentClient, Provider.Premiumize => premiumizeTorrentClient,
Provider.RealDebrid => realDebridTorrentClient, Provider.RealDebrid => realDebridTorrentClient,
Provider.AllDebrid => allDebridTorrentClient, Provider.AllDebrid => allDebridTorrentClient,
Provider.TorBox => torBoxTorrentClient,
_ => throw new("Invalid Provider") _ => throw new("Invalid Provider")
}; };
} }
@ -551,7 +553,7 @@ public class Torrents(
{ {
Log($"Deleting {filePath}", download, download.Torrent); Log($"Deleting {filePath}", download, download.Torrent);
await FileHelper.Delete(filePath); await FileHelper.Delete(filePath.Result!);
} }
Log($"Resetting", download, download.Torrent); Log($"Resetting", download, download.Torrent);

View file

@ -31,7 +31,7 @@ public class UnpackClient(Download download, String destinationPath)
{ {
if (!_cancellationTokenSource.IsCancellationRequested) if (!_cancellationTokenSource.IsCancellationRequested)
{ {
await Unpack(filePath, _cancellationTokenSource.Token); await Unpack(filePath.Result!, _cancellationTokenSource.Token);
} }
}); });
} }