diff --git a/back/src/Kyoo.Abstractions/Controllers/IIdentifier.cs b/back/src/Kyoo.Abstractions/Controllers/IIdentifier.cs deleted file mode 100644 index dd7ce855..00000000 --- a/back/src/Kyoo.Abstractions/Controllers/IIdentifier.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System.Threading.Tasks; -using Kyoo.Abstractions.Models; -using Kyoo.Abstractions.Models.Exceptions; - -namespace Kyoo.Abstractions.Controllers -{ - /// - /// An interface to identify episodes, shows and metadata based on the episode file. - /// - public interface IIdentifier - { - /// - /// Identify a path and return the parsed metadata. - /// - /// The path of the episode file to parse. - /// - /// The identifier could not work for the given path. - /// - /// - /// A tuple of models representing parsed metadata. - /// If no metadata could be parsed for a type, null can be returned. - /// - Task<(Collection, Show, Season, Episode)> Identify(string path); - - /// - /// Identify an external subtitle or track file from it's path and return the parsed metadata. - /// - /// The path of the external track file to parse. - /// - /// The identifier could not work for the given path. - /// - /// - /// The metadata of the track identified. - /// - Task IdentifyTrack(string path); - } -} diff --git a/back/src/Kyoo.Abstractions/Controllers/IMetadataProvider.cs b/back/src/Kyoo.Abstractions/Controllers/IMetadataProvider.cs deleted file mode 100644 index feb9d56d..00000000 --- a/back/src/Kyoo.Abstractions/Controllers/IMetadataProvider.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System.Collections.Generic; -using System.Threading.Tasks; -using JetBrains.Annotations; -using Kyoo.Abstractions.Models; - -namespace Kyoo.Abstractions.Controllers -{ - /// - /// An interface to automatically retrieve metadata from external providers. - /// - public interface IMetadataProvider - { - /// - /// The corresponding to this provider. - /// This allow to map metadata to a provider, keep metadata links and - /// know witch is used for a specific . - /// - Provider Provider { get; } - - /// - /// Return a new item with metadata from your provider. - /// - /// - /// The item to retrieve metadata from. Most of the time, only the name will be available but other - /// properties may be filed by other providers before a call to this method. This can allow you to identify - /// the collection on your provider. - /// - /// - /// You must not use metadata from the given . - /// Merging metadata is the job of Kyoo, a complex is given - /// to make a precise search and give you every available properties, not to discard properties. - /// - /// The type of resource to retrieve metadata for. - /// A new containing metadata from your provider or null - [ItemCanBeNull] - Task Get([NotNull] T item) - where T : class, IResource; - - /// - /// Search for a specific type of items with a given query. - /// - /// The search query to use. - /// The type of resource to search metadata for. - /// The list of items that could be found on this specific provider. - [ItemNotNull] - Task> Search(string query) - where T : class, IResource; - } - - /// - /// A special that merge results. - /// This interface exists to specify witch provider to use but it can be used like any other metadata provider. - /// - public abstract class AProviderComposite : IMetadataProvider - { - /// - [ItemNotNull] - public abstract Task Get(T item) - where T : class, IResource; - - /// - public abstract Task> Search(string query) - where T : class, IResource; - - /// - /// Since this is a composite and not a real provider, no metadata is available. - /// It is not meant to be stored or selected. This class will handle merge based on what is required. - /// - public Provider Provider => null; - - /// - /// Select witch providers to use. - /// The associated with the given will be used. - /// - /// The list of providers to use - public abstract void UseProviders(IEnumerable providers); - } -} diff --git a/back/src/Kyoo.Abstractions/Controllers/IPlugin.cs b/back/src/Kyoo.Abstractions/Controllers/IPlugin.cs index c7b09229..a61d7b50 100644 --- a/back/src/Kyoo.Abstractions/Controllers/IPlugin.cs +++ b/back/src/Kyoo.Abstractions/Controllers/IPlugin.cs @@ -34,32 +34,11 @@ namespace Kyoo.Abstractions.Controllers [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] public interface IPlugin { - /// - /// A slug to identify this plugin in queries. - /// - string Slug { get; } - /// /// The name of the plugin /// string Name { get; } - /// - /// The description of this plugin. This will be displayed on the "installed plugins" page. - /// - string Description { get; } - - /// - /// true if the plugin should be enabled, false otherwise. - /// If a plugin is not enabled, no configure method will be called. - /// This allow one to enable a plugin if a specific configuration value is set or if the environment contains - /// the right settings. - /// - /// - /// By default, a plugin is always enabled. This method can be overriden to change this behavior. - /// - virtual bool Enabled => true; - /// /// A list of types that will be available via the IOptions interfaces and will be listed inside /// an IConfiguration. @@ -73,7 +52,7 @@ namespace Kyoo.Abstractions.Controllers /// An optional configuration step to allow a plugin to change asp net configurations. /// /// - virtual IEnumerable ConfigureSteps => ArraySegment.Empty; + IEnumerable ConfigureSteps => ArraySegment.Empty; /// /// A configure method that will be run on plugin's startup. @@ -94,15 +73,5 @@ namespace Kyoo.Abstractions.Controllers { // Skipped } - - /// - /// An optional function to execute and initialize your plugin. - /// It can be used to initialize a database connection, fill initial data or anything. - /// - /// A service provider to request services - void Initialize(IServiceProvider provider) - { - // Skipped - } } } diff --git a/back/src/Kyoo.Abstractions/Controllers/ITask.cs b/back/src/Kyoo.Abstractions/Controllers/ITask.cs deleted file mode 100644 index 7c9f749d..00000000 --- a/back/src/Kyoo.Abstractions/Controllers/ITask.cs +++ /dev/null @@ -1,212 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using JetBrains.Annotations; -using Kyoo.Abstractions.Models; -using Kyoo.Abstractions.Models.Exceptions; - -namespace Kyoo.Abstractions.Controllers -{ - /// - /// A common interface that tasks should implement. - /// - public interface ITask - { - /// - /// The list of parameters - /// - /// - /// All parameters that this task as. Every one of them will be given to the run function with a value. - /// - public TaskParameters GetParameters(); - - /// - /// Start this task. - /// - /// - /// The list of parameters. - /// - /// - /// The progress reporter. Used to inform the sender the percentage of completion of this task - /// . - /// A token to request the task's cancellation. - /// If this task is not cancelled quickly, it might be killed by the runner. - /// - /// - /// An exception meaning that the task has failed for handled reasons like invalid arguments, - /// invalid environment, missing plugins or failures not related to a default in the code. - /// This exception allow the task to display a failure message to the end user while others exceptions - /// will be displayed as unhandled exceptions and display a stack trace. - /// - /// A representing the asynchronous operation. - public Task Run([NotNull] TaskParameters arguments, - [NotNull] IProgress progress, - CancellationToken cancellationToken); - } - - /// - /// A single task parameter. This struct contains metadata to display and utility functions to get them in the task. - /// - /// This struct will be used to generate the swagger documentation of the task. - public record TaskParameter - { - /// - /// The name of this parameter. - /// - public string Name { get; init; } - - /// - /// The description of this parameter. - /// - public string Description { get; init; } - - /// - /// The type of this parameter. - /// - public Type Type { get; init; } - - /// - /// Is this parameter required or can it be ignored? - /// - public bool IsRequired { get; init; } - - /// - /// The default value of this object. - /// - public object DefaultValue { get; init; } - - /// - /// The value of the parameter. - /// - private object _Value { get; init; } - - /// - /// Create a new task parameter. - /// - /// The name of the parameter - /// The description of the parameter - /// The type of the parameter. - /// A new task parameter. - public static TaskParameter Create(string name, string description) - { - return new TaskParameter - { - Name = name, - Description = description, - Type = typeof(T) - }; - } - - /// - /// Create a new required task parameter. - /// - /// The name of the parameter - /// The description of the parameter - /// The type of the parameter. - /// A new task parameter. - public static TaskParameter CreateRequired(string name, string description) - { - return new TaskParameter - { - Name = name, - Description = description, - Type = typeof(T), - IsRequired = true - }; - } - - /// - /// Create a parameter's value to give to a task. - /// - /// The name of the parameter - /// The value of the parameter. It's type will be used as parameter's type. - /// The type of the parameter - /// A TaskParameter that can be used as value. - public static TaskParameter CreateValue(string name, T value) - { - return new() - { - Name = name, - Type = typeof(T), - _Value = value - }; - } - - /// - /// Create a parameter's value for the current parameter. - /// - /// The value to use - /// A new parameter's value for this current parameter - public TaskParameter CreateValue(object value) - { - return this with { _Value = value }; - } - - /// - /// Get the value of this parameter. If the value is of the wrong type, it will be converted. - /// - /// The type of this parameter - /// The value of this parameter. - public T As() - { - if (typeof(T) == typeof(object)) - return (T)_Value; - - if (_Value is IResource resource) - { - if (typeof(T) == typeof(string)) - return (T)(object)resource.Slug; - if (typeof(T) == typeof(int)) - return (T)(object)resource.ID; - } - - return (T)Convert.ChangeType(_Value, typeof(T)); - } - } - - /// - /// A parameters container implementing an indexer to allow simple usage of parameters. - /// - public class TaskParameters : List - { - /// - /// An indexer that return the parameter with the specified name. - /// - /// The name of the task (case sensitive) - public TaskParameter this[string name] => this.FirstOrDefault(x => x.Name == name); - - /// - /// Create a new, empty, - /// - public TaskParameters() { } - - /// - /// Create a with an initial parameters content. - /// - /// The list of parameters - public TaskParameters(IEnumerable parameters) - { - AddRange(parameters); - } - } -} diff --git a/back/src/Kyoo.Abstractions/Controllers/ITaskManager.cs b/back/src/Kyoo.Abstractions/Controllers/ITaskManager.cs deleted file mode 100644 index 556f3631..00000000 --- a/back/src/Kyoo.Abstractions/Controllers/ITaskManager.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Threading; -using Kyoo.Abstractions.Models.Attributes; -using Kyoo.Abstractions.Models.Exceptions; - -namespace Kyoo.Abstractions.Controllers -{ - /// - /// A service to handle long running tasks. - /// - /// The concurrent number of running tasks is implementation dependent. - public interface ITaskManager - { - /// - /// Start a new task (or queue it). - /// - /// - /// The slug of the task to run. - /// - /// - /// A progress reporter to know the percentage of completion of the task. - /// - /// - /// A list of arguments to pass to the task. An automatic conversion will be made if arguments to not fit. - /// - /// - /// A custom cancellation token for the task. - /// - /// - /// If the number of arguments is invalid, if an argument can't be converted or if the task finds the argument - /// invalid. - /// - /// - /// The task could not be found. - /// - void StartTask(string taskSlug, - [NotNull] IProgress progress, - Dictionary arguments = null, - CancellationToken? cancellationToken = null); - - /// - /// Start a new task (or queue it). - /// - /// - /// A progress reporter to know the percentage of completion of the task. - /// - /// - /// A list of arguments to pass to the task. An automatic conversion will be made if arguments to not fit. - /// - /// - /// The type of the task to start. - /// - /// - /// A custom cancellation token for the task. - /// - /// - /// If the number of arguments is invalid, if an argument can't be converted or if the task finds the argument - /// invalid. - /// - /// - /// The task could not be found. - /// - void StartTask([NotNull] IProgress progress, - Dictionary arguments = null, - CancellationToken? cancellationToken = null) - where T : ITask; - - /// - /// Get all currently running tasks - /// - /// A list of currently running tasks. - ICollection<(TaskMetadataAttribute, ITask)> GetRunningTasks(); - - /// - /// Get all available tasks - /// - /// A list of every tasks that this instance know. - ICollection GetAllTasks(); - } -} diff --git a/back/src/Kyoo.Abstractions/Models/Exceptions/IdentificationFailedException.cs b/back/src/Kyoo.Abstractions/Models/Exceptions/IdentificationFailedException.cs deleted file mode 100644 index 0549c444..00000000 --- a/back/src/Kyoo.Abstractions/Models/Exceptions/IdentificationFailedException.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Runtime.Serialization; -using Kyoo.Abstractions.Controllers; - -namespace Kyoo.Abstractions.Models.Exceptions -{ - /// - /// An exception raised when an failed. - /// - [Serializable] - public class IdentificationFailedException : Exception - { - /// - /// Create a new with a default message. - /// - public IdentificationFailedException() - : base("An identification failed.") - { } - - /// - /// Create a new with a custom message. - /// - /// The message to use. - public IdentificationFailedException(string message) - : base(message) - { } - - /// - /// The serialization constructor - /// - /// Serialization infos - /// The serialization context - protected IdentificationFailedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } -} diff --git a/back/src/Kyoo.Abstractions/Models/Exceptions/TaskFailedException.cs b/back/src/Kyoo.Abstractions/Models/Exceptions/TaskFailedException.cs deleted file mode 100644 index a40b962c..00000000 --- a/back/src/Kyoo.Abstractions/Models/Exceptions/TaskFailedException.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Runtime.Serialization; -using Kyoo.Abstractions.Controllers; - -namespace Kyoo.Abstractions.Models.Exceptions -{ - /// - /// An exception raised when an failed. - /// - [Serializable] - public class TaskFailedException : AggregateException - { - /// - /// Create a new with a default message. - /// - public TaskFailedException() - : base("A task failed.") - { } - - /// - /// Create a new with a custom message. - /// - /// The message to use. - public TaskFailedException(string message) - : base(message) - { } - - /// - /// Create a new wrapping another exception. - /// - /// The exception to wrap. - public TaskFailedException(Exception exception) - : base(exception) - { } - - /// - /// The serialization constructor - /// - /// Serialization infos - /// The serialization context - protected TaskFailedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } -} diff --git a/back/src/Kyoo.Abstractions/Module.cs b/back/src/Kyoo.Abstractions/Module.cs index 932777fd..dc0edc67 100644 --- a/back/src/Kyoo.Abstractions/Module.cs +++ b/back/src/Kyoo.Abstractions/Module.cs @@ -16,12 +16,10 @@ // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . -using System; using Autofac; using Autofac.Builder; using Kyoo.Abstractions.Controllers; using Kyoo.Utils; -using Microsoft.Extensions.Configuration; namespace Kyoo.Abstractions { @@ -30,32 +28,6 @@ namespace Kyoo.Abstractions /// public static class Module { - /// - /// Register a new task to the container. - /// - /// The container - /// The type of the task - /// The registration builder of this new task. That can be used to edit the registration. - public static IRegistrationBuilder - RegisterTask(this ContainerBuilder builder) - where T : class, ITask - { - return builder.RegisterType().As(); - } - - /// - /// Register a new metadata provider to the container. - /// - /// The container - /// The type of the task - /// The registration builder of this new provider. That can be used to edit the registration. - public static IRegistrationBuilder - RegisterProvider(this ContainerBuilder builder) - where T : class, IMetadataProvider - { - return builder.RegisterType().As().InstancePerLifetimeScope(); - } - /// /// Register a new repository to the container. /// diff --git a/back/src/Kyoo.Authentication/AuthenticationModule.cs b/back/src/Kyoo.Authentication/AuthenticationModule.cs index c33408ab..bbbec812 100644 --- a/back/src/Kyoo.Authentication/AuthenticationModule.cs +++ b/back/src/Kyoo.Authentication/AuthenticationModule.cs @@ -35,15 +35,9 @@ namespace Kyoo.Authentication /// public class AuthenticationModule : IPlugin { - /// - public string Slug => "auth"; - /// public string Name => "Authentication"; - /// - public string Description => "Enable an authentication/permission system for Kyoo (via Jwt or ApiKeys)."; - /// public Dictionary Configuration => new() { diff --git a/back/src/Kyoo.Core/Controllers/ProviderComposite.cs b/back/src/Kyoo.Core/Controllers/ProviderComposite.cs deleted file mode 100644 index e44da72e..00000000 --- a/back/src/Kyoo.Core/Controllers/ProviderComposite.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models; -using Kyoo.Utils; -using Microsoft.Extensions.Logging; - -namespace Kyoo.Core.Controllers -{ - /// - /// A metadata provider composite that merge results from all available providers. - /// - public class ProviderComposite : AProviderComposite - { - /// - /// The list of metadata providers - /// - private readonly ICollection _providers; - - /// - /// The logger used to print errors. - /// - private readonly ILogger _logger; - - /// - /// The list of selected providers. If no provider has been selected, this is null. - /// - private ICollection _selectedProviders; - - /// - /// Create a new with a list of available providers. - /// - /// The list of providers to merge. - /// The logger used to print errors. - public ProviderComposite(IEnumerable providers, ILogger logger) - { - _providers = providers.ToArray(); - _logger = logger; - } - - /// - public override void UseProviders(IEnumerable providers) - { - _selectedProviders = providers.ToArray(); - } - - /// - /// Return the list of providers that should be used for queries. - /// - /// The list of providers to use, respecting the . - private IEnumerable _GetProviders() - { - return _selectedProviders? - .Select(x => _providers.FirstOrDefault(y => y.Provider.Slug == x.Slug)) - .Where(x => x != null) - ?? _providers; - } - - /// - public override async Task Get(T item) - { - T ret = item; - - foreach (IMetadataProvider provider in _GetProviders()) - { - try - { - ret = Merger.Merge(ret, await provider.Get(ret)); - } - catch (Exception ex) - { - _logger.LogError(ex, "The provider {Provider} could not get a {Type}", - provider.Provider.Name, typeof(T).Name); - } - } - - return ret; - } - - /// - public override async Task> Search(string query) - { - List ret = new(); - - foreach (IMetadataProvider provider in _GetProviders()) - { - try - { - ret.AddRange(await provider.Search(query)); - } - catch (Exception ex) - { - _logger.LogError(ex, "The provider {Provider} could not search for {Type}", - provider.Provider.Name, typeof(T).Name); - } - } - - return ret; - } - } -} diff --git a/back/src/Kyoo.Core/Controllers/RegexIdentifier.cs b/back/src/Kyoo.Core/Controllers/RegexIdentifier.cs deleted file mode 100644 index 77a117e0..00000000 --- a/back/src/Kyoo.Core/Controllers/RegexIdentifier.cs +++ /dev/null @@ -1,160 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models; -using Kyoo.Abstractions.Models.Exceptions; -using Kyoo.Core.Models; -using Kyoo.Core.Models.Options; -using Kyoo.Utils; -using Microsoft.Extensions.Options; - -namespace Kyoo.Core.Controllers -{ - /// - /// An identifier that use a regex to extract basics metadata. - /// - public class RegexIdentifier : IIdentifier - { - /// - /// The configuration of kyoo to retrieve the identifier regex. - /// - private readonly IOptionsMonitor _configuration; - - /// - /// The library manager used to retrieve libraries paths. - /// - private readonly ILibraryManager _libraryManager; - - /// - /// Create a new . - /// - /// The regex patterns to use. - /// The library manager used to retrieve libraries paths. - public RegexIdentifier(IOptionsMonitor configuration, ILibraryManager libraryManager) - { - _configuration = configuration; - _libraryManager = libraryManager; - } - - /// - /// Retrieve the relative path of an episode or subtitle. - /// - /// The full path of the episode - /// The path relative to the library root. - private async Task _GetRelativePath(string path) - { - string libraryPath = (await _libraryManager.GetAll()) - .SelectMany(x => x.Paths) - .Where(path.StartsWith) - .MaxBy(x => x.Length); - return path[(libraryPath?.Length ?? 0)..]; - } - - /// - public async Task<(Collection, Show, Season, Episode)> Identify(string path) - { - string relativePath = await _GetRelativePath(path); - Match match = _configuration.CurrentValue.Regex - .Select(x => new Regex(x, RegexOptions.IgnoreCase | RegexOptions.Compiled)) - .Select(x => x.Match(relativePath)) - .FirstOrDefault(x => x.Success); - - if (match == null) - throw new IdentificationFailedException($"The episode at {path} does not match the episode's regex."); - - (Collection collection, Show show, Season season, Episode episode) ret = ( - collection: new Collection - { - Slug = Utility.ToSlug(match.Groups["Collection"].Value), - Name = match.Groups["Collection"].Value - }, - show: new Show - { - Slug = Utility.ToSlug(match.Groups["Show"].Value), - Title = match.Groups["Show"].Value, - Path = Path.GetDirectoryName(path), - StartAir = match.Groups["StartYear"].Success - ? new DateTime(int.Parse(match.Groups["StartYear"].Value), 1, 1) - : null - }, - season: null, - episode: new Episode - { - SeasonNumber = match.Groups["Season"].Success - ? int.Parse(match.Groups["Season"].Value) - : null, - EpisodeNumber = match.Groups["Episode"].Success - ? int.Parse(match.Groups["Episode"].Value) - : null, - AbsoluteNumber = match.Groups["Absolute"].Success - ? int.Parse(match.Groups["Absolute"].Value) - : null, - Path = path - } - ); - - if (ret.episode.SeasonNumber.HasValue) - ret.season = new Season { SeasonNumber = ret.episode.SeasonNumber.Value }; - - if (ret.episode.SeasonNumber == null && ret.episode.EpisodeNumber == null - && ret.episode.AbsoluteNumber == null) - { - ret.show.IsMovie = true; - ret.episode.Title = ret.show.Title; - } - - return ret; - } - - /// - public Task IdentifyTrack(string path) - { - Match match = _configuration.CurrentValue.SubtitleRegex - .Select(x => new Regex(x, RegexOptions.IgnoreCase | RegexOptions.Compiled)) - .Select(x => x.Match(path)) - .FirstOrDefault(x => x.Success); - - if (match == null) - throw new IdentificationFailedException($"The subtitle at {path} does not match the subtitle's regex."); - - string episodePath = match.Groups["Episode"].Value; - string extension = Path.GetExtension(path); - return Task.FromResult(new Track - { - Type = StreamType.Subtitle, - Language = match.Groups["Language"].Value, - IsDefault = match.Groups["Default"].Success, - IsForced = match.Groups["Forced"].Success, - Codec = FileExtensions.SubtitleExtensions.GetValueOrDefault(extension, extension[1..]), - IsExternal = true, - Path = path, - Episode = new Episode - { - Path = episodePath - } - }); - } - } -} diff --git a/back/src/Kyoo.Core/CoreModule.cs b/back/src/Kyoo.Core/CoreModule.cs index 0436779b..eaac6cc1 100644 --- a/back/src/Kyoo.Core/CoreModule.cs +++ b/back/src/Kyoo.Core/CoreModule.cs @@ -24,15 +24,12 @@ using Kyoo.Abstractions; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models.Utils; using Kyoo.Core.Controllers; -using Kyoo.Core.Models.Options; -using Kyoo.Core.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using IMetadataProvider = Kyoo.Abstractions.Controllers.IMetadataProvider; using JsonOptions = Kyoo.Core.Api.JsonOptions; namespace Kyoo.Core @@ -42,22 +39,13 @@ namespace Kyoo.Core /// public class CoreModule : IPlugin { - /// - public string Slug => "core"; - /// public string Name => "Core"; - /// - public string Description => "The core module containing default implementations."; - /// public Dictionary Configuration => new() { - { TaskOptions.Path, typeof(TaskOptions) }, - { MediaOptions.Path, typeof(MediaOptions) }, { "database", null }, - { "logging", null } }; /// @@ -69,17 +57,6 @@ namespace Kyoo.Core builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().SingleInstance(); - - builder.RegisterComposite(); - builder.Register(x => (AProviderComposite)x.Resolve()); - - builder.RegisterTask(); - builder.RegisterTask(); - builder.RegisterTask(); - builder.RegisterTask(); - builder.RegisterTask(); - builder.RegisterTask(); builder.RegisterRepository(); builder.RegisterRepository(); diff --git a/back/src/Kyoo.Core/Models/FileExtensions.cs b/back/src/Kyoo.Core/Models/FileExtensions.cs deleted file mode 100644 index 5db0b582..00000000 --- a/back/src/Kyoo.Core/Models/FileExtensions.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System.Collections.Generic; -using System.Collections.Immutable; -using System.IO; - -namespace Kyoo.Core.Models -{ - /// - /// A static class allowing one to identify files extensions. - /// - public static class FileExtensions - { - /// - /// The list of known video extensions - /// - public static readonly ImmutableArray VideoExtensions = ImmutableArray.Create( - ".webm", - ".mkv", - ".flv", - ".vob", - ".ogg", - ".ogv", - ".avi", - ".mts", - ".m2ts", - ".ts", - ".mov", - ".qt", - ".asf", - ".mp4", - ".m4p", - ".m4v", - ".mpg", - ".mp2", - ".mpeg", - ".mpe", - ".mpv", - ".m2v", - ".3gp", - ".3g2" - ); - - /// - /// Check if a file represent a video file (only by checking the extension of the file) - /// - /// The path of the file to check - /// true if the file is a video file, false otherwise. - public static bool IsVideo(string filePath) - { - return VideoExtensions.Contains(Path.GetExtension(filePath)); - } - - /// - /// The dictionary of known subtitles extensions and the name of the subtitle codec. - /// - public static readonly ImmutableDictionary SubtitleExtensions = new Dictionary - { - { ".ass", "ass" }, - { ".str", "subrip" } - }.ToImmutableDictionary(); - - /// - /// Check if a file represent a subtitle file (only by checking the extension of the file) - /// - /// The path of the file to check - /// true if the file is a subtitle file, false otherwise. - public static bool IsSubtitle(string filePath) - { - return SubtitleExtensions.ContainsKey(Path.GetExtension(filePath)); - } - } -} diff --git a/back/src/Kyoo.Core/Models/Options/BasicOptions.cs b/back/src/Kyoo.Core/Models/Options/BasicOptions.cs index 1536004d..056a8686 100644 --- a/back/src/Kyoo.Core/Models/Options/BasicOptions.cs +++ b/back/src/Kyoo.Core/Models/Options/BasicOptions.cs @@ -28,11 +28,6 @@ namespace Kyoo.Core.Models.Options /// public const string Path = "Basics"; - /// - /// The path of the plugin directory. - /// - public string PluginPath { get; set; } = "plugins/"; - /// /// The temporary folder to cache transmuxed file. /// diff --git a/back/src/Kyoo.Core/Models/Options/MediaOptions.cs b/back/src/Kyoo.Core/Models/Options/MediaOptions.cs deleted file mode 100644 index 32b54a24..00000000 --- a/back/src/Kyoo.Core/Models/Options/MediaOptions.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -namespace Kyoo.Core.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; } - } -} diff --git a/back/src/Kyoo.Core/Models/Options/TaskOptions.cs b/back/src/Kyoo.Core/Models/Options/TaskOptions.cs deleted file mode 100644 index 48dd13ee..00000000 --- a/back/src/Kyoo.Core/Models/Options/TaskOptions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using JetBrains.Annotations; - -namespace Kyoo.Core.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(); - } -} diff --git a/back/src/Kyoo.Core/Tasks/Crawler.cs b/back/src/Kyoo.Core/Tasks/Crawler.cs deleted file mode 100644 index f4f48f2a..00000000 --- a/back/src/Kyoo.Core/Tasks/Crawler.cs +++ /dev/null @@ -1,189 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models; -using Kyoo.Abstractions.Models.Attributes; -using Kyoo.Core.Models; -using Microsoft.Extensions.Logging; - -namespace Kyoo.Core.Tasks -{ - /// - /// A task to add new video files. - /// - [TaskMetadata("scan", "Scan libraries", "Scan your libraries and load data for new shows.", RunOnStartup = true)] - public class Crawler : ITask - { - /// - /// The library manager used to get libraries and providers to use. - /// - private readonly ILibraryManager _libraryManager; - - /// - /// The file manager used walk inside directories and check they existences. - /// - private readonly IFileSystem _fileSystem; - - /// - /// A task manager used to create sub tasks for each episode to add to the database. - /// - private readonly ITaskManager _taskManager; - - /// - /// The logger used to inform the current status to the console. - /// - private readonly ILogger _logger; - - /// - /// Create a new . - /// - /// The library manager to retrieve existing episodes/library/tracks - /// The file system to glob files - /// The task manager used to start . - /// The logger used print messages. - public Crawler(ILibraryManager libraryManager, - IFileSystem fileSystem, - ITaskManager taskManager, - ILogger logger) - { - _libraryManager = libraryManager; - _fileSystem = fileSystem; - _taskManager = taskManager; - _logger = logger; - } - - /// - public TaskParameters GetParameters() - { - return new() - { - TaskParameter.Create("slug", "A library slug to restrict the scan to this library.") - }; - } - - /// - public async Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) - { - string argument = arguments["slug"].As(); - ICollection libraries = argument == null - ? await _libraryManager.GetAll() - : new[] { await _libraryManager.GetOrDefault(argument) }; - - if (argument != null && libraries.First() == null) - throw new ArgumentException($"No library found with the name {argument}"); - - foreach (Library library in libraries) - await _libraryManager.Load(library, x => x.Providers); - - progress.Report(0); - float percent = 0; - - ICollection episodes = await _libraryManager.GetAll(); - ICollection tracks = await _libraryManager.GetAll(); - foreach (Library library in libraries) - { - IProgress reporter = new Progress(x => - { - // ReSharper disable once AccessToModifiedClosure - progress.Report(percent + (x / libraries.Count)); - }); - await _Scan(library, episodes, tracks, reporter, cancellationToken); - percent += 100f / libraries.Count; - - if (cancellationToken.IsCancellationRequested) - return; - } - - progress.Report(100); - } - - private async Task _Scan(Library library, - IEnumerable episodes, - IEnumerable tracks, - IProgress progress, - CancellationToken cancellationToken) - { - _logger.LogInformation("Scanning library {Library} at {Paths}", library.Name, library.Paths); - foreach (string path in library.Paths) - { - ICollection files = await _fileSystem.ListFiles(path, SearchOption.AllDirectories); - - if (cancellationToken.IsCancellationRequested) - return; - - // We try to group episodes by shows to register one episode of each show first. - // This speeds up the scan process because further episodes of a show are registered when all metadata - // of the show has already been fetched. - List> shows = files - .Where(FileExtensions.IsVideo) - .Where(x => !Path.GetFileName(x).StartsWith('.')) // ignore hidden files. - .Where(x => episodes.All(y => y.Path != x)) - .GroupBy(Path.GetDirectoryName) - .ToList(); - - string[] paths = shows.Select(x => x.First()) - .Concat(shows.SelectMany(x => x.Skip(1))) - .ToArray(); - float percent = 0; - IProgress reporter = new Progress(x => - { - // ReSharper disable once AccessToModifiedClosure - progress.Report((percent + (x / paths.Length) - 10) / library.Paths.Length); - }); - - foreach (string episodePath in paths) - { - _taskManager.StartTask(reporter, new Dictionary - { - ["path"] = episodePath, - ["library"] = library - }, cancellationToken); - percent += 100f / paths.Length; - } - - string[] subtitles = files - .Where(FileExtensions.IsSubtitle) - .Where(x => !x.Contains("Extra")) - .Where(x => tracks.All(y => y.Path != x)) - .ToArray(); - percent = 0; - reporter = new Progress(x => - { - // ReSharper disable once AccessToModifiedClosure - progress.Report((90 + (percent + (x / subtitles.Length))) / library.Paths.Length); - }); - - foreach (string trackPath in subtitles) - { - _taskManager.StartTask(reporter, new Dictionary - { - ["path"] = trackPath - }, cancellationToken); - percent += 100f / subtitles.Length; - } - } - } - } -} diff --git a/back/src/Kyoo.Core/Tasks/ExtractMetadata.cs b/back/src/Kyoo.Core/Tasks/ExtractMetadata.cs deleted file mode 100644 index a12e24e1..00000000 --- a/back/src/Kyoo.Core/Tasks/ExtractMetadata.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -// using System; -// using System.Collections.Generic; -// using System.Linq; -// using System.Threading; -// using System.Threading.Tasks; -// using Kyoo.Controllers; -// using Kyoo.Models; -// using Microsoft.Extensions.DependencyInjection; -// -// namespace Kyoo.Tasks -// { -// public class ExtractMetadata : ITask -// { -// public string Slug => "extract"; -// public string Name => "Metadata Extractor"; -// public string Description => "Extract subtitles or download thumbnails for a show/episode."; -// public string HelpMessage => null; -// public bool RunOnStartup => false; -// public int Priority => 0; -// -// -// private ILibraryManager _library; -// private IThumbnailsManager _thumbnails; -// private ITranscoder _transcoder; -// -// public async Task Run(IServiceProvider serviceProvider, CancellationToken token, string arguments = null) -// { -// string[] args = arguments?.Split('/'); -// -// if (args == null || args.Length < 2) -// return; -// -// string slug = args[1]; -// bool thumbs = args.Length < 3 || string.Equals(args[2], "thumbnails", StringComparison.InvariantCultureIgnoreCase); -// bool subs = args.Length < 3 || string.Equals(args[2], "subs", StringComparison.InvariantCultureIgnoreCase); -// -// using IServiceScope serviceScope = serviceProvider.CreateScope(); -// _library = serviceScope.ServiceProvider.GetService(); -// _thumbnails = serviceScope.ServiceProvider.GetService(); -// _transcoder = serviceScope.ServiceProvider.GetService(); -// int id; -// -// switch (args[0].ToLowerInvariant()) -// { -// case "show": -// case "shows": -// Show show = await (int.TryParse(slug, out id) -// ? _library!.Get(id) -// : _library!.Get(slug)); -// await ExtractShow(show, thumbs, subs, token); -// break; -// case "season": -// case "seasons": -// Season season = await (int.TryParse(slug, out id) -// ? _library!.Get(id) -// : _library!.Get(slug)); -// await ExtractSeason(season, thumbs, subs, token); -// break; -// case "episode": -// case "episodes": -// Episode episode = await (int.TryParse(slug, out id) -// ? _library!.Get(id) -// : _library!.Get(slug)); -// await ExtractEpisode(episode, thumbs, subs); -// break; -// } -// } -// -// private async Task ExtractShow(Show show, bool thumbs, bool subs, CancellationToken token) -// { -// if (thumbs) -// await _thumbnails!.Validate(show, true); -// await _library.Load(show, x => x.Seasons); -// foreach (Season season in show.Seasons) -// { -// if (token.IsCancellationRequested) -// return; -// await ExtractSeason(season, thumbs, subs, token); -// } -// } -// -// private async Task ExtractSeason(Season season, bool thumbs, bool subs, CancellationToken token) -// { -// if (thumbs) -// await _thumbnails!.Validate(season, true); -// await _library.Load(season, x => x.Episodes); -// foreach (Episode episode in season.Episodes) -// { -// if (token.IsCancellationRequested) -// return; -// await ExtractEpisode(episode, thumbs, subs); -// } -// } -// -// private async Task ExtractEpisode(Episode episode, bool thumbs, bool subs) -// { -// if (thumbs) -// await _thumbnails!.Validate(episode, true); -// if (subs) -// { -// await _library.Load(episode, x => x.Tracks); -// episode.Tracks = (await _transcoder!.ExtractInfos(episode, true)) -// .Where(x => x.Type != StreamType.Attachment) -// .Concat(episode.Tracks.Where(x => x.IsExternal)) -// .ToList(); -// await _library.Edit(episode, false); -// } -// } -// -// public Task> GetPossibleParameters() -// { -// return Task.FromResult>(null); -// } -// -// public int? Progress() -// { -// return null; -// } -// } -// } diff --git a/back/src/Kyoo.Core/Tasks/Housekeeping.cs b/back/src/Kyoo.Core/Tasks/Housekeeping.cs deleted file mode 100644 index a13bbb77..00000000 --- a/back/src/Kyoo.Core/Tasks/Housekeeping.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Threading; -using System.Threading.Tasks; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models; -using Kyoo.Abstractions.Models.Attributes; -using Microsoft.Extensions.Logging; - -namespace Kyoo.Core.Tasks -{ - /// - /// A task to remove orphaned episode and series. - /// - [TaskMetadata("housekeeping", "Housekeeping", "Remove orphaned episode and series.", RunOnStartup = true)] - public class Housekeeping : ITask - { - /// - /// The library manager used to get libraries or remove deleted episodes. - /// - private readonly ILibraryManager _libraryManager; - - /// - /// The file manager used walk inside directories and check they existences. - /// - private readonly IFileSystem _fileSystem; - - /// - /// The logger used to inform the user that episodes has been removed. - /// - private readonly ILogger _logger; - - /// - /// Create a new task. - /// - /// The library manager used to get libraries or remove deleted episodes. - /// The file manager used walk inside directories and check they existences. - /// The logger used to inform the user that episodes has been removed. - public Housekeeping(ILibraryManager libraryManager, IFileSystem fileSystem, ILogger logger) - { - _libraryManager = libraryManager; - _fileSystem = fileSystem; - _logger = logger; - } - - /// - public TaskParameters GetParameters() - { - return new(); - } - - /// - public async Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) - { - int count = 0; - int delCount = await _libraryManager.GetCount() + await _libraryManager.GetCount(); - progress.Report(0); - - foreach (Show show in await _libraryManager.GetAll()) - { - progress.Report(count / delCount * 100); - count++; - - if (await _fileSystem.Exists(show.Path)) - continue; - _logger.LogWarning("Show {Name}'s folder has been deleted (was {Path}), removing it from kyoo", - show.Title, show.Path); - await _libraryManager.Delete(show); - } - - foreach (Episode episode in await _libraryManager.GetAll()) - { - progress.Report(count / delCount * 100); - count++; - - if (await _fileSystem.Exists(episode.Path)) - continue; - _logger.LogWarning("Episode {Slug}'s file has been deleted (was {Path}), removing it from kyoo", - episode.Slug, episode.Path); - await _libraryManager.Delete(episode); - } - - progress.Report(100); - } - } -} diff --git a/back/src/Kyoo.Core/Tasks/LibraryCreator.cs b/back/src/Kyoo.Core/Tasks/LibraryCreator.cs deleted file mode 100644 index 25b1049e..00000000 --- a/back/src/Kyoo.Core/Tasks/LibraryCreator.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models; -using Kyoo.Abstractions.Models.Attributes; -using Kyoo.Utils; - -namespace Kyoo.Core.Tasks -{ - /// - /// A task to add new video files. - /// - [TaskMetadata("library-creator", "Create libraries", "Create libraries on the library root folder.", - RunOnStartup = true, Priority = 500)] - public class LibraryCreator : ITask - { - /// - /// The library manager used to get libraries and providers to use. - /// - private readonly ILibraryManager _libraryManager; - - /// - /// Create a new . - /// - /// The library manager to retrieve existing episodes/library/tracks - public LibraryCreator(ILibraryManager libraryManager) - { - _libraryManager = libraryManager; - } - - /// - public TaskParameters GetParameters() - { - return new(); - } - - /// - public async Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) - { - ICollection providers = await _libraryManager.GetAll(); - ICollection existings = (await _libraryManager.GetAll()).SelectMany(x => x.Paths).ToArray(); - IEnumerable newLibraries = Directory.GetDirectories(Environment.GetEnvironmentVariable("KYOO_LIBRARY_ROOT") ?? "/video") - .Where(x => !existings.Contains(x)) - .Select(x => new Library - { - Slug = Utility.ToSlug(Path.GetFileName(x)), - Name = Path.GetFileName(x), - Paths = new string[] { x }, - Providers = providers, - }); - - foreach (Library library in newLibraries) - { - await _libraryManager.Create(library); - } - } - } -} diff --git a/back/src/Kyoo.Core/Tasks/MetadataProviderLoader.cs b/back/src/Kyoo.Core/Tasks/MetadataProviderLoader.cs deleted file mode 100644 index c9160fda..00000000 --- a/back/src/Kyoo.Core/Tasks/MetadataProviderLoader.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models.Attributes; -using Kyoo.Abstractions.Models.Exceptions; - -namespace Kyoo.Core.Tasks -{ - /// - /// A task that download metadata providers images. - /// - [TaskMetadata("reload-metadata", "Reload Metadata Providers", "Add every loaded metadata provider to the database.", - RunOnStartup = true, Priority = 1000, IsHidden = true)] - public class MetadataProviderLoader : ITask - { - /// - /// The provider repository used to create in-db providers from metadata providers. - /// - private readonly IProviderRepository _providers; - - /// - /// The thumbnail manager used to download providers logo. - /// - private readonly IThumbnailsManager _thumbnails; - - /// - /// The list of metadata providers to register. - /// - private readonly ICollection _metadataProviders; - - /// - /// Create a new task. - /// - /// - /// The provider repository used to create in-db providers from metadata providers. - /// - /// - /// The thumbnail manager used to download providers logo. - /// - /// - /// The list of metadata providers to register. - /// - public MetadataProviderLoader(IProviderRepository providers, - IThumbnailsManager thumbnails, - ICollection metadataProviders) - { - _providers = providers; - _thumbnails = thumbnails; - _metadataProviders = metadataProviders; - } - - /// - public TaskParameters GetParameters() - { - return new TaskParameters(); - } - - /// - public async Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) - { - float percent = 0; - progress.Report(0); - - foreach (IMetadataProvider provider in _metadataProviders) - { - if (string.IsNullOrEmpty(provider.Provider.Slug)) - throw new TaskFailedException($"Empty provider slug (name: {provider.Provider.Name})."); - await _providers.CreateIfNotExists(provider.Provider); - await _thumbnails.DownloadImages(provider.Provider); - percent += 100f / _metadataProviders.Count; - progress.Report(percent); - } - progress.Report(100); - } - } -} diff --git a/back/src/Kyoo.Core/Tasks/ReScan.cs b/back/src/Kyoo.Core/Tasks/ReScan.cs deleted file mode 100644 index 87bfbada..00000000 --- a/back/src/Kyoo.Core/Tasks/ReScan.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -// using System; -// using System.Collections.Generic; -// using System.Linq; -// using System.Threading; -// using System.Threading.Tasks; -// using Kyoo.Controllers; -// using Kyoo.Models; -// using Microsoft.Extensions.DependencyInjection; -// -// namespace Kyoo.Tasks -// { -// public class ReScan: ITask -// { -// public string Slug => "re-scan"; -// public string Name => "ReScan"; -// public string Description => "Re download metadata of an item using it's external ids."; -// public string HelpMessage => null; -// public bool RunOnStartup => false; -// public int Priority => 0; -// -// -// private IServiceProvider _serviceProvider; -// private IThumbnailsManager _thumbnailsManager; -// private IProviderManager _providerManager; -// private DatabaseContext _database; -// -// public async Task Run(IServiceProvider serviceProvider, CancellationToken cancellationToken, string arguments = null) -// { -// using IServiceScope serviceScope = serviceProvider.CreateScope(); -// _serviceProvider = serviceProvider; -// _thumbnailsManager = serviceProvider.GetService(); -// _providerManager = serviceProvider.GetService(); -// _database = serviceScope.ServiceProvider.GetService(); -// -// if (arguments == null || !arguments.Contains('/')) -// return; -// -// string slug = arguments.Substring(arguments.IndexOf('/') + 1); -// switch (arguments.Substring(0, arguments.IndexOf('/'))) -// { -// case "show": -// await ReScanShow(slug); -// break; -// case "season": -// await ReScanSeason(slug); -// break; -// } -// } -// -// private async Task ReScanShow(string slug) -// { -// Show old; -// -// using (IServiceScope serviceScope = _serviceProvider.CreateScope()) -// { -// ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService(); -// old = _database.Shows.FirstOrDefault(x => x.Slug == slug); -// if (old == null) -// return; -// Library library = _database.LibraryLinks.First(x => x.Show == old && x.Library != null).Library; -// Show edited = await _providerManager.CompleteShow(old, library); -// edited.ID = old.ID; -// edited.Slug = old.Slug; -// edited.Path = old.Path; -// await libraryManager.EditShow(edited, true); -// await _thumbnailsManager.Validate(edited, true); -// } -// if (old.Seasons != null) -// await Task.WhenAll(old.Seasons.Select(x => ReScanSeason(old, x))); -// IEnumerable orphans = old.Episodes.Where(x => x.Season == null).ToList(); -// if (orphans.Any()) -// await Task.WhenAll(orphans.Select(x => ReScanEpisode(old, x))); -// } -// -// private async Task ReScanSeason(string seasonSlug) -// { -// string[] infos = seasonSlug.Split('-'); -// if (infos.Length != 2 || int.TryParse(infos[1], out int seasonNumber)) -// return; -// string slug = infos[0]; -// Show show = _database.Shows.FirstOrDefault(x => x.Slug == slug); -// if (show == null) -// return; -// Season old = _database.Seasons.FirstOrDefault(x => x.SeasonNumber == seasonNumber && x.Show.ID == show.ID); -// if (old == null) -// return; -// await ReScanSeason(show, old); -// } -// -// private async Task ReScanSeason(Show show, Season old) -// { -// using (IServiceScope serviceScope = _serviceProvider.CreateScope()) -// { -// ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService(); -// Library library = _database.LibraryLinks.First(x => x.Show == show && x.Library != null).Library; -// Season edited = await _providerManager.GetSeason(show, old.SeasonNumber, library); -// edited.ID = old.ID; -// await libraryManager.EditSeason(edited, true); -// await _thumbnailsManager.Validate(edited, true); -// } -// if (old.Episodes != null) -// await Task.WhenAll(old.Episodes.Select(x => ReScanEpisode(show, x))); -// } -// -// private async Task ReScanEpisode(Show show, Episode old) -// { -// using IServiceScope serviceScope = _serviceProvider.CreateScope(); -// ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService(); -// -// Library library = _database.LibraryLinks.First(x => x.Show == show && x.Library != null).Library; -// Episode edited = await _providerManager.GetEpisode(show, old.Path, old.SeasonNumber, old.EpisodeNumber, old.AbsoluteNumber, library); -// edited.ID = old.ID; -// await libraryManager.EditEpisode(edited, true); -// await _thumbnailsManager.Validate(edited, true); -// } -// -// public Task> GetPossibleParameters() -// { -// return Task.FromResult>(null); -// } -// -// public int? Progress() -// { -// return null; -// } -// } -// } diff --git a/back/src/Kyoo.Core/Tasks/RegisterEpisode.cs b/back/src/Kyoo.Core/Tasks/RegisterEpisode.cs deleted file mode 100644 index 7a9641c8..00000000 --- a/back/src/Kyoo.Core/Tasks/RegisterEpisode.cs +++ /dev/null @@ -1,210 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models; -using Kyoo.Abstractions.Models.Attributes; -using Kyoo.Abstractions.Models.Exceptions; - -namespace Kyoo.Core.Tasks -{ - /// - /// A task to register a new episode - /// - [TaskMetadata("register", "Register episode", "Register a new episode")] - public class RegisterEpisode : ITask - { - /// - /// An identifier to extract metadata from paths. - /// - private readonly IIdentifier _identifier; - - /// - /// The library manager used to register the episode. - /// - private readonly ILibraryManager _libraryManager; - - /// - /// A metadata provider to retrieve the metadata of the new episode (and related items if they do not exist). - /// - private readonly AProviderComposite _metadataProvider; - - /// - /// The thumbnail manager used to download images. - /// - private readonly IThumbnailsManager _thumbnailsManager; - - /// - /// The transcoder used to extract subtitles and metadata. - /// - private readonly IFileSystem _transcoder; - - /// - /// Create a new task. - /// - /// - /// An identifier to extract metadata from paths. - /// - /// - /// The library manager used to register the episode. - /// - /// - /// A metadata provider to retrieve the metadata of the new episode (and related items if they do not exist). - /// - /// - /// The thumbnail manager used to download images. - /// - /// - /// The file manager used to retrieve episodes metadata. - /// - public RegisterEpisode(IIdentifier identifier, - ILibraryManager libraryManager, - AProviderComposite metadataProvider, - IThumbnailsManager thumbnailsManager, - IFileSystem transcoder) - { - _identifier = identifier; - _libraryManager = libraryManager; - _metadataProvider = metadataProvider; - _thumbnailsManager = thumbnailsManager; - _transcoder = transcoder; - } - - /// - public TaskParameters GetParameters() - { - return new() - { - TaskParameter.CreateRequired("path", "The path of the episode file"), - TaskParameter.CreateRequired("library", "The library in witch the episode is") - }; - } - - /// - public async Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) - { - string path = arguments["path"].As(); - Library library = arguments["library"].As(); - progress.Report(0); - - if (library != null) - { - if (library.Providers == null) - await _libraryManager.Load(library, x => x.Providers); - _metadataProvider.UseProviders(library.Providers); - } - - try - { - (Collection collection, Show show, Season season, Episode episode) = await _identifier.Identify(path); - progress.Report(15); - - collection = await _RegisterAndFill(collection); - progress.Report(20); - - Show registeredShow = await _RegisterAndFill(show); - if (registeredShow.Path != show.Path) - { - if (show.StartAir.HasValue) - { - show.Slug += $"-{show.StartAir.Value.Year}"; - show = await _libraryManager.Create(show); - } - else - { - throw new TaskFailedException($"Duplicated show found ({show.Slug}) " + - $"at {registeredShow.Path} and {show.Path}"); - } - } - else - show = registeredShow; - - progress.Report(50); - - if (season != null) - season.Show = show; - season = await _RegisterAndFill(season); - progress.Report(60); - - episode.Show = show; - episode.Season = season; - if (!show.IsMovie) - episode = await _metadataProvider.Get(episode); - progress.Report(70); - episode.Tracks = await _transcoder.ExtractInfos(episode, false); - await _thumbnailsManager.DownloadImages(episode); - progress.Report(90); - - await _libraryManager.Create(episode); - progress.Report(95); - await _libraryManager.AddShowLink(show, library, collection); - progress.Report(100); - } - catch (IdentificationFailedException ex) - { - throw new TaskFailedException(ex); - } - catch (DuplicatedItemException ex) - { - throw new TaskFailedException(ex); - } - } - - /// - /// Retrieve the equivalent item if it already exists in the database, - /// if it does not, fill metadata using the metadata provider, download images and register the item to the - /// database. - /// - /// The item to retrieve or fill and register - /// The type of the item - /// The existing or filled item. - private async Task _RegisterAndFill(T item) - where T : class, IResource, IThumbnails, IMetadata - { - if (item == null || string.IsNullOrEmpty(item.Slug)) - return null; - - T existing = await _libraryManager.GetOrDefault(item.Slug); - if (existing != null) - { - await _libraryManager.Load(existing, x => x.ExternalIDs); - return existing; - } - - item = await _metadataProvider.Get(item); - await _thumbnailsManager.DownloadImages(item); - - switch (item) - { - case Show show when show.People != null: - foreach (PeopleRole role in show.People) - await _thumbnailsManager.DownloadImages(role.People); - break; - case Season season: - season.Title ??= $"Season {season.SeasonNumber}"; - break; - } - - return await _libraryManager.CreateIfNotExists(item); - } - } -} diff --git a/back/src/Kyoo.Core/Tasks/RegisterSubtitle.cs b/back/src/Kyoo.Core/Tasks/RegisterSubtitle.cs deleted file mode 100644 index ae1380fb..00000000 --- a/back/src/Kyoo.Core/Tasks/RegisterSubtitle.cs +++ /dev/null @@ -1,102 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Threading; -using System.Threading.Tasks; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models; -using Kyoo.Abstractions.Models.Attributes; -using Kyoo.Abstractions.Models.Exceptions; - -namespace Kyoo.Core.Tasks -{ - /// - /// A task to register a new episode - /// - [TaskMetadata("register-sub", "Register subtitle", "Register a new subtitle")] - public class RegisterSubtitle : ITask - { - /// - /// An identifier to extract metadata from paths. - /// - private readonly IIdentifier _identifier; - - /// - /// The library manager used to register the episode. - /// - private readonly ILibraryManager _libraryManager; - - /// - /// Create a new task. - /// - /// An identifier to extract metadata from paths. - /// The library manager used to register the episode. - public RegisterSubtitle(IIdentifier identifier, ILibraryManager libraryManager) - { - _identifier = identifier; - _libraryManager = libraryManager; - } - - /// - public TaskParameters GetParameters() - { - return new() - { - TaskParameter.CreateRequired("path", "The path of the subtitle file") - }; - } - - /// - public async Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) - { - string path = arguments["path"].As(); - - try - { - progress.Report(0); - Track track = await _identifier.IdentifyTrack(path); - progress.Report(25); - - if (track.Episode == null) - throw new TaskFailedException($"No episode identified for the track at {path}"); - if (track.Episode.ID == 0) - { - if (track.Episode.Slug != null) - track.Episode = await _libraryManager.Get(track.Episode.Slug); - else if (track.Episode.Path != null) - { - track.Episode = await _libraryManager.GetOrDefault(x => x.Path.StartsWith(track.Episode.Path)); - if (track.Episode == null) - throw new TaskFailedException($"No episode found for the track at: {path}."); - } - else - throw new TaskFailedException($"No episode identified for the track at {path}"); - } - - progress.Report(50); - await _libraryManager.Create(track); - progress.Report(100); - } - catch (IdentificationFailedException ex) - { - throw new TaskFailedException(ex); - } - } - } -} diff --git a/back/src/Kyoo.Core/Views/Admin/TaskApi.cs b/back/src/Kyoo.Core/Views/Admin/TaskApi.cs deleted file mode 100644 index 5ed8790e..00000000 --- a/back/src/Kyoo.Core/Views/Admin/TaskApi.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models.Attributes; -using Kyoo.Abstractions.Models.Permissions; -using Kyoo.Abstractions.Models.Utils; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using static Kyoo.Abstractions.Models.Utils.Constants; - -namespace Kyoo.Core.Api -{ - /// - /// An endpoint to list and run tasks in the background. - /// - [Route("tasks")] - [Route("task", Order = AlternativeRoute)] - [ApiController] - [ResourceView] - [PartialPermission("Task", Group = Group.Admin)] - [ApiDefinition("Tasks", Group = AdminGroup)] - public class TaskApi : ControllerBase - { - /// - /// The task manager used to retrieve and start tasks. - /// - private readonly ITaskManager _taskManager; - - /// - /// Create a new . - /// - /// The task manager used to start tasks. - public TaskApi(ITaskManager taskManager) - { - _taskManager = taskManager; - } - - /// - /// Get all tasks - /// - /// - /// Retrieve all tasks available in this instance of Kyoo. - /// - /// A list of every tasks that this instance know. - [HttpGet] - [PartialPermission(Kind.Read)] - [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetTasks() - { - return Ok(_taskManager.GetAllTasks()); - } - - /// - /// Start task - /// - /// - /// Start a task with the given arguments. If a task is already running, it may be queued and started only when - /// a runner become available. - /// - /// The slug of the task to start. - /// The list of arguments to give to the task. - /// The task has been started or is queued. - /// The task misses an argument or an argument is invalid. - /// No task could be found with the given slug. - [HttpPut("{taskSlug}")] - [HttpGet("{taskSlug}", Order = AlternativeRoute)] - [PartialPermission(Kind.Create)] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public IActionResult RunTask(string taskSlug, - [FromQuery] Dictionary args) - { - _taskManager.StartTask(taskSlug, new Progress(), args); - return Ok(); - } - } -} diff --git a/back/src/Kyoo.Host/Application.cs b/back/src/Kyoo.Host/Application.cs index 0e677ba5..baeaec00 100644 --- a/back/src/Kyoo.Host/Application.cs +++ b/back/src/Kyoo.Host/Application.cs @@ -40,18 +40,13 @@ namespace Kyoo.Host /// Hosts of kyoo (main functions) generally only create a new /// and return . /// - public class Application : IDisposable + public class Application { /// /// The environment in witch Kyoo will run (ether "Production" or "Development"). /// private readonly string _environment; - /// - /// The cancellation token source used to allow the app to be shutdown or restarted. - /// - private CancellationTokenSource _tokenSource; - /// /// The logger used for startup and error messages. /// @@ -109,8 +104,7 @@ namespace Kyoo.Host .ConfigureContainer(configure) .Build(); - _tokenSource = new CancellationTokenSource(); - await _StartWithHost(host, _tokenSource.Token); + await _StartWithHost(host); } /// @@ -118,7 +112,7 @@ namespace Kyoo.Host /// /// The host to start. /// A token to allow one to stop the host. - private async Task _StartWithHost(IHost host, CancellationToken cancellationToken) + private async Task _StartWithHost(IHost host, CancellationToken cancellationToken = default) { try { @@ -187,12 +181,5 @@ namespace Kyoo.Host .Enrich.WithThreadId() .Enrich.FromLogContext(); } - - /// - public void Dispose() - { - _tokenSource.Dispose(); - GC.SuppressFinalize(this); - } } } diff --git a/back/src/Kyoo.Host/Contollers/PluginManager.cs b/back/src/Kyoo.Host/Contollers/PluginManager.cs index 1a9ee933..01a68311 100644 --- a/back/src/Kyoo.Host/Contollers/PluginManager.cs +++ b/back/src/Kyoo.Host/Contollers/PluginManager.cs @@ -18,10 +18,7 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Reflection; -using System.Runtime.Loader; using Kyoo.Abstractions.Controllers; using Kyoo.Core.Models.Options; using Microsoft.Extensions.DependencyInjection; @@ -89,51 +86,11 @@ namespace Kyoo.Host.Controllers return _plugins; } - /// - /// Load a single plugin and return all IPlugin implementations contained in the Assembly. - /// - /// The path of the dll - /// The list of dlls in hte assembly - private IPlugin[] _LoadPlugin(string path) - { - path = Path.GetFullPath(path); - try - { - PluginDependencyLoader loader = new(path); - Assembly assembly = loader.LoadFromAssemblyPath(path); - return assembly.GetTypes() - .Where(x => typeof(IPlugin).IsAssignableFrom(x)) - .Where(x => _plugins.All(y => y.GetType() != x)) - .Select(x => (IPlugin)ActivatorUtilities.CreateInstance(_provider, x)) - .ToArray(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Could not load the plugin at {Path}", path); - return Array.Empty(); - } - } - /// public void LoadPlugins(ICollection plugins) { - string pluginFolder = _options.Value.PluginPath; - if (!Directory.Exists(pluginFolder)) - Directory.CreateDirectory(pluginFolder); - - _logger.LogTrace("Loading new plugins..."); - string[] pluginsPaths = Directory.GetFiles(pluginFolder, "*.dll", SearchOption.AllDirectories); - _plugins.AddRange(plugins - .Concat(pluginsPaths.SelectMany(_LoadPlugin)) - .Where(x => x.Enabled) - .GroupBy(x => x.Name) - .Select(x => x.First()) - ); - - if (!_plugins.Any()) - _logger.LogInformation("No plugin enabled"); - else - _logger.LogInformation("Plugin enabled: {Plugins}", _plugins.Select(x => x.Name)); + _plugins.AddRange(plugins); + _logger.LogInformation("Modules enabled: {Plugins}", _plugins.Select(x => x.Name)); } /// @@ -144,52 +101,5 @@ namespace Kyoo.Host.Controllers .ToArray() ); } - - /// - /// A custom to load plugin's dependency if they are on the same folder. - /// - private class PluginDependencyLoader : AssemblyLoadContext - { - /// - /// The basic resolver that will be used to load dlls. - /// - private readonly AssemblyDependencyResolver _resolver; - - /// - /// Create a new for the given path. - /// - /// The path of the plugin and it's dependencies - public PluginDependencyLoader(string pluginPath) - { - _resolver = new AssemblyDependencyResolver(pluginPath); - } - - /// - protected override Assembly Load(AssemblyName assemblyName) - { - Assembly existing = AppDomain.CurrentDomain.GetAssemblies() - .FirstOrDefault(x => - { - AssemblyName name = x.GetName(); - return name.Name == assemblyName.Name && name.Version == assemblyName.Version; - }); - if (existing != null) - return existing; - // TODO load the assembly from the common folder if the file exists (this would allow shared libraries) - string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); - if (assemblyPath != null) - return LoadFromAssemblyPath(assemblyPath); - return base.Load(assemblyName); - } - - /// - protected override IntPtr LoadUnmanagedDll(string unmanagedDllName) - { - string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName); - if (libraryPath != null) - return LoadUnmanagedDllFromPath(libraryPath); - return base.LoadUnmanagedDll(unmanagedDllName); - } - } } } diff --git a/back/src/Kyoo.Host/Contollers/TaskManager.cs b/back/src/Kyoo.Host/Contollers/TaskManager.cs deleted file mode 100644 index 45f48040..00000000 --- a/back/src/Kyoo.Host/Contollers/TaskManager.cs +++ /dev/null @@ -1,346 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using Autofac.Features.Metadata; -using Autofac.Features.OwnedInstances; -using JetBrains.Annotations; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models.Attributes; -using Kyoo.Abstractions.Models.Exceptions; -using Kyoo.Core.Models.Options; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace Kyoo.Host.Controllers -{ - /// - /// A service to handle long running tasks and a background runner. - /// - /// Task will be queued, only one can run simultaneously. - public class TaskManager : BackgroundService, ITaskManager - { - /// - /// The class representing task under this jurisdiction. - /// - private class ManagedTask - { - /// - /// The metadata for this task (the slug, and other useful information). - /// - public TaskMetadataAttribute Metadata { get; set; } - - /// - /// The function used to create the task object. - /// - public Func> Factory { get; init; } - - /// - /// The next scheduled date for this task - /// - public DateTime ScheduledDate { get; set; } - } - - /// - /// A class representing a task inside the list. - /// - private class QueuedTask - { - /// - /// The task currently queued. - /// - public ManagedTask Task { get; init; } - - /// - /// The progress reporter that this task should use. - /// - public IProgress ProgressReporter { get; init; } - - /// - /// The arguments to give to run the task with. - /// - public Dictionary Arguments { get; init; } - - /// - /// A token informing the task that it should be cancelled or not. - /// - public CancellationToken? CancellationToken { get; init; } - } - - /// - /// The configuration instance used to get schedule information - /// - private readonly IOptionsMonitor _options; - - /// - /// The logger instance. - /// - private readonly ILogger _logger; - - /// - /// The list of tasks and their next scheduled run. - /// - private readonly List _tasks; - - /// - /// The queue of tasks that should be run as soon as possible. - /// - private readonly Queue _queuedTasks = new(); - - /// - /// The cancellation token used to cancel the running task when the runner should shutdown. - /// - private readonly CancellationTokenSource _taskToken = new(); - - /// - /// The currently running task. - /// - private (TaskMetadataAttribute, ITask)? _runningTask; - - /// - /// Create a new . - /// - /// The list of tasks to manage with their metadata - /// The configuration to load schedule information. - /// The logger. - public TaskManager(IEnumerable>, TaskMetadataAttribute>> tasks, - IOptionsMonitor options, - ILogger logger) - { - _options = options; - _logger = logger; - _tasks = tasks.Select(x => new ManagedTask - { - Factory = x.Value, - Metadata = x.Metadata, - ScheduledDate = _GetNextTaskDate(x.Metadata.Slug) - }).ToList(); - - if (_tasks.Any()) - _logger.LogTrace("Task manager initiated with: {Tasks}", _tasks.Select(x => x.Metadata.Name)); - else - _logger.LogInformation("Task manager initiated without any tasks"); - } - - /// - /// Triggered when the application host is ready to start the service. - /// - /// Start the runner in another thread. - /// Indicates that the start process has been aborted. - /// A representing the asynchronous operation. - public override Task StartAsync(CancellationToken cancellationToken) - { - Task.Run(() => base.StartAsync(cancellationToken), CancellationToken.None); - return Task.CompletedTask; - } - - /// - public override Task StopAsync(CancellationToken cancellationToken) - { - _taskToken.Cancel(); - return base.StopAsync(cancellationToken); - } - - /// - /// The runner that will host tasks and run queued tasks. - /// - /// A token to stop the runner - /// A representing the asynchronous operation. - protected override async Task ExecuteAsync(CancellationToken cancellationToken) - { - _EnqueueStartupTasks(); - - while (!cancellationToken.IsCancellationRequested) - { - if (_queuedTasks.Any()) - { - QueuedTask task = _queuedTasks.Dequeue(); - try - { - await _RunTask(task.Task, task.ProgressReporter, task.Arguments, task.CancellationToken); - } - catch (TaskFailedException ex) - { - _logger.LogWarning("The task \"{Task}\" failed: {Message}", - task.Task.Metadata.Name, ex.Message); - } - catch (Exception e) - { - _logger.LogError(e, "An unhandled exception occured while running the task {Task}", - task.Task.Metadata.Name); - } - } - else - { - await Task.Delay(1000, cancellationToken); - _QueueScheduledTasks(); - } - } - } - - /// - /// Parse parameters, inject a task and run it. - /// - /// The task to run - /// A progress reporter to know the percentage of completion of the task. - /// The arguments to pass to the function - /// An optional cancellation token that will be passed to the task. - /// - /// If the number of arguments is invalid, if an argument can't be converted or if the task finds the argument - /// invalid. - /// - private async Task _RunTask(ManagedTask task, - [NotNull] IProgress progress, - Dictionary arguments, - CancellationToken? cancellationToken = null) - { - using (_logger.BeginScope("Task: {Task}", task.Metadata.Name)) - { - await using Owned taskObj = task.Factory.Invoke(); - ICollection all = taskObj.Value.GetParameters(); - - _runningTask = (task.Metadata, taskObj.Value); - ICollection invalids = arguments.Keys - .Where(x => all.All(y => x != y.Name)) - .ToArray(); - if (invalids.Any()) - { - throw new ArgumentException($"{string.Join(", ", invalids)} are " + - $"invalid arguments for the task {task.Metadata.Name}"); - } - - TaskParameters args = new(all - .Select(x => - { - object value = arguments - .FirstOrDefault(y => string.Equals(y.Key, x.Name, StringComparison.OrdinalIgnoreCase)) - .Value; - if (value == null && x.IsRequired) - { - throw new ArgumentException($"The argument {x.Name} is required to run " + - $"{task.Metadata.Name} but it was not specified."); - } - return x.CreateValue(value ?? x.DefaultValue); - })); - - _logger.LogInformation("Task starting: {Task} ({Parameters})", - task.Metadata.Name, args.ToDictionary(x => x.Name, x => x.As())); - - CancellationToken token = cancellationToken != null - ? CancellationTokenSource.CreateLinkedTokenSource(_taskToken.Token, cancellationToken.Value).Token - : _taskToken.Token; - await taskObj.Value.Run(args, progress, token); - - _logger.LogInformation("Task finished: {Task}", task.Metadata.Name); - _runningTask = null; - } - } - - /// - /// Start tasks that are scheduled for start. - /// - private void _QueueScheduledTasks() - { - IEnumerable tasksToQueue = _tasks.Where(x => x.ScheduledDate <= DateTime.Now) - .Select(x => x.Metadata.Slug); - foreach (string task in tasksToQueue) - { - _logger.LogDebug("Queuing task scheduled for running: {Task}", task); - StartTask(task, new Progress(), new Dictionary()); - } - } - - /// - /// Queue startup tasks with respect to the priority rules. - /// - private void _EnqueueStartupTasks() - { - IEnumerable startupTasks = _tasks - .Where(x => x.Metadata.RunOnStartup) - .OrderByDescending(x => x.Metadata.Priority) - .Select(x => x.Metadata.Slug); - foreach (string task in startupTasks) - StartTask(task, new Progress(), new Dictionary()); - } - - /// - public void StartTask(string taskSlug, - IProgress progress, - Dictionary arguments = null, - CancellationToken? cancellationToken = null) - { - arguments ??= new Dictionary(); - - int index = _tasks.FindIndex(x => x.Metadata.Slug == taskSlug); - if (index == -1) - throw new ItemNotFoundException($"No task found with the slug {taskSlug}"); - _queuedTasks.Enqueue(new QueuedTask - { - Task = _tasks[index], - ProgressReporter = progress, - Arguments = arguments, - CancellationToken = cancellationToken - }); - _tasks[index].ScheduledDate = _GetNextTaskDate(taskSlug); - } - - /// - public void StartTask(IProgress progress, - Dictionary arguments = null, - CancellationToken? cancellationToken = null) - where T : ITask - { - TaskMetadataAttribute metadata = typeof(T).GetCustomAttribute(); - if (metadata == null) - throw new ArgumentException($"No metadata found on the given task (type: {typeof(T).Name})."); - StartTask(metadata.Slug, progress, arguments, cancellationToken); - } - - /// - /// Get the next date of the execution of the given task. - /// - /// The slug of the task - /// The next date. - private DateTime _GetNextTaskDate(string taskSlug) - { - if (_options.CurrentValue.Scheduled.TryGetValue(taskSlug, out TimeSpan delay)) - return DateTime.Now + delay; - return DateTime.MaxValue; - } - - /// - public ICollection<(TaskMetadataAttribute, ITask)> GetRunningTasks() - { - return _runningTask == null - ? ArraySegment<(TaskMetadataAttribute, ITask)>.Empty - : new[] { _runningTask.Value }; - } - - /// - public ICollection GetAllTasks() - { - return _tasks.Select(x => x.Metadata).ToArray(); - } - } -} diff --git a/back/src/Kyoo.Host/HostModule.cs b/back/src/Kyoo.Host/HostModule.cs index 5c3599b9..6bbadf16 100644 --- a/back/src/Kyoo.Host/HostModule.cs +++ b/back/src/Kyoo.Host/HostModule.cs @@ -20,13 +20,10 @@ using System; using System.Collections.Generic; using Autofac; using Autofac.Extras.AttributeMetadata; -using Kyoo.Abstractions; using Kyoo.Abstractions.Controllers; using Kyoo.Core.Models.Options; -using Kyoo.Core.Tasks; using Kyoo.Host.Controllers; using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Hosting; using Serilog; namespace Kyoo.Host @@ -36,15 +33,9 @@ namespace Kyoo.Host /// public class HostModule : IPlugin { - /// - public string Slug => "host"; - /// public string Name => "Host"; - /// - public string Description => "A module that registers host controllers and other needed things."; - /// public Dictionary Configuration => new() { @@ -71,8 +62,6 @@ namespace Kyoo.Host builder.RegisterModule(); builder.RegisterInstance(_plugins).As().ExternallyOwned(); builder.RegisterComposite().InstancePerLifetimeScope(); - builder.RegisterType().As().As().SingleInstance(); - builder.RegisterTask(); } /// diff --git a/back/src/Kyoo.Host/Tasks/PluginInitializer.cs b/back/src/Kyoo.Host/Tasks/PluginInitializer.cs deleted file mode 100644 index 1b455c7c..00000000 --- a/back/src/Kyoo.Host/Tasks/PluginInitializer.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Kyoo - A portable and vast media library solution. -// Copyright (c) Kyoo. -// -// See AUTHORS.md and LICENSE file in the project root for full license information. -// -// Kyoo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// Kyoo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Kyoo. If not, see . - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models.Attributes; - -namespace Kyoo.Core.Tasks -{ - /// - /// A task run on Kyoo's startup to initialize plugins - /// - [TaskMetadata("plugin-init", "Plugin Initializer", "A task to initialize plugins.", - RunOnStartup = true, Priority = int.MaxValue, IsHidden = true)] - public class PluginInitializer : ITask - { - /// - /// The plugin manager used to retrieve plugins to initialize them. - /// - private readonly IPluginManager _pluginManager; - - /// - /// The service provider given to each method. - /// - private readonly IServiceProvider _provider; - - /// - /// Create a new task - /// - /// The plugin manager used to retrieve plugins to initialize them. - /// The service provider given to each method. - public PluginInitializer(IPluginManager pluginManager, IServiceProvider provider) - { - _pluginManager = pluginManager; - _provider = provider; - } - - /// - public TaskParameters GetParameters() - { - return new(); - } - - /// - public Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) - { - ICollection plugins = _pluginManager.GetAllPlugins(); - int count = 0; - progress.Report(0); - - foreach (IPlugin plugin in plugins) - { - plugin.Initialize(_provider); - - progress.Report(count / plugins.Count * 100); - count++; - } - - progress.Report(100); - return Task.CompletedTask; - } - } -} diff --git a/back/src/Kyoo.Host/settings.json b/back/src/Kyoo.Host/settings.json index e9e70933..fa6df81a 100644 --- a/back/src/Kyoo.Host/settings.json +++ b/back/src/Kyoo.Host/settings.json @@ -1,29 +1,10 @@ { "basics": { - "pluginsPath": "plugins/", "transmuxPath": "cached/transmux", "transcodePath": "cached/transcode", "metadataPath": "metadata/" }, - "tasks": { - "parallels": "1", - "scheduled": { - "scan": "24:00:00" - } - }, - - "media": { - "regex": [ - "^[\\/\\\\]*(?.+)?[\\/\\\\]+(?.+?)(?: \\((?\\d+)\\))?[\\/\\\\]+\\k(?: \\(\\d+\\))? S(?\\d+)E(?\\d+)\\..*$", - "^[\\/\\\\]*(?.+)?[\\/\\\\]+(?.+?)(?: \\((?\\d+)\\))?[\\/\\\\]+\\k(?: \\(\\d+\\))? (?\\d+)\\..*$", - "^[\\/\\\\]*(?.+)?[\\/\\\\]+(?.+?)(?: \\((?\\d+)\\))?[\\/\\\\]+\\k(?: \\(\\d+\\))?\\..*$" - ], - "subtitleRegex": [ - "^(?.+)\\.(?\\w{1,3})\\.(?default\\.)?(?forced\\.)?.*$" - ] - }, - "authentication": { "permissions": { "default": ["overall.read", "overall.write"], diff --git a/back/src/Kyoo.Postgresql/PostgresModule.cs b/back/src/Kyoo.Postgresql/PostgresModule.cs index fbcb3bfa..b35e2f30 100644 --- a/back/src/Kyoo.Postgresql/PostgresModule.cs +++ b/back/src/Kyoo.Postgresql/PostgresModule.cs @@ -34,21 +34,12 @@ namespace Kyoo.Postgresql /// public class PostgresModule : IPlugin { - /// - public string Slug => "postgresql"; - /// public string Name => "Postgresql"; - /// - public string Description => "A database context for postgresql."; - /// public Dictionary Configuration => new(); - /// - public bool Enabled => true; - /// /// The configuration to use. The database connection string is pulled from it. /// diff --git a/back/src/Kyoo.Swagger/SwaggerModule.cs b/back/src/Kyoo.Swagger/SwaggerModule.cs index 886ce10f..ed2a4647 100644 --- a/back/src/Kyoo.Swagger/SwaggerModule.cs +++ b/back/src/Kyoo.Swagger/SwaggerModule.cs @@ -18,14 +18,11 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models.Utils; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using NJsonSchema; using NJsonSchema.Generation.TypeMappers; @@ -40,32 +37,12 @@ namespace Kyoo.Swagger /// public class SwaggerModule : IPlugin { - /// - public string Slug => "swagger"; - /// public string Name => "Swagger"; - /// - public string Description => "A swagger interface and an OpenAPI endpoint to document Kyoo."; - /// public Dictionary Configuration => new(); - /// - /// The configuration instance used to retrieve the server's public url. - /// - private readonly IConfiguration _configuration; - - /// - /// Create a new . - /// - /// The configuration instance used to retrieve the server's public url. - public SwaggerModule(IConfiguration configuration) - { - _configuration = configuration; - } - /// public void Configure(IServiceCollection services) { @@ -133,7 +110,7 @@ namespace Kyoo.Swagger SA.New(app => app.UseReDoc(x => { x.Path = "/doc"; - x.TransformToExternalPath = (internalUiRoute, request) => "/api" + internalUiRoute; + x.TransformToExternalPath = (internalUiRoute, _) => "/api" + internalUiRoute; x.AdditionalSettings["theme"] = new { colors = new { primary = new { main = "#e13e13" } }