diff --git a/Kyoo.Abstractions/Controllers/IPlugin.cs b/Kyoo.Abstractions/Controllers/IPlugin.cs index 0ff6c932..6fc2cc3c 100644 --- a/Kyoo.Abstractions/Controllers/IPlugin.cs +++ b/Kyoo.Abstractions/Controllers/IPlugin.cs @@ -93,14 +93,5 @@ namespace Kyoo.Abstractions.Controllers { // Skipped } - - /// - /// 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. - /// - void Disabled() - { - // Skipped - } } } \ No newline at end of file diff --git a/Kyoo.Core/Application.cs b/Kyoo.Core/Application.cs index 2101aeb6..f09245e9 100644 --- a/Kyoo.Core/Application.cs +++ b/Kyoo.Core/Application.cs @@ -42,6 +42,11 @@ namespace Kyoo.Core /// private readonly string _environment; + /// + /// The logger used for startup and error messages. + /// + private ILogger _logger; + /// /// Create a new that will use the specified environment. @@ -76,9 +81,9 @@ namespace Kyoo.Core _dataDir = _SetupDataDir(args); LoggerConfiguration config = new(); - _ConfigureLogging(config, null); - Log.Logger = config.CreateBootstrapLogger() - .ForContext(); + _ConfigureLogging(config, null, null); + Log.Logger = config.CreateBootstrapLogger(); + _logger = Log.Logger.ForContext(); AppDomain.CurrentDomain.ProcessExit += (_, _) => Log.CloseAndFlush(); AppDomain.CurrentDomain.UnhandledException += (_, ex) @@ -89,7 +94,6 @@ namespace Kyoo.Core IHost host = _CreateWebHostBuilder(args) .ConfigureContainer(configure) .Build(); - Log.Logger = host.Services.GetRequiredService().ForContext(); _tokenSource = new CancellationTokenSource(); await _StartWithHost(host, _tokenSource.Token); @@ -173,13 +177,13 @@ namespace Kyoo.Core { try { - Log.Information("Running as {Name}", Environment.UserName); - Log.Information("Data directory: {DataDirectory}", GetDataDirectory()); + _logger.Information("Running as {Name}", Environment.UserName); + _logger.Information("Data directory: {DataDirectory}", GetDataDirectory()); await host.RunAsync(cancellationToken); } catch (Exception ex) { - Log.Fatal(ex, "Unhandled exception"); + _logger.Fatal(ex, "Unhandled exception"); } } @@ -197,7 +201,7 @@ namespace Kyoo.Core .UseContentRoot(AppDomain.CurrentDomain.BaseDirectory) .UseEnvironment(_environment) .ConfigureAppConfiguration(x => _SetupConfig(x, args)) - .UseSerilog((host, builder) => _ConfigureLogging(builder, host.Configuration)) + .UseSerilog((host, services, builder) => _ConfigureLogging(builder, host.Configuration, services)) .ConfigureServices(x => x.AddRouting()) .ConfigureContainer(x => { @@ -227,13 +231,16 @@ namespace Kyoo.Core .AddEnvironmentVariables("KYOO_") .AddCommandLine(args); } - + /// /// Configure the logging. /// /// The logger builder to configure. /// The configuration to read settings from. - private void _ConfigureLogging(LoggerConfiguration builder, [CanBeNull] IConfiguration configuration) + /// The services to read configuration from. + private void _ConfigureLogging(LoggerConfiguration builder, + [CanBeNull] IConfiguration configuration, + [CanBeNull] IServiceProvider services) { if (configuration != null) { @@ -243,10 +250,13 @@ namespace Kyoo.Core } catch (Exception ex) { - Log.Fatal(ex, "Could not read serilog configuration"); + _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}"; diff --git a/Kyoo.Core/Controllers/PluginManager.cs b/Kyoo.Core/Controllers/PluginManager.cs index 37dc173d..e87d83a8 100644 --- a/Kyoo.Core/Controllers/PluginManager.cs +++ b/Kyoo.Core/Controllers/PluginManager.cs @@ -51,14 +51,6 @@ namespace Kyoo.Core.Controllers _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; - } - - /// public T GetPlugin(string name) { @@ -111,16 +103,13 @@ namespace Kyoo.Core.Controllers _logger.LogTrace("Loading new plugins..."); string[] pluginsPaths = Directory.GetFiles(pluginFolder, "*.dll", SearchOption.AllDirectories); - IPlugin[] newPlugins = plugins + _plugins.AddRange(plugins .Concat(pluginsPaths.SelectMany(LoadPlugin)) + .Where(x => x.Enabled) .GroupBy(x => x.Name) .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()) _logger.LogInformation("No plugin enabled"); else diff --git a/Kyoo.Core/settings.json b/Kyoo.Core/settings.json index 299f0e5c..64466270 100644 --- a/Kyoo.Core/settings.json +++ b/Kyoo.Core/settings.json @@ -74,9 +74,9 @@ }, "tvdb": { - "apiKey": "REDACTED" + "apiKey": "" }, "the-moviedb": { - "apiKey": "REDACTED" + "apiKey": "" } } diff --git a/Kyoo.TheMovieDb/PluginTmdb.cs b/Kyoo.TheMovieDb/PluginTmdb.cs index 6fb94e23..9af1a267 100644 --- a/Kyoo.TheMovieDb/PluginTmdb.cs +++ b/Kyoo.TheMovieDb/PluginTmdb.cs @@ -4,6 +4,8 @@ using Autofac; using Kyoo.Abstractions; using Kyoo.Abstractions.Controllers; using Kyoo.TheMovieDb.Models; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; namespace Kyoo.TheMovieDb { @@ -16,17 +18,38 @@ namespace Kyoo.TheMovieDb public string Slug => "the-moviedb"; /// - public string Name => "TheMovieDb Provider"; + public string Name => "TheMovieDb"; /// public string Description => "A metadata provider for TheMovieDB."; - + + /// + public bool Enabled => !string.IsNullOrEmpty(_configuration.GetValue("the-moviedb:apikey")); + /// public Dictionary Configuration => new() { { TheMovieDbOptions.Path, typeof(TheMovieDbOptions) } }; + /// + /// The configuration used to check if the api key is present or not. + /// + private readonly IConfiguration _configuration; + + /// + /// Create a new . + /// + /// The configuration used to check if the api key is present or not. + /// The logger used to warn when the api key is not present. + public PluginTmdb(IConfiguration configuration, ILogger logger) + { + _configuration = configuration; + if (!Enabled) + logger.LogWarning("No API key configured for TheMovieDB provider. " + + "To enable TheMovieDB, specify one in the setting the-moviedb:APIKEY "); + } + /// public void Configure(ContainerBuilder builder) { diff --git a/Kyoo.TheTvdb/Kyoo.TheTvdb.csproj b/Kyoo.TheTvdb/Kyoo.TheTvdb.csproj index 29995a3c..f2c052ff 100644 --- a/Kyoo.TheTvdb/Kyoo.TheTvdb.csproj +++ b/Kyoo.TheTvdb/Kyoo.TheTvdb.csproj @@ -10,6 +10,7 @@ + diff --git a/Kyoo.TheTvdb/PluginTvdb.cs b/Kyoo.TheTvdb/PluginTvdb.cs index 8d43cb81..75feee76 100644 --- a/Kyoo.TheTvdb/PluginTvdb.cs +++ b/Kyoo.TheTvdb/PluginTvdb.cs @@ -4,6 +4,8 @@ using Autofac; using Kyoo.Abstractions; using Kyoo.Abstractions.Controllers; using Kyoo.TheTvdb.Models; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; using TvDbSharper; namespace Kyoo.TheTvdb @@ -15,19 +17,40 @@ namespace Kyoo.TheTvdb { /// public string Slug => "the-tvdb"; - + /// - public string Name => "The TVDB Provider"; - + public string Name => "TVDB"; + /// public string Description => "A metadata provider for The TVDB."; + /// + public bool Enabled => !string.IsNullOrEmpty(_configuration.GetValue("tvdb:apikey")); + /// public Dictionary Configuration => new() { { TvdbOption.Path, typeof(TvdbOption) } }; + /// + /// The configuration used to check if the api key is present or not. + /// + private readonly IConfiguration _configuration; + + /// + /// Create a new . + /// + /// The configuration used to check if the api key is present or not. + /// The logger used to warn when the api key is not present. + public PluginTvdb(IConfiguration configuration, ILogger logger) + { + _configuration = configuration; + if (!Enabled) + logger.LogWarning("No API key configured for TVDB provider. " + + "To enable TVDB, specify one in the setting TVDB:APIKEY "); + } + /// public void Configure(ContainerBuilder builder) { diff --git a/Kyoo.WebApp/Kyoo.WebApp.csproj b/Kyoo.WebApp/Kyoo.WebApp.csproj index d1a0402b..910d2167 100644 --- a/Kyoo.WebApp/Kyoo.WebApp.csproj +++ b/Kyoo.WebApp/Kyoo.WebApp.csproj @@ -63,11 +63,6 @@ - - - - - diff --git a/Kyoo.WebApp/WebAppModule.cs b/Kyoo.WebApp/WebAppModule.cs index dc17c899..a83910cb 100644 --- a/Kyoo.WebApp/WebAppModule.cs +++ b/Kyoo.WebApp/WebAppModule.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Runtime.CompilerServices; using Kyoo.Abstractions.Controllers; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -33,28 +34,17 @@ namespace Kyoo.WebApp /// public bool Enabled => Directory.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot")); - - /// - /// A logger only used to inform the user if the webapp could not be enabled. - /// - private readonly ILogger _logger; - /// /// Create a new . /// /// A logger only used to inform the user if the webapp could not be enabled. public WebAppModule(ILogger logger) { - _logger = logger; + if (!Enabled) + logger.LogError("The web app files could not be found, it will be disabled. " + + "If you cloned the project, you probably forgot to use the --recurse flag"); } - - /// - public void Disabled() - { - _logger.LogError("The web app files could not be found, it will be disabled. " + - "If you cloned the project, you probably forgot to use the --recurse flag"); - } - + /// public void Configure(IServiceCollection services) { @@ -99,12 +89,27 @@ namespace Kyoo.WebApp { app.UseSpa(spa => { - spa.Options.SourcePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Kyoo.WebApp", "Front"); + spa.Options.SourcePath = _GetSpaSourcePath(); if (env.IsDevelopment()) spa.UseAngularCliServer("start"); }); }, SA.Endpoint - 500) }; + + /// + /// Get the root directory of the web app + /// + /// The path of the source code of the web app or null if the directory has been deleted. + private static string _GetSpaSourcePath() + { + string GetSelfPath([CallerFilePath] string path = null) + { + return path; + } + + string path = Path.Join(Path.GetDirectoryName(GetSelfPath()), "Front"); + return Directory.Exists(path) ? path : null; + } } } \ No newline at end of file