From dcfb1e538cab09832808f638364d71d1b4f1052e Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 20 May 2021 00:22:35 +0200 Subject: [PATCH] Adding strongly typed options --- Kyoo.Authentication/AuthenticationModule.cs | 4 +- .../Controllers/IConfigurationManager.cs | 20 ++++++++ Kyoo.Common/Module.cs | 11 +++++ Kyoo.CommonAPI/CrudApi.cs | 5 +- Kyoo.Postgresql/PostgresModule.cs | 4 -- Kyoo/Controllers/ConfigurationManager.cs | 28 +++++++++++ Kyoo/Controllers/PluginManager.cs | 13 ++--- Kyoo/Controllers/TaskManager.cs | 18 +++---- Kyoo/Controllers/ThumbnailsManager.cs | 25 +++++----- Kyoo/Controllers/Transcoder.cs | 15 +++--- Kyoo/CoreModule.cs | 10 +++- Kyoo/Models/Options/BasicOptions.cs | 48 +++++++++++++++++++ Kyoo/Models/Options/MediaOptions.cs | 23 +++++++++ Kyoo/Models/Options/TaskOptions.cs | 28 +++++++++++ Kyoo/Program.cs | 7 ++- Kyoo/Startup.cs | 5 +- Kyoo/Views/CollectionApi.cs | 7 +-- Kyoo/Views/ConfigurationApi.cs | 40 +++++----------- Kyoo/Views/EpisodeApi.cs | 7 +-- Kyoo/Views/GenreApi.cs | 7 +-- Kyoo/Views/LibraryApi.cs | 7 +-- Kyoo/Views/LibraryItemApi.cs | 7 +-- Kyoo/Views/PeopleApi.cs | 7 +-- Kyoo/Views/ProviderApi.cs | 7 +-- Kyoo/Views/SeasonApi.cs | 7 +-- Kyoo/Views/ShowApi.cs | 7 +-- Kyoo/Views/StudioApi.cs | 7 +-- Kyoo/Views/TrackApi.cs | 7 +-- Kyoo/Views/VideoApi.cs | 15 +++--- Kyoo/settings.json | 42 ++++++++-------- 30 files changed, 302 insertions(+), 136 deletions(-) create mode 100644 Kyoo/Models/Options/BasicOptions.cs create mode 100644 Kyoo/Models/Options/MediaOptions.cs create mode 100644 Kyoo/Models/Options/TaskOptions.cs diff --git a/Kyoo.Authentication/AuthenticationModule.cs b/Kyoo.Authentication/AuthenticationModule.cs index 66cdf2fd..8e2c78c4 100644 --- a/Kyoo.Authentication/AuthenticationModule.cs +++ b/Kyoo.Authentication/AuthenticationModule.cs @@ -84,7 +84,7 @@ namespace Kyoo.Authentication /// public void Configure(IServiceCollection services, ICollection availableTypes) { - string publicUrl = _configuration.GetValue("publicUrl").TrimEnd('/'); + string publicUrl = _configuration.GetPublicUrl(); if (_environment.IsDevelopment()) IdentityModelEventSource.ShowPII = true; @@ -146,7 +146,7 @@ namespace Kyoo.Authentication app.UseAuthentication(); app.Use((ctx, next) => { - ctx.SetIdentityServerOrigin(_configuration.GetValue("publicUrl").TrimEnd('/')); + ctx.SetIdentityServerOrigin(_configuration.GetPublicUrl()); return next(); }); app.UseIdentityServer(); diff --git a/Kyoo.Common/Controllers/IConfigurationManager.cs b/Kyoo.Common/Controllers/IConfigurationManager.cs index 089f7312..9159d92c 100644 --- a/Kyoo.Common/Controllers/IConfigurationManager.cs +++ b/Kyoo.Common/Controllers/IConfigurationManager.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Exceptions; @@ -11,6 +12,25 @@ namespace Kyoo.Controllers /// public interface IConfigurationManager { + /// + /// Get the value of a setting using it's path. + /// + /// The path of the resource (can be separated by ':' or '__') + /// No setting found at the given path. + /// The value of the settings (if it's a strongly typed one, the given type is instantiated + object GetValue(string path); + + /// + /// Get the value of a setting using it's path. + /// If your don't need a strongly typed value, see . + /// + /// The path of the resource (can be separated by ':' or '__') + /// A type to strongly type your option. + /// If your type is not the same as the registered type + /// No setting found at the given path. + /// The value of the settings (if it's a strongly typed one, the given type is instantiated + T GetValue(string path); + /// /// Edit the value of a setting using it's path. Save it to the json file. /// diff --git a/Kyoo.Common/Module.cs b/Kyoo.Common/Module.cs index e8fcf1b6..0b5e0d04 100644 --- a/Kyoo.Common/Module.cs +++ b/Kyoo.Common/Module.cs @@ -2,6 +2,7 @@ using System; using System.Linq; using Kyoo.Controllers; using Kyoo.Models; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace Kyoo @@ -81,5 +82,15 @@ namespace Kyoo services.AddSingleton(confRef); return services; } + + /// + /// Get the public URL of kyoo using the given configuration instance. + /// + /// The configuration instance + /// The public URl of kyoo (without a slash at the end) + public static string GetPublicUrl(this IConfiguration configuration) + { + return configuration["basics:publicUrl"]?.TrimEnd('/') ?? "http://localhost:5000"; + } } } \ No newline at end of file diff --git a/Kyoo.CommonAPI/CrudApi.cs b/Kyoo.CommonAPI/CrudApi.cs index 75a2758c..b6d03580 100644 --- a/Kyoo.CommonAPI/CrudApi.cs +++ b/Kyoo.CommonAPI/CrudApi.cs @@ -7,7 +7,6 @@ using Kyoo.Models; using Kyoo.Models.Exceptions; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; namespace Kyoo.CommonApi { @@ -18,10 +17,10 @@ namespace Kyoo.CommonApi private readonly IRepository _repository; protected readonly string BaseURL; - public CrudApi(IRepository repository, IConfiguration configuration) + public CrudApi(IRepository repository, string baseURL) { _repository = repository; - BaseURL = configuration.GetValue("publicUrl").TrimEnd('/'); + BaseURL = baseURL; } diff --git a/Kyoo.Postgresql/PostgresModule.cs b/Kyoo.Postgresql/PostgresModule.cs index 7a818296..f0c8f23c 100644 --- a/Kyoo.Postgresql/PostgresModule.cs +++ b/Kyoo.Postgresql/PostgresModule.cs @@ -66,10 +66,6 @@ namespace Kyoo.Postgresql if (_environment.IsDevelopment()) x.EnableDetailedErrors().EnableSensitiveDataLogging(); }); - // services.AddScoped(_ => new PostgresContext( - // _configuration.GetDatabaseConnection("postgres"), - // _environment.IsDevelopment())); - // services.AddScoped(x => x.GetRequiredService()); } /// diff --git a/Kyoo/Controllers/ConfigurationManager.cs b/Kyoo/Controllers/ConfigurationManager.cs index 42bdf433..c0a1340b 100644 --- a/Kyoo/Controllers/ConfigurationManager.cs +++ b/Kyoo/Controllers/ConfigurationManager.cs @@ -35,6 +35,34 @@ namespace Kyoo.Controllers _references = references.ToDictionary(x => x.Path, x => x.Type, StringComparer.OrdinalIgnoreCase); } + /// + public object GetValue(string path) + { + path = path.Replace("__", ":"); + // TODO handle lists and dictionaries. + if (!_references.TryGetValue(path, out Type type)) + throw new ItemNotFoundException($"No configuration exists for the name: {path}"); + object ret = _configuration.GetValue(type, path); + if (ret != null) + return ret; + object option = Activator.CreateInstance(type); + _configuration.Bind(path, option); + return option; + } + + /// + public T GetValue(string path) + { + path = path.Replace("__", ":"); + // TODO handle lists and dictionaries. + if (!_references.TryGetValue(path, out Type type)) + throw new ItemNotFoundException($"No configuration exists for the name: {path}"); + if (typeof(T).IsAssignableFrom(type)) + throw new InvalidCastException($"The type {typeof(T).Name} is not valid for " + + $"a resource of type {type.Name}."); + return (T)GetValue(path); + } + /// public async Task EditValue(string path, object value) { diff --git a/Kyoo/Controllers/PluginManager.cs b/Kyoo/Controllers/PluginManager.cs index 321d2f57..7d0c399b 100644 --- a/Kyoo/Controllers/PluginManager.cs +++ b/Kyoo/Controllers/PluginManager.cs @@ -4,10 +4,11 @@ using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Loader; +using Kyoo.Models.Options; using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Kyoo.Controllers { @@ -24,7 +25,7 @@ namespace Kyoo.Controllers /// /// The configuration to get the plugin's directory. /// - private readonly IConfiguration _config; + private readonly IOptionsMonitor _options; /// /// The logger used by this class. /// @@ -39,14 +40,14 @@ namespace Kyoo.Controllers /// Create a new instance. /// /// A service container to allow initialization of plugins - /// The configuration instance, to get the plugin's directory path. + /// The configuration instance, to get the plugin's directory path. /// The logger used by this class. public PluginManager(IServiceProvider provider, - IConfiguration config, + IOptionsMonitor options, ILogger logger) { _provider = provider; - _config = config; + _options = options; _logger = logger; } @@ -97,7 +98,7 @@ namespace Kyoo.Controllers /// public void LoadPlugins(ICollection plugins) { - string pluginFolder = _config.GetValue("plugins"); + string pluginFolder = _options.CurrentValue.PluginPath; if (!Directory.Exists(pluginFolder)) Directory.CreateDirectory(pluginFolder); diff --git a/Kyoo/Controllers/TaskManager.cs b/Kyoo/Controllers/TaskManager.cs index 5f281ba3..caa7a01d 100644 --- a/Kyoo/Controllers/TaskManager.cs +++ b/Kyoo/Controllers/TaskManager.cs @@ -7,10 +7,11 @@ using System.Threading.Tasks; using JetBrains.Annotations; using Kyoo.Models.Attributes; using Kyoo.Models.Exceptions; -using Microsoft.Extensions.Configuration; +using Kyoo.Models.Options; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Kyoo.Controllers { @@ -27,7 +28,7 @@ namespace Kyoo.Controllers /// /// The configuration instance used to get schedule information /// - private readonly IConfiguration _configuration; + private readonly IOptionsMonitor _options; /// /// The logger instance. /// @@ -56,15 +57,15 @@ namespace Kyoo.Controllers /// /// The list of tasks to manage /// The service provider to request services for tasks - /// The configuration to load schedule information. + /// The configuration to load schedule information. /// The logger. public TaskManager(IEnumerable tasks, IServiceProvider provider, - IConfiguration configuration, + IOptionsMonitor options, ILogger logger) { _provider = provider; - _configuration = configuration.GetSection("scheduledTasks"); + _options = options; _logger = logger; _tasks = tasks.Select(x => (x, GetNextTaskDate(x.Slug))).ToList(); @@ -224,10 +225,9 @@ namespace Kyoo.Controllers /// The next date. private DateTime GetNextTaskDate(string taskSlug) { - TimeSpan delay = _configuration.GetValue(taskSlug); - if (delay == default) - return DateTime.MaxValue; - return DateTime.Now + delay; + if (_options.CurrentValue.Scheduled.TryGetValue(taskSlug, out TimeSpan delay)) + return DateTime.Now + delay; + return DateTime.MaxValue; } /// diff --git a/Kyoo/Controllers/ThumbnailsManager.cs b/Kyoo/Controllers/ThumbnailsManager.cs index b75e3231..1e84cef6 100644 --- a/Kyoo/Controllers/ThumbnailsManager.cs +++ b/Kyoo/Controllers/ThumbnailsManager.cs @@ -1,26 +1,25 @@ using Kyoo.Models; -using Microsoft.Extensions.Configuration; using System; using System.IO; using System.Net; using System.Threading.Tasks; using JetBrains.Annotations; +using Kyoo.Models.Options; +using Microsoft.Extensions.Options; namespace Kyoo.Controllers { public class ThumbnailsManager : IThumbnailsManager { private readonly IFileManager _files; - private readonly string _peoplePath; - private readonly string _providerPath; + private readonly IOptionsMonitor _options; - public ThumbnailsManager(IConfiguration configuration, IFileManager files) + public ThumbnailsManager(IFileManager files, IOptionsMonitor options) { _files = files; - _peoplePath = Path.GetFullPath(configuration.GetValue("peoplePath")); - _providerPath = Path.GetFullPath(configuration.GetValue("providerPath")); - Directory.CreateDirectory(_peoplePath); - Directory.CreateDirectory(_providerPath); + _options = options; + Directory.CreateDirectory(_options.CurrentValue.PeoplePath); + Directory.CreateDirectory(_options.CurrentValue.ProviderPath); } private static async Task DownloadImage(string url, string localPath, string what) @@ -141,16 +140,18 @@ namespace Kyoo.Controllers { if (people == null) throw new ArgumentNullException(nameof(people)); - string thumbPath = Path.GetFullPath(Path.Combine(_peoplePath, $"{people.Slug}.jpg")); - return Task.FromResult(thumbPath.StartsWith(_peoplePath) ? thumbPath : null); + string peoplePath = _options.CurrentValue.PeoplePath; + string thumbPath = Path.GetFullPath(Path.Combine(peoplePath, $"{people.Slug}.jpg")); + return Task.FromResult(thumbPath.StartsWith(peoplePath) ? thumbPath : null); } public Task GetProviderLogo(Provider provider) { if (provider == null) throw new ArgumentNullException(nameof(provider)); - string thumbPath = Path.GetFullPath(Path.Combine(_providerPath, $"{provider.Slug}.{provider.LogoExtension}")); - return Task.FromResult(thumbPath.StartsWith(_providerPath) ? thumbPath : null); + string providerPath = _options.CurrentValue.ProviderPath; + string thumbPath = Path.GetFullPath(Path.Combine(providerPath, $"{provider.Slug}.{provider.LogoExtension}")); + return Task.FromResult(thumbPath.StartsWith(providerPath) ? thumbPath : null); } } } diff --git a/Kyoo/Controllers/Transcoder.cs b/Kyoo/Controllers/Transcoder.cs index 54cb5bfc..823aa9d2 100644 --- a/Kyoo/Controllers/Transcoder.cs +++ b/Kyoo/Controllers/Transcoder.cs @@ -3,7 +3,8 @@ using System.IO; using System.Runtime.InteropServices; using System.Threading.Tasks; using Kyoo.Models; -using Microsoft.Extensions.Configuration; +using Kyoo.Models.Options; +using Microsoft.Extensions.Options; using Stream = Kyoo.Models.Watch.Stream; // We use threads so tasks are not always awaited. @@ -66,20 +67,18 @@ namespace Kyoo.Controllers tracks = Array.Empty(); if (ptr != IntPtr.Zero) - free(ptr); // free_streams is not necesarry since the Marshal free the unmanaged pointers. + free(ptr); // free_streams is not necessary since the Marshal free the unmanaged pointers. return tracks; } } private readonly IFileManager _files; - private readonly string _transmuxPath; - private readonly string _transcodePath; + private readonly IOptions _options; - public Transcoder(IConfiguration config, IFileManager files) + public Transcoder(IFileManager files, IOptions options) { _files = files; - _transmuxPath = Path.GetFullPath(config.GetValue("transmuxTempPath")); - _transcodePath = Path.GetFullPath(config.GetValue("transcodeTempPath")); + _options = options; if (TranscoderAPI.init() != Marshal.SizeOf()) throw new BadTranscoderException(); @@ -100,7 +99,7 @@ namespace Kyoo.Controllers if (!File.Exists(episode.Path)) throw new ArgumentException("Path does not exists. Can't transcode."); - string folder = Path.Combine(_transmuxPath, episode.Slug); + string folder = Path.Combine(_options.Value.TransmuxPath, episode.Slug); string manifest = Path.Combine(folder, episode.Slug + ".m3u8"); float playableDuration = 0; bool transmuxFailed = false; diff --git a/Kyoo/CoreModule.cs b/Kyoo/CoreModule.cs index cbd6cbd9..726ed36a 100644 --- a/Kyoo/CoreModule.cs +++ b/Kyoo/CoreModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Kyoo.Controllers; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; using Kyoo.Tasks; using Microsoft.AspNetCore.Builder; @@ -90,8 +91,15 @@ namespace Kyoo /// public void Configure(IServiceCollection services, ICollection availableTypes) { - string publicUrl = _configuration.GetValue("publicUrl"); + string publicUrl = _configuration.GetPublicUrl(); + services.Configure(_configuration.GetSection(BasicOptions.Path)); + services.AddConfiguration(BasicOptions.Path); + services.Configure(_configuration.GetSection(TaskOptions.Path)); + services.AddConfiguration(TaskOptions.Path); + services.Configure(_configuration.GetSection(MediaOptions.Path)); + services.AddConfiguration(MediaOptions.Path); + services.AddControllers() .AddNewtonsoftJson(x => { diff --git a/Kyoo/Models/Options/BasicOptions.cs b/Kyoo/Models/Options/BasicOptions.cs new file mode 100644 index 00000000..95d4873a --- /dev/null +++ b/Kyoo/Models/Options/BasicOptions.cs @@ -0,0 +1,48 @@ +namespace Kyoo.Models.Options +{ + /// + /// The typed list of basic/global options for Kyoo + /// + public class BasicOptions + { + /// + /// The path of this list of options + /// + public const string Path = "Basics"; + + /// + /// The internal url where the server will listen + /// + public string Url { get; set; } = "http://*:5000"; + + /// + /// The public url that will be used in items response and in authentication server host. + /// + public string PublicUrl { get; set; } = "http://localhost:5000/"; + + /// + /// The path of the plugin directory. + /// + public string PluginPath { get; set; } = "plugins/"; + + /// + /// The path of the people pictures. + /// + public string PeoplePath { get; set; } = "people/"; + + /// + /// The path of providers icons. + /// + public string ProviderPath { get; set; } = "providers/"; + + /// + /// The temporary folder to cache transmuxed file. + /// + public string TransmuxPath { get; set; } = "cached/transmux"; + + /// + /// The temporary folder to cache transcoded file. + /// + public string TranscodePath { get; set; } = "cached/transcode"; + } +} \ No newline at end of file diff --git a/Kyoo/Models/Options/MediaOptions.cs b/Kyoo/Models/Options/MediaOptions.cs new file mode 100644 index 00000000..d53b13d0 --- /dev/null +++ b/Kyoo/Models/Options/MediaOptions.cs @@ -0,0 +1,23 @@ +namespace Kyoo.Models.Options +{ + /// + /// Options for media registering. + /// + public class MediaOptions + { + /// + /// The path of this options + /// + public const string Path = "Media"; + + /// + /// A regex for episodes + /// + public string Regex { get; set; } + + /// + /// A regex for subtitles + /// + public string SubtitleRegex { get; set; } + } +} \ No newline at end of file diff --git a/Kyoo/Models/Options/TaskOptions.cs b/Kyoo/Models/Options/TaskOptions.cs new file mode 100644 index 00000000..922a9ff4 --- /dev/null +++ b/Kyoo/Models/Options/TaskOptions.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace Kyoo.Models.Options +{ + /// + /// Options related to tasks + /// + public class TaskOptions + { + /// + /// The path of this options + /// + public const string Path = "Tasks"; + + /// + /// The number of tasks that can be run concurrently. + /// + public int Parallels { get; set; } + + /// + /// The delay of tasks that should be automatically started at fixed times. + /// + [UsedImplicitly] + public Dictionary Scheduled { get; set; } = new(); + } +} \ No newline at end of file diff --git a/Kyoo/Program.cs b/Kyoo/Program.cs index 32d763fd..db83cfd9 100644 --- a/Kyoo/Program.cs +++ b/Kyoo/Program.cs @@ -83,14 +83,16 @@ namespace Kyoo /// A new web host instance private static IWebHostBuilder CreateWebHostBuilder(string[] args) { + IConfiguration configuration = SetupConfig(new ConfigurationBuilder(), args).Build(); + return new WebHostBuilder() .UseContentRoot(AppDomain.CurrentDomain.BaseDirectory) - .UseConfiguration(SetupConfig(new ConfigurationBuilder(), args).Build()) + .UseConfiguration(configuration) .ConfigureAppConfiguration(x => SetupConfig(x, args)) .ConfigureLogging((context, builder) => { builder.AddConfiguration(context.Configuration.GetSection("logging")) - .AddSimpleConsole(x => + .AddSimpleConsole(x => { x.TimestampFormat = "[hh:mm:ss] "; }) @@ -107,6 +109,7 @@ namespace Kyoo .UseKestrel(options => { options.AddServerHeader = false; }) .UseIIS() .UseIISIntegration() + .UseUrls(configuration.GetValue("basics:urls")) .UseStartup(); } } diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index 361c1a27..8bd517cc 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -3,6 +3,7 @@ using System.IO; using Kyoo.Authentication; using Kyoo.Controllers; using Kyoo.Models; +using Kyoo.Models.Options; using Kyoo.Postgresql; using Kyoo.Tasks; using Microsoft.AspNetCore.Builder; @@ -12,6 +13,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Kyoo { @@ -38,7 +40,8 @@ namespace Kyoo /// A logger factory used to create a logger for the plugin manager. public Startup(IServiceProvider hostProvider, IConfiguration configuration, ILoggerFactory loggerFactory, IWebHostEnvironment host) { - _plugins = new PluginManager(hostProvider, configuration, loggerFactory.CreateLogger()); + IOptionsMonitor options = hostProvider.GetService>(); + _plugins = new PluginManager(hostProvider, options, loggerFactory.CreateLogger()); // TODO remove postgres from here and load it like a normal plugin. _plugins.LoadPlugins(new IPlugin[] { diff --git a/Kyoo/Views/CollectionApi.cs b/Kyoo/Views/CollectionApi.cs index 214cb60d..783bb67b 100644 --- a/Kyoo/Views/CollectionApi.cs +++ b/Kyoo/Views/CollectionApi.cs @@ -6,8 +6,9 @@ using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; using Kyoo.CommonApi; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -19,8 +20,8 @@ namespace Kyoo.Api { private readonly ILibraryManager _libraryManager; - public CollectionApi(ILibraryManager libraryManager, IConfiguration configuration) - : base(libraryManager.CollectionRepository, configuration) + public CollectionApi(ILibraryManager libraryManager, IOptions options) + : base(libraryManager.CollectionRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; } diff --git a/Kyoo/Views/ConfigurationApi.cs b/Kyoo/Views/ConfigurationApi.cs index e8829e3b..833d5993 100644 --- a/Kyoo/Views/ConfigurationApi.cs +++ b/Kyoo/Views/ConfigurationApi.cs @@ -1,13 +1,9 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Kyoo.Controllers; -using Kyoo.Models; using Kyoo.Models.Exceptions; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; namespace Kyoo.Api { @@ -19,28 +15,18 @@ namespace Kyoo.Api [ApiController] public class ConfigurationApi : Controller { + /// + /// The configuration manager used to retrieve and edit configuration values (while being type safe). + /// private readonly IConfigurationManager _manager; - /// - /// The configuration to retrieve and edit. - /// - private readonly IConfiguration _configuration; - - /// - /// The strongly typed list of options - /// - private readonly Dictionary _references; - /// /// Create a new using the given configuration. /// - /// The configuration to use. - /// The strongly typed option list. - public ConfigurationApi(IConfigurationManager manager, IConfiguration configuration, IEnumerable references) + /// The configuration manager used to retrieve and edit configuration values + public ConfigurationApi(IConfigurationManager manager) { _manager = manager; - _configuration = configuration; - _references = references.ToDictionary(x => x.Path, x => x.Type, StringComparer.OrdinalIgnoreCase); } /// @@ -54,16 +40,14 @@ namespace Kyoo.Api [Permission(nameof(ConfigurationApi), Kind.Admin)] public ActionResult GetConfiguration(string slug) { - slug = slug.Replace("__", ":"); - // TODO handle lists and dictionaries. - if (!_references.TryGetValue(slug, out Type type)) + try + { + return _manager.GetValue(slug); + } + catch (ItemNotFoundException) + { return NotFound(); - object ret = _configuration.GetValue(type, slug); - if (ret != null) - return ret; - object option = Activator.CreateInstance(type); - _configuration.Bind(slug, option); - return option; + } } /// diff --git a/Kyoo/Views/EpisodeApi.cs b/Kyoo/Views/EpisodeApi.cs index c87a2704..490d0b34 100644 --- a/Kyoo/Views/EpisodeApi.cs +++ b/Kyoo/Views/EpisodeApi.cs @@ -7,8 +7,9 @@ using System.Threading.Tasks; using Kyoo.CommonApi; using Kyoo.Controllers; using Kyoo.Models.Exceptions; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -23,10 +24,10 @@ namespace Kyoo.Api private readonly IFileManager _files; public EpisodeApi(ILibraryManager libraryManager, - IConfiguration configuration, + IOptions options, IFileManager files, IThumbnailsManager thumbnails) - : base(libraryManager.EpisodeRepository, configuration) + : base(libraryManager.EpisodeRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; _files = files; diff --git a/Kyoo/Views/GenreApi.cs b/Kyoo/Views/GenreApi.cs index 83ebb38d..e494665d 100644 --- a/Kyoo/Views/GenreApi.cs +++ b/Kyoo/Views/GenreApi.cs @@ -5,9 +5,10 @@ using System.Threading.Tasks; using Kyoo.CommonApi; using Kyoo.Controllers; using Kyoo.Models; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -19,8 +20,8 @@ namespace Kyoo.Api { private readonly ILibraryManager _libraryManager; - public GenreApi(ILibraryManager libraryManager, IConfiguration config) - : base(libraryManager.GenreRepository, config) + public GenreApi(ILibraryManager libraryManager, IOptions options) + : base(libraryManager.GenreRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; } diff --git a/Kyoo/Views/LibraryApi.cs b/Kyoo/Views/LibraryApi.cs index bbcd7a90..93cd57d3 100644 --- a/Kyoo/Views/LibraryApi.cs +++ b/Kyoo/Views/LibraryApi.cs @@ -6,8 +6,9 @@ using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; using Kyoo.CommonApi; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -20,8 +21,8 @@ namespace Kyoo.Api private readonly ILibraryManager _libraryManager; private readonly ITaskManager _taskManager; - public LibraryApi(ILibraryManager libraryManager, ITaskManager taskManager, IConfiguration configuration) - : base(libraryManager.LibraryRepository, configuration) + public LibraryApi(ILibraryManager libraryManager, ITaskManager taskManager, IOptions options) + : base(libraryManager.LibraryRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; _taskManager = taskManager; diff --git a/Kyoo/Views/LibraryItemApi.cs b/Kyoo/Views/LibraryItemApi.cs index 6cd81b05..5fd6b7e3 100644 --- a/Kyoo/Views/LibraryItemApi.cs +++ b/Kyoo/Views/LibraryItemApi.cs @@ -6,9 +6,10 @@ using Kyoo.CommonApi; using Kyoo.Controllers; using Kyoo.Models; using Kyoo.Models.Exceptions; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -22,10 +23,10 @@ namespace Kyoo.Api private readonly string _baseURL; - public LibraryItemApi(ILibraryItemRepository libraryItems, IConfiguration configuration) + public LibraryItemApi(ILibraryItemRepository libraryItems, IOptions options) { _libraryItems = libraryItems; - _baseURL = configuration.GetValue("publicUrl").TrimEnd('/'); + _baseURL = options.Value.PublicUrl; } [HttpGet] diff --git a/Kyoo/Views/PeopleApi.cs b/Kyoo/Views/PeopleApi.cs index 724198e5..c421fc16 100644 --- a/Kyoo/Views/PeopleApi.cs +++ b/Kyoo/Views/PeopleApi.cs @@ -5,9 +5,10 @@ using Kyoo.CommonApi; using Kyoo.Controllers; using Kyoo.Models; using Kyoo.Models.Exceptions; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -21,10 +22,10 @@ namespace Kyoo.Api private readonly IThumbnailsManager _thumbs; public PeopleApi(ILibraryManager libraryManager, - IConfiguration configuration, + IOptions options, IFileManager files, IThumbnailsManager thumbs) - : base(libraryManager.PeopleRepository, configuration) + : base(libraryManager.PeopleRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; _files = files; diff --git a/Kyoo/Views/ProviderApi.cs b/Kyoo/Views/ProviderApi.cs index 133c15fd..eac22675 100644 --- a/Kyoo/Views/ProviderApi.cs +++ b/Kyoo/Views/ProviderApi.cs @@ -2,9 +2,10 @@ using System.Threading.Tasks; using Kyoo.CommonApi; using Kyoo.Controllers; using Kyoo.Models; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -19,10 +20,10 @@ namespace Kyoo.Api private readonly IFileManager _files; public ProviderApi(ILibraryManager libraryManager, - IConfiguration config, + IOptions options, IFileManager files, IThumbnailsManager thumbnails) - : base(libraryManager.ProviderRepository, config) + : base(libraryManager.ProviderRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; _files = files; diff --git a/Kyoo/Views/SeasonApi.cs b/Kyoo/Views/SeasonApi.cs index 1987e7c5..a32b0b1c 100644 --- a/Kyoo/Views/SeasonApi.cs +++ b/Kyoo/Views/SeasonApi.cs @@ -6,8 +6,9 @@ using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Linq; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -22,10 +23,10 @@ namespace Kyoo.Api private readonly IFileManager _files; public SeasonApi(ILibraryManager libraryManager, - IConfiguration configuration, + IOptions options, IThumbnailsManager thumbs, IFileManager files) - : base(libraryManager.SeasonRepository, configuration) + : base(libraryManager.SeasonRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; _thumbs = thumbs; diff --git a/Kyoo/Views/ShowApi.cs b/Kyoo/Views/ShowApi.cs index 8b73afd2..4e121d75 100644 --- a/Kyoo/Views/ShowApi.cs +++ b/Kyoo/Views/ShowApi.cs @@ -8,8 +8,9 @@ using System.Threading.Tasks; using Kyoo.CommonApi; using Kyoo.Controllers; using Kyoo.Models.Exceptions; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -26,8 +27,8 @@ namespace Kyoo.Api public ShowApi(ILibraryManager libraryManager, IFileManager files, IThumbnailsManager thumbs, - IConfiguration configuration) - : base(libraryManager.ShowRepository, configuration) + IOptions options) + : base(libraryManager.ShowRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; _files = files; diff --git a/Kyoo/Views/StudioApi.cs b/Kyoo/Views/StudioApi.cs index 657988bb..a6957e33 100644 --- a/Kyoo/Views/StudioApi.cs +++ b/Kyoo/Views/StudioApi.cs @@ -5,9 +5,10 @@ using System.Threading.Tasks; using Kyoo.CommonApi; using Kyoo.Controllers; using Kyoo.Models; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -19,8 +20,8 @@ namespace Kyoo.Api { private readonly ILibraryManager _libraryManager; - public StudioApi(ILibraryManager libraryManager, IConfiguration config) - : base(libraryManager.StudioRepository, config) + public StudioApi(ILibraryManager libraryManager, IOptions options) + : base(libraryManager.StudioRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; } diff --git a/Kyoo/Views/TrackApi.cs b/Kyoo/Views/TrackApi.cs index 77f8669e..0eadaf3b 100644 --- a/Kyoo/Views/TrackApi.cs +++ b/Kyoo/Views/TrackApi.cs @@ -4,9 +4,10 @@ using Kyoo.CommonApi; using Kyoo.Controllers; using Kyoo.Models; using Kyoo.Models.Exceptions; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -18,8 +19,8 @@ namespace Kyoo.Api { private readonly ILibraryManager _libraryManager; - public TrackApi(ILibraryManager libraryManager, IConfiguration configuration) - : base(libraryManager.TrackRepository, configuration) + public TrackApi(ILibraryManager libraryManager, IOptions options) + : base(libraryManager.TrackRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; } diff --git a/Kyoo/Views/VideoApi.cs b/Kyoo/Views/VideoApi.cs index 050b82b4..5c48f7bc 100644 --- a/Kyoo/Views/VideoApi.cs +++ b/Kyoo/Views/VideoApi.cs @@ -2,11 +2,12 @@ using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Kyoo.Models.Exceptions; +using Kyoo.Models.Options; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Options; namespace Kyoo.Api { @@ -16,20 +17,18 @@ namespace Kyoo.Api { private readonly ILibraryManager _libraryManager; private readonly ITranscoder _transcoder; + private readonly IOptions _options; private readonly IFileManager _files; - private readonly string _transmuxPath; - private readonly string _transcodePath; public VideoApi(ILibraryManager libraryManager, ITranscoder transcoder, - IConfiguration config, + IOptions options, IFileManager files) { _libraryManager = libraryManager; _transcoder = transcoder; + _options = options; _files = files; - _transmuxPath = config.GetValue("transmuxTempPath"); - _transcodePath = config.GetValue("transcodeTempPath"); } public override void OnActionExecuted(ActionExecutedContext ctx) @@ -101,7 +100,7 @@ namespace Kyoo.Api [Permission("video", Kind.Read)] public IActionResult GetTransmuxedChunk(string episodeLink, string chunk) { - string path = Path.GetFullPath(Path.Combine(_transmuxPath, episodeLink)); + string path = Path.GetFullPath(Path.Combine(_options.Value.TransmuxPath, episodeLink)); path = Path.Combine(path, "segments", chunk); return PhysicalFile(path, "video/MP2T"); } @@ -110,7 +109,7 @@ namespace Kyoo.Api [Permission("video", Kind.Read)] public IActionResult GetTranscodedChunk(string episodeLink, string chunk) { - string path = Path.GetFullPath(Path.Combine(_transcodePath, episodeLink)); + string path = Path.GetFullPath(Path.Combine(_options.Value.TranscodePath, episodeLink)); path = Path.Combine(path, "segments", chunk); return PhysicalFile(path, "video/MP2T"); } diff --git a/Kyoo/settings.json b/Kyoo/settings.json index 114636fe..71e2574d 100644 --- a/Kyoo/settings.json +++ b/Kyoo/settings.json @@ -1,7 +1,14 @@ { - "server.urls": "http://*:5000", - "publicUrl": "http://localhost:5000/", - + "basics": { + "url": "http://*:5000", + "publicUrl": "http://localhost:5000/", + "pluginsPath": "plugins/", + "peoplePath": "people/", + "providerPath": "providers/", + "transmuxPath": "cached/transmux", + "transcodePath": "cached/transcode" + }, + "database": { "postgres": { "server": "127.0.0.1", @@ -24,6 +31,18 @@ "Kyoo": "Trace" } }, + + "tasks": { + "parallels": "1", + "scheduled": { + "scan": "24:00:00" + } + }, + + "media": { + "regex": "(?:\\/(?.*?))?\\/(?.*?)(?: \\(\\d+\\))?\\/\\k(?: \\(\\d+\\))?(?:(?: S(?\\d+)E(?\\d+))| (?\\d+))?.*$", + "subtitleRegex": "^(?.*)\\.(?\\w{1,3})\\.(?default\\.)?(?forced\\.)?.*$" + }, "authentication": { "certificate": { @@ -37,20 +56,5 @@ }, "profilePicturePath": "users/", "clients": [] - }, - - - "parallelTasks": "1", - - "scheduledTasks": { - "scan": "24:00:00" - }, - - "transmuxTempPath": "cached/kyoo/transmux", - "transcodeTempPath": "cached/kyoo/transcode", - "peoplePath": "people", - "providerPath": "providers", - "plugins": "plugins/", - "regex": "(?:\\/(?.*?))?\\/(?.*?)(?: \\(\\d+\\))?\\/\\k(?: \\(\\d+\\))?(?:(?: S(?\\d+)E(?\\d+))| (?\\d+))?.*$", - "subtitleRegex": "^(?.*)\\.(?\\w{1,3})\\.(?default\\.)?(?forced\\.)?.*$" + } }