Merge pull request #36 from AnonymusRaccoon/windows

Supporting windows
This commit is contained in:
Zoe Roux 2021-09-02 14:20:21 +02:00 committed by GitHub
commit 81e0d09135
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
130 changed files with 1100 additions and 425 deletions

View File

@ -1,5 +1,5 @@
name: Analysis name: Analysis
on: [push, pull_request] on: [push, pull_request, workflow_dispatch]
jobs: jobs:
analysis: analysis:

View File

@ -1,5 +1,5 @@
name: Build name: Build
on: [push, pull_request] on: [push, pull_request, workflow_dispatch]
jobs: jobs:
build: build:
@ -10,7 +10,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: ubuntu-latest #ubuntu-16.04 # We are using an old version of ubuntu to have an old libc version (forward compatibility exist but not backward) - os: ubuntu-latest
runtime: linux-x64 runtime: linux-x64
artifact: linux artifact: linux
- os: windows-latest - os: windows-latest
@ -35,13 +35,18 @@ jobs:
elif [[ "${{runner.os}}" == "macOS" ]]; then elif [[ "${{runner.os}}" == "macOS" ]]; then
brew install ffmpeg brew install ffmpeg
else else
# sudo add-apt-repository -y "deb http://azure.archive.ubuntu.com/ubuntu groovy main multiverse restricted universe" sudo apt-get update
sudo apt-get update
sudo apt-get install -y libavutil-dev libavcodec-dev libavformat-dev sudo apt-get install -y libavutil-dev libavcodec-dev libavformat-dev
fi fi
- name: Enabling windows compilations tools - name: Enabling windows compilations tools
if: matrix.artifact == 'windows' if: matrix.artifact == 'windows'
uses: ilammy/msvc-dev-cmd@v1 uses: ilammy/msvc-dev-cmd@v1
- name: Select the project to build
shell: bash
run: |
echo "PROJECT=$([ "${{runner.os}}" == "Windows" ] \
&& echo " -p:IncludeConsole=true Kyoo.Host.WindowsTrait" \
|| echo Kyoo.Host.Console)" >> $GITHUB_ENV
- name: Build the app - name: Build the app
env: env:
INCLUDE: ${{env.INCLUDE}};C:\Program Files\FFmpeg\include INCLUDE: ${{env.INCLUDE}};C:\Program Files\FFmpeg\include
@ -49,7 +54,7 @@ jobs:
LIBPATH: ${{env.LIBPATH}};C:\Program Files\FFmpeg\lib LIBPATH: ${{env.LIBPATH}};C:\Program Files\FFmpeg\lib
CFLAGS: -I/usr/local/include CFLAGS: -I/usr/local/include
LDFLAGS: -L/usr/local/lib LDFLAGS: -L/usr/local/lib
run: dotnet publish -r ${{matrix.runtime}} -c Release -o dist Kyoo run: dotnet publish -r ${{matrix.runtime}} -c Release -o dist ${{env.PROJECT}}
- name: Compression output - name: Compression output
shell: bash shell: bash
run: | run: |
@ -69,7 +74,34 @@ jobs:
path: | path: |
*.zip *.zip
*.tar.gz *.tar.gz
windows_release:
name: Create windows release
runs-on: windows-latest
needs: build
if: github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v1
- name: Download windows build
uses: actions/download-artifact@v2
with:
name: kyoo_windows
path: artifact
- name: Unzip windows files
run: mkdir dist_win && 7z x artifact/kyoo_windows.zip -odist_win
- name: Install Inno Setup
shell: cmd
run: |
curl -L https://jrsoftware.org/download.php/is.exe > innosetup.exe
innosetup.exe /VERYSILENT /SUPPRESSMSGBOXES /Log=log.txt || (cat log.txt && exit 1)
- name: Create windows installer
shell: bash
run: iscc -Dkyoo=$(realpath dist_win) -O./ -Fkyoo-windows deployment/kyoo-windows.iss
- uses: actions/upload-artifact@v2
with:
name: kyoo_windows_installer
path: ./kyoo-windows.exe
release: release:
name: Create debian, rpm & arch releases name: Create debian, rpm & arch releases
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -80,7 +112,8 @@ jobs:
version: v0.0.1 #${{ github.ref }} version: v0.0.1 #${{ github.ref }}
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/download-artifact@v2 - name: Download linux build
uses: actions/download-artifact@v2
with: with:
name: kyoo_linux name: kyoo_linux
path: artifact path: artifact
@ -89,19 +122,18 @@ jobs:
- name: Create the package structure - name: Create the package structure
run: | run: |
sudo mkdir -p pkg/usr/lib/ sudo mkdir -p pkg/usr/lib/
sudo mkdir -p pkg/DEBIAN
sudo cp -r --no-preserve ownership dist pkg/usr/lib/kyoo sudo cp -r --no-preserve ownership dist pkg/usr/lib/kyoo
sudo install -Dm 644 deployment/kyoo.service -t pkg/usr/lib/systemd/system/ sudo install -Dm 644 deployment/kyoo.service -t pkg/usr/lib/systemd/system/
sudo install -Dm 644 deployment/kyoo.sysusers pkg/usr/lib/sysusers.d/kyoo.conf sudo install -Dm 644 deployment/kyoo.sysusers pkg/usr/lib/sysusers.d/kyoo.conf
sudo install -Dm 644 deployment/kyoo.tmpfiles pkg/usr/lib/tmpfiles.d/kyoo.conf sudo install -Dm 644 deployment/kyoo.tmpfiles pkg/usr/lib/tmpfiles.d/kyoo.conf
sudo install -Dm 755 deployment/postinst -t pkg/DEBIAN/ - name: Build debian package
- uses: jiro4989/build-deb-action@v2 uses: jiro4989/build-deb-action@v2
with: with:
package: kyoo package: kyoo
package_root: pkg package_root: pkg
maintainer: Zoe Roux <zoe.roux@sdg.moe> maintainer: Zoe Roux <zoe.roux@sdg.moe>
version: ${{env.version}} version: ${{env.version}}
depends: "postgresql, libavutil-dev, libavcodec-dev, libavformat-dev" depends: "libavutil-dev, libavcodec-dev, libavformat-dev"
arch: amd64 arch: amd64
desc: ${{env.description}} desc: ${{env.description}}
- name: Build rpm package - name: Build rpm package

View File

@ -1,6 +1,5 @@
name: Docker name: Docker
on: [push, pull_request, workflow_dispatch]
on: [push, pull_request]
jobs: jobs:
build: build:

View File

@ -0,0 +1,31 @@
namespace Kyoo.Abstractions.Controllers
{
/// <summary>
/// An interface that allow one to interact with the host and shutdown or restart the app.
/// </summary>
public interface IApplication
{
/// <summary>
/// Shutdown the process and stop gracefully.
/// </summary>
void Shutdown();
/// <summary>
/// Restart Kyoo from scratch, reload plugins, configurations and restart the web server.
/// </summary>
void Restart();
/// <summary>
/// Get the data directory
/// </summary>
/// <returns>Retrieve the data directory where runtime data should be stored</returns>
string GetDataDirectory();
/// <summary>
/// Retrieve the path of the json configuration file
/// (relative to the data directory, see <see cref="GetDataDirectory"/>).
/// </summary>
/// <returns>The configuration file name.</returns>
string GetConfigFile();
}
}

View File

