Added most functionality on the client and serverside

This commit is contained in:
Roger Far 2020-04-04 15:12:04 -06:00
parent 703d650676
commit f77c1860de
80 changed files with 4081 additions and 72 deletions

View file

@ -0,0 +1,6 @@
{
"/Api": {
"target": "http://localhost:4201/",
"secure": false
}
}

View file

@ -23,13 +23,8 @@
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.scss"],
"scripts": []
},
"configurations": {
@ -66,7 +61,8 @@
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "rdt-client:build"
"browserTarget": "rdt-client:build",
"proxyConfig": "angular-proxy.json"
},
"configurations": {
"production": {
@ -87,13 +83,8 @@
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.scss"],
"scripts": []
}
},
@ -105,9 +96,7 @@
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
"exclude": ["**/node_modules/**"]
}
},
"e2e": {
@ -123,6 +112,7 @@
}
}
}
}},
}
},
"defaultProject": "rdt-client"
}

View file

@ -1371,6 +1371,11 @@
"to-fast-properties": "^2.0.0"
}
},
"@fortawesome/fontawesome-free": {
"version": "5.13.0",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz",
"integrity": "sha512-xKOeQEl5O47GPZYIMToj6uuA2syyFlq9EMSl2ui0uytjY9xbe8XS0pexNWmxrdcCyNGyDmLyYw5FtKsalBUeOg=="
},
"@istanbuljs/schema": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz",
@ -2659,6 +2664,11 @@
"integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
"dev": true
},
"bulma": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/bulma/-/bulma-0.8.1.tgz",
"integrity": "sha512-Afi2zv4DKmNSYfmx55V+Mtnt8+WfR8Rs65kWArmzEuWP7vNr7dSAEDI+ORZlgOR1gueNZwpKaPdUi4ZiTNwgPA=="
},
"bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
@ -4807,6 +4817,11 @@
"minimatch": "^3.0.3"
}
},
"filesize": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz",
"integrity": "sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg=="
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@ -7377,6 +7392,14 @@
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
"dev": true
},
"ngx-filesize": {
"version": "2.0.13",
"resolved": "https://registry.npmjs.org/ngx-filesize/-/ngx-filesize-2.0.13.tgz",
"integrity": "sha512-rdOJMmJTou8tjiMLqxybDD1SWrQETbioXE9InlxABuxGJO0eEWzLfXXxMvNj2o92Wo6YqbkkQwi2KEOk7XvFZw==",
"requires": {
"filesize": ">= 4.0.0"
}
},
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",

View file

@ -19,6 +19,9 @@
"@angular/platform-browser": "~9.1.0",
"@angular/platform-browser-dynamic": "~9.1.0",
"@angular/router": "~9.1.0",
"@fortawesome/fontawesome-free": "^5.13.0",
"bulma": "^0.8.1",
"ngx-filesize": "^2.0.13",
"rxjs": "~6.5.4",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"

View file

@ -1,10 +1,23 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MainLayoutComponent } from './main-layout/main-layout.component';
import { LoginComponent } from './login/login.component';
import { AuthGuard } from './auth.guard';
const routes: Routes = [];
const routes: Routes = [
{
path: 'login',
component: LoginComponent,
},
{
path: '',
component: MainLayoutComponent,
canActivate: [AuthGuard],
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
exports: [RouterModule],
})
export class AppRoutingModule {}

View file

@ -2,7 +2,7 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
template: '<router-outlet></router-outlet>',
styles: []
})
export class AppComponent {}

View file

@ -1,13 +1,44 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { NgxFilesizeModule, FileSizePipe } from 'ngx-filesize';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { MainLayoutComponent } from './main-layout/main-layout.component';
import { NavbarComponent } from './navbar/navbar.component';
import { AddNewTorrentComponent } from './navbar/add-new-torrent/add-new-torrent.component';
import { TorrentTableComponent } from './torrent-table/torrent-table.component';
import { TorrentRowComponent } from './torrent-row/torrent-row.component';
import { TorrentFileComponent } from './torrent-file/torrent-file.component';
import { SettingsComponent } from './navbar/settings/settings.component';
import { TorrentStatusPipe } from './torrent-status.pipe';
import { FileStatusPipe } from './file-status.pipe';
import { LoginComponent } from './login/login.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, AppRoutingModule],
providers: [],
bootstrap: [AppComponent]
declarations: [
AppComponent,
MainLayoutComponent,
NavbarComponent,
AddNewTorrentComponent,
TorrentTableComponent,
TorrentRowComponent,
TorrentFileComponent,
SettingsComponent,
TorrentStatusPipe,
FileStatusPipe,
LoginComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule,
NgxFilesizeModule,
],
providers: [FileSizePipe],
bootstrap: [AppComponent],
})
export class AppModule {}

View file

@ -0,0 +1,27 @@
import { Injectable } from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
Router,
} from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { UsersService } from './users.service';
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate {
constructor(private router: Router, private usersService: UsersService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return true;
//this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
//return false;
}
}

View file

@ -0,0 +1,25 @@
import { Pipe, PipeTransform } from '@angular/core';
import { TorrentFile } from './models/torrent.model';
import { DownloadStatus } from './models/download.model';
@Pipe({
name: 'fileStatus',
})
export class FileStatusPipe implements PipeTransform {
transform(value: TorrentFile): string {
if (
!value.download ||
value.download.status === DownloadStatus.PendingDownload
) {
return 'Pending';
}
if (value.download.status === DownloadStatus.Downloading) {
return `${value.download.progress}%`;
}
if (value.download.status === DownloadStatus.Finished) {
return `Finished`;
}
}
}

View file

@ -0,0 +1,36 @@
<section class="hero is-dark is-fullheight">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
<div class="column is-5-tablet is-4-desktop is-3-widescreen">
<img src="../../assets/logo.png" />
<form class="box">
<div class="field">
<label for="" class="label">Username</label>
<div class="control has-icons-left">
<input type="text" placeholder="" class="input" required />
<span class="icon is-small is-left">
<i class="fa fa-envelope"></i>
</span>
</div>
</div>
<div class="field">
<label for="" class="label">Password</label>
<div class="control has-icons-left">
<input type="password" class="input" required />
<span class="icon is-small is-left">
<i class="fa fa-lock"></i>
</span>
</div>
</div>
<div class="field">
<button class="button is-success">
Login
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View file

@ -0,0 +1,6 @@
<app-navbar></app-navbar>
<section class="section main-list">
<div class="container">
<app-torrent-table></app-torrent-table>
</div>
</section>

View file

@ -0,0 +1,3 @@
.main-list {
padding-top: 6em;
}

View file

@ -0,0 +1,12 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-main-layout',
templateUrl: './main-layout.component.html',
styleUrls: ['./main-layout.component.scss']
})
export class MainLayoutComponent implements OnInit {
constructor() {}
ngOnInit(): void {}
}

View file

@ -0,0 +1,19 @@
export class Download {
public downloadId: string;
public torrentId: string;
public link: string;
public added: Date;
public status: DownloadStatus;
public progress: number;
}
export enum DownloadStatus {
PendingDownload = 0,
Downloading,
Finished,
}

View file

@ -0,0 +1,4 @@
export class Profile {
userName: string;
expiration: Date;
}

View file

@ -0,0 +1,4 @@
export class Setting {
public settingId: string;
public value: string;
}

View file

@ -0,0 +1,41 @@
import { Download } from './download.model';
export class Torrent {
torrentId: string;
hash: string;
status: TorrentStatus;
rdId: string;
rdName: string;
rdSize: number;
rdHost: string;
rdSplit: number;
rdProgress: number;
rdStatus: string;
rdAdded: Date;
rdEnded: Date;
rdSpeed: number;
rdSeeders: number;
rdFiles: string;
files: TorrentFile[];
downloads: Download[];
downloadProgress: number;
}
export class TorrentFile {
id: string;
path: string;
bytes: string;
selected: boolean;
download: Download;
}
export enum TorrentStatus {
RealDebrid = 0,
WaitingForDownload,
Downloading,
Finished,
Error = 99,
}

View file

@ -0,0 +1,66 @@
<div class="modal" [class.is-active]="isActive">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Add New Torrent</p>
<button class="delete" aria-label="close" (click)="cancel()"></button>
</header>
<section class="modal-card-body">
<div class="field">
<label class="label">Magnet Link</label>
<div class="control">
<textarea
class="textarea"
placeholder="Paste your magnet link here"
[(ngModel)]="magnetLink"
[disabled]="saving"
></textarea>
</div>
</div>
<hr />
<div class="field">
<label class="label">Torrent file</label>
<div class="file has-name">
<label class="file-label">
<input
class="file-input"
type="file"
name="resume"
(change)="pickFile($event)"
[disabled]="saving"
/>
<span class="file-cta">
<span class="file-icon">
<i class="fas fa-upload"></i>
</span>
<span class="file-label">
Pick a torrent file...
</span>
</span>
<span class="file-name">
{{ fileName }}
</span>
</label>
</div>
</div>
<div class="notification is-danger is-light" *ngIf="error?.length > 0">
Cannot add torrent: {{ error }}
</div>
</section>
<footer class="modal-card-foot">
<button class="button is-success" *ngIf="saving">
<span class="icon">
<i class="fas fa-spinner fa-pulse"></i>
</span>
<span>Add Torrent</span>
</button>
<button class="button is-success" (click)="ok()" *ngIf="!saving">
Add Torrent
</button>
<button class="button" (click)="cancel()" [disabled]="saving">
Cancel
</button>
</footer>
</div>
</div>

View file

@ -0,0 +1,4 @@
.file-name {
max-width: 24em;
width: 24em;
}

View file

