From 5265a8b442f37a32818380810d631a166cf23b62 Mon Sep 17 00:00:00 2001 From: Roger Far Date: Wed, 10 Mar 2021 17:56:54 -0700 Subject: [PATCH] Changed the unrestrict process to only unrestrict when the download is starting. --- client/src/app/models/download.model.ts | 1 + client/src/app/models/torrent.model.ts | 2 - .../add-new-torrent.component.html | 31 +- .../add-new-torrent.component.scss | 4 + .../add-new-torrent.component.ts | 43 +- .../torrent-download.component.html | 3 +- .../torrent-row/torrent-row.component.html | 2 - client/src/app/torrent.service.ts | 25 +- server/RdtClient.Data/Data/DownloadData.cs | 21 +- server/RdtClient.Data/Data/TorrentData.cs | 6 +- ...10311002748_Downloads_Add_Path.Designer.cs | 418 ++++++++++++++++++ .../20210311002748_Downloads_Add_Path.cs | 23 + ...11005539_Torrents_Removed_Auto.Designer.cs | 412 +++++++++++++++++ .../20210311005539_Torrents_Removed_Auto.cs | 35 ++ .../Migrations/DataContextModelSnapshot.cs | 11 +- server/RdtClient.Data/Models/Data/Download.cs | 2 + server/RdtClient.Data/Models/Data/Torrent.cs | 2 - .../RdtClient.Service/Services/Downloads.cs | 8 +- .../RdtClient.Service/Services/QBittorrent.cs | 12 +- .../Services/TorrentRunner.cs | 22 +- server/RdtClient.Service/Services/Torrents.cs | 51 +-- .../Controllers/QBittorrentController.cs | 4 +- .../Controllers/TorrentsController.cs | 59 ++- 23 files changed, 1095 insertions(+), 102 deletions(-) create mode 100644 server/RdtClient.Data/Migrations/20210311002748_Downloads_Add_Path.Designer.cs create mode 100644 server/RdtClient.Data/Migrations/20210311002748_Downloads_Add_Path.cs create mode 100644 server/RdtClient.Data/Migrations/20210311005539_Torrents_Removed_Auto.Designer.cs create mode 100644 server/RdtClient.Data/Migrations/20210311005539_Torrents_Removed_Auto.cs diff --git a/client/src/app/models/download.model.ts b/client/src/app/models/download.model.ts index fe2c712..204b175 100644 --- a/client/src/app/models/download.model.ts +++ b/client/src/app/models/download.model.ts @@ -1,6 +1,7 @@ export class Download { public downloadId: string; public torrentId: string; + public path: string; public link: string; public added: Date; public downloadQueued: Date; diff --git a/client/src/app/models/torrent.model.ts b/client/src/app/models/torrent.model.ts index e44f5c5..68d8c2a 100644 --- a/client/src/app/models/torrent.model.ts +++ b/client/src/app/models/torrent.model.ts @@ -6,8 +6,6 @@ export class Torrent { public category: string; public added: Date; public completed: Date; - public autoDownload: boolean; - public autoUnpack: boolean; public autoDelete: boolean; public rdId: string; diff --git a/client/src/app/navbar/add-new-torrent/add-new-torrent.component.html b/client/src/app/navbar/add-new-torrent/add-new-torrent.component.html index 3d3a58f..04832a0 100644 --- a/client/src/app/navbar/add-new-torrent/add-new-torrent.component.html +++ b/client/src/app/navbar/add-new-torrent/add-new-torrent.component.html @@ -37,14 +37,6 @@
- -
+ + diff --git a/client/src/app/navbar/add-new-torrent/add-new-torrent.component.scss b/client/src/app/navbar/add-new-torrent/add-new-torrent.component.scss index 3cef3d3..4b5fc83 100644 --- a/client/src/app/navbar/add-new-torrent/add-new-torrent.component.scss +++ b/client/src/app/navbar/add-new-torrent/add-new-torrent.component.scss @@ -2,3 +2,7 @@ max-width: 24em; width: 24em; } + +.file-modal { + width: calc(75% - 40px); +} diff --git a/client/src/app/navbar/add-new-torrent/add-new-torrent.component.ts b/client/src/app/navbar/add-new-torrent/add-new-torrent.component.ts index 4c3b9bd..8d1ce08 100644 --- a/client/src/app/navbar/add-new-torrent/add-new-torrent.component.ts +++ b/client/src/app/navbar/add-new-torrent/add-new-torrent.component.ts @@ -21,13 +21,14 @@ export class AddNewTorrentComponent implements OnInit { public openChange = new EventEmitter(); public isActive = false; + public isFileModalActive = false; public fileName: string; public magnetLink: string; - public autoDownload: boolean; - public autoUnpack: boolean; public autoDelete: boolean; + public fileList: string[]; + public saving = false; public error: string; @@ -41,7 +42,6 @@ export class AddNewTorrentComponent implements OnInit { this.fileName = ''; this.magnetLink = ''; this.autoDelete = false; - this.autoDownload = true; this.saving = false; this.selectedFile = null; @@ -67,7 +67,7 @@ export class AddNewTorrentComponent implements OnInit { this.error = null; if (this.magnetLink) { - this.torrentService.uploadMagnet(this.magnetLink, this.autoDownload, this.autoUnpack, this.autoDelete).subscribe( + this.torrentService.uploadMagnet(this.magnetLink, this.autoDelete).subscribe( () => { this.cancel(); }, @@ -77,7 +77,7 @@ export class AddNewTorrentComponent implements OnInit { } ); } else if (this.selectedFile) { - this.torrentService.uploadFile(this.selectedFile, this.autoDownload, this.autoUnpack, this.autoDelete).subscribe( + this.torrentService.uploadFile(this.selectedFile, this.autoDelete).subscribe( () => { this.cancel(); }, @@ -91,6 +91,39 @@ export class AddNewTorrentComponent implements OnInit { } } + public checkFiles(): void { + this.saving = true; + this.error = null; + + if (this.magnetLink) { + this.torrentService.checkFilesMagnet(this.magnetLink).subscribe( + (result) => { + this.saving = false; + this.isFileModalActive = true; + this.fileList = result; + }, + (err) => { + this.error = err.error; + this.saving = false; + } + ); + } else if (this.selectedFile) { + this.torrentService.checkFiles(this.selectedFile).subscribe( + (result) => { + this.saving = false; + this.isFileModalActive = true; + this.fileList = result; + }, + (err) => { + this.error = err.error; + this.saving = false; + } + ); + } else { + this.cancel(); + } + } + public cancel(): void { this.isActive = false; this.openChange.emit(this.open); diff --git a/client/src/app/torrent-download/torrent-download.component.html b/client/src/app/torrent-download/torrent-download.component.html index 0b3f8e2..c4fbf06 100644 --- a/client/src/app/torrent-download/torrent-download.component.html +++ b/client/src/app/torrent-download/torrent-download.component.html @@ -1,6 +1,7 @@ - {{ download.link }} + {{ download.link }} + {{ download.path }} {{ download.bytesTotal | filesize }} diff --git a/client/src/app/torrent-row/torrent-row.component.html b/client/src/app/torrent-row/torrent-row.component.html index 82da83e..cc337d2 100644 --- a/client/src/app/torrent-row/torrent-row.component.html +++ b/client/src/app/torrent-row/torrent-row.component.html @@ -6,8 +6,6 @@ {{ torrent.downloads.length | number }} - - diff --git a/client/src/app/torrent.service.ts b/client/src/app/torrent.service.ts index 5e89346..7bcc20d 100644 --- a/client/src/app/torrent.service.ts +++ b/client/src/app/torrent.service.ts @@ -31,27 +31,32 @@ export class TorrentService { return this.http.get(`/Api/Torrents`); } - public uploadMagnet( - magnetLink: string, - autoDownload: boolean, - autoUnpack: boolean, - autoDelete: boolean - ): Observable { + public uploadMagnet(magnetLink: string, autoDelete: boolean): Observable { return this.http.post(`/Api/Torrents/UploadMagnet`, { magnetLink, - autoDownload, - autoUnpack, autoDelete, }); } - public uploadFile(file: File, autoDownload: boolean, autoUnpack: boolean, autoDelete: boolean): Observable { + public uploadFile(file: File, autoDelete: boolean): Observable { const formData: FormData = new FormData(); formData.append('file', file); - formData.append('formData', JSON.stringify({ autoDownload, autoUnpack, autoDelete })); + formData.append('formData', JSON.stringify({ autoDelete })); return this.http.post(`/Api/Torrents/UploadFile`, formData); } + public checkFilesMagnet(magnetLink: string): Observable { + return this.http.post(`/Api/Torrents/CheckFilesMagnet`, { + magnetLink, + }); + } + + public checkFiles(file: File): Observable { + const formData: FormData = new FormData(); + formData.append('file', file); + return this.http.post(`/Api/Torrents/CheckFiles`, formData); + } + public download(torrentId: string): Observable { return this.http.get(`/Api/Torrents/Download/${torrentId}`); } diff --git a/server/RdtClient.Data/Data/DownloadData.cs b/server/RdtClient.Data/Data/DownloadData.cs index 9465785..d8b3c7f 100644 --- a/server/RdtClient.Data/Data/DownloadData.cs +++ b/server/RdtClient.Data/Data/DownloadData.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; -using RdtClient.Data.Models.Data; +using Download = RdtClient.Data.Models.Data.Download; namespace RdtClient.Data.Data { @@ -12,7 +12,8 @@ namespace RdtClient.Data.Data Task> Get(); Task> GetForTorrent(Guid torrentId); Task GetById(Guid downloadId); - Task Add(Guid torrentId, String link); + Task Add(Guid torrentId, String path); + Task UpdateUnrestrictedLink(Guid downloadId, String unrestrictedLink); Task UpdateDownloadStarted(Guid downloadId, DateTimeOffset? dateTime); Task UpdateDownloadFinished(Guid downloadId, DateTimeOffset? dateTime); Task UpdateUnpackingQueued(Guid downloadId, DateTimeOffset? dateTime); @@ -56,13 +57,13 @@ namespace RdtClient.Data.Data .FirstOrDefaultAsync(m => m.DownloadId == downloadId); } - public async Task Add(Guid torrentId, String link) + public async Task Add(Guid torrentId, String path) { var download = new Download { DownloadId = Guid.NewGuid(), TorrentId = torrentId, - Link = link, + Path = path, Added = DateTimeOffset.UtcNow, DownloadQueued = DateTimeOffset.UtcNow }; @@ -73,7 +74,17 @@ namespace RdtClient.Data.Data return download; } - + + public async Task UpdateUnrestrictedLink(Guid downloadId, String unrestrictedLink) + { + var dbDownload = await _dataContext.Downloads + .FirstOrDefaultAsync(m => m.DownloadId == downloadId); + + dbDownload.Link = unrestrictedLink; + + await _dataContext.SaveChangesAsync(); + } + public async Task UpdateDownloadStarted(Guid downloadId, DateTimeOffset? dateTime) { var dbDownload = await _dataContext.Downloads diff --git a/server/RdtClient.Data/Data/TorrentData.cs b/server/RdtClient.Data/Data/TorrentData.cs index 80a8fb1..c0bfcb4 100644 --- a/server/RdtClient.Data/Data/TorrentData.cs +++ b/server/RdtClient.Data/Data/TorrentData.cs @@ -12,7 +12,7 @@ namespace RdtClient.Data.Data Task> Get(); Task GetById(Guid torrentId); Task GetByHash(String hash); - Task Add(String realDebridId, String hash, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete); + Task Add(String realDebridId, String hash, String category, Boolean autoDelete); Task UpdateRdData(Torrent torrent); Task UpdateCategory(Guid torrentId, String category); Task UpdateComplete(Guid torrentId, DateTimeOffset datetime); @@ -78,7 +78,7 @@ namespace RdtClient.Data.Data return dbTorrent; } - public async Task Add(String realDebridId, String hash, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete) + public async Task Add(String realDebridId, String hash, String category, Boolean autoDelete) { var torrent = new Torrent { @@ -87,8 +87,6 @@ namespace RdtClient.Data.Data RdId = realDebridId, Hash = hash.ToLower(), Category = category, - AutoDownload = autoDownload, - AutoUnpack = autoUnpack, AutoDelete = autoDelete }; diff --git a/server/RdtClient.Data/Migrations/20210311002748_Downloads_Add_Path.Designer.cs b/server/RdtClient.Data/Migrations/20210311002748_Downloads_Add_Path.Designer.cs new file mode 100644 index 0000000..40dfe9b --- /dev/null +++ b/server/RdtClient.Data/Migrations/20210311002748_Downloads_Add_Path.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("20210311002748_Downloads_Add_Path")] + partial class Downloads_Add_Path + { + 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("AutoDownload") + .HasColumnType("INTEGER"); + + b.Property("AutoUnpack") + .HasColumnType("INTEGER"); + + b.Property("Category") + .HasColumnType("TEXT"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Hash") + .HasColumnType("TEXT"); + + 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/20210311002748_Downloads_Add_Path.cs b/server/RdtClient.Data/Migrations/20210311002748_Downloads_Add_Path.cs new file mode 100644 index 0000000..56c8ba2 --- /dev/null +++ b/server/RdtClient.Data/Migrations/20210311002748_Downloads_Add_Path.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace RdtClient.Data.Migrations +{ + public partial class Downloads_Add_Path : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Path", + table: "Downloads", + type: "TEXT", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Path", + table: "Downloads"); + } + } +} diff --git a/server/RdtClient.Data/Migrations/20210311005539_Torrents_Removed_Auto.Designer.cs b/server/RdtClient.Data/Migrations/20210311005539_Torrents_Removed_Auto.Designer.cs new file mode 100644 index 0000000..456dc25 --- /dev/null +++ b/server/RdtClient.Data/Migrations/20210311005539_Torrents_Removed_Auto.Designer.cs @@ -0,0 +1,412 @@ +// +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("20210311005539_Torrents_Removed_Auto")] + partial class Torrents_Removed_Auto + { + 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("Hash") + .HasColumnType("TEXT"); + + 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/20210311005539_Torrents_Removed_Auto.cs b/server/RdtClient.Data/Migrations/20210311005539_Torrents_Removed_Auto.cs new file mode 100644 index 0000000..36cfde6 --- /dev/null +++ b/server/RdtClient.Data/Migrations/20210311005539_Torrents_Removed_Auto.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace RdtClient.Data.Migrations +{ + public partial class Torrents_Removed_Auto : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AutoDownload", + table: "Torrents"); + + migrationBuilder.DropColumn( + name: "AutoUnpack", + table: "Torrents"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AutoDownload", + table: "Torrents", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "AutoUnpack", + table: "Torrents", + type: "INTEGER", + nullable: false, + defaultValue: false); + } + } +} diff --git a/server/RdtClient.Data/Migrations/DataContextModelSnapshot.cs b/server/RdtClient.Data/Migrations/DataContextModelSnapshot.cs index fab3dba..9bee96b 100644 --- a/server/RdtClient.Data/Migrations/DataContextModelSnapshot.cs +++ b/server/RdtClient.Data/Migrations/DataContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace RdtClient.Data.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "5.0.1"); + .HasAnnotation("ProductVersion", "5.0.3"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -235,6 +235,9 @@ namespace RdtClient.Data.Migrations b.Property("Link") .HasColumnType("TEXT"); + b.Property("Path") + .HasColumnType("TEXT"); + b.Property("TorrentId") .HasColumnType("TEXT"); @@ -282,12 +285,6 @@ namespace RdtClient.Data.Migrations b.Property("AutoDelete") .HasColumnType("INTEGER"); - b.Property("AutoDownload") - .HasColumnType("INTEGER"); - - b.Property("AutoUnpack") - .HasColumnType("INTEGER"); - b.Property("Category") .HasColumnType("TEXT"); diff --git a/server/RdtClient.Data/Models/Data/Download.cs b/server/RdtClient.Data/Models/Data/Download.cs index bddee89..252d59f 100644 --- a/server/RdtClient.Data/Models/Data/Download.cs +++ b/server/RdtClient.Data/Models/Data/Download.cs @@ -11,6 +11,8 @@ namespace RdtClient.Data.Models.Data public Guid TorrentId { get; set; } + public String Path { get; set; } + public String Link { get; set; } public DateTimeOffset Added { get; set; } diff --git a/server/RdtClient.Data/Models/Data/Torrent.cs b/server/RdtClient.Data/Models/Data/Torrent.cs index 5a7f40c..d16cb04 100644 --- a/server/RdtClient.Data/Models/Data/Torrent.cs +++ b/server/RdtClient.Data/Models/Data/Torrent.cs @@ -20,8 +20,6 @@ namespace RdtClient.Data.Models.Data public DateTimeOffset Added { get; set; } public DateTimeOffset? Completed { get; set; } - public Boolean AutoDownload { get; set; } - public Boolean AutoUnpack { get; set; } public Boolean AutoDelete { get; set; } [InverseProperty("Torrent")] diff --git a/server/RdtClient.Service/Services/Downloads.cs b/server/RdtClient.Service/Services/Downloads.cs index 9d78eb6..19bf0c5 100644 --- a/server/RdtClient.Service/Services/Downloads.cs +++ b/server/RdtClient.Service/Services/Downloads.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using RdtClient.Data.Data; -using RdtClient.Data.Models.Data; +using Download = RdtClient.Data.Models.Data.Download; namespace RdtClient.Service.Services { @@ -12,6 +12,7 @@ namespace RdtClient.Service.Services Task> GetForTorrent(Guid torrentId); Task GetById(Guid downloadId); Task Add(Guid torrentId, String link); + Task UpdateUnrestrictedLink(Guid downloadId, String unrestrictedLink); Task UpdateDownloadStarted(Guid downloadId, DateTimeOffset? dateTime); Task UpdateDownloadFinished(Guid downloadId, DateTimeOffset? dateTime); Task UpdateUnpackingQueued(Guid downloadId, DateTimeOffset? dateTime); @@ -51,6 +52,11 @@ namespace RdtClient.Service.Services return await _downloadData.Add(torrentId, link); } + public async Task UpdateUnrestrictedLink(Guid downloadId, String unrestrictedLink) + { + await _downloadData.UpdateUnrestrictedLink(downloadId, unrestrictedLink); + } + public async Task UpdateDownloadStarted(Guid downloadId, DateTimeOffset? dateTime) { await _downloadData.UpdateDownloadStarted(downloadId, dateTime); diff --git a/server/RdtClient.Service/Services/QBittorrent.cs b/server/RdtClient.Service/Services/QBittorrent.cs index a544da8..7aba234 100644 --- a/server/RdtClient.Service/Services/QBittorrent.cs +++ b/server/RdtClient.Service/Services/QBittorrent.cs @@ -18,8 +18,8 @@ namespace RdtClient.Service.Services Task> TorrentFileContents(String hash); Task TorrentProperties(String hash); Task TorrentsDelete(String hash, Boolean deleteFiles); - Task TorrentsAddMagnet(String magnetLink, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete); - Task TorrentsAddFile(Byte[] fileBytes, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete); + Task TorrentsAddMagnet(String magnetLink, String category, Boolean autoDelete); + Task TorrentsAddFile(Byte[] fileBytes, String category, Boolean autoDelete); Task TorrentsSetCategory(String hash, String category); Task> TorrentsCategories(); } @@ -424,14 +424,14 @@ namespace RdtClient.Service.Services await _torrents.Delete(torrent.TorrentId, true, true, deleteFiles); } - public async Task TorrentsAddMagnet(String magnetLink, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete) + public async Task TorrentsAddMagnet(String magnetLink, String category, Boolean autoDelete) { - await _torrents.UploadMagnet(magnetLink, category, autoDownload, autoUnpack, autoDelete); + await _torrents.UploadMagnet(magnetLink, category, autoDelete); } - public async Task TorrentsAddFile(Byte[] fileBytes, String category,Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete) + public async Task TorrentsAddFile(Byte[] fileBytes, String category, Boolean autoDelete) { - await _torrents.UploadFile(fileBytes, category, autoDownload, autoUnpack, autoDelete); + await _torrents.UploadFile(fileBytes, category, autoDelete); } public async Task TorrentsSetCategory(String hash, String category) diff --git a/server/RdtClient.Service/Services/TorrentRunner.cs b/server/RdtClient.Service/Services/TorrentRunner.cs index ce73044..a941ea4 100644 --- a/server/RdtClient.Service/Services/TorrentRunner.cs +++ b/server/RdtClient.Service/Services/TorrentRunner.cs @@ -219,6 +219,9 @@ namespace RdtClient.Service.Services continue; } + var downloadLink = await _torrents.UnrestrictLink(download.DownloadId); + download.Link = downloadLink; + download.DownloadStarted = DateTime.UtcNow; await _downloads.UpdateDownloadStarted(download.DownloadId, download.DownloadStarted); @@ -332,7 +335,7 @@ namespace RdtClient.Service.Services } // RealDebrid is waiting for file selection, select which files to download. - if (torrent.AutoDownload && torrent.RdStatus == RealDebridStatus.WaitingForFileSelection) + if (torrent.RdStatus == RealDebridStatus.WaitingForFileSelection) { Log.Debug($"Torrent {torrent.RdId} selecting files"); @@ -374,7 +377,7 @@ namespace RdtClient.Service.Services Log.Debug($"Selecting files for torrent {torrent.RdId}: {String.Join(", ", fileIds)}"); - await _torrents.SelectFiles(torrent.RdId, fileIds); + await _torrents.SelectFiles(torrent.TorrentId, fileIds); } // If the torrent doesn't have any files at this point, don't process it further. @@ -385,25 +388,16 @@ namespace RdtClient.Service.Services } // RealDebrid finished downloading the torrent, process the file to host. - if (torrent.AutoDownload && torrent.RdStatus == RealDebridStatus.Finished) + if (torrent.RdStatus == RealDebridStatus.Finished) { Log.Debug($"Torrent {torrent.RdId} completed, download starting"); - // If the torrent doesn't have any Downloads, unrestrict the links and add them to the database. - if (torrent.Downloads.Count == 0) - { - Log.Debug($"Torrent {torrent.RdId} unrestricting links"); - - await _torrents.Unrestrict(torrent.TorrentId); - - continue; - } - // If the torrent has any files that need starting to be downloaded, download them. var downloadsPending = torrent.Downloads .Where(m => m.Completed == null && m.DownloadStarted == null && m.DownloadFinished == null) + .OrderBy(m => m.Added) .ToList(); Log.Debug($"Torrent {torrent.RdId} found {downloadsPending.Count} downloads pending"); @@ -421,7 +415,7 @@ namespace RdtClient.Service.Services } } - if (torrent.AutoUnpack && torrent.RdStatus == RealDebridStatus.Finished) + if (torrent.RdStatus == RealDebridStatus.Finished) { Log.Debug($"Torrent {torrent.RdId} completed, unpack starting"); diff --git a/server/RdtClient.Service/Services/Torrents.cs b/server/RdtClient.Service/Services/Torrents.cs index 37b0657..f24b3f4 100644 --- a/server/RdtClient.Service/Services/Torrents.cs +++ b/server/RdtClient.Service/Services/Torrents.cs @@ -20,12 +20,12 @@ namespace RdtClient.Service.Services Task GetById(Guid torrentId); Task GetByHash(String hash); Task UpdateCategory(String hash, String category); - Task UploadMagnet(String magnetLink, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete); - Task UploadFile(Byte[] bytes, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete); + Task UploadMagnet(String magnetLink, String category, Boolean autoDelete); + Task UploadFile(Byte[] bytes, String category, Boolean autoDelete); Task> GetAvailableFiles(String hash); - Task SelectFiles(String torrentId, IList fileIds); + Task SelectFiles(Guid torrentId, IList fileIds); Task Delete(Guid torrentId, Boolean deleteData, Boolean deleteRdTorrent, Boolean deleteLocalFiles); - Task Unrestrict(Guid torrentId); + Task UnrestrictLink(Guid downloadId); Task Download(Guid downloadId); Task Unpack(Guid downloadId); void Reset(); @@ -135,22 +135,22 @@ namespace RdtClient.Service.Services await _torrentData.UpdateCategory(torrent.TorrentId, category); } - public async Task UploadMagnet(String magnetLink, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete) + public async Task UploadMagnet(String magnetLink, String category, Boolean autoDelete) { var magnet = MagnetLink.Parse(magnetLink); var rdTorrent = await GetRdNetClient().AddTorrentMagnetAsync(magnetLink); - await Add(rdTorrent.Id, magnet.InfoHash.ToHex(), category, autoDownload, autoUnpack, autoDelete); + await Add(rdTorrent.Id, magnet.InfoHash.ToHex(), category, autoDelete); } - public async Task UploadFile(Byte[] bytes, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete) + public async Task UploadFile(Byte[] bytes, String category, Boolean autoDelete) { var torrent = await MonoTorrent.Torrent.LoadAsync(bytes); var rdTorrent = await GetRdNetClient().AddTorrentFileAsync(bytes); - await Add(rdTorrent.Id, torrent.InfoHash.ToHex(), category, autoDownload, autoUnpack, autoDelete); + await Add(rdTorrent.Id, torrent.InfoHash.ToHex(), category, autoDelete); } public async Task> GetAvailableFiles(String hash) @@ -164,9 +164,18 @@ namespace RdtClient.Service.Services return groups.Select(m => m.Key).ToList(); } - public async Task SelectFiles(String torrentId, IList fileIds) + public async Task SelectFiles(Guid torrentId, IList fileIds) { - await GetRdNetClient().SelectTorrentFilesAsync(torrentId, fileIds.ToArray()); + var torrent = await GetById(torrentId); + + await GetRdNetClient().SelectTorrentFilesAsync(torrent.RdId, fileIds.ToArray()); + + var rdTorrent = await GetRdNetClient().GetTorrentInfoAsync(torrent.RdId); + + foreach (var file in rdTorrent.Links) + { + await _downloads.Add(torrent.TorrentId, file); + } } public async Task Delete(Guid torrentId, Boolean deleteData, Boolean deleteRdTorrent, Boolean deleteLocalFiles) @@ -212,23 +221,15 @@ namespace RdtClient.Service.Services } } - public async Task Unrestrict(Guid torrentId) + public async Task UnrestrictLink(Guid downloadId) { - var torrent = await _torrentData.GetById(torrentId); + var download = await _downloads.GetById(downloadId); - var rdTorrent = await GetRdNetClient().GetTorrentInfoAsync(torrent.RdId); + var unrestrictedLink = await GetRdNetClient().UnrestrictLinkAsync(download.Path); - foreach (var link in rdTorrent.Links) - { - var unrestrictedLink = await GetRdNetClient().UnrestrictLinkAsync(link); + await _downloads.UpdateUnrestrictedLink(downloadId, unrestrictedLink.Download); - if (torrent.Downloads.Any(m => m.Link == unrestrictedLink.Download)) - { - continue; - } - - await _downloads.Add(torrent.TorrentId, unrestrictedLink.Download); - } + return unrestrictedLink.Download; } public async Task Download(Guid downloadId) @@ -269,7 +270,7 @@ namespace RdtClient.Service.Services return profile; } - private async Task Add(String rdTorrentId, String infoHash, String category, Boolean autoDownload, Boolean autoUnpack, Boolean autoDelete) + private async Task Add(String rdTorrentId, String infoHash, String category, Boolean autoDelete) { var w = await SemaphoreSlim.WaitAsync(60000); if (!w) @@ -286,7 +287,7 @@ namespace RdtClient.Service.Services return; } - var newTorrent = await _torrentData.Add(rdTorrentId, infoHash, category, autoDownload, autoUnpack, autoDelete); + var newTorrent = await _torrentData.Add(rdTorrentId, infoHash, category, autoDelete); var rdTorrent = await GetRdNetClient().GetTorrentInfoAsync(rdTorrentId); diff --git a/server/RdtClient.Web/Controllers/QBittorrentController.cs b/server/RdtClient.Web/Controllers/QBittorrentController.cs index a585755..d396f74 100644 --- a/server/RdtClient.Web/Controllers/QBittorrentController.cs +++ b/server/RdtClient.Web/Controllers/QBittorrentController.cs @@ -245,7 +245,7 @@ namespace RdtClient.Web.Controllers foreach (var url in urls) { - await _qBittorrent.TorrentsAddMagnet(url.Trim(), request.Category, true, true, false); + await _qBittorrent.TorrentsAddMagnet(url.Trim(), request.Category, false); } return Ok(); @@ -265,7 +265,7 @@ namespace RdtClient.Web.Controllers await file.CopyToAsync(target); var fileBytes = target.ToArray(); - await _qBittorrent.TorrentsAddFile(fileBytes, request.Category, true, true, false); + await _qBittorrent.TorrentsAddFile(fileBytes, request.Category, false); } } diff --git a/server/RdtClient.Web/Controllers/TorrentsController.cs b/server/RdtClient.Web/Controllers/TorrentsController.cs index 1e93e9a..ea73343 100644 --- a/server/RdtClient.Web/Controllers/TorrentsController.cs +++ b/server/RdtClient.Web/Controllers/TorrentsController.cs @@ -6,9 +6,10 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using RdtClient.Data.Models.Data; +using MonoTorrent; using RdtClient.Service.Helpers; using RdtClient.Service.Services; +using Torrent = RdtClient.Data.Models.Data.Torrent; namespace RdtClient.Web.Controllers { @@ -74,7 +75,7 @@ namespace RdtClient.Web.Controllers var bytes = memoryStream.ToArray(); - await _torrents.UploadFile(bytes, null, formData.AutoDownload, formData.AutoUnpack, formData.AutoDelete); + await _torrents.UploadFile(bytes, null, formData.AutoDelete); return Ok(); } @@ -83,10 +84,45 @@ namespace RdtClient.Web.Controllers [Route("UploadMagnet")] public async Task UploadMagnet([FromBody] TorrentControllerUploadMagnetRequest request) { - await _torrents.UploadMagnet(request.MagnetLink, null, request.AutoDownload, request.AutoUnpack, request.AutoDelete); + await _torrents.UploadMagnet(request.MagnetLink, null, request.AutoDelete); return Ok(); } + + [HttpPost] + [Route("CheckFiles")] + public async Task CheckFiles([FromForm] IFormFile file) + { + if (file == null || file.Length <= 0) + { + throw new Exception("Invalid torrent file"); + } + + var fileStream = file.OpenReadStream(); + + await using var memoryStream = new MemoryStream(); + + await fileStream.CopyToAsync(memoryStream); + + var bytes = memoryStream.ToArray(); + + var torrent = await MonoTorrent.Torrent.LoadAsync(bytes); + + var result = await _torrents.GetAvailableFiles(torrent.InfoHash.ToHex()); + + return Ok(result); + } + + [HttpPost] + [Route("CheckFilesMagnet")] + public async Task CheckFilesMagnet([FromBody] TorrentControllerCheckFilesRequest request) + { + var magnet = MagnetLink.Parse(request.MagnetLink); + + var result = await _torrents.GetAvailableFiles(magnet.InfoHash.ToHex()); + + return Ok(result); + } [HttpPost] [Route("Delete/{id}")] @@ -101,7 +137,13 @@ namespace RdtClient.Web.Controllers [Route("Download/{id}")] public async Task Download(Guid id) { - await _torrents.Unrestrict(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(); } @@ -123,16 +165,12 @@ namespace RdtClient.Web.Controllers public class TorrentControllerUploadFileRequest { - public Boolean AutoDownload { get; set; } - public Boolean AutoUnpack { get; set; } public Boolean AutoDelete { get; set; } } public class TorrentControllerUploadMagnetRequest { public String MagnetLink { get; set; } - public Boolean AutoDownload { get; set; } - public Boolean AutoUnpack { get; set; } public Boolean AutoDelete { get; set; } } @@ -142,4 +180,9 @@ namespace RdtClient.Web.Controllers public Boolean DeleteRdTorrent { get; set; } public Boolean DeleteLocalFiles { get; set; } } + + public class TorrentControllerCheckFilesRequest + { + public String MagnetLink { get; set; } + } } \ No newline at end of file