Upgrade packages

Moved C# code to file scoped namespaces
Merged Startup.cs and Program.cs
This commit is contained in:
Roger Far 2022-04-30 11:22:15 -06:00
parent 2cff8ec0a6
commit cd6002b5d6
69 changed files with 7484 additions and 7591 deletions

1644
client/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -10,33 +10,33 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "~13.2.6", "@angular/animations": "~13.3.5",
"@angular/cdk": "^13.2.6", "@angular/cdk": "^13.3.5",
"@angular/common": "~13.2.6", "@angular/common": "~13.3.5",
"@angular/compiler": "~13.2.6", "@angular/compiler": "~13.3.5",
"@angular/core": "~13.2.6", "@angular/core": "~13.3.5",
"@angular/flex-layout": "^13.0.0-beta.38", "@angular/flex-layout": "^13.0.0-beta.38",
"@angular/forms": "~13.2.6", "@angular/forms": "~13.3.5",
"@angular/platform-browser": "~13.2.6", "@angular/platform-browser": "~13.3.5",
"@angular/platform-browser-dynamic": "~13.2.6", "@angular/platform-browser-dynamic": "~13.3.5",
"@angular/router": "~13.2.6", "@angular/router": "~13.3.5",
"@fortawesome/fontawesome-free": "^6.0.0", "@fortawesome/fontawesome-free": "^6.1.1",
"@microsoft/signalr": "^6.0.3", "@microsoft/signalr": "^6.0.4",
"bulma": "^0.9.3", "bulma": "^0.9.3",
"curray": "^1.0.8", "curray": "^1.0.8",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"ngx-filesize": "^2.0.16", "ngx-filesize": "^2.0.16",
"rxjs": "~7.5.5", "rxjs": "~7.5.5",
"tslib": "^2.3.1", "tslib": "^2.4.0",
"zone.js": "~0.11.5" "zone.js": "~0.11.5"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "~13.2.6", "@angular-devkit/build-angular": "~13.3.4",
"@angular/cli": "~13.2.6", "@angular/cli": "~13.3.4",
"@angular/compiler-cli": "~13.2.6", "@angular/compiler-cli": "~13.3.5",
"@angular/language-service": "~13.2.6", "@angular/language-service": "~13.3.5",
"@types/file-saver": "^2.0.5", "@types/file-saver": "^2.0.5",
"@types/node": "^17.0.21", "@types/node": "^17.0.30",
"typescript": "~4.5.5" "typescript": "~4.5.5"
} }
} }

View file

@ -1,14 +1,11 @@
using System.Collections.Generic; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
namespace RdtClient.Data.Data namespace RdtClient.Data.Data;
public class DataContext : IdentityDbContext
{ {
public class DataContext : IdentityDbContext
{
public DataContext(DbContextOptions options) : base(options) public DataContext(DbContextOptions options) : base(options)
{ {
} }
@ -86,11 +83,11 @@ namespace RdtClient.Data.Data
{ {
SettingId = "DownloadPath", SettingId = "DownloadPath",
Type = "String", Type = "String",
#if DEBUG #if DEBUG
Value = @"C:\Temp\rdtclient" Value = @"C:\Temp\rdtclient"
#else #else
Value = "/data/downloads" Value = "/data/downloads"
#endif #endif
}, },
new Setting new Setting
{ {
@ -222,5 +219,4 @@ namespace RdtClient.Data.Data
} }
} }
} }
}
} }

View file

@ -1,14 +1,10 @@
using System; using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Download = RdtClient.Data.Models.Data.Download; using Download = RdtClient.Data.Models.Data.Download;
namespace RdtClient.Data.Data namespace RdtClient.Data.Data;
public class DownloadData
{ {
public class DownloadData
{
private readonly DataContext _dataContext; private readonly DataContext _dataContext;
public DownloadData(DataContext dataContext) public DownloadData(DataContext dataContext)
@ -263,5 +259,4 @@ namespace RdtClient.Data.Data
await TorrentData.VoidCache(); await TorrentData.VoidCache();
} }
}
} }

View file

@ -1,17 +1,12 @@
using System; using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.Internal; using RdtClient.Data.Models.Internal;
using Serilog; using Serilog;
namespace RdtClient.Data.Data namespace RdtClient.Data.Data;
public class SettingData
{ {
public class SettingData
{
private static readonly SemaphoreSlim _settingCacheLock = new(1); private static readonly SemaphoreSlim _settingCacheLock = new(1);
private readonly DataContext _dataContext; private readonly DataContext _dataContext;
@ -134,5 +129,4 @@ namespace RdtClient.Data.Data
_settingCacheLock.Release(); _settingCacheLock.Release();
} }
} }
}
} }

View file

@ -1,15 +1,10 @@
using System; using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
namespace RdtClient.Data.Data namespace RdtClient.Data.Data;
public class TorrentData
{ {
public class TorrentData
{
private static IList<Torrent> _torrentCache; private static IList<Torrent> _torrentCache;
private static readonly SemaphoreSlim TorrentCacheLock = new(1, 1); private static readonly SemaphoreSlim TorrentCacheLock = new(1, 1);
@ -312,5 +307,4 @@ namespace RdtClient.Data.Data
TorrentCacheLock.Release(); TorrentCacheLock.Release();
} }
} }
}
} }

View file

@ -1,11 +1,10 @@
using System.Threading.Tasks; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace RdtClient.Data.Data namespace RdtClient.Data.Data;
public class UserData
{ {
public class UserData
{
private readonly DataContext _dataContext; private readonly DataContext _dataContext;
public UserData(DataContext dataContext) public UserData(DataContext dataContext)
@ -17,5 +16,4 @@ namespace RdtClient.Data.Data
{ {
return await _dataContext.Users.FirstOrDefaultAsync(); return await _dataContext.Users.FirstOrDefaultAsync();
} }
}
} }

View file

@ -1,16 +1,20 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RdtClient.Data.Data; using RdtClient.Data.Data;
using RdtClient.Data.Models.Internal;
namespace RdtClient.Data namespace RdtClient.Data;
public static class DiConfig
{ {
public static class DiConfig public static void Config(IServiceCollection services, AppSettings appSettings)
{
public static void Config(IServiceCollection services)
{ {
var connectionString = $"Data Source={appSettings.Database.Path}";
services.AddDbContext<DataContext>(options => options.UseSqlite(connectionString));
services.AddScoped<DownloadData>(); services.AddScoped<DownloadData>();
services.AddScoped<SettingData>(); services.AddScoped<SettingData>();
services.AddScoped<TorrentData>(); services.AddScoped<TorrentData>();
services.AddScoped<UserData>(); services.AddScoped<UserData>();
} }
}
} }

View file

@ -1,9 +1,8 @@
namespace RdtClient.Data.Enums namespace RdtClient.Data.Enums;
public enum TorrentDownloadAction
{ {
public enum TorrentDownloadAction
{
DownloadAll = 0, DownloadAll = 0,
DownloadAvailableFiles = 1, DownloadAvailableFiles = 1,
DownloadManual = 2 DownloadManual = 2
}
} }

View file

@ -1,9 +1,8 @@
namespace RdtClient.Data.Enums namespace RdtClient.Data.Enums;
public enum TorrentFinishedAction
{ {
public enum TorrentFinishedAction
{
None = 0, None = 0,
RemoveAllTorrents = 1, RemoveAllTorrents = 1,
RemoveRealDebrid = 2 RemoveRealDebrid = 2
}
} }

View file

@ -1,7 +1,7 @@
namespace RdtClient.Data.Enums namespace RdtClient.Data.Enums;
public enum TorrentStatus
{ {
public enum TorrentStatus
{
Processing = 0, Processing = 0,
WaitingForFileSelection = 1, WaitingForFileSelection = 1,
Downloading = 2, Downloading = 2,
@ -9,5 +9,4 @@
Uploading = 4, Uploading = 4,
Error = 99 Error = 99
}
} }

View file

@ -1,11 +1,10 @@
using System; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace RdtClient.Data.Models.Data namespace RdtClient.Data.Models.Data;
public class Download
{ {
public class Download
{
[Key] [Key]
public Guid DownloadId { get; set; } public Guid DownloadId { get; set; }
@ -40,5 +39,4 @@ namespace RdtClient.Data.Models.Data
[NotMapped] [NotMapped]
public Int64 Speed { get; set; } public Int64 Speed { get; set; }
}
} }

View file

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

View file