@ -0,0 +1,91 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { TorrentService } from 'src/app/torrent.service';
@Component({
selector: 'app-add-new-torrent',
templateUrl: './add-new-torrent.component.html',
styleUrls: ['./add-new-torrent.component.scss']
})
export class AddNewTorrentComponent implements OnInit {
@Input()
public get open(): boolean {
return this.isActive;
}
public set open(val: boolean) {
this.reset();
this.isActive = val;
}
@Output()
public openChange = new EventEmitter<boolean>();
public isActive = false;
public fileName: string;
public magnetLink: string;
public saving = false;
public error: string;
private selectedFile: File;
constructor(private torrentService: TorrentService) {}
ngOnInit(): void {}
public reset(): void {
this.fileName = '';
this.magnetLink = '';
this.saving = false;
this.selectedFile = null;
this.error = null;
}
public pickFile(evt: Event): void {
const files = (evt.target as HTMLInputElement).files;
if (files.length === 0) {
return;
}
const file = files[0];
this.fileName = file.name;
this.selectedFile = file;
}
public ok(): void {
this.saving = true;
this.error = null;
if (this.magnetLink) {
this.torrentService.uploadMagnet(this.magnetLink).subscribe(
() => {
this.cancel();
},
err => {
this.error = err.error;
this.saving = false;
}
);
} else if (this.selectedFile) {
this.torrentService.uploadFile(this.selectedFile).subscribe(
() => {
this.cancel();
},
err => {
this.error = err.error;
this.saving = false;
}
);
} else {
this.cancel();
}
}
public cancel(): void {
this.isActive = false;
this.openChange.emit(this.open);
}
}

View file

@ -0,0 +1,77 @@
<nav
class="navbar is-dark is-fixed-top"
role="navigation"
aria-label="main navigation"
>
<div class="navbar-brand">
<a class="navbar-item">
<img src="../../assets/logo.png" />
</a>
<a
role="button"
class="navbar-burger burger"
aria-label="menu"
aria-expanded="false"
[class.is-active]="showMobileMenu"
(click)="showMobileMenu = !showMobileMenu"
>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div class="navbar-menu" [class.is-active]="showMobileMenu">
<div class="navbar-start">
<a class="navbar-item" (click)="this.showNewTorrent = true">
<span class="icon">
<i class="fas fa-plus" aria-hidden="true"></i>
</span>
<span>Add New Torrent</span>
</a>
<a class="navbar-item" (click)="this.showSettings = true">
<span class="icon">
<i class="fas fa-cog" aria-hidden="true"></i>
</span>
<span>Settings</span>
</a>
<a
class="navbar-item"
*ngIf="profile"
href="https://real-debrid.com/?id=1348683"
target="_blank"
rel="noopener"
>
<span class="icon">
<i class="fas fa-euro-sign" aria-hidden="true"></i>
</span>
<span>Premium Status: {{ profile.expiration | date }}</span>
</a>
</div>
<div class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<span class="navbar-link">
Account
</span>
<div class="navbar-dropdown is-right">
<a class="navbar-item">
Profile
</a>
<a class="navbar-item">
Logout
</a>
<hr class="navbar-divider" />
<div class="navbar-item">
Version 0.8.0
</div>
</div>
</div>
</div>
</div>
</nav>
<app-add-new-torrent [(open)]="showNewTorrent"></app-add-new-torrent>
<app-settings [(open)]="showSettings"></app-settings>

View file

@ -0,0 +1,26 @@
import { Component, OnInit } from '@angular/core';
import { TorrentService } from '../torrent.service';
import { SettingsService } from '../settings.service';
import { Profile } from '../models/profile.model';
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss'],
})
export class NavbarComponent implements OnInit {
public showMobileMenu = false;
public showNewTorrent = false;
public showSettings = false;
public profile: Profile;
constructor(private settingsService: SettingsService) {}
ngOnInit(): void {
this.settingsService.getProfile().subscribe((result) => {
this.profile = result;
});
}
}

View file

@ -0,0 +1,79 @@
<div class="modal" [class.is-active]="isActive">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Settings</p>
<button class="delete" aria-label="close" (click)="cancel()"></button>
</header>
<section class="modal-card-body">
<div class="field">
<label class="label">Real-Debrid API Key</label>
<div class="control">
<input
class="input"
type="text"
maxlength="100"
[(ngModel)]="settingRealDebridApiKey"
/>
</div>
<p class="help">
You can find your API key here:
<a
href="https://real-debrid.com/apitoken"
target="_blank"
rel="noopener"
>https://real-debrid.com/apitoken</a
>.
</p>
</div>
<div class="field">
<label class="label">Download folder</label>
<div class="control">
<input
class="input"
type="text"
maxlength="1000"
[(ngModel)]="settingDownloadFolder"
/>
</div>
<p class="help">
Path on the host where Real Debrid Client is hosted.
</p>
</div>
<div class="field">
<label class="label">Maximum parallel downloads</label>
<div class="control">
<input
class="input"
type="number"
max="100"
min="1"
[(ngModel)]="settingDownloadLimit"
/>
</div>
<p class="help">
Maximum amount of torrents that get downloaded to your host at the
same time.
</p>
</div>
<div class="notification is-danger is-light" *ngIf="error?.length > 0">
Error saving settings: {{ error }}
</div>
</section>
<footer class="modal-card-foot">
<button class="button is-success" *ngIf="saving">
<span class="icon">
<i class="fas fa-spinner fa-pulse"></i>
</span>
<span>Save Settings</span>
</button>
<button class="button is-success" (click)="ok()" *ngIf="!saving">
Save Settings
</button>
<button class="button" (click)="cancel()" [disabled]="saving">
Cancel
</button>
</footer>
</div>
</div>

View file

@ -0,0 +1,103 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { SettingsService } from 'src/app/settings.service';
import { Setting } from 'src/app/models/setting.model';
@Component({
selector: 'app-settings',
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.scss'],
})
export class SettingsComponent implements OnInit {
@Input()
public get open(): boolean {
return this.isActive;
}
public set open(val: boolean) {
this.reset();
this.isActive = val;
}
@Output()
public openChange = new EventEmitter<boolean>();
public isActive = false;
public saving = false;
public error: string;
public settingRealDebridApiKey: string;
public settingDownloadFolder: string;
public settingDownloadLimit: number;
constructor(private settingsService: SettingsService) {}
ngOnInit(): void {}
public reset(): void {
this.saving = false;
this.error = null;
this.settingsService.get().subscribe(
(results) => {
this.settingRealDebridApiKey = this.getSetting(
results,
'RealDebridApiKey'
);
this.settingDownloadFolder = this.getSetting(results, 'DownloadFolder');
this.settingDownloadLimit = parseInt(
this.getSetting(results, 'DownloadLimit'),
10
);
},
(err) => {
this.error = err.error;
this.saving = true;
}
);
}
public ok(): void {
this.saving = true;
const settings: Setting[] = [
{
settingId: 'RealDebridApiKey',
value: this.settingRealDebridApiKey,
},
{
settingId: 'DownloadFolder',
value: this.settingDownloadFolder,
},
{
settingId: 'DownloadLimit',
value: (this.settingDownloadLimit ?? 10).toString(),
},
];
this.settingsService.update(settings).subscribe(
() => {
this.isActive = false;
this.openChange.emit(this.open);
},
(err) => {
this.error = err;
}
);
}
public cancel(): void {
this.isActive = false;
this.openChange.emit(this.open);
}
private getSetting(settings: Setting[], key: string): string {
const setting = settings.filter((m) => m.settingId === key);
if (setting.length !== 1) {
throw new Error(`Unable to find setting with key ${key}`);
}
return setting[0].value;
}
}

View file

@ -0,0 +1,24 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Setting } from './models/setting.model';
import { Profile } from './models/profile.model';
@Injectable({
providedIn: 'root',
})
export class SettingsService {
constructor(private http: HttpClient) {}
public get(): Observable<Setting[]> {
return this.http.get<Setting[]>(`/Api/Settings`);
}
public update(settings: Setting[]): Observable<void> {
return this.http.put<void>(`/Api/Settings`, { settings });
}
public getProfile(): Observable<Profile> {
return this.http.get<Profile>(`/Api/Settings/Profile`);
}
}

View file

@ -0,0 +1,10 @@
<td>
<i class="fas fa-file" aria-hidden="true"></i>
{{ file.path }}
</td>
<td>{{ file.bytes | filesize }}</td>
<td>
{{ file | fileStatus }}
</td>
<td></td>
<td></td>

View file

@ -0,0 +1,3 @@
td {
font-size: smaller;
}

View file

@ -0,0 +1,17 @@
import { Component, OnInit, Input } from '@angular/core';
import { Torrent, TorrentFile } from '../models/torrent.model';
import { TorrentService } from '../torrent.service';
@Component({
selector: '[app-torrent-file]',
templateUrl: './torrent-file.component.html',
styleUrls: ['./torrent-file.component.scss'],
})
export class TorrentFileComponent implements OnInit {
@Input()
public file: TorrentFile;
constructor(private torrentService: TorrentService) {}
ngOnInit(): void {}
}

View file

@ -0,0 +1,27 @@
<td>{{ torrent.rdName }}</td>
<td>
{{ torrent.rdSize | filesize }}
</td>
<td>
{{ torrent | status }}
</td>
<td>
<span
class="icon download-icon"
(click)="download($event)"
title="Download to disk"
*ngIf="!loading && torrent.status === 1"
>
<i class="fas fa-download"></i>
</span>
</td>
<td>
<span
class="icon delete-icon"
(click)="delete($event)"
title="Delete torrent"
*ngIf="!loading"
>
<i class="fas fa-times"></i>
</span>
</td>

View file

@ -0,0 +1,4 @@
.delete-icon {
color: red;
cursor: pointer;
}

View file

@ -0,0 +1,36 @@
import { Component, OnInit, Input } from '@angular/core';
import { Torrent, TorrentStatus } from 'src/app/models/torrent.model';
import { TorrentService } from 'src/app/torrent.service';
@Component({
selector: '[app-torrent-row]',
templateUrl: './torrent-row.component.html',
styleUrls: ['./torrent-row.component.scss'],
})
export class TorrentRowComponent implements OnInit {
@Input()
public torrent: Torrent;
public loading = false;
constructor(private torrentService: TorrentService) {}
ngOnInit(): void {}
public download(event: Event): void {
event.stopPropagation();
this.loading = true;
this.torrentService.download(this.torrent.torrentId).subscribe(() => {
this.loading = false;
this.torrent.status = TorrentStatus.Downloading;
});
}
public delete(event: Event): void {
event.stopPropagation();
this.loading = true;
this.torrentService.delete(this.torrent.torrentId).subscribe(() => {});
}
}

