diff --git a/client/src/app/torrent-row/torrent-row.component.html b/client/src/app/torrent-row/torrent-row.component.html
index cc337d2..b69355e 100644
--- a/client/src/app/torrent-row/torrent-row.component.html
+++ b/client/src/app/torrent-row/torrent-row.component.html
@@ -15,18 +15,10 @@
{{ torrent | status }}
-
-
+
+
-
-
-
-
+
diff --git a/client/src/app/torrent-row/torrent-row.component.ts b/client/src/app/torrent-row/torrent-row.component.ts
index 17e5088..76554c5 100644
--- a/client/src/app/torrent-row/torrent-row.component.ts
+++ b/client/src/app/torrent-row/torrent-row.component.ts
@@ -1,6 +1,5 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { RealDebridStatus, Torrent } from 'src/app/models/torrent.model';
-import { TorrentService } from 'src/app/torrent.service';
+import { Torrent } from 'src/app/models/torrent.model';
@Component({
selector: '[app-torrent-row]',
@@ -14,55 +13,22 @@ export class TorrentRowComponent implements OnInit {
@Output('delete')
public delete = new EventEmitter();
+ @Output('retry')
+ public retry = new EventEmitter();
+
public loading = false;
- constructor(private torrentService: TorrentService) {}
+ constructor() {}
ngOnInit(): void {}
- public download(event: Event): void {
- event.stopPropagation();
-
- this.loading = true;
- this.torrentService.download(this.torrent.torrentId).subscribe(
- () => {
- this.loading = false;
- },
- (err) => {
- this.loading = false;
- }
- );
- }
-
- public unpack(event: Event): void {
- event.stopPropagation();
-
- this.loading = true;
- this.torrentService.unpack(this.torrent.torrentId).subscribe(
- () => {
- this.loading = false;
- },
- (err) => {
- this.loading = false;
- }
- );
- }
-
- public delete1(event: Event): void {
+ public deleteClick(event: Event): void {
event.stopPropagation();
this.delete.emit(this.torrent.torrentId);
}
- public canDownload(): boolean {
- return (
- (this.torrent.rdStatus === RealDebridStatus.Finished && this.torrent.downloads.length === 0) ||
- (this.torrent.downloads.length > 0 && this.torrent.downloads.any((m) => m.error != null))
- );
- }
-
- public canUnpack(): boolean {
- const downloadsDone = this.torrent.downloads.any((m) => m.downloadFinished != null);
- const downloadsUnpacked = this.torrent.downloads.any((m) => m.unpackingQueued != null);
- return downloadsDone && !downloadsUnpacked;
+ public retryClick(event: Event): void {
+ event.stopPropagation();
+ this.retry.emit(this.torrent.torrentId);
}
}
diff --git a/client/src/app/torrent-table/torrent-table.component.html b/client/src/app/torrent-table/torrent-table.component.html
index 12af847..ce51221 100644
--- a/client/src/app/torrent-table/torrent-table.component.html
+++ b/client/src/app/torrent-table/torrent-table.component.html
@@ -4,7 +4,6 @@
-
| Name |
@@ -23,6 +22,7 @@
[torrent]="torrent"
(click)="selectTorrent(torrent)"
(delete)="showDeleteModal($event)"
+ (retry)="showRetryModal($event)"
>
@@ -88,3 +88,45 @@
+
+
+
+
+
+
+
+ 0">
+ Error retrying torrent: {{ retryError }}
+
+
+
+
+
diff --git a/client/src/app/torrent-table/torrent-table.component.ts b/client/src/app/torrent-table/torrent-table.component.ts
index a0b0da6..e59569b 100644
--- a/client/src/app/torrent-table/torrent-table.component.ts
+++ b/client/src/app/torrent-table/torrent-table.component.ts
@@ -20,6 +20,12 @@ export class TorrentTableComponent implements OnInit, OnDestroy {
public deleteRdTorrent: boolean;
public deleteLocalFiles: boolean;
+ public isRetryModalActive: boolean;
+ public retryError: string;
+ public retrying: boolean;
+ public retryTorrentId: string;
+ public retry: number;
+
constructor(private torrentService: TorrentService) {}
ngOnInit(): void {
@@ -52,6 +58,10 @@ export class TorrentTableComponent implements OnInit, OnDestroy {
}
public showDeleteModal(torrentId: string): void {
+ this.deleteData = false;
+ this.deleteRdTorrent = false;
+ this.deleteLocalFiles = false;
+
this.deleteTorrentId = torrentId;
this.isDeleteModalActive = true;
}
@@ -76,4 +86,30 @@ export class TorrentTableComponent implements OnInit, OnDestroy {
}
);
}
+
+ public showRetryModal(torrentId: string): void {
+ this.retry = 0;
+
+ this.retryTorrentId = torrentId;
+ this.isRetryModalActive = true;
+ }
+
+ public retryCancel(): void {
+ this.isRetryModalActive = false;
+ }
+
+ public retryOk(): void {
+ this.retrying = true;
+
+ this.torrentService.retry(this.retryTorrentId, this.retry).subscribe(
+ () => {
+ this.isRetryModalActive = false;
+ this.retrying = false;
+ },
+ (err) => {
+ this.retryError = err.error;
+ this.retrying = false;
+ }
+ );
+ }
}
diff --git a/client/src/app/torrent.service.ts b/client/src/app/torrent.service.ts
index 7bcc20d..0360f8d 100644
--- a/client/src/app/torrent.service.ts
+++ b/client/src/app/torrent.service.ts
@@ -57,14 +57,6 @@ export class TorrentService {
return this.http.post(`/Api/Torrents/CheckFiles`, formData);
}
- public download(torrentId: string): Observable {
- return this.http.get(`/Api/Torrents/Download/${torrentId}`);
- }
-
- public unpack(torrentId: string): Observable {
- return this.http.get(`/Api/Torrents/Unpack/${torrentId}`);
- }
-
public delete(
torrentId: string,
deleteData: boolean,
@@ -77,4 +69,10 @@ export class TorrentService {
deleteLocalFiles,
});
}
+
+ public retry(torrentId: string, retry: number): Observable {
+ return this.http.post(`/Api/Torrents/Retry/${torrentId}`, {
+ retry,
+ });
+ }
}
diff --git a/server/RdtClient.Data/Data/TorrentData.cs b/server/RdtClient.Data/Data/TorrentData.cs
index c0bfcb4..81fe9f3 100644
--- a/server/RdtClient.Data/Data/TorrentData.cs
+++ b/server/RdtClient.Data/Data/TorrentData.cs
@@ -12,10 +12,10 @@ namespace RdtClient.Data.Data
Task> Get();
Task GetById(Guid torrentId);
Task GetByHash(String hash);
- Task Add(String realDebridId, String hash, String category, Boolean autoDelete);
+ Task Add(String realDebridId, String hash, String category, Boolean autoDelete, String fileOrMagnetContents, Boolean isFile);
Task UpdateRdData(Torrent torrent);
Task UpdateCategory(Guid torrentId, String category);
- Task UpdateComplete(Guid torrentId, DateTimeOffset datetime);
+ Task UpdateComplete(Guid torrentId, DateTimeOffset? datetime);
Task Delete(Guid torrentId);
}
@@ -78,7 +78,7 @@ namespace RdtClient.Data.Data
return dbTorrent;
}
- public async Task Add(String realDebridId, String hash, String category, Boolean autoDelete)
+ public async Task Add(String realDebridId, String hash, String category, Boolean autoDelete, String fileOrMagnetContents, Boolean isFile)
{
var torrent = new Torrent
{
@@ -87,7 +87,9 @@ namespace RdtClient.Data.Data
RdId = realDebridId,
Hash = hash.ToLower(),
Category = category,
- AutoDelete = autoDelete
+ AutoDelete = autoDelete,
+ FileOrMagnet = fileOrMagnetContents,
+ IsFile = isFile
};
await _dataContext.Torrents.AddAsync(torrent);
@@ -140,7 +142,7 @@ namespace RdtClient.Data.Data
await _dataContext.SaveChangesAsync();
}
- public async Task UpdateComplete(Guid torrentId, DateTimeOffset datetime)
+ public async Task UpdateComplete(Guid torrentId, DateTimeOffset? datetime)
{
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
diff --git a/server/RdtClient.Data/Migrations/20210313145632_Torrents_Add_FileOrMagnet.Designer.cs b/server/RdtClient.Data/Migrations/20210313145632_Torrents_Add_FileOrMagnet.Designer.cs
new file mode 100644
index 0000000..227f006
--- /dev/null
+++ b/server/RdtClient.Data/Migrations/20210313145632_Torrents_Add_FileOrMagnet.Designer.cs
@@ -0,0 +1,418 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using RdtClient.Data.Data;
+
+namespace RdtClient.Data.Migrations
+{
+ [DbContext(typeof(DataContext))]
+ [Migration("20210313145632_Torrents_Add_FileOrMagnet")]
+ partial class Torrents_Add_FileOrMagnet
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "5.0.3");
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property("NormalizedName")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName")
+ .IsUnique()
+ .HasDatabaseName("RoleNameIndex");
+
+ b.ToTable("AspNetRoles");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("ClaimType")
+ .HasColumnType("TEXT");
+
+ b.Property("ClaimValue")
+ .HasColumnType("TEXT");
+
+ b.Property("RoleId")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetRoleClaims");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("AccessFailedCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("TEXT");
+
+ b.Property("Email")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property("EmailConfirmed")
+ .HasColumnType("INTEGER");
+
+ b.Property("LockoutEnabled")
+ .HasColumnType("INTEGER");
+
+ b.Property("LockoutEnd")
+ .HasColumnType("TEXT");
+
+ b.Property("NormalizedEmail")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property("NormalizedUserName")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property("PasswordHash")
+ .HasColumnType("TEXT");
+
+ b.Property("PhoneNumber")
+ .HasColumnType("TEXT");
+
+ b.Property("PhoneNumberConfirmed")
+ .HasColumnType("INTEGER");
+
+ b.Property("SecurityStamp")
+ .HasColumnType("TEXT");
+
+ b.Property("TwoFactorEnabled")
+ .HasColumnType("INTEGER");
+
+ b.Property("UserName")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedEmail")
+ .HasDatabaseName("EmailIndex");
+
+ b.HasIndex("NormalizedUserName")
+ .IsUnique()
+ .HasDatabaseName("UserNameIndex");
+
+ b.ToTable("AspNetUsers");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("ClaimType")
+ .HasColumnType("TEXT");
+
+ b.Property("ClaimValue")
+ .HasColumnType("TEXT");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserClaims");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.Property("LoginProvider")
+ .HasColumnType("TEXT");
+
+ b.Property("ProviderKey")
+ .HasColumnType("TEXT");
+
+ b.Property("ProviderDisplayName")
+ .HasColumnType("TEXT");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("LoginProvider", "ProviderKey");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserLogins");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("TEXT");
+
+ b.Property("RoleId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetUserRoles");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("TEXT");
+
+ b.Property("LoginProvider")
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("Value")
+ .HasColumnType("TEXT");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AspNetUserTokens");
+ });
+
+ modelBuilder.Entity("RdtClient.Data.Models.Data.Download", b =>
+ {
+ b.Property("DownloadId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Added")
+ .HasColumnType("TEXT");
+
+ b.Property("Completed")
+ .HasColumnType("TEXT");
+
+ b.Property("DownloadFinished")
+ .HasColumnType("TEXT");
+
+ b.Property("DownloadQueued")
+ .HasColumnType("TEXT");
+
+ b.Property("DownloadStarted")
+ .HasColumnType("TEXT");
+
+ b.Property("Error")
+ .HasColumnType("TEXT");
+
+ b.Property("Link")
+ .HasColumnType("TEXT");
+
+ b.Property("Path")
+ .HasColumnType("TEXT");
+
+ b.Property("TorrentId")
+ .HasColumnType("TEXT");
+
+ b.Property("UnpackingFinished")
+ .HasColumnType("TEXT");
+
+ b.Property("UnpackingQueued")
+ .HasColumnType("TEXT");
+
+ b.Property("UnpackingStarted")
+ .HasColumnType("TEXT");
+
+ b.HasKey("DownloadId");
+
+ b.HasIndex("TorrentId");
+
+ b.ToTable("Downloads");
+ });
+
+ modelBuilder.Entity("RdtClient.Data.Models.Data.Setting", b =>
+ {
+ b.Property("SettingId")
+ .HasColumnType("TEXT");
+
+ b.Property("Type")
+ .HasColumnType("TEXT");
+
+ b.Property("Value")
+ .HasColumnType("TEXT");
+
+ b.HasKey("SettingId");
+
+ b.ToTable("Settings");
+ });
+
+ modelBuilder.Entity("RdtClient.Data.Models.Data.Torrent", b =>
+ {
+ b.Property("TorrentId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Added")
+ .HasColumnType("TEXT");
+
+ b.Property("AutoDelete")
+ .HasColumnType("INTEGER");
+
+ b.Property("Category")
+ .HasColumnType("TEXT");
+
+ b.Property("Completed")
+ .HasColumnType("TEXT");
+
+ b.Property("FileOrMagnet")
+ .HasColumnType("TEXT");
+
+ b.Property("Hash")
+ .HasColumnType("TEXT");
+
+ b.Property("IsFile")
+ .HasColumnType("INTEGER");
+
+ b.Property("RdAdded")
+ .HasColumnType("TEXT");
+
+ b.Property("RdEnded")
+ .HasColumnType("TEXT");
+
+ b.Property("RdFiles")
+ .HasColumnType("TEXT");
+
+ b.Property("RdHost")
+ .HasColumnType("TEXT");
+
+ b.Property("RdId")
+ .HasColumnType("TEXT");
+
+ b.Property("RdName")
+ .HasColumnType("TEXT");
+
+ b.Property("RdProgress")
+ .HasColumnType("INTEGER");
+
+ b.Property("RdSeeders")
+ .HasColumnType("INTEGER");
+
+ b.Property("RdSize")
+ .HasColumnType("INTEGER");
+
+ b.Property("RdSpeed")
+ .HasColumnType("INTEGER");
+
+ b.Property("RdSplit")
+ .HasColumnType("INTEGER");
+
+ b.Property("RdStatus")
+ .HasColumnType("INTEGER");
+
+ b.Property("RdStatusRaw")
+ .HasColumnType("TEXT");
+
+ b.HasKey("TorrentId");
+
+ b.ToTable("Torrents");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("RdtClient.Data.Models.Data.Download", b =>
+ {
+ b.HasOne("RdtClient.Data.Models.Data.Torrent", "Torrent")
+ .WithMany("Downloads")
+ .HasForeignKey("TorrentId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+
+ b.Navigation("Torrent");
+ });
+
+ modelBuilder.Entity("RdtClient.Data.Models.Data.Torrent", b =>
+ {
+ b.Navigation("Downloads");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/server/RdtClient.Data/Migrations/20210313145632_Torrents_Add_FileOrMagnet.cs b/server/RdtClient.Data/Migrations/20210313145632_Torrents_Add_FileOrMagnet.cs
new file mode 100644
index 0000000..6c06d59
--- /dev/null
+++ b/server/RdtClient.Data/Migrations/20210313145632_Torrents_Add_FileOrMagnet.cs
@@ -0,0 +1,34 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace RdtClient.Data.Migrations
+{
+ public partial class Torrents_Add_FileOrMagnet : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "FileOrMagnet",
+ table: "Torrents",
+ type: "TEXT",
+ nullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "IsFile",
+ table: "Torrents",
+ type: "INTEGER",
+ nullable: false,
+ defaultValue: false);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "FileOrMagnet",
+ table: "Torrents");
+
+ migrationBuilder.DropColumn(
+ name: "IsFile",
+ table: "Torrents");
+ }
+ }
+}
diff --git a/server/RdtClient.Data/Migrations/DataContextModelSnapshot.cs b/server/RdtClient.Data/Migrations/DataContextModelSnapshot.cs
index 9bee96b..ac3dcac 100644
--- a/server/RdtClient.Data/Migrations/DataContextModelSnapshot.cs
+++ b/server/RdtClient.Data/Migrations/DataContextModelSnapshot.cs
@@ -291,9 +291,15 @@ namespace RdtClient.Data.Migrations
b.Property("Completed")
.HasColumnType("TEXT");
+ b.Property("FileOrMagnet")
+ .HasColumnType("TEXT");
+
b.Property("Hash")
.HasColumnType("TEXT");
+ b.Property("IsFile")
+ .HasColumnType("INTEGER");
+
b.Property("RdAdded")
.HasColumnType("TEXT");
diff --git a/server/RdtClient.Data/Models/Data/Torrent.cs b/server/RdtClient.Data/Models/Data/Torrent.cs
index d16cb04..d1d550e 100644
--- a/server/RdtClient.Data/Models/Data/Torrent.cs
+++ b/server/RdtClient.Data/Models/Data/Torrent.cs
@@ -21,6 +21,9 @@ namespace RdtClient.Data.Models.Data
public DateTimeOffset? Completed { get; set; }
public Boolean AutoDelete { get; set; }
+
+ public String FileOrMagnet { get; set; }
+ public Boolean IsFile { get; set; }
[InverseProperty("Torrent")]
public IList Downloads { get; set; }
diff --git a/server/RdtClient.Service/Services/TorrentRunner.cs b/server/RdtClient.Service/Services/TorrentRunner.cs
index 17cd92d..16ca179 100644
--- a/server/RdtClient.Service/Services/TorrentRunner.cs
+++ b/server/RdtClient.Service/Services/TorrentRunner.cs
@@ -335,7 +335,7 @@ namespace RdtClient.Service.Services
}
// RealDebrid is waiting for file selection, select which files to download.
- if (torrent.RdStatus == RealDebridStatus.WaitingForFileSelection && torrent.Downloads.Count == 0)
+ if (torrent.RdStatus == RealDebridStatus.WaitingForFileSelection || torrent.Downloads.Count == 0)
{
Log.Debug($"Torrent {torrent.RdId} selecting files");
@@ -390,8 +390,6 @@ namespace RdtClient.Service.Services
// RealDebrid finished downloading the torrent, process the file to host.
if (torrent.RdStatus == RealDebridStatus.Finished)
{
- Log.Debug($"Torrent {torrent.RdId} completed, download starting");
-
// If the torrent has any files that need starting to be downloaded, download them.
var downloadsPending = torrent.Downloads
.Where(m => m.Completed == null &&
@@ -413,11 +411,6 @@ namespace RdtClient.Service.Services
continue;
}
- }
-
- if (torrent.RdStatus == RealDebridStatus.Finished)
- {
- Log.Debug($"Torrent {torrent.RdId} completed, unpack starting");
// If all files are finished downloading, move to the unpacking step.
var unpackingPending = torrent.Downloads
diff --git a/server/RdtClient.Service/Services/Torrents.cs b/server/RdtClient.Service/Services/Torrents.cs
index f24b3f4..9d49db4 100644
--- a/server/RdtClient.Service/Services/Torrents.cs
+++ b/server/RdtClient.Service/Services/Torrents.cs
@@ -17,7 +17,6 @@ namespace RdtClient.Service.Services
public interface ITorrents
{
Task> Get();
- Task GetById(Guid torrentId);
Task GetByHash(String hash);
Task UpdateCategory(String hash, String category);
Task UploadMagnet(String magnetLink, String category, Boolean autoDelete);
@@ -32,6 +31,7 @@ namespace RdtClient.Service.Services
Task GetProfile();
Task UpdateComplete(Guid torrentId, DateTimeOffset datetime);
Task Update();
+ Task Retry(Guid id, Int32 retry);
}
public class Torrents : ITorrents
@@ -141,7 +141,7 @@ namespace RdtClient.Service.Services
var rdTorrent = await GetRdNetClient().AddTorrentMagnetAsync(magnetLink);
- await Add(rdTorrent.Id, magnet.InfoHash.ToHex(), category, autoDelete);
+ await Add(rdTorrent.Id, magnet.InfoHash.ToHex(), category, autoDelete, magnetLink, false);
}
public async Task UploadFile(Byte[] bytes, String category, Boolean autoDelete)
@@ -150,7 +150,9 @@ namespace RdtClient.Service.Services
var rdTorrent = await GetRdNetClient().AddTorrentFileAsync(bytes);
- await Add(rdTorrent.Id, torrent.InfoHash.ToHex(), category, autoDelete);
+ var fileAsBase64 = Convert.ToBase64String(bytes);
+
+ await Add(rdTorrent.Id, torrent.InfoHash.ToHex(), category, autoDelete, fileAsBase64, true);
}
public async Task> GetAvailableFiles(String hash)
@@ -197,17 +199,6 @@ namespace RdtClient.Service.Services
}
}
- if (deleteLocalFiles)
- {
- var downloadPath = await DownloadPath(torrent);
- downloadPath = Path.Combine(downloadPath, torrent.RdName);
-
- if (Directory.Exists(downloadPath))
- {
- Directory.Delete(downloadPath, true);
- }
- }
-
if (deleteData)
{
await _downloads.DeleteForTorrent(torrent.TorrentId);
@@ -218,6 +209,37 @@ namespace RdtClient.Service.Services
{
await GetRdNetClient().DeleteTorrentAsync(torrent.RdId);
}
+
+ if (deleteLocalFiles)
+ {
+ var downloadPath = await DownloadPath(torrent);
+ downloadPath = Path.Combine(downloadPath, torrent.RdName);
+
+ if (Directory.Exists(downloadPath))
+ {
+ var retry = 0;
+
+ while (true)
+ {
+ try
+ {
+ Directory.Delete(downloadPath, true);
+
+ break;
+ }
+ catch
+ {
+ retry++;
+ if (retry >= 3)
+ {
+ throw;
+ }
+
+ await Task.Delay(1000);
+ }
+ }
+ }
+ }
}
}
@@ -270,7 +292,7 @@ namespace RdtClient.Service.Services
return profile;
}
- private async Task Add(String rdTorrentId, String infoHash, String category, Boolean autoDelete)
+ private async Task Add(String rdTorrentId, String infoHash, String category, Boolean autoDelete, String fileOrMagnetContents, Boolean isFile)
{
var w = await SemaphoreSlim.WaitAsync(60000);
if (!w)
@@ -287,7 +309,7 @@ namespace RdtClient.Service.Services
return;
}
- var newTorrent = await _torrentData.Add(rdTorrentId, infoHash, category, autoDelete);
+ var newTorrent = await _torrentData.Add(rdTorrentId, infoHash, category, autoDelete, fileOrMagnetContents, isFile);
var rdTorrent = await GetRdNetClient().GetTorrentInfoAsync(rdTorrentId);
@@ -305,8 +327,6 @@ namespace RdtClient.Service.Services
if (!w)
{
-
-
return;
}
@@ -352,6 +372,43 @@ namespace RdtClient.Service.Services
}
}
+ public async Task Retry(Guid id, Int32 retry)
+ {
+ var torrent = await _torrentData.GetById(id);
+
+ if (retry == 0)
+ {
+ await Delete(id, true, true, true);
+
+ if (String.IsNullOrWhiteSpace(torrent.FileOrMagnet))
+ {
+ throw new Exception($"Cannot re-add this torrent, original magnet or file not found");
+ }
+
+ if (torrent.IsFile)
+ {
+ var bytes = Convert.FromBase64String(torrent.FileOrMagnet);
+
+ await UploadFile(bytes, torrent.Category, torrent.AutoDelete);
+ }
+ else
+ {
+ await UploadMagnet(torrent.FileOrMagnet, torrent.Category, torrent.AutoDelete);
+ }
+ }
+ else if (retry == 1)
+ {
+ await Delete(id, false, false, true);
+
+ await _torrentData.UpdateComplete(id, null);
+ await _downloads.DeleteForTorrent(id);
+ }
+ else
+ {
+ throw new Exception($"Invalid retry option {retry}");
+ }
+ }
+
public async Task UpdateComplete(Guid torrentId, DateTimeOffset datetime)
{
await _torrentData.UpdateComplete(torrentId, datetime);
diff --git a/server/RdtClient.Web/Controllers/TorrentsController.cs b/server/RdtClient.Web/Controllers/TorrentsController.cs
index ea73343..77beaf2 100644
--- a/server/RdtClient.Web/Controllers/TorrentsController.cs
+++ b/server/RdtClient.Web/Controllers/TorrentsController.cs
@@ -132,32 +132,12 @@ namespace RdtClient.Web.Controllers
return Ok();
}
-
- [HttpGet]
- [Route("Download/{id}")]
- public async Task Download(Guid id)
- {
- var torrent = await _torrents.GetById(id);
-
- foreach (var link in torrent.Files.Where(m => m.Selected))
- {
- await _downloads.Add(id, link.Path);
- await _torrents.UnrestrictLink(id);
- }
-
- return Ok();
- }
- [HttpGet]
- [Route("Unpack/{id}")]
- public async Task Unpack(Guid id)
+ [HttpPost]
+ [Route("Retry/{id}")]
+ public async Task Retry(Guid id, [FromBody] TorrentControllerRetryRequest request)
{
- var downloads = await _downloads.GetForTorrent(id);
-
- foreach (var download in downloads)
- {
- await _torrents.Unpack(download.DownloadId);
- }
+ await _torrents.Retry(id, request.Retry);
return Ok();
}
@@ -181,6 +161,11 @@ namespace RdtClient.Web.Controllers
public Boolean DeleteLocalFiles { get; set; }
}
+ public class TorrentControllerRetryRequest
+ {
+ public Int32 Retry { get; set; }
+ }
+
public class TorrentControllerCheckFilesRequest
{
public String MagnetLink { get; set; }
|