@ -1,15 +1,13 @@
using System; using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json; using System.Text.Json;
using RdtClient.Data.Enums; using RdtClient.Data.Enums;
using RdtClient.Data.Models.TorrentClient; using RdtClient.Data.Models.TorrentClient;
namespace RdtClient.Data.Models.Data namespace RdtClient.Data.Models.Data;
public class Torrent
{ {
public class Torrent
{
[Key] [Key]
public Guid TorrentId { get; set; } public Guid TorrentId { get; set; }
@ -90,5 +88,4 @@ namespace RdtClient.Data.Models.Data
return DownloadManualFiles.Split(","); return DownloadManualFiles.Split(",");
} }
} }
}
} }

View file

@ -1,31 +1,26 @@
using System; namespace RdtClient.Data.Models.Internal;
namespace RdtClient.Data.Models.Internal public class AppSettings
{ {
public class AppSettings
{
public AppSettingsLogging Logging { get; set; } public AppSettingsLogging Logging { get; set; }
public AppSettingsDatabase Database { get; set; } public AppSettingsDatabase Database { get; set; }
public String AllowedHosts { get; set; } public Int32 Port { get; set; }
public String HostUrl { get; set; } }
}
public class AppSettingsLogging public class AppSettingsLogging
{ {
public AppSettingsLoggingFile File { get; set; } public AppSettingsLoggingFile File { get; set; }
} }
public class AppSettingsLoggingFile public class AppSettingsLoggingFile
{ {
public String Path { get; set; } public String Path { get; set; }
public String Append { get; set; }
public Int64 FileSizeLimitBytes { get; set; } public Int64 FileSizeLimitBytes { get; set; }
public Int32 MaxRollingFiles { get; set; } public Int32 MaxRollingFiles { get; set; }
} }
public class AppSettingsDatabase public class AppSettingsDatabase
{ {
public String Path { get; set; } public String Path { get; set; }
}
} }

View file

@ -1,9 +1,7 @@
using System; namespace RdtClient.Data.Models.Internal;
namespace RdtClient.Data.Models.Internal public class DbSettings
{ {
public class DbSettings
{
public String Provider { get; set; } public String Provider { get; set; }
public Int32 ProviderAutoImport { get; set; } public Int32 ProviderAutoImport { get; set; }
public String ProviderAutoImportCategory { get; set; } public String ProviderAutoImportCategory { get; set; }
@ -30,5 +28,4 @@ namespace RdtClient.Data.Models.Internal
public Int32 TorrentLifetime { get; set; } public Int32 TorrentLifetime { get; set; }
public String RunOnTorrentCompleteFileName { get; set; } public String RunOnTorrentCompleteFileName { get; set; }
public String RunOnTorrentCompleteArguments { get; set; } public String RunOnTorrentCompleteArguments { get; set; }
}
} }

View file

@ -1,13 +1,10 @@
using System; namespace RdtClient.Data.Models.Internal;
namespace RdtClient.Data.Models.Internal public class Profile
{ {
public class Profile
{
public String Provider { get; set; } public String Provider { get; set; }
public String UserName { get; set; } public String UserName { get; set; }
public DateTimeOffset? Expiration { get; set; } public DateTimeOffset? Expiration { get; set; }
public String CurrentVersion { get; set; } public String CurrentVersion { get; set; }
public String LatestVersion { get; set; } public String LatestVersion { get; set; }
}
} }

View file

@ -1,10 +1,9 @@
using System; using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace RdtClient.Data.Models.QBittorrent namespace RdtClient.Data.Models.QBittorrent;
public class AppBuildInfo
{ {
public class AppBuildInfo
{
[JsonPropertyName("bitness")] [JsonPropertyName("bitness")]
public Int64 Bitness { get; set; } public Int64 Bitness { get; set; }
@ -22,5 +21,4 @@ namespace RdtClient.Data.Models.QBittorrent
[JsonPropertyName("zlib")] [JsonPropertyName("zlib")]
public String Zlib { get; set; } public String Zlib { get; set; }
}
} }

View file

@ -1,12 +1,9 @@
using System; using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace RdtClient.Data.Models.QBittorrent namespace RdtClient.Data.Models.QBittorrent;
public class AppPreferences
{ {
namespace QuickType
{
public class AppPreferences
{
[JsonPropertyName("add_trackers")] [JsonPropertyName("add_trackers")]
public String AddTrackers { get; set; } public String AddTrackers { get; set; }
@ -426,10 +423,8 @@ namespace RdtClient.Data.Models.QBittorrent
[JsonPropertyName("web_ui_username")] [JsonPropertyName("web_ui_username")]
public String WebUiUsername { get; set; } public String WebUiUsername { get; set; }
} }
public class ScanDirs public class ScanDirs
{ {
}
}
} }

View file

@ -1,12 +1,9 @@
using System; using System.Text.Json.Serialization;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using RdtClient.Data.Models.QBittorrent.QuickType;
namespace RdtClient.Data.Models.QBittorrent namespace RdtClient.Data.Models.QBittorrent;
public class SyncMetaData
{ {
public class SyncMetaData
{
[JsonPropertyName("categories")] [JsonPropertyName("categories")]
public IDictionary<String, TorrentCategory> Categories { get; set; } public IDictionary<String, TorrentCategory> Categories { get; set; }
@ -27,10 +24,10 @@ namespace RdtClient.Data.Models.QBittorrent
[JsonPropertyName("trackers")] [JsonPropertyName("trackers")]
public IDictionary<String, List<String>> Trackers { get; set; } public IDictionary<String, List<String>> Trackers { get; set; }
} }
public class SyncMetaDataServerState public class SyncMetaDataServerState
{ {
[JsonPropertyName("alltime_dl")] [JsonPropertyName("alltime_dl")]
public Int64 AlltimeDl { get; set; } public Int64 AlltimeDl { get; set; }
@ -102,5 +99,4 @@ namespace RdtClient.Data.Models.QBittorrent
[JsonPropertyName("write_cache_overload")] [JsonPropertyName("write_cache_overload")]
public String WriteCacheOverload { get; set; } public String WriteCacheOverload { get; set; }
}
} }

View file

@ -1,14 +1,12 @@
using System; using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace RdtClient.Data.Models.QBittorrent namespace RdtClient.Data.Models.QBittorrent;
public class TorrentCategory
{ {
public class TorrentCategory
{
[JsonPropertyName("name")] [JsonPropertyName("name")]
public String Name { get; set; } public String Name { get; set; }
[JsonPropertyName("savePath")] [JsonPropertyName("savePath")]
public String SavePath { get; set; } public String SavePath { get; set; }
}
} }

View file

@ -1,11 +1,9 @@
using System;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace RdtClient.Data.Models.QBittorrent namespace RdtClient.Data.Models.QBittorrent;
public class TorrentFileItem
{ {
public class TorrentFileItem
{
[JsonPropertyName("name")] [JsonPropertyName("name")]
public String Name { get; set; } public String Name { get; set; }
}
} }

View file

@ -1,12 +1,9 @@
using System; using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace RdtClient.Data.Models.QBittorrent namespace RdtClient.Data.Models.QBittorrent;
public class TorrentInfo
{ {
namespace QuickType
{
public class TorrentInfo
{
[JsonPropertyName("added_on")] [JsonPropertyName("added_on")]
public Int64 AddedOn { get; set; } public Int64 AddedOn { get; set; }
@ -138,6 +135,4 @@ namespace RdtClient.Data.Models.QBittorrent
[JsonPropertyName("upspeed")] [JsonPropertyName("upspeed")]
public Int64 Upspeed { get; set; } public Int64 Upspeed { get; set; }
}
}
} }

View file

@ -1,10 +1,9 @@
using System; using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace RdtClient.Data.Models.QBittorrent namespace RdtClient.Data.Models.QBittorrent;
public class TorrentProperties
{ {
public class TorrentProperties
{
[JsonPropertyName("addition_date")] [JsonPropertyName("addition_date")]
public Int64 AdditionDate { get; set; } public Int64 AdditionDate { get; set; }
@ -103,5 +102,4 @@ namespace RdtClient.Data.Models.QBittorrent
[JsonPropertyName("up_speed_avg")] [JsonPropertyName("up_speed_avg")]
public Int64 UpSpeedAvg { get; set; } public Int64 UpSpeedAvg { get; set; }
}
} }

View file

@ -1,11 +1,8 @@
using System; namespace RdtClient.Data.Models.TorrentClient;
namespace RdtClient.Data.Models.TorrentClient public class TorrentClientAvailableFile
{ {
public class TorrentClientAvailableFile
{
public String Filename { get; set; } public String Filename { get; set; }
public Int64 Filesize { get; set; } public Int64 Filesize { get; set; }
}
} }