View file

@ -0,0 +1,28 @@
import { Pipe, PipeTransform } from '@angular/core';
import { Torrent, TorrentStatus } from './models/torrent.model';
import { FileSizePipe } from 'ngx-filesize';
@Pipe({
name: 'status',
})
export class TorrentStatusPipe implements PipeTransform {
constructor(private pipe: FileSizePipe) {}
transform(torrent: Torrent): string {
switch (torrent.status) {
case TorrentStatus.RealDebrid:
const speed = this.pipe.transform(torrent.rdSpeed, 'filesize');
return `Downloading from RD (${torrent.rdProgress}% - ${speed}/s)`;
case TorrentStatus.WaitingForDownload:
return `Waiting to download`;
case TorrentStatus.Downloading:
return `Downloading (${torrent.downloadProgress}%)`;
case TorrentStatus.Finished:
return `Finished`;
case TorrentStatus.Error:
return `Error`;
default:
return 'Unknown status';
}
}
}

View file

@ -0,0 +1,48 @@
<div class="table-container">
<table class="table is-fullwidth is-hoverable">
<colgroup>
<col />
<col />
<col />
<col style="width: 50px;" />
<col style="width: 50px;" />
</colgroup>
<thead>
<tr>
<th>Name</th>
<th>Size</th>
<th>Status</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let torrent of torrents; trackBy: trackByMethod">
<tr
app-torrent-row
[torrent]="torrent"
(click)="selectTorrent(torrent)"
></tr>
<ng-container
*ngIf="showFiles[torrent.torrentId] && torrent?.files.length === 0"
>
<tr>
<td colspan="20">
<i class="fas fa-spinner fa-pulse"></i>
</td>
</tr>
</ng-container>
<ng-container
*ngIf="showFiles[torrent.torrentId] && torrent?.files.length > 0"
>
<tr
app-torrent-file
[file]="file"
*ngFor="let file of torrent.files"
></tr>
</ng-container>
</ng-container>
</tbody>
</table>
</div>

View file

@ -0,0 +1,5 @@
table {
tr {
cursor: pointer;
}
}

View file

@ -0,0 +1,61 @@
import {
Component,
OnInit,
OnDestroy,
HostListener,
ElementRef,
} from '@angular/core';
import { Torrent } from '../models/torrent.model';
import { TorrentService } from '../torrent.service';
@Component({
selector: 'app-torrent-table',
templateUrl: './torrent-table.component.html',
styleUrls: ['./torrent-table.component.scss'],
})
export class TorrentTableComponent implements OnInit, OnDestroy {
public torrents: Torrent[] = [];
public showFiles: { [key: string]: boolean } = {};
private timer: any;
constructor(private torrentService: TorrentService) {}
ngOnInit(): void {
this.timer = setInterval(() => {
this.torrentService.getList().subscribe((result) => {
this.torrents = result;
});
}, 1000);
}
ngOnDestroy(): void {
clearInterval(this.timer);
}
public selectTorrent(torrent: Torrent): void {
this.showFiles[torrent.torrentId] = !this.showFiles[torrent.torrentId];
if (this.showFiles[torrent.torrentId]) {
this.torrentService.getDetails(torrent.torrentId).subscribe((result) => {
torrent.files = result.files;
torrent.downloads = result.downloads;
torrent.files.forEach((file) => {
const downloads = torrent.downloads.filter(
(m) => m.link === file.path
);
if (downloads.length > 0) {
file.download = downloads[0];
}
});
});
}
}
public trackByMethod(index: number, el: Torrent): string {
return el.torrentId;
}
}

View file

@ -0,0 +1,37 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, Subject } from 'rxjs';
import { Torrent } from './models/torrent.model';
@Injectable({
providedIn: 'root',
})
export class TorrentService {
constructor(private http: HttpClient) {}
public getList(): Observable<Torrent[]> {
return this.http.get<Torrent[]>(`/Api/Torrents`);
}
public getDetails(torrentId: string): Observable<Torrent> {
return this.http.get<Torrent>(`/Api/Torrents/${torrentId}`);
}
public uploadMagnet(magnetLink: string): Observable<void> {
return this.http.post<void>(`/Api/Torrents/UploadMagnet`, { magnetLink });
}
public uploadFile(file: File): Observable<void> {
const formData: FormData = new FormData();
formData.append('file', file);
return this.http.post<void>(`/Api/Torrents/UploadFile`, formData);
}
public download(torrentId: string): Observable<void> {
return this.http.get<void>(`/Api/Torrents/Download/${torrentId}`);
}
public delete(torrentId: string): Observable<void> {
return this.http.delete<void>(`/Api/Torrents/${torrentId}`);
}
}

View file

@ -0,0 +1,10 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class UsersService {
constructor() {}
public getLoggedInUser() {}
}

BIN
client/src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1 +1,2 @@
/* You can add global styles to this file, and also import other style files */
@import "../node_modules/bulma/bulma.sass";
@import "../node_modules/@fortawesome/fontawesome-free/css/all.css";

View file

@ -0,0 +1,60 @@
using System;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using RdtClient.Data.Models.Data;
namespace RdtClient.Data.Data
{
public class DataContext : IdentityDbContext
{
public DataContext(DbContextOptions options) : base(options)
{
}
public DataContext()
{
}
public static String ConnectionString => $"Data Source={AppContext.BaseDirectory}database.db";
public DbSet<Download> Downloads { get; set; }
public DbSet<Setting> Settings { get; set; }
public DbSet<Torrent> Torrents { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlite(ConnectionString);
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Setting>()
.HasData(new Setting
{
SettingId = "RealDebridApiKey",
Type = "String",
Value = ""
});
builder.Entity<Setting>()
.HasData(new Setting
{
SettingId = "DownloadFolder",
Type = "String",
Value = @"C:\Downloads"
});
builder.Entity<Setting>()
.HasData(new Setting
{
SettingId = "DownloadLimit",
Type = "Int32",
Value = "10"
});
}
public void Migrate()
{
Database.Migrate();
}
}
}

View file

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
namespace RdtClient.Data.Data
{
public interface IDownloadData
{
Task<IList<Download>> Get();
Task<Download> Add(Guid torrentId, String link);
Task UpdateStatus(Guid downloadId, DownloadStatus status);
Task DeleteForTorrent(Guid torrentId);
}
public class DownloadData : IDownloadData
{
private readonly DataContext _dataContext;
public DownloadData(DataContext dataContext)
{
_dataContext = dataContext;
}
public async Task<IList<Download>> Get()
{
return await _dataContext.Downloads.ToListAsync();
}
public async Task<Download> Add(Guid torrentId, String link)
{
var download = new Download
{
DownloadId = Guid.NewGuid(),
TorrentId = torrentId,
Link = link,
Added = DateTimeOffset.UtcNow,
Status = DownloadStatus.PendingDownload
};
_dataContext.Downloads.Add(download);
await _dataContext.SaveChangesAsync();
return download;
}
public async Task UpdateStatus(Guid downloadId, DownloadStatus status)
{
var download = await _dataContext.Downloads.FirstOrDefaultAsync(m => m.DownloadId == downloadId);
download.Status = status;
await _dataContext.SaveChangesAsync();
}
public async Task DeleteForTorrent(Guid torrentId)
{
var downloads = await _dataContext.Downloads
.Where(m => m.TorrentId == torrentId)
.ToListAsync();
_dataContext.Downloads.RemoveRange(downloads);
await _dataContext.SaveChangesAsync();
}
}
}

View file

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using RdtClient.Data.Models.Data;
namespace RdtClient.Data.Data
{
public interface ISettingData
{
Task<IList<Setting>> GetAll();
Task Update(IList<Setting> settings);
Task<Setting> Get(String key);
}
public class SettingData : ISettingData
{
private readonly DataContext _dataContext;
public SettingData(DataContext dataContext)
{
_dataContext = dataContext;
}
public async Task<IList<Setting>> GetAll()
{
return await _dataContext.Settings.ToListAsync();
}
public async Task Update(IList<Setting> settings)
{
var dbSettings = await _dataContext.Settings.ToListAsync();
foreach (var dbSetting in dbSettings)
{
var setting = settings.FirstOrDefault(m => m.SettingId == dbSetting.SettingId);
if (setting != null)
{
dbSetting.Value = setting.Value;
}
}
await _dataContext.SaveChangesAsync();
}
public async Task<Setting> Get(String key)
{
return await _dataContext.Settings.FirstOrDefaultAsync(m => m.SettingId == key);
}
}
}

View file

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
namespace RdtClient.Data.Data
{
public interface ITorrentData
{
Task<IList<Torrent>> Get();
Task<Torrent> Get(Guid id);
Task<Torrent> Add(String realDebridId, String hash);
Task UpdateRdData(Torrent torrent);
Task UpdateStatus(Guid torrentId, TorrentStatus status);
Task Delete(Guid id);
}
public class TorrentData : ITorrentData
{
private readonly DataContext _dataContext;
public TorrentData(DataContext dataContext)
{
_dataContext = dataContext;
}
public async Task<IList<Torrent>> Get()
{
return await _dataContext.Torrents.ToListAsync();
}
public async Task<Torrent> Get(Guid id)
{
var results = await _dataContext.Torrents
.Include(m => m.Downloads)
.FirstOrDefaultAsync(m => m.TorrentId == id);
foreach (var file in results.Downloads)
{
file.Torrent = null;
}
return results;
}
public async Task<Torrent> Add(String realDebridId, String hash)
{
var torrent = new Torrent
{
TorrentId = Guid.NewGuid(),
RdId = realDebridId,
Hash = hash,
Status = TorrentStatus.RealDebrid
};
_dataContext.Torrents.Add(torrent);
await _dataContext.SaveChangesAsync();
return torrent;
}
public async Task UpdateRdData(Torrent torrent)
{
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrent.TorrentId);
dbTorrent.RdName = torrent.RdName;
dbTorrent.RdSize = torrent.RdSize;
dbTorrent.RdHost = torrent.RdHost;
dbTorrent.RdSplit = torrent.RdSplit;
dbTorrent.RdProgress = torrent.RdProgress;
dbTorrent.RdStatus = torrent.RdStatus;
dbTorrent.RdAdded = torrent.RdAdded;
dbTorrent.RdEnded = torrent.RdEnded;
dbTorrent.RdSpeed = torrent.RdSpeed;
dbTorrent.RdSeeders = torrent.RdSeeders;
await _dataContext.SaveChangesAsync();
}
public async Task UpdateStatus(Guid torrentId, TorrentStatus status)
{
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == torrentId);
dbTorrent.Status = status;
await _dataContext.SaveChangesAsync();
}
public async Task Delete(Guid id)
{
var dbTorrent = await _dataContext.Torrents.FirstOrDefaultAsync(m => m.TorrentId == id);
_dataContext.Torrents.Remove(dbTorrent);
await _dataContext.SaveChangesAsync();
}
}
}

