mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Merge pull request #28 from AnonymusRaccoon/config
Adding a configuration api
This commit is contained in:
commit
7a52065196
@ -84,7 +84,7 @@ namespace Kyoo.Authentication
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Configure(IServiceCollection services, ICollection<Type> availableTypes)
|
public void Configure(IServiceCollection services, ICollection<Type> availableTypes)
|
||||||
{
|
{
|
||||||
string publicUrl = _configuration.GetValue<string>("publicUrl").TrimEnd('/');
|
string publicUrl = _configuration.GetPublicUrl();
|
||||||
|
|
||||||
if (_environment.IsDevelopment())
|
if (_environment.IsDevelopment())
|
||||||
IdentityModelEventSource.ShowPII = true;
|
IdentityModelEventSource.ShowPII = true;
|
||||||
@ -98,6 +98,7 @@ namespace Kyoo.Authentication
|
|||||||
services.Configure<PermissionOption>(_configuration.GetSection(PermissionOption.Path));
|
services.Configure<PermissionOption>(_configuration.GetSection(PermissionOption.Path));
|
||||||
services.Configure<CertificateOption>(_configuration.GetSection(CertificateOption.Path));
|
services.Configure<CertificateOption>(_configuration.GetSection(CertificateOption.Path));
|
||||||
services.Configure<AuthenticationOption>(_configuration.GetSection(AuthenticationOption.Path));
|
services.Configure<AuthenticationOption>(_configuration.GetSection(AuthenticationOption.Path));
|
||||||
|
services.AddConfiguration<AuthenticationOption>(AuthenticationOption.Path);
|
||||||
|
|
||||||
|
|
||||||
List<Client> clients = new();
|
List<Client> clients = new();
|
||||||
@ -145,7 +146,7 @@ namespace Kyoo.Authentication
|
|||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.Use((ctx, next) =>
|
app.Use((ctx, next) =>
|
||||||
{
|
{
|
||||||
ctx.SetIdentityServerOrigin(_configuration.GetValue<string>("publicUrl").TrimEnd('/'));
|
ctx.SetIdentityServerOrigin(_configuration.GetPublicUrl());
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
app.UseIdentityServer();
|
app.UseIdentityServer();
|
||||||
|
@ -36,7 +36,7 @@ namespace Kyoo.Authentication
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IFilterMetadata Create(PermissionAttribute attribute)
|
public IFilterMetadata Create(PermissionAttribute attribute)
|
||||||
{
|
{
|
||||||
return new PermissionValidator(attribute.Type, attribute.Kind, _options);
|
return new PermissionValidator(attribute.Type, attribute.Kind, attribute.Group, _options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -58,6 +58,11 @@ namespace Kyoo.Authentication
|
|||||||
/// The kind of permission needed
|
/// The kind of permission needed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Kind? _kind;
|
private readonly Kind? _kind;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The group of he permission
|
||||||
|
/// </summary>
|
||||||
|
private readonly Group _group = Group.Overall;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The permissions options to retrieve default permissions.
|
/// The permissions options to retrieve default permissions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -68,11 +73,13 @@ namespace Kyoo.Authentication
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="permission">The permission to validate</param>
|
/// <param name="permission">The permission to validate</param>
|
||||||
/// <param name="kind">The kind of permission needed</param>
|
/// <param name="kind">The kind of permission needed</param>
|
||||||
|
/// <param name="group">The group of the permission</param>
|
||||||
/// <param name="options">The option containing default values.</param>
|
/// <param name="options">The option containing default values.</param>
|
||||||
public PermissionValidator(string permission, Kind kind, IOptionsMonitor<PermissionOption> options)
|
public PermissionValidator(string permission, Kind kind, Group group, IOptionsMonitor<PermissionOption> options)
|
||||||
{
|
{
|
||||||
_permission = permission;
|
_permission = permission;
|
||||||
_kind = kind;
|
_kind = kind;
|
||||||
|
_group = group;
|
||||||
_options = options;
|
_options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +132,7 @@ namespace Kyoo.Authentication
|
|||||||
}
|
}
|
||||||
|
|
||||||
string permStr = $"{permission.ToLower()}.{kind.ToString()!.ToLower()}";
|
string permStr = $"{permission.ToLower()}.{kind.ToString()!.ToLower()}";
|
||||||
string overallStr = $"overall.{kind.ToString()!.ToLower()}";
|
string overallStr = $"{_group.ToString().ToLower()}.{kind.ToString()!.ToLower()}";
|
||||||
AuthenticateResult res = await context.HttpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
|
AuthenticateResult res = await context.HttpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
|
||||||
if (res.Succeeded)
|
if (res.Succeeded)
|
||||||
{
|
{
|
||||||
|
42
Kyoo.Common/Controllers/IConfigurationManager.cs
Normal file
42
Kyoo.Common/Controllers/IConfigurationManager.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kyoo.Models;
|
||||||
|
using Kyoo.Models.Exceptions;
|
||||||
|
|
||||||
|
namespace Kyoo.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A class to ease configuration management. This work WITH Microsoft's package, you can still use IOptions patterns
|
||||||
|
/// to access your options, this manager ease dynamic work and editing.
|
||||||
|
/// It works with <see cref="ConfigurationReference"/>.
|
||||||
|
/// </summary>
|
||||||
|
public interface IConfigurationManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the value of a setting using it's path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path of the resource (can be separated by ':' or '__')</param>
|
||||||
|
/// <exception cref="ItemNotFoundException">No setting found at the given path.</exception>
|
||||||
|
/// <returns>The value of the settings (if it's a strongly typed one, the given type is instantiated</returns>
|
||||||
|
object GetValue(string path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the value of a setting using it's path.
|
||||||
|
/// If your don't need a strongly typed value, see <see cref="GetValue"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path of the resource (can be separated by ':' or '__')</param>
|
||||||
|
/// <typeparam name="T">A type to strongly type your option.</typeparam>
|
||||||
|
/// <exception cref="InvalidCastException">If your type is not the same as the registered type</exception>
|
||||||
|
/// <exception cref="ItemNotFoundException">No setting found at the given path.</exception>
|
||||||
|
/// <returns>The value of the settings (if it's a strongly typed one, the given type is instantiated</returns>
|
||||||
|
T GetValue<T>(string path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Edit the value of a setting using it's path. Save it to the json file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path of the resource (can be separated by ':' or '__')</param>
|
||||||
|
/// <param name="value">The new value of the resource</param>
|
||||||
|
/// <exception cref="ItemNotFoundException">No setting found at the given path.</exception>
|
||||||
|
Task EditValue(string path, object value);
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
namespace Kyoo.Models
|
|
||||||
{
|
|
||||||
public class Account
|
|
||||||
{
|
|
||||||
public string Username { get; set; }
|
|
||||||
public string Email { get; set; }
|
|
||||||
public string Picture { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,6 +15,15 @@ namespace Kyoo.Models.Permissions
|
|||||||
Delete
|
Delete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The group of the permission.
|
||||||
|
/// </summary>
|
||||||
|
public enum Group
|
||||||
|
{
|
||||||
|
Overall,
|
||||||
|
Admin
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specify permissions needed for the API.
|
/// Specify permissions needed for the API.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -29,6 +38,10 @@ namespace Kyoo.Models.Permissions
|
|||||||
/// The needed permission kind.
|
/// The needed permission kind.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Kind Kind { get; }
|
public Kind Kind { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// The group of this permission
|
||||||
|
/// </summary>
|
||||||
|
public Group Group { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ask a permission to run an action.
|
/// Ask a permission to run an action.
|
||||||
@ -38,12 +51,17 @@ namespace Kyoo.Models.Permissions
|
|||||||
/// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
|
/// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="permission">The kind of permission needed</param>
|
/// <param name="permission">The kind of permission needed</param>
|
||||||
public PermissionAttribute(string type, Kind permission)
|
/// <param name="group">
|
||||||
|
/// The group of this permission (allow grouped permission like overall.read
|
||||||
|
/// for all read permissions of this group)
|
||||||
|
/// </param>
|
||||||
|
public PermissionAttribute(string type, Kind permission, Group group = Group.Overall)
|
||||||
{
|
{
|
||||||
if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
|
if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
|
||||||
type = type[..^3];
|
type = type[..^3];
|
||||||
Type = type.ToLower();
|
Type = type.ToLower();
|
||||||
Kind = permission;
|
Kind = permission;
|
||||||
|
Group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
97
Kyoo.Common/Models/ConfigurationReference.cs
Normal file
97
Kyoo.Common/Models/ConfigurationReference.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
|
namespace Kyoo.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A class given information about a strongly typed configuration.
|
||||||
|
/// </summary>
|
||||||
|
public class ConfigurationReference
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The path of the resource (separated by ':')
|
||||||
|
/// </summary>
|
||||||
|
public string Path { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the resource.
|
||||||
|
/// </summary>
|
||||||
|
public Type Type { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="ConfigurationReference"/> using a given path and type.
|
||||||
|
/// This method does not create sub configuration resources. Please see <see cref="CreateReference"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path of the resource (separated by ':' or "__")</param>
|
||||||
|
/// <param name="type">The type of the resource</param>
|
||||||
|
/// <seealso cref="CreateReference"/>
|
||||||
|
public ConfigurationReference(string path, Type type)
|
||||||
|
{
|
||||||
|
Path = path;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the list of configuration reference a type has.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">
|
||||||
|
/// The base path of the type (separated by ':' or "__". If empty, it will start at root)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="type">The type of the object</param>
|
||||||
|
/// <returns>The list of configuration reference a type has.</returns>
|
||||||
|
public static IEnumerable<ConfigurationReference> CreateReference(string path, [NotNull] Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException(nameof(type));
|
||||||
|
|
||||||
|
List<ConfigurationReference> ret = new()
|
||||||
|
{
|
||||||
|
new ConfigurationReference(path, type)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (!type.IsClass || type.AssemblyQualifiedName?.StartsWith("System") == true)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
Type enumerable = Utility.GetGenericDefinition(type, typeof(IEnumerable<>));
|
||||||
|
Type dictionary = Utility.GetGenericDefinition(type, typeof(IDictionary<,>));
|
||||||
|
Type dictionaryKey = dictionary?.GetGenericArguments()[0];
|
||||||
|
|
||||||
|
if (dictionary != null && dictionaryKey == typeof(string))
|
||||||
|
ret.AddRange(CreateReference($"{path}:{type.Name}:*", dictionary.GetGenericArguments()[1]));
|
||||||
|
else if (dictionary != null && dictionaryKey == typeof(int))
|
||||||
|
ret.AddRange(CreateReference($"{path}:{type.Name}:", dictionary.GetGenericArguments()[1]));
|
||||||
|
else if (enumerable != null)
|
||||||
|
ret.AddRange(CreateReference($"{path}:{type.Name}:", enumerable.GetGenericArguments()[0]));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (PropertyInfo child in type.GetProperties())
|
||||||
|
ret.AddRange(CreateReference($"{path}:{child.Name}", child.PropertyType));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the list of configuration reference a type has.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">
|
||||||
|
/// The base path of the type (separated by ':' or "__". If empty, it will start at root)
|
||||||
|
/// </param>
|
||||||
|
/// <typeparam name="T">The type of the object</typeparam>
|
||||||
|
/// <returns>The list of configuration reference a type has.</returns>
|
||||||
|
public static IEnumerable<ConfigurationReference> CreateReference<T>(string path)
|
||||||
|
{
|
||||||
|
return CreateReference(path, typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ConfigurationReference CreateUntyped(string path)
|
||||||
|
{
|
||||||
|
return new(path, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
namespace Kyoo.Models
|
|
||||||
{
|
|
||||||
public enum ImageType { Poster, Background, Logo }
|
|
||||||
}
|
|
@ -1,5 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
|
using Kyoo.Models;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Kyoo
|
namespace Kyoo
|
||||||
@ -62,5 +65,46 @@ namespace Kyoo
|
|||||||
services.Add(ServiceDescriptor.Describe(typeof(T), typeof(T2), lifetime));
|
services.Add(ServiceDescriptor.Describe(typeof(T), typeof(T2), lifetime));
|
||||||
return services.AddRepository<T2>(lifetime);
|
return services.AddRepository<T2>(lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add an editable configuration to the editable configuration list
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services">The service collection to edit</param>
|
||||||
|
/// <param name="path">The root path of the editable configuration. It should not be a nested type.</param>
|
||||||
|
/// <typeparam name="T">The type of the configuration</typeparam>
|
||||||
|
/// <returns>The given service collection is returned.</returns>
|
||||||
|
public static IServiceCollection AddConfiguration<T>(this IServiceCollection services, string path)
|
||||||
|
where T : class
|
||||||
|
{
|
||||||
|
if (services.Any(x => x.ServiceType == typeof(T)))
|
||||||
|
return services;
|
||||||
|
foreach (ConfigurationReference confRef in ConfigurationReference.CreateReference<T>(path))
|
||||||
|
services.AddSingleton(confRef);
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add an editable configuration to the editable configuration list.
|
||||||
|
/// WARNING: this method allow you to add an unmanaged type. This type won't be editable. This can be used
|
||||||
|
/// for external libraries or variable arguments.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services">The service collection to edit</param>
|
||||||
|
/// <param name="path">The root path of the editable configuration. It should not be a nested type.</param>
|
||||||
|
/// <returns>The given service collection is returned.</returns>
|
||||||
|
public static IServiceCollection AddUntypedConfiguration(this IServiceCollection services, string path)
|
||||||
|
{
|
||||||
|
services.AddSingleton(ConfigurationReference.CreateUntyped(path));
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the public URL of kyoo using the given configuration instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="configuration">The configuration instance</param>
|
||||||
|
/// <returns>The public URl of kyoo (without a slash at the end)</returns>
|
||||||
|
public static string GetPublicUrl(this IConfiguration configuration)
|
||||||
|
{
|
||||||
|
return configuration["basics:publicUrl"]?.TrimEnd('/') ?? "http://localhost:5000";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,7 +10,6 @@ using System.Text;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Kyoo.Models;
|
|
||||||
using Kyoo.Models.Attributes;
|
using Kyoo.Models.Attributes;
|
||||||
|
|
||||||
namespace Kyoo
|
namespace Kyoo
|
||||||
@ -33,7 +32,7 @@ namespace Kyoo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the name of a property. Usfull for selectors as members ex: Load(x => x.Shows)
|
/// Get the name of a property. Useful for selectors as members ex: Load(x => x.Shows)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ex">The expression</param>
|
/// <param name="ex">The expression</param>
|
||||||
/// <returns>The name of the expression</returns>
|
/// <returns>The name of the expression</returns>
|
||||||
@ -71,10 +70,10 @@ namespace Kyoo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Slugify a string (Replace spaces by -, Uniformise accents é -> e)
|
/// Slugify a string (Replace spaces by -, Uniformize accents é -> e)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="str">The string to slugify</param>
|
/// <param name="str">The string to slugify</param>
|
||||||
/// <returns>The slugified string</returns>
|
/// <returns>The slug version of the given string</returns>
|
||||||
public static string ToSlug(string str)
|
public static string ToSlug(string str)
|
||||||
{
|
{
|
||||||
if (str == null)
|
if (str == null)
|
||||||
@ -99,36 +98,11 @@ namespace Kyoo
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the image of a show using the <see cref="ImageType"/> type.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="show">The owner of the image</param>
|
|
||||||
/// <param name="imgUrl">The url of the image</param>
|
|
||||||
/// <param name="type">The type of the image</param>
|
|
||||||
public static void SetImage(Show show, string imgUrl, ImageType type)
|
|
||||||
{
|
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
case ImageType.Poster:
|
|
||||||
show.Poster = imgUrl;
|
|
||||||
break;
|
|
||||||
case ImageType.Logo:
|
|
||||||
show.Logo = imgUrl;
|
|
||||||
break;
|
|
||||||
case ImageType.Background:
|
|
||||||
show.Backdrop = imgUrl;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Merge two lists, can keep duplicates or remove them.
|
/// Merge two lists, can keep duplicates or remove them.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="first">The first enumarble to merge</param>
|
/// <param name="first">The first enumerable to merge</param>
|
||||||
/// <param name="second">The second enumerable to merge, if items from this list are equals to one from the first, they are not keeped</param>
|
/// <param name="second">The second enumerable to merge, if items from this list are equals to one from the first, they are not kept</param>
|
||||||
/// <param name="isEqual">Equality function to compare items. If this is null, duplicated elements are kept</param>
|
/// <param name="isEqual">Equality function to compare items. If this is null, duplicated elements are kept</param>
|
||||||
/// <returns>The two list merged as an array</returns>
|
/// <returns>The two list merged as an array</returns>
|
||||||
public static T[] MergeLists<T>(IEnumerable<T> first,
|
public static T[] MergeLists<T>(IEnumerable<T> first,
|
||||||
@ -150,7 +124,7 @@ namespace Kyoo
|
|||||||
/// At the end, the OnMerge method of first will be called if first is a <see cref="IOnMerge"/>
|
/// At the end, the OnMerge method of first will be called if first is a <see cref="IOnMerge"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="first">The object to assign</param>
|
/// <param name="first">The object to assign</param>
|
||||||
/// <param name="second">The object containg new values</param>
|
/// <param name="second">The object containing new values</param>
|
||||||
/// <typeparam name="T">Fields of T will be used</typeparam>
|
/// <typeparam name="T">Fields of T will be used</typeparam>
|
||||||
/// <returns><see cref="first"/></returns>
|
/// <returns><see cref="first"/></returns>
|
||||||
public static T Assign<T>(T first, T second)
|
public static T Assign<T>(T first, T second)
|
||||||
@ -339,7 +313,7 @@ namespace Kyoo
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type">The type to check</param>
|
/// <param name="type">The type to check</param>
|
||||||
/// <param name="genericType">The generic type to check against (Only generic types are supported like typeof(IEnumerable<>).</param>
|
/// <param name="genericType">The generic type to check against (Only generic types are supported like typeof(IEnumerable<>).</param>
|
||||||
/// <returns>The generic definition of genericType that type inherit or null if type does not implement the genric type.</returns>
|
/// <returns>The generic definition of genericType that type inherit or null if type does not implement the generic type.</returns>
|
||||||
/// <exception cref="ArgumentNullException"><see cref="type"/> and <see cref="genericType"/> can't be null</exception>
|
/// <exception cref="ArgumentNullException"><see cref="type"/> and <see cref="genericType"/> can't be null</exception>
|
||||||
/// <exception cref="ArgumentException"><see cref="genericType"/> must be a generic type</exception>
|
/// <exception cref="ArgumentException"><see cref="genericType"/> must be a generic type</exception>
|
||||||
public static Type GetGenericDefinition([NotNull] Type type, [NotNull] Type genericType)
|
public static Type GetGenericDefinition([NotNull] Type type, [NotNull] Type genericType)
|
||||||
|
@ -7,7 +7,6 @@ using Kyoo.Models;
|
|||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
|
|
||||||
namespace Kyoo.CommonApi
|
namespace Kyoo.CommonApi
|
||||||
{
|
{
|
||||||
@ -18,10 +17,10 @@ namespace Kyoo.CommonApi
|
|||||||
private readonly IRepository<T> _repository;
|
private readonly IRepository<T> _repository;
|
||||||
protected readonly string BaseURL;
|
protected readonly string BaseURL;
|
||||||
|
|
||||||
public CrudApi(IRepository<T> repository, IConfiguration configuration)
|
public CrudApi(IRepository<T> repository, string baseURL)
|
||||||
{
|
{
|
||||||
_repository = repository;
|
_repository = repository;
|
||||||
BaseURL = configuration.GetValue<string>("publicUrl").TrimEnd('/');
|
BaseURL = baseURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,10 +66,6 @@ namespace Kyoo.Postgresql
|
|||||||
if (_environment.IsDevelopment())
|
if (_environment.IsDevelopment())
|
||||||
x.EnableDetailedErrors().EnableSensitiveDataLogging();
|
x.EnableDetailedErrors().EnableSensitiveDataLogging();
|
||||||
});
|
});
|
||||||
// services.AddScoped<DatabaseContext>(_ => new PostgresContext(
|
|
||||||
// _configuration.GetDatabaseConnection("postgres"),
|
|
||||||
// _environment.IsDevelopment()));
|
|
||||||
// services.AddScoped<DbContext>(x => x.GetRequiredService<PostgresContext>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
150
Kyoo/Controllers/ConfigurationManager.cs
Normal file
150
Kyoo/Controllers/ConfigurationManager.cs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kyoo.Api;
|
||||||
|
using Kyoo.Models;
|
||||||
|
using Kyoo.Models.Exceptions;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Kyoo.Controllers
|
||||||
|
{
|
||||||
|
public class ConfigurationManager : IConfigurationManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration to retrieve and edit.
|
||||||
|
/// </summary>
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The strongly typed list of options
|
||||||
|
/// </summary>
|
||||||
|
private readonly Dictionary<string, Type> _references;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="ConfigurationApi"/> using the given configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="configuration">The configuration to use.</param>
|
||||||
|
/// <param name="references">The strongly typed option list.</param>
|
||||||
|
public ConfigurationManager(IConfiguration configuration, IEnumerable<ConfigurationReference> references)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
_references = references.ToDictionary(x => x.Path, x => x.Type, StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type GetType(string path)
|
||||||
|
{
|
||||||
|
path = path.Replace("__", ":");
|
||||||
|
|
||||||
|
// TODO handle lists and dictionaries.
|
||||||
|
if (_references.TryGetValue(path, out Type type))
|
||||||
|
{
|
||||||
|
if (type != null)
|
||||||
|
return type;
|
||||||
|
throw new ArgumentException($"The configuration at {path} is not editable or readable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string parent = path.Contains(':') ? path[..path.IndexOf(':')] : null;
|
||||||
|
if (parent != null && _references.TryGetValue(parent, out type) && type == null)
|
||||||
|
throw new ArgumentException($"The configuration at {path} is not editable or readable.");
|
||||||
|
throw new ItemNotFoundException($"No configuration exists for the name: {path}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public object GetValue(string path)
|
||||||
|
{
|
||||||
|
path = path.Replace("__", ":");
|
||||||
|
// TODO handle lists and dictionaries.
|
||||||
|
Type type = GetType(path);
|
||||||
|
object ret = _configuration.GetValue(type, path);
|
||||||
|
if (ret != null)
|
||||||
|
return ret;
|
||||||
|
object option = Activator.CreateInstance(type);
|
||||||
|
_configuration.Bind(path, option);
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public T GetValue<T>(string path)
|
||||||
|
{
|
||||||
|
path = path.Replace("__", ":");
|
||||||
|
// TODO handle lists and dictionaries.
|
||||||
|
Type type = GetType(path);
|
||||||
|
if (typeof(T).IsAssignableFrom(type))
|
||||||
|
throw new InvalidCastException($"The type {typeof(T).Name} is not valid for " +
|
||||||
|
$"a resource of type {type.Name}.");
|
||||||
|
return (T)GetValue(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task EditValue(string path, object value)
|
||||||
|
{
|
||||||
|
path = path.Replace("__", ":");
|
||||||
|
Type type = GetType(path);
|
||||||
|
value = JObject.FromObject(value).ToObject(type);
|
||||||
|
if (value == null)
|
||||||
|
throw new ArgumentException("Invalid value format.");
|
||||||
|
|
||||||
|
ExpandoObject config = ToObject(_configuration);
|
||||||
|
IDictionary<string, object> configDic = config;
|
||||||
|
configDic[path] = value;
|
||||||
|
JObject obj = JObject.FromObject(config);
|
||||||
|
await using StreamWriter writer = new(Program.JsonConfigPath);
|
||||||
|
await writer.WriteAsync(obj.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transform a configuration to a strongly typed object (the root configuration is an <see cref="ExpandoObject"/>
|
||||||
|
/// but child elements are using strong types.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config">The configuration to transform</param>
|
||||||
|
/// <returns>A strongly typed representation of the configuration.</returns>
|
||||||
|
[SuppressMessage("ReSharper", "RedundantJumpStatement")]
|
||||||
|
private ExpandoObject ToObject(IConfiguration config)
|
||||||
|
{
|
||||||
|
ExpandoObject obj = new();
|
||||||
|
|
||||||
|
foreach (IConfigurationSection section in config.GetChildren())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Type type = GetType(section.Path);
|
||||||
|
obj.TryAdd(section.Key, section.Get(type));
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
obj.TryAdd(section.Key, ToUntyped(section));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transform the configuration section in nested expando objects.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config">The section to convert</param>
|
||||||
|
/// <returns>The converted section</returns>
|
||||||
|
private static object ToUntyped(IConfigurationSection config)
|
||||||
|
{
|
||||||
|
ExpandoObject obj = new();
|
||||||
|
|
||||||
|
foreach (IConfigurationSection section in config.GetChildren())
|
||||||
|
{
|
||||||
|
obj.TryAdd(section.Key, ToUntyped(section));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj.Any())
|
||||||
|
return config.Value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,10 +4,11 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
@ -24,7 +25,7 @@ namespace Kyoo.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The configuration to get the plugin's directory.
|
/// The configuration to get the plugin's directory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IConfiguration _config;
|
private readonly IOptionsMonitor<BasicOptions> _options;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger used by this class.
|
/// The logger used by this class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -39,14 +40,14 @@ namespace Kyoo.Controllers
|
|||||||
/// Create a new <see cref="PluginManager"/> instance.
|
/// Create a new <see cref="PluginManager"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="provider">A service container to allow initialization of plugins</param>
|
/// <param name="provider">A service container to allow initialization of plugins</param>
|
||||||
/// <param name="config">The configuration instance, to get the plugin's directory path.</param>
|
/// <param name="options">The configuration instance, to get the plugin's directory path.</param>
|
||||||
/// <param name="logger">The logger used by this class.</param>
|
/// <param name="logger">The logger used by this class.</param>
|
||||||
public PluginManager(IServiceProvider provider,
|
public PluginManager(IServiceProvider provider,
|
||||||
IConfiguration config,
|
IOptionsMonitor<BasicOptions> options,
|
||||||
ILogger<PluginManager> logger)
|
ILogger<PluginManager> logger)
|
||||||
{
|
{
|
||||||
_provider = provider;
|
_provider = provider;
|
||||||
_config = config;
|
_options = options;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ namespace Kyoo.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void LoadPlugins(ICollection<IPlugin> plugins)
|
public void LoadPlugins(ICollection<IPlugin> plugins)
|
||||||
{
|
{
|
||||||
string pluginFolder = _config.GetValue<string>("plugins");
|
string pluginFolder = _options.CurrentValue.PluginPath;
|
||||||
if (!Directory.Exists(pluginFolder))
|
if (!Directory.Exists(pluginFolder))
|
||||||
Directory.CreateDirectory(pluginFolder);
|
Directory.CreateDirectory(pluginFolder);
|
||||||
|
|
||||||
|
@ -7,10 +7,11 @@ using System.Threading.Tasks;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Kyoo.Models.Attributes;
|
using Kyoo.Models.Attributes;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Kyoo.Models.Options;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
@ -27,7 +28,7 @@ namespace Kyoo.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The configuration instance used to get schedule information
|
/// The configuration instance used to get schedule information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IOptionsMonitor<TaskOptions> _options;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger instance.
|
/// The logger instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -56,15 +57,15 @@ namespace Kyoo.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tasks">The list of tasks to manage</param>
|
/// <param name="tasks">The list of tasks to manage</param>
|
||||||
/// <param name="provider">The service provider to request services for tasks</param>
|
/// <param name="provider">The service provider to request services for tasks</param>
|
||||||
/// <param name="configuration">The configuration to load schedule information.</param>
|
/// <param name="options">The configuration to load schedule information.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
public TaskManager(IEnumerable<ITask> tasks,
|
public TaskManager(IEnumerable<ITask> tasks,
|
||||||
IServiceProvider provider,
|
IServiceProvider provider,
|
||||||
IConfiguration configuration,
|
IOptionsMonitor<TaskOptions> options,
|
||||||
ILogger<TaskManager> logger)
|
ILogger<TaskManager> logger)
|
||||||
{
|
{
|
||||||
_provider = provider;
|
_provider = provider;
|
||||||
_configuration = configuration.GetSection("scheduledTasks");
|
_options = options;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_tasks = tasks.Select(x => (x, GetNextTaskDate(x.Slug))).ToList();
|
_tasks = tasks.Select(x => (x, GetNextTaskDate(x.Slug))).ToList();
|
||||||
|
|
||||||
@ -224,10 +225,9 @@ namespace Kyoo.Controllers
|
|||||||
/// <returns>The next date.</returns>
|
/// <returns>The next date.</returns>
|
||||||
private DateTime GetNextTaskDate(string taskSlug)
|
private DateTime GetNextTaskDate(string taskSlug)
|
||||||
{
|
{
|
||||||
TimeSpan delay = _configuration.GetValue<TimeSpan>(taskSlug);
|
if (_options.CurrentValue.Scheduled.TryGetValue(taskSlug, out TimeSpan delay))
|
||||||
if (delay == default)
|
return DateTime.Now + delay;
|
||||||
return DateTime.MaxValue;
|
return DateTime.MaxValue;
|
||||||
return DateTime.Now + delay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -1,26 +1,25 @@
|
|||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class ThumbnailsManager : IThumbnailsManager
|
public class ThumbnailsManager : IThumbnailsManager
|
||||||
{
|
{
|
||||||
private readonly IFileManager _files;
|
private readonly IFileManager _files;
|
||||||
private readonly string _peoplePath;
|
private readonly IOptionsMonitor<BasicOptions> _options;
|
||||||
private readonly string _providerPath;
|
|
||||||
|
|
||||||
public ThumbnailsManager(IConfiguration configuration, IFileManager files)
|
public ThumbnailsManager(IFileManager files, IOptionsMonitor<BasicOptions> options)
|
||||||
{
|
{
|
||||||
_files = files;
|
_files = files;
|
||||||
_peoplePath = Path.GetFullPath(configuration.GetValue<string>("peoplePath"));
|
_options = options;
|
||||||
_providerPath = Path.GetFullPath(configuration.GetValue<string>("providerPath"));
|
Directory.CreateDirectory(_options.CurrentValue.PeoplePath);
|
||||||
Directory.CreateDirectory(_peoplePath);
|
Directory.CreateDirectory(_options.CurrentValue.ProviderPath);
|
||||||
Directory.CreateDirectory(_providerPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task DownloadImage(string url, string localPath, string what)
|
private static async Task DownloadImage(string url, string localPath, string what)
|
||||||
@ -141,16 +140,18 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
if (people == null)
|
if (people == null)
|
||||||
throw new ArgumentNullException(nameof(people));
|
throw new ArgumentNullException(nameof(people));
|
||||||
string thumbPath = Path.GetFullPath(Path.Combine(_peoplePath, $"{people.Slug}.jpg"));
|
string peoplePath = _options.CurrentValue.PeoplePath;
|
||||||
return Task.FromResult(thumbPath.StartsWith(_peoplePath) ? thumbPath : null);
|
string thumbPath = Path.GetFullPath(Path.Combine(peoplePath, $"{people.Slug}.jpg"));
|
||||||
|
return Task.FromResult(thumbPath.StartsWith(peoplePath) ? thumbPath : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<string> GetProviderLogo(Provider provider)
|
public Task<string> GetProviderLogo(Provider provider)
|
||||||
{
|
{
|
||||||
if (provider == null)
|
if (provider == null)
|
||||||
throw new ArgumentNullException(nameof(provider));
|
throw new ArgumentNullException(nameof(provider));
|
||||||
string thumbPath = Path.GetFullPath(Path.Combine(_providerPath, $"{provider.Slug}.{provider.LogoExtension}"));
|
string providerPath = _options.CurrentValue.ProviderPath;
|
||||||
return Task.FromResult(thumbPath.StartsWith(_providerPath) ? thumbPath : null);
|
string thumbPath = Path.GetFullPath(Path.Combine(providerPath, $"{provider.Slug}.{provider.LogoExtension}"));
|
||||||
|
return Task.FromResult(thumbPath.StartsWith(providerPath) ? thumbPath : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@ using System.IO;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Kyoo.Models.Options;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Stream = Kyoo.Models.Watch.Stream;
|
using Stream = Kyoo.Models.Watch.Stream;
|
||||||
|
|
||||||
// We use threads so tasks are not always awaited.
|
// We use threads so tasks are not always awaited.
|
||||||
@ -66,20 +67,18 @@ namespace Kyoo.Controllers
|
|||||||
tracks = Array.Empty<Track>();
|
tracks = Array.Empty<Track>();
|
||||||
|
|
||||||
if (ptr != IntPtr.Zero)
|
if (ptr != IntPtr.Zero)
|
||||||
free(ptr); // free_streams is not necesarry since the Marshal free the unmanaged pointers.
|
free(ptr); // free_streams is not necessary since the Marshal free the unmanaged pointers.
|
||||||
return tracks;
|
return tracks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IFileManager _files;
|
private readonly IFileManager _files;
|
||||||
private readonly string _transmuxPath;
|
private readonly IOptions<BasicOptions> _options;
|
||||||
private readonly string _transcodePath;
|
|
||||||
|
|
||||||
public Transcoder(IConfiguration config, IFileManager files)
|
public Transcoder(IFileManager files, IOptions<BasicOptions> options)
|
||||||
{
|
{
|
||||||
_files = files;
|
_files = files;
|
||||||
_transmuxPath = Path.GetFullPath(config.GetValue<string>("transmuxTempPath"));
|
_options = options;
|
||||||
_transcodePath = Path.GetFullPath(config.GetValue<string>("transcodeTempPath"));
|
|
||||||
|
|
||||||
if (TranscoderAPI.init() != Marshal.SizeOf<Stream>())
|
if (TranscoderAPI.init() != Marshal.SizeOf<Stream>())
|
||||||
throw new BadTranscoderException();
|
throw new BadTranscoderException();
|
||||||
@ -100,7 +99,7 @@ namespace Kyoo.Controllers
|
|||||||
if (!File.Exists(episode.Path))
|
if (!File.Exists(episode.Path))
|
||||||
throw new ArgumentException("Path does not exists. Can't transcode.");
|
throw new ArgumentException("Path does not exists. Can't transcode.");
|
||||||
|
|
||||||
string folder = Path.Combine(_transmuxPath, episode.Slug);
|
string folder = Path.Combine(_options.Value.TransmuxPath, episode.Slug);
|
||||||
string manifest = Path.Combine(folder, episode.Slug + ".m3u8");
|
string manifest = Path.Combine(folder, episode.Slug + ".m3u8");
|
||||||
float playableDuration = 0;
|
float playableDuration = 0;
|
||||||
bool transmuxFailed = false;
|
bool transmuxFailed = false;
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Kyoo.Tasks;
|
using Kyoo.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
|
||||||
namespace Kyoo
|
namespace Kyoo
|
||||||
{
|
{
|
||||||
@ -66,9 +72,44 @@ namespace Kyoo
|
|||||||
typeof(IProviderRepository)
|
typeof(IProviderRepository)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration to use.
|
||||||
|
/// </summary>
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new core module instance and use the given configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="configuration">The configuration to use</param>
|
||||||
|
public CoreModule(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Configure(IServiceCollection services, ICollection<Type> availableTypes)
|
public void Configure(IServiceCollection services, ICollection<Type> availableTypes)
|
||||||
{
|
{
|
||||||
|
string publicUrl = _configuration.GetPublicUrl();
|
||||||
|
|
||||||
|
services.Configure<BasicOptions>(_configuration.GetSection(BasicOptions.Path));
|
||||||
|
services.AddConfiguration<BasicOptions>(BasicOptions.Path);
|
||||||
|
services.Configure<TaskOptions>(_configuration.GetSection(TaskOptions.Path));
|
||||||
|
services.AddConfiguration<TaskOptions>(TaskOptions.Path);
|
||||||
|
services.Configure<MediaOptions>(_configuration.GetSection(MediaOptions.Path));
|
||||||
|
services.AddConfiguration<MediaOptions>(MediaOptions.Path);
|
||||||
|
services.AddUntypedConfiguration("database");
|
||||||
|
services.AddUntypedConfiguration("logging");
|
||||||
|
|
||||||
|
services.AddControllers()
|
||||||
|
.AddNewtonsoftJson(x =>
|
||||||
|
{
|
||||||
|
x.SerializerSettings.ContractResolver = new JsonPropertyIgnorer(publicUrl);
|
||||||
|
x.SerializerSettings.Converters.Add(new PeopleRoleConverter());
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddSingleton<IConfigurationManager, ConfigurationManager>();
|
||||||
services.AddSingleton<IFileManager, FileManager>();
|
services.AddSingleton<IFileManager, FileManager>();
|
||||||
services.AddSingleton<ITranscoder, Transcoder>();
|
services.AddSingleton<ITranscoder, Transcoder>();
|
||||||
services.AddSingleton<IThumbnailsManager, ThumbnailsManager>();
|
services.AddSingleton<IThumbnailsManager, ThumbnailsManager>();
|
||||||
@ -99,5 +140,22 @@ namespace Kyoo
|
|||||||
if (services.All(x => x.ServiceType != typeof(IPermissionValidator)))
|
if (services.All(x => x.ServiceType != typeof(IPermissionValidator)))
|
||||||
services.AddSingleton<IPermissionValidator, PassthroughPermissionValidator>();
|
services.AddSingleton<IPermissionValidator, PassthroughPermissionValidator>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void ConfigureAspNet(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
FileExtensionContentTypeProvider contentTypeProvider = new();
|
||||||
|
contentTypeProvider.Mappings[".data"] = "application/octet-stream";
|
||||||
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
|
{
|
||||||
|
ContentTypeProvider = contentTypeProvider,
|
||||||
|
FileProvider = new PhysicalFileProvider(Path.Join(AppDomain.CurrentDomain.BaseDirectory, "wwwroot"))
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapControllers();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
48
Kyoo/Models/Options/BasicOptions.cs
Normal file
48
Kyoo/Models/Options/BasicOptions.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
namespace Kyoo.Models.Options
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The typed list of basic/global options for Kyoo
|
||||||
|
/// </summary>
|
||||||
|
public class BasicOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The path of this list of options
|
||||||
|
/// </summary>
|
||||||
|
public const string Path = "Basics";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The internal url where the server will listen
|
||||||
|
/// </summary>
|
||||||
|
public string Url { get; set; } = "http://*:5000";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The public url that will be used in items response and in authentication server host.
|
||||||
|
/// </summary>
|
||||||
|
public string PublicUrl { get; set; } = "http://localhost:5000/";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path of the plugin directory.
|
||||||
|
/// </summary>
|
||||||
|
public string PluginPath { get; set; } = "plugins/";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path of the people pictures.
|
||||||
|
/// </summary>
|
||||||
|
public string PeoplePath { get; set; } = "people/";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path of providers icons.
|
||||||
|
/// </summary>
|
||||||
|
public string ProviderPath { get; set; } = "providers/";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The temporary folder to cache transmuxed file.
|
||||||
|
/// </summary>
|
||||||
|
public string TransmuxPath { get; set; } = "cached/transmux";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The temporary folder to cache transcoded file.
|
||||||
|
/// </summary>
|
||||||
|
public string TranscodePath { get; set; } = "cached/transcode";
|
||||||
|
}
|
||||||
|
}
|
23
Kyoo/Models/Options/MediaOptions.cs
Normal file
23
Kyoo/Models/Options/MediaOptions.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
namespace Kyoo.Models.Options
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options for media registering.
|
||||||
|
/// </summary>
|
||||||
|
public class MediaOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The path of this options
|
||||||
|
/// </summary>
|
||||||
|
public const string Path = "Media";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A regex for episodes
|
||||||
|
/// </summary>
|
||||||
|
public string Regex { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A regex for subtitles
|
||||||
|
/// </summary>
|
||||||
|
public string SubtitleRegex { get; set; }
|
||||||
|
}
|
||||||
|
}
|
28
Kyoo/Models/Options/TaskOptions.cs
Normal file
28
Kyoo/Models/Options/TaskOptions.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
|
namespace Kyoo.Models.Options
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options related to tasks
|
||||||
|
/// </summary>
|
||||||
|
public class TaskOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The path of this options
|
||||||
|
/// </summary>
|
||||||
|
public const string Path = "Tasks";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of tasks that can be run concurrently.
|
||||||
|
/// </summary>
|
||||||
|
public int Parallels { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The delay of tasks that should be automatically started at fixed times.
|
||||||
|
/// </summary>
|
||||||
|
[UsedImplicitly]
|
||||||
|
public Dictionary<string, TimeSpan> Scheduled { get; set; } = new();
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
@ -14,10 +15,16 @@ namespace Kyoo
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The path of the json configuration of the application.
|
||||||
|
/// </summary>
|
||||||
|
public const string JsonConfigPath = "./settings.json";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Main function of the program
|
/// Main function of the program
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">Command line arguments</param>
|
/// <param name="args">Command line arguments</param>
|
||||||
|
[SuppressMessage("ReSharper", "ConditionIsAlwaysTrueOrFalse")]
|
||||||
public static async Task Main(string[] args)
|
public static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
if (!File.Exists("./settings.json"))
|
if (!File.Exists("./settings.json"))
|
||||||
@ -64,7 +71,7 @@ namespace Kyoo
|
|||||||
/// <returns>The modified configuration builder</returns>
|
/// <returns>The modified configuration builder</returns>
|
||||||
private static IConfigurationBuilder SetupConfig(IConfigurationBuilder builder, string[] args)
|
private static IConfigurationBuilder SetupConfig(IConfigurationBuilder builder, string[] args)
|
||||||
{
|
{
|
||||||
return builder.AddJsonFile("./settings.json", false, true)
|
return builder.AddJsonFile(JsonConfigPath, false, true)
|
||||||
.AddEnvironmentVariables()
|
.AddEnvironmentVariables()
|
||||||
.AddCommandLine(args);
|
.AddCommandLine(args);
|
||||||
}
|
}
|
||||||
@ -76,14 +83,16 @@ namespace Kyoo
|
|||||||
/// <returns>A new web host instance</returns>
|
/// <returns>A new web host instance</returns>
|
||||||
private static IWebHostBuilder CreateWebHostBuilder(string[] args)
|
private static IWebHostBuilder CreateWebHostBuilder(string[] args)
|
||||||
{
|
{
|
||||||
|
IConfiguration configuration = SetupConfig(new ConfigurationBuilder(), args).Build();
|
||||||
|
|
||||||
return new WebHostBuilder()
|
return new WebHostBuilder()
|
||||||
.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
|
.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
|
||||||
.UseConfiguration(SetupConfig(new ConfigurationBuilder(), args).Build())
|
.UseConfiguration(configuration)
|
||||||
.ConfigureAppConfiguration(x => SetupConfig(x, args))
|
.ConfigureAppConfiguration(x => SetupConfig(x, args))
|
||||||
.ConfigureLogging((context, builder) =>
|
.ConfigureLogging((context, builder) =>
|
||||||
{
|
{
|
||||||
builder.AddConfiguration(context.Configuration.GetSection("logging"))
|
builder.AddConfiguration(context.Configuration.GetSection("logging"))
|
||||||
.AddSimpleConsole(x =>
|
.AddSimpleConsole(x =>
|
||||||
{
|
{
|
||||||
x.TimestampFormat = "[hh:mm:ss] ";
|
x.TimestampFormat = "[hh:mm:ss] ";
|
||||||
})
|
})
|
||||||
@ -100,6 +109,7 @@ namespace Kyoo
|
|||||||
.UseKestrel(options => { options.AddServerHeader = false; })
|
.UseKestrel(options => { options.AddServerHeader = false; })
|
||||||
.UseIIS()
|
.UseIIS()
|
||||||
.UseIISIntegration()
|
.UseIISIntegration()
|
||||||
|
.UseUrls(configuration.GetValue<string>("basics:url"))
|
||||||
.UseStartup<Startup>();
|
.UseStartup<Startup>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,17 @@ using System.IO;
|
|||||||
using Kyoo.Authentication;
|
using Kyoo.Authentication;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Postgresql;
|
using Kyoo.Postgresql;
|
||||||
using Kyoo.Tasks;
|
using Kyoo.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.SpaServices.AngularCli;
|
using Microsoft.AspNetCore.SpaServices.AngularCli;
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.FileProviders;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo
|
namespace Kyoo
|
||||||
{
|
{
|
||||||
@ -22,10 +22,6 @@ namespace Kyoo
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The configuration context
|
|
||||||
/// </summary>
|
|
||||||
private readonly IConfiguration _configuration;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A plugin manager used to load plugins and allow them to configure services / asp net.
|
/// A plugin manager used to load plugins and allow them to configure services / asp net.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -44,11 +40,12 @@ namespace Kyoo
|
|||||||
/// <param name="loggerFactory">A logger factory used to create a logger for the plugin manager.</param>
|
/// <param name="loggerFactory">A logger factory used to create a logger for the plugin manager.</param>
|
||||||
public Startup(IServiceProvider hostProvider, IConfiguration configuration, ILoggerFactory loggerFactory, IWebHostEnvironment host)
|
public Startup(IServiceProvider hostProvider, IConfiguration configuration, ILoggerFactory loggerFactory, IWebHostEnvironment host)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
IOptionsMonitor<BasicOptions> options = hostProvider.GetService<IOptionsMonitor<BasicOptions>>();
|
||||||
_plugins = new PluginManager(hostProvider, _configuration, loggerFactory.CreateLogger<PluginManager>());
|
_plugins = new PluginManager(hostProvider, options, loggerFactory.CreateLogger<PluginManager>());
|
||||||
|
|
||||||
// TODO remove postgres from here and load it like a normal plugin.
|
// TODO remove postgres from here and load it like a normal plugin.
|
||||||
_plugins.LoadPlugins(new IPlugin[] {new CoreModule(),
|
_plugins.LoadPlugins(new IPlugin[] {
|
||||||
|
new CoreModule(configuration),
|
||||||
new PostgresModule(configuration, host),
|
new PostgresModule(configuration, host),
|
||||||
new AuthenticationModule(configuration, loggerFactory, host)
|
new AuthenticationModule(configuration, loggerFactory, host)
|
||||||
});
|
});
|
||||||
@ -60,8 +57,6 @@ namespace Kyoo
|
|||||||
/// <param name="services">The service collection to fill.</param>
|
/// <param name="services">The service collection to fill.</param>
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
string publicUrl = _configuration.GetValue<string>("publicUrl");
|
|
||||||
|
|
||||||
services.AddMvc().AddControllersAsServices();
|
services.AddMvc().AddControllersAsServices();
|
||||||
|
|
||||||
services.AddSpaStaticFiles(configuration =>
|
services.AddSpaStaticFiles(configuration =>
|
||||||
@ -73,12 +68,6 @@ namespace Kyoo
|
|||||||
x.EnableForHttps = true;
|
x.EnableForHttps = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddControllers()
|
|
||||||
.AddNewtonsoftJson(x =>
|
|
||||||
{
|
|
||||||
x.SerializerSettings.ContractResolver = new JsonPropertyIgnorer(publicUrl);
|
|
||||||
x.SerializerSettings.Converters.Add(new PeopleRoleConverter());
|
|
||||||
});
|
|
||||||
services.AddHttpClient();
|
services.AddHttpClient();
|
||||||
|
|
||||||
services.AddTransient(typeof(Lazy<>), typeof(LazyDi<>));
|
services.AddTransient(typeof(Lazy<>), typeof(LazyDi<>));
|
||||||
@ -99,22 +88,14 @@ namespace Kyoo
|
|||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
app.UseExceptionHandler("/Error");
|
app.UseExceptionHandler("/error");
|
||||||
app.UseHsts();
|
app.UseHsts();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileExtensionContentTypeProvider contentTypeProvider = new();
|
|
||||||
contentTypeProvider.Mappings[".data"] = "application/octet-stream";
|
|
||||||
app.UseStaticFiles(new StaticFileOptions
|
|
||||||
{
|
|
||||||
ContentTypeProvider = contentTypeProvider,
|
|
||||||
FileProvider = new PhysicalFileProvider(Path.Join(AppDomain.CurrentDomain.BaseDirectory, "wwwroot"))
|
|
||||||
});
|
|
||||||
if (!env.IsDevelopment())
|
if (!env.IsDevelopment())
|
||||||
app.UseSpaStaticFiles();
|
app.UseSpaStaticFiles();
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
app.Use((ctx, next) =>
|
app.Use((ctx, next) =>
|
||||||
{
|
{
|
||||||
ctx.Response.Headers.Remove("X-Powered-By");
|
ctx.Response.Headers.Remove("X-Powered-By");
|
||||||
@ -131,12 +112,6 @@ namespace Kyoo
|
|||||||
|
|
||||||
_plugins.ConfigureAspnet(app);
|
_plugins.ConfigureAspnet(app);
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
|
||||||
{
|
|
||||||
endpoints.MapControllers();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
app.UseSpa(spa =>
|
app.UseSpa(spa =>
|
||||||
{
|
{
|
||||||
spa.Options.SourcePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Kyoo.WebApp");
|
spa.Options.SourcePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Kyoo.WebApp");
|
||||||
|
@ -6,8 +6,9 @@ using Kyoo.Models;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.CommonApi;
|
using Kyoo.CommonApi;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -19,8 +20,8 @@ namespace Kyoo.Api
|
|||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
public CollectionApi(ILibraryManager libraryManager, IConfiguration configuration)
|
public CollectionApi(ILibraryManager libraryManager, IOptions<BasicOptions> options)
|
||||||
: base(libraryManager.CollectionRepository, configuration)
|
: base(libraryManager.CollectionRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
}
|
}
|
||||||
|
80
Kyoo/Views/ConfigurationApi.cs
Normal file
80
Kyoo/Views/ConfigurationApi.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kyoo.Controllers;
|
||||||
|
using Kyoo.Models.Exceptions;
|
||||||
|
using Kyoo.Models.Permissions;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Kyoo.Api
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An API to retrieve or edit configuration settings
|
||||||
|
/// </summary>
|
||||||
|
[Route("api/config")]
|
||||||
|
[Route("api/configuration")]
|
||||||
|
[ApiController]
|
||||||
|
public class ConfigurationApi : Controller
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration manager used to retrieve and edit configuration values (while being type safe).
|
||||||
|
/// </summary>
|
||||||
|
private readonly IConfigurationManager _manager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="ConfigurationApi"/> using the given configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="manager">The configuration manager used to retrieve and edit configuration values</param>
|
||||||
|
public ConfigurationApi(IConfigurationManager manager)
|
||||||
|
{
|
||||||
|
_manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a permission from it's slug.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="slug">The permission to retrieve. You can use ':' or "__" to get a child value.</param>
|
||||||
|
/// <returns>The associate value or list of values.</returns>
|
||||||
|
/// <response code="200">Return the configuration value or the list of configurations</response>
|
||||||
|
/// <response code="404">No configuration exists for the given slug</response>
|
||||||
|
[HttpGet("{slug}")]
|
||||||
|
[Permission(nameof(ConfigurationApi), Kind.Read, Group.Admin)]
|
||||||
|
public ActionResult<object> GetConfiguration(string slug)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _manager.GetValue(slug);
|
||||||
|
}
|
||||||
|
catch (ItemNotFoundException)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Edit a permission from it's slug.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="slug">The permission to edit. You can use ':' or "__" to get a child value.</param>
|
||||||
|
/// <param name="newValue">The new value of the configuration</param>
|
||||||
|
/// <returns>The edited value.</returns>
|
||||||
|
/// <response code="200">Return the edited value</response>
|
||||||
|
/// <response code="404">No configuration exists for the given slug</response>
|
||||||
|
[HttpPut("{slug}")]
|
||||||
|
[Permission(nameof(ConfigurationApi), Kind.Write, Group.Admin)]
|
||||||
|
public async Task<ActionResult<object>> EditConfiguration(string slug, [FromBody] object newValue)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _manager.EditValue(slug, newValue);
|
||||||
|
return newValue;
|
||||||
|
}
|
||||||
|
catch (ItemNotFoundException)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,8 +7,9 @@ using System.Threading.Tasks;
|
|||||||
using Kyoo.CommonApi;
|
using Kyoo.CommonApi;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -23,10 +24,10 @@ namespace Kyoo.Api
|
|||||||
private readonly IFileManager _files;
|
private readonly IFileManager _files;
|
||||||
|
|
||||||
public EpisodeApi(ILibraryManager libraryManager,
|
public EpisodeApi(ILibraryManager libraryManager,
|
||||||
IConfiguration configuration,
|
IOptions<BasicOptions> options,
|
||||||
IFileManager files,
|
IFileManager files,
|
||||||
IThumbnailsManager thumbnails)
|
IThumbnailsManager thumbnails)
|
||||||
: base(libraryManager.EpisodeRepository, configuration)
|
: base(libraryManager.EpisodeRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_files = files;
|
_files = files;
|
||||||
|
@ -5,9 +5,10 @@ using System.Threading.Tasks;
|
|||||||
using Kyoo.CommonApi;
|
using Kyoo.CommonApi;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -19,8 +20,8 @@ namespace Kyoo.Api
|
|||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
public GenreApi(ILibraryManager libraryManager, IConfiguration config)
|
public GenreApi(ILibraryManager libraryManager, IOptions<BasicOptions> options)
|
||||||
: base(libraryManager.GenreRepository, config)
|
: base(libraryManager.GenreRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,23 @@ using Kyoo.Models;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.CommonApi;
|
using Kyoo.CommonApi;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
[Route("api/library")]
|
[Route("api/library")]
|
||||||
[Route("api/libraries")]
|
[Route("api/libraries")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[PartialPermission(nameof(LibraryAPI))]
|
[PartialPermission(nameof(LibraryApi))]
|
||||||
public class LibraryAPI : CrudApi<Library>
|
public class LibraryApi : CrudApi<Library>
|
||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ITaskManager _taskManager;
|
private readonly ITaskManager _taskManager;
|
||||||
|
|
||||||
public LibraryAPI(ILibraryManager libraryManager, ITaskManager taskManager, IConfiguration configuration)
|
public LibraryApi(ILibraryManager libraryManager, ITaskManager taskManager, IOptions<BasicOptions> options)
|
||||||
: base(libraryManager.LibraryRepository, configuration)
|
: base(libraryManager.LibraryRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_taskManager = taskManager;
|
_taskManager = taskManager;
|
||||||
|
@ -6,9 +6,10 @@ using Kyoo.CommonApi;
|
|||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -22,10 +23,10 @@ namespace Kyoo.Api
|
|||||||
private readonly string _baseURL;
|
private readonly string _baseURL;
|
||||||
|
|
||||||
|
|
||||||
public LibraryItemApi(ILibraryItemRepository libraryItems, IConfiguration configuration)
|
public LibraryItemApi(ILibraryItemRepository libraryItems, IOptions<BasicOptions> options)
|
||||||
{
|
{
|
||||||
_libraryItems = libraryItems;
|
_libraryItems = libraryItems;
|
||||||
_baseURL = configuration.GetValue<string>("publicUrl").TrimEnd('/');
|
_baseURL = options.Value.PublicUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
@ -5,9 +5,10 @@ using Kyoo.CommonApi;
|
|||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -21,10 +22,10 @@ namespace Kyoo.Api
|
|||||||
private readonly IThumbnailsManager _thumbs;
|
private readonly IThumbnailsManager _thumbs;
|
||||||
|
|
||||||
public PeopleApi(ILibraryManager libraryManager,
|
public PeopleApi(ILibraryManager libraryManager,
|
||||||
IConfiguration configuration,
|
IOptions<BasicOptions> options,
|
||||||
IFileManager files,
|
IFileManager files,
|
||||||
IThumbnailsManager thumbs)
|
IThumbnailsManager thumbs)
|
||||||
: base(libraryManager.PeopleRepository, configuration)
|
: base(libraryManager.PeopleRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_files = files;
|
_files = files;
|
||||||
|
@ -2,9 +2,10 @@ using System.Threading.Tasks;
|
|||||||
using Kyoo.CommonApi;
|
using Kyoo.CommonApi;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -19,10 +20,10 @@ namespace Kyoo.Api
|
|||||||
private readonly IFileManager _files;
|
private readonly IFileManager _files;
|
||||||
|
|
||||||
public ProviderApi(ILibraryManager libraryManager,
|
public ProviderApi(ILibraryManager libraryManager,
|
||||||
IConfiguration config,
|
IOptions<BasicOptions> options,
|
||||||
IFileManager files,
|
IFileManager files,
|
||||||
IThumbnailsManager thumbnails)
|
IThumbnailsManager thumbnails)
|
||||||
: base(libraryManager.ProviderRepository, config)
|
: base(libraryManager.ProviderRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_files = files;
|
_files = files;
|
||||||
|
@ -6,8 +6,9 @@ using Kyoo.Controllers;
|
|||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -22,10 +23,10 @@ namespace Kyoo.Api
|
|||||||
private readonly IFileManager _files;
|
private readonly IFileManager _files;
|
||||||
|
|
||||||
public SeasonApi(ILibraryManager libraryManager,
|
public SeasonApi(ILibraryManager libraryManager,
|
||||||
IConfiguration configuration,
|
IOptions<BasicOptions> options,
|
||||||
IThumbnailsManager thumbs,
|
IThumbnailsManager thumbs,
|
||||||
IFileManager files)
|
IFileManager files)
|
||||||
: base(libraryManager.SeasonRepository, configuration)
|
: base(libraryManager.SeasonRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_thumbs = thumbs;
|
_thumbs = thumbs;
|
||||||
|
@ -8,8 +8,9 @@ using System.Threading.Tasks;
|
|||||||
using Kyoo.CommonApi;
|
using Kyoo.CommonApi;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -26,8 +27,8 @@ namespace Kyoo.Api
|
|||||||
public ShowApi(ILibraryManager libraryManager,
|
public ShowApi(ILibraryManager libraryManager,
|
||||||
IFileManager files,
|
IFileManager files,
|
||||||
IThumbnailsManager thumbs,
|
IThumbnailsManager thumbs,
|
||||||
IConfiguration configuration)
|
IOptions<BasicOptions> options)
|
||||||
: base(libraryManager.ShowRepository, configuration)
|
: base(libraryManager.ShowRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_files = files;
|
_files = files;
|
||||||
|
@ -5,9 +5,10 @@ using System.Threading.Tasks;
|
|||||||
using Kyoo.CommonApi;
|
using Kyoo.CommonApi;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -15,12 +16,12 @@ namespace Kyoo.Api
|
|||||||
[Route("api/studios")]
|
[Route("api/studios")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[PartialPermission(nameof(ShowApi))]
|
[PartialPermission(nameof(ShowApi))]
|
||||||
public class StudioAPI : CrudApi<Studio>
|
public class StudioApi : CrudApi<Studio>
|
||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
public StudioAPI(ILibraryManager libraryManager, IConfiguration config)
|
public StudioApi(ILibraryManager libraryManager, IOptions<BasicOptions> options)
|
||||||
: base(libraryManager.StudioRepository, config)
|
: base(libraryManager.StudioRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,10 @@ using Kyoo.CommonApi;
|
|||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -18,8 +19,8 @@ namespace Kyoo.Api
|
|||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
public TrackApi(ILibraryManager libraryManager, IConfiguration configuration)
|
public TrackApi(ILibraryManager libraryManager, IOptions<BasicOptions> options)
|
||||||
: base(libraryManager.TrackRepository, configuration)
|
: base(libraryManager.TrackRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Kyoo.Models.Permissions;
|
using Kyoo.Models.Permissions;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -16,20 +17,18 @@ namespace Kyoo.Api
|
|||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ITranscoder _transcoder;
|
private readonly ITranscoder _transcoder;
|
||||||
|
private readonly IOptions<BasicOptions> _options;
|
||||||
private readonly IFileManager _files;
|
private readonly IFileManager _files;
|
||||||
private readonly string _transmuxPath;
|
|
||||||
private readonly string _transcodePath;
|
|
||||||
|
|
||||||
public VideoApi(ILibraryManager libraryManager,
|
public VideoApi(ILibraryManager libraryManager,
|
||||||
ITranscoder transcoder,
|
ITranscoder transcoder,
|
||||||
IConfiguration config,
|
IOptions<BasicOptions> options,
|
||||||
IFileManager files)
|
IFileManager files)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_transcoder = transcoder;
|
_transcoder = transcoder;
|
||||||
|
_options = options;
|
||||||
_files = files;
|
_files = files;
|
||||||
_transmuxPath = config.GetValue<string>("transmuxTempPath");
|
|
||||||
_transcodePath = config.GetValue<string>("transcodeTempPath");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnActionExecuted(ActionExecutedContext ctx)
|
public override void OnActionExecuted(ActionExecutedContext ctx)
|
||||||
@ -101,7 +100,7 @@ namespace Kyoo.Api
|
|||||||
[Permission("video", Kind.Read)]
|
[Permission("video", Kind.Read)]
|
||||||
public IActionResult GetTransmuxedChunk(string episodeLink, string chunk)
|
public IActionResult GetTransmuxedChunk(string episodeLink, string chunk)
|
||||||
{
|
{
|
||||||
string path = Path.GetFullPath(Path.Combine(_transmuxPath, episodeLink));
|
string path = Path.GetFullPath(Path.Combine(_options.Value.TransmuxPath, episodeLink));
|
||||||
path = Path.Combine(path, "segments", chunk);
|
path = Path.Combine(path, "segments", chunk);
|
||||||
return PhysicalFile(path, "video/MP2T");
|
return PhysicalFile(path, "video/MP2T");
|
||||||
}
|
}
|
||||||
@ -110,7 +109,7 @@ namespace Kyoo.Api
|
|||||||
[Permission("video", Kind.Read)]
|
[Permission("video", Kind.Read)]
|
||||||
public IActionResult GetTranscodedChunk(string episodeLink, string chunk)
|
public IActionResult GetTranscodedChunk(string episodeLink, string chunk)
|
||||||
{
|
{
|
||||||
string path = Path.GetFullPath(Path.Combine(_transcodePath, episodeLink));
|
string path = Path.GetFullPath(Path.Combine(_options.Value.TranscodePath, episodeLink));
|
||||||
path = Path.Combine(path, "segments", chunk);
|
path = Path.Combine(path, "segments", chunk);
|
||||||
return PhysicalFile(path, "video/MP2T");
|
return PhysicalFile(path, "video/MP2T");
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
{
|
{
|
||||||
"server.urls": "http://*:5000",
|
"basics": {
|
||||||
"publicUrl": "http://localhost:5000/",
|
"url": "http://*:5000",
|
||||||
|
"publicUrl": "http://localhost:5000/",
|
||||||
|
"pluginsPath": "plugins/",
|
||||||
|
"peoplePath": "people/",
|
||||||
|
"providerPath": "providers/",
|
||||||
|
"transmuxPath": "cached/transmux",
|
||||||
|
"transcodePath": "cached/transcode"
|
||||||
|
},
|
||||||
|
|
||||||
"database": {
|
"database": {
|
||||||
"postgres": {
|
"postgres": {
|
||||||
@ -25,6 +32,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"tasks": {
|
||||||
|
"parallels": "1",
|
||||||
|
"scheduled": {
|
||||||
|
"scan": "24:00:00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"media": {
|
||||||
|
"regex": "(?:\\/(?<Collection>.*?))?\\/(?<Show>.*?)(?: \\(\\d+\\))?\\/\\k<Show>(?: \\(\\d+\\))?(?:(?: S(?<Season>\\d+)E(?<Episode>\\d+))| (?<Absolute>\\d+))?.*$",
|
||||||
|
"subtitleRegex": "^(?<Episode>.*)\\.(?<Language>\\w{1,3})\\.(?<Default>default\\.)?(?<Forced>forced\\.)?.*$"
|
||||||
|
},
|
||||||
|
|
||||||
"authentication": {
|
"authentication": {
|
||||||
"certificate": {
|
"certificate": {
|
||||||
"file": "certificate.pfx",
|
"file": "certificate.pfx",
|
||||||
@ -32,25 +51,10 @@
|
|||||||
"password": "passphrase"
|
"password": "passphrase"
|
||||||
},
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"default": ["overall.read", "overall.write", "overall.create", "overall.delete"],
|
"default": ["overall.read", "overall.write", "overall.create", "overall.delete", "admin.read", "admin.write"],
|
||||||
"newUser": ["overall.read", "overall.write", "overall.create", "overall.delete"]
|
"newUser": ["overall.read", "overall.write", "overall.create", "overall.delete", "admin.read", "admin.write"]
|
||||||
},
|
},
|
||||||
"profilePicturePath": "users/",
|
"profilePicturePath": "users/",
|
||||||
"clients": []
|
"clients": []
|
||||||
},
|
}
|
||||||
|
|
||||||
|
|
||||||
"parallelTasks": "1",
|
|
||||||
|
|
||||||
"scheduledTasks": {
|
|
||||||
"scan": "24:00:00"
|
|
||||||
},
|
|
||||||
|
|
||||||
"transmuxTempPath": "cached/kyoo/transmux",
|
|
||||||
"transcodeTempPath": "cached/kyoo/transcode",
|
|
||||||
"peoplePath": "people",
|
|
||||||
"providerPath": "providers",
|
|
||||||
"plugins": "plugins/",
|
|
||||||
"regex": "(?:\\/(?<Collection>.*?))?\\/(?<Show>.*?)(?: \\(\\d+\\))?\\/\\k<Show>(?: \\(\\d+\\))?(?:(?: S(?<Season>\\d+)E(?<Episode>\\d+))| (?<Absolute>\\d+))?.*$",
|
|
||||||
"subtitleRegex": "^(?<Episode>.*)\\.(?<Language>\\w{1,3})\\.(?<Default>default\\.)?(?<Forced>forced\\.)?.*$"
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user