View file

@ -1,12 +1,9 @@
using System; namespace RdtClient.Data.Models.TorrentClient;
namespace RdtClient.Data.Models.TorrentClient public class TorrentClientFile
{ {
public class TorrentClientFile
{
public Int64 Id { get; set; } public Int64 Id { get; set; }
public String Path { get; set; } public String Path { get; set; }
public Int64 Bytes { get; set; } public Int64 Bytes { get; set; }
public Boolean Selected { get; set; } public Boolean Selected { get; set; }
}
} }

View file

@ -1,10 +1,7 @@
using System; namespace RdtClient.Data.Models.TorrentClient;
using System.Collections.Generic;
namespace RdtClient.Data.Models.TorrentClient public class TorrentClientTorrent
{ {
public class TorrentClientTorrent
{
public String Id { get; set; } public String Id { get; set; }
public String Filename { get; set; } public String Filename { get; set; }
public String OriginalFilename { get; set; } public String OriginalFilename { get; set; }
@ -22,5 +19,4 @@ namespace RdtClient.Data.Models.TorrentClient
public DateTimeOffset? Ended { get; set; } public DateTimeOffset? Ended { get; set; }
public Int64? Speed { get; set; } public Int64? Speed { get; set; }
public Int64? Seeders { get; set; } public Int64? Seeders { get; set; }
}
} }

View file

@ -1,10 +1,7 @@
using System; namespace RdtClient.Data.Models.TorrentClient;
namespace RdtClient.Data.Models.TorrentClient public class TorrentClientUser
{ {
public class TorrentClientUser
{
public String Username { get; set; } public String Username { get; set; }
public DateTimeOffset? Expiration { get; set; } public DateTimeOffset? Expiration { get; set; }
}
} }

View file

@ -2,18 +2,21 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.3" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.4" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.3" /> <PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.3" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.3"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.4">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Serilog" Version="2.10.0" /> <PackageReference Include="Serilog" Version="2.11.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -2,10 +2,10 @@
using RdtClient.Service.Services; using RdtClient.Service.Services;
using RdtClient.Service.Services.TorrentClients; using RdtClient.Service.Services.TorrentClients;
namespace RdtClient.Service namespace RdtClient.Service;
public static class DiConfig
{ {
public static class DiConfig
{
public static void Config(IServiceCollection services) public static void Config(IServiceCollection services)
{ {
services.AddScoped<AllDebridTorrentClient>(); services.AddScoped<AllDebridTorrentClient>();
@ -19,6 +19,7 @@ namespace RdtClient.Service
services.AddScoped<TorrentRunner>(); services.AddScoped<TorrentRunner>();
services.AddHostedService<Startup>(); services.AddHostedService<Startup>();
} services.AddHostedService<TaskRunner>();
services.AddHostedService<UpdateChecker>();
} }
} }

View file

@ -1,13 +1,10 @@
using System; using System.Web;
using System.IO;
using System.Linq;
using System.Web;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
namespace RdtClient.Service.Helpers namespace RdtClient.Service.Helpers;
public static class DownloadHelper
{ {
public static class DownloadHelper
{
public static String GetDownloadPath(String downloadPath, Torrent torrent, Download download) public static String GetDownloadPath(String downloadPath, Torrent torrent, Download download)
{ {
var fileUrl = download.Link; var fileUrl = download.Link;
@ -33,5 +30,4 @@ namespace RdtClient.Service.Helpers
return filePath; return filePath;
} }
}
} }

View file

@ -1,11 +1,7 @@
using System; namespace RdtClient.Service.Helpers;
using System.IO;
using System.Threading.Tasks;
namespace RdtClient.Service.Helpers public static class FileHelper
{ {
public static class FileHelper
{
public static async Task Delete(String path) public static async Task Delete(String path)
{ {
if (String.IsNullOrWhiteSpace(path)) if (String.IsNullOrWhiteSpace(path))
@ -41,5 +37,4 @@ namespace RdtClient.Service.Helpers
} }
} }
} }
}
} }

View file

@ -1,11 +1,9 @@
using System; using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace RdtClient.Service.Helpers namespace RdtClient.Service.Helpers;
public class JsonModelBinder : IModelBinder
{ {
public class JsonModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext) public Task BindModelAsync(ModelBindingContext bindingContext)
{ {
if (bindingContext == null) if (bindingContext == null)
@ -29,5 +27,4 @@ namespace RdtClient.Service.Helpers
return Task.CompletedTask; return Task.CompletedTask;
} }
}
} }

View file

@ -1,12 +1,10 @@
using System; using System.Web;
using System.Linq;
using System.Web;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
namespace RdtClient.Service.Helpers namespace RdtClient.Service.Helpers;
public static class Logger
{ {
public static class Logger
{
public static String ToLog(this Download download) public static String ToLog(this Download download)
{ {
var fileName = download.Path; var fileName = download.Path;
@ -27,5 +25,4 @@ namespace RdtClient.Service.Helpers
{ {
return $"for torrent {torrent.RdName} ({torrent.RdId} - {torrent.RdStatusRaw} {torrent.RdProgress}%) ({torrent.TorrentId})"; return $"for torrent {torrent.RdName} ({torrent.RdId} - {torrent.RdStatusRaw} {torrent.RdProgress}%) ({torrent.TorrentId})";
} }
}
} }

View file

@ -1,12 +1,9 @@
using System; using RdtClient.Data.Models.Data;
using System.Collections.Generic;
using System.Linq;
using RdtClient.Data.Models.Data;
namespace RdtClient.Service.Helpers namespace RdtClient.Service.Helpers;
public static class SettingsHelper
{ {
public static class SettingsHelper
{
public static String GetString(this IList<Setting> settings, String key) public static String GetString(this IList<Setting> settings, String key)
{ {
var setting = settings.FirstOrDefault(m => m.SettingId == key); var setting = settings.FirstOrDefault(m => m.SettingId == key);
@ -30,5 +27,4 @@ namespace RdtClient.Service.Helpers
return Int32.Parse(setting.Value); return Int32.Parse(setting.Value);
} }
}
} }

View file

@ -1,12 +1,10 @@
using System; using System.Net;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace RdtClient.Service.Middleware namespace RdtClient.Service.Middleware;
public class AuthorizeMiddleware
{ {
public class AuthorizeMiddleware
{
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
public AuthorizeMiddleware(RequestDelegate next) public AuthorizeMiddleware(RequestDelegate next)
@ -28,5 +26,4 @@ namespace RdtClient.Service.Middleware
context.Response.StatusCode = (Int32) HttpStatusCode.Forbidden; context.Response.StatusCode = (Int32) HttpStatusCode.Forbidden;
} }
} }
}
} }

View file

@ -1,13 +1,12 @@
using System; using System.Net;
using System.Net;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace RdtClient.Service.Middleware namespace RdtClient.Service.Middleware;
public static class ExceptionMiddlewareExtensions
{ {
public static class ExceptionMiddlewareExtensions
{
public static void ConfigureExceptionHandler(this IApplicationBuilder app) public static void ConfigureExceptionHandler(this IApplicationBuilder app)
{ {
app.UseExceptionHandler(appError => app.UseExceptionHandler(appError =>
@ -25,5 +24,4 @@ namespace RdtClient.Service.Middleware
}); });
}); });
} }
}
} }

View file

@ -1,20 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<OutputType>library</OutputType> <Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="AllDebrid.NET" Version="1.0.7" /> <PackageReference Include="AllDebrid.NET" Version="1.0.7" />
<PackageReference Include="Aria2.NET" Version="1.0.4" /> <PackageReference Include="Aria2.NET" Version="1.0.4" />
<PackageReference Include="Downloader" Version="2.3.3" /> <PackageReference Include="Downloader" Version="2.3.3" />
<PackageReference Include="MonoTorrent" Version="2.0.4" /> <PackageReference Include="MonoTorrent" Version="2.0.5" />
<PackageReference Include="RD.NET" Version="2.1.2" /> <PackageReference Include="RD.NET" Version="2.1.2" />
<PackageReference Include="Serilog" Version="2.10.0" /> <PackageReference Include="Serilog" Version="2.11.0" />
<PackageReference Include="Serilog.Exceptions" Version="8.1.0" /> <PackageReference Include="Serilog.Exceptions" Version="8.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="SharpCompress" Version="0.30.1" /> <PackageReference Include="SharpCompress" Version="0.31.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,12 +1,10 @@
using System; using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using RdtClient.Data.Data; using RdtClient.Data.Data;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class Authentication
{ {
public class Authentication
{
private readonly SignInManager<IdentityUser> _signInManager; private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager; private readonly UserManager<IdentityUser> _userManager;
private readonly UserData _userData; private readonly UserData _userData;
@ -75,5 +73,4 @@ namespace RdtClient.Service.Services
return IdentityResult.Success; return IdentityResult.Success;
} }
}
} }