View file

@ -1,9 +0,0 @@
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
namespace RdtClient.Data.DataContext
{
public class DataContext : IdentityDbContext
{
}
}

View file

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using RdtClient.Data.Data;
namespace RdtClient.Data
{
@ -6,7 +7,9 @@ namespace RdtClient.Data
{
public static void Config(IServiceCollection services)
{
//services.AddScoped<IFql, Fql>();
services.AddScoped<IDownloadData, DownloadData>();
services.AddScoped<ISettingData, SettingData>();
services.AddScoped<ITorrentData, TorrentData>();
}
}
}

View file

@ -0,0 +1,9 @@
namespace RdtClient.Data.Enums
{
public enum DownloadStatus
{
PendingDownload = 0,
Downloading,
Finished
}
}

View file

@ -0,0 +1,12 @@
namespace RdtClient.Data.Enums
{
public enum TorrentStatus
{
RealDebrid = 0,
WaitingForDownload,
Downloading,
Finished,
Error = 99
}
}

View file

@ -0,0 +1,395 @@
// <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
}
}
}

View file

@ -0,0 +1,305 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace RdtClient.Data.Migrations
{
public partial class Initial : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserName = table.Column<string>(maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
Email = table.Column<string>(maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(nullable: false),
PasswordHash = table.Column<string>(nullable: true),
SecurityStamp = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
PhoneNumber = table.Column<string>(nullable: true),
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
TwoFactorEnabled = table.Column<bool>(nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnabled = table.Column<bool>(nullable: false),
AccessFailedCount = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Settings",
columns: table => new
{
SettingId = table.Column<string>(nullable: false),
Value = table.Column<string>(nullable: true),
Type = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Settings", x => x.SettingId);
});
migrationBuilder.CreateTable(
name: "Torrents",
columns: table => new
{
TorrentId = table.Column<Guid>(nullable: false),
Hash = table.Column<string>(nullable: true),
Status = table.Column<int>(nullable: false),
RdId = table.Column<string>(nullable: true),
RdName = table.Column<string>(nullable: true),
RdSize = table.Column<long>(nullable: false),
RdHost = table.Column<string>(nullable: true),
RdSplit = table.Column<long>(nullable: false),
RdProgress = table.Column<long>(nullable: false),
RdStatus = table.Column<string>(nullable: true),
RdAdded = table.Column<DateTimeOffset>(nullable: false),
RdEnded = table.Column<DateTimeOffset>(nullable: true),
RdSpeed = table.Column<long>(nullable: true),
RdSeeders = table.Column<long>(nullable: true),
RdFiles = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Torrents", x => x.TorrentId);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
RoleId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
UserId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(nullable: false),
ProviderKey = table.Column<string>(nullable: false),
ProviderDisplayName = table.Column<string>(nullable: true),
UserId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
RoleId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
LoginProvider = table.Column<string>(nullable: false),
Name = table.Column<string>(nullable: false),
Value = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Downloads",
columns: table => new
{
DownloadId = table.Column<Guid>(nullable: false),
TorrentId = table.Column<Guid>(nullable: false),
Link = table.Column<string>(nullable: true),
Added = table.Column<DateTimeOffset>(nullable: false),
Status = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Downloads", x => x.DownloadId);
table.ForeignKey(
name: "FK_Downloads_Torrents_TorrentId",
column: x => x.TorrentId,
principalTable: "Torrents",
principalColumn: "TorrentId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.InsertData(
table: "Settings",
columns: new[] { "SettingId", "Type", "Value" },
values: new object[] { "RealDebridApiKey", "String", "" });
migrationBuilder.InsertData(
table: "Settings",
columns: new[] { "SettingId", "Type", "Value" },
values: new object[] { "DownloadFolder", "String", "C:\\Downloads" });
migrationBuilder.InsertData(
table: "Settings",
columns: new[] { "SettingId", "Type", "Value" },
values: new object[] { "DownloadLimit", "Int32", "1" });
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Downloads_TorrentId",
table: "Downloads",
column: "TorrentId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "Downloads");
migrationBuilder.DropTable(
name: "Settings");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "AspNetUsers");
migrationBuilder.DropTable(
name: "Torrents");
}
}
}

View file

@ -0,0 +1,387 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using RdtClient.Data.Data;
namespace RdtClient.Data.Migrations
{
[DbContext(typeof(DataContext))]
partial class DataContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(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 = "DownloadLimit",
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
}
}
}

View file

@ -0,0 +1,27 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using RdtClient.Data.Enums;
namespace RdtClient.Data.Models.Data
{
public class Download
{
[Key]
public Guid DownloadId { get; set; }
public Guid TorrentId { get; set; }
public String Link { get; set; }
public DateTimeOffset Added { get; set; }
public DownloadStatus Status { get; set; }
[ForeignKey("TorrentId")]
public Torrent Torrent { get; set; }
[NotMapped]
public Int32 Progress { get; set; }
}
}

View file

@ -0,0 +1,15 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace RdtClient.Data.Models.Data
{
public class Setting
{
[Key]
public String SettingId { get; set; }
public String Value { get; set; }
public String Type { get; set; }
}
}

View file

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
using RDNET.Models;
using RdtClient.Data.Enums;
namespace RdtClient.Data.Models.Data
{
public class Torrent
{
[Key]
public Guid TorrentId { get; set; }
public String Hash { get; set; }
public TorrentStatus Status { get; set; }
[InverseProperty("Torrent")]
public IList<Download> Downloads { get; set; }
public String RdId { get; set; }
public String RdName { get; set; }
public Int64 RdSize { get; set; }
public String RdHost { get; set; }
public Int64 RdSplit { get; set; }
public Int64 RdProgress { get; set; }
public String RdStatus { get; set; }
public DateTimeOffset RdAdded { get; set; }
public DateTimeOffset? RdEnded { get; set; }
public Int64? RdSpeed { get; set; }
public Int64? RdSeeders { get; set; }
public String RdFiles { get; set; }
[NotMapped]
public Int32 DownloadProgress { get; set; }
[NotMapped]
public IList<TorrentFile> Files
{
get
{
if (String.IsNullOrWhiteSpace(RdFiles))
{
return new List<TorrentFile>();
}
try
{
return JsonConvert.DeserializeObject<List<TorrentFile>>(RdFiles);
}
catch
{
return new List<TorrentFile>();
}
}
}
}
}

View file

@ -1,14 +1,6 @@
using System;
namespace RdtClient.Data.Models.Internal
namespace RdtClient.Data.Models.Internal
{
public class AppSettings
{
public AppSettingsConnectionStrings ConnectionStrings { get; set; }
}
public class AppSettingsConnectionStrings
{
public String Client { get; set; }
}
}

View file

@ -4,14 +4,47 @@
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Migrations\20200402172935_AspNetIdentity.cs" />
<Compile Remove="Migrations\20200402172935_AspNetIdentity.Designer.cs" />
<Compile Remove="Migrations\20200402173119_Torrents.cs" />
<Compile Remove="Migrations\20200402173119_Torrents.Designer.cs" />
<Compile Remove="Migrations\20200402190746_Torrents.cs" />
<Compile Remove="Migrations\20200402190746_Torrents.Designer.cs" />
<Compile Remove="Migrations\20200402194059_Torrents.cs" />
<Compile Remove="Migrations\20200402194059_Torrents.Designer.cs" />
<Compile Remove="Migrations\20200402212417_Torrents.cs" />
<Compile Remove="Migrations\20200402212417_Torrents.Designer.cs" />
<Compile Remove="Migrations\20200403143200_Torrent.cs" />
<Compile Remove="Migrations\20200403143200_Torrent.Designer.cs" />
<Compile Remove="Migrations\20200403143240_Settings.cs" />
<Compile Remove="Migrations\20200403143240_Settings.Designer.cs" />
<Compile Remove="Migrations\20200403145651_Settings.cs" />
<Compile Remove="Migrations\20200403145651_Settings.Designer.cs" />
<Compile Remove="Migrations\20200403164143_Downloads.cs" />
<Compile Remove="Migrations\20200403164143_Downloads.Designer.cs" />
<Compile Remove="Migrations\20200403174830_Initia.cs" />
<Compile Remove="Migrations\20200403174830_Initia.Designer.cs" />
<Compile Remove="Migrations\20200403174846_Initial.cs" />
<Compile Remove="Migrations\20200403174846_Initial.Designer.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.3" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>
<Reference Include="RDNET">
<HintPath>..\libs\RDNET.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View file

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using RdtClient.Service.Services;
namespace RdtClient.Service
{
@ -6,7 +7,10 @@ namespace RdtClient.Service
{
public static void Config(IServiceCollection services)
{
//services.AddScoped<IFql, Fql>();
services.AddScoped<IDownloads, Downloads>();
services.AddScoped<IScheduler, Scheduler>();
services.AddScoped<ISettings, Settings>();
services.AddScoped<ITorrents, Torrents>();
}
}
}
}

View file

@ -0,0 +1,10 @@
using System;
namespace RdtClient.Service.Models
{
public class Profile
{
public String UserName { get; set; }
public DateTimeOffset Expiration { get; set; }
}
}

View file

@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53591/",
"sslPort": 44310
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"RdtClient.Service": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

View file

@ -1,11 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>library</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Hangfire.Core" Version="1.7.10" />
<PackageReference Include="MonoTorrent" Version="1.0.19" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="SharpCompress" Version="0.25.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RdtClient.Data\RdtClient.Data.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="RDNET">
<HintPath>..\libs\RDNET.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>IIS Express</ActiveDebugProfile>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,147 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using RdtClient.Data.Data;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
using SharpCompress.Common;
using SharpCompress.Readers;
namespace RdtClient.Service.Services
{
public class DownloadManager
{
public static readonly ConcurrentDictionary<Guid, Download> ActiveDownloads = new ConcurrentDictionary<Guid, Download>();
private static readonly Object Lock = new Object();
static DownloadManager()
{
ServicePointManager.Expect100Continue = false;
ServicePointManager.DefaultConnectionLimit = 100;
ServicePointManager.MaxServicePointIdleTime = 1000;
}
public static async Task Download(Download download, String destinationFolderPath)
{
await UpdateStatus(download.DownloadId, DownloadStatus.Downloading, TorrentStatus.Downloading);
if (!ActiveDownloads.TryAdd(download.DownloadId, download))
{
return;
}
var fileUrl = download.Link;
var uri = new Uri(fileUrl);
var filePath = Path.Combine(destinationFolderPath, uri.Segments.Last());
var webRequest = WebRequest.Create(fileUrl);
webRequest.Method = "HEAD";
Int64 responseLength;
using (var webResponse = await webRequest.GetResponseAsync())
{
responseLength = Int64.Parse(webResponse.Headers.Get("Content-Length"));
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
var request = WebRequest.Create(fileUrl);
using (var response = await request.GetResponseAsync())
{
await using var stream = response.GetResponseStream();
await using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write);
var buffer = new Byte[4096];
while (fileStream.Length < response.ContentLength)
{
var read = stream.Read(buffer, 0, buffer.Length);
if (read > 0)
{
fileStream.Write(buffer, 0, read);
download.Progress = (Int32) (fileStream.Length * 100 / responseLength);
ActiveDownloads.TryAdd(download.DownloadId, download);
}
else
{
break;
}
}
}
try
{
await using Stream stream = File.OpenRead(filePath);
var reader = ReaderFactory.Open(stream);
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
Console.WriteLine(reader.Entry.Key);
reader.WriteEntryToDirectory(destinationFolderPath,
new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true
});
}
}
File.Delete(filePath);
}
catch
{
// ignored
}
await UpdateStatus(download.DownloadId, DownloadStatus.Finished, TorrentStatus.Finished);
ActiveDownloads.TryRemove(download.DownloadId, out _);
}
private static async Task UpdateStatus(Guid downloadId, DownloadStatus downloadStatus, TorrentStatus torrentStatus)
{
await using var context = new DataContext();
var download = await context.Downloads.FirstOrDefaultAsync(m => m.DownloadId == downloadId);
download.Status = downloadStatus;
await context.SaveChangesAsync();
var torrent = await context.Torrents.FirstOrDefaultAsync(m => m.TorrentId == download.TorrentId);
if (torrentStatus == TorrentStatus.Finished)
{
var allDownloads = await context.Downloads.Where(m => m.TorrentId == download.TorrentId)
.ToListAsync();
if (allDownloads.All(m => m.Status == DownloadStatus.Finished))
{
torrent.Status = TorrentStatus.Finished;
}
else
{
torrent.Status = TorrentStatus.Downloading;
}
}
else
{
torrent.Status = torrentStatus;
}
await context.SaveChangesAsync();
}
}
}

View file

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using RdtClient.Data.Data;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
namespace RdtClient.Service.Services
{
public interface IDownloads
{
Task<IList<Download>> Get();
Task<Download> Add(Guid torrentId, String link);
Task UpdateStatus(Guid downloadId, DownloadStatus status);
Task DeleteForTorrent(Guid torrentId);
}
public class Downloads : IDownloads
{
private readonly IDownloadData _downloadData;
private readonly ISettings _settings;
public Downloads(IDownloadData downloadData, ISettings settings)
{
_downloadData = downloadData;
_settings = settings;
}
public async Task<IList<Download>> Get()
{
return await _downloadData.Get();
}
public async Task<Download> Add(Guid torrentId, String link)
{
return await _downloadData.Add(torrentId, link);
}
public async Task UpdateStatus(Guid downloadId, DownloadStatus status)
{
await _downloadData.UpdateStatus(downloadId, status);
}
public async Task DeleteForTorrent(Guid torrentId)
{
await _downloadData.DeleteForTorrent(torrentId);
}
}
}

View file

@ -0,0 +1,62 @@
using System.Linq;
using System.Threading.Tasks;
using Hangfire;
using RdtClient.Data.Enums;
namespace RdtClient.Service.Services
{
public interface IScheduler
{
void Start();
Task Process();
}
public class Scheduler : IScheduler
{
private readonly IDownloads _downloads;
private readonly ISettings _settings;
private readonly ITorrents _torrents;
public Scheduler(ITorrents torrents, IDownloads downloads, ISettings settings)
{
_torrents = torrents;
_downloads = downloads;
_settings = settings;
}
public void Start()
{
RecurringJob.AddOrUpdate(() => Process(), "* * * * *");
BackgroundJob.Enqueue(() => Process());
}
[DisableConcurrentExecution(5)]
public async Task Process()
{
await _torrents.Update();
var downloads = await _downloads.Get();
downloads = downloads.Where(m => m.Status != DownloadStatus.Finished)
.OrderByDescending(m => m.Status)
.ThenByDescending(m => m.Added)
.ToList();
var maxDownloads = await _settings.GetNumber("DownloadLimit");
var destinationFolderPath = await _settings.GetString("DownloadFolder");
foreach (var download in downloads)
{
if (DownloadManager.ActiveDownloads.Count >= maxDownloads)
{
return;
}
download.Torrent = null;
BackgroundJob.Enqueue(() => DownloadManager.Download(download, destinationFolderPath));
await Task.Delay(1000);
}
}
}
}

View file

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using RdtClient.Data.Data;
using RdtClient.Data.Models.Data;
namespace RdtClient.Service.Services
{
public interface ISettings
{
Task<IList<Setting>> GetAll();
Task Update(IList<Setting> settings);
Task<String> GetString(String key);
Task<Int32> GetNumber(String key);
}
public class Settings : ISettings
{
private readonly ISettingData _settingData;
public Settings(ISettingData settingData)
{
_settingData = settingData;
}
public async Task<IList<Setting>> GetAll()
{
return await _settingData.GetAll();
}
public async Task Update(IList<Setting> settings)
{
await _settingData.Update(settings);
}
public async Task<String> GetString(String key)
{
var setting = await _settingData.Get(key);
if (setting == null)
{
throw new Exception($"Setting with key {key} not found");
}
return setting.Value;
}
public async Task<Int32> GetNumber(String key)
{
var setting = await _settingData.Get(key);
if (setting == null)
{
throw new Exception($"Setting with key {key} not found");
}
return Int32.Parse(setting.Value);
}
}
}

View file

@ -0,0 +1,277 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using RDNET;
using RdtClient.Data.Data;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data;
using RdtClient.Service.Models;
namespace RdtClient.Service.Services
{
public interface ITorrents
{
Task<IList<Torrent>> Get();
Task<Torrent> Get(Guid id);
Task<IList<Torrent>> Update();
Task UploadMagnet(String magnetLink);
Task UploadFile(Byte[] bytes);
Task Delete(Guid id);
Task Download(Guid id);
void Reset();
Task<Profile> GetProfile();
}
public class Torrents : ITorrents
{
private readonly ITorrentData _torrentData;
private readonly ISettings _settings;
private readonly IDownloads _downloads;
private static RdNetClient _rdtClient;
private static DateTime _rdtLastUpdate = DateTime.UtcNow;
private static readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1,1);
private RdNetClient RdNetClient
{
get
{
if (_rdtClient == null)
{
var apiKey = _settings.GetString("RealDebridApiKey").Result;
if (String.IsNullOrWhiteSpace(apiKey))
{
throw new Exception("RealDebrid API Key not set in the settings");
}
_rdtClient = new RdNetClient("X245A4XAIBGVM", null, null, null, null, apiKey);
}
return _rdtClient;
}
}
public Torrents(ITorrentData torrentData, ISettings settings, IDownloads downloads)
{
_torrentData = torrentData;
_settings = settings;
_downloads = downloads;
}
public async Task<IList<Torrent>> Get()
{
var torrents = await _torrentData.Get();
if (DateTime.UtcNow > _rdtLastUpdate)
{
_rdtLastUpdate = DateTime.UtcNow.AddSeconds(10);
torrents = await Update();
}
foreach (var torrent in torrents)
{
var downloads = DownloadManager.ActiveDownloads.Where(m => m.Value.TorrentId == torrent.TorrentId).ToList();
if (torrent.Files.Count > 0)
{
torrent.DownloadProgress = downloads.Sum(m => m.Value.Progress) / torrent.Files.Count;
}
}
return torrents;
}
public async Task<Torrent> Get(Guid id)
{
var torrent = await _torrentData.Get(id);
if (torrent != null)
{
var rdTorrent = await RdNetClient.TorrentInfoAsync(torrent.RdId);
await Update(torrent, rdTorrent);
}
return torrent;
}
public async Task<IList<Torrent>> Update()
{
var torrents = await _torrentData.Get();
var w = await SemaphoreSlim.WaitAsync(10);
if (!w)
{
return torrents;
}
try
{
var rdTorrents = await RdNetClient.TorrentsAsync(0, 100);
foreach (var rdTorrent in rdTorrents)
{
var torrent = torrents.FirstOrDefault(m => m.RdId == rdTorrent.Id);
if (torrent == null)
{
var newTorrent = await _torrentData.Add(rdTorrent.Id, rdTorrent.Hash);
await Get(newTorrent.TorrentId);
}
else
{
await Update(torrent, rdTorrent);
}
}
foreach (var torrent in torrents)
{
var rdTorrent = rdTorrents.FirstOrDefault(m => m.Id == torrent.RdId);
if (rdTorrent == null)
{
await _torrentData.Delete(torrent.TorrentId);
}
}
return torrents;
}
finally
{
SemaphoreSlim.Release();
}
}
public async Task UploadMagnet(String magnetLink)
{
var magnet = MonoTorrent.MagnetLink.Parse(magnetLink);
var rdTorrent = await RdNetClient.TorrentAddMagnet(magnetLink);
await Add(rdTorrent.Id, magnet.InfoHash.ToHex());
}
public async Task UploadFile(Byte[] bytes)
{
var torrent = MonoTorrent.Torrent.Load(bytes);
var rdTorrent = await RdNetClient.TorrentAddFile(bytes);
await Add(rdTorrent.Id, torrent.InfoHash.ToHex());
}
public async Task Delete(Guid id)
{
var torrent = await Get(id);
if (torrent != null)
{
await _torrentData.Delete(id);
await RdNetClient.TorrentDelete(torrent.RdId);
}
}
public async Task Download(Guid id)
{
var torrent = await _torrentData.Get(id);
await _downloads.DeleteForTorrent(id);
var rdTorrent = await RdNetClient.TorrentInfoAsync(torrent.RdId);
foreach (var file in rdTorrent.Files)
{
var unrestrictedLink = await RdNetClient.UnrestrictLinkAsync(file.Path);
await _downloads.Add(torrent.TorrentId, unrestrictedLink.Download);
}
}
public void Reset()
{
_rdtClient = null;
_rdtLastUpdate = DateTime.UtcNow;
}
public async Task<Profile> GetProfile()
{
var user = await _rdtClient.UserAsync();
var profile = new Profile
{
UserName = user.Username,
Expiration = user.Expiration
};
return profile;
}
private async Task Add(String rdTorrentId, String infoHash)
{
var newTorrent = await _torrentData.Add(rdTorrentId, infoHash);
var rdTorrent = await RdNetClient.TorrentInfoAsync(rdTorrentId);
if (rdTorrent.Files != null && rdTorrent.Files.Count > 0)
{
if (!rdTorrent.Files.Any(m => m.Selected))
{
var fileIds = rdTorrent.Files.Select(m => m.Id.ToString()).ToArray();
await RdNetClient.TorrentSelectFiles(rdTorrentId, fileIds);
}
}
await Update(newTorrent, rdTorrent);
}
private async Task Update(Torrent torrent, RDNET.Models.Torrent rdTorrent)
{
if (!String.IsNullOrWhiteSpace(rdTorrent.Filename))
{
torrent.RdName = rdTorrent.Filename;
}
else if (!String.IsNullOrWhiteSpace(rdTorrent.OriginalFilename))
{
torrent.RdName = rdTorrent.OriginalFilename;
}
if (rdTorrent.Bytes > 0)
{
torrent.RdSize = rdTorrent.Bytes;
}
else if (rdTorrent.OriginalBytes > 0)
{
torrent.RdSize = rdTorrent.OriginalBytes;
}
if (rdTorrent.Files != null)
{
torrent.RdFiles = JsonConvert.SerializeObject(rdTorrent.Files);
}
torrent.RdHost = rdTorrent.Host;
torrent.RdSplit = rdTorrent.Split;
torrent.RdProgress = rdTorrent.Progress;
torrent.RdStatus = rdTorrent.Status;
torrent.RdAdded = rdTorrent.Added;
torrent.RdEnded = rdTorrent.Ended;
torrent.RdSpeed = rdTorrent.Speed;
torrent.RdSeeders = rdTorrent.Seeders;
await _torrentData.UpdateRdData(torrent);
if (torrent.Status == TorrentStatus.RealDebrid && torrent.RdProgress == 100)
{
await _torrentData.UpdateStatus(torrent.TorrentId, TorrentStatus.WaitingForDownload);
}
}
}
}

View file

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using RdtClient.Data.Models.Data;
using RdtClient.Service.Models;
using RdtClient.Service.Services;
namespace RdtClient.Web.Controllers
{
[Route("Api/Settings")]
public class SettingsController : Controller
{
private readonly ISettings _settings;
private readonly ITorrents _torrents;
public SettingsController(ISettings settings, ITorrents torrents)
{
_settings = settings;
_torrents = torrents;
}
[HttpGet]
[Route("")]
public async Task<ActionResult<IList<Setting>>> Get()
{
try
{
var result = await _settings.GetAll();
return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
[HttpPut]
[Route("")]
public async Task<ActionResult> Update([FromBody] SettingsControllerUpdateRequest request)
{
try
{
await _settings.Update(request.Settings);
_torrents.Reset();
return Ok();
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
[HttpGet]
[Route("Profile")]
public async Task<ActionResult<Profile>> Profile()
{
try
{
var profile = await _torrents.GetProfile();
return Ok(profile);
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
}
public class SettingsControllerUpdateRequest
{
public IList<Setting> Settings { get; set; }
}
}

View file

@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using RdtClient.Data.Models.Data;
using RdtClient.Service.Services;
namespace RdtClient.Web.Controllers
{
[Route("Api/Torrents")]
public class TorrentsController : Controller
{
private readonly ITorrents _torrents;
private readonly IScheduler _scheduler;
public TorrentsController(ITorrents torrents, IScheduler scheduler)
{
_torrents = torrents;
_scheduler = scheduler;
}
[HttpGet]
[Route("")]
public async Task<ActionResult<IList<Torrent>>> Get()
{
try
{
var result = await _torrents.Get();
return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
[HttpGet]
[Route("{id}")]
public async Task<ActionResult<Torrent>> Get(Guid id)
{
try
{
var result = await _torrents.Get(id);
if (result == null)
{
throw new Exception("Torrent not found");
}
return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
[HttpPost]
[Route("UploadFile")]
public async Task<ActionResult> UploadFile([FromForm] IFormFile file)
{
try
{
if (file == null || file.Length <= 0)
{
throw new Exception("Invalid torrent file");
}
var fileStream = file.OpenReadStream();
await using var memoryStream = new MemoryStream();
fileStream.CopyTo(memoryStream);
var bytes = memoryStream.ToArray();
await _torrents.UploadFile(bytes);
return Ok();
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost]
[Route("UploadMagnet")]
public async Task<ActionResult> UploadMagnet([FromBody] TorrentControllerUploadMagnetRequest request)
{
try
{
await _torrents.UploadMagnet(request.MagnetLink);
return Ok();
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpDelete]
[Route("{id}")]
public async Task<ActionResult> Delete(Guid id)
{
try
{
await _torrents.Delete(id);
return Ok();
}
catch(Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpGet]
[Route("Download/{id}")]
public async Task<ActionResult> Download(Guid id)
{
try
{
await _torrents.Download(id);
await _scheduler.Process();
return Ok();
}
catch(Exception ex)
{
return BadRequest(ex.Message);
}
}
}
public class TorrentControllerUploadMagnetRequest
{
public String MagnetLink { get; set; }
}
}

View file

@ -1,6 +1,7 @@
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace RdtClient.Web
{
@ -13,8 +14,15 @@ namespace RdtClient.Web
.Run();
}
private static IHostBuilder CreateHostBuilder(String[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
private static IHostBuilder CreateHostBuilder(String[] args)
{
return Host
.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddFile("app.log");
})
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
}
}
}

View file

@ -1,18 +1,16 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52923",
"sslPort": 44356
"applicationUrl": "http://localhost:4201",
"sslPort": 0
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@ -21,10 +19,10 @@
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}
}

View file

@ -5,11 +5,13 @@
</PropertyGroup>
<ItemGroup>
<Folder Include="Controllers\" />
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Hangfire.AspNetCore" Version="1.7.10" />
<PackageReference Include="Hangfire.Core" Version="1.7.10" />
<PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.1.3" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
@ -19,6 +21,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="3.1.3" />
<PackageReference Include="NReco.Logging.File" Version="1.0.5" />
</ItemGroup>
<ItemGroup>

View file

@ -1,3 +1,5 @@
using Hangfire;
using Hangfire.MemoryStorage;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
@ -6,8 +8,9 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using RdtClient.Data.DataContext;
using RdtClient.Data.Data;
using RdtClient.Data.Models.Internal;
using RdtClient.Service.Services;
namespace RdtClient.Web
{
@ -27,7 +30,7 @@ namespace RdtClient.Web
services.AddSingleton(appSettings);
services.AddDbContext<DataContext>(options => options.UseSqlite(appSettings.ConnectionStrings.Client));
services.AddDbContext<DataContext>(options => options.UseSqlite(DataContext.ConnectionString));
services.AddControllers();
@ -51,6 +54,8 @@ namespace RdtClient.Web
services.AddHttpsRedirection(options => { options.HttpsPort = 443; });
services.AddHttpClient();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => { options.SlidingExpiration = true; });
@ -68,15 +73,22 @@ namespace RdtClient.Web
.AddEntityFrameworkStores<DataContext>()
.AddDefaultTokenProviders();
services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseMemoryStorage());
services.AddHangfireServer();
Data.DiConfig.Config(services);
Service.DiConfig.Config(services);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext dataContext, IScheduler scheduler)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseCors("Dev");
}
else
@ -92,6 +104,8 @@ namespace RdtClient.Web
app.UseAuthorization();
app.UseHangfireServer();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
@ -101,6 +115,10 @@ namespace RdtClient.Web
{
spa.Options.SourcePath = "wwwroot";
});
dataContext.Migrate();
scheduler.Start();
}
}
}

View file

@ -0,0 +1,512 @@
2020-04-03T15:59:20.1355273-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T15:59:20.1385649-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T15:59:20.2294123-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T15:59:20.2294368-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T15:59:20.2510079-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:17836:3146ca38 successfully announced in 101.8542 ms
2020-04-03T15:59:20.2510111-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:17836:f605d0e0 successfully announced in 20.7292 ms
2020-04-03T15:59:20.2541883-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:17836:3146ca38 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T15:59:20.2541883-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:17836:f605d0e0 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T15:59:20.2588662-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:17836:f605d0e0 all the dispatchers started
2020-04-03T15:59:20.2589265-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:17836:3146ca38 all the dispatchers started
2020-04-03T15:59:20.9901692-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-03T15:59:20.9902829-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-03T15:59:20.9903021-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-03T15:59:22.6292638-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T15:59:22.6322230-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T15:59:22.7242705-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T15:59:22.7243034-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T15:59:22.7452766-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:c48269cc successfully announced in 19.9586 ms
2020-04-03T15:59:22.7452765-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:15034db2 successfully announced in 101.7602 ms
2020-04-03T15:59:22.7481327-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:15034db2 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T15:59:22.7481351-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:c48269cc is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T15:59:22.7533167-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:15034db2 all the dispatchers started
2020-04-03T15:59:22.7535232-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:c48269cc all the dispatchers started
2020-04-03T15:59:23.4204963-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-03T15:59:23.4206249-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-03T15:59:23.4206510-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-03T15:59:30.7772267-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:c48269cc caught stopping signal...
2020-04-03T15:59:30.7779767-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application is shutting down...
2020-04-03T15:59:30.7783343-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:c48269cc caught stopped signal...
2020-04-03T15:59:30.7794920-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:15034db2 caught stopping signal...
2020-04-03T15:59:30.7796436-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:15034db2 caught stopped signal...
2020-04-03T15:59:30.7812297-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:15034db2 All dispatchers stopped
2020-04-03T15:59:30.7812297-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:c48269cc All dispatchers stopped
2020-04-03T15:59:30.7828238-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:15034db2 successfully reported itself as stopped in 0.2783 ms
2020-04-03T15:59:30.7828222-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:c48269cc successfully reported itself as stopped in 0.2778 ms
2020-04-03T15:59:30.7828386-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:15034db2 has been stopped in total 3.303 ms
2020-04-03T15:59:30.7828431-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25392:c48269cc has been stopped in total 5.4344 ms
2020-04-03T15:59:49.2420348-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T15:59:49.2449966-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T15:59:49.7330627-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T15:59:49.7342224-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T15:59:49.7767552-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:7656:238a3170 successfully announced in 518.619 ms
2020-04-03T15:59:49.7778417-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:7656:b384ecba successfully announced in 37.4892 ms
2020-04-03T15:59:49.7897107-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:7656:238a3170 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T15:59:49.7907947-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:7656:b384ecba is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T15:59:49.9335939-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:7656:238a3170 all the dispatchers started
2020-04-03T15:59:49.9493934-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:7656:b384ecba all the dispatchers started
2020-04-03T15:59:50.8034032-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-03T15:59:50.8108739-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-03T15:59:50.8127580-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-03T16:06:29.6254854-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T16:06:29.6288727-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T16:06:29.7314839-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T16:06:29.7315143-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T16:06:29.7529384-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18896:dd12c44a successfully announced in 111.5091 ms
2020-04-03T16:06:29.7529396-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18896:15c956d5 successfully announced in 20.4625 ms
2020-04-03T16:06:29.7557415-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18896:dd12c44a is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T16:06:29.7557411-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18896:15c956d5 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T16:06:29.7606532-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18896:15c956d5 all the dispatchers started
2020-04-03T16:06:29.7608761-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18896:dd12c44a all the dispatchers started
2020-04-03T16:06:30.9858222-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-03T16:06:30.9940710-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-03T16:06:30.9966766-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-03T17:20:18.4268508-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T17:20:18.4340796-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T17:20:18.6487165-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T17:20:18.6500981-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T17:20:18.6947841-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:21168:a6490904 successfully announced in 34.9489 ms
2020-04-03T17:20:18.6960854-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:21168:b2e9a60c successfully announced in 230.7784 ms
2020-04-03T17:20:18.7105510-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:21168:a6490904 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T17:20:18.7121052-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:21168:b2e9a60c is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T17:20:18.8720117-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:21168:a6490904 all the dispatchers started
2020-04-03T17:20:18.8774595-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:21168:b2e9a60c all the dispatchers started
2020-04-03T17:20:19.7386911-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-03T17:20:19.7416238-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-03T17:20:19.7486505-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-03T17:59:08.0700362-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T17:59:08.0750113-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T17:59:08.2398601-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-03T17:59:08.2411315-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-03T17:59:08.2913718-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:10716:5ebe162c successfully announced in 42.0268 ms
2020-04-03T17:59:08.2925085-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:10716:fb956c19 successfully announced in 197.5027 ms
2020-04-03T17:59:08.3038936-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:10716:5ebe162c is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T17:59:08.3049895-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:10716:fb956c19 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-03T17:59:08.4396784-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:10716:5ebe162c all the dispatchers started
2020-04-03T17:59:08.4538634-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:10716:fb956c19 all the dispatchers started
2020-04-03T17:59:09.4423137-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-03T17:59:09.4523143-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-03T17:59:09.4550262-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T13:36:51.3899679-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T13:36:51.3954070-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T13:36:52.2046648-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T13:36:52.2058469-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T13:36:52.2165588-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18576:7232176f successfully announced in 5.629 ms
2020-04-04T13:36:52.2175955-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18576:0c930dc4 successfully announced in 783.68 ms
2020-04-04T13:36:52.2258088-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18576:0c930dc4 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T13:36:52.2270592-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18576:7232176f is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T13:36:52.3608248-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18576:0c930dc4 all the dispatchers started
2020-04-04T13:36:52.3651180-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18576:7232176f all the dispatchers started
2020-04-04T13:36:53.3815332-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T13:36:53.3835819-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T13:36:53.3855069-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T13:39:17.4290475-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T13:39:17.4351614-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T13:39:17.6188800-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T13:39:17.6200228-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T13:39:17.6633116-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:12312:46ba0401 successfully announced in 205.437 ms
2020-04-04T13:39:17.6653058-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:12312:626ef5ce successfully announced in 36.9854 ms
2020-04-04T13:39:17.6810736-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:12312:46ba0401 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T13:39:17.6821454-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:12312:626ef5ce is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T13:39:17.8313892-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:12312:626ef5ce all the dispatchers started
2020-04-04T13:39:17.8518228-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:12312:46ba0401 all the dispatchers started
2020-04-04T13:39:18.6777049-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T13:39:18.6853112-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T13:39:18.6872717-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T13:45:52.2178972-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T13:45:52.2209059-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T13:45:52.7257245-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T13:45:52.7268420-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T13:45:52.7605590-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25428:371ab538 successfully announced in 29.31 ms
2020-04-04T13:45:52.7616163-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25428:beb90aed successfully announced in 527.3207 ms
2020-04-04T13:45:52.7947890-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25428:371ab538 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T13:45:52.7958992-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25428:beb90aed is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T13:45:52.9335865-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25428:beb90aed all the dispatchers started
2020-04-04T13:45:52.9433737-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:25428:371ab538 all the dispatchers started
2020-04-04T13:45:53.7610065-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T13:45:53.7667118-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T13:45:53.7686187-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:06:51.9875312-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:06:51.9910970-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:06:52.4849160-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:06:52.4860716-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:06:52.5226185-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:4496:e9cb1104 successfully announced in 517.9776 ms
2020-04-04T14:06:52.5276877-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:4496:2aa9fc9e successfully announced in 32.1255 ms
2020-04-04T14:06:52.5356524-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:4496:2aa9fc9e is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:06:52.5368007-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:4496:e9cb1104 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:06:52.6798034-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:4496:e9cb1104 all the dispatchers started
2020-04-04T14:06:52.6843382-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:4496:2aa9fc9e all the dispatchers started
2020-04-04T14:06:53.5337779-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:06:53.5419397-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:06:53.5438903-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:09:28.6901247-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:09:28.6934944-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:09:28.8003885-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:09:28.8004416-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:09:28.8235716-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11712:2f63d054 successfully announced in 22.2108 ms
2020-04-04T14:09:28.8235763-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11712:6de68e38 successfully announced in 117.3382 ms
2020-04-04T14:09:28.8266785-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11712:6de68e38 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:09:28.8266804-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11712:2f63d054 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:09:28.8331305-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11712:6de68e38 all the dispatchers started
2020-04-04T14:09:28.8332117-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11712:2f63d054 all the dispatchers started
2020-04-04T14:09:30.0597550-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:09:30.0661109-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:09:30.0679982-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:10:30.2700465-06:00 FAIL [Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer] [ApplicationError] Connection ID "18158513750708060161", Request ID "80000002-000c-fc00-b63f-84710c7967bb": An unhandled exception was thrown by the application.System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32.
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializerCycleDetected(Int32 maxDepth)
at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, Object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|27_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()
2020-04-04T14:11:12.4711056-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:11:12.4740177-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:11:12.5685353-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:11:12.5685678-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:11:12.5896902-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11556:f733969e successfully announced in 104.0185 ms
2020-04-04T14:11:12.5896902-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11556:85c7f28f successfully announced in 20.4301 ms
2020-04-04T14:11:12.5927719-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11556:85c7f28f is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:11:12.5927773-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11556:f733969e is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:11:12.5982186-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11556:85c7f28f all the dispatchers started
2020-04-04T14:11:12.5982679-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11556:f733969e all the dispatchers started
2020-04-04T14:11:13.8266479-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:11:13.8300908-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:11:13.8397525-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:23:21.7687075-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:23:21.7715620-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:23:21.8650133-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:23:21.8650397-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:23:21.8862045-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:13516:63077182 successfully announced in 103.9192 ms
2020-04-04T14:23:21.8862045-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:13516:8f1cdbd3 successfully announced in 19.9902 ms
2020-04-04T14:23:21.8889891-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:13516:63077182 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:23:21.8889884-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:13516:8f1cdbd3 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:23:21.8939088-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:13516:63077182 all the dispatchers started
2020-04-04T14:23:21.8939936-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:13516:8f1cdbd3 all the dispatchers started
2020-04-04T14:23:23.0689646-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:23:23.0709673-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:23:23.0779228-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:24:37.9847342-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:24:37.9882985-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:24:38.0825819-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:24:38.0826064-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:24:38.1036306-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22580:c1366df7 successfully announced in 103.9479 ms
2020-04-04T14:24:38.1036305-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22580:e3e831b7 successfully announced in 20.0026 ms
2020-04-04T14:24:38.1065641-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22580:c1366df7 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:24:38.1065662-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22580:e3e831b7 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:24:38.1114065-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22580:e3e831b7 all the dispatchers started
2020-04-04T14:24:38.1114793-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22580:c1366df7 all the dispatchers started
2020-04-04T14:24:39.2282210-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:24:39.2423550-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:24:39.2447909-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:28:26.3492596-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:28:26.3544781-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:28:26.5174135-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:28:26.5187379-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:28:26.5578223-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:20488:c6bc92b2 successfully announced in 182.3826 ms
2020-04-04T14:28:26.5588998-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:20488:20d17df5 successfully announced in 34.3576 ms
2020-04-04T14:28:26.5704666-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:20488:c6bc92b2 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:28:26.5716322-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:20488:20d17df5 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:28:26.7149113-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:20488:20d17df5 all the dispatchers started
2020-04-04T14:28:26.7226988-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:20488:c6bc92b2 all the dispatchers started
2020-04-04T14:28:27.5476942-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:28:27.5548312-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:28:27.5565374-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:29:22.4970867-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:29:22.5000868-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:29:22.5972226-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:29:22.5972498-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:29:22.6185406-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:8704:7f562bd0 successfully announced in 20.3044 ms
2020-04-04T14:29:22.6185503-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:8704:25c03ed6 successfully announced in 107.2263 ms
2020-04-04T14:29:22.6212883-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:8704:25c03ed6 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:29:22.6212868-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:8704:7f562bd0 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:29:22.6272480-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:8704:25c03ed6 all the dispatchers started
2020-04-04T14:29:22.6275399-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:8704:7f562bd0 all the dispatchers started
2020-04-04T14:29:23.8020576-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:29:23.8092332-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:29:23.8114626-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:33:29.3029557-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:33:29.3060421-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:33:29.3995563-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:33:29.3996017-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:33:29.4210320-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11468:78e298c5 successfully announced in 103.7016 ms
2020-04-04T14:33:29.4210325-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11468:79ee0690 successfully announced in 20.3431 ms
2020-04-04T14:33:29.4238373-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11468:78e298c5 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:33:29.4238390-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11468:79ee0690 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:33:29.4293346-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11468:78e298c5 all the dispatchers started
2020-04-04T14:33:29.4294031-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:11468:79ee0690 all the dispatchers started
2020-04-04T14:33:30.5171651-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:33:30.5207118-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:33:30.5262510-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:35:26.4931298-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:35:26.4960740-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:35:26.5902385-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:35:26.5902725-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:35:26.6112554-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9364:548bcc22 successfully announced in 20.0425 ms
2020-04-04T14:35:26.6112554-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9364:a39fa135 successfully announced in 104.5842 ms
2020-04-04T14:35:26.6138703-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9364:548bcc22 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:35:26.6138680-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9364:a39fa135 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:35:26.6186498-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9364:a39fa135 all the dispatchers started
2020-04-04T14:35:26.6187979-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9364:548bcc22 all the dispatchers started
2020-04-04T14:35:27.7550471-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:35:27.7577200-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:35:27.7656669-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:36:13.4963403-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:36:13.4995347-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:36:13.5937296-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:36:13.5937661-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:36:13.6136017-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:24484:d3f096b7 successfully announced in 102.8649 ms
2020-04-04T14:36:13.6136017-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:24484:0486235c successfully announced in 18.8774 ms
2020-04-04T14:36:13.6161824-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:24484:0486235c is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:36:13.6161810-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:24484:d3f096b7 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:36:13.6211768-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:24484:0486235c all the dispatchers started
2020-04-04T14:36:13.6212520-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:24484:d3f096b7 all the dispatchers started
2020-04-04T14:36:14.7116432-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:36:14.7193962-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:36:14.7217224-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:44:06.0389258-06:00 FAIL [Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer] [ApplicationError] Connection ID "18302628887244309062", Request ID "80000247-0000-fe00-b63f-84710c7967bb": An unhandled exception was thrown by the application.System.InvalidOperationException: The SPA default page middleware could not return the default page '/index.html' because it was not found, and no other middleware handled the request.
at Microsoft.AspNetCore.SpaServices.SpaDefaultPageMiddleware.<>c__DisplayClass0_0.<Attach>b__1(HttpContext context, Func`1 next)
at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_1.<Use>b__1(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.TryServeStaticFile(HttpContext context, String contentType, PathString subPath)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_2.<Use>b__2()
at Microsoft.AspNetCore.SpaServices.SpaDefaultPageMiddleware.<>c__DisplayClass0_0.<Attach>b__0(HttpContext context, Func`1 next)
at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_1.<Use>b__1(HttpContext context)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()
2020-04-04T14:44:07.1916383-06:00 FAIL [Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer] [ApplicationError] Connection ID "18302628930193982207", Request ID "80000300-000a-fe00-b63f-84710c7967bb": An unhandled exception was thrown by the application.System.InvalidOperationException: The SPA default page middleware could not return the default page '/index.html' because it was not found, and no other middleware handled the request.
at Microsoft.AspNetCore.SpaServices.SpaDefaultPageMiddleware.<>c__DisplayClass0_0.<Attach>b__1(HttpContext context, Func`1 next)
at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_1.<Use>b__1(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.TryServeStaticFile(HttpContext context, String contentType, PathString subPath)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_2.<Use>b__2()
at Microsoft.AspNetCore.SpaServices.SpaDefaultPageMiddleware.<>c__DisplayClass0_0.<Attach>b__0(HttpContext context, Func`1 next)
at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_1.<Use>b__1(HttpContext context)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()
2020-04-04T14:47:54.0323392-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:47:54.0367216-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:47:54.1985129-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:47:54.1996782-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:47:54.2766426-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9924:7a1f1a6b successfully announced in 70.8826 ms
2020-04-04T14:47:54.2806642-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9924:d0351e6f successfully announced in 214.1212 ms
2020-04-04T14:47:54.2889140-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9924:7a1f1a6b is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:47:54.2900438-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9924:d0351e6f is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:47:54.4139151-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9924:d0351e6f all the dispatchers started
2020-04-04T14:47:54.4368669-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:9924:7a1f1a6b all the dispatchers started
2020-04-04T14:47:55.2715624-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:47:55.2771286-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:47:55.2789075-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:48:49.5565338-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:48:49.5594208-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:48:49.6547594-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:48:49.6547886-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:48:49.6754648-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22936:b12db8cb successfully announced in 105.0262 ms
2020-04-04T14:48:49.6754648-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22936:fd149353 successfully announced in 19.6826 ms
2020-04-04T14:48:49.6783402-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22936:b12db8cb is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:48:49.6783431-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22936:fd149353 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:48:50.1962026-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22936:fd149353 all the dispatchers started
2020-04-04T14:48:50.1981452-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:22936:b12db8cb all the dispatchers started
2020-04-04T14:48:51.0147387-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:48:51.0220660-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:48:51.0239132-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web
2020-04-04T14:50:09.5762316-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:50:09.5792141-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:50:09.6739724-06:00 INFO [Hangfire.BackgroundJobServer] [0] Starting Hangfire Server using job storage: 'Hangfire.MemoryStorage.MemoryStorage'
2020-04-04T14:50:09.6740028-06:00 INFO [Hangfire.BackgroundJobServer] [0] Using the following options for Hangfire Server:
Worker count: 20
Listening queues: 'default'
Shutdown timeout: 00:00:15
Schedule polling interval: 00:00:15
2020-04-04T14:50:09.6944222-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18196:9c827089 successfully announced in 19.5569 ms
2020-04-04T14:50:09.6944222-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18196:a1cafa69 successfully announced in 104.5052 ms
2020-04-04T14:50:09.6970626-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18196:9c827089 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:50:09.6970626-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18196:a1cafa69 is starting the registered dispatchers: ServerWatchdog, ServerJobCancellationWatcher, ExpirationManager, CountersAggregator, Worker, DelayedJobScheduler, RecurringJobScheduler...
2020-04-04T14:50:09.7022113-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18196:9c827089 all the dispatchers started
2020-04-04T14:50:09.7024526-06:00 INFO [Hangfire.Server.BackgroundServerProcess] [0] Server roger-pc:18196:a1cafa69 all the dispatchers started
2020-04-04T14:50:10.8721989-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.
2020-04-04T14:50:10.8807198-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development
2020-04-04T14:50:10.8830457-06:00 INFO [Microsoft.Hosting.Lifetime] [0] Content root path: C:\Projects\rdt-client\server\RdtClient.Web

View file

@ -3,11 +3,15 @@
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
"Microsoft.Hosting.Lifetime": "Information",
"Hangfire": "Information"
},
"File": {
"Path": "app.log",
"Append": "True",
"FileSizeLimitBytes": 2048,
"MaxRollingFiles": 5
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"Client": "Host=localhost;Database=fieldcap;Username=fieldcap;Password=fieldcap;Maximum Pool Size=30"
}
"AllowedHosts": "*"
}