@ -93,14 +93,5 @@ namespace Kyoo.Abstractions.Controllers
{ {
// Skipped // Skipped
} }
/// <summary>
/// An optional callback function called when the startups ends and this plugin has been flagged has disabled.
/// It allow a plugin to log an error or warning message to inform why it has been disabled.
/// </summary>
void Disabled()
{
// Skipped
}
} }
} }

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Utils;
namespace Kyoo.Abstractions.Controllers namespace Kyoo.Abstractions.Controllers
{ {

View File

@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>Kyoo.Abstractions</Title> <Title>Kyoo.Abstractions</Title>
<Authors>Zoe Roux</Authors> <Authors>Zoe Roux</Authors>
<Description>Base package to create plugins for Kyoo.</Description> <Description>Base package to create plugins for Kyoo.</Description>

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using JetBrains.Annotations; using JetBrains.Annotations;
using Kyoo.Utils;
namespace Kyoo.Abstractions.Models namespace Kyoo.Abstractions.Models
{ {

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Kyoo.Utils;
namespace Kyoo.Abstractions.Models namespace Kyoo.Abstractions.Models
{ {

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Utils;
namespace Kyoo.Abstractions.Models namespace Kyoo.Abstractions.Models
{ {

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Utils;
namespace Kyoo.Abstractions.Models namespace Kyoo.Abstractions.Models
{ {

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Utils;
namespace Kyoo.Abstractions.Models namespace Kyoo.Abstractions.Models
{ {

View File

@ -1,6 +1,7 @@
using Autofac; using Autofac;
using Autofac.Builder; using Autofac.Builder;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Utils;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
namespace Kyoo.Abstractions namespace Kyoo.Abstractions

View File

@ -4,7 +4,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Kyoo namespace Kyoo.Utils
{ {
/// <summary> /// <summary>
/// A set of extensions class for enumerable. /// A set of extensions class for enumerable.

View File

@ -8,7 +8,7 @@ using JetBrains.Annotations;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
namespace Kyoo namespace Kyoo.Utils
{ {
/// <summary> /// <summary>
/// A class containing helper methods to merge objects. /// A class containing helper methods to merge objects.

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Reflection; using System.Reflection;
namespace Kyoo namespace Kyoo.Utils
{ {
/// <summary> /// <summary>
/// Static class containing MethodOf calls. /// Static class containing MethodOf calls.

View File

@ -2,7 +2,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Kyoo namespace Kyoo.Utils
{ {
/// <summary> /// <summary>
/// A class containing helper method for tasks. /// A class containing helper method for tasks.

View File

@ -9,7 +9,7 @@ using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Kyoo namespace Kyoo.Utils
{ {
/// <summary> /// <summary>
/// A set of utility functions that can be used everywhere. /// A set of utility functions that can be used everywhere.

View File

@ -110,6 +110,14 @@ namespace Kyoo.Authentication
CertificateOption certificateOptions = new(); CertificateOption certificateOptions = new();
_configuration.GetSection(CertificateOption.Path).Bind(certificateOptions); _configuration.GetSection(CertificateOption.Path).Bind(certificateOptions);
clients.AddRange(IdentityContext.GetClients());
foreach (Client client in clients)
{
client.RedirectUris = client.RedirectUris
.Select(x => x.StartsWith("/") ? publicUrl + x : x)
.ToArray();
}
services.AddIdentityServer(options => services.AddIdentityServer(options =>
{ {
options.IssuerUri = publicUrl; options.IssuerUri = publicUrl;
@ -120,7 +128,7 @@ namespace Kyoo.Authentication
.AddInMemoryIdentityResources(IdentityContext.GetIdentityResources()) .AddInMemoryIdentityResources(IdentityContext.GetIdentityResources())
.AddInMemoryApiScopes(IdentityContext.GetScopes()) .AddInMemoryApiScopes(IdentityContext.GetScopes())
.AddInMemoryApiResources(IdentityContext.GetApis()) .AddInMemoryApiResources(IdentityContext.GetApis())
.AddInMemoryClients(IdentityContext.GetClients().Concat(clients)) .AddInMemoryClients(clients)
.AddProfileService<AccountApi>() .AddProfileService<AccountApi>()
.AddSigninKeys(certificateOptions); .AddSigninKeys(certificateOptions);

View File

@ -22,7 +22,7 @@
<ItemGroup> <ItemGroup>
<None Remove="$(LoginRoot)**;" /> <None Remove="$(LoginRoot)**;" />
<Content Include="$(LoginRoot)**"> <Content Include="$(LoginRoot)**" Visible="false">
<Link>login/%(RecursiveDir)%(Filename)%(Extension)</Link> <Link>login/%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Utils;
namespace Kyoo.Authentication.Models.DTO namespace Kyoo.Authentication.Models.DTO
{ {

276
Kyoo.Core/Application.cs Normal file
View File

@ -0,0 +1,276 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using JetBrains.Annotations;
using Kyoo.Abstractions.Controllers;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Win32;
using Serilog;
using Serilog.Templates;
using Serilog.Templates.Themes;
using ILogger = Serilog.ILogger;
namespace Kyoo.Core
{
public class Application : IApplication
{
/// <summary>
/// The path to the data directory.
/// </summary>
private string _dataDir;
/// <summary>
/// Should the application restart after a shutdown?
/// </summary>
private bool _shouldRestart;
/// <summary>
/// The cancellation token source used to allow the app to be shutdown or restarted.
/// </summary>
private CancellationTokenSource _tokenSource;
/// <summary>
/// The environment in witch Kyoo will run (ether "Production" or "Development").
/// </summary>
private readonly string _environment;
/// <summary>
/// The logger used for startup and error messages.
/// </summary>
private ILogger _logger;
/// <summary>
/// Create a new <see cref="Application"/> that will use the specified environment.
/// </summary>
/// <param name="environment">The environment to run in.</param>
public Application(string environment)
{
_environment = environment;
}
/// <summary>
/// Start the application with the given console args.
/// This is generally called from the Main entrypoint of Kyoo.
/// </summary>
/// <param name="args">The console arguments to use for kyoo.</param>
/// <returns>A task representing the whole process</returns>
public Task Start(string[] args)
{
return Start(args, _ => { });
}
/// <summary>
/// Start the application with the given console args.
/// This is generally called from the Main entrypoint of Kyoo.
/// </summary>
/// <param name="args">The console arguments to use for kyoo.</param>
/// <param name="configure">A custom action to configure the container before the start</param>
/// <returns>A task representing the whole process</returns>
public async Task Start(string[] args, Action<ContainerBuilder> configure)
{
_dataDir = _SetupDataDir(args);
LoggerConfiguration config = new();
_ConfigureLogging(config, null, null);
Log.Logger = config.CreateBootstrapLogger();
_logger = Log.Logger.ForContext<Application>();
AppDomain.CurrentDomain.ProcessExit += (_, _) => Log.CloseAndFlush();
AppDomain.CurrentDomain.UnhandledException += (_, ex)
=> Log.Fatal(ex.ExceptionObject as Exception, "Unhandled exception");
do
{
IHost host = _CreateWebHostBuilder(args)
.ConfigureContainer(configure)
.Build();
_tokenSource = new CancellationTokenSource();
await _StartWithHost(host, _tokenSource.Token);
}
while (_shouldRestart);
}
/// <inheritdoc />
public void Shutdown()
{
_shouldRestart = false;
_tokenSource.Cancel();
}
/// <inheritdoc />
public void Restart()
{
_shouldRestart = true;
_tokenSource.Cancel();
}
/// <inheritdoc />
public string GetDataDirectory()
{
return _dataDir;
}
/// <inheritdoc />
public string GetConfigFile()
{
return "./settings.json";
}
/// <summary>
/// Parse the data directory from environment variables and command line arguments, create it if necessary.
/// Set the current directory to said data folder and place a default configuration file if it does not already
/// exists.
/// </summary>
/// <param name="args">The command line arguments</param>
/// <returns>The current data directory.</returns>
private string _SetupDataDir(string[] args)
{
Dictionary<string, string> registry = new();
if (OperatingSystem.IsWindows())
{
object dataDir = Registry.GetValue(@"HKEY_LOCAL_MACHINE\Software\SDG\Kyoo\Settings", "DataDir", null)
?? Registry.GetValue(@"HKEY_CURRENT_USER\Software\SDG\Kyoo\Settings", "DataDir", null);
if (dataDir is string data)
registry.Add("DataDir", data);
}
IConfiguration parsed = new ConfigurationBuilder()
.AddInMemoryCollection(registry)
.AddEnvironmentVariables()
.AddEnvironmentVariables("KYOO_")
.AddCommandLine(args)
.Build();
string path = parsed.GetValue<string>("datadir")
?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Kyoo");
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
Environment.CurrentDirectory = path;
if (!File.Exists(GetConfigFile()))
File.Copy(Path.Join(AppDomain.CurrentDomain.BaseDirectory, GetConfigFile()),
GetConfigFile());
return path;
}
/// <summary>
/// Start the given host and log failing exceptions.
/// </summary>
/// <param name="host">The host to start.</param>
/// <param name="cancellationToken">A token to allow one to stop the host.</param>
private async Task _StartWithHost(IHost host, CancellationToken cancellationToken)
{
try
{
_logger.Information("Running as {Name}", Environment.UserName);
_logger.Information("Data directory: {DataDirectory}", GetDataDirectory());
await host.RunAsync(cancellationToken);
}
catch (Exception ex)
{
_logger.Fatal(ex, "Unhandled exception");
}
}
/// <summary>
/// Create a a web host
/// </summary>
/// <param name="args">Command line parameters that can be handled by kestrel</param>
/// <returns>A new web host instance</returns>
private IHostBuilder _CreateWebHostBuilder(string[] args)
{
IConfiguration configuration = _SetupConfig(new ConfigurationBuilder(), args).Build();
return new HostBuilder()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
.UseEnvironment(_environment)
.ConfigureAppConfiguration(x => _SetupConfig(x, args))
.UseSerilog((host, services, builder) => _ConfigureLogging(builder, host.Configuration, services))
.ConfigureServices(x => x.AddRouting())
.ConfigureContainer<ContainerBuilder>(x =>
{
x.RegisterInstance(this).As<IApplication>().SingleInstance().ExternallyOwned();
})
.ConfigureWebHost(x => x
.UseKestrel(options => { options.AddServerHeader = false; })
.UseIIS()
.UseIISIntegration()
.UseUrls(configuration.GetValue<string>("basics:url"))
.UseStartup(host => PluginsStartup.FromWebHost(host, new LoggerFactory().AddSerilog()))
);
}
/// <summary>
/// Register settings.json, environment variables and command lines arguments as configuration.
/// </summary>
/// <param name="builder">The configuration builder to use</param>
/// <param name="args">The command line arguments</param>
/// <returns>The modified configuration builder</returns>
private IConfigurationBuilder _SetupConfig(IConfigurationBuilder builder, string[] args)
{
return builder.SetBasePath(GetDataDirectory())
.AddJsonFile(Path.Join(AppDomain.CurrentDomain.BaseDirectory, GetConfigFile()), false, true)
.AddJsonFile(GetConfigFile(), false, true)
.AddEnvironmentVariables()
.AddEnvironmentVariables("KYOO_")
.AddCommandLine(args);
}
/// <summary>
/// Configure the logging.
/// </summary>
/// <param name="builder">The logger builder to configure.</param>
/// <param name="configuration">The configuration to read settings from.</param>
/// <param name="services">The services to read configuration from.</param>
private void _ConfigureLogging(LoggerConfiguration builder,
[CanBeNull] IConfiguration configuration,
[CanBeNull] IServiceProvider services)
{
if (configuration != null)
{
try
{
builder.ReadFrom.Configuration(configuration, "logging");
}
catch (Exception ex)
{
_logger.Fatal(ex, "Could not read serilog configuration");
}
}
if (services != null)
builder.ReadFrom.Services(services);
const string template =
"[{@t:HH:mm:ss} {@l:u3} {Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1), 15} "
+ "({@i:0000000000})] {@m}{#if not EndsWith(@m, '\n')}\n{#end}{@x}";
builder
.WriteTo.Console(new ExpressionTemplate(template, theme: TemplateTheme.Code))
.WriteTo.File(
path: Path.Combine(GetDataDirectory(), "logs", "log-.log"),
formatter: new ExpressionTemplate(template),
rollingInterval: RollingInterval.Day,
rollOnFileSizeLimit: true
)
.Enrich.WithThreadId()
.Enrich.FromLogContext();
}
}
}

View File

@ -8,11 +8,11 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Api; using Kyoo.Core.Api;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
public class ConfigurationManager : IConfigurationManager public class ConfigurationManager : IConfigurationManager
{ {
@ -21,6 +21,11 @@ namespace Kyoo.Controllers
/// </summary> /// </summary>
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;
/// <summary>
/// The application running Kyoo, it is used to retrieve the configuration file.
/// </summary>
private readonly IApplication _application;
/// <summary> /// <summary>
/// The strongly typed list of options /// The strongly typed list of options
/// </summary> /// </summary>
@ -31,9 +36,11 @@ namespace Kyoo.Controllers
/// </summary> /// </summary>
/// <param name="configuration">The configuration to use.</param> /// <param name="configuration">The configuration to use.</param>
/// <param name="references">The strongly typed option list.</param> /// <param name="references">The strongly typed option list.</param>
public ConfigurationManager(IConfiguration configuration, IEnumerable<ConfigurationReference> references) /// <param name="application">The application running Kyoo, it is used to retrieve the configuration file.</param>
public ConfigurationManager(IConfiguration configuration, IEnumerable<ConfigurationReference> references, IApplication application)
{ {
_configuration = configuration; _configuration = configuration;
_application = application;
_references = references.ToDictionary(x => x.Path, x => x.Type, StringComparer.OrdinalIgnoreCase); _references = references.ToDictionary(x => x.Path, x => x.Type, StringComparer.OrdinalIgnoreCase);
} }
@ -131,7 +138,7 @@ namespace Kyoo.Controllers
IDictionary<string, object> configDic = config; IDictionary<string, object> configDic = config;
configDic[path] = value; configDic[path] = value;
JObject obj = JObject.FromObject(config); JObject obj = JObject.FromObject(config);
await using StreamWriter writer = new(Program.JsonConfigPath); await using StreamWriter writer = new(_application.GetConfigFile());
await writer.WriteAsync(obj.ToString()); await writer.WriteAsync(obj.ToString());
} }

View File

@ -9,11 +9,11 @@ using JetBrains.Annotations;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A composite that merge every <see cref="IFileSystem"/> available /// A composite that merge every <see cref="IFileSystem"/> available

View File

@ -9,7 +9,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A <see cref="IFileSystem"/> for http/https links. /// A <see cref="IFileSystem"/> for http/https links.

View File

@ -5,12 +5,12 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A <see cref="IFileSystem"/> for the local filesystem (using System.IO). /// A <see cref="IFileSystem"/> for the local filesystem (using System.IO).

View File

@ -6,8 +6,9 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Utils;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
public class LibraryManager : ILibraryManager public class LibraryManager : ILibraryManager
{ {

View File

@ -2,7 +2,7 @@ using Kyoo.Abstractions.Models.Permissions;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A permission validator that always validate permissions. This effectively disable the permission system. /// A permission validator that always validate permissions. This effectively disable the permission system.

View File

@ -5,12 +5,12 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.Loader; using System.Runtime.Loader;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// An implementation of <see cref="IPluginManager"/>. /// An implementation of <see cref="IPluginManager"/>.
@ -21,7 +21,7 @@ namespace Kyoo.Controllers
/// <summary> /// <summary>
/// The service provider. It allow plugin's activation. /// The service provider. It allow plugin's activation.
/// </summary> /// </summary>
private IServiceProvider _provider; private readonly IServiceProvider _provider;
/// <summary> /// <summary>
/// The configuration to get the plugin's directory. /// The configuration to get the plugin's directory.
/// </summary> /// </summary>
@ -51,14 +51,6 @@ namespace Kyoo.Controllers
_logger = logger; _logger = logger;
} }
public void SetProvider(IServiceProvider provider)
{
// TODO temporary bullshit to inject services before the configure asp net.
// TODO should rework this when the host will be reworked, as well as the asp net configure.
_provider = provider;
}
/// <inheritdoc /> /// <inheritdoc />
public T GetPlugin<T>(string name) public T GetPlugin<T>(string name)
{ {
@ -111,16 +103,13 @@ namespace Kyoo.Controllers
_logger.LogTrace("Loading new plugins..."); _logger.LogTrace("Loading new plugins...");
string[] pluginsPaths = Directory.GetFiles(pluginFolder, "*.dll", SearchOption.AllDirectories); string[] pluginsPaths = Directory.GetFiles(pluginFolder, "*.dll", SearchOption.AllDirectories);
IPlugin[] newPlugins = plugins _plugins.AddRange(plugins
.Concat(pluginsPaths.SelectMany(LoadPlugin)) .Concat(pluginsPaths.SelectMany(LoadPlugin))
.Where(x => x.Enabled)
.GroupBy(x => x.Name) .GroupBy(x => x.Name)
.Select(x => x.First()) .Select(x => x.First())
.ToArray(); );
_plugins.AddRange(newPlugins.Where(x => x.Enabled));
foreach (IPlugin plugin in newPlugins.Where(x => !x.Enabled))
plugin.Disabled();
if (!_plugins.Any()) if (!_plugins.Any())
_logger.LogInformation("No plugin enabled"); _logger.LogInformation("No plugin enabled");
else else

View File

@ -4,9 +4,10 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A metadata provider composite that merge results from all available providers. /// A metadata provider composite that merge results from all available providers.

View File

@ -7,11 +7,12 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Kyoo.Models.Watch; using Kyoo.Core.Models.Watch;
using Kyoo.Utils;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// An identifier that use a regex to extract basics metadata. /// An identifier that use a regex to extract basics metadata.

View File

@ -8,7 +8,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Database; using Kyoo.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle collections /// A local repository to handle collections

View File

@ -7,9 +7,10 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Database; using Kyoo.Database;
using Kyoo.Utils;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle episodes. /// A local repository to handle episodes.

View File

@ -8,7 +8,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Database; using Kyoo.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository for genres. /// A local repository for genres.

View File

@ -9,7 +9,7 @@ using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Database; using Kyoo.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle library items. /// A local repository to handle library items.

View File

@ -6,9 +6,10 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Database; using Kyoo.Database;
using Kyoo.Utils;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle libraries. /// A local repository to handle libraries.

View File

@ -8,10 +8,11 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Api; using Kyoo.Utils;
using Kyoo.Core.Api;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A base class to create repositories using Entity Framework. /// A base class to create repositories using Entity Framework.

View File

@ -7,9 +7,10 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Database; using Kyoo.Database;
using Kyoo.Utils;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle people. /// A local repository to handle people.

View File

@ -8,7 +8,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Database; using Kyoo.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle providers. /// A local repository to handle providers.

View File

@ -9,7 +9,7 @@ using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Database; using Kyoo.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle seasons. /// A local repository to handle seasons.

View File

@ -5,10 +5,11 @@ using System.Linq.Expressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using Kyoo.Database; using Kyoo.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle shows /// A local repository to handle shows

View File

@ -8,7 +8,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Database; using Kyoo.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle studios /// A local repository to handle studios

View File

@ -7,7 +7,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Database; using Kyoo.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A local repository to handle tracks. /// A local repository to handle tracks.

View File

@ -8,7 +8,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Database; using Kyoo.Database;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A repository for users. /// A repository for users.

View File

@ -10,12 +10,12 @@ using JetBrains.Annotations;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// A service to handle long running tasks and a background runner. /// A service to handle long running tasks and a background runner.

View File

@ -7,7 +7,7 @@ using Kyoo.Abstractions.Models;
using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary> /// <summary>
/// Download images and retrieve the path of those images for a resource. /// Download images and retrieve the path of those images for a resource.

View File

@ -4,14 +4,14 @@ using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Stream = Kyoo.Models.Watch.Stream; using Stream = Kyoo.Core.Models.Watch.Stream;
// We use threads so tasks are not always awaited. // We use threads so tasks are not always awaited.
#pragma warning disable 4014 #pragma warning disable 4014
namespace Kyoo.Controllers namespace Kyoo.Core.Controllers
{ {
public class BadTranscoderException : Exception {} public class BadTranscoderException : Exception {}
@ -22,29 +22,40 @@ namespace Kyoo.Controllers
private const string TranscoderPath = "transcoder"; private const string TranscoderPath = "transcoder";
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
public static extern int init(); private static extern int init();
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] public static int Init() => init();
public static extern int transmux(string path, string outpath, out float playableDuration);
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
public static extern int transcode(string path, string outpath, out float playableDuration);
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
private static extern int transmux(string path, string outpath, out float playableDuration);
public static int Transmux(string path, string outPath, out float playableDuration)
{
path = path.Replace('\\', '/');
outPath = outPath.Replace('\\', '/');
return transmux(path, outPath, out playableDuration);
}
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
private static extern IntPtr extract_infos(string path, private static extern IntPtr extract_infos(string path,
string outpath, string outpath,
out int length, out uint length,
out int trackCount, out uint trackCount,
bool reextracct); bool reextracct);
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
private static extern void free(IntPtr ptr); private static extern void free_streams(IntPtr streams, uint count);
public static Track[] ExtractInfos(string path, string outPath, bool reextract) public static Track[] ExtractInfos(string path, string outPath, bool reextract)
{ {
int size = Marshal.SizeOf<Stream>(); path = path.Replace('\\', '/');
IntPtr ptr = extract_infos(path, outPath, out int arrayLength, out int trackCount, reextract); outPath = outPath.Replace('\\', '/');
int size = Marshal.SizeOf<Models.Watch.Stream>();
IntPtr ptr = extract_infos(path, outPath, out uint arrayLength, out uint trackCount, reextract);
IntPtr streamsPtr = ptr; IntPtr streamsPtr = ptr;
Track[] tracks; Track[] tracks;
@ -55,7 +66,7 @@ namespace Kyoo.Controllers
int j = 0; int j = 0;
for (int i = 0; i < arrayLength; i++) for (int i = 0; i < arrayLength; i++)
{ {
Stream stream = Marshal.PtrToStructure<Stream>(streamsPtr); Models.Watch.Stream stream = Marshal.PtrToStructure<Models.Watch.Stream>(streamsPtr);
if (stream!.Type != StreamType.Unknown) if (stream!.Type != StreamType.Unknown)
{ {
tracks[j] = stream.ToTrack(); tracks[j] = stream.ToTrack();
@ -68,7 +79,7 @@ namespace Kyoo.Controllers
tracks = Array.Empty<Track>(); tracks = Array.Empty<Track>();
if (ptr != IntPtr.Zero) if (ptr != IntPtr.Zero)
free(ptr); // free_streams is not necessary since the Marshal free the unmanaged pointers. free_streams(ptr, trackCount);
return tracks; return tracks;
} }
} }
@ -83,7 +94,7 @@ namespace Kyoo.Controllers
_options = options; _options = options;
_library = library; _library = library;
if (TranscoderAPI.init() != Marshal.SizeOf<Stream>()) if (TranscoderAPI.Init() != Marshal.SizeOf<Models.Watch.Stream>())
throw new BadTranscoderException(); throw new BadTranscoderException();
} }
@ -122,8 +133,7 @@ namespace Kyoo.Controllers
Task.Factory.StartNew(() => Task.Factory.StartNew(() =>
{ {
string cleanManifest = manifest.Replace('\\', '/'); transmuxFailed = TranscoderAPI.Transmux(episode.Path, manifest, out playableDuration) != 0;
transmuxFailed = TranscoderAPI.transmux(episode.Path, cleanManifest, out playableDuration) != 0;
}, TaskCreationOptions.LongRunning); }, TaskCreationOptions.LongRunning);
while (playableDuration < 10 || !File.Exists(manifest) && !transmuxFailed) while (playableDuration < 10 || !File.Exists(manifest) && !transmuxFailed)
await Task.Delay(10); await Task.Delay(10);

View File

@ -7,19 +7,20 @@ using Autofac.Extras.AttributeMetadata;
using Kyoo.Abstractions; using Kyoo.Abstractions;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Api; using Kyoo.Core.Api;
using Kyoo.Controllers; using Kyoo.Core.Controllers;
using Kyoo.Core.Models.Options;
using Kyoo.Core.Tasks;
using Kyoo.Database; using Kyoo.Database;
using Kyoo.Models.Options;
using Kyoo.Tasks;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Serilog;
using IMetadataProvider = Kyoo.Abstractions.Controllers.IMetadataProvider; using IMetadataProvider = Kyoo.Abstractions.Controllers.IMetadataProvider;
namespace Kyoo namespace Kyoo.Core
{ {
/// <summary> /// <summary>
/// The core module containing default implementations /// The core module containing default implementations
@ -70,10 +71,11 @@ namespace Kyoo
builder.RegisterType<LocalFileSystem>().As<IFileSystem>().SingleInstance(); builder.RegisterType<LocalFileSystem>().As<IFileSystem>().SingleInstance();
builder.RegisterType<HttpFileSystem>().As<IFileSystem>().SingleInstance(); builder.RegisterType<HttpFileSystem>().As<IFileSystem>().SingleInstance();
builder.RegisterType<TaskManager>().As<ITaskManager>().As<IHostedService>().SingleInstance();
builder.RegisterType<ConfigurationManager>().As<IConfigurationManager>().SingleInstance(); builder.RegisterType<ConfigurationManager>().As<IConfigurationManager>().SingleInstance();
builder.RegisterType<Transcoder>().As<ITranscoder>().SingleInstance(); builder.RegisterType<Transcoder>().As<ITranscoder>().SingleInstance();
builder.RegisterType<ThumbnailsManager>().As<IThumbnailsManager>().InstancePerLifetimeScope(); builder.RegisterType<ThumbnailsManager>().As<IThumbnailsManager>().InstancePerLifetimeScope();
builder.RegisterType<TaskManager>().As<ITaskManager>().SingleInstance();
builder.RegisterType<LibraryManager>().As<ILibraryManager>().InstancePerLifetimeScope(); builder.RegisterType<LibraryManager>().As<ILibraryManager>().InstancePerLifetimeScope();
builder.RegisterType<RegexIdentifier>().As<IIdentifier>().SingleInstance(); builder.RegisterType<RegexIdentifier>().As<IIdentifier>().SingleInstance();
@ -135,8 +137,6 @@ namespace Kyoo
}); });
services.AddHttpClient(); services.AddHttpClient();
services.AddHostedService(x => x.GetService<ITaskManager>() as TaskManager);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -152,6 +152,7 @@ namespace Kyoo
app.UseHsts(); app.UseHsts();
} }
}, SA.Before), }, SA.Before),
SA.New<IApplicationBuilder>(app => app.UseSerilogRequestLogging(), SA.Before),
SA.New<IApplicationBuilder>(app => app.UseResponseCompression(), SA.Routing + 1), SA.New<IApplicationBuilder>(app => app.UseResponseCompression(), SA.Routing + 1),
SA.New<IApplicationBuilder>(app => app.UseRouting(), SA.Routing), SA.New<IApplicationBuilder>(app => app.UseRouting(), SA.Routing),
SA.New<IApplicationBuilder>(app => app.UseEndpoints(x => x.MapControllers()), SA.Endpoint) SA.New<IApplicationBuilder>(app => app.UseEndpoints(x => x.MapControllers()), SA.Endpoint)

View File

@ -2,7 +2,7 @@ using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Kyoo namespace Kyoo.Core
{ {
public static class Helper public static class Helper
{ {

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
@ -7,10 +7,9 @@
<Company>SDG</Company> <Company>SDG</Company>
<Authors>Zoe Roux</Authors> <Authors>Zoe Roux</Authors>
<RepositoryUrl>https://github.com/AnonymusRaccoon/Kyoo</RepositoryUrl> <RepositoryUrl>https://github.com/AnonymusRaccoon/Kyoo</RepositoryUrl>
<StartupObject>Kyoo.Program</StartupObject>
<LangVersion>default</LangVersion> <LangVersion>default</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<IsWindows Condition="$([MSBuild]::IsOSPlatform('Windows'))">true</IsWindows> <IsWindows Condition="$([MSBuild]::IsOSPlatform('Windows'))">true</IsWindows>
<IsOSX Condition="$([MSBuild]::IsOSPlatform('OSX'))">true</IsOSX> <IsOSX Condition="$([MSBuild]::IsOSPlatform('OSX'))">true</IsOSX>
@ -18,12 +17,16 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<TranscoderBinary Condition="'$(IsWindows)' == 'true'">transcoder.dll</TranscoderBinary> <TranscoderBinary Condition="$(IsWindows) == true">transcoder.dll</TranscoderBinary>
<TranscoderBinary Condition="'$(IsOSX)' == 'true'">libtranscoder.dylib</TranscoderBinary> <TranscoderBinary Condition="$(IsOSX) == true">libtranscoder.dylib</TranscoderBinary>
<TranscoderBinary Condition="'$(IsLinux)' == 'true'">libtranscoder.so</TranscoderBinary> <TranscoderBinary Condition="$(IsLinux) == true">libtranscoder.so</TranscoderBinary>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageReference Include="Serilog.Expressions" Version="3.2.0" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" /> <PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
<PackageReference Include="Autofac" Version="6.2.0" /> <PackageReference Include="Autofac" Version="6.2.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
@ -35,7 +38,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="../Kyoo.Abstractions/Kyoo.Abstractions.csproj" /> <ProjectReference Include="../Kyoo.Abstractions/Kyoo.Abstractions.csproj" />
<ProjectReference Include="..\Kyoo.Database\Kyoo.Database.csproj" /> <ProjectReference Include="../Kyoo.Database/Kyoo.Database.csproj" />
<ProjectReference Include="../Kyoo.TheMovieDb/Kyoo.TheMovieDb.csproj" /> <ProjectReference Include="../Kyoo.TheMovieDb/Kyoo.TheMovieDb.csproj" />
<ProjectReference Include="../Kyoo.TheTvdb/Kyoo.TheTvdb.csproj" /> <ProjectReference Include="../Kyoo.TheTvdb/Kyoo.TheTvdb.csproj" />
<ProjectReference Include="../Kyoo.Postgresql/Kyoo.Postgresql.csproj" /> <ProjectReference Include="../Kyoo.Postgresql/Kyoo.Postgresql.csproj" />
@ -44,9 +47,14 @@
<ProjectReference Include="../Kyoo.WebApp/Kyoo.WebApp.csproj" /> <ProjectReference Include="../Kyoo.WebApp/Kyoo.WebApp.csproj" />
</ItemGroup> </ItemGroup>
<Target Name="BuildTranscoder" BeforeTargets="BeforeBuild" Condition="'$(SkipTranscoder)' != 'true'"> <Target Name="BuildTranscoder" BeforeTargets="BeforeBuild" Condition="'$(SkipTranscoder)' != 'true' And !Exists('$(TranscoderRoot)/build/$(TranscoderBinary)')">
<Exec WorkingDirectory="$(TranscoderRoot)" Condition="'$(IsWindows)' != 'true'" Command="mkdir -p build %26%26 cd build %26%26 cmake .. %26%26 make -j" /> <Exec WorkingDirectory="$(TranscoderRoot)" Condition="'$(IsWindows)' != 'true'" Command="mkdir -p build %26%26 cd build %26%26 cmake .. %26%26 make -j" ContinueOnError="true">
<Exec WorkingDirectory="$(TranscoderRoot)" Condition="'$(IsWindows)' == 'true'" Command="(if not exist build mkdir build) %26%26 cd build %26%26 cmake .. -G &quot;NMake Makefiles&quot; %26%26 nmake" /> <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Exec WorkingDirectory="$(TranscoderRoot)" Condition="'$(IsWindows)' == 'true'" Command="(if not exist build mkdir build) %26%26 cd build %26%26 cmake .. -G &quot;NMake Makefiles&quot; %26%26 nmake" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="An environement capable of building the transcoder was not found. Appropriate tools are not installed, not available in the $PATH or not correctly configured. To fix this you can ether:&#xA; - Fix your tools&#xA; - Skip the transcoder via the '-p:SkipTranscoder=true'&#xA; - Download an already built transcoder and put it in ./Kyoo.Transcoder/build" />
</Target> </Target>
<ItemGroup Condition="'$(SkipTranscoder)' != 'true'"> <ItemGroup Condition="'$(SkipTranscoder)' != 'true'">
@ -55,4 +63,9 @@
<Visible>false</Visible> <Visible>false</Visible>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="../LICENSE" CopyToOutputDirectory="Always" Visible="false" />
<Content Include="settings.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project> </Project>

View File

@ -2,7 +2,7 @@ using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.IO; using System.IO;
namespace Kyoo.Models.Watch namespace Kyoo.Core.Models.Watch
{ {
/// <summary> /// <summary>
/// A static class allowing one to identify files extensions. /// A static class allowing one to identify files extensions.

View File

@ -1,7 +1,7 @@
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using System; using System;
namespace Kyoo.Models.Options namespace Kyoo.Core.Models.Options
{ {
/// <summary> /// <summary>
/// The typed list of basic/global options for Kyoo /// The typed list of basic/global options for Kyoo

View File

@ -1,4 +1,4 @@
namespace Kyoo.Models.Options namespace Kyoo.Core.Models.Options
{ {
/// <summary> /// <summary>
/// Options for media registering. /// Options for media registering.

View File

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Kyoo.Models.Options namespace Kyoo.Core.Models.Options
{ {
/// <summary> /// <summary>
/// Options related to tasks /// Options related to tasks

View File

@ -2,7 +2,7 @@ using System.Runtime.InteropServices;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
namespace Kyoo.Models.Watch namespace Kyoo.Core.Models.Watch
{ {
/// <summary> /// <summary>
/// The unmanaged stream that the transcoder will return. /// The unmanaged stream that the transcoder will return.

View File

@ -5,13 +5,14 @@ using Autofac;
using Kyoo.Abstractions; using Kyoo.Abstractions;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Authentication; using Kyoo.Authentication;
using Kyoo.Controllers; using Kyoo.Core.Controllers;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Kyoo.Core.Tasks;
using Kyoo.Postgresql; using Kyoo.Postgresql;
using Kyoo.SqLite; using Kyoo.SqLite;
using Kyoo.Tasks;
using Kyoo.TheMovieDb; using Kyoo.TheMovieDb;
using Kyoo.TheTvdb; using Kyoo.TheTvdb;
using Kyoo.Utils;
using Kyoo.WebApp; using Kyoo.WebApp;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
@ -21,7 +22,7 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo namespace Kyoo.Core
{ {
/// <summary> /// <summary>
/// The Startup class is used to configure the AspNet's webhost. /// The Startup class is used to configure the AspNet's webhost.
@ -131,19 +132,13 @@ namespace Kyoo
/// This is meant to be used from <see cref="WebHostBuilderExtensions.UseStartup"/>. /// This is meant to be used from <see cref="WebHostBuilderExtensions.UseStartup"/>.
/// </summary> /// </summary>
/// <param name="host">The context of the web host.</param> /// <param name="host">The context of the web host.</param>
/// <param name="loggingConfiguration"> /// <param name="logger">
/// The method used to configure the logger factory used by the plugin manager and plugins during startup. /// The logger factory used to log while the application is setting itself up.
/// </param> /// </param>
/// <returns>A new <see cref="PluginsStartup"/>.</returns> /// <returns>A new <see cref="PluginsStartup"/>.</returns>
public static PluginsStartup FromWebHost(WebHostBuilderContext host, public static PluginsStartup FromWebHost(WebHostBuilderContext host,
Action<HostBuilderContext, ILoggingBuilder> loggingConfiguration) ILoggerFactory logger)
{ {
HostBuilderContext genericHost = new(new Dictionary<object, object>())
{
Configuration = host.Configuration,
HostingEnvironment = host.HostingEnvironment
};
ILoggerFactory logger = LoggerFactory.Create(builder => loggingConfiguration(genericHost, builder));
HostServiceProvider hostProvider = new(host.HostingEnvironment, host.Configuration, logger); HostServiceProvider hostProvider = new(host.HostingEnvironment, host.Configuration, logger);
PluginManager plugins = new( PluginManager plugins = new(
hostProvider, hostProvider,

View File

@ -7,10 +7,10 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Models.Watch; using Kyoo.Core.Models.Watch;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Kyoo.Tasks namespace Kyoo.Core.Tasks
{ {
/// <summary> /// <summary>
/// A task to add new video files. /// A task to add new video files.
@ -146,7 +146,7 @@ namespace Kyoo.Tasks
string[] subtitles = files string[] subtitles = files
.Where(FileExtensions.IsSubtitle) .Where(FileExtensions.IsSubtitle)
.Where(x => !x.Contains("/Extra/")) .Where(x => !x.Contains("Extra"))
.Where(x => tracks.All(y => y.Path != x)) .Where(x => tracks.All(y => y.Path != x))
.ToArray(); .ToArray();
percent = 0; percent = 0;

View File

@ -6,7 +6,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Kyoo.Tasks namespace Kyoo.Core.Tasks
{ {
/// <summary> /// <summary>
/// A task to remove orphaned episode and series. /// A task to remove orphaned episode and series.

View File

@ -6,7 +6,7 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
namespace Kyoo.Tasks namespace Kyoo.Core.Tasks
{ {
/// <summary> /// <summary>
/// A task that download metadata providers images. /// A task that download metadata providers images.

View File

@ -5,7 +5,7 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
namespace Kyoo.Tasks namespace Kyoo.Core.Tasks
{ {
/// <summary> /// <summary>
/// A task run on Kyoo's startup to initialize plugins /// A task run on Kyoo's startup to initialize plugins

View File

@ -7,7 +7,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
namespace Kyoo.Tasks namespace Kyoo.Core.Tasks
{ {
/// <summary> /// <summary>
/// A task to register a new episode /// A task to register a new episode

View File

@ -6,7 +6,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
namespace Kyoo.Tasks namespace Kyoo.Core.Tasks
{ {
/// <summary> /// <summary>
/// A task to register a new episode /// A task to register a new episode

View File

@ -7,10 +7,10 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/collection")] [Route("api/collection")]
[Route("api/collections")] [Route("api/collections")]

View File

@ -5,7 +5,7 @@ using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
/// <summary> /// <summary>
/// An API to retrieve or edit configuration settings /// An API to retrieve or edit configuration settings

View File

@ -7,10 +7,10 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/episode")] [Route("api/episode")]
[Route("api/episodes")] [Route("api/episodes")]

View File

@ -5,11 +5,11 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/genre")] [Route("api/genre")]
[Route("api/genres")] [Route("api/genres")]

View File

@ -6,7 +6,7 @@ using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
public static class ApiHelper public static class ApiHelper
{ {

View File

@ -8,7 +8,7 @@ using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[ApiController] [ApiController]
[ResourceView] [ResourceView]

View File

@ -6,11 +6,12 @@ using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Utils;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
public class JsonPropertyIgnorer : CamelCasePropertyNamesContractResolver public class JsonPropertyIgnorer : CamelCasePropertyNamesContractResolver
{ {

View File

@ -6,12 +6,13 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
using Kyoo.Utils;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
public class ResourceViewAttribute : ActionFilterAttribute public class ResourceViewAttribute : ActionFilterAttribute
{ {

View File

@ -6,10 +6,10 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/library")] [Route("api/library")]
[Route("api/libraries")] [Route("api/libraries")]

View File

@ -6,11 +6,11 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/item")] [Route("api/item")]
[Route("api/items")] [Route("api/items")]

View File

@ -5,11 +5,11 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/people")] [Route("api/people")]
[ApiController] [ApiController]

View File

@ -2,11 +2,11 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/provider")] [Route("api/provider")]
[Route("api/providers")] [Route("api/providers")]

View File

@ -5,7 +5,7 @@ using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/search/{query}")] [Route("api/search/{query}")]
[ApiController] [ApiController]

View File

@ -6,10 +6,10 @@ using System.Linq;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/season")] [Route("api/season")]
[Route("api/seasons")] [Route("api/seasons")]

View File

@ -8,10 +8,10 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/show")] [Route("api/show")]
[Route("api/shows")] [Route("api/shows")]

View File

@ -5,11 +5,11 @@ using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/studio")] [Route("api/studio")]
[Route("api/studios")] [Route("api/studios")]

View File

@ -7,7 +7,7 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("subtitle")] [Route("subtitle")]
[ApiController] [ApiController]

View File

@ -5,7 +5,7 @@ using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/task")] [Route("api/task")]
[Route("api/tasks")] [Route("api/tasks")]

View File

@ -4,11 +4,11 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/track")] [Route("api/track")]
[Route("api/tracks")] [Route("api/tracks")]

View File

@ -5,11 +5,11 @@ using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Models.Options; using Kyoo.Core.Models.Options;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("video")] [Route("video")]
[ApiController] [ApiController]

View File

@ -5,7 +5,7 @@ using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Permissions;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Api namespace Kyoo.Core.Api
{ {
[Route("api/watch")] [Route("api/watch")]
[ApiController] [ApiController]

View File

@ -30,12 +30,14 @@
}, },
"logging": { "logging": {
"logLevel": { "MinimumLevel": {
"default": "Warning", "Default": "Warning",
"Microsoft": "Warning", "Override": {
"Microsoft.Hosting.Lifetime": "Information", "Microsoft": "Warning",
"Microsoft.EntityFrameworkCore": "None", "Microsoft.Hosting.Lifetime": "Information",
"Kyoo": "Trace" "Microsoft.EntityFrameworkCore": "Fatal",
"Kyoo": "Verbose"
}
} }
}, },
@ -45,12 +47,12 @@
"scan": "24:00:00" "scan": "24:00:00"
} }
}, },
"media": { "media": {
"regex": [ "regex": [
"^\\/?(?<Collection>.+)?\\/(?<Show>.+?)(?: \\((?<StartYear>\\d+)\\))?\\/\\k<Show>(?: \\(\\d+\\))? S(?<Season>\\d+)E(?<Episode>\\d+)\\..*$", "^[\\/\\\\]*(?<Collection>.+)?[\\/\\\\]+(?<Show>.+?)(?: \\((?<StartYear>\\d+)\\))?[\\/\\\\]+\\k<Show>(?: \\(\\d+\\))? S(?<Season>\\d+)E(?<Episode>\\d+)\\..*$",
"^\\/?(?<Collection>.+)?\\/(?<Show>.+?)(?: \\((?<StartYear>\\d+)\\))?\\/\\k<Show>(?: \\(\\d+\\))? (?<Absolute>\\d+)\\..*$", "^[\\/\\\\]*(?<Collection>.+)?[\\/\\\\]+(?<Show>.+?)(?: \\((?<StartYear>\\d+)\\))?[\\/\\\\]+\\k<Show>(?: \\(\\d+\\))? (?<Absolute>\\d+)\\..*$",
"^\\/?(?<Collection>.+)?\\/(?<Show>.+?)(?: \\((?<StartYear>\\d+)\\))?\\/\\k<Show>(?: \\(\\d+\\))?\\..*$" "^[\\/\\\\]*(?<Collection>.+)?[\\/\\\\]+(?<Show>.+?)(?: \\((?<StartYear>\\d+)\\))?[\\/\\\\]+\\k<Show>(?: \\(\\d+\\))?\\..*$"
], ],
"subtitleRegex": [ "subtitleRegex": [
"^(?<Episode>.+)\\.(?<Language>\\w{1,3})\\.(?<Default>default\\.)?(?<Forced>forced\\.)?.*$" "^(?<Episode>.+)\\.(?<Language>\\w{1,3})\\.(?<Default>default\\.)?(?<Forced>forced\\.)?.*$"
@ -72,9 +74,9 @@
}, },
"tvdb": { "tvdb": {
"apiKey": "REDACTED" "apiKey": ""
}, },
"the-moviedb": { "the-moviedb": {
"apiKey": "REDACTED" "apiKey": ""
} }
} }

View File

@ -1,7 +1,7 @@
using System.Data.Common; using System.Data.Common;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
namespace Kyoo namespace Kyoo.Database
{ {
/// <summary> /// <summary>
/// A class that regroup extensions used by some asp-net related parts of the app. /// A class that regroup extensions used by some asp-net related parts of the app.

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<StartupObject>Kyoo.Host.Console.Program</StartupObject>
<Company>SDG</Company>
<Authors>Zoe Roux</Authors>
<RepositoryUrl>https://github.com/AnonymusRaccoon/Kyoo</RepositoryUrl>
<LangVersion>default</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="$(IncludeConsole) == true">
<!--
IncludeConsole is a property used when deploying the windows host. Since the runtime identifier is removed,
we specify it manually. This is kindy hacky but MsBuild does not really work well with multiples exe output
and we need multiples exe with the same shared framework (SelfContained).
-->
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Kyoo.Core/Kyoo.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,31 @@
using System.Threading.Tasks;
using Kyoo.Core;
using Microsoft.AspNetCore.Hosting;
namespace Kyoo.Host.Console
{
/// <summary>
/// Program entrypoint.
/// </summary>
public static class Program
{
/// <summary>
/// The string representation of the environment used in <see cref="IWebHostEnvironment"/>.
/// </summary>
#if DEBUG
private const string Environment = "Development";
#else
private const string Environment = "Production";
#endif
/// <summary>
/// Main function of the program
/// </summary>
/// <param name="args">Command line arguments</param>
public static Task Main(string[] args)
{
Application application = new(Environment);
return application.Start(args);
}
}
}

View File

@ -0,0 +1,12 @@
<Project>
<PropertyGroup>
<IsWindows Condition="$([MSBuild]::IsOSPlatform('Windows'))">true</IsWindows>
</PropertyGroup>
<Import Project="Kyoo.Host.WindowsTrait.target" Condition="$(IsWindows) == true" />
<Import Project="Kyoo.Host.WindowsTrait.linux.target" Condition="$(IsWindows) != true" />
<ItemGroup>
<None Remove="*.target" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,26 @@
<Project>
<!-- Project file used instead of the default csproj when the host system is not windows. This only skip the build. -->
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<NoWarn>NU1503</NoWarn>
</PropertyGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<Target Name="Build">
<Message Importance="high" Text="Detected current operating system is not windows, skipping WindowsHost build." />
</Target>
<Target Name="Clean" />
<Target Name="Pack" />
<Target Name="Restore" />
<Target Name="Publish" />
<ItemGroup>
<None Include="@(Compile)" />
<Compile Remove="*" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Project file used instead of the default csproj when the host system is windows.
This is the real csproj used to compile the project.
-->
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<RootNamespace>Kyoo.WindowsHost</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Kyoo.Core/Kyoo.Core.csproj" />
<ProjectReference Include="../Kyoo.Host.Console/Kyoo.Host.Console.csproj" Condition="$(IncludeConsole) == true" />
</ItemGroup>
<ItemGroup>
<None Remove="kyoo.ico"/>
<Content Include="kyoo.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@ -0,0 +1,32 @@
using System.Threading.Tasks;
using Autofac;
using Kyoo.Core;
namespace Kyoo.Host.WindowsTrait
{
public static class Program
{
/// <summary>
/// The string representation of the environment used in IWebHostEnvironment.
/// </summary>
#if DEBUG
private const string Environment = "Development";
#else
private const string Environment = "Production";
#endif
/// <summary>
/// The main entry point for the application that overrides the default host.
/// It adds a system trait for windows and since the host is build as a windows executable instead of a console
/// app, the console is not showed.
/// </summary>
public static Task Main(string[] args)
{
Application application = new(Environment);
return application.Start(args, builder =>
{
builder.RegisterType<SystemTrait>().As<IStartable>().SingleInstance();
});
}
}
}

View File

@ -0,0 +1,163 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Autofac;
using Kyoo.Abstractions.Controllers;
using Kyoo.Core.Models.Options;
using Microsoft.Extensions.Options;
namespace Kyoo.Host.WindowsTrait
{
/// <summary>
/// A singleton that add an notification icon on the window's toolbar.
/// </summary>
public sealed class SystemTrait : IStartable, IDisposable
{
/// <summary>
/// The application running Kyoo.
/// </summary>
private readonly IApplication _application;
/// <summary>
/// The options containing the <see cref="BasicOptions.PublicUrl"/>.
/// </summary>
private readonly IOptions<BasicOptions> _options;
/// <summary>
/// The thread where the trait is running.
/// </summary>
private Thread _thread;
/// <summary>
/// Create a new <see cref="SystemTrait"/>.
/// </summary>
/// <param name="application">The application running Kyoo.</param>
/// <param name="options">The options to use.</param>
public SystemTrait(IApplication application, IOptions<BasicOptions> options)
{
_application = application;
_options = options;
}
/// <inheritdoc />
public void Start()
{
_thread = new Thread(() => InternalSystemTrait.Run(_application, _options))
{
IsBackground = true
};
_thread.Start();
}
/// <inheritdoc />
public void Dispose()
{
System.Windows.Forms.Application.Exit();
_thread?.Join();
_thread = null;
}
/// <summary>
/// The internal class for <see cref="SystemTrait"/>. It should be invoked via
/// <see cref="InternalSystemTrait.Run"/>.
/// </summary>
private class InternalSystemTrait : ApplicationContext
{
/// <summary>
/// The application running Kyoo.
/// </summary>
private readonly IApplication _application;
/// <summary>
/// The options containing the <see cref="BasicOptions.PublicUrl"/>.
/// </summary>
private readonly IOptions<BasicOptions> _options;
/// <summary>
/// The Icon that is displayed in the window's bar.
/// </summary>
private readonly NotifyIcon _icon;
/// <summary>
/// Create a new <see cref="InternalSystemTrait"/>. Used only by <see cref="Run"/>.
/// </summary>
/// <param name="application">The application running Kyoo.</param>
/// <param name="options">The option containing the public url.</param>
private InternalSystemTrait(IApplication application, IOptions<BasicOptions> options)
{
_application = application;
_options = options;
AppDomain.CurrentDomain.ProcessExit += (_, _) => Dispose();
System.Windows.Forms.Application.ApplicationExit += (_, _) => Dispose();
_icon = new NotifyIcon();
_icon.Text = "Kyoo";
_icon.Icon = new Icon(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "kyoo.ico"));
_icon.Visible = true;
_icon.MouseClick += (_, e) =>
{
if (e.Button != MouseButtons.Left)
return;
_StartBrowser();
};
_icon.ContextMenuStrip = new ContextMenuStrip();
_icon.ContextMenuStrip.Items.AddRange(new ToolStripItem[]
{
new ToolStripMenuItem("Open browser", null, (_, _) => { _StartBrowser(); }),
new ToolStripMenuItem("Open logs", null, (_, _) => { _OpenLogs(); }),
new ToolStripSeparator(),
new ToolStripMenuItem("Exit", null, (_, _) => { _application.Shutdown(); })
});
}
/// <summary>
/// Run the trait in the current thread, this method does not return while the trait is running.
/// </summary>
/// <param name="application">The application running Kyoo.</param>
/// <param name="options">The options to pass to <see cref="InternalSystemTrait"/>.</param>
public static void Run(IApplication application, IOptions<BasicOptions> options)
{
using InternalSystemTrait trait = new(application, options);
System.Windows.Forms.Application.Run(trait);
}
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
_icon.Visible = false;
base.Dispose(disposing);
_icon.Dispose();
}
/// <summary>
/// Open kyoo's page in the user's default browser.
/// </summary>
private void _StartBrowser()
{
Process browser = new()
{
StartInfo = new ProcessStartInfo(_options.Value.PublicUrl.ToString())
{
UseShellExecute = true
}
};
browser.Start();
}
/// <summary>
/// Open the log directory in windows's explorer.
/// </summary>
private void _OpenLogs()
{
string logDir = Path.Combine(_application.GetDataDirectory(), "logs");
Process.Start("explorer.exe", logDir);
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -5,6 +5,7 @@ using System.Reflection;
using EFCore.NamingConventions.Internal; using EFCore.NamingConventions.Internal;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Database; using Kyoo.Database;
using Kyoo.Utils;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Npgsql; using Npgsql;

View File

@ -4,6 +4,7 @@ using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Database; using Kyoo.Database;
using Kyoo.Utils;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using TMDbLib.Objects.Search; using TMDbLib.Objects.Search;
namespace Kyoo.TheMovieDb namespace Kyoo.TheMovieDb

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using TMDbLib.Objects.Movies; using TMDbLib.Objects.Movies;
using TMDbLib.Objects.Search; using TMDbLib.Objects.Search;

Some files were not shown because too many files have changed in this diff Show More