View file

@ -1,14 +1,12 @@
using System; using RdtClient.Data.Models.Data;
using System.Threading.Tasks;
using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.Internal; using RdtClient.Data.Models.Internal;
using RdtClient.Service.Helpers; using RdtClient.Service.Helpers;
using RdtClient.Service.Services.Downloaders; using RdtClient.Service.Services.Downloaders;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class DownloadClient
{ {
public class DownloadClient
{
private readonly String _destinationPath; private readonly String _destinationPath;
private readonly Download _download; private readonly Download _download;
@ -122,5 +120,4 @@ namespace RdtClient.Service.Services
} }
await Downloader.Resume(); await Downloader.Resume();
} }
}
} }

View file

@ -1,17 +1,11 @@
using System; using Aria2NET;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Aria2NET;
using RdtClient.Data.Models.Internal; using RdtClient.Data.Models.Internal;
using Serilog; using Serilog;
namespace RdtClient.Service.Services.Downloaders namespace RdtClient.Service.Services.Downloaders;
public class Aria2cDownloader : IDownloader
{ {
public class Aria2cDownloader : IDownloader
{
public event EventHandler<DownloadCompleteEventArgs> DownloadComplete; public event EventHandler<DownloadCompleteEventArgs> DownloadComplete;
public event EventHandler<DownloadProgressEventArgs> DownloadProgress; public event EventHandler<DownloadProgressEventArgs> DownloadProgress;
@ -168,7 +162,7 @@ namespace RdtClient.Service.Services.Downloaders
if (download == null) if (download == null)
{ {
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs DownloadComplete.Invoke(this, new DownloadCompleteEventArgs
{ {
Error = $"Download was not found in Aria2" Error = $"Download was not found in Aria2"
}); });
@ -178,7 +172,7 @@ namespace RdtClient.Service.Services.Downloaders
if (!String.IsNullOrWhiteSpace(download.ErrorMessage) || download.Status == "error") if (!String.IsNullOrWhiteSpace(download.ErrorMessage) || download.Status == "error")
{ {
await Remove(); await Remove();
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs DownloadComplete.Invoke(this, new DownloadCompleteEventArgs
{ {
Error = $"{download.ErrorCode}: {download.ErrorMessage}" Error = $"{download.ErrorCode}: {download.ErrorMessage}"
}); });
@ -196,7 +190,7 @@ namespace RdtClient.Service.Services.Downloaders
{ {
if (retryCount >= 10) if (retryCount >= 10)
{ {
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs DownloadComplete.Invoke(this, new DownloadCompleteEventArgs
{ {
Error = $"File not found at {_filePath}" Error = $"File not found at {_filePath}"
}); });
@ -205,7 +199,7 @@ namespace RdtClient.Service.Services.Downloaders
if (File.Exists(_filePath)) if (File.Exists(_filePath))
{ {
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs()); DownloadComplete.Invoke(this, new DownloadCompleteEventArgs());
break; break;
} }
@ -215,7 +209,7 @@ namespace RdtClient.Service.Services.Downloaders
return; return;
} }
DownloadProgress?.Invoke(this, new DownloadProgressEventArgs DownloadProgress.Invoke(this, new DownloadProgressEventArgs
{ {
BytesDone = download.CompletedLength, BytesDone = download.CompletedLength,
BytesTotal = download.TotalLength, BytesTotal = download.TotalLength,
@ -268,5 +262,4 @@ namespace RdtClient.Service.Services.Downloaders
return false; return false;
} }
}
} }

View file

@ -1,27 +1,23 @@
using System; namespace RdtClient.Service.Services.Downloaders;
using System.Threading.Tasks;
namespace RdtClient.Service.Services.Downloaders public class DownloadCompleteEventArgs
{ {
public class DownloadCompleteEventArgs
{
public String Error { get; set; } public String Error { get; set; }
} }
public class DownloadProgressEventArgs public class DownloadProgressEventArgs
{ {
public Int64 Speed { get; set; } public Int64 Speed { get; set; }
public Int64 BytesDone { get; set; } public Int64 BytesDone { get; set; }
public Int64 BytesTotal { get; set; } public Int64 BytesTotal { get; set; }
} }
public interface IDownloader public interface IDownloader
{ {
event EventHandler<DownloadCompleteEventArgs> DownloadComplete; event EventHandler<DownloadCompleteEventArgs> DownloadComplete;
event EventHandler<DownloadProgressEventArgs> DownloadProgress; event EventHandler<DownloadProgressEventArgs> DownloadProgress;
Task<String> Download(); Task<String> Download();
Task Cancel(); Task Cancel();
Task Pause(); Task Pause();
Task Resume(); Task Resume();
}
} }

View file

@ -1,15 +1,12 @@
using System; using System.Net;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Downloader; using Downloader;
using RdtClient.Data.Models.Internal; using RdtClient.Data.Models.Internal;
using Serilog; using Serilog;
namespace RdtClient.Service.Services.Downloaders namespace RdtClient.Service.Services.Downloaders;
public class MultiDownloader : IDownloader
{ {
public class MultiDownloader : IDownloader
{
public event EventHandler<DownloadCompleteEventArgs> DownloadComplete; public event EventHandler<DownloadCompleteEventArgs> DownloadComplete;
public event EventHandler<DownloadProgressEventArgs> DownloadProgress; public event EventHandler<DownloadProgressEventArgs> DownloadProgress;
@ -86,7 +83,7 @@ namespace RdtClient.Service.Services.Downloaders
return; return;
} }
DownloadProgress?.Invoke(this, DownloadProgress.Invoke(this,
new DownloadProgressEventArgs new DownloadProgressEventArgs
{ {
Speed = (Int64)args.BytesPerSecondSpeed, Speed = (Int64)args.BytesPerSecondSpeed,
@ -143,5 +140,4 @@ namespace RdtClient.Service.Services.Downloaders
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }
}
} }

View file

@ -1,15 +1,10 @@
using System; using System.Net;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Serilog; using Serilog;
namespace RdtClient.Service.Services.Downloaders namespace RdtClient.Service.Services.Downloaders;
public class SimpleDownloader : IDownloader
{ {
public class SimpleDownloader : IDownloader
{
private const Int32 BufferSize = 8 * 1024; private const Int32 BufferSize = 8 * 1024;
public event EventHandler<DownloadCompleteEventArgs> DownloadComplete; public event EventHandler<DownloadCompleteEventArgs> DownloadComplete;
@ -144,11 +139,11 @@ namespace RdtClient.Service.Services.Downloaders
throw new Exception($"Download timed out"); throw new Exception($"Download timed out");
} }
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs()); DownloadComplete.Invoke(this, new DownloadCompleteEventArgs());
} }
catch (Exception ex) catch (Exception ex)
{ {
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs DownloadComplete.Invoke(this, new DownloadCompleteEventArgs
{ {
Error = ex.Message Error = ex.Message
}); });
@ -181,5 +176,4 @@ namespace RdtClient.Service.Services.Downloaders
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }
}
} }

View file

@ -1,13 +1,10 @@
using System; using RdtClient.Data.Data;
using System.Collections.Generic;
using System.Threading.Tasks;
using RdtClient.Data.Data;
using Download = RdtClient.Data.Models.Data.Download; using Download = RdtClient.Data.Models.Data.Download;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class Downloads
{ {
public class Downloads
{
private readonly DownloadData _downloadData; private readonly DownloadData _downloadData;
public Downloads(DownloadData downloadData) public Downloads(DownloadData downloadData)
@ -94,5 +91,4 @@ namespace RdtClient.Service.Services
{ {
await _downloadData.Reset(downloadId); await _downloadData.Reset(downloadId);
} }
}
} }

View file

@ -1,17 +1,11 @@
using System; using RdtClient.Data.Enums;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.QBittorrent; using RdtClient.Data.Models.QBittorrent;
using RdtClient.Data.Models.QBittorrent.QuickType;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class QBittorrent
{ {
public class QBittorrent
{
private readonly Authentication _authentication; private readonly Authentication _authentication;
private readonly Settings _settings; private readonly Settings _settings;
private readonly Torrents _torrents; private readonly Torrents _torrents;
@ -618,5 +612,4 @@ namespace RdtClient.Service.Services
} }
}; };
} }
}
} }

View file

@ -1,13 +1,10 @@
using System; using System.Collections.Concurrent;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class RdtHub : Hub
{ {
public class RdtHub : Hub
{
private static readonly ConcurrentDictionary<String, String> Users = new(); private static readonly ConcurrentDictionary<String, String> Users = new();
public static Boolean HasConnections => Users.Any(); public static Boolean HasConnections => Users.Any();
@ -23,5 +20,4 @@ namespace RdtClient.Service.Services
Users.TryRemove(Context.ConnectionId, out _); Users.TryRemove(Context.ConnectionId, out _);
await base.OnDisconnectedAsync(exception); await base.OnDisconnectedAsync(exception);
} }
}
} }

View file

@ -1,12 +1,9 @@
using System; using Microsoft.AspNetCore.SignalR;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class RemoteService
{ {
public class RemoteService
{
private readonly IHubContext<RdtHub> _hub; private readonly IHubContext<RdtHub> _hub;
private readonly Torrents _torrents; private readonly Torrents _torrents;
@ -32,5 +29,4 @@ namespace RdtClient.Service.Services
torrents torrents
}); });
} }
}
} }

View file

@ -1,19 +1,18 @@
using System; using System.Diagnostics;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Aria2NET; using Aria2NET;
using RdtClient.Data.Data; using RdtClient.Data.Data;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.Internal; using RdtClient.Data.Models.Internal;
using RdtClient.Service.Helpers; using RdtClient.Service.Helpers;
using Serilog.Core;
using Serilog.Events;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class Settings
{ {
public class Settings public static readonly LoggingLevelSwitch LoggingLevelSwitch = new(LogEventLevel.Debug);
{
private readonly SettingData _settingData; private readonly SettingData _settingData;
public Settings(SettingData settingData) public Settings(SettingData settingData)
@ -178,5 +177,4 @@ namespace RdtClient.Service.Services
{ {
await _settingData.ResetCache(); await _settingData.ResetCache();
} }
}
} }

View file

@ -1,13 +1,15 @@
using System; using System.Reflection;
using System.Threading; using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using RdtClient.Data.Data;
using Serilog;
using Serilog.Events;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class Startup : IHostedService
{ {
public class Startup : IHostedService
{
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
public Startup(IServiceProvider serviceProvider) public Startup(IServiceProvider serviceProvider)
@ -19,6 +21,29 @@ namespace RdtClient.Service.Services
{ {
using var scope = _serviceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<DataContext>();
await dbContext.Database.MigrateAsync(cancellationToken);
await dbContext.Seed();
var logLevelSettingDb = await dbContext.Settings.FirstOrDefaultAsync(m => m.SettingId == "LogLevel", cancellationToken);
var logLevelSetting = "Warning";
if (logLevelSettingDb != null)
{
logLevelSetting = logLevelSettingDb.Value;
}
if (!Enum.TryParse<LogEventLevel>(logLevelSetting, out var logLevel))
{
logLevel = LogEventLevel.Warning;
}
Settings.LoggingLevelSwitch.MinimumLevel = logLevel;
var version = Assembly.GetEntryAssembly()?.GetName().Version;
Log.Warning($"Starting host on version {version}");
var settings = scope.ServiceProvider.GetRequiredService<Settings>(); var settings = scope.ServiceProvider.GetRequiredService<Settings>();
await settings.ResetCache(); await settings.ResetCache();
@ -27,6 +52,4 @@ namespace RdtClient.Service.Services
} }
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
} }

View file

@ -1,14 +1,11 @@
using System; using Microsoft.Extensions.DependencyInjection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class TaskRunner : BackgroundService
{ {
public class TaskRunner : BackgroundService
{
private readonly ILogger<TaskRunner> _logger; private readonly ILogger<TaskRunner> _logger;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
@ -45,5 +42,4 @@ namespace RdtClient.Service.Services
_logger.LogInformation("TaskRunner stopped."); _logger.LogInformation("TaskRunner stopped.");
} }
}
} }

View file

@ -1,16 +1,11 @@
using System; namespace RdtClient.Service.Services;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace RdtClient.Service.Services /// <summary>
/// Class for streaming data with throttling support.
/// Taken from Downloader: https://github.com/bezzad/Downloader
/// </summary>
public class ThrottledStream : Stream
{ {
/// <summary>
/// Class for streaming data with throttling support.
/// Taken from Downloader: https://github.com/bezzad/Downloader
/// </summary>
public class ThrottledStream : Stream
{
public Int64 Speed => (Int64)_bandwidth.AverageSpeed; public Int64 Speed => (Int64)_bandwidth.AverageSpeed;
private Bandwidth _bandwidth; private Bandwidth _bandwidth;
@ -148,10 +143,10 @@ namespace RdtClient.Service.Services
{ {
return _baseStream.ToString(); return _baseStream.ToString();
} }
} }
internal class Bandwidth internal class Bandwidth
{ {
private const Double OneSecond = 1000; // millisecond private const Double OneSecond = 1000; // millisecond
private Int64 _count; private Int64 _count;
private Int32 _lastSecondCheckpoint; private Int32 _lastSecondCheckpoint;
@ -207,5 +202,4 @@ namespace RdtClient.Service.Services
Interlocked.Exchange(ref _lastSecondCheckpoint, Environment.TickCount); Interlocked.Exchange(ref _lastSecondCheckpoint, Environment.TickCount);
Interlocked.Exchange(ref _lastTransferredBytesCount, 0); Interlocked.Exchange(ref _lastTransferredBytesCount, 0);
} }
}
} }

View file

@ -1,9 +1,4 @@
using System; using AllDebridNET;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using AllDebridNET;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using RDNET; using RDNET;
@ -11,12 +6,13 @@ using RDNET.Exceptions;
using RdtClient.Data.Enums; using RdtClient.Data.Enums;
using RdtClient.Data.Models.TorrentClient; using RdtClient.Data.Models.TorrentClient;
using RdtClient.Service.Helpers; using RdtClient.Service.Helpers;
using File = AllDebridNET.File;
using Torrent = RdtClient.Data.Models.Data.Torrent; using Torrent = RdtClient.Data.Models.Data.Torrent;
namespace RdtClient.Service.Services.TorrentClients namespace RdtClient.Service.Services.TorrentClients;
public class AllDebridTorrentClient : ITorrentClient
{ {
public class AllDebridTorrentClient : ITorrentClient
{
private readonly ILogger<AllDebridTorrentClient> _logger; private readonly ILogger<AllDebridTorrentClient> _logger;
private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpClientFactory _httpClientFactory;
@ -330,5 +326,4 @@ namespace RdtClient.Service.Services.TorrentClients
_logger.LogDebug(message); _logger.LogDebug(message);
} }
}
} }

View file

@ -1,13 +1,10 @@
using System; using RdtClient.Data.Models.Data;
using System.Collections.Generic;
using System.Threading.Tasks;
using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.TorrentClient; using RdtClient.Data.Models.TorrentClient;
namespace RdtClient.Service.Services.TorrentClients namespace RdtClient.Service.Services.TorrentClients;
public interface ITorrentClient
{ {
public interface ITorrentClient
{
Task<IList<TorrentClientTorrent>> GetTorrents(); Task<IList<TorrentClientTorrent>> GetTorrents();
Task<TorrentClientUser> GetUser(); Task<TorrentClientUser> GetUser();
Task<String> AddMagnet(String magnetLink); Task<String> AddMagnet(String magnetLink);
@ -19,5 +16,4 @@ namespace RdtClient.Service.Services.TorrentClients
Task<String> Unrestrict(String link); Task<String> Unrestrict(String link);
Task<Torrent> UpdateData(Torrent torrent, TorrentClientTorrent torrentClientTorrent); Task<Torrent> UpdateData(Torrent torrent, TorrentClientTorrent torrentClientTorrent);
Task<IList<String>> GetDownloadLinks(Torrent torrent); Task<IList<String>> GetDownloadLinks(Torrent torrent);
}
} }

View file

@ -1,19 +1,14 @@
using System; using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using RDNET; using RDNET;
using RdtClient.Data.Enums; using RdtClient.Data.Enums;
using RdtClient.Data.Models.TorrentClient; using RdtClient.Data.Models.TorrentClient;
using RdtClient.Service.Helpers; using RdtClient.Service.Helpers;
namespace RdtClient.Service.Services.TorrentClients namespace RdtClient.Service.Services.TorrentClients;
public class RealDebridTorrentClient : ITorrentClient
{ {
public class RealDebridTorrentClient : ITorrentClient
{
private readonly ILogger<RealDebridTorrentClient> _logger; private readonly ILogger<RealDebridTorrentClient> _logger;
private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpClientFactory _httpClientFactory;
private TimeSpan _offset; private TimeSpan _offset;
@ -351,5 +346,4 @@ namespace RdtClient.Service.Services.TorrentClients
_logger.LogDebug(message); _logger.LogDebug(message);
} }
}
} }

View file

@ -1,11 +1,6 @@
using System; using System.Collections.Concurrent;
using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks;
using System.Web; using System.Web;
using Aria2NET; using Aria2NET;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -15,10 +10,10 @@ using RdtClient.Data.Models.Internal;
using RdtClient.Service.Helpers; using RdtClient.Service.Helpers;
using RdtClient.Service.Services.Downloaders; using RdtClient.Service.Services.Downloaders;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class TorrentRunner
{ {
public class TorrentRunner
{
private static DateTime _nextUpdate = DateTime.UtcNow; private static DateTime _nextUpdate = DateTime.UtcNow;
public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new(); public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new();
@ -623,5 +618,4 @@ namespace RdtClient.Service.Services
_logger.LogDebug(message); _logger.LogDebug(message);
} }
}
} }

View file

@ -1,13 +1,7 @@
using System; using System.Diagnostics;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Linq;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using MonoTorrent; using MonoTorrent;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -19,10 +13,10 @@ using RdtClient.Service.Helpers;
using RdtClient.Service.Services.TorrentClients; using RdtClient.Service.Services.TorrentClients;
using Torrent = RdtClient.Data.Models.Data.Torrent; using Torrent = RdtClient.Data.Models.Data.Torrent;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class Torrents
{ {
public class Torrents
{
private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1); private static readonly SemaphoreSlim RealDebridUpdateLock = new(1, 1);
private readonly ILogger<Torrents> _logger; private readonly ILogger<Torrents> _logger;
@ -765,5 +759,4 @@ namespace RdtClient.Service.Services
_logger.LogDebug(message); _logger.LogDebug(message);
} }
}
} }

View file

@ -1,18 +1,13 @@
using System; using RdtClient.Data.Models.Data;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using RdtClient.Data.Models.Data;
using RdtClient.Service.Helpers; using RdtClient.Service.Helpers;
using SharpCompress.Archives; using SharpCompress.Archives;
using SharpCompress.Archives.Rar; using SharpCompress.Archives.Rar;
using SharpCompress.Common; using SharpCompress.Common;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class UnpackClient
{ {
public class UnpackClient
{
public Boolean Finished { get; private set; } public Boolean Finished { get; private set; }
public String Error { get; private set; } public String Error { get; private set; }
@ -145,5 +140,4 @@ namespace RdtClient.Service.Services
BytesDone = _rarfileStatus.Sum(m => m.Value); BytesDone = _rarfileStatus.Sum(m => m.Value);
} }
}
} }

View file

@ -1,19 +1,13 @@
using System; using System.Net.Http.Headers;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection; using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace RdtClient.Service.Services namespace RdtClient.Service.Services;
public class UpdateChecker : BackgroundService
{ {
public class UpdateChecker : BackgroundService
{
public static String CurrentVersion { get; private set; } public static String CurrentVersion { get; private set; }
public static String LatestVersion { get; private set; } public static String LatestVersion { get; private set; }
@ -73,11 +67,10 @@ namespace RdtClient.Service.Services
_logger.LogInformation("UpdateChecker stopped."); _logger.LogInformation("UpdateChecker stopped.");
} }
} }
public class GitHubReleasesResponse public class GitHubReleasesResponse
{ {
[JsonProperty("name")] [JsonProperty("name")]
public String Name { get; set; } public String Name { get; set; }
}
} }

View file

@ -1,15 +1,12 @@
using System; using Microsoft.AspNetCore.Authorization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using RdtClient.Service.Services; using RdtClient.Service.Services;
namespace RdtClient.Web.Controllers namespace RdtClient.Web.Controllers;
[Route("Api/Authentication")]
public class AuthController : Controller
{ {
[Route("Api/Authentication")]
public class AuthController : Controller
{
private readonly Authentication _authentication; private readonly Authentication _authentication;
public AuthController(Authentication authentication) public AuthController(Authentication authentication)
@ -104,17 +101,16 @@ namespace RdtClient.Web.Controllers
return Ok(); return Ok();
} }
} }
public class AuthControllerLoginRequest public class AuthControllerLoginRequest
{ {
public String UserName { get; set; } public String UserName { get; set; }
public String Password { get; set; } public String Password { get; set; }
} }
public class AuthControllerUpdateRequest public class AuthControllerUpdateRequest
{ {
public String UserName { get; set; } public String UserName { get; set; }
public String Password { get; set; } public String Password { get; set; }
}
} }

View file

@ -1,26 +1,19 @@
using System; using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using RdtClient.Data.Models.QBittorrent; using RdtClient.Data.Models.QBittorrent;
using RdtClient.Data.Models.QBittorrent.QuickType;
using RdtClient.Service.Services; using RdtClient.Service.Services;
namespace RdtClient.Web.Controllers namespace RdtClient.Web.Controllers;
/// <summary>
/// This API behaves as a regular QBittorrent 4+ API
/// Documentation is found here: https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)
/// </summary>
[ApiController]
[Route("api/v2")]
public class QBittorrentController : Controller
{ {
/// <summary>
/// This API behaves as a regular QBittorrent 4+ API
/// Documentation is found here: https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)
/// </summary>
[ApiController]
[Route("api/v2")]
public class QBittorrentController : Controller
{
private readonly QBittorrent _qBittorrent; private readonly QBittorrent _qBittorrent;
public QBittorrentController(QBittorrent qBittorrent) public QBittorrentController(QBittorrent qBittorrent)
@ -136,20 +129,24 @@ namespace RdtClient.Web.Controllers
[Route("torrents/info")] [Route("torrents/info")]
[HttpGet] [HttpGet]
[HttpPost] [HttpPost]
public async Task<ActionResult<IList<TorrentInfo>>> TorrentsInfo([FromQuery] QBTorrentsHashRequest request) public async Task<ActionResult<IList<TorrentInfo>>> TorrentsInfo([FromQuery] QBTorrentsInfoRequest request)
{ {
var results = await _qBittorrent.TorrentInfo(); var results = await _qBittorrent.TorrentInfo();
IList<TorrentInfo> filteredResults = new List<TorrentInfo>();
if (request.Category == null) { if (!String.IsNullOrWhiteSpace(request.Category))
filteredResults = results; {
} else if (request.Category == "") { results = results.Where(m => m.Category == request.Category).ToList();
filteredResults = results.Where(m => m.Category == null).ToList();
} else {
filteredResults = results.Where(m => m.Category == request.Category).ToList();
} }
return Ok(filteredResults); return Ok(results);
}
[Authorize]
[Route("torrents/info")]
[HttpPost]
public async Task<ActionResult<IList<TorrentInfo>>> TorrentsFilesPost([FromForm] QBTorrentsInfoRequest request)
{
return await TorrentsInfo(request);
} }
[Authorize] [Authorize]
@ -450,51 +447,55 @@ namespace RdtClient.Web.Controllers
{ {
return await SyncMainData(); return await SyncMainData();
} }
} }
public class QBAuthLoginRequest public class QBAuthLoginRequest
{ {
public String UserName { get; set; } public String UserName { get; set; }
public String Password { get; set; } public String Password { get; set; }
} }
public class QBTorrentsHashRequest public class QBTorrentsInfoRequest
{ {
public String Category { get; set; }
}
public class QBTorrentsHashRequest
{
public String Hash { get; set; } public String Hash { get; set; }
public String Category { get; set; } public String Category { get; set; }
} }
public class QBTorrentsDeleteRequest public class QBTorrentsDeleteRequest
{ {
public String Hashes { get; set; } public String Hashes { get; set; }
public Boolean DeleteFiles { get; set; } public Boolean DeleteFiles { get; set; }
} }
public class QBTorrentsAddRequest public class QBTorrentsAddRequest
{ {
public String Urls { get; set; } public String Urls { get; set; }
public String Category { get; set; } public String Category { get; set; }
public Int32? Priority { get; set; } public Int32? Priority { get; set; }
} }
public class QBTorrentsSetCategoryRequest public class QBTorrentsSetCategoryRequest
{ {
public String Hashes { get; set; } public String Hashes { get; set; }
public String Category { get; set; } public String Category { get; set; }
} }
public class QBTorrentsCreateCategoryRequest public class QBTorrentsCreateCategoryRequest
{ {
public String Category { get; set; } public String Category { get; set; }
} }
public class QBTorrentsRemoveCategoryRequest public class QBTorrentsRemoveCategoryRequest
{ {
public String Categories { get; set; } public String Categories { get; set; }
} }
public class QBTorrentsHashesRequest public class QBTorrentsHashesRequest
{ {
public String Hashes { get; set; } public String Hashes { get; set; }
}
} }

View file

@ -1,20 +1,16 @@
using System; using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
using RdtClient.Data.Models.Internal; using RdtClient.Data.Models.Internal;
using RdtClient.Service.Services; using RdtClient.Service.Services;
using Serilog.Events; using Serilog.Events;
namespace RdtClient.Web.Controllers namespace RdtClient.Web.Controllers;
[Authorize]
[Route("Api/Settings")]
public class SettingsController : Controller
{ {
[Authorize]
[Route("Api/Settings")]
public class SettingsController : Controller
{
private readonly Settings _settings; private readonly Settings _settings;
private readonly Torrents _torrents; private readonly Torrents _torrents;
@ -43,7 +39,7 @@ namespace RdtClient.Web.Controllers
logLevel = LogEventLevel.Information; logLevel = LogEventLevel.Information;
} }
Program.LoggingLevelSwitch.MinimumLevel = logLevel; Settings.LoggingLevelSwitch.MinimumLevel = logLevel;
return Ok(); return Ok();
} }
@ -91,21 +87,20 @@ namespace RdtClient.Web.Controllers
return Ok(version); return Ok(version);
} }
} }
public class SettingsControllerUpdateRequest public class SettingsControllerUpdateRequest
{ {
public IList<Setting> Settings { get; set; } public IList<Setting> Settings { get; set; }
} }
public class SettingsControllerTestPathRequest public class SettingsControllerTestPathRequest
{ {
public String Path { get; set; } public String Path { get; set; }
} }
public class SettingsControllerTestAria2cConnectionRequest public class SettingsControllerTestAria2cConnectionRequest
{ {
public String Url { get; set; } public String Url { get; set; }
public String Secret { get; set; } public String Secret { get; set; }
}
} }

View file

@ -1,22 +1,16 @@
using System; using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MonoTorrent; using MonoTorrent;
using RdtClient.Service.Helpers; using RdtClient.Service.Helpers;
using RdtClient.Service.Services; using RdtClient.Service.Services;
using Torrent = RdtClient.Data.Models.Data.Torrent; using Torrent = RdtClient.Data.Models.Data.Torrent;
namespace RdtClient.Web.Controllers namespace RdtClient.Web.Controllers;
[Authorize]
[Route("Api/Torrents")]
public class TorrentsController : Controller
{ {
[Authorize]
[Route("Api/Torrents")]
public class TorrentsController : Controller
{
private readonly TorrentRunner _torrentRunner; private readonly TorrentRunner _torrentRunner;
private readonly Torrents _torrents; private readonly Torrents _torrents;
@ -193,28 +187,27 @@ namespace RdtClient.Web.Controllers
return Ok(); return Ok();
} }
} }
public class TorrentControllerUploadFileRequest public class TorrentControllerUploadFileRequest
{ {
public Torrent Torrent { get; set; } public Torrent Torrent { get; set; }
} }
public class TorrentControllerUploadMagnetRequest public class TorrentControllerUploadMagnetRequest
{ {
public String MagnetLink { get; set; } public String MagnetLink { get; set; }
public Torrent Torrent { get; set; } public Torrent Torrent { get; set; }
} }
public class TorrentControllerDeleteRequest public class TorrentControllerDeleteRequest
{ {
public Boolean DeleteData { get; set; } public Boolean DeleteData { get; set; }
public Boolean DeleteRdTorrent { get; set; } public Boolean DeleteRdTorrent { get; set; }
public Boolean DeleteLocalFiles { get; set; } public Boolean DeleteLocalFiles { get; set; }
} }
public class TorrentControllerCheckFilesRequest public class TorrentControllerCheckFilesRequest
{ {
public String MagnetLink { get; set; } public String MagnetLink { get; set; }
}
} }

View file

@ -1,92 +1,38 @@
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Net;
using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using RdtClient.Data.Data; using RdtClient.Data.Data;
using RdtClient.Data.Models.Internal; using RdtClient.Data.Models.Internal;
using RdtClient.Service.Middleware;
using RdtClient.Service.Services; using RdtClient.Service.Services;
using Serilog; using Serilog;
using Serilog.Core;
using Serilog.Events; using Serilog.Events;
using Serilog.Exceptions; using Serilog.Exceptions;
namespace RdtClient.Web var builder = WebApplication.CreateBuilder(args);
// Bind the AppSettings from the appsettings.json files.
builder.Configuration.AddJsonFile("appsettings.json", false, false);
builder.Configuration.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", true, false);
// Bind AppSettings
var appSettings = new AppSettings();
builder.Configuration.Bind(appSettings);
builder.Services.AddSingleton(appSettings);
// Configure URLs
if (appSettings.Port <= 0)
{ {
public class Program appSettings.Port = 6500;
{ }
public static readonly LoggingLevelSwitch LoggingLevelSwitch = new(LogEventLevel.Debug);
public static async Task Main(String[] args) builder.WebHost.ConfigureKestrel(options =>
{ {
try options.ListenAnyIP(appSettings.Port);
{ });
var host = CreateHostBuilder(args).Build();
// Perform migrations builder.Host.UseSerilog((_, lc) => lc.Enrich.FromLogContext()
using (var scope = host.Services.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<DataContext>();
await dbContext.Database.MigrateAsync();
await dbContext.Seed();
var logLevelSettingDb = await dbContext.Settings.FirstOrDefaultAsync(m => m.SettingId == "LogLevel");
var logLevelSetting = "Warning";
if (logLevelSettingDb != null)
{
logLevelSetting = logLevelSettingDb.Value;
}
if (!Enum.TryParse<LogEventLevel>(logLevelSetting, out var logLevel))
{
logLevel = LogEventLevel.Warning;
}
LoggingLevelSwitch.MinimumLevel = logLevel;
}
var version = Assembly.GetEntryAssembly()?.GetName().Version;
Log.Warning($"Starting host on version {version}");
await host.RunAsync();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
// ReSharper disable once MemberCanBePrivate.Global
public static IHostBuilder CreateHostBuilder(String[] args)
{
var configuration = new ConfigurationBuilder()
#if DEBUG
.AddJsonFile("appsettings.Development.json", true, false)
#else
.AddJsonFile("appsettings.json", true, false)
#endif
.Build();
var appSettings = new AppSettings();
configuration.Bind(appSettings);
if (String.IsNullOrWhiteSpace(appSettings.HostUrl))
{
appSettings.HostUrl = "http://0.0.0.0:6500";
}
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithExceptionDetails() .Enrich.WithExceptionDetails()
.WriteTo.File(appSettings.Logging.File.Path, .WriteTo.File(appSettings.Logging.File.Path,
rollOnFileSizeLimit: true, rollOnFileSizeLimit: true,
@ -94,33 +40,141 @@ namespace RdtClient.Web
retainedFileCountLimit: appSettings.Logging.File.MaxRollingFiles, retainedFileCountLimit: appSettings.Logging.File.MaxRollingFiles,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {SourceContext}: {Message:lj}{NewLine}{Exception}") outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {SourceContext}: {Message:lj}{NewLine}{Exception}")
.WriteTo.Console() .WriteTo.Console()
.MinimumLevel.ControlledBy(LoggingLevelSwitch) .MinimumLevel.ControlledBy(Settings.LoggingLevelSwitch)
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System.Net.Http", LogEventLevel.Warning) .MinimumLevel.Override("System.Net.Http", LogEventLevel.Warning));
.CreateLogger();
Serilog.Debugging.SelfLog.Enable(msg => Serilog.Debugging.SelfLog.Enable(msg =>
{ {
Debug.Print(msg); Debug.Print(msg);
Debugger.Break(); Debugger.Break();
Console.WriteLine(msg); Console.WriteLine(msg);
Debug.WriteLine(msg); Debug.WriteLine(msg);
});
Log.Information("Starting RealDebridClient host");
builder.Services.AddControllers();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.SlidingExpiration = true;
}); });
return Host.CreateDefaultBuilder(args) builder.Services.AddAuthorization();
.UseWindowsService()
.ConfigureServices((_, services) => builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
{ {
services.AddHostedService<TaskRunner>(); options.User.RequireUniqueEmail = false;
services.AddHostedService<UpdateChecker>(); options.Password.RequiredLength = 10;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequiredUniqueChars = 5;
}) })
.ConfigureWebHostDefaults(webBuilder => .AddEntityFrameworkStores<DataContext>()
.AddDefaultTokenProviders();
builder.Services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{ {
webBuilder.UseUrls(appSettings.HostUrl) context.Response.StatusCode = StatusCodes.Status401Unauthorized;
.UseKestrel() return Task.CompletedTask;
.UseStartup<Startup>(); };
}) options.Cookie.Name = "SID";
.UseSerilog(); });
// Configure development cors.
builder.Services.AddCors(options =>
{
options.AddPolicy("Dev",
corsBuilder => corsBuilder.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
// Configure misc services.
builder.Services.AddResponseCaching();
builder.Services.AddMemoryCache();
builder.Services.AddDistributedMemoryCache();
builder.Services.AddHttpClient();
builder.Services.AddHttpContextAccessor();
builder.Services.AddSession();
builder.Services.AddSpaStaticFiles(spaBuilder =>
{
spaBuilder.RootPath = "wwwroot";
});
builder.Services.AddSignalR(hubOptions =>
{
hubOptions.EnableDetailedErrors = true;
});
builder.Host.UseWindowsService();
RdtClient.Data.DiConfig.Config(builder.Services, appSettings);
RdtClient.Service.DiConfig.Config(builder.Services);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
try
{
// Build the app
var app = builder.Build();
if (builder.Environment.IsDevelopment())
{
app.UseCors("Dev");
app.UseDeveloperExceptionPage();
} }
app.ConfigureExceptionHandler();
app.UseMiddleware<AuthorizeMiddleware>();
app.Use(async (context, next) =>
{
await next.Invoke();
if (context.Response.StatusCode != 200)
{
Log.Warning("{StatusCode}: {Value}", context.Response.StatusCode, context.Request.Path.Value);
} }
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<RdtHub>("/hub");
endpoints.MapControllers();
});
app.MapWhen(x => !x.Request.Path.StartsWithSegments("/api"), routeBuilder =>
{
routeBuilder.UseSpaStaticFiles();
routeBuilder.UseSpa(spa =>
{
spa.Options.SourcePath = "wwwroot";
spa.Options.DefaultPage = "/index.html";
});
});
// Run the app
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
} }

View file

@ -5,6 +5,9 @@
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<UserSecretsId>94c24cba-f03f-4453-a671-3640b517c573</UserSecretsId> <UserSecretsId>94c24cba-f03f-4453-a671-3640b517c573</UserSecretsId>
<Version>2.0.12</Version> <Version>2.0.12</Version>
<Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -26,16 +29,16 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.3" /> <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.3" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.3"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.4">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.3" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.4" />
<PackageReference Include="Serilog" Version="2.10.0" /> <PackageReference Include="Serilog" Version="2.11.0" />
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup> </ItemGroup>

View file

@ -1,137 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using RdtClient.Data.Data;
using RdtClient.Data.Models.Internal;
using RdtClient.Service.Middleware;
using RdtClient.Service.Services;
namespace RdtClient.Web
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
private IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
var appSettings = new AppSettings();
Configuration.Bind(appSettings);
services.AddSingleton(appSettings);
var connectionString = $"Data Source={appSettings.Database.Path}";
services.AddDbContext<DataContext>(options => options.UseSqlite(connectionString));
services.AddControllers();
services.AddSpaStaticFiles(configuration => { configuration.RootPath = "wwwroot"; });
services.AddSignalR(options =>
{
options.EnableDetailedErrors = true;
});
services.AddHttpContextAccessor();
services.AddCors(options =>
{
options.AddPolicy("Dev",
builder =>
{
builder.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin();
});
});
services.AddHttpClient();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => { options.SlidingExpiration = true; });
services.AddAuthorization();
services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.User.RequireUniqueEmail = false;
options.Password.RequiredLength = 10;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequiredUniqueChars = 5;
})
.AddEntityFrameworkStores<DataContext>()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
};
options.Cookie.Name = "SID";
});
Data.DiConfig.Config(services);
Service.DiConfig.Config(services);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
if (env.IsDevelopment())
{
app.UseCors("Dev");
}
app.ConfigureExceptionHandler();
app.UseMiddleware<AuthorizeMiddleware>();
app.Use(async (context, next) =>
{
await next.Invoke();
if (context.Response.StatusCode != 200)
{
logger.LogWarning("{StatusCode}: {Value}", context.Response.StatusCode, context.Request.Path.Value);
}
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<RdtHub>("/hub");
endpoints.MapControllers();
});
app.MapWhen(x => !x.Request.Path.Value.StartsWith("/api"), builder =>
{
builder.UseSpaStaticFiles();
builder.UseSpa(spa =>
{
spa.Options.SourcePath = "wwwroot";
spa.Options.DefaultPage = "/index.html";
});
});
}
}
}

View file

@ -2,7 +2,6 @@
"Logging": { "Logging": {
"File": { "File": {
"Path": "C:/Temp/rdtclient/rdtclient.log", "Path": "C:/Temp/rdtclient/rdtclient.log",
"Append": "True",
"FileSizeLimitBytes": 5242880, "FileSizeLimitBytes": 5242880,
"MaxRollingFiles": 5 "MaxRollingFiles": 5
} }
@ -10,6 +9,5 @@
"Database": { "Database": {
"Path": "C:/Temp/rdtclient/rdtclient.db" "Path": "C:/Temp/rdtclient/rdtclient.db"
}, },
"AllowedHosts": "*", "Port": "6500"
"HostUrl": "http://0.0.0.0:6500"
} }

View file

@ -2,7 +2,6 @@
"Logging": { "Logging": {
"File": { "File": {
"Path": "/data/db/rdtclient.log", "Path": "/data/db/rdtclient.log",
"Append": "True",
"FileSizeLimitBytes": 5242880, "FileSizeLimitBytes": 5242880,
"MaxRollingFiles": 5 "MaxRollingFiles": 5
} }
@ -10,6 +9,5 @@
"Database": { "Database": {
"Path": "/data/db/rdtclient.db" "Path": "/data/db/rdtclient.db"
}, },
"AllowedHosts": "*", "Port": "6500"
"HostUrl": "http://0.0.0.0:6500"
} }

View file

@ -1,7 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/Browsers/Enable/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/Browsers/Enable/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=48FF995D_002DAD14_002D4E41_002DBC69_002D7A144C84E3B6/@EntryIndexedValue">ExplicitlyExcluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=92EF8817_002DAD73_002D4301_002D93BD_002D745D7D61DD74_002Fd_003AMigrations/@EntryIndexedValue">ExplicitlyExcluded</s:String>
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=_002A_002Eappxmanifest/@EntryIndexedValue">*.appxmanifest</s:String> <s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=_002A_002Eappxmanifest/@EntryIndexedValue">*.appxmanifest</s:String>
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=_002A_002Ed_002Ets/@EntryIndexedValue">*.d.ts</s:String> <s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=_002A_002Ed_002Ets/@EntryIndexedValue">*.d.ts</s:String>
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=_002A_002Edebug_002Ejs/@EntryIndexedValue">*.debug.js</s:String> <s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=_002A_002Edebug_002Ejs/@EntryIndexedValue">*.debug.js</s:String>
@ -29,6 +27,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeLocalFunctionBody/@EntryIndexedValue">SUGGESTION</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeLocalFunctionBody/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeMethodOrOperatorBody/@EntryIndexedValue">SUGGESTION</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeMethodOrOperatorBody/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeModifiersOrder/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeModifiersOrder/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeNamespaceBody/@EntryIndexedValue">ERROR</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeThisQualifier/@EntryIndexedValue">ERROR</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeThisQualifier/@EntryIndexedValue">ERROR</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeMemberModifiers/@EntryIndexedValue">ERROR</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeMemberModifiers/@EntryIndexedValue">ERROR</s:String>
@ -178,6 +177,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HCP/@EntryIndexedValue">HCP</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HCP/@EntryIndexedValue">HCP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QA/@EntryIndexedValue">QA</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QA/@EntryIndexedValue">QA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QB/@EntryIndexedValue">QB</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QB/@EntryIndexedValue">QB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=US/@EntryIndexedValue">US</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XML/@EntryIndexedValue">XML</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XML/@EntryIndexedValue">XML</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>