View file

@ -0,0 +1,63 @@
{
"runtimeTarget": {
"name": ".NETStandard,Version=v2.0/",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETStandard,Version=v2.0": {},
".NETStandard,Version=v2.0/": {
"RDNET/1.0.0": {
"dependencies": {
"NETStandard.Library": "2.0.3",
"Newtonsoft.Json": "12.0.3"
},
"runtime": {
"RDNET.dll": {}
}
},
"Microsoft.NETCore.Platforms/1.1.0": {},
"NETStandard.Library/2.0.3": {
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0"
}
},
"Newtonsoft.Json/12.0.3": {
"runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": {
"assemblyVersion": "12.0.0.0",
"fileVersion": "12.0.3.23909"
}
}
}
}
},
"libraries": {
"RDNET/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Microsoft.NETCore.Platforms/1.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==",
"path": "microsoft.netcore.platforms/1.1.0",
"hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512"
},
"NETStandard.Library/2.0.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
"path": "netstandard.library/2.0.3",
"hashPath": "netstandard.library.2.0.3.nupkg.sha512"
},
"Newtonsoft.Json/12.0.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-6mgjfnRB4jKMlzHSl+VD+oUc1IebOZabkbyWj2RiTgWwYPPuaK1H97G1sHqGwPlS5npiF5Q0OrxN1wni2n5QWg==",
"path": "newtonsoft.json/12.0.3",
"hashPath": "newtonsoft.json.12.0.3.nupkg.sha512"
}
}
}

BIN
server/libs/RDNET.dll Normal file

Binary file not shown.

BIN
server/libs/RDNET.pdb Normal file

Binary file not shown.