Add a download speed tracker.
This commit is contained in:
parent
d7062de42e
commit
c96ce980d5
19 changed files with 168 additions and 479 deletions
|
|
@ -10,6 +10,8 @@ export class Download {
|
||||||
public status: DownloadStatus;
|
public status: DownloadStatus;
|
||||||
|
|
||||||
public progress: number;
|
public progress: number;
|
||||||
|
|
||||||
|
public speed: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DownloadStatus {
|
export enum DownloadStatus {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export class Torrent {
|
||||||
|
|
||||||
files: TorrentFile[];
|
files: TorrentFile[];
|
||||||
downloads: Download[];
|
downloads: Download[];
|
||||||
downloadProgress: number;
|
activeDownload: Download;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TorrentFile {
|
export class TorrentFile {
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,22 @@ export class TorrentStatusPipe implements PipeTransform {
|
||||||
|
|
||||||
transform(torrent: Torrent): string {
|
transform(torrent: Torrent): string {
|
||||||
switch (torrent.status) {
|
switch (torrent.status) {
|
||||||
case TorrentStatus.RealDebrid:
|
case TorrentStatus.RealDebrid: {
|
||||||
const speed = this.pipe.transform(torrent.rdSpeed, 'filesize');
|
const speed = this.pipe.transform(torrent.rdSpeed, 'filesize');
|
||||||
return `Downloading from RD (${torrent.rdProgress}% - ${speed}/s)`;
|
return `Downloading from RD (${torrent.rdProgress}% - ${speed}/s)`;
|
||||||
|
}
|
||||||
case TorrentStatus.WaitingForDownload:
|
case TorrentStatus.WaitingForDownload:
|
||||||
return `Waiting to download`;
|
return `Waiting to download`;
|
||||||
case TorrentStatus.Downloading:
|
case TorrentStatus.Downloading: {
|
||||||
return `Downloading (${torrent.downloadProgress}%)`;
|
if (torrent.activeDownload != null) {
|
||||||
|
const speed = this.pipe.transform(
|
||||||
|
torrent.activeDownload.speed,
|
||||||
|
'filesize'
|
||||||
|
);
|
||||||
|
return `Downloading (${torrent.activeDownload.progress}% - ${speed}/s)`;
|
||||||
|
}
|
||||||
|
return `Downloading`;
|
||||||
|
}
|
||||||
case TorrentStatus.Finished:
|
case TorrentStatus.Finished:
|
||||||
return `Finished`;
|
return `Finished`;
|
||||||
case TorrentStatus.Error:
|
case TorrentStatus.Error:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { Torrent } from '../models/torrent.model';
|
import { Torrent } from '../models/torrent.model';
|
||||||
import { TorrentService } from '../torrent.service';
|
import { TorrentService } from '../torrent.service';
|
||||||
|
import { DownloadStatus } from '../models/download.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-torrent-table',
|
selector: 'app-torrent-table',
|
||||||
|
|
@ -26,6 +27,15 @@ export class TorrentTableComponent implements OnInit, OnDestroy {
|
||||||
this.timer = setInterval(() => {
|
this.timer = setInterval(() => {
|
||||||
this.torrentService.getList().subscribe((result) => {
|
this.torrentService.getList().subscribe((result) => {
|
||||||
this.torrents = result;
|
this.torrents = result;
|
||||||
|
|
||||||
|
this.torrents.forEach((torrent) => {
|
||||||
|
const activeDownloads = torrent.downloads.filter(
|
||||||
|
(m) => m.status === DownloadStatus.Downloading
|
||||||
|
);
|
||||||
|
if (activeDownloads.length > 0) {
|
||||||
|
torrent.activeDownload = activeDownloads[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using RdtClient.Data.Models.Data;
|
using RdtClient.Data.Models.Data;
|
||||||
|
|
@ -50,6 +51,15 @@ namespace RdtClient.Data.Data
|
||||||
Type = "Int32",
|
Type = "Int32",
|
||||||
Value = "10"
|
Value = "10"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var cascadeFKs = builder.Model.GetEntityTypes()
|
||||||
|
.SelectMany(t => t.GetForeignKeys())
|
||||||
|
.Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
foreach (var fk in cascadeFKs)
|
||||||
|
{
|
||||||
|
fk.DeleteBehavior = DeleteBehavior.Restrict;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Migrate()
|
public void Migrate()
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,10 @@ namespace RdtClient.Data.Data
|
||||||
|
|
||||||
public async Task<IList<Download>> Get()
|
public async Task<IList<Download>> Get()
|
||||||
{
|
{
|
||||||
return await _dataContext.Downloads.ToListAsync();
|
return await _dataContext.Downloads
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(m => m.Torrent)
|
||||||
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Download> Add(Guid torrentId, String link)
|
public async Task<Download> Add(Guid torrentId, String link)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace RdtClient.Data.Data
|
||||||
|
|
||||||
public async Task<IList<Setting>> GetAll()
|
public async Task<IList<Setting>> GetAll()
|
||||||
{
|
{
|
||||||
return await _dataContext.Settings.ToListAsync();
|
return await _dataContext.Settings.AsNoTracking().ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Update(IList<Setting> settings)
|
public async Task Update(IList<Setting> settings)
|
||||||
|
|
@ -47,7 +47,7 @@ namespace RdtClient.Data.Data
|
||||||
|
|
||||||
public async Task<Setting> Get(String key)
|
public async Task<Setting> Get(String key)
|
||||||
{
|
{
|
||||||
return await _dataContext.Settings.FirstOrDefaultAsync(m => m.SettingId == key);
|
return await _dataContext.Settings.AsNoTracking().FirstOrDefaultAsync(m => m.SettingId == key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,26 @@ namespace RdtClient.Data.Data
|
||||||
|
|
||||||
public async Task<IList<Torrent>> Get()
|
public async Task<IList<Torrent>> Get()
|
||||||
{
|
{
|
||||||
return await _dataContext.Torrents.ToListAsync();
|
var results = await _dataContext.Torrents
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(m => m.Downloads)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
foreach (var torrent in results)
|
||||||
|
{
|
||||||
|
foreach (var file in torrent.Downloads)
|
||||||
|
{
|
||||||
|
file.Torrent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Torrent> GetById(Guid id)
|
public async Task<Torrent> GetById(Guid id)
|
||||||
{
|
{
|
||||||
var results = await _dataContext.Torrents
|
var results = await _dataContext.Torrents
|
||||||
|
.AsNoTracking()
|
||||||
.Include(m => m.Downloads)
|
.Include(m => m.Downloads)
|
||||||
.FirstOrDefaultAsync(m => m.TorrentId == id);
|
.FirstOrDefaultAsync(m => m.TorrentId == id);
|
||||||
|
|
||||||
|
|
@ -50,6 +64,7 @@ namespace RdtClient.Data.Data
|
||||||
public async Task<Torrent> GetByHash(String hash)
|
public async Task<Torrent> GetByHash(String hash)
|
||||||
{
|
{
|
||||||
var results = await _dataContext.Torrents
|
var results = await _dataContext.Torrents
|
||||||
|
.AsNoTracking()
|
||||||
.Include(m => m.Downloads)
|
.Include(m => m.Downloads)
|
||||||
.FirstOrDefaultAsync(m => m.Hash == hash);
|
.FirstOrDefaultAsync(m => m.Hash == hash);
|
||||||
|
|
||||||
|
|
@ -82,6 +97,8 @@ namespace RdtClient.Data.Data
|
||||||
{
|
{
|
||||||
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId);
|
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId);
|
||||||
|
|
||||||
|
dbTorrent.Status = torrent.Status;
|
||||||
|
|
||||||
dbTorrent.RdName = torrent.RdName;
|
dbTorrent.RdName = torrent.RdName;
|
||||||
dbTorrent.RdSize = torrent.RdSize;
|
dbTorrent.RdSize = torrent.RdSize;
|
||||||
dbTorrent.RdHost = torrent.RdHost;
|
dbTorrent.RdHost = torrent.RdHost;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
{
|
{
|
||||||
PendingDownload = 0,
|
PendingDownload = 0,
|
||||||
Downloading,
|
Downloading,
|
||||||
|
Unpacking,
|
||||||
Finished
|
Finished
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,395 +0,0 @@
|
||||||
// <auto-generated />
|
|
||||||
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("20200403195110_Initial")]
|
|
||||||
partial class Initial
|
|
||||||
{
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "3.1.3");
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("Id")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("ConcurrencyStamp")
|
|
||||||
.IsConcurrencyToken()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasMaxLength(256);
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedName")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasMaxLength(256);
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedName")
|
|
||||||
.IsUnique()
|
|
||||||
.HasName("RoleNameIndex");
|
|
||||||
|
|
||||||
b.ToTable("AspNetRoles");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimType")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimValue")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("RoleId")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("RoleId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetRoleClaims");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("Id")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("AccessFailedCount")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("ConcurrencyStamp")
|
|
||||||
.IsConcurrencyToken()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasMaxLength(256);
|
|
||||||
|
|
||||||
b.Property<bool>("EmailConfirmed")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<bool>("LockoutEnabled")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedEmail")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasMaxLength(256);
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedUserName")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasMaxLength(256);
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<bool>("PhoneNumberConfirmed")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("SecurityStamp")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<bool>("TwoFactorEnabled")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasMaxLength(256);
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedEmail")
|
|
||||||
.HasName("EmailIndex");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedUserName")
|
|
||||||
.IsUnique()
|
|
||||||
.HasName("UserNameIndex");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUsers");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimType")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimValue")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("UserId")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserClaims");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("LoginProvider")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("ProviderKey")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("ProviderDisplayName")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("UserId")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.HasKey("LoginProvider", "ProviderKey");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserLogins");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("UserId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("RoleId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.HasKey("UserId", "RoleId");
|
|
||||||
|
|
||||||
b.HasIndex("RoleId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserRoles");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("UserId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("LoginProvider")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("Value")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.HasKey("UserId", "LoginProvider", "Name");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserTokens");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("RdtClient.Data.Models.Data.Download", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("DownloadId")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("Added")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("Link")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<Guid>("TorrentId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.HasKey("DownloadId");
|
|
||||||
|
|
||||||
b.HasIndex("TorrentId");
|
|
||||||
|
|
||||||
b.ToTable("Downloads");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("RdtClient.Data.Models.Data.Setting", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("SettingId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("Type")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("Value")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.HasKey("SettingId");
|
|
||||||
|
|
||||||
b.ToTable("Settings");
|
|
||||||
|
|
||||||
b.HasData(
|
|
||||||
new
|
|
||||||
{
|
|
||||||
SettingId = "RealDebridApiKey",
|
|
||||||
Type = "String",
|
|
||||||
Value = ""
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
SettingId = "DownloadFolder",
|
|
||||||
Type = "String",
|
|
||||||
Value = "C:\\Downloads"
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
SettingId = "SpeedLimit",
|
|
||||||
Type = "Int32",
|
|
||||||
Value = "0"
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
SettingId = "SegmentsLimit",
|
|
||||||
Type = "Int32",
|
|
||||||
Value = "10"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("RdtClient.Data.Models.Data.Torrent", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("TorrentId")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("Hash")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("RdAdded")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("RdEnded")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("RdFiles")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("RdHost")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("RdId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("RdName")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<long>("RdProgress")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<long?>("RdSeeders")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<long>("RdSize")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<long?>("RdSpeed")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<long>("RdSplit")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("RdStatus")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.HasKey("TorrentId");
|
|
||||||
|
|
||||||
b.ToTable("Torrents");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("RoleId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("RoleId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("RdtClient.Data.Models.Data.Download", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("RdtClient.Data.Models.Data.Torrent", "Torrent")
|
|
||||||
.WithMany("Downloads")
|
|
||||||
.HasForeignKey("TorrentId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace RdtClient.Data.Migrations
|
|
||||||
{
|
|
||||||
public partial class Torrents_Add_Category : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "Category",
|
|
||||||
table: "Torrents",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "Category",
|
|
||||||
table: "Torrents");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -9,8 +9,8 @@ using RdtClient.Data.Data;
|
||||||
namespace RdtClient.Data.Migrations
|
namespace RdtClient.Data.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(DataContext))]
|
[DbContext(typeof(DataContext))]
|
||||||
[Migration("20200406172142_Torrents_Add_Category")]
|
[Migration("20200407174750_Initial")]
|
||||||
partial class Torrents_Add_Category
|
partial class Initial
|
||||||
{
|
{
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
|
|
@ -332,7 +332,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("RoleId")
|
.HasForeignKey("RoleId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -341,7 +341,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -350,7 +350,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -359,13 +359,13 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("RoleId")
|
.HasForeignKey("RoleId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -374,7 +374,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -383,7 +383,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("RdtClient.Data.Models.Data.Torrent", "Torrent")
|
b.HasOne("RdtClient.Data.Models.Data.Torrent", "Torrent")
|
||||||
.WithMany("Downloads")
|
.WithMany("Downloads")
|
||||||
.HasForeignKey("TorrentId")
|
.HasForeignKey("TorrentId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
|
|
@ -65,6 +65,7 @@ namespace RdtClient.Data.Migrations
|
||||||
{
|
{
|
||||||
TorrentId = table.Column<Guid>(nullable: false),
|
TorrentId = table.Column<Guid>(nullable: false),
|
||||||
Hash = table.Column<string>(nullable: true),
|
Hash = table.Column<string>(nullable: true),
|
||||||
|
Category = table.Column<string>(nullable: true),
|
||||||
Status = table.Column<int>(nullable: false),
|
Status = table.Column<int>(nullable: false),
|
||||||
RdId = table.Column<string>(nullable: true),
|
RdId = table.Column<string>(nullable: true),
|
||||||
RdName = table.Column<string>(nullable: true),
|
RdName = table.Column<string>(nullable: true),
|
||||||
|
|
@ -102,7 +103,7 @@ namespace RdtClient.Data.Migrations
|
||||||
column: x => x.RoleId,
|
column: x => x.RoleId,
|
||||||
principalTable: "AspNetRoles",
|
principalTable: "AspNetRoles",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
|
|
@ -123,7 +124,7 @@ namespace RdtClient.Data.Migrations
|
||||||
column: x => x.UserId,
|
column: x => x.UserId,
|
||||||
principalTable: "AspNetUsers",
|
principalTable: "AspNetUsers",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
|
|
@ -143,7 +144,7 @@ namespace RdtClient.Data.Migrations
|
||||||
column: x => x.UserId,
|
column: x => x.UserId,
|
||||||
principalTable: "AspNetUsers",
|
principalTable: "AspNetUsers",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
|
|
@ -161,13 +162,13 @@ namespace RdtClient.Data.Migrations
|
||||||
column: x => x.RoleId,
|
column: x => x.RoleId,
|
||||||
principalTable: "AspNetRoles",
|
principalTable: "AspNetRoles",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Restrict);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
|
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
|
||||||
column: x => x.UserId,
|
column: x => x.UserId,
|
||||||
principalTable: "AspNetUsers",
|
principalTable: "AspNetUsers",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
|
|
@ -187,7 +188,7 @@ namespace RdtClient.Data.Migrations
|
||||||
column: x => x.UserId,
|
column: x => x.UserId,
|
||||||
principalTable: "AspNetUsers",
|
principalTable: "AspNetUsers",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
|
|
@ -208,7 +209,7 @@ namespace RdtClient.Data.Migrations
|
||||||
column: x => x.TorrentId,
|
column: x => x.TorrentId,
|
||||||
principalTable: "Torrents",
|
principalTable: "Torrents",
|
||||||
principalColumn: "TorrentId",
|
principalColumn: "TorrentId",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.InsertData(
|
migrationBuilder.InsertData(
|
||||||
|
|
@ -224,7 +225,7 @@ namespace RdtClient.Data.Migrations
|
||||||
migrationBuilder.InsertData(
|
migrationBuilder.InsertData(
|
||||||
table: "Settings",
|
table: "Settings",
|
||||||
columns: new[] { "SettingId", "Type", "Value" },
|
columns: new[] { "SettingId", "Type", "Value" },
|
||||||
values: new object[] { "DownloadLimit", "Int32", "1" });
|
values: new object[] { "DownloadLimit", "Int32", "10" });
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_AspNetRoleClaims_RoleId",
|
name: "IX_AspNetRoleClaims_RoleId",
|
||||||
|
|
@ -330,7 +330,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("RoleId")
|
.HasForeignKey("RoleId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -339,7 +339,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -348,7 +348,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -357,13 +357,13 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("RoleId")
|
.HasForeignKey("RoleId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -372,7 +372,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -381,7 +381,7 @@ namespace RdtClient.Data.Migrations
|
||||||
b.HasOne("RdtClient.Data.Models.Data.Torrent", "Torrent")
|
b.HasOne("RdtClient.Data.Models.Data.Torrent", "Torrent")
|
||||||
.WithMany("Downloads")
|
.WithMany("Downloads")
|
||||||
.HasForeignKey("TorrentId")
|
.HasForeignKey("TorrentId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
|
|
|
||||||
|
|
@ -23,5 +23,14 @@ namespace RdtClient.Data.Models.Data
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public Int32 Progress { get; set; }
|
public Int32 Progress { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public Int64 Speed { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public DateTime NextUpdate { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public Int64 BytesLastUpdate { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,6 @@ namespace RdtClient.Data.Models.Data
|
||||||
public Int64? RdSeeders { get; set; }
|
public Int64? RdSeeders { get; set; }
|
||||||
public String RdFiles { get; set; }
|
public String RdFiles { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
|
||||||
public Int32 DownloadProgress { get; set; }
|
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public IList<TorrentFile> Files
|
public IList<TorrentFile> Files
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
@ -15,7 +16,7 @@ namespace RdtClient.Service.Services
|
||||||
{
|
{
|
||||||
public static class DownloadManager
|
public static class DownloadManager
|
||||||
{
|
{
|
||||||
public static readonly ConcurrentDictionary<Guid, Download> ActiveDownloads = new ConcurrentDictionary<Guid, Download>();
|
public static readonly Dictionary<Guid, Download> ActiveDownloads = new Dictionary<Guid, Download>();
|
||||||
|
|
||||||
static DownloadManager()
|
static DownloadManager()
|
||||||
{
|
{
|
||||||
|
|
@ -33,11 +34,21 @@ namespace RdtClient.Service.Services
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
download.Progress = 0;
|
||||||
|
download.BytesLastUpdate = 0;
|
||||||
|
download.NextUpdate = DateTime.UtcNow.AddSeconds(1);
|
||||||
|
download.Speed = 0;
|
||||||
|
|
||||||
var fileUrl = download.Link;
|
var fileUrl = download.Link;
|
||||||
|
|
||||||
var uri = new Uri(fileUrl);
|
var uri = new Uri(fileUrl);
|
||||||
var filePath = Path.Combine(destinationFolderPath, uri.Segments.Last());
|
var filePath = Path.Combine(destinationFolderPath, uri.Segments.Last());
|
||||||
|
|
||||||
|
if (!Directory.Exists(destinationFolderPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(destinationFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
var webRequest = WebRequest.Create(fileUrl);
|
var webRequest = WebRequest.Create(fileUrl);
|
||||||
webRequest.Method = "HEAD";
|
webRequest.Method = "HEAD";
|
||||||
Int64 responseLength;
|
Int64 responseLength;
|
||||||
|
|
@ -56,7 +67,6 @@ namespace RdtClient.Service.Services
|
||||||
{
|
{
|
||||||
await using var stream = response.GetResponseStream();
|
await using var stream = response.GetResponseStream();
|
||||||
await using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write);
|
await using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write);
|
||||||
|
|
||||||
var buffer = new Byte[4096];
|
var buffer = new Byte[4096];
|
||||||
|
|
||||||
while (fileStream.Length < response.ContentLength)
|
while (fileStream.Length < response.ContentLength)
|
||||||
|
|
@ -67,8 +77,17 @@ namespace RdtClient.Service.Services
|
||||||
{
|
{
|
||||||
fileStream.Write(buffer, 0, read);
|
fileStream.Write(buffer, 0, read);
|
||||||
|
|
||||||
download.Progress = (Int32) (fileStream.Length * 100 / responseLength);
|
ActiveDownloads[download.DownloadId].Progress = (Int32) (fileStream.Length * 100 / responseLength);
|
||||||
ActiveDownloads.TryAdd(download.DownloadId, download);
|
|
||||||
|
if (DateTime.UtcNow > ActiveDownloads[download.DownloadId]
|
||||||
|
.NextUpdate)
|
||||||
|
{
|
||||||
|
ActiveDownloads[download.DownloadId].Speed = fileStream.Length - ActiveDownloads[download.DownloadId].BytesLastUpdate;
|
||||||
|
ActiveDownloads[download.DownloadId].NextUpdate = DateTime.UtcNow.AddSeconds(1);
|
||||||
|
ActiveDownloads[download.DownloadId].BytesLastUpdate = fileStream.Length;
|
||||||
|
|
||||||
|
Debug.WriteLine($"{fileStream.Length}/{responseLength} {ActiveDownloads[download.DownloadId].Speed}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -77,26 +96,48 @@ namespace RdtClient.Service.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActiveDownloads[download.DownloadId].Speed = 0;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await using Stream stream = File.OpenRead(filePath);
|
if (filePath.EndsWith(".rar"))
|
||||||
|
|
||||||
var reader = ReaderFactory.Open(stream);
|
|
||||||
while (reader.MoveToNextEntry())
|
|
||||||
{
|
{
|
||||||
if (!reader.Entry.IsDirectory)
|
await UpdateStatus(download.DownloadId, DownloadStatus.Unpacking, TorrentStatus.Downloading);
|
||||||
|
|
||||||
|
await using (Stream stream = File.OpenRead(filePath))
|
||||||
{
|
{
|
||||||
Console.WriteLine(reader.Entry.Key);
|
var reader = ReaderFactory.Open(stream);
|
||||||
reader.WriteEntryToDirectory(destinationFolderPath,
|
while (reader.MoveToNextEntry())
|
||||||
new ExtractionOptions
|
{
|
||||||
{
|
if (reader.Entry.IsDirectory)
|
||||||
ExtractFullPath = true,
|
{
|
||||||
Overwrite = true
|
continue;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
reader.WriteEntryToDirectory(destinationFolderPath,
|
||||||
|
new ExtractionOptions
|
||||||
|
{
|
||||||
|
ExtractFullPath = true,
|
||||||
|
Overwrite = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var retryCount = 0;
|
||||||
|
while (File.Exists(filePath) && retryCount < 10)
|
||||||
|
{
|
||||||
|
retryCount++;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(filePath);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File.Delete(filePath);
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
@ -105,7 +146,7 @@ namespace RdtClient.Service.Services
|
||||||
|
|
||||||
await UpdateStatus(download.DownloadId, DownloadStatus.Finished, TorrentStatus.Finished);
|
await UpdateStatus(download.DownloadId, DownloadStatus.Finished, TorrentStatus.Finished);
|
||||||
|
|
||||||
ActiveDownloads.TryRemove(download.DownloadId, out _);
|
ActiveDownloads.Remove(download.DownloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task UpdateStatus(Guid downloadId, DownloadStatus downloadStatus, TorrentStatus torrentStatus)
|
private static async Task UpdateStatus(Guid downloadId, DownloadStatus downloadStatus, TorrentStatus torrentStatus)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Linq;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Hangfire;
|
using Hangfire;
|
||||||
using RdtClient.Data.Enums;
|
using RdtClient.Data.Enums;
|
||||||
|
|
@ -52,8 +53,10 @@ namespace RdtClient.Service.Services
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var folderPath = Path.Combine(destinationFolderPath, download.Torrent.RdName);
|
||||||
|
|
||||||
download.Torrent = null;
|
download.Torrent = null;
|
||||||
BackgroundJob.Enqueue(() => DownloadManager.Download(download, destinationFolderPath));
|
BackgroundJob.Enqueue(() => DownloadManager.Download(download, folderPath));
|
||||||
|
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,12 +80,13 @@ namespace RdtClient.Service.Services
|
||||||
|
|
||||||
foreach (var torrent in torrents)
|
foreach (var torrent in torrents)
|
||||||
{
|
{
|
||||||
var downloads = DownloadManager.ActiveDownloads.Where(m => m.Value.TorrentId == torrent.TorrentId)
|
foreach (var download in torrent.Downloads)
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (torrent.Files.Count > 0)
|
|
||||||
{
|
{
|
||||||
torrent.DownloadProgress = downloads.Sum(m => m.Value.Progress) / torrent.Files.Count;
|
if (DownloadManager.ActiveDownloads.TryGetValue(download.DownloadId, out var activeDownload))
|
||||||
|
{
|
||||||
|
download.Speed = activeDownload.Speed;
|
||||||
|
download.Progress = activeDownload.Progress;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,6 +156,7 @@ namespace RdtClient.Service.Services
|
||||||
|
|
||||||
if (rdTorrent == null)
|
if (rdTorrent == null)
|
||||||
{
|
{
|
||||||
|
await _downloads.DeleteForTorrent(torrent.TorrentId);
|
||||||
await _torrentData.Delete(torrent.TorrentId);
|
await _torrentData.Delete(torrent.TorrentId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -203,6 +205,7 @@ namespace RdtClient.Service.Services
|
||||||
|
|
||||||
if (torrent != null)
|
if (torrent != null)
|
||||||
{
|
{
|
||||||
|
await _downloads.DeleteForTorrent(torrent.TorrentId);
|
||||||
await _torrentData.Delete(id);
|
await _torrentData.Delete(id);
|
||||||
await RdNetClient.TorrentDelete(torrent.RdId);
|
await RdNetClient.TorrentDelete(torrent.RdId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue