Reworking the plugin manager

This commit is contained in:
Zoe Roux
2021-04-29 23:59:46 +02:00
parent 833447ded8
commit 79995ea191
39 changed files with 394 additions and 253 deletions
+13 -13
View File
@@ -18,7 +18,7 @@ namespace Kyoo.Controllers
/// Get the repository corresponding to the T item.
/// </summary>
/// <typeparam name="T">The type you want</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The repository corresponding</returns>
IRepository<T> GetRepository<T>() where T : class, IResource;
@@ -82,7 +82,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="id">The id of the resource</param>
/// <typeparam name="T">The type of the resource</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The resource found</returns>
Task<T> Get<T>(int id) where T : class, IResource;
@@ -91,7 +91,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="slug">The slug of the resource</param>
/// <typeparam name="T">The type of the resource</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The resource found</returns>
Task<T> Get<T>(string slug) where T : class, IResource;
@@ -100,7 +100,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="where">The filter function.</param>
/// <typeparam name="T">The type of the resource</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The first resource found that match the where function</returns>
Task<T> Get<T>(Expression<Func<T, bool>> where) where T : class, IResource;
@@ -109,7 +109,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="showID">The id of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The season found</returns>
Task<Season> Get(int showID, int seasonNumber);
@@ -118,7 +118,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The season found</returns>
Task<Season> Get(string showSlug, int seasonNumber);
@@ -128,7 +128,7 @@ namespace Kyoo.Controllers
/// <param name="showID">The id of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <param name="episodeNumber">The episode's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The episode found</returns>
Task<Episode> Get(int showID, int seasonNumber, int episodeNumber);
@@ -138,7 +138,7 @@ namespace Kyoo.Controllers
/// <param name="showSlug">The slug of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <param name="episodeNumber">The episode's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The episode found</returns>
Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber);
@@ -147,7 +147,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="slug">The slug of the track</param>
/// <param name="type">The type (Video, Audio or Subtitle)</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The tracl found</returns>
Task<Track> Get(string slug, StreamType type = StreamType.Unknown);
@@ -505,7 +505,7 @@ namespace Kyoo.Controllers
/// <param name="item">The resourcce to edit, it's ID can't change.</param>
/// <param name="resetOld">Should old properties of the resource be discarded or should null values considered as not changed?</param>
/// <typeparam name="T">The type of resources</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The resource edited and completed by database's informations (related items & so on)</returns>
Task<T> Edit<T>(T item, bool resetOld) where T : class, IResource;
@@ -514,7 +514,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="item">The resource to delete</param>
/// <typeparam name="T">The type of resource to delete</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task Delete<T>(T item) where T : class, IResource;
/// <summary>
@@ -522,7 +522,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="id">The id of the resource to delete</param>
/// <typeparam name="T">The type of resource to delete</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task Delete<T>(int id) where T : class, IResource;
/// <summary>
@@ -530,7 +530,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="slug">The slug of the resource to delete</param>
/// <typeparam name="T">The type of resource to delete</typeparam>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task Delete<T>(string slug) where T : class, IResource;
}
}
+17 -12
View File
@@ -1,6 +1,6 @@
using System;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Unity;
namespace Kyoo.Controllers
@@ -8,6 +8,8 @@ namespace Kyoo.Controllers
/// <summary>
/// A common interface used to discord plugins
/// </summary>
/// <remarks>You can inject services in the IPlugin constructor.
/// You should only inject well known services like an ILogger, IConfiguration or IWebHostEnvironment.</remarks>
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
public interface IPlugin
{
@@ -30,30 +32,33 @@ namespace Kyoo.Controllers
/// A list of services that are provided by this service. This allow other plugins to declare dependencies.
/// </summary>
/// <remarks>
/// The format should be the name of the interface ':' and the name of the implementation.
/// For a plugins that provide a new service named IService with a default implementation named Koala, that would
/// be "IService:Koala".
/// You should put directly the type that you will register in configure, Kyoo will detect by itself which
/// interfaces are implemented by your type.
/// </remarks>
string[] Provides { get; }
Type[] Provides { get; }
/// <summary>
/// A list of services that are required by this service.
/// The Core will warn the user that this plugin can't be loaded if a required service is not found.
/// </summary>
/// <remarks>
/// This is the same format as <see cref="Provides"/> but you may leave a blank implementation's name if you don't need a special one.
/// For example, if you need a service named IService but you don't care what implementation it will be, you can use
/// "IService:"
/// Put here the most complete type that are needed for your plugin to work. If you need a LibraryManager,
/// put typeof(ILibraryManager).
/// </remarks>
string[] Requires { get; }
Type[] Requires { get; }
/// <summary>
/// A configure method that will be run on plugin's startup.
/// </summary>
/// <param name="container">A unity container to register new services.</param>
/// <param name="config">The configuration, if you need values at config time (database connection strings...)</param>
void Configure(IUnityContainer container);
/// <summary>
/// An optional configuration step to allow a plugin to change asp net configurations.
/// WARNING: This is only called on Kyoo's startup so you must restart the app to apply this changes.
/// </summary>
/// <param name="app">The Asp.Net application builder. On most case it is not needed but you can use it to add asp net functionalities.</param>
/// <param name="debugMode">True if the app should run in debug mode.</param>
void Configure(IUnityContainer container, IConfiguration config, IApplicationBuilder app, bool debugMode);
void ConfigureAspNet(IApplicationBuilder app) {}
}
}
+29 -3
View File
@@ -1,13 +1,39 @@
using System.Collections.Generic;
using Kyoo.Models;
using Kyoo.Models.Exceptions;
namespace Kyoo.Controllers
{
/// <summary>
/// A manager to load plugins and retrieve information from them.
/// </summary>
public interface IPluginManager
{
/// <summary>
/// Get a single plugin that match the type and name given.
/// </summary>
/// <param name="name">The name of the plugin</param>
/// <typeparam name="T">The type of the plugin</typeparam>
/// <exception cref="ItemNotFoundException">If no plugins match the query</exception>
/// <returns>A plugin that match the queries</returns>
public T GetPlugin<T>(string name);
public IEnumerable<T> GetPlugins<T>();
public IEnumerable<IPlugin> GetAllPlugins();
/// <summary>
/// Get all plugins of the given type.
/// </summary>
/// <typeparam name="T">The type of plugins to get</typeparam>
/// <returns>A list of plugins matching the given type or an empty list of none match.</returns>
public ICollection<T> GetPlugins<T>();
/// <summary>
/// Get all plugins currently running on Kyoo. This also includes deleted plugins if the app as not been restarted.
/// </summary>
/// <returns>All plugins currently loaded.</returns>
public ICollection<IPlugin> GetAllPlugins();
/// <summary>
/// Load new plugins from the plugin directory.
/// </summary>
/// <exception cref="MissingDependencyException">If a plugin can't be loaded because a dependency can't be resolved.</exception>
public void ReloadPlugins();
}
}
+22 -22
View File
@@ -127,21 +127,21 @@ namespace Kyoo.Controllers
/// Get a resource from it's ID.
/// </summary>
/// <param name="id">The id of the resource</param>
/// <exception cref="ItemNotFound">If the item could not be found.</exception>
/// <exception cref="ItemNotFoundException">If the item could not be found.</exception>
/// <returns>The resource found</returns>
Task<T> Get(int id);
/// <summary>
/// Get a resource from it's slug.
/// </summary>
/// <param name="slug">The slug of the resource</param>
/// <exception cref="ItemNotFound">If the item could not be found.</exception>
/// <exception cref="ItemNotFoundException">If the item could not be found.</exception>
/// <returns>The resource found</returns>
Task<T> Get(string slug);
/// <summary>
/// Get the first resource that match the predicate.
/// </summary>
/// <param name="where">A predicate to filter the resource.</param>
/// <exception cref="ItemNotFound">If the item could not be found.</exception>
/// <exception cref="ItemNotFoundException">If the item could not be found.</exception>
/// <returns>The resource found</returns>
Task<T> Get(Expression<Func<T, bool>> where);
@@ -221,7 +221,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="edited">The resourcce to edit, it's ID can't change.</param>
/// <param name="resetOld">Should old properties of the resource be discarded or should null values considered as not changed?</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The resource edited and completed by database's informations (related items & so on)</returns>
Task<T> Edit([NotNull] T edited, bool resetOld);
@@ -229,62 +229,62 @@ namespace Kyoo.Controllers
/// Delete a resource by it's ID
/// </summary>
/// <param name="id">The ID of the resource</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task Delete(int id);
/// <summary>
/// Delete a resource by it's slug
/// </summary>
/// <param name="slug">The slug of the resource</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task Delete(string slug);
/// <summary>
/// Delete a resource
/// </summary>
/// <param name="obj">The resource to delete</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task Delete([NotNull] T obj);
/// <summary>
/// Delete a list of resources.
/// </summary>
/// <param name="objs">One or multiple resources to delete</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task DeleteRange(params T[] objs) => DeleteRange(objs.AsEnumerable());
/// <summary>
/// Delete a list of resources.
/// </summary>
/// <param name="objs">An enumerable of resources to delete</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task DeleteRange(IEnumerable<T> objs);
/// <summary>
/// Delete a list of resources.
/// </summary>
/// <param name="ids">One or multiple resources's id</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task DeleteRange(params int[] ids) => DeleteRange(ids.AsEnumerable());
/// <summary>
/// Delete a list of resources.
/// </summary>
/// <param name="ids">An enumearble of resources's id</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task DeleteRange(IEnumerable<int> ids);
/// <summary>
/// Delete a list of resources.
/// </summary>
/// <param name="slugs">One or multiple resources's slug</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task DeleteRange(params string[] slugs) => DeleteRange(slugs.AsEnumerable());
/// <summary>
/// Delete a list of resources.
/// </summary>
/// <param name="slugs">An enumerable of resources's slug</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task DeleteRange(IEnumerable<string> slugs);
/// <summary>
/// Delete a list of resources.
/// </summary>
/// <param name="where">A predicate to filter resources to delete. Every resource that match this will be deleted.</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
Task DeleteRange([NotNull] Expression<Func<T, bool>> where);
}
@@ -306,7 +306,7 @@ namespace Kyoo.Controllers
/// Get a show's slug from it's ID.
/// </summary>
/// <param name="showID">The ID of the show</param>
/// <exception cref="ItemNotFound">If a show with the given ID is not found.</exception>
/// <exception cref="ItemNotFoundException">If a show with the given ID is not found.</exception>
/// <returns>The show's slug</returns>
Task<string> GetSlug(int showID);
}
@@ -321,7 +321,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="showID">The id of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The season found</returns>
Task<Season> Get(int showID, int seasonNumber);
@@ -330,7 +330,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The season found</returns>
Task<Season> Get(string showSlug, int seasonNumber);
@@ -362,7 +362,7 @@ namespace Kyoo.Controllers
/// <param name="showID">The id of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <param name="episodeNumber">The episode's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The episode found</returns>
Task<Episode> Get(int showID, int seasonNumber, int episodeNumber);
/// <summary>
@@ -371,7 +371,7 @@ namespace Kyoo.Controllers
/// <param name="showSlug">The slug of the show</param>
/// <param name="seasonNumber">The season's number</param>
/// <param name="episodeNumber">The episode's number</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The episode found</returns>
Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber);
@@ -397,7 +397,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="showID">The id of the show</param>
/// <param name="absoluteNumber">The episode's absolute number (The episode number does not reset to 1 after the end of a season.</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The episode found</returns>
Task<Episode> GetAbsolute(int showID, int absoluteNumber);
/// <summary>
@@ -405,7 +405,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="showSlug">The slug of the show</param>
/// <param name="absoluteNumber">The episode's absolute number (The episode number does not reset to 1 after the end of a season.</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The episode found</returns>
Task<Episode> GetAbsolute(string showSlug, int absoluteNumber);
}
@@ -420,7 +420,7 @@ namespace Kyoo.Controllers
/// </summary>
/// <param name="slug">The slug of the track</param>
/// <param name="type">The type (Video, Audio or Subtitle)</param>
/// <exception cref="ItemNotFound">If the item is not found</exception>
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
/// <returns>The tracl found</returns>
Task<Track> Get(string slug, StreamType type = StreamType.Unknown);
+2 -3
View File
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using Kyoo.Models;
using Kyoo.Models.Exceptions;
namespace Kyoo.Controllers
@@ -17,7 +16,7 @@ namespace Kyoo.Controllers
/// <param name="taskSlug">The slug of the task to run</param>
/// <param name="arguments">A list of arguments to pass to the task. An automatic conversion will be made if arguments to not fit.</param>
/// <exception cref="ArgumentException">If the number of arguments is invalid or if an argument can't be converted.</exception>
/// <exception cref="ItemNotFound">The task could not be found.</exception>
/// <exception cref="ItemNotFoundException">The task could not be found.</exception>
void StartTask(string taskSlug, Dictionary<string, object> arguments = null);
/// <summary>
@@ -27,7 +26,7 @@ namespace Kyoo.Controllers
ICollection<ITask> GetRunningTasks();
/// <summary>
/// Get all availables tasks
/// Get all available tasks
/// </summary>
/// <returns>A list of every tasks that this instance know.</returns>
ICollection<ITask> GetAllTasks();
@@ -1,5 +1,4 @@
using Kyoo.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
@@ -66,7 +66,7 @@ namespace Kyoo.Controllers
{
if (_repositories.FirstOrDefault(x => x.RepositoryType == typeof(T)) is IRepository<T> ret)
return ret;
throw new ItemNotFound();
throw new ItemNotFoundException();
}
/// <inheritdoc />