mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Merge pull request #39 from AnonymusRaccoon/coding-style
Enforcing coding style
This commit is contained in:
commit
66d6b27e38
91
.editorconfig
Normal file
91
.editorconfig
Normal file
@ -0,0 +1,91 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = tab
|
||||
smart_tab = true
|
||||
|
||||
[{*.yaml,*.yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.cs]
|
||||
# Sort using and Import directives with System.* appearing first
|
||||
dotnet_sort_system_directives_first = true
|
||||
csharp_using_directive_placement = outside_namespace:warning
|
||||
# Avoid "this." if not necessary
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
dotnet_style_qualification_for_property = false:suggestion
|
||||
dotnet_style_qualification_for_method = false:suggestion
|
||||
dotnet_style_qualification_for_event = false:suggestion
|
||||
# Use language keywords instead of framework type names for type references
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
# Suggest more modern language features when available
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
dotnet_style_prefer_auto_properties = true
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true
|
||||
dotnet_style_prefer_conditional_expression_over_return = true
|
||||
# Disable strange throw.
|
||||
csharp_style_throw_expression = false:suggestion
|
||||
# Forbid "var" everywhere
|
||||
csharp_style_var_for_built_in_types = false:warning
|
||||
csharp_style_var_when_type_is_apparent = false:warning
|
||||
csharp_style_var_elsewhere = false:warning
|
||||
# Prefer method-like constructs to have a block body
|
||||
csharp_style_expression_bodied_methods = false:none
|
||||
csharp_style_expression_bodied_constructors = false:none
|
||||
csharp_style_expression_bodied_operators = false:none
|
||||
# Prefer property-like constructs to have an expression-body
|
||||
csharp_style_expression_bodied_properties = true:none
|
||||
csharp_style_expression_bodied_indexers = true:none
|
||||
csharp_style_expression_bodied_accessors = true:none
|
||||
# Newline settings
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = false
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
# Indentation settings
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
# Modifiers
|
||||
dotnet_style_readonly_field = true:suggestion
|
||||
csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
|
||||
# Naming style
|
||||
dotnet_naming_symbols.privates.applicable_kinds = property,method,event,delegate
|
||||
dotnet_naming_symbols.privates.applicable_accessibilities = private
|
||||
dotnet_naming_style.underscore_pascal.capitalization = pascal_case
|
||||
dotnet_naming_style.underscore_pascal.required_prefix = _
|
||||
dotnet_naming_rule.privates_with_underscore.symbols = privates
|
||||
dotnet_naming_rule.privates_with_underscore.style = underscore_pascal
|
||||
dotnet_naming_rule.privates_with_underscore.severity = warning
|
||||
dotnet_diagnostic.IDE1006.severity = warning
|
||||
# ReSharper properties
|
||||
resharper_align_multiline_binary_expressions_chain = false
|
||||
resharper_csharp_empty_block_style = together_same_line
|
||||
resharper_indent_nested_foreach_stmt = true
|
||||
resharper_indent_nested_for_stmt = true
|
||||
resharper_indent_nested_while_stmt = true
|
||||
resharper_keep_existing_embedded_arrangement = false
|
||||
resharper_place_accessorholder_attribute_on_same_line = true
|
||||
resharper_place_simple_embedded_statement_on_same_line = false
|
||||
resharper_wrap_before_arrow_with_expressions = true
|
||||
resharper_xmldoc_attribute_indent = align_by_first_attribute
|
||||
resharper_xmldoc_indent_child_elements = RemoveIndent
|
||||
resharper_xmldoc_indent_text = RemoveIndent
|
||||
|
14
.github/workflows/build.yml
vendored
14
.github/workflows/build.yml
vendored
@ -35,7 +35,7 @@ jobs:
|
||||
elif [[ "${{runner.os}}" == "macOS" ]]; then
|
||||
brew install ffmpeg
|
||||
else
|
||||
sudo apt-get update
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libavutil-dev libavcodec-dev libavformat-dev
|
||||
fi
|
||||
- name: Enabling windows compilations tools
|
||||
@ -45,10 +45,10 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
echo "PROJECT=$([ "${{runner.os}}" == "Windows" ] \
|
||||
&& echo " -p:IncludeConsole=true Kyoo.Host.WindowsTrait" \
|
||||
|| echo Kyoo.Host.Console)" >> $GITHUB_ENV
|
||||
&& echo " -p:IncludeConsole=true -p:CheckCodingStyle=false src/Kyoo.Host.WindowsTrait" \
|
||||
|| echo " -p:CheckCodingStyle=false src/Kyoo.Host.Console")" >> $GITHUB_ENV
|
||||
- name: Build the app
|
||||
env:
|
||||
env:
|
||||
INCLUDE: ${{env.INCLUDE}};C:\Program Files\FFmpeg\include
|
||||
LIB: ${{env.LIB}};C:\Program Files\FFmpeg\lib
|
||||
LIBPATH: ${{env.LIBPATH}};C:\Program Files\FFmpeg\lib
|
||||
@ -126,7 +126,7 @@ jobs:
|
||||
sudo install -Dm 644 deployment/kyoo.service -t pkg/usr/lib/systemd/system/
|
||||
sudo install -Dm 644 deployment/kyoo.sysusers pkg/usr/lib/sysusers.d/kyoo.conf
|
||||
sudo install -Dm 644 deployment/kyoo.tmpfiles pkg/usr/lib/tmpfiles.d/kyoo.conf
|
||||
- name: Build debian package
|
||||
- name: Build debian package
|
||||
uses: jiro4989/build-deb-action@v2
|
||||
with:
|
||||
package: kyoo
|
||||
@ -163,8 +163,8 @@ jobs:
|
||||
with:
|
||||
name: kyoo_arch
|
||||
path: ${{steps.makepkg.outputs.pkgfile0}}
|
||||
|
||||
|
||||
# new-version:
|
||||
# if: startsWith(github.ref, 'refs/tags/v')
|
||||
# runs-on: ubuntu-latest
|
||||
# runs-on: ubuntu-latest
|
||||
|
||||
|
15
.github/workflows/coding-style.yml
vendored
Normal file
15
.github/workflows/coding-style.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
name: CodingStyle
|
||||
on: [pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Coding style check"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.x
|
||||
- name: Build the app
|
||||
run: dotnet build -p:CheckCodingStyle=true -p:TreatWarningsAsErrors=true '-p:SkipTranscoder=true;SkipWebApp=true'
|
4
.github/workflows/tests.yml
vendored
4
.github/workflows/tests.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
- name: Build
|
||||
run: |
|
||||
dotnet build --no-restore '-p:SkipWebApp=true;SkipTranscoder=true' -p:CopyLocalLockFileAssemblies=true
|
||||
cp ./Kyoo.Abstractions/bin/Debug/net5.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll ./tests/Kyoo.Tests/bin/Debug/net5.0/
|
||||
cp ./src/Kyoo.Abstractions/bin/Debug/net5.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll ./tests/Kyoo.Tests/bin/Debug/net5.0/
|
||||
- name: Test
|
||||
run: dotnet test --no-build '-p:CollectCoverage=true;CoverletOutputFormat=opencover'
|
||||
env:
|
||||
@ -33,7 +33,7 @@ jobs:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
- name: Sanitize coverage output
|
||||
if: ${{ always() }}
|
||||
run: sed -i "s'$(pwd)'.'" tests/Kyoo.Tests/coverage.opencover.xml
|
||||
run: sed -i "s'$(pwd)'.'" tests/Kyoo.Tests/coverage.opencover.xml
|
||||
- name: Upload coverage report
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,8 +1,8 @@
|
||||
[submodule "transcoder"]
|
||||
path = Kyoo.Transcoder
|
||||
path = src/Kyoo.Transcoder
|
||||
url = ../Kyoo.Transcoder.git
|
||||
branch = master
|
||||
[submodule "WebApp"]
|
||||
path = Kyoo.WebApp/Front
|
||||
path = src/Kyoo.WebApp/Front
|
||||
url = ../Kyoo.WebApp.git
|
||||
branch = master
|
||||
|
4
AUTHORS.md
Normal file
4
AUTHORS.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Authors
|
||||
Alphabetical order by first name.
|
||||
|
||||
* Zoe Roux ([@AnonymusRaccoon](http://github.com/AnonymusRaccoon))
|
@ -1,12 +1,12 @@
|
||||
FROM gcc:latest as transcoder
|
||||
RUN apt-get update && apt-get install -y cmake make libavutil-dev libavcodec-dev libavformat-dev
|
||||
WORKDIR /transcoder
|
||||
COPY Kyoo.Transcoder .
|
||||
COPY src/Kyoo.Transcoder .
|
||||
RUN cmake . && make -j
|
||||
|
||||
FROM node:alpine as webapp
|
||||
WORKDIR /webapp
|
||||
COPY Kyoo.WebApp .
|
||||
COPY src/Kyoo.WebApp .
|
||||
WORKDIR /webapp/Front
|
||||
RUN npm install
|
||||
RUN npm run build -- --prod
|
||||
|
@ -1,31 +0,0 @@
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface that allow one to interact with the host and shutdown or restart the app.
|
||||
/// </summary>
|
||||
public interface IApplication
|
||||
{
|
||||
/// <summary>
|
||||
/// Shutdown the process and stop gracefully.
|
||||
/// </summary>
|
||||
void Shutdown();
|
||||
|
||||
/// <summary>
|
||||
/// Restart Kyoo from scratch, reload plugins, configurations and restart the web server.
|
||||
/// </summary>
|
||||
void Restart();
|
||||
|
||||
/// <summary>
|
||||
/// Get the data directory
|
||||
/// </summary>
|
||||
/// <returns>Retrieve the data directory where runtime data should be stored</returns>
|
||||
string GetDataDirectory();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the path of the json configuration file
|
||||
/// (relative to the data directory, see <see cref="GetDataDirectory"/>).
|
||||
/// </summary>
|
||||
/// <returns>The configuration file name.</returns>
|
||||
string GetConfigFile();
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using Kyoo.Abstractions.Models;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
public interface ITranscoder
|
||||
{
|
||||
Task<Track[]> ExtractInfos(Episode episode, bool reextract);
|
||||
Task<string> Transmux(Episode episode);
|
||||
Task<string> Transcode(Episode episode);
|
||||
}
|
||||
}
|
@ -1,221 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of constant priorities used for <see cref="IStartupAction"/>'s <see cref="IStartupAction.Priority"/>.
|
||||
/// It also contains helper methods for creating new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
public static class SA
|
||||
{
|
||||
public const int Before = 5000;
|
||||
public const int Routing = 4000;
|
||||
public const int StaticFiles = 3000;
|
||||
public const int Authentication = 2000;
|
||||
public const int Authorization = 1000;
|
||||
public const int Endpoint = 0;
|
||||
public const int After = -1000;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to run</param>
|
||||
/// <param name="priority">The priority of the new action</param>
|
||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||
public static StartupAction New(Action action, int priority)
|
||||
=> new(action, priority);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to run</param>
|
||||
/// <param name="priority">The priority of the new action</param>
|
||||
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||
public static StartupAction<T> New<T>(Action<T> action, int priority)
|
||||
=> new(action, priority);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to run</param>
|
||||
/// <param name="priority">The priority of the new action</param>
|
||||
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
||||
/// <typeparam name="T2">A second dependency that this action will use.</typeparam>
|
||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||
public static StartupAction<T, T2> New<T, T2>(Action<T, T2> action, int priority)
|
||||
=> new(action, priority);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to run</param>
|
||||
/// <param name="priority">The priority of the new action</param>
|
||||
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
||||
/// <typeparam name="T2">A second dependency that this action will use.</typeparam>
|
||||
/// <typeparam name="T3">A third dependency that this action will use.</typeparam>
|
||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||
public static StartupAction<T, T2, T3> New<T, T2, T3>(Action<T, T2, T3> action, int priority)
|
||||
=> new(action, priority);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// An action executed on kyoo's startup to initialize the asp-net container.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the base interface, see <see cref="StartupAction"/> for a simpler use of this.
|
||||
/// </remarks>
|
||||
public interface IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The priority of this action. The actions will be executed on descending priority order.
|
||||
/// If two actions have the same priority, their order is undefined.
|
||||
/// </summary>
|
||||
int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Run this action to configure the container, a service provider containing all services can be used.
|
||||
/// </summary>
|
||||
/// <param name="provider">The service provider containing all services can be used.</param>
|
||||
void Run(IServiceProvider provider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IStartupAction"/> with no dependencies.
|
||||
/// </summary>
|
||||
public class StartupAction : IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The action to execute at startup.
|
||||
/// </summary>
|
||||
private readonly Action _action;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on startup.</param>
|
||||
/// <param name="priority">The priority of this action (see <see cref="Priority"/>).</param>
|
||||
public StartupAction(Action action, int priority)
|
||||
{
|
||||
_action = action;
|
||||
Priority = priority;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IServiceProvider provider)
|
||||
{
|
||||
_action.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IStartupAction"/> with one dependencies.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dependency to use.</typeparam>
|
||||
public class StartupAction<T> : IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The action to execute at startup.
|
||||
/// </summary>
|
||||
private readonly Action<T> _action;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on startup.</param>
|
||||
/// <param name="priority">The priority of this action (see <see cref="Priority"/>).</param>
|
||||
public StartupAction(Action<T> action, int priority)
|
||||
{
|
||||
_action = action;
|
||||
Priority = priority;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IServiceProvider provider)
|
||||
{
|
||||
_action.Invoke(provider.GetRequiredService<T>());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IStartupAction"/> with two dependencies.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dependency to use.</typeparam>
|
||||
/// <typeparam name="T2">The second dependency to use.</typeparam>
|
||||
public class StartupAction<T, T2> : IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The action to execute at startup.
|
||||
/// </summary>
|
||||
private readonly Action<T, T2> _action;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction{T, T2}"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on startup.</param>
|
||||
/// <param name="priority">The priority of this action (see <see cref="Priority"/>).</param>
|
||||
public StartupAction(Action<T, T2> action, int priority)
|
||||
{
|
||||
_action = action;
|
||||
Priority = priority;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IServiceProvider provider)
|
||||
{
|
||||
_action.Invoke(
|
||||
provider.GetRequiredService<T>(),
|
||||
provider.GetRequiredService<T2>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IStartupAction"/> with three dependencies.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dependency to use.</typeparam>
|
||||
/// <typeparam name="T2">The second dependency to use.</typeparam>
|
||||
/// <typeparam name="T3">The third dependency to use.</typeparam>
|
||||
public class StartupAction<T, T2, T3> : IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The action to execute at startup.
|
||||
/// </summary>
|
||||
private readonly Action<T, T2, T3> _action;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction{T, T2, T3}"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on startup.</param>
|
||||
/// <param name="priority">The priority of this action (see <see cref="Priority"/>).</param>
|
||||
public StartupAction(Action<T, T2, T3> action, int priority)
|
||||
{
|
||||
_action = action;
|
||||
Priority = priority;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IServiceProvider provider)
|
||||
{
|
||||
_action.Invoke(
|
||||
provider.GetRequiredService<T>(),
|
||||
provider.GetRequiredService<T2>(),
|
||||
provider.GetRequiredService<T3>()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A class wrapping a value that will be set after the completion of the task it is related to.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class replace the use of an out parameter on a task since tasks and out can't be combined.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the value</typeparam>
|
||||
public class AsyncRef<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The value that will be set before the completion of the task.
|
||||
/// </summary>
|
||||
public T Value { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// An attribute to inform that the property is computed automatically and can't be assigned manually.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class ComputedAttribute : NotMergeableAttribute { }
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Specify that a property can't be merged.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class NotMergeableAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// An interface with a method called when this object is merged.
|
||||
/// </summary>
|
||||
public interface IOnMerge
|
||||
{
|
||||
/// <summary>
|
||||
/// This function is called after the object has been merged.
|
||||
/// </summary>
|
||||
/// <param name="merged">The object that has been merged with this.</param>
|
||||
void OnMerge(object merged);
|
||||
}
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Permissions
|
||||
{
|
||||
/// <summary>
|
||||
/// The kind of permission needed.
|
||||
/// </summary>
|
||||
public enum Kind
|
||||
{
|
||||
Read,
|
||||
Write,
|
||||
Create,
|
||||
Delete
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The group of the permission.
|
||||
/// </summary>
|
||||
public enum Group
|
||||
{
|
||||
Overall,
|
||||
Admin
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify permissions needed for the API.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
||||
public class PermissionAttribute : Attribute, IFilterFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The needed permission as string.
|
||||
/// </summary>
|
||||
public string Type { get; }
|
||||
/// <summary>
|
||||
/// The needed permission kind.
|
||||
/// </summary>
|
||||
public Kind Kind { get; }
|
||||
/// <summary>
|
||||
/// The group of this permission
|
||||
/// </summary>
|
||||
public Group Group { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ask a permission to run an action.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// The type of the action
|
||||
/// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
|
||||
/// </param>
|
||||
/// <param name="permission">The kind of permission needed</param>
|
||||
/// <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))
|
||||
type = type[..^3];
|
||||
Type = type.ToLower();
|
||||
Kind = permission;
|
||||
Group = group;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||
{
|
||||
return serviceProvider.GetRequiredService<IPermissionValidator>().Create(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReusable => true;
|
||||
|
||||
/// <summary>
|
||||
/// Return this permission attribute as a string
|
||||
/// </summary>
|
||||
/// <returns>The string representation.</returns>
|
||||
public string AsPermissionString()
|
||||
{
|
||||
return Type;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify one part of a permissions needed for the API (the kind or the type).
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
||||
public class PartialPermissionAttribute : Attribute, IFilterFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The needed permission type.
|
||||
/// </summary>
|
||||
public string Type { get; }
|
||||
/// <summary>
|
||||
/// The needed permission kind.
|
||||
/// </summary>
|
||||
public Kind Kind { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ask a permission to run an action.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// With this attribute, you can only specify a type or a kind.
|
||||
/// To have a valid permission attribute, you must specify the kind and the permission using two attributes.
|
||||
/// Those attributes can be dispatched at different places (one on the class, one on the method for example).
|
||||
/// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will
|
||||
/// lead to unspecified behaviors.
|
||||
/// </remarks>
|
||||
/// <param name="type">
|
||||
/// The type of the action
|
||||
/// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
|
||||
/// </param>
|
||||
public PartialPermissionAttribute(string type)
|
||||
{
|
||||
if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
|
||||
type = type[..^3];
|
||||
Type = type.ToLower();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ask a permission to run an action.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// With this attribute, you can only specify a type or a kind.
|
||||
/// To have a valid permission attribute, you must specify the kind and the permission using two attributes.
|
||||
/// Those attributes can be dispatched at different places (one on the class, one on the method for example).
|
||||
/// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will
|
||||
/// lead to unspecified behaviors.
|
||||
/// </remarks>
|
||||
/// <param name="permission">The kind of permission needed</param>
|
||||
public PartialPermissionAttribute(Kind permission)
|
||||
{
|
||||
Kind = permission;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||
{
|
||||
return serviceProvider.GetRequiredService<IPermissionValidator>().Create(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReusable => true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A service to validate permissions
|
||||
/// </summary>
|
||||
public interface IPermissionValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an IAuthorizationFilter that will be used to validate permissions.
|
||||
/// This can registered with any lifetime.
|
||||
/// </summary>
|
||||
/// <param name="attribute">The permission attribute to validate</param>
|
||||
/// <returns>An authorization filter used to validate the permission</returns>
|
||||
IFilterMetadata Create(PermissionAttribute attribute);
|
||||
|
||||
/// <summary>
|
||||
/// Create an IAuthorizationFilter that will be used to validate permissions.
|
||||
/// This can registered with any lifetime.
|
||||
/// </summary>
|
||||
/// <param name="attribute">
|
||||
/// A partial attribute to validate. See <see cref="PartialPermissionAttribute"/>.
|
||||
/// </param>
|
||||
/// <returns>An authorization filter used to validate the permission</returns>
|
||||
IFilterMetadata Create(PartialPermissionAttribute attribute);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Kyoo.Authentication.Models.DTO
|
||||
{
|
||||
/// <summary>
|
||||
/// A model only used on account update requests.
|
||||
/// </summary>
|
||||
public class AccountUpdateRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The new email address of the user
|
||||
/// </summary>
|
||||
[EmailAddress(ErrorMessage = "The email is invalid.")]
|
||||
public string Email { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The new username of the user.
|
||||
/// </summary>
|
||||
[MinLength(4, ErrorMessage = "The username must have at least 4 characters")]
|
||||
public string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The picture icon.
|
||||
/// </summary>
|
||||
public IFormFile Picture { get; set; }
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
namespace Kyoo.Authentication.Models.DTO
|
||||
{
|
||||
/// <summary>
|
||||
/// A model only used on login requests.
|
||||
/// </summary>
|
||||
public class LoginRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The user's username.
|
||||
/// </summary>
|
||||
public string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user's password.
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should the user stay logged in? If true a cookie will be put.
|
||||
/// </summary>
|
||||
public bool StayLoggedIn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The return url of the login flow.
|
||||
/// </summary>
|
||||
public string ReturnURL { get; set; }
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
namespace Kyoo.Authentication.Models.DTO
|
||||
{
|
||||
/// <summary>
|
||||
/// A model to represent an otac request
|
||||
/// </summary>
|
||||
public class OtacRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The One Time Access Code
|
||||
/// </summary>
|
||||
public string Otac { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should the user stay logged
|
||||
/// </summary>
|
||||
public bool StayLoggedIn { get; set; }
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
namespace Kyoo.Authentication.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The main authentication options.
|
||||
/// </summary>
|
||||
public class AuthenticationOption
|
||||
{
|
||||
/// <summary>
|
||||
/// The path to get this option from the root configuration.
|
||||
/// </summary>
|
||||
public const string Path = "authentication";
|
||||
|
||||
/// <summary>
|
||||
/// The options for certificates
|
||||
/// </summary>
|
||||
public CertificateOption Certificate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Options for permissions
|
||||
/// </summary>
|
||||
public PermissionOption Permissions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Root path of user's profile pictures.
|
||||
/// </summary>
|
||||
public string ProfilePicturePath { get; set; }
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
namespace Kyoo.Authentication.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A typed option model for the certificate
|
||||
/// </summary>
|
||||
public class CertificateOption
|
||||
{
|
||||
/// <summary>
|
||||
/// The path to get this option from the root configuration.
|
||||
/// </summary>
|
||||
public const string Path = "authentication:certificate";
|
||||
|
||||
/// <summary>
|
||||
/// The path of the certificate file.
|
||||
/// </summary>
|
||||
public string File { get; set; }
|
||||
/// <summary>
|
||||
/// The path of the old certificate file.
|
||||
/// </summary>
|
||||
public string OldFile { get; set; }
|
||||
/// <summary>
|
||||
/// The password of the certificates.
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
namespace Kyoo.Authentication.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Permission options.
|
||||
/// </summary>
|
||||
public class PermissionOption
|
||||
{
|
||||
/// <summary>
|
||||
/// The path to get this option from the root configuration.
|
||||
/// </summary>
|
||||
public const string Path = "authentication:permissions";
|
||||
|
||||
/// <summary>
|
||||
/// The default permissions that will be given to a non-connected user.
|
||||
/// </summary>
|
||||
public string[] Default { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Permissions applied to a new user.
|
||||
/// </summary>
|
||||
public string[] NewUser { get; set; }
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
using Kyoo.Abstractions.Models.Permissions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Kyoo.Core.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// A permission validator that always validate permissions. This effectively disable the permission system.
|
||||
/// </summary>
|
||||
public class PassthroughPermissionValidator : IPermissionValidator
|
||||
{
|
||||
// ReSharper disable once SuggestBaseTypeForParameter
|
||||
public PassthroughPermissionValidator(ILogger<PassthroughPermissionValidator> logger)
|
||||
{
|
||||
logger.LogWarning("No permission validator has been enabled, all users will have all permissions");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IFilterMetadata Create(PermissionAttribute attribute)
|
||||
{
|
||||
return new PassthroughValidator();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IFilterMetadata Create(PartialPermissionAttribute attribute)
|
||||
{
|
||||
return new PassthroughValidator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An useless filter that does nothing.
|
||||
/// </summary>
|
||||
private class PassthroughValidator : IFilterMetadata { }
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
namespace Kyoo.Core.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; }
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Kyoo.Core.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,156 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
using Kyoo.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Kyoo.Core.Api
|
||||
{
|
||||
public class JsonPropertyIgnorer : CamelCasePropertyNamesContractResolver
|
||||
{
|
||||
private int _depth = -1;
|
||||
private string _host;
|
||||
|
||||
public JsonPropertyIgnorer(string host)
|
||||
{
|
||||
_host = host;
|
||||
}
|
||||
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
|
||||
{
|
||||
JsonProperty property = base.CreateProperty(member, memberSerialization);
|
||||
|
||||
LoadableRelationAttribute relation = member.GetCustomAttribute<LoadableRelationAttribute>();
|
||||
if (relation != null)
|
||||
{
|
||||
if (relation.RelationID == null)
|
||||
property.ShouldSerialize = x => _depth == 0 && member.GetValue(x) != null;
|
||||
else
|
||||
property.ShouldSerialize = x =>
|
||||
{
|
||||
if (_depth != 0)
|
||||
return false;
|
||||
if (member.GetValue(x) != null)
|
||||
return true;
|
||||
return x.GetType().GetProperty(relation.RelationID)?.GetValue(x) != null;
|
||||
};
|
||||
}
|
||||
|
||||
if (member.GetCustomAttribute<SerializeIgnoreAttribute>() != null)
|
||||
property.ShouldSerialize = _ => false;
|
||||
if (member.GetCustomAttribute<DeserializeIgnoreAttribute>() != null)
|
||||
property.ShouldDeserialize = _ => false;
|
||||
|
||||
// TODO use http context to disable serialize as.
|
||||
// TODO check https://stackoverflow.com/questions/53288633/net-core-api-custom-json-resolver-based-on-request-values
|
||||
SerializeAsAttribute serializeAs = member.GetCustomAttribute<SerializeAsAttribute>();
|
||||
if (serializeAs != null)
|
||||
property.ValueProvider = new SerializeAsProvider(serializeAs.Format, _host);
|
||||
return property;
|
||||
}
|
||||
|
||||
protected override JsonContract CreateContract(Type objectType)
|
||||
{
|
||||
JsonContract contract = base.CreateContract(objectType);
|
||||
if (Utility.GetGenericDefinition(objectType, typeof(Page<>)) == null
|
||||
&& !objectType.IsAssignableTo(typeof(IEnumerable))
|
||||
&& objectType.Name != "AnnotatedProblemDetails")
|
||||
{
|
||||
contract.OnSerializingCallbacks.Add((_, _) => _depth++);
|
||||
contract.OnSerializedCallbacks.Add((_, _) => _depth--);
|
||||
}
|
||||
|
||||
return contract;
|
||||
}
|
||||
}
|
||||
|
||||
public class PeopleRoleConverter : JsonConverter<PeopleRole>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, PeopleRole value, JsonSerializer serializer)
|
||||
{
|
||||
ICollection<PeopleRole> oldPeople = value.Show?.People;
|
||||
ICollection<PeopleRole> oldRoles = value.People?.Roles;
|
||||
if (value.Show != null)
|
||||
value.Show.People = null;
|
||||
if (value.People != null)
|
||||
value.People.Roles = null;
|
||||
|
||||
JObject obj = JObject.FromObject((value.ForPeople ? value.People : value.Show)!, serializer);
|
||||
obj.Add("role", value.Role);
|
||||
obj.Add("type", value.Type);
|
||||
obj.WriteTo(writer);
|
||||
|
||||
if (value.Show != null)
|
||||
value.Show.People = oldPeople;
|
||||
if (value.People != null)
|
||||
value.People.Roles = oldRoles;
|
||||
}
|
||||
|
||||
public override PeopleRole ReadJson(JsonReader reader,
|
||||
Type objectType,
|
||||
PeopleRole existingValue,
|
||||
bool hasExistingValue,
|
||||
JsonSerializer serializer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializeAsProvider : IValueProvider
|
||||
{
|
||||
private string _format;
|
||||
private string _host;
|
||||
|
||||
public SerializeAsProvider(string format, string host)
|
||||
{
|
||||
_format = format;
|
||||
_host = host.TrimEnd('/');
|
||||
}
|
||||
|
||||
public object GetValue(object target)
|
||||
{
|
||||
return Regex.Replace(_format, @"(?<!{){(\w+)(:(\w+))?}", x =>
|
||||
{
|
||||
string value = x.Groups[1].Value;
|
||||
string modifier = x.Groups[3].Value;
|
||||
|
||||
if (value == "HOST")
|
||||
return _host;
|
||||
|
||||
PropertyInfo properties = target.GetType()
|
||||
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.FirstOrDefault(y => y.Name == value);
|
||||
if (properties == null)
|
||||
return null;
|
||||
object objValue = properties.GetValue(target);
|
||||
if (objValue is not string ret)
|
||||
ret = objValue?.ToString();
|
||||
if (ret == null)
|
||||
throw new ArgumentException($"Invalid serializer replacement {value}");
|
||||
|
||||
foreach (char modification in modifier)
|
||||
{
|
||||
ret = modification switch
|
||||
{
|
||||
'l' => ret.ToLowerInvariant(),
|
||||
'u' => ret.ToUpperInvariant(),
|
||||
_ => throw new ArgumentException($"Invalid serializer modificator {modification}.")
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
}
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
{
|
||||
// Values are ignored and should not be editable, except if the internal value is set.
|
||||
}
|
||||
}
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Kyoo.Abstractions.Models.Permissions;
|
||||
|
||||
namespace Kyoo.Core.Api
|
||||
{
|
||||
[Route("subtitle")]
|
||||
[ApiController]
|
||||
public class SubtitleApi : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IFileSystem _files;
|
||||
|
||||
public SubtitleApi(ILibraryManager libraryManager, IFileSystem files)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_files = files;
|
||||
}
|
||||
|
||||
[HttpGet("{id:int}")]
|
||||
[Permission(nameof(SubtitleApi), Kind.Read)]
|
||||
public async Task<IActionResult> GetSubtitle(int id)
|
||||
{
|
||||
Track subtitle = await _libraryManager.GetOrDefault<Track>(id);
|
||||
return subtitle != null
|
||||
? _files.FileResult(subtitle.Path)
|
||||
: NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("{id:int}.{extension}")]
|
||||
[Permission(nameof(SubtitleApi), Kind.Read)]
|
||||
public async Task<IActionResult> GetSubtitle(int id, string extension)
|
||||
{
|
||||
Track subtitle = await _libraryManager.GetOrDefault<Track>(id);
|
||||
if (subtitle == null)
|
||||
return NotFound();
|
||||
if (subtitle.Codec == "subrip" && extension == "vtt")
|
||||
return new ConvertSubripToVtt(subtitle.Path, _files);
|
||||
return _files.FileResult(subtitle.Path);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("{slug}")]
|
||||
[Permission(nameof(SubtitleApi), Kind.Read)]
|
||||
public async Task<IActionResult> GetSubtitle(string slug)
|
||||
{
|
||||
string extension = null;
|
||||
|
||||
if (slug.Count(x => x == '.') == 3)
|
||||
{
|
||||
int idx = slug.LastIndexOf('.');
|
||||
extension = slug[(idx + 1)..];
|
||||
slug = slug[..idx];
|
||||
}
|
||||
|
||||
Track subtitle = await _libraryManager.GetOrDefault<Track>(Track.BuildSlug(slug, StreamType.Subtitle));
|
||||
if (subtitle == null)
|
||||
return NotFound();
|
||||
if (subtitle.Codec == "subrip" && extension == "vtt")
|
||||
return new ConvertSubripToVtt(subtitle.Path, _files);
|
||||
return _files.FileResult(subtitle.Path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ConvertSubripToVtt : IActionResult
|
||||
{
|
||||
private readonly string _path;
|
||||
private readonly IFileSystem _files;
|
||||
|
||||
public ConvertSubripToVtt(string subtitlePath, IFileSystem files)
|
||||
{
|
||||
_path = subtitlePath;
|
||||
_files = files;
|
||||
}
|
||||
|
||||
public async Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
List<string> lines = new();
|
||||
|
||||
context.HttpContext.Response.StatusCode = 200;
|
||||
context.HttpContext.Response.Headers.Add("Content-Type", "text/vtt");
|
||||
|
||||
await using (StreamWriter writer = new(context.HttpContext.Response.Body))
|
||||
{
|
||||
await writer.WriteLineAsync("WEBVTT");
|
||||
await writer.WriteLineAsync("");
|
||||
await writer.WriteLineAsync("");
|
||||
|
||||
using StreamReader reader = new(await _files.GetReader(_path));
|
||||
string line;
|
||||
while ((line = await reader.ReadLineAsync()) != null)
|
||||
{
|
||||
if (line == "")
|
||||
{
|
||||
lines.Add("");
|
||||
IEnumerable<string> processedBlock = ConvertBlock(lines);
|
||||
foreach (string t in processedBlock)
|
||||
await writer.WriteLineAsync(t);
|
||||
lines.Clear();
|
||||
}
|
||||
else
|
||||
lines.Add(line);
|
||||
}
|
||||
}
|
||||
|
||||
await context.HttpContext.Response.Body.FlushAsync();
|
||||
}
|
||||
|
||||
private static IEnumerable<string> ConvertBlock(IList<string> lines)
|
||||
{
|
||||
if (lines.Count < 3)
|
||||
return lines;
|
||||
lines[1] = lines[1].Replace(',', '.');
|
||||
if (lines[2].Length > 5)
|
||||
{
|
||||
lines[1] += lines[2].Substring(0, 6) switch
|
||||
{
|
||||
"{\\an1}" => " line:93% position:15%",
|
||||
"{\\an2}" => " line:93%",
|
||||
"{\\an3}" => " line:93% position:85%",
|
||||
"{\\an4}" => " line:50% position:15%",
|
||||
"{\\an5}" => " line:50%",
|
||||
"{\\an6}" => " line:50% position:85%",
|
||||
"{\\an7}" => " line:7% position:15%",
|
||||
"{\\an8}" => " line:7%",
|
||||
"{\\an9}" => " line:7% position:85%",
|
||||
_ => " line:93%"
|
||||
};
|
||||
}
|
||||
|
||||
if (lines[2].StartsWith("{\\an"))
|
||||
lines[2] = lines[2].Substring(6);
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Kyoo.Abstractions.Models.Exceptions;
|
||||
using Kyoo.Abstractions.Models.Permissions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Kyoo.Core.Api
|
||||
{
|
||||
[Route("api/watch")]
|
||||
[ApiController]
|
||||
public class WatchApi : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public WatchApi(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet("{slug}")]
|
||||
[Permission("video", Kind.Read)]
|
||||
public async Task<ActionResult<WatchItem>> GetWatchItem(string slug)
|
||||
{
|
||||
try
|
||||
{
|
||||
Episode item = await _libraryManager.Get<Episode>(slug);
|
||||
return await WatchItem.FromEpisode(item, _libraryManager);
|
||||
}
|
||||
catch (ItemNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Core;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
||||
namespace Kyoo.Host.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Program entrypoint.
|
||||
/// </summary>
|
||||
public static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The string representation of the environment used in <see cref="IWebHostEnvironment"/>.
|
||||
/// </summary>
|
||||
#if DEBUG
|
||||
private const string Environment = "Development";
|
||||
#else
|
||||
private const string Environment = "Production";
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Main function of the program
|
||||
/// </summary>
|
||||
/// <param name="args">Command line arguments</param>
|
||||
public static Task Main(string[] args)
|
||||
{
|
||||
Application application = new(Environment);
|
||||
return application.Start(args);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<IsWindows Condition="$([MSBuild]::IsOSPlatform('Windows'))">true</IsWindows>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="Kyoo.Host.WindowsTrait.target" Condition="$(IsWindows) == true" />
|
||||
<Import Project="Kyoo.Host.WindowsTrait.linux.target" Condition="$(IsWindows) != true" />
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="*.target" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,26 +0,0 @@
|
||||
<Project>
|
||||
<!-- Project file used instead of the default csproj when the host system is not windows. This only skip the build. -->
|
||||
|
||||
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<NoWarn>NU1503</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
|
||||
|
||||
<Target Name="Build">
|
||||
<Message Importance="high" Text="Detected current operating system is not windows, skipping WindowsHost build." />
|
||||
</Target>
|
||||
|
||||
<Target Name="Clean" />
|
||||
<Target Name="Pack" />
|
||||
<Target Name="Restore" />
|
||||
<Target Name="Publish" />
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="@(Compile)" />
|
||||
<Compile Remove="*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,32 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Autofac;
|
||||
using Kyoo.Core;
|
||||
|
||||
namespace Kyoo.Host.WindowsTrait
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The string representation of the environment used in IWebHostEnvironment.
|
||||
/// </summary>
|
||||
#if DEBUG
|
||||
private const string Environment = "Development";
|
||||
#else
|
||||
private const string Environment = "Production";
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application that overrides the default host.
|
||||
/// It adds a system trait for windows and since the host is build as a windows executable instead of a console
|
||||
/// app, the console is not showed.
|
||||
/// </summary>
|
||||
public static Task Main(string[] args)
|
||||
{
|
||||
Application application = new(Environment);
|
||||
return application.Start(args, builder =>
|
||||
{
|
||||
builder.RegisterType<SystemTrait>().As<IStartable>().SingleInstance();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,846 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
namespace Kyoo.Postgresql.Migrations
|
||||
{
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterDatabase()
|
||||
.Annotation("Npgsql:Enum:item_type", "show,movie,collection")
|
||||
.Annotation("Npgsql:Enum:status", "unknown,finished,airing,planned")
|
||||
.Annotation("Npgsql:Enum:stream_type", "unknown,video,audio,subtitle,attachment");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "collections",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: false),
|
||||
name = table.Column<string>(type: "text", nullable: true),
|
||||
images = table.Column<Dictionary<int, string>>(type: "jsonb", nullable: true),
|
||||
overview = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_collections", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "genres",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: false),
|
||||
name = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_genres", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "libraries",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: false),
|
||||
name = table.Column<string>(type: "text", nullable: true),
|
||||
paths = table.Column<string[]>(type: "text[]", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_libraries", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "people",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: false),
|
||||
name = table.Column<string>(type: "text", nullable: true),
|
||||
images = table.Column<Dictionary<int, string>>(type: "jsonb", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_people", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "providers",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: false),
|
||||
name = table.Column<string>(type: "text", nullable: true),
|
||||
images = table.Column<Dictionary<int, string>>(type: "jsonb", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_providers", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "studios",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: false),
|
||||
name = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_studios", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "users",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: false),
|
||||
username = table.Column<string>(type: "text", nullable: true),
|
||||
email = table.Column<string>(type: "text", nullable: true),
|
||||
password = table.Column<string>(type: "text", nullable: true),
|
||||
permissions = table.Column<string[]>(type: "text[]", nullable: true),
|
||||
extra_data = table.Column<Dictionary<string, string>>(type: "jsonb", nullable: true),
|
||||
images = table.Column<Dictionary<int, string>>(type: "jsonb", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_users", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "link_library_collection",
|
||||
columns: table => new
|
||||
{
|
||||
collection_id = table.Column<int>(type: "integer", nullable: false),
|
||||
library_id = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_link_library_collection", x => new { x.collection_id, x.library_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_link_library_collection_collections_collection_id",
|
||||
column: x => x.collection_id,
|
||||
principalTable: "collections",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_link_library_collection_libraries_library_id",
|
||||
column: x => x.library_id,
|
||||
principalTable: "libraries",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "collection_metadata_id",
|
||||
columns: table => new
|
||||
{
|
||||
resource_id = table.Column<int>(type: "integer", nullable: false),
|
||||
provider_id = table.Column<int>(type: "integer", nullable: false),
|
||||
data_id = table.Column<string>(type: "text", nullable: true),
|
||||
link = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_collection_metadata_id", x => new { x.resource_id, x.provider_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_collection_metadata_id_collections_collection_id",
|
||||
column: x => x.resource_id,
|
||||
principalTable: "collections",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_collection_metadata_id_providers_provider_id",
|
||||
column: x => x.provider_id,
|
||||
principalTable: "providers",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "link_library_provider",
|
||||
columns: table => new
|
||||
{
|
||||
library_id = table.Column<int>(type: "integer", nullable: false),
|
||||
provider_id = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_link_library_provider", x => new { x.library_id, x.provider_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_link_library_provider_libraries_library_id",
|
||||
column: x => x.library_id,
|
||||
principalTable: "libraries",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_link_library_provider_providers_provider_id",
|
||||
column: x => x.provider_id,
|
||||
principalTable: "providers",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "people_metadata_id",
|
||||
columns: table => new
|
||||
{
|
||||
resource_id = table.Column<int>(type: "integer", nullable: false),
|
||||
provider_id = table.Column<int>(type: "integer", nullable: false),
|
||||
data_id = table.Column<string>(type: "text", nullable: true),
|
||||
link = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_people_metadata_id", x => new { x.resource_id, x.provider_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_people_metadata_id_people_people_id",
|
||||
column: x => x.resource_id,
|
||||
principalTable: "people",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_people_metadata_id_providers_provider_id",
|
||||
column: x => x.provider_id,
|
||||
principalTable: "providers",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "shows",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: false),
|
||||
title = table.Column<string>(type: "text", nullable: true),
|
||||
aliases = table.Column<string[]>(type: "text[]", nullable: true),
|
||||
path = table.Column<string>(type: "text", nullable: true),
|
||||
overview = table.Column<string>(type: "text", nullable: true),
|
||||
status = table.Column<Status>(type: "status", nullable: false),
|
||||
start_air = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
|
||||
end_air = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
|
||||
images = table.Column<Dictionary<int, string>>(type: "jsonb", nullable: true),
|
||||
is_movie = table.Column<bool>(type: "boolean", nullable: false),
|
||||
studio_id = table.Column<int>(type: "integer", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_shows", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_shows_studios_studio_id",
|
||||
column: x => x.studio_id,
|
||||
principalTable: "studios",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "studio_metadata_id",
|
||||
columns: table => new
|
||||
{
|
||||
resource_id = table.Column<int>(type: "integer", nullable: false),
|
||||
provider_id = table.Column<int>(type: "integer", nullable: false),
|
||||
data_id = table.Column<string>(type: "text", nullable: true),
|
||||
link = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_studio_metadata_id", x => new { x.resource_id, x.provider_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_studio_metadata_id_providers_provider_id",
|
||||
column: x => x.provider_id,
|
||||
principalTable: "providers",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_studio_metadata_id_studios_studio_id",
|
||||
column: x => x.resource_id,
|
||||
principalTable: "studios",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "link_collection_show",
|
||||
columns: table => new
|
||||
{
|
||||
collection_id = table.Column<int>(type: "integer", nullable: false),
|
||||
show_id = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_link_collection_show", x => new { x.collection_id, x.show_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_link_collection_show_collections_collection_id",
|
||||
column: x => x.collection_id,
|
||||
principalTable: "collections",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_link_collection_show_shows_show_id",
|
||||
column: x => x.show_id,
|
||||
principalTable: "shows",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "link_library_show",
|
||||
columns: table => new
|
||||
{
|
||||
library_id = table.Column<int>(type: "integer", nullable: false),
|
||||
show_id = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_link_library_show", x => new { x.library_id, x.show_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_link_library_show_libraries_library_id",
|
||||
column: x => x.library_id,
|
||||
principalTable: "libraries",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_link_library_show_shows_show_id",
|
||||
column: x => x.show_id,
|
||||
principalTable: "shows",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "link_show_genre",
|
||||
columns: table => new
|
||||
{
|
||||
genre_id = table.Column<int>(type: "integer", nullable: false),
|
||||
show_id = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_link_show_genre", x => new { x.genre_id, x.show_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_link_show_genre_genres_genre_id",
|
||||
column: x => x.genre_id,
|
||||
principalTable: "genres",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_link_show_genre_shows_show_id",
|
||||
column: x => x.show_id,
|
||||
principalTable: "shows",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "link_user_show",
|
||||
columns: table => new
|
||||
{
|
||||
users_id = table.Column<int>(type: "integer", nullable: false),
|
||||
watched_id = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_link_user_show", x => new { x.users_id, x.watched_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_link_user_show_shows_watched_id",
|
||||
column: x => x.watched_id,
|
||||
principalTable: "shows",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_link_user_show_users_users_id",
|
||||
column: x => x.users_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "people_roles",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
people_id = table.Column<int>(type: "integer", nullable: false),
|
||||
show_id = table.Column<int>(type: "integer", nullable: false),
|
||||
type = table.Column<string>(type: "text", nullable: true),
|
||||
role = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_people_roles", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_people_roles_people_people_id",
|
||||
column: x => x.people_id,
|
||||
principalTable: "people",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_people_roles_shows_show_id",
|
||||
column: x => x.show_id,
|
||||
principalTable: "shows",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "seasons",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: true),
|
||||
show_id = table.Column<int>(type: "integer", nullable: false),
|
||||
season_number = table.Column<int>(type: "integer", nullable: false),
|
||||
title = table.Column<string>(type: "text", nullable: true),
|
||||
overview = table.Column<string>(type: "text", nullable: true),
|
||||
start_date = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
|
||||
end_date = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
|
||||
images = table.Column<Dictionary<int, string>>(type: "jsonb", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_seasons", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_seasons_shows_show_id",
|
||||
column: x => x.show_id,
|
||||
principalTable: "shows",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "show_metadata_id",
|
||||
columns: table => new
|
||||
{
|
||||
resource_id = table.Column<int>(type: "integer", nullable: false),
|
||||
provider_id = table.Column<int>(type: "integer", nullable: false),
|
||||
data_id = table.Column<string>(type: "text", nullable: true),
|
||||
link = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_show_metadata_id", x => new { x.resource_id, x.provider_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_show_metadata_id_providers_provider_id",
|
||||
column: x => x.provider_id,
|
||||
principalTable: "providers",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_show_metadata_id_shows_show_id",
|
||||
column: x => x.resource_id,
|
||||
principalTable: "shows",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "episodes",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: true),
|
||||
show_id = table.Column<int>(type: "integer", nullable: false),
|
||||
season_id = table.Column<int>(type: "integer", nullable: true),
|
||||
season_number = table.Column<int>(type: "integer", nullable: true),
|
||||
episode_number = table.Column<int>(type: "integer", nullable: true),
|
||||
absolute_number = table.Column<int>(type: "integer", nullable: true),
|
||||
path = table.Column<string>(type: "text", nullable: true),
|
||||
images = table.Column<Dictionary<int, string>>(type: "jsonb", nullable: true),
|
||||
title = table.Column<string>(type: "text", nullable: true),
|
||||
overview = table.Column<string>(type: "text", nullable: true),
|
||||
release_date = table.Column<DateTime>(type: "timestamp without time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_episodes", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_episodes_seasons_season_id",
|
||||
column: x => x.season_id,
|
||||
principalTable: "seasons",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_episodes_shows_show_id",
|
||||
column: x => x.show_id,
|
||||
principalTable: "shows",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "season_metadata_id",
|
||||
columns: table => new
|
||||
{
|
||||
resource_id = table.Column<int>(type: "integer", nullable: false),
|
||||
provider_id = table.Column<int>(type: "integer", nullable: false),
|
||||
data_id = table.Column<string>(type: "text", nullable: true),
|
||||
link = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_season_metadata_id", x => new { x.resource_id, x.provider_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_season_metadata_id_providers_provider_id",
|
||||
column: x => x.provider_id,
|
||||
principalTable: "providers",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_season_metadata_id_seasons_season_id",
|
||||
column: x => x.resource_id,
|
||||
principalTable: "seasons",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "episode_metadata_id",
|
||||
columns: table => new
|
||||
{
|
||||
resource_id = table.Column<int>(type: "integer", nullable: false),
|
||||
provider_id = table.Column<int>(type: "integer", nullable: false),
|
||||
data_id = table.Column<string>(type: "text", nullable: true),
|
||||
link = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_episode_metadata_id", x => new { x.resource_id, x.provider_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_episode_metadata_id_episodes_episode_id",
|
||||
column: x => x.resource_id,
|
||||
principalTable: "episodes",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_episode_metadata_id_providers_provider_id",
|
||||
column: x => x.provider_id,
|
||||
principalTable: "providers",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tracks",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
slug = table.Column<string>(type: "text", nullable: true),
|
||||
title = table.Column<string>(type: "text", nullable: true),
|
||||
language = table.Column<string>(type: "text", nullable: true),
|
||||
codec = table.Column<string>(type: "text", nullable: true),
|
||||
is_default = table.Column<bool>(type: "boolean", nullable: false),
|
||||
is_forced = table.Column<bool>(type: "boolean", nullable: false),
|
||||
is_external = table.Column<bool>(type: "boolean", nullable: false),
|
||||
path = table.Column<string>(type: "text", nullable: true),
|
||||
type = table.Column<StreamType>(type: "stream_type", nullable: false),
|
||||
episode_id = table.Column<int>(type: "integer", nullable: false),
|
||||
track_index = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tracks", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_tracks_episodes_episode_id",
|
||||
column: x => x.episode_id,
|
||||
principalTable: "episodes",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "watched_episodes",
|
||||
columns: table => new
|
||||
{
|
||||
user_id = table.Column<int>(type: "integer", nullable: false),
|
||||
episode_id = table.Column<int>(type: "integer", nullable: false),
|
||||
watched_percentage = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_watched_episodes", x => new { x.user_id, x.episode_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_watched_episodes_episodes_episode_id",
|
||||
column: x => x.episode_id,
|
||||
principalTable: "episodes",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_watched_episodes_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_collection_metadata_id_provider_id",
|
||||
table: "collection_metadata_id",
|
||||
column: "provider_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_collections_slug",
|
||||
table: "collections",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_episode_metadata_id_provider_id",
|
||||
table: "episode_metadata_id",
|
||||
column: "provider_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_episodes_season_id",
|
||||
table: "episodes",
|
||||
column: "season_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_episodes_show_id_season_number_episode_number_absolute_numb",
|
||||
table: "episodes",
|
||||
columns: new[] { "show_id", "season_number", "episode_number", "absolute_number" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_episodes_slug",
|
||||
table: "episodes",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_genres_slug",
|
||||
table: "genres",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_libraries_slug",
|
||||
table: "libraries",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_link_collection_show_show_id",
|
||||
table: "link_collection_show",
|
||||
column: "show_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_link_library_collection_library_id",
|
||||
table: "link_library_collection",
|
||||
column: "library_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_link_library_provider_provider_id",
|
||||
table: "link_library_provider",
|
||||
column: "provider_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_link_library_show_show_id",
|
||||
table: "link_library_show",
|
||||
column: "show_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_link_show_genre_show_id",
|
||||
table: "link_show_genre",
|
||||
column: "show_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_link_user_show_watched_id",
|
||||
table: "link_user_show",
|
||||
column: "watched_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_people_slug",
|
||||
table: "people",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_people_metadata_id_provider_id",
|
||||
table: "people_metadata_id",
|
||||
column: "provider_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_people_roles_people_id",
|
||||
table: "people_roles",
|
||||
column: "people_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_people_roles_show_id",
|
||||
table: "people_roles",
|
||||
column: "show_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_providers_slug",
|
||||
table: "providers",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_season_metadata_id_provider_id",
|
||||
table: "season_metadata_id",
|
||||
column: "provider_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_seasons_show_id_season_number",
|
||||
table: "seasons",
|
||||
columns: new[] { "show_id", "season_number" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_seasons_slug",
|
||||
table: "seasons",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_show_metadata_id_provider_id",
|
||||
table: "show_metadata_id",
|
||||
column: "provider_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_shows_slug",
|
||||
table: "shows",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_shows_studio_id",
|
||||
table: "shows",
|
||||
column: "studio_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_studio_metadata_id_provider_id",
|
||||
table: "studio_metadata_id",
|
||||
column: "provider_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_studios_slug",
|
||||
table: "studios",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tracks_episode_id_type_language_track_index_is_forced",
|
||||
table: "tracks",
|
||||
columns: new[] { "episode_id", "type", "language", "track_index", "is_forced" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tracks_slug",
|
||||
table: "tracks",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_users_slug",
|
||||
table: "users",
|
||||
column: "slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_watched_episodes_episode_id",
|
||||
table: "watched_episodes",
|
||||
column: "episode_id");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "collection_metadata_id");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "episode_metadata_id");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "link_collection_show");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "link_library_collection");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "link_library_provider");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "link_library_show");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "link_show_genre");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "link_user_show");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "people_metadata_id");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "people_roles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "season_metadata_id");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "show_metadata_id");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "studio_metadata_id");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tracks");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "watched_episodes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "collections");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "libraries");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "genres");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "people");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "providers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "episodes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "users");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "seasons");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "shows");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "studios");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,838 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Kyoo.SqLite.Migrations
|
||||
{
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Collections",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Images = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Overview = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Collections", x => x.ID);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Genres",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Genres", x => x.ID);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Libraries",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Paths = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Libraries", x => x.ID);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "People",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Images = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_People", x => x.ID);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Providers",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Images = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Providers", x => x.ID);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Studios",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Studios", x => x.ID);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Users",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Username = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Email = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Password = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Permissions = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ExtraData = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Images = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Users", x => x.ID);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LinkLibraryCollection",
|
||||
columns: table => new
|
||||
{
|
||||
CollectionID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
LibraryID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LinkLibraryCollection", x => new { x.CollectionID, x.LibraryID });
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkLibraryCollection_Collections_CollectionID",
|
||||
column: x => x.CollectionID,
|
||||
principalTable: "Collections",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkLibraryCollection_Libraries_LibraryID",
|
||||
column: x => x.LibraryID,
|
||||
principalTable: "Libraries",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "CollectionMetadataID",
|
||||
columns: table => new
|
||||
{
|
||||
ResourceID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ProviderID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
DataID = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Link = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_CollectionMetadataID", x => new { x.ResourceID, x.ProviderID });
|
||||
table.ForeignKey(
|
||||
name: "FK_CollectionMetadataID_Collections_ResourceID",
|
||||
column: x => x.ResourceID,
|
||||
principalTable: "Collections",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_CollectionMetadataID_Providers_ProviderID",
|
||||
column: x => x.ProviderID,
|
||||
principalTable: "Providers",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LinkLibraryProvider",
|
||||
columns: table => new
|
||||
{
|
||||
LibraryID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ProviderID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LinkLibraryProvider", x => new { x.LibraryID, x.ProviderID });
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkLibraryProvider_Libraries_LibraryID",
|
||||
column: x => x.LibraryID,
|
||||
principalTable: "Libraries",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkLibraryProvider_Providers_ProviderID",
|
||||
column: x => x.ProviderID,
|
||||
principalTable: "Providers",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PeopleMetadataID",
|
||||
columns: table => new
|
||||
{
|
||||
ResourceID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ProviderID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
DataID = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Link = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PeopleMetadataID", x => new { x.ResourceID, x.ProviderID });
|
||||
table.ForeignKey(
|
||||
name: "FK_PeopleMetadataID_People_ResourceID",
|
||||
column: x => x.ResourceID,
|
||||
principalTable: "People",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_PeopleMetadataID_Providers_ProviderID",
|
||||
column: x => x.ProviderID,
|
||||
principalTable: "Providers",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Shows",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Title = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Aliases = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Path = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Overview = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Status = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
StartAir = table.Column<DateTime>(type: "TEXT", nullable: true),
|
||||
EndAir = table.Column<DateTime>(type: "TEXT", nullable: true),
|
||||
Images = table.Column<string>(type: "TEXT", nullable: true),
|
||||
IsMovie = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
StudioID = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Shows", x => x.ID);
|
||||
table.ForeignKey(
|
||||
name: "FK_Shows_Studios_StudioID",
|
||||
column: x => x.StudioID,
|
||||
principalTable: "Studios",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "StudioMetadataID",
|
||||
columns: table => new
|
||||
{
|
||||
ResourceID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ProviderID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
DataID = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Link = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_StudioMetadataID", x => new { x.ResourceID, x.ProviderID });
|
||||
table.ForeignKey(
|
||||
name: "FK_StudioMetadataID_Providers_ProviderID",
|
||||
column: x => x.ProviderID,
|
||||
principalTable: "Providers",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_StudioMetadataID_Studios_ResourceID",
|
||||
column: x => x.ResourceID,
|
||||
principalTable: "Studios",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LinkCollectionShow",
|
||||
columns: table => new
|
||||
{
|
||||
CollectionID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ShowID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LinkCollectionShow", x => new { x.CollectionID, x.ShowID });
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkCollectionShow_Collections_CollectionID",
|
||||
column: x => x.CollectionID,
|
||||
principalTable: "Collections",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkCollectionShow_Shows_ShowID",
|
||||
column: x => x.ShowID,
|
||||
principalTable: "Shows",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LinkLibraryShow",
|
||||
columns: table => new
|
||||
{
|
||||
LibraryID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ShowID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LinkLibraryShow", x => new { x.LibraryID, x.ShowID });
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkLibraryShow_Libraries_LibraryID",
|
||||
column: x => x.LibraryID,
|
||||
principalTable: "Libraries",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkLibraryShow_Shows_ShowID",
|
||||
column: x => x.ShowID,
|
||||
principalTable: "Shows",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LinkShowGenre",
|
||||
columns: table => new
|
||||
{
|
||||
GenreID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ShowID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LinkShowGenre", x => new { x.GenreID, x.ShowID });
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkShowGenre_Genres_GenreID",
|
||||
column: x => x.GenreID,
|
||||
principalTable: "Genres",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkShowGenre_Shows_ShowID",
|
||||
column: x => x.ShowID,
|
||||
principalTable: "Shows",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LinkUserShow",
|
||||
columns: table => new
|
||||
{
|
||||
UsersID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
WatchedID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LinkUserShow", x => new { x.UsersID, x.WatchedID });
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkUserShow_Shows_WatchedID",
|
||||
column: x => x.WatchedID,
|
||||
principalTable: "Shows",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_LinkUserShow_Users_UsersID",
|
||||
column: x => x.UsersID,
|
||||
principalTable: "Users",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PeopleRoles",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
PeopleID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ShowID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Type = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Role = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PeopleRoles", x => x.ID);
|
||||
table.ForeignKey(
|
||||
name: "FK_PeopleRoles_People_PeopleID",
|
||||
column: x => x.PeopleID,
|
||||
principalTable: "People",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_PeopleRoles_Shows_ShowID",
|
||||
column: x => x.ShowID,
|
||||
principalTable: "Shows",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Seasons",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ShowID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
SeasonNumber = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Title = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Overview = table.Column<string>(type: "TEXT", nullable: true),
|
||||
StartDate = table.Column<DateTime>(type: "TEXT", nullable: true),
|
||||
EndDate = table.Column<DateTime>(type: "TEXT", nullable: true),
|
||||
Images = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Seasons", x => x.ID);
|
||||
table.ForeignKey(
|
||||
name: "FK_Seasons_Shows_ShowID",
|
||||
column: x => x.ShowID,
|
||||
principalTable: "Shows",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ShowMetadataID",
|
||||
columns: table => new
|
||||
{
|
||||
ResourceID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ProviderID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
DataID = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Link = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ShowMetadataID", x => new { x.ResourceID, x.ProviderID });
|
||||
table.ForeignKey(
|
||||
name: "FK_ShowMetadataID_Providers_ProviderID",
|
||||
column: x => x.ProviderID,
|
||||
principalTable: "Providers",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_ShowMetadataID_Shows_ResourceID",
|
||||
column: x => x.ResourceID,
|
||||
principalTable: "Shows",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Episodes",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ShowID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
SeasonID = table.Column<int>(type: "INTEGER", nullable: true),
|
||||
SeasonNumber = table.Column<int>(type: "INTEGER", nullable: true),
|
||||
EpisodeNumber = table.Column<int>(type: "INTEGER", nullable: true),
|
||||
AbsoluteNumber = table.Column<int>(type: "INTEGER", nullable: true),
|
||||
Path = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Images = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Title = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Overview = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ReleaseDate = table.Column<DateTime>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Episodes", x => x.ID);
|
||||
table.ForeignKey(
|
||||
name: "FK_Episodes_Seasons_SeasonID",
|
||||
column: x => x.SeasonID,
|
||||
principalTable: "Seasons",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Episodes_Shows_ShowID",
|
||||
column: x => x.ShowID,
|
||||
principalTable: "Shows",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SeasonMetadataID",
|
||||
columns: table => new
|
||||
{
|
||||
ResourceID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ProviderID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
DataID = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Link = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SeasonMetadataID", x => new { x.ResourceID, x.ProviderID });
|
||||
table.ForeignKey(
|
||||
name: "FK_SeasonMetadataID_Providers_ProviderID",
|
||||
column: x => x.ProviderID,
|
||||
principalTable: "Providers",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_SeasonMetadataID_Seasons_ResourceID",
|
||||
column: x => x.ResourceID,
|
||||
principalTable: "Seasons",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "EpisodeMetadataID",
|
||||
columns: table => new
|
||||
{
|
||||
ResourceID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ProviderID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
DataID = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Link = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_EpisodeMetadataID", x => new { x.ResourceID, x.ProviderID });
|
||||
table.ForeignKey(
|
||||
name: "FK_EpisodeMetadataID_Episodes_ResourceID",
|
||||
column: x => x.ResourceID,
|
||||
principalTable: "Episodes",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_EpisodeMetadataID_Providers_ProviderID",
|
||||
column: x => x.ProviderID,
|
||||
principalTable: "Providers",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Tracks",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Title = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Language = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Codec = table.Column<string>(type: "TEXT", nullable: true),
|
||||
IsDefault = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
IsForced = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
IsExternal = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
Path = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Type = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
EpisodeID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
TrackIndex = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Tracks", x => x.ID);
|
||||
table.ForeignKey(
|
||||
name: "FK_Tracks_Episodes_EpisodeID",
|
||||
column: x => x.EpisodeID,
|
||||
principalTable: "Episodes",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "WatchedEpisodes",
|
||||
columns: table => new
|
||||
{
|
||||
UserID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
EpisodeID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
WatchedPercentage = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_WatchedEpisodes", x => new { x.UserID, x.EpisodeID });
|
||||
table.ForeignKey(
|
||||
name: "FK_WatchedEpisodes_Episodes_EpisodeID",
|
||||
column: x => x.EpisodeID,
|
||||
principalTable: "Episodes",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_WatchedEpisodes_Users_UserID",
|
||||
column: x => x.UserID,
|
||||
principalTable: "Users",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_CollectionMetadataID_ProviderID",
|
||||
table: "CollectionMetadataID",
|
||||
column: "ProviderID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Collections_Slug",
|
||||
table: "Collections",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_EpisodeMetadataID_ProviderID",
|
||||
table: "EpisodeMetadataID",
|
||||
column: "ProviderID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Episodes_SeasonID",
|
||||
table: "Episodes",
|
||||
column: "SeasonID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Episodes_ShowID_SeasonNumber_EpisodeNumber_AbsoluteNumber",
|
||||
table: "Episodes",
|
||||
columns: new[] { "ShowID", "SeasonNumber", "EpisodeNumber", "AbsoluteNumber" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Episodes_Slug",
|
||||
table: "Episodes",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Genres_Slug",
|
||||
table: "Genres",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Libraries_Slug",
|
||||
table: "Libraries",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LinkCollectionShow_ShowID",
|
||||
table: "LinkCollectionShow",
|
||||
column: "ShowID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LinkLibraryCollection_LibraryID",
|
||||
table: "LinkLibraryCollection",
|
||||
column: "LibraryID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LinkLibraryProvider_ProviderID",
|
||||
table: "LinkLibraryProvider",
|
||||
column: "ProviderID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LinkLibraryShow_ShowID",
|
||||
table: "LinkLibraryShow",
|
||||
column: "ShowID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LinkShowGenre_ShowID",
|
||||
table: "LinkShowGenre",
|
||||
column: "ShowID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LinkUserShow_WatchedID",
|
||||
table: "LinkUserShow",
|
||||
column: "WatchedID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_People_Slug",
|
||||
table: "People",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PeopleMetadataID_ProviderID",
|
||||
table: "PeopleMetadataID",
|
||||
column: "ProviderID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PeopleRoles_PeopleID",
|
||||
table: "PeopleRoles",
|
||||
column: "PeopleID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PeopleRoles_ShowID",
|
||||
table: "PeopleRoles",
|
||||
column: "ShowID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Providers_Slug",
|
||||
table: "Providers",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SeasonMetadataID_ProviderID",
|
||||
table: "SeasonMetadataID",
|
||||
column: "ProviderID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Seasons_ShowID_SeasonNumber",
|
||||
table: "Seasons",
|
||||
columns: new[] { "ShowID", "SeasonNumber" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Seasons_Slug",
|
||||
table: "Seasons",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ShowMetadataID_ProviderID",
|
||||
table: "ShowMetadataID",
|
||||
column: "ProviderID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Shows_Slug",
|
||||
table: "Shows",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Shows_StudioID",
|
||||
table: "Shows",
|
||||
column: "StudioID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_StudioMetadataID_ProviderID",
|
||||
table: "StudioMetadataID",
|
||||
column: "ProviderID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Studios_Slug",
|
||||
table: "Studios",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tracks_EpisodeID_Type_Language_TrackIndex_IsForced",
|
||||
table: "Tracks",
|
||||
columns: new[] { "EpisodeID", "Type", "Language", "TrackIndex", "IsForced" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tracks_Slug",
|
||||
table: "Tracks",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_Slug",
|
||||
table: "Users",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_WatchedEpisodes_EpisodeID",
|
||||
table: "WatchedEpisodes",
|
||||
column: "EpisodeID");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "CollectionMetadataID");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "EpisodeMetadataID");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LinkCollectionShow");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LinkLibraryCollection");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LinkLibraryProvider");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LinkLibraryShow");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LinkShowGenre");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LinkUserShow");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PeopleMetadataID");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PeopleRoles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "SeasonMetadataID");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ShowMetadataID");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "StudioMetadataID");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Tracks");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "WatchedEpisodes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Collections");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Libraries");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Genres");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "People");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Providers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Episodes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Users");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Seasons");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Shows");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Studios");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
namespace Kyoo.TheMovieDb.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The option containing the api key for TheMovieDb.
|
||||
/// </summary>
|
||||
public class TheMovieDbOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The path to get this option from the root configuration.
|
||||
/// </summary>
|
||||
public const string Path = "the-moviedb";
|
||||
|
||||
/// <summary>
|
||||
/// The api key of TheMovieDb.
|
||||
/// </summary>
|
||||
public string ApiKey { get; set; }
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
namespace Kyoo.TheTvdb.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The option containing the api key for the tvdb.
|
||||
/// </summary>
|
||||
public class TvdbOption
|
||||
{
|
||||
/// <summary>
|
||||
/// The path to get this option from the root configuration.
|
||||
/// </summary>
|
||||
public const string Path = "tvdb";
|
||||
|
||||
/// <summary>
|
||||
/// The api key of the tvdb.
|
||||
/// </summary>
|
||||
public string ApiKey { get; set; }
|
||||
}
|
||||
}
|
44
Kyoo.ruleset
Normal file
44
Kyoo.ruleset
Normal file
@ -0,0 +1,44 @@
|
||||
<RuleSet Name="Kyoo" ToolsVersion="10.0">
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.MaintainabilityRules">
|
||||
<Rule Id="SA1413" Action="None" /> <!-- UseTrailingCommasInMultiLineInitializers -->
|
||||
<Rule Id="SA1414" Action="None" /> <!-- UseTrailingCommasInMultiLineInitializers -->
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.OrderingRules">
|
||||
<Rule Id="SA1201" Action="None" /> <!-- ElementsMustAppearInTheCorrectOrder -->
|
||||
<Rule Id="SA1202" Action="None" /> <!-- ElementsMustBeOrderedByAccess -->
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.NamingRules">
|
||||
<Rule Id="SA1309" Action="None" /> <!-- FieldNamesMustNotBeginWithUnderscore -->
|
||||
<Rule Id="SX1309" Action="Warning" /> <!-- FieldNamesMustBeginWithUnderscore -->
|
||||
<Rule Id="SA1300" Action="None" /> <!-- ElementMustBeginWithUpperCaseLetter (this conflict with the _ prefix for privates, enforced by an IDE rule) -->
|
||||
<Rule Id="SA1316" Action="None" /> <!-- TupleElementNamesShouldUseCorrectCasing (should be camels when deconstructing but pascal otherwise. -->
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.ReadabilityRules">
|
||||
<Rule Id="SA1101" Action="None" /> <!-- PrefixLocalCallsWithThis -->
|
||||
<Rule Id="SX1101" Action="Warning" /> <!-- DoNotPrefixLocalMembersWithThis -->
|
||||
<Rule Id="SA1134" Action="None" /> <!-- AttributesMustNotShareLine -->
|
||||
<Rule Id="SA1117" Action="None" /> <!-- ParametersMustBeOnSameLineOrSeparateLines -->
|
||||
<Rule Id="SA1116" Action="None" /> <!-- SplitParametersMustStartOnLineAfterDeclaration -->
|
||||
<Rule Id="SA1111" Action="None" /> <!-- ClosingParenthesisMustBeOnLineOfLastParameter -->
|
||||
<Rule Id="SA1009" Action="None" /> <!-- ClosingParenthesisMustBeSpacedCorrectly (bugged if the parenthesis is on a line by iteself) -->
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.SpacingRules">
|
||||
<Rule Id="SA1502" Action="None"/> <!-- DocumentationLinesMustBeginWithSingleSpace -->
|
||||
<Rule Id="SA1027" Action="None"/> <!-- UseTabsCorrectly (smarts tabs are broken). TODO find a way to enable smart tabs -->
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.LayoutRules">
|
||||
<Rule Id="SA1503" Action="None"/> <!-- BracesMustNotBeOmitted -->
|
||||
<Rule Id="SA1520" Action="None"/> <!-- UseBracesConsistently -->
|
||||
<Rule Id="SA1515" Action="None"/> <!-- SingleLineCommentMustBePrecededByBlankLine -->
|
||||
<Rule Id="SA1513" Action="None"/> <!-- ClosingBraceMustBeFollowedByBlankLine -->
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.DocumentationRules">
|
||||
<Rule Id="SA1642" Action="None" /> <!-- ConstructorSummaryDocumentationMustBeginWithStandardText -->
|
||||
<Rule Id="SA1643" Action="None" /> <!-- DestructorSummaryDocumentationMustBeginWithStandardText -->
|
||||
<Rule Id="SA1623" Action="None" /> <!-- PropertySummaryDocumentationMustMatchAccessors -->
|
||||
|
||||
|
||||
|
||||
<Rule Id="SA1629" Action="None" /> <!-- DocumentationTextMustEndWithAPeriod TODO remove this, this is only temporary -->
|
||||
</Rules>
|
||||
</RuleSet>
|
24
Kyoo.sln
24
Kyoo.sln
@ -1,27 +1,27 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kyoo.Core", "Kyoo.Core\Kyoo.Core.csproj", "{0F8275B6-C7DD-42DF-A168-755C81B1C329}"
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kyoo.Core", "src\Kyoo.Core\Kyoo.Core.csproj", "{0F8275B6-C7DD-42DF-A168-755C81B1C329}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Abstractions", "Kyoo.Abstractions\Kyoo.Abstractions.csproj", "{BAB2CAE1-AC28-4509-AA3E-8DC75BD59220}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Abstractions", "src\Kyoo.Abstractions\Kyoo.Abstractions.csproj", "{BAB2CAE1-AC28-4509-AA3E-8DC75BD59220}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Database", "Kyoo.Database\Kyoo.Database.csproj", "{6F91B645-F785-46BB-9C4F-1EFC83E489B6}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Database", "src\Kyoo.Database\Kyoo.Database.csproj", "{6F91B645-F785-46BB-9C4F-1EFC83E489B6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Postgresql", "Kyoo.Postgresql\Kyoo.Postgresql.csproj", "{3213C96D-0BF3-460B-A8B5-B9977229408A}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Postgresql", "src\Kyoo.Postgresql\Kyoo.Postgresql.csproj", "{3213C96D-0BF3-460B-A8B5-B9977229408A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Authentication", "Kyoo.Authentication\Kyoo.Authentication.csproj", "{7A841335-6523-47DB-9717-80AA7BD943FD}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Authentication", "src\Kyoo.Authentication\Kyoo.Authentication.csproj", "{7A841335-6523-47DB-9717-80AA7BD943FD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.SqLite", "Kyoo.SqLite\Kyoo.SqLite.csproj", "{6515380E-1E57-42DA-B6E3-E1C8A848818A}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.SqLite", "src\Kyoo.SqLite\Kyoo.SqLite.csproj", "{6515380E-1E57-42DA-B6E3-E1C8A848818A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.TheTvdb", "Kyoo.TheTvdb\Kyoo.TheTvdb.csproj", "{D06BF829-23F5-40F3-A62D-627D9F4B4D6C}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.TheTvdb", "src\Kyoo.TheTvdb\Kyoo.TheTvdb.csproj", "{D06BF829-23F5-40F3-A62D-627D9F4B4D6C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.TheMovieDb", "Kyoo.TheMovieDb\Kyoo.TheMovieDb.csproj", "{BAB270D4-E0EA-4329-BA65-512FDAB01001}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.TheMovieDb", "src\Kyoo.TheMovieDb\Kyoo.TheMovieDb.csproj", "{BAB270D4-E0EA-4329-BA65-512FDAB01001}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Tests", "tests\Kyoo.Tests\Kyoo.Tests.csproj", "{0C8AA7EA-E723-4532-852F-35AA4E8AFED5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.WebApp", "Kyoo.WebApp\Kyoo.WebApp.csproj", "{2374D500-1ADB-4752-85DB-8BB0DDF5A8E8}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.WebApp", "src\Kyoo.WebApp\Kyoo.WebApp.csproj", "{2374D500-1ADB-4752-85DB-8BB0DDF5A8E8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Host.WindowsTrait", "Kyoo.Host.WindowsTrait\Kyoo.Host.WindowsTrait.csproj", "{98851001-40DD-46A6-94B3-2F8D90722076}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Host.WindowsTrait", "src\Kyoo.Host.WindowsTrait\Kyoo.Host.WindowsTrait.csproj", "{98851001-40DD-46A6-94B3-2F8D90722076}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Host.Console", "Kyoo.Host.Console\Kyoo.Host.Console.csproj", "{D8658BEA-8949-45AC-BEBB-A4FFC4F800F5}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Host.Console", "src\Kyoo.Host.Console\Kyoo.Host.Console.csproj", "{D8658BEA-8949-45AC-BEBB-A4FFC4F800F5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
29
src/Directory.Build.props
Normal file
29
src/Directory.Build.props
Normal file
@ -0,0 +1,29 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<IsWindows Condition="$([MSBuild]::IsOSPlatform('Windows'))">true</IsWindows>
|
||||
<IsOSX Condition="$([MSBuild]::IsOSPlatform('OSX'))">true</IsOSX>
|
||||
<IsLinux Condition="$([MSBuild]::IsOSPlatform('Linux'))">true</IsLinux>
|
||||
|
||||
|
||||
<!-- TODO the next thing does not work on rider, enabling coding style check by default. -->
|
||||
<!--<CheckCodingStyle Condition="$(BuildingInsideVisualStudio) == true">true</CheckCodingStyle>-->
|
||||
<!--<CheckCodingStyle Condition="$(BuildingInsideReSharper) == true">true</CheckCodingStyle>-->
|
||||
<CheckCodingStyle Condition="$(CheckCodingStyle) == ''">true</CheckCodingStyle>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="$(CheckCodingStyle) == true">
|
||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.354" PrivateAssets="All" />
|
||||
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)../stylecop.json" Link="stylecop.json" Visible="false" />
|
||||
<None Include="$(MSBuildThisFileDirectory)../.editorconfig" Link=".editorconfig" Visible="false" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition="$(CheckCodingStyle) == true">
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>CS1591;SA1600;SA1601</NoWarn>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)../Kyoo.ruleset</CodeAnalysisRuleSet>
|
||||
<!-- <AnalysisMode>AllEnabledByDefault</AnalysisMode>-->
|
||||
</PropertyGroup>
|
||||
</Project>
|
49
src/Kyoo.Abstractions/Controllers/IApplication.cs
Normal file
49
src/Kyoo.Abstractions/Controllers/IApplication.cs
Normal file
@ -0,0 +1,49 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface that allow one to interact with the host and shutdown or restart the app.
|
||||
/// </summary>
|
||||
public interface IApplication
|
||||
{
|
||||
/// <summary>
|
||||
/// Shutdown the process and stop gracefully.
|
||||
/// </summary>
|
||||
void Shutdown();
|
||||
|
||||
/// <summary>
|
||||
/// Restart Kyoo from scratch, reload plugins, configurations and restart the web server.
|
||||
/// </summary>
|
||||
void Restart();
|
||||
|
||||
/// <summary>
|
||||
/// Get the data directory.
|
||||
/// </summary>
|
||||
/// <returns>Retrieve the data directory where runtime data should be stored.</returns>
|
||||
string GetDataDirectory();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the path of the json configuration file
|
||||
/// (relative to the data directory, see <see cref="GetDataDirectory"/>).
|
||||
/// </summary>
|
||||
/// <returns>The configuration file name.</returns>
|
||||
string GetConfigFile();
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
@ -14,12 +32,12 @@ namespace Kyoo.Abstractions.Controllers
|
||||
public interface IConfigurationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Add an editable configuration to the editable configuration list
|
||||
/// Add an editable configuration to the editable configuration list.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
/// <typeparam name="T">The type of the configuration.</typeparam>
|
||||
void AddTyped<T>(string path);
|
||||
|
||||
|
||||
/// <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
|
||||
@ -36,32 +54,33 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="path">The root path of the editable configuration. It should not be a nested type.</param>
|
||||
/// <param name="type">The type of the configuration or null.</param>
|
||||
void Register(string path, [CanBeNull] Type type);
|
||||
|
||||
|
||||
/// <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>
|
||||
/// <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>
|
||||
/// <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>
|
||||
/// <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="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>
|
||||
/// <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>
|
||||
/// <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>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task EditValue(string path, object value);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
@ -8,7 +26,8 @@ using Microsoft.AspNetCore.Mvc;
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// A service to abstract the file system to allow custom file systems (like distant file systems or external providers)
|
||||
/// A service to abstract the file system to allow custom file systems
|
||||
/// (like distant file systems or external providers).
|
||||
/// </summary>
|
||||
public interface IFileSystem
|
||||
{
|
||||
@ -16,10 +35,10 @@ namespace Kyoo.Abstractions.Controllers
|
||||
|
||||
/// <summary>
|
||||
/// Used for http queries returning a file. This should be used to return local files
|
||||
/// or proxy them from a distant server
|
||||
/// or proxy them from a distant server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If no file exists at the given path or if the path is null, a NotFoundResult is returned
|
||||
/// If no file exists at the given path or if the path is null, a NotFoundResult is returned
|
||||
/// to handle it gracefully.
|
||||
/// </remarks>
|
||||
/// <param name="path">The path of the file.</param>
|
||||
@ -42,7 +61,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <exception cref="FileNotFoundException">If the file could not be found.</exception>
|
||||
/// <returns>A reader to read the file.</returns>
|
||||
public Task<Stream> GetReader([NotNull] string path);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Read a file present at <paramref name="path"/>. The reader can be used in an arbitrary context.
|
||||
/// To return files from an http endpoint, use <see cref="FileResult"/>.
|
||||
@ -80,7 +99,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="path">The path of the directory</param>
|
||||
/// <param name="options">Should the search be recursive or not.</param>
|
||||
/// <returns>A list of files's path.</returns>
|
||||
public Task<ICollection<string>> ListFiles([NotNull] string path,
|
||||
public Task<ICollection<string>> ListFiles([NotNull] string path,
|
||||
SearchOption options = SearchOption.TopDirectoryOnly);
|
||||
|
||||
/// <summary>
|
||||
@ -100,4 +119,4 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The extra directory of the resource.</returns>
|
||||
public Task<string> GetExtraDirectory<T>([NotNull] T resource);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Kyoo.Abstractions.Models.Exceptions;
|
||||
@ -21,7 +39,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// If no metadata could be parsed for a type, null can be returned.
|
||||
/// </returns>
|
||||
Task<(Collection, Show, Season, Episode)> Identify(string path);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Identify an external subtitle or track file from it's path and return the parsed metadata.
|
||||
/// </summary>
|
||||
@ -34,4 +52,4 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// </returns>
|
||||
Task<Track> IdentifyTrack(string path);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,22 @@
|
||||
using System;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Runtime.InteropServices;
|
||||
@ -10,7 +28,7 @@ using Kyoo.Abstractions.Models.Exceptions;
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface to interract with the database. Every repository is mapped through here.
|
||||
/// An interface to interact with the database. Every repository is mapped through here.
|
||||
/// </summary>
|
||||
public interface ILibraryManager
|
||||
{
|
||||
@ -20,68 +38,69 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <typeparam name="T">The type you want</typeparam>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The repository corresponding</returns>
|
||||
IRepository<T> GetRepository<T>() where T : class, IResource;
|
||||
IRepository<T> GetRepository<T>()
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle libraries.
|
||||
/// </summary>
|
||||
ILibraryRepository LibraryRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle libraries's items (a wrapper arround shows & collections).
|
||||
/// The repository that handle libraries items (a wrapper around shows and collections).
|
||||
/// </summary>
|
||||
ILibraryItemRepository LibraryItemRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle collections.
|
||||
/// </summary>
|
||||
ICollectionRepository CollectionRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle shows.
|
||||
/// </summary>
|
||||
IShowRepository ShowRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle seasons.
|
||||
/// </summary>
|
||||
ISeasonRepository SeasonRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle episodes.
|
||||
/// </summary>
|
||||
IEpisodeRepository EpisodeRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle tracks.
|
||||
/// </summary>
|
||||
ITrackRepository TrackRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle people.
|
||||
/// </summary>
|
||||
IPeopleRepository PeopleRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle studios.
|
||||
/// </summary>
|
||||
IStudioRepository StudioRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle genres.
|
||||
/// </summary>
|
||||
IGenreRepository GenreRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle providers.
|
||||
/// </summary>
|
||||
IProviderRepository ProviderRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository that handle users.
|
||||
/// </summary>
|
||||
IUserRepository UserRepository { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the resource by it's ID
|
||||
/// </summary>
|
||||
@ -90,8 +109,9 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemNotNull]
|
||||
Task<T> Get<T>(int id) where T : class, IResource;
|
||||
|
||||
Task<T> Get<T>(int id)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Get the resource by it's slug
|
||||
/// </summary>
|
||||
@ -100,8 +120,9 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemNotNull]
|
||||
Task<T> Get<T>(string slug) where T : class, IResource;
|
||||
|
||||
Task<T> Get<T>(string slug)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Get the resource by a filter function.
|
||||
/// </summary>
|
||||
@ -110,7 +131,8 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The first resource found that match the where function</returns>
|
||||
[ItemNotNull]
|
||||
Task<T> Get<T>(Expression<Func<T, bool>> where) where T : class, IResource;
|
||||
Task<T> Get<T>(Expression<Func<T, bool>> where)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Get a season from it's showID and it's seasonNumber
|
||||
@ -121,7 +143,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The season found</returns>
|
||||
[ItemNotNull]
|
||||
Task<Season> Get(int showID, int seasonNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a season from it's show slug and it's seasonNumber
|
||||
/// </summary>
|
||||
@ -131,7 +153,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The season found</returns>
|
||||
[ItemNotNull]
|
||||
Task<Season> Get(string showSlug, int seasonNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a episode from it's showID, it's seasonNumber and it's episode number.
|
||||
/// </summary>
|
||||
@ -142,7 +164,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The episode found</returns>
|
||||
[ItemNotNull]
|
||||
Task<Episode> Get(int showID, int seasonNumber, int episodeNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a episode from it's show slug, it's seasonNumber and it's episode number.
|
||||
/// </summary>
|
||||
@ -161,8 +183,9 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <typeparam name="T">The type of the resource</typeparam>
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<T> GetOrDefault<T>(int id) where T : class, IResource;
|
||||
|
||||
Task<T> GetOrDefault<T>(int id)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Get the resource by it's slug or null if it is not found.
|
||||
/// </summary>
|
||||
@ -170,8 +193,9 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <typeparam name="T">The type of the resource</typeparam>
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<T> GetOrDefault<T>(string slug) where T : class, IResource;
|
||||
|
||||
Task<T> GetOrDefault<T>(string slug)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Get the resource by a filter function or null if it is not found.
|
||||
/// </summary>
|
||||
@ -179,7 +203,8 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <typeparam name="T">The type of the resource</typeparam>
|
||||
/// <returns>The first resource found that match the where function</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<T> GetOrDefault<T>(Expression<Func<T, bool>> where) where T : class, IResource;
|
||||
Task<T> GetOrDefault<T>(Expression<Func<T, bool>> where)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Get a season from it's showID and it's seasonNumber or null if it is not found.
|
||||
@ -189,7 +214,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The season found</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<Season> GetOrDefault(int showID, int seasonNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a season from it's show slug and it's seasonNumber or null if it is not found.
|
||||
/// </summary>
|
||||
@ -198,7 +223,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The season found</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<Season> GetOrDefault(string showSlug, int seasonNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a episode from it's showID, it's seasonNumber and it's episode number or null if it is not found.
|
||||
/// </summary>
|
||||
@ -208,7 +233,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The episode found</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a episode from it's show slug, it's seasonNumber and it's episode number or null if it is not found.
|
||||
/// </summary>
|
||||
@ -219,20 +244,19 @@ namespace Kyoo.Abstractions.Controllers
|
||||
[ItemCanBeNull]
|
||||
Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Load a related resource
|
||||
/// </summary>
|
||||
/// <param name="obj">The source object.</param>
|
||||
/// <param name="member">A getter function for the member to load</param>
|
||||
/// <param name="force">
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// </param>
|
||||
/// <typeparam name="T">The type of the source object</typeparam>
|
||||
/// <typeparam name="T2">The related resource's type</typeparam>
|
||||
/// <returns>The param <see cref="obj"/></returns>
|
||||
/// <returns>The param <paramref name="obj"/></returns>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, System.String, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, string, bool)"/>
|
||||
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, T2>> member, bool force = false)
|
||||
where T : class, IResource
|
||||
@ -244,13 +268,13 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="obj">The source object.</param>
|
||||
/// <param name="member">A getter function for the member to load</param>
|
||||
/// <param name="force">
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// </param>
|
||||
/// <typeparam name="T">The type of the source object</typeparam>
|
||||
/// <typeparam name="T2">The related resource's type</typeparam>
|
||||
/// <returns>The param <see cref="obj"/></returns>
|
||||
/// <returns>The param <paramref name="obj"/></returns>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, System.String, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, string, bool)"/>
|
||||
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, ICollection<T2>>> member, bool force = false)
|
||||
where T : class, IResource
|
||||
@ -262,10 +286,10 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="obj">The source object.</param>
|
||||
/// <param name="memberName">The name of the resource to load (case sensitive)</param>
|
||||
/// <param name="force">
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// </param>
|
||||
/// <typeparam name="T">The type of the source object</typeparam>
|
||||
/// <returns>The param <see cref="obj"/></returns>
|
||||
/// <returns>The param <paramref name="obj"/></returns>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||
@ -273,33 +297,34 @@ namespace Kyoo.Abstractions.Controllers
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Load a related resource without specifing it's type.
|
||||
/// Load a related resource without specifying it's type.
|
||||
/// </summary>
|
||||
/// <param name="obj">The source object.</param>
|
||||
/// <param name="memberName">The name of the resource to load (case sensitive)</param>
|
||||
/// <param name="force">
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// </param>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, System.String, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, string, bool)"/>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task Load([NotNull] IResource obj, string memberName, bool force = false);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper arround shows or collections) from a library.
|
||||
/// Get items (A wrapper around shows or collections) from a library.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the library</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort informations (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<LibraryItem>> GetItemsFromLibrary(int id,
|
||||
Expression<Func<LibraryItem, bool>> where = null,
|
||||
Sort<LibraryItem> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper arround shows or collections) from a library.
|
||||
/// Get items (A wrapper around shows or collections) from a library.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the library</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
@ -311,22 +336,22 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<LibraryItem, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetItemsFromLibrary(id, where, new Sort<LibraryItem>(sort), limit);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper arround shows or collections) from a library.
|
||||
/// Get items (A wrapper around shows or collections) from a library.
|
||||
/// </summary>
|
||||
/// <param name="slug">The slug of the library</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort informations (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<LibraryItem>> GetItemsFromLibrary(string slug,
|
||||
Expression<Func<LibraryItem, bool>> where = null,
|
||||
Sort<LibraryItem> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper arround shows or collections) from a library.
|
||||
/// Get items (A wrapper around shows or collections) from a library.
|
||||
/// </summary>
|
||||
/// <param name="slug">The slug of the library</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
@ -338,21 +363,20 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<LibraryItem, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetItemsFromLibrary(slug, where, new Sort<LibraryItem>(sort), limit);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
/// <param name="showID">The ID of the show</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort informations (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetPeopleFromShow(int showID,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
@ -366,20 +390,20 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetPeopleFromShow(showID, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
/// <param name="showSlug">The slug of the show</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort informations (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetPeopleFromShow(string showSlug,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
@ -393,21 +417,20 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetPeopleFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the person</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort informations (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetRolesFromPeople(int id,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
@ -421,20 +444,20 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetRolesFromPeople(id, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
/// <param name="slug">The slug of the person</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort informations (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetRolesFromPeople(string slug,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
@ -449,35 +472,37 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Pagination limit = default
|
||||
) => GetRolesFromPeople(slug, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Setup relations between a show, a library and a collection
|
||||
/// </summary>
|
||||
/// <param name="showID">The show's ID to setup relations with</param>
|
||||
/// <param name="libraryID">The library's ID to setup relations with (optional)</param>
|
||||
/// <param name="collectionID">The collection's ID to setup relations with (optional)</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task AddShowLink(int showID, int? libraryID, int? collectionID);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Setup relations between a show, a library and a collection
|
||||
/// </summary>
|
||||
/// <param name="show">The show to setup relations with</param>
|
||||
/// <param name="library">The library to setup relations with (optional)</param>
|
||||
/// <param name="collection">The collection to setup relations with (optional)</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task AddShowLink([NotNull] Show show, Library library, Collection collection);
|
||||
|
||||
/// <summary>
|
||||
/// Get all resources with filters
|
||||
/// </summary>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort informations (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <typeparam name="T">The type of resources to load</typeparam>
|
||||
/// <returns>A list of resources that match every filters</returns>
|
||||
Task<ICollection<T>> GetAll<T>(Expression<Func<T, bool>> where = null,
|
||||
Sort<T> sort = default,
|
||||
Pagination limit = default) where T : class, IResource;
|
||||
|
||||
Pagination limit = default)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Get all resources with filters
|
||||
/// </summary>
|
||||
@ -488,7 +513,8 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>A list of resources that match every filters</returns>
|
||||
Task<ICollection<T>> GetAll<T>([Optional] Expression<Func<T, bool>> where,
|
||||
Expression<Func<T, object>> sort,
|
||||
Pagination limit = default) where T : class, IResource
|
||||
Pagination limit = default)
|
||||
where T : class, IResource
|
||||
{
|
||||
return GetAll(where, new Sort<T>(sort), limit);
|
||||
}
|
||||
@ -499,7 +525,8 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <typeparam name="T">The type of resources to load</typeparam>
|
||||
/// <returns>A list of resources that match every filters</returns>
|
||||
Task<int> GetCount<T>(Expression<Func<T, bool>> where = null) where T : class, IResource;
|
||||
Task<int> GetCount<T>(Expression<Func<T, bool>> where = null)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Search for a resource
|
||||
@ -507,33 +534,37 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="query">The search query</param>
|
||||
/// <typeparam name="T">The type of resources</typeparam>
|
||||
/// <returns>A list of 20 items that match the search query</returns>
|
||||
Task<ICollection<T>> Search<T>(string query) where T : class, IResource;
|
||||
Task<ICollection<T>> Search<T>(string query)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource.
|
||||
/// </summary>
|
||||
/// <param name="item">The item to register</param>
|
||||
/// <typeparam name="T">The type of resource</typeparam>
|
||||
/// <returns>The resource registers and completed by database's informations (related items & so on)</returns>
|
||||
Task<T> Create<T>([NotNull] T item) where T : class, IResource;
|
||||
|
||||
/// <returns>The resource registers and completed by database's information (related items and so on)</returns>
|
||||
Task<T> Create<T>([NotNull] T item)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource if it does not exist already. If it does, the existing value is returned instead.
|
||||
/// </summary>
|
||||
/// <param name="item">The item to register</param>
|
||||
/// <typeparam name="T">The type of resource</typeparam>
|
||||
/// <returns>The newly created item or the existing value if it existed.</returns>
|
||||
Task<T> CreateIfNotExists<T>([NotNull] T item) where T : class, IResource;
|
||||
|
||||
Task<T> CreateIfNotExists<T>([NotNull] T item)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Edit a resource
|
||||
/// </summary>
|
||||
/// <param name="item">The resourcce to edit, it's ID can't change.</param>
|
||||
/// <param name="item">The resource 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="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;
|
||||
/// <returns>The resource edited and completed by database's information (related items and so on)</returns>
|
||||
Task<T> Edit<T>(T item, bool resetOld)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Delete a resource.
|
||||
@ -541,22 +572,28 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="item">The resource to delete</param>
|
||||
/// <typeparam name="T">The type of resource to delete</typeparam>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
Task Delete<T>(T item) where T : class, IResource;
|
||||
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task Delete<T>(T item)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Delete a resource by it's ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the resource to delete</param>
|
||||
/// <typeparam name="T">The type of resource to delete</typeparam>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
Task Delete<T>(int id) where T : class, IResource;
|
||||
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task Delete<T>(int id)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Delete a resource by it's slug.
|
||||
/// </summary>
|
||||
/// <param name="slug">The slug of the resource to delete</param>
|
||||
/// <typeparam name="T">The type of resource to delete</typeparam>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
Task Delete<T>(string slug) where T : class, IResource;
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task Delete<T>(string slug)
|
||||
where T : class, IResource;
|
||||
}
|
||||
}
|
@ -1,7 +1,25 @@
|
||||
using Kyoo.Abstractions.Models;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Kyoo.Abstractions.Models;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
@ -30,6 +48,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// Merging metadata is the job of Kyoo, a complex <typeparamref name="T"/> is given
|
||||
/// to make a precise search and give you every available properties, not to discard properties.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of resource to retrieve metadata for.</typeparam>
|
||||
/// <returns>A new <typeparamref name="T"/> containing metadata from your provider or null</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<T> Get<T>([NotNull] T item)
|
||||
@ -39,6 +58,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// Search for a specific type of items with a given query.
|
||||
/// </summary>
|
||||
/// <param name="query">The search query to use.</param>
|
||||
/// <typeparam name="T">The type of resource to search metadata for.</typeparam>
|
||||
/// <returns>The list of items that could be found on this specific provider.</returns>
|
||||
[ItemNotNull]
|
||||
Task<ICollection<T>> Search<T>(string query)
|
||||
@ -62,7 +82,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
|
||||
/// <summary>
|
||||
/// Since this is a composite and not a real provider, no metadata is available.
|
||||
/// It is not meant to be stored or selected. This class will handle merge based on what is required.
|
||||
/// It is not meant to be stored or selected. This class will handle merge based on what is required.
|
||||
/// </summary>
|
||||
public Provider Provider => null;
|
||||
|
47
src/Kyoo.Abstractions/Controllers/IPermissionValidator.cs
Normal file
47
src/Kyoo.Abstractions/Controllers/IPermissionValidator.cs
Normal file
@ -0,0 +1,47 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using Kyoo.Abstractions.Models.Permissions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// A service to validate permissions.
|
||||
/// </summary>
|
||||
public interface IPermissionValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an IAuthorizationFilter that will be used to validate permissions.
|
||||
/// This can registered with any lifetime.
|
||||
/// </summary>
|
||||
/// <param name="attribute">The permission attribute to validate.</param>
|
||||
/// <returns>An authorization filter used to validate the permission.</returns>
|
||||
IFilterMetadata Create(PermissionAttribute attribute);
|
||||
|
||||
/// <summary>
|
||||
/// Create an IAuthorizationFilter that will be used to validate permissions.
|
||||
/// This can registered with any lifetime.
|
||||
/// </summary>
|
||||
/// <param name="attribute">
|
||||
/// A partial attribute to validate. See <see cref="PartialPermissionAttribute"/>.
|
||||
/// </param>
|
||||
/// <returns>An authorization filter used to validate the permission.</returns>
|
||||
IFilterMetadata Create(PartialPermissionAttribute attribute);
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Autofac;
|
||||
@ -20,28 +38,28 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// A slug to identify this plugin in queries.
|
||||
/// </summary>
|
||||
string Slug { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of the plugin
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The description of this plugin. This will be displayed on the "installed plugins" page.
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <c>true</c> if the plugin should be enabled, <c>false</c> otherwise.
|
||||
/// If a plugin is not enabled, no configure method will be called.
|
||||
/// This allow one to enable a plugin if a specific configuration value is set or if the environment contains
|
||||
/// the right settings.
|
||||
/// the right settings.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, a plugin is always enabled. This method can be overriden to change this behavior.
|
||||
/// </remarks>
|
||||
virtual bool Enabled => true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A list of types that will be available via the IOptions interfaces and will be listed inside
|
||||
/// an IConfiguration.
|
||||
@ -64,7 +82,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <seealso cref="SA"/>
|
||||
virtual IEnumerable<IStartupAction> ConfigureSteps => ArraySegment<IStartupAction>.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// A configure method that will be run on plugin's startup.
|
||||
/// </summary>
|
||||
/// <param name="builder">The autofac service container to register services.</param>
|
||||
@ -72,7 +90,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
// Skipped
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A configure method that will be run on plugin's startup.
|
||||
/// This is available for libraries that build upon a <see cref="IServiceCollection"/>, for more precise
|
||||
@ -94,4 +112,4 @@ namespace Kyoo.Abstractions.Controllers
|
||||
// Skipped
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Models.Exceptions;
|
||||
@ -17,14 +35,14 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <exception cref="ItemNotFoundException">If no plugins match the query</exception>
|
||||
/// <returns>A plugin that match the queries</returns>
|
||||
public T GetPlugin<T>(string name);
|
||||
|
||||
|
||||
/// <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>
|
||||
@ -39,7 +57,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// You should not try to put plugins from the plugins directory here as they will get automatically loaded.
|
||||
/// </param>
|
||||
public void LoadPlugins(ICollection<IPlugin> plugins);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Load plugins and their dependencies from the plugin directory.
|
||||
/// </summary>
|
||||
@ -49,4 +67,4 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// </param>
|
||||
public void LoadPlugins(params Type[] plugins);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
@ -6,122 +24,15 @@ using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Kyoo.Abstractions.Models.Exceptions;
|
||||
using Kyoo.Utils;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// Information about the pagination. How many items should be displayed and where to start.
|
||||
/// </summary>
|
||||
public readonly struct Pagination
|
||||
{
|
||||
/// <summary>
|
||||
/// The count of items to return.
|
||||
/// </summary>
|
||||
public int Count { get; }
|
||||
/// <summary>
|
||||
/// Where to start? Using the given sort
|
||||
/// </summary>
|
||||
public int AfterID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Pagination"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="count">Set the <see cref="Count"/> value</param>
|
||||
/// <param name="afterID">Set the <see cref="AfterID"/> value. If not specified, it will start from the start</param>
|
||||
public Pagination(int count, int afterID = 0)
|
||||
{
|
||||
Count = count;
|
||||
AfterID = afterID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly create a new pagination from a limit number.
|
||||
/// </summary>
|
||||
/// <param name="limit">Set the <see cref="Count"/> value</param>
|
||||
/// <returns>A new <see cref="Pagination"/> instance</returns>
|
||||
public static implicit operator Pagination(int limit) => new(limit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information about how a query should be sorted. What factor should decide the sort and in which order.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">For witch type this sort applies</typeparam>
|
||||
public readonly struct Sort<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The sort key. This member will be used to sort the results.
|
||||
/// </summary>
|
||||
public Expression<Func<T, object>> Key { get; }
|
||||
/// <summary>
|
||||
/// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order.
|
||||
/// </summary>
|
||||
public bool Descendant { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Sort{T}"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="key">The sort key given. It is assigned to <see cref="Key"/>.</param>
|
||||
/// <param name="descendant">Should this be in descendant order? The default is false.</param>
|
||||
/// <exception cref="ArgumentException">If the given key is not a member.</exception>
|
||||
public Sort(Expression<Func<T, object>> key, bool descendant = false)
|
||||
{
|
||||
Key = key;
|
||||
Descendant = descendant;
|
||||
|
||||
if (!Utility.IsPropertyExpression(Key))
|
||||
throw new ArgumentException("The given sort key is not valid.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Sort{T}"/> instance from a key's name (case insensitive).
|
||||
/// </summary>
|
||||
/// <param name="sortBy">A key name with an optional order specifier. Format: "key:asc", "key:desc" or "key".</param>
|
||||
/// <exception cref="ArgumentException">An invalid key or sort specifier as been given.</exception>
|
||||
public Sort(string sortBy)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sortBy))
|
||||
{
|
||||
Key = null;
|
||||
Descendant = false;
|
||||
return;
|
||||
}
|
||||
|
||||
string key = sortBy.Contains(':') ? sortBy[..sortBy.IndexOf(':')] : sortBy;
|
||||
string order = sortBy.Contains(':') ? sortBy[(sortBy.IndexOf(':') + 1)..] : null;
|
||||
|
||||
ParameterExpression param = Expression.Parameter(typeof(T), "x");
|
||||
MemberExpression property = Expression.Property(param, key);
|
||||
Key = property.Type.IsValueType
|
||||
? Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param)
|
||||
: Expression.Lambda<Func<T, object>>(property, param);
|
||||
|
||||
Descendant = order switch
|
||||
{
|
||||
"desc" => true,
|
||||
"asc" => false,
|
||||
null => false,
|
||||
_ => throw new ArgumentException($"The sort order, if set, should be :asc or :desc but it was :{order}.")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A base class for repositories. Every service implementing this will be handled by the <see cref="ILibraryManager"/>.
|
||||
/// </summary>
|
||||
public interface IBaseRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// The type for witch this repository is responsible or null if non applicable.
|
||||
/// </summary>
|
||||
Type RepositoryType { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A common repository for every resources.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The resource's type that this repository manage.</typeparam>
|
||||
public interface IRepository<T> : IBaseRepository where T : class, IResource
|
||||
public interface IRepository<T> : IBaseRepository
|
||||
where T : class, IResource
|
||||
{
|
||||
/// <summary>
|
||||
/// Get a resource from it's ID.
|
||||
@ -131,6 +42,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemNotNull]
|
||||
Task<T> Get(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Get a resource from it's slug.
|
||||
/// </summary>
|
||||
@ -139,6 +51,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemNotNull]
|
||||
Task<T> Get(string slug);
|
||||
|
||||
/// <summary>
|
||||
/// Get the first resource that match the predicate.
|
||||
/// </summary>
|
||||
@ -147,7 +60,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemNotNull]
|
||||
Task<T> Get(Expression<Func<T, bool>> where);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a resource from it's ID or null if it is not found.
|
||||
/// </summary>
|
||||
@ -155,6 +68,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<T> GetOrDefault(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Get a resource from it's slug or null if it is not found.
|
||||
/// </summary>
|
||||
@ -162,6 +76,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<T> GetOrDefault(string slug);
|
||||
|
||||
/// <summary>
|
||||
/// Get the first resource that match the predicate or null if it is not found.
|
||||
/// </summary>
|
||||
@ -169,7 +84,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The resource found</returns>
|
||||
[ItemCanBeNull]
|
||||
Task<T> GetOrDefault(Expression<Func<T, bool>> where);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Search for resources.
|
||||
/// </summary>
|
||||
@ -177,7 +92,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>A list of resources found</returns>
|
||||
[ItemNotNull]
|
||||
Task<ICollection<T>> Search(string query);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get every resources that match all filters
|
||||
/// </summary>
|
||||
@ -186,9 +101,10 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="limit">How pagination should be done (where to start and how many to return)</param>
|
||||
/// <returns>A list of resources that match every filters</returns>
|
||||
[ItemNotNull]
|
||||
Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
|
||||
Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
|
||||
Sort<T> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get every resources that match all filters
|
||||
/// </summary>
|
||||
@ -208,16 +124,15 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="where">A filter predicate</param>
|
||||
/// <returns>How many resources matched that filter</returns>
|
||||
Task<int> GetCount(Expression<Func<T, bool>> where = null);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource.
|
||||
/// </summary>
|
||||
/// <param name="obj">The item to register</param>
|
||||
/// <returns>The resource registers and completed by database's information (related items & so on)</returns>
|
||||
/// <returns>The resource registers and completed by database's information (related items and so on)</returns>
|
||||
[ItemNotNull]
|
||||
Task<T> Create([NotNull] T obj);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new resource if it does not exist already. If it does, the existing value is returned instead.
|
||||
/// </summary>
|
||||
@ -225,44 +140,61 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The newly created item or the existing value if it existed.</returns>
|
||||
[ItemNotNull]
|
||||
Task<T> CreateIfNotExists([NotNull] T obj);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Edit a resource
|
||||
/// </summary>
|
||||
/// <param name="edited">The resource 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="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The resource edited and completed by database's information (related items & so on)</returns>
|
||||
/// <returns>The resource edited and completed by database's information (related items and so on)</returns>
|
||||
[ItemNotNull]
|
||||
Task<T> Edit([NotNull] T edited, bool resetOld);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Delete a resource by it's ID
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the resource</param>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task Delete(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a resource by it's slug
|
||||
/// </summary>
|
||||
/// <param name="slug">The slug of the resource</param>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task Delete(string slug);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a resource
|
||||
/// </summary>
|
||||
/// <param name="obj">The resource to delete</param>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task Delete([NotNull] T obj);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Delete all resources that match the predicate.
|
||||
/// </summary>
|
||||
/// <param name="where">A predicate to filter resources to delete. Every resource that match this will be deleted.</param>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task DeleteAll([NotNull] Expression<Func<T, bool>> where);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A base class for repositories. Every service implementing this will be handled by the <see cref="ILibraryManager"/>.
|
||||
/// </summary>
|
||||
public interface IBaseRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// The type for witch this repository is responsible or null if non applicable.
|
||||
/// </summary>
|
||||
Type RepositoryType { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A repository to handle shows.
|
||||
/// </summary>
|
||||
@ -275,6 +207,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="showID">The ID of the show</param>
|
||||
/// <param name="libraryID">The ID of the library (optional)</param>
|
||||
/// <param name="collectionID">The ID of the collection (optional)</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task AddShowLink(int showID, int? libraryID, int? collectionID);
|
||||
|
||||
/// <summary>
|
||||
@ -299,7 +232,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The season found</returns>
|
||||
Task<Season> Get(int showID, int seasonNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a season from it's show slug and it's seasonNumber
|
||||
/// </summary>
|
||||
@ -308,7 +241,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The season found</returns>
|
||||
Task<Season> Get(string showSlug, int seasonNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a season from it's showID and it's seasonNumber or null if it is not found.
|
||||
/// </summary>
|
||||
@ -316,7 +249,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="seasonNumber">The season's number</param>
|
||||
/// <returns>The season found</returns>
|
||||
Task<Season> GetOrDefault(int showID, int seasonNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a season from it's show slug and it's seasonNumber or null if it is not found.
|
||||
/// </summary>
|
||||
@ -325,7 +258,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <returns>The season found</returns>
|
||||
Task<Season> GetOrDefault(string showSlug, int seasonNumber);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The repository to handle episodes
|
||||
/// </summary>
|
||||
@ -340,6 +273,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <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>
|
||||
/// Get a episode from it's show slug, it's seasonNumber and it's episode number.
|
||||
/// </summary>
|
||||
@ -358,6 +292,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="episodeNumber">The episode's number</param>
|
||||
/// <returns>The episode found</returns>
|
||||
Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Get a episode from it's show slug, it's seasonNumber and it's episode number or null if it is not found.
|
||||
/// </summary>
|
||||
@ -366,7 +301,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="episodeNumber">The episode's number</param>
|
||||
/// <returns>The episode found</returns>
|
||||
Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a episode from it's showID and it's absolute number.
|
||||
/// </summary>
|
||||
@ -375,6 +310,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The episode found</returns>
|
||||
Task<Episode> GetAbsolute(int showID, int absoluteNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Get a episode from it's showID and it's absolute number.
|
||||
/// </summary>
|
||||
@ -389,7 +325,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// A repository to handle tracks
|
||||
/// </summary>
|
||||
public interface ITrackRepository : IRepository<Track> { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A repository to handle libraries.
|
||||
/// </summary>
|
||||
@ -405,13 +341,14 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the library</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort information (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
public Task<ICollection<LibraryItem>> GetFromLibrary(int id,
|
||||
Expression<Func<LibraryItem, bool>> where = null,
|
||||
Sort<LibraryItem> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper around shows or collections) from a library.
|
||||
/// </summary>
|
||||
@ -425,19 +362,20 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<LibraryItem, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromLibrary(id, where, new Sort<LibraryItem>(sort), limit);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper around shows or collections) from a library.
|
||||
/// </summary>
|
||||
/// <param name="slug">The slug of the library</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort information (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
public Task<ICollection<LibraryItem>> GetFromLibrary(string slug,
|
||||
Expression<Func<LibraryItem, bool>> where = null,
|
||||
Sort<LibraryItem> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get items (A wrapper around shows or collections) from a library.
|
||||
/// </summary>
|
||||
@ -451,18 +389,18 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<LibraryItem, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromLibrary(slug, where, new Sort<LibraryItem>(sort), limit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A repository for collections
|
||||
/// </summary>
|
||||
public interface ICollectionRepository : IRepository<Collection> { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A repository for genres.
|
||||
/// </summary>
|
||||
public interface IGenreRepository : IRepository<Genre> { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A repository for studios.
|
||||
/// </summary>
|
||||
@ -478,13 +416,14 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// </summary>
|
||||
/// <param name="showID">The ID of the show</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort information (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetFromShow(int showID,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
@ -498,19 +437,20 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromShow(showID, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
/// <param name="showSlug">The slug of the show</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort information (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetFromShow(string showSlug,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a show.
|
||||
/// </summary>
|
||||
@ -524,19 +464,20 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the person</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort information (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetFromPeople(int id,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
@ -550,19 +491,20 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Expression<Func<PeopleRole, object>> sort,
|
||||
Pagination limit = default
|
||||
) => GetFromPeople(id, where, new Sort<PeopleRole>(sort), limit);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
/// <param name="slug">The slug of the person</param>
|
||||
/// <param name="where">A filter function</param>
|
||||
/// <param name="sort">Sort information (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">How many items to return and where to start</param>
|
||||
/// <returns>A list of items that match every filters</returns>
|
||||
Task<ICollection<PeopleRole>> GetFromPeople(string slug,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Expression<Func<PeopleRole, bool>> where = null,
|
||||
Sort<PeopleRole> sort = default,
|
||||
Pagination limit = default);
|
||||
|
||||
/// <summary>
|
||||
/// Get people's roles from a person.
|
||||
/// </summary>
|
||||
@ -587,11 +529,11 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// Get a list of external ids that match all filters
|
||||
/// </summary>
|
||||
/// <param name="where">A predicate to add arbitrary filter</param>
|
||||
/// <param name="sort">Sort information (sort order & sort by)</param>
|
||||
/// <param name="sort">Sort information (sort order and sort by)</param>
|
||||
/// <param name="limit">Pagination information (where to start and how many to get)</param>
|
||||
/// <typeparam name="T">The type of metadata to retrieve</typeparam>
|
||||
/// <returns>A filtered list of external ids.</returns>
|
||||
Task<ICollection<MetadataID>> GetMetadataID<T>(Expression<Func<MetadataID, bool>> where = null,
|
||||
Task<ICollection<MetadataID>> GetMetadataID<T>(Expression<Func<MetadataID, bool>> where = null,
|
||||
Sort<MetadataID> sort = default,
|
||||
Pagination limit = default)
|
||||
where T : class, IMetadata;
|
||||
@ -602,16 +544,18 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="where">A predicate to add arbitrary filter</param>
|
||||
/// <param name="sort">A sort by expression</param>
|
||||
/// <param name="limit">Pagination information (where to start and how many to get)</param>
|
||||
/// <typeparam name="T">The type of metadata to retrieve</typeparam>
|
||||
/// <returns>A filtered list of external ids.</returns>
|
||||
Task<ICollection<MetadataID>> GetMetadataID<T>([Optional] Expression<Func<MetadataID, bool>> where,
|
||||
Expression<Func<MetadataID, object>> sort,
|
||||
Pagination limit = default
|
||||
) where T : class, IMetadata
|
||||
)
|
||||
where T : class, IMetadata
|
||||
=> GetMetadataID<T>(where, new Sort<MetadataID>(sort), limit);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A repository to handle users.
|
||||
/// </summary>
|
||||
public interface IUserRepository : IRepository<User> {}
|
||||
public interface IUserRepository : IRepository<User> { }
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -9,153 +27,6 @@ using Kyoo.Abstractions.Models.Exceptions;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// A single task parameter. This struct contains metadata to display and utility functions to get them in the task.
|
||||
/// </summary>
|
||||
/// <remarks>This struct will be used to generate the swagger documentation of the task.</remarks>
|
||||
public record TaskParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of this parameter.
|
||||
/// </summary>
|
||||
public string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The description of this parameter.
|
||||
/// </summary>
|
||||
public string Description { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of this parameter.
|
||||
/// </summary>
|
||||
public Type Type { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Is this parameter required or can it be ignored?
|
||||
/// </summary>
|
||||
public bool IsRequired { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The default value of this object.
|
||||
/// </summary>
|
||||
public object DefaultValue { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the parameter.
|
||||
/// </summary>
|
||||
private object Value { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new task parameter.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter</param>
|
||||
/// <param name="description">The description of the parameter</param>
|
||||
/// <typeparam name="T">The type of the parameter.</typeparam>
|
||||
/// <returns>A new task parameter.</returns>
|
||||
public static TaskParameter Create<T>(string name, string description)
|
||||
{
|
||||
return new TaskParameter
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
Type = typeof(T)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new required task parameter.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter</param>
|
||||
/// <param name="description">The description of the parameter</param>
|
||||
/// <typeparam name="T">The type of the parameter.</typeparam>
|
||||
/// <returns>A new task parameter.</returns>
|
||||
public static TaskParameter CreateRequired<T>(string name, string description)
|
||||
{
|
||||
return new TaskParameter
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
Type = typeof(T),
|
||||
IsRequired = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a parameter's value to give to a task.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter</param>
|
||||
/// <param name="value">The value of the parameter. It's type will be used as parameter's type.</param>
|
||||
/// <typeparam name="T">The type of the parameter</typeparam>
|
||||
/// <returns>A TaskParameter that can be used as value.</returns>
|
||||
public static TaskParameter CreateValue<T>(string name, T value)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
Name = name,
|
||||
Type = typeof(T),
|
||||
Value = value
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a parameter's value for the current parameter.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to use</param>
|
||||
/// <returns>A new parameter's value for this current parameter</returns>
|
||||
public TaskParameter CreateValue(object value)
|
||||
{
|
||||
return this with {Value = value};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of this parameter. If the value is of the wrong type, it will be converted.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of this parameter</typeparam>
|
||||
/// <returns>The value of this parameter.</returns>
|
||||
public T As<T>()
|
||||
{
|
||||
if (typeof(T) == typeof(object))
|
||||
return (T)Value;
|
||||
|
||||
if (Value is IResource resource)
|
||||
{
|
||||
if (typeof(T) == typeof(string))
|
||||
return (T)(object)resource.Slug;
|
||||
if (typeof(T) == typeof(int))
|
||||
return (T)(object)resource.ID;
|
||||
}
|
||||
|
||||
return (T)Convert.ChangeType(Value, typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A parameters container implementing an indexer to allow simple usage of parameters.
|
||||
/// </summary>
|
||||
public class TaskParameters : List<TaskParameter>
|
||||
{
|
||||
/// <summary>
|
||||
/// An indexer that return the parameter with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the task (case sensitive)</param>
|
||||
public TaskParameter this[string name] => this.FirstOrDefault(x => x.Name == name);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new, empty, <see cref="TaskParameters"/>
|
||||
/// </summary>
|
||||
public TaskParameters() {}
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="TaskParameters"/> with an initial parameters content
|
||||
/// </summary>
|
||||
/// <param name="parameters">The list of parameters</param>
|
||||
public TaskParameters(IEnumerable<TaskParameter> parameters)
|
||||
{
|
||||
AddRange(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A common interface that tasks should implement.
|
||||
/// </summary>
|
||||
@ -168,7 +39,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// All parameters that this task as. Every one of them will be given to the run function with a value.
|
||||
/// </returns>
|
||||
public TaskParameters GetParameters();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Start this task.
|
||||
/// </summary>
|
||||
@ -187,8 +58,155 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// This exception allow the task to display a failure message to the end user while others exceptions
|
||||
/// will be displayed as unhandled exceptions and display a stack trace.
|
||||
/// </exception>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public Task Run([NotNull] TaskParameters arguments,
|
||||
[NotNull] IProgress<float> progress,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A single task parameter. This struct contains metadata to display and utility functions to get them in the task.
|
||||
/// </summary>
|
||||
/// <remarks>This struct will be used to generate the swagger documentation of the task.</remarks>
|
||||
public record TaskParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of this parameter.
|
||||
/// </summary>
|
||||
public string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The description of this parameter.
|
||||
/// </summary>
|
||||
public string Description { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of this parameter.
|
||||
/// </summary>
|
||||
public Type Type { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Is this parameter required or can it be ignored?
|
||||
/// </summary>
|
||||
public bool IsRequired { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The default value of this object.
|
||||
/// </summary>
|
||||
public object DefaultValue { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the parameter.
|
||||
/// </summary>
|
||||
private object _Value { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new task parameter.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter</param>
|
||||
/// <param name="description">The description of the parameter</param>
|
||||
/// <typeparam name="T">The type of the parameter.</typeparam>
|
||||
/// <returns>A new task parameter.</returns>
|
||||
public static TaskParameter Create<T>(string name, string description)
|
||||
{
|
||||
return new TaskParameter
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
Type = typeof(T)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new required task parameter.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter</param>
|
||||
/// <param name="description">The description of the parameter</param>
|
||||
/// <typeparam name="T">The type of the parameter.</typeparam>
|
||||
/// <returns>A new task parameter.</returns>
|
||||
public static TaskParameter CreateRequired<T>(string name, string description)
|
||||
{
|
||||
return new TaskParameter
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
Type = typeof(T),
|
||||
IsRequired = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a parameter's value to give to a task.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the parameter</param>
|
||||
/// <param name="value">The value of the parameter. It's type will be used as parameter's type.</param>
|
||||
/// <typeparam name="T">The type of the parameter</typeparam>
|
||||
/// <returns>A TaskParameter that can be used as value.</returns>
|
||||
public static TaskParameter CreateValue<T>(string name, T value)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
Name = name,
|
||||
Type = typeof(T),
|
||||
_Value = value
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a parameter's value for the current parameter.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to use</param>
|
||||
/// <returns>A new parameter's value for this current parameter</returns>
|
||||
public TaskParameter CreateValue(object value)
|
||||
{
|
||||
return this with { _Value = value };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of this parameter. If the value is of the wrong type, it will be converted.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of this parameter</typeparam>
|
||||
/// <returns>The value of this parameter.</returns>
|
||||
public T As<T>()
|
||||
{
|
||||
if (typeof(T) == typeof(object))
|
||||
return (T)_Value;
|
||||
|
||||
if (_Value is IResource resource)
|
||||
{
|
||||
if (typeof(T) == typeof(string))
|
||||
return (T)(object)resource.Slug;
|
||||
if (typeof(T) == typeof(int))
|
||||
return (T)(object)resource.ID;
|
||||
}
|
||||
|
||||
return (T)Convert.ChangeType(_Value, typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A parameters container implementing an indexer to allow simple usage of parameters.
|
||||
/// </summary>
|
||||
public class TaskParameters : List<TaskParameter>
|
||||
{
|
||||
/// <summary>
|
||||
/// An indexer that return the parameter with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the task (case sensitive)</param>
|
||||
public TaskParameter this[string name] => this.FirstOrDefault(x => x.Name == name);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new, empty, <see cref="TaskParameters"/>
|
||||
/// </summary>
|
||||
public TaskParameters() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="TaskParameters"/> with an initial parameters content.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The list of parameters</param>
|
||||
public TaskParameters(IEnumerable<TaskParameter> parameters)
|
||||
{
|
||||
AddRange(parameters);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
@ -35,7 +53,7 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <exception cref="ItemNotFoundException">
|
||||
/// The task could not be found.
|
||||
/// </exception>
|
||||
void StartTask(string taskSlug,
|
||||
void StartTask(string taskSlug,
|
||||
[NotNull] IProgress<float> progress,
|
||||
Dictionary<string, object> arguments = null,
|
||||
CancellationToken? cancellationToken = null);
|
||||
@ -66,17 +84,17 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Dictionary<string, object> arguments = null,
|
||||
CancellationToken? cancellationToken = null)
|
||||
where T : ITask;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get all currently running tasks
|
||||
/// </summary>
|
||||
/// <returns>A list of currently running tasks.</returns>
|
||||
ICollection<(TaskMetadataAttribute, ITask)> GetRunningTasks();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get all available tasks
|
||||
/// </summary>
|
||||
/// <returns>A list of every tasks that this instance know.</returns>
|
||||
ICollection<TaskMetadataAttribute> GetAllTasks();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,24 @@
|
||||
using Kyoo.Abstractions.Models;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Kyoo.Abstractions.Models;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
@ -24,7 +42,6 @@ namespace Kyoo.Abstractions.Controllers
|
||||
Task<bool> DownloadImages<T>([NotNull] T item, bool alwaysDownload = false)
|
||||
where T : IThumbnails;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the local path of an image of the given item.
|
||||
/// </summary>
|
32
src/Kyoo.Abstractions/Controllers/ITranscoder.cs
Normal file
32
src/Kyoo.Abstractions/Controllers/ITranscoder.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Models;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
public interface ITranscoder
|
||||
{
|
||||
Task<Track[]> ExtractInfos(Episode episode, bool reextract);
|
||||
|
||||
Task<string> Transmux(Episode episode);
|
||||
|
||||
Task<string> Transcode(Episode episode);
|
||||
}
|
||||
}
|
269
src/Kyoo.Abstractions/Controllers/StartupAction.cs
Normal file
269
src/Kyoo.Abstractions/Controllers/StartupAction.cs
Normal file
@ -0,0 +1,269 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of constant priorities used for <see cref="IStartupAction"/>'s <see cref="IStartupAction.Priority"/>.
|
||||
/// It also contains helper methods for creating new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name",
|
||||
Justification = "StartupAction is nested and the name SA is short to improve readability in plugin's startup.")]
|
||||
public static class SA
|
||||
{
|
||||
/// <summary>
|
||||
/// The highest predefined priority existing for <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
public const int Before = 5000;
|
||||
|
||||
/// <summary>
|
||||
/// Items defining routing (see IApplicationBuilder.UseRouting use this priority.
|
||||
/// </summary>
|
||||
public const int Routing = 4000;
|
||||
|
||||
/// <summary>
|
||||
/// Actions defining new static files router use this priority.
|
||||
/// </summary>
|
||||
public const int StaticFiles = 3000;
|
||||
|
||||
/// <summary>
|
||||
/// Actions calling IApplicationBuilder.UseAuthentication use this priority.
|
||||
/// </summary>
|
||||
public const int Authentication = 2000;
|
||||
|
||||
/// <summary>
|
||||
/// Actions calling IApplicationBuilder.UseAuthorization use this priority.
|
||||
/// </summary>
|
||||
public const int Authorization = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Action adding endpoint should use this priority (with a negative modificator if there is a catchall).
|
||||
/// </summary>
|
||||
public const int Endpoint = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The lowest predefined priority existing for <see cref="StartupAction"/>.
|
||||
/// It should run after all other actions.
|
||||
/// </summary>
|
||||
public const int After = -1000;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to run</param>
|
||||
/// <param name="priority">The priority of the new action</param>
|
||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||
public static StartupAction New(Action action, int priority)
|
||||
=> new(action, priority);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to run</param>
|
||||
/// <param name="priority">The priority of the new action</param>
|
||||
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||
public static StartupAction<T> New<T>(Action<T> action, int priority)
|
||||
=> new(action, priority);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to run</param>
|
||||
/// <param name="priority">The priority of the new action</param>
|
||||
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
||||
/// <typeparam name="T2">A second dependency that this action will use.</typeparam>
|
||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||
public static StartupAction<T, T2> New<T, T2>(Action<T, T2> action, int priority)
|
||||
=> new(action, priority);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to run</param>
|
||||
/// <param name="priority">The priority of the new action</param>
|
||||
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
||||
/// <typeparam name="T2">A second dependency that this action will use.</typeparam>
|
||||
/// <typeparam name="T3">A third dependency that this action will use.</typeparam>
|
||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||
public static StartupAction<T, T2, T3> New<T, T2, T3>(Action<T, T2, T3> action, int priority)
|
||||
=> new(action, priority);
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IStartupAction"/> with no dependencies.
|
||||
/// </summary>
|
||||
public class StartupAction : IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The action to execute at startup.
|
||||
/// </summary>
|
||||
private readonly Action _action;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on startup.</param>
|
||||
/// <param name="priority">The priority of this action (see <see cref="Priority"/>).</param>
|
||||
public StartupAction(Action action, int priority)
|
||||
{
|
||||
_action = action;
|
||||
Priority = priority;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IServiceProvider provider)
|
||||
{
|
||||
_action.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IStartupAction"/> with one dependencies.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dependency to use.</typeparam>
|
||||
public class StartupAction<T> : IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The action to execute at startup.
|
||||
/// </summary>
|
||||
private readonly Action<T> _action;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on startup.</param>
|
||||
/// <param name="priority">The priority of this action (see <see cref="Priority"/>).</param>
|
||||
public StartupAction(Action<T> action, int priority)
|
||||
{
|
||||
_action = action;
|
||||
Priority = priority;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IServiceProvider provider)
|
||||
{
|
||||
_action.Invoke(provider.GetRequiredService<T>());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IStartupAction"/> with two dependencies.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dependency to use.</typeparam>
|
||||
/// <typeparam name="T2">The second dependency to use.</typeparam>
|
||||
public class StartupAction<T, T2> : IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The action to execute at startup.
|
||||
/// </summary>
|
||||
private readonly Action<T, T2> _action;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction{T, T2}"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on startup.</param>
|
||||
/// <param name="priority">The priority of this action (see <see cref="Priority"/>).</param>
|
||||
public StartupAction(Action<T, T2> action, int priority)
|
||||
{
|
||||
_action = action;
|
||||
Priority = priority;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IServiceProvider provider)
|
||||
{
|
||||
_action.Invoke(
|
||||
provider.GetRequiredService<T>(),
|
||||
provider.GetRequiredService<T2>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IStartupAction"/> with three dependencies.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dependency to use.</typeparam>
|
||||
/// <typeparam name="T2">The second dependency to use.</typeparam>
|
||||
/// <typeparam name="T3">The third dependency to use.</typeparam>
|
||||
public class StartupAction<T, T2, T3> : IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The action to execute at startup.
|
||||
/// </summary>
|
||||
private readonly Action<T, T2, T3> _action;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StartupAction{T, T2, T3}"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on startup.</param>
|
||||
/// <param name="priority">The priority of this action (see <see cref="Priority"/>).</param>
|
||||
public StartupAction(Action<T, T2, T3> action, int priority)
|
||||
{
|
||||
_action = action;
|
||||
Priority = priority;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IServiceProvider provider)
|
||||
{
|
||||
_action.Invoke(
|
||||
provider.GetRequiredService<T>(),
|
||||
provider.GetRequiredService<T2>(),
|
||||
provider.GetRequiredService<T3>()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An action executed on kyoo's startup to initialize the asp-net container.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the base interface, see <see cref="SA.StartupAction"/> for a simpler use of this.
|
||||
/// </remarks>
|
||||
public interface IStartupAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The priority of this action. The actions will be executed on descending priority order.
|
||||
/// If two actions have the same priority, their order is undefined.
|
||||
/// </summary>
|
||||
int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Run this action to configure the container, a service provider containing all services can be used.
|
||||
/// </summary>
|
||||
/// <param name="provider">The service provider containing all services can be used.</param>
|
||||
void Run(IServiceProvider provider);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
28
src/Kyoo.Abstractions/Models/Attributes/ComputedAttribute.cs
Normal file
28
src/Kyoo.Abstractions/Models/Attributes/ComputedAttribute.cs
Normal file
@ -0,0 +1,28 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// An attribute to inform that the property is computed automatically and can't be assigned manually.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class ComputedAttribute : NotMergeableAttribute { }
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// The targeted relation can be edited via calls to the repository's <see cref="IRepository{T}.Edit"/> method.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class EditableRelationAttribute : Attribute { }
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
@ -20,13 +38,12 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
/// If multiples files with the same schemes exists, an exception will be thrown.
|
||||
/// </remarks>
|
||||
public string[] Scheme { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <c>true</c> if the scheme should be removed from the path before calling
|
||||
/// methods of this <see cref="IFileSystem"/>, <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
public bool StripScheme { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="FileSystemMetadataAttribute"/> using the specified schemes.
|
||||
@ -36,7 +53,7 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
Scheme = schemes;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="FileSystemMetadataAttribute"/> using a dictionary of metadata.
|
||||
/// </summary>
|
||||
@ -50,4 +67,4 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
StripScheme = (bool)metadata[nameof(StripScheme)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,26 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// The targeted relation can be edited via calls to the repository's <see cref="IRepository{T}.Edit"/> method.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class EditableRelationAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// The targeted relation can be loaded via a call to <see cref="ILibraryManager.Load"/>.
|
||||
/// </summary>
|
||||
@ -19,11 +31,11 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
/// The name of the field containing the related resource's ID.
|
||||
/// </summary>
|
||||
public string RelationID { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="LoadableRelationAttribute"/>.
|
||||
/// </summary>
|
||||
public LoadableRelationAttribute() {}
|
||||
public LoadableRelationAttribute() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="LoadableRelationAttribute"/> with a baking relationID field.
|
||||
@ -34,4 +46,4 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
RelationID = relationID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Specify that a property can't be merged.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class NotMergeableAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// An interface with a method called when this object is merged.
|
||||
/// </summary>
|
||||
public interface IOnMerge
|
||||
{
|
||||
/// <summary>
|
||||
/// This function is called after the object has been merged.
|
||||
/// </summary>
|
||||
/// <param name="merged">The object that has been merged with this.</param>
|
||||
void OnMerge(object merged);
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Permissions
|
||||
{
|
||||
/// <summary>
|
||||
/// Specify one part of a permissions needed for the API (the kind or the type).
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
||||
public class PartialPermissionAttribute : Attribute, IFilterFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The needed permission type.
|
||||
/// </summary>
|
||||
public string Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The needed permission kind.
|
||||
/// </summary>
|
||||
public Kind Kind { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ask a permission to run an action.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// With this attribute, you can only specify a type or a kind.
|
||||
/// To have a valid permission attribute, you must specify the kind and the permission using two attributes.
|
||||
/// Those attributes can be dispatched at different places (one on the class, one on the method for example).
|
||||
/// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will
|
||||
/// lead to unspecified behaviors.
|
||||
/// </remarks>
|
||||
/// <param name="type">
|
||||
/// The type of the action
|
||||
/// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
|
||||
/// </param>
|
||||
public PartialPermissionAttribute(string type)
|
||||
{
|
||||
if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
|
||||
type = type[..^3];
|
||||
Type = type.ToLower();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ask a permission to run an action.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// With this attribute, you can only specify a type or a kind.
|
||||
/// To have a valid permission attribute, you must specify the kind and the permission using two attributes.
|
||||
/// Those attributes can be dispatched at different places (one on the class, one on the method for example).
|
||||
/// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will
|
||||
/// lead to unspecified behaviors.
|
||||
/// </remarks>
|
||||
/// <param name="permission">The kind of permission needed.</param>
|
||||
public PartialPermissionAttribute(Kind permission)
|
||||
{
|
||||
Kind = permission;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||
{
|
||||
return serviceProvider.GetRequiredService<IPermissionValidator>().Create(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReusable => true;
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Permissions
|
||||
{
|
||||
/// <summary>
|
||||
/// The kind of permission needed.
|
||||
/// </summary>
|
||||
public enum Kind
|
||||
{
|
||||
/// <summary>
|
||||
/// Allow the user to read for this kind of data.
|
||||
/// </summary>
|
||||
Read,
|
||||
|
||||
/// <summary>
|
||||
/// Allow the user to write for this kind of data.
|
||||
/// </summary>
|
||||
Write,
|
||||
|
||||
/// <summary>
|
||||
/// Allow the user to create this kind of data.
|
||||
/// </summary>
|
||||
Create,
|
||||
|
||||
/// <summary>
|
||||
/// Allow the user to delete this kind od data.
|
||||
/// </summary>
|
||||
Delete
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The group of the permission.
|
||||
/// </summary>
|
||||
public enum Group
|
||||
{
|
||||
/// <summary>
|
||||
/// Allow all operations on basic items types.
|
||||
/// </summary>
|
||||
Overall,
|
||||
|
||||
/// <summary>
|
||||
/// Allow operation on sensitive items like libraries path, configurations and so on.
|
||||
/// </summary>
|
||||
Admin
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify permissions needed for the API.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
||||
public class PermissionAttribute : Attribute, IFilterFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The needed permission as string.
|
||||
/// </summary>
|
||||
public string Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The needed permission kind.
|
||||
/// </summary>
|
||||
public Kind Kind { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The group of this permission.
|
||||
/// </summary>
|
||||
public Group Group { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ask a permission to run an action.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// The type of the action
|
||||
/// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
|
||||
/// </param>
|
||||
/// <param name="permission">The kind of permission needed.</param>
|
||||
/// <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))
|
||||
type = type[..^3];
|
||||
Type = type.ToLower();
|
||||
Kind = permission;
|
||||
Group = group;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||
{
|
||||
return serviceProvider.GetRequiredService<IPermissionValidator>().Create(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReusable => true;
|
||||
|
||||
/// <summary>
|
||||
/// Return this permission attribute as a string.
|
||||
/// </summary>
|
||||
/// <returns>The string representation.</returns>
|
||||
public string AsPermissionString()
|
||||
{
|
||||
return Type;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Remove a property from the deserialization pipeline. The user can't input value for this property.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class DeserializeIgnoreAttribute : Attribute { }
|
||||
}
|
@ -1,19 +1,25 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Remove an property from the serialization pipeline. It will simply be skipped.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class SerializeIgnoreAttribute : Attribute {}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a property from the deserialization pipeline. The user can't input value for this property.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class DeserializeIgnoreAttribute : Attribute {}
|
||||
|
||||
/// <summary>
|
||||
/// Change the way the field is serialized. It allow one to use a string format like formatting instead of the default value.
|
||||
/// This can be disabled for a request by setting the "internal" query string parameter to true.
|
||||
@ -25,7 +31,7 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
/// The format string to use.
|
||||
/// </summary>
|
||||
public string Format { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SerializeAsAttribute"/> with the selected format.
|
||||
/// </summary>
|
||||
@ -42,4 +48,4 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
Format = format;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Remove an property from the serialization pipeline. It will simply be skipped.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class SerializeIgnoreAttribute : Attribute { }
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
@ -16,12 +34,12 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
/// The slug of the task, used to start it.
|
||||
/// </summary>
|
||||
public string Slug { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of the task that will be displayed to the user.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A quick description of what this task will do.
|
||||
/// </summary>
|
||||
@ -31,18 +49,17 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
/// Should this task be automatically run at app startup?
|
||||
/// </summary>
|
||||
public bool RunOnStartup { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The priority of this task. Only used if <see cref="RunOnStartup"/> is true.
|
||||
/// It allow one to specify witch task will be started first as tasked are run on a Priority's descending order.
|
||||
/// </summary>
|
||||
public int Priority { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <c>true</c> if this task should not be displayed to the user, <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
public bool IsHidden { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TaskMetadataAttribute"/> with the given slug, name and description.
|
||||
@ -56,7 +73,7 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
Name = name;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TaskMetadataAttribute"/> using a dictionary of metadata.
|
||||
/// </summary>
|
||||
@ -74,4 +91,4 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
IsHidden = (bool)metadata[nameof(IsHidden)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <summary>
|
||||
@ -9,16 +27,16 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The start time of the chapter (in second from the start of the episode).
|
||||
/// </summary>
|
||||
public float StartTime { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The end time of the chapter (in second from the start of the episode)&.
|
||||
/// The end time of the chapter (in second from the start of the episode).
|
||||
/// </summary>
|
||||
public float EndTime { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of this chapter. This should be a human-readable name that could be presented to the user.
|
||||
/// There should be well-known chapters name for commonly used chapters.
|
||||
/// For example, use "Opening" for the introduction-song and "Credits" for the end chapter with credits.
|
||||
/// For example, use "Opening" for the introduction-song and "Credits" for the end chapter with credits.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
@ -35,4 +53,4 @@ namespace Kyoo.Abstractions.Models
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
@ -21,7 +39,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </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"/>
|
||||
@ -53,7 +70,6 @@ namespace Kyoo.Abstractions.Models
|
||||
new ConfigurationReference(path, type)
|
||||
};
|
||||
|
||||
|
||||
if (!type.IsClass || type.AssemblyQualifiedName?.StartsWith("System") == true)
|
||||
return ret;
|
||||
|
||||
@ -75,7 +91,7 @@ namespace Kyoo.Abstractions.Models
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return the list of configuration reference a type has.
|
||||
/// </summary>
|
||||
@ -89,10 +105,9 @@ namespace Kyoo.Abstractions.Models
|
||||
return CreateReference(path, typeof(T));
|
||||
}
|
||||
|
||||
|
||||
public static ConfigurationReference CreateUntyped(string path)
|
||||
{
|
||||
return new(path, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
@ -15,7 +33,7 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
public DuplicatedItemException()
|
||||
: base("Already exists in the database.")
|
||||
{ }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="DuplicatedItemException"/> with a custom message.
|
||||
/// </summary>
|
||||
@ -23,9 +41,9 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
public DuplicatedItemException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The serialization constructor
|
||||
/// The serialization constructor.
|
||||
/// </summary>
|
||||
/// <param name="info">Serialization infos</param>
|
||||
/// <param name="context">The serialization context</param>
|
||||
@ -33,4 +51,4 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
@ -15,18 +33,18 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
/// </summary>
|
||||
public IdentificationFailedException()
|
||||
: base("An identification failed.")
|
||||
{}
|
||||
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="IdentificationFailedException"/> with a custom message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to use.</param>
|
||||
public IdentificationFailedException(string message)
|
||||
: base(message)
|
||||
{}
|
||||
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// The serialization constructor
|
||||
/// The serialization constructor
|
||||
/// </summary>
|
||||
/// <param name="info">Serialization infos</param>
|
||||
/// <param name="context">The serialization context</param>
|
||||
@ -34,4 +52,4 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
@ -12,7 +30,7 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
/// <summary>
|
||||
/// Create a default <see cref="ItemNotFoundException"/> with no message.
|
||||
/// </summary>
|
||||
public ItemNotFoundException() {}
|
||||
public ItemNotFoundException() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="ItemNotFoundException"/> with a message
|
||||
@ -21,9 +39,9 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
public ItemNotFoundException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The serialization constructor
|
||||
/// The serialization constructor
|
||||
/// </summary>
|
||||
/// <param name="info">Serialization infos</param>
|
||||
/// <param name="context">The serialization context</param>
|
||||
@ -31,4 +49,4 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
@ -15,26 +33,26 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
/// </summary>
|
||||
public TaskFailedException()
|
||||
: base("A task failed.")
|
||||
{}
|
||||
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TaskFailedException"/> with a custom message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to use.</param>
|
||||
public TaskFailedException(string message)
|
||||
: base(message)
|
||||
{}
|
||||
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TaskFailedException"/> wrapping another exception.
|
||||
/// </summary>
|
||||
/// <param name="exception">The exception to wrap.</param>
|
||||
public TaskFailedException(Exception exception)
|
||||
: base(exception)
|
||||
{}
|
||||
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// The serialization constructor
|
||||
/// The serialization constructor
|
||||
/// </summary>
|
||||
/// <param name="info">Serialization infos</param>
|
||||
/// <param name="context">The serialization context</param>
|
||||
@ -42,4 +60,4 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
@ -10,11 +28,22 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </summary>
|
||||
public enum ItemType
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="LibraryItem"/> is a <see cref="Show"/>.
|
||||
/// </summary>
|
||||
Show,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="LibraryItem"/> is a Movie (a <see cref="Show"/> with <see cref="Models.Show.IsMovie"/> equals to true).
|
||||
/// </summary>
|
||||
Movie,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="LibraryItem"/> is a <see cref="Collection"/>.
|
||||
/// </summary>
|
||||
Collection
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A type union between <see cref="Show"/> and <see cref="Collection"/>.
|
||||
/// This is used to list content put inside a library.
|
||||
@ -23,30 +52,30 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The title of the show or collection.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The summary of the show or collection.
|
||||
/// </summary>
|
||||
public string Overview { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Is this show airing, not aired yet or finished? This is only applicable for shows.
|
||||
/// </summary>
|
||||
public Status? Status { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The date this show or collection started airing. It can be null if this is unknown.
|
||||
/// The date this show or collection started airing. It can be null if this is unknown.
|
||||
/// </summary>
|
||||
public DateTime? StartAir { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The date this show or collection finished airing.
|
||||
/// It must be after the <see cref="StartAir"/> but can be the same (example: for movies).
|
||||
@ -64,17 +93,16 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/{Type:l}/{Slug}/poster")]
|
||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The type of this item (ether a collection, a show or a movie).
|
||||
/// </summary>
|
||||
public ItemType Type { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new, empty <see cref="LibraryItem"/>.
|
||||
/// </summary>
|
||||
public LibraryItem() {}
|
||||
public LibraryItem() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="LibraryItem"/> from a show.
|
||||
@ -92,7 +120,7 @@ namespace Kyoo.Abstractions.Models
|
||||
Images = show.Images;
|
||||
Type = show.IsMovie ? ItemType.Movie : ItemType.Show;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="LibraryItem"/> from a collection
|
||||
/// </summary>
|
||||
@ -125,7 +153,7 @@ namespace Kyoo.Abstractions.Models
|
||||
Images = x.Images,
|
||||
Type = x.IsMovie ? ItemType.Movie : ItemType.Show
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// An expression to create a <see cref="LibraryItem"/> representing a collection.
|
||||
/// </summary>
|
||||
@ -142,4 +170,4 @@ namespace Kyoo.Abstractions.Models
|
||||
Type = ItemType.Collection
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
@ -9,6 +27,14 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </summary>
|
||||
public class MetadataID
|
||||
{
|
||||
/// <summary>
|
||||
/// The expression to retrieve the unique ID of a MetadataID. This is an aggregate of the two resources IDs.
|
||||
/// </summary>
|
||||
public static Expression<Func<MetadataID, object>> PrimaryKey
|
||||
{
|
||||
get { return x => new { First = x.ResourceID, Second = x.ProviderID }; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the resource which possess the metadata.
|
||||
/// </summary>
|
||||
@ -33,13 +59,5 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The URL of the resource on the external provider.
|
||||
/// </summary>
|
||||
public string Link { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The expression to retrieve the unique ID of a MetadataID. This is an aggregate of the two resources IDs.
|
||||
/// </summary>
|
||||
public static Expression<Func<MetadataID, object>> PrimaryKey
|
||||
{
|
||||
get { return x => new { First = x.ResourceID, Second = x.ProviderID }; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -9,18 +27,19 @@ namespace Kyoo.Abstractions.Models
|
||||
/// A page of resource that contains information about the pagination of resources.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of resource contained in this page.</typeparam>
|
||||
public class Page<T> where T : IResource
|
||||
public class Page<T>
|
||||
where T : IResource
|
||||
{
|
||||
/// <summary>
|
||||
/// The link of the current page.
|
||||
/// </summary>
|
||||
public Uri This { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The link of the first page.
|
||||
/// </summary>
|
||||
public Uri First { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The link of the next page.
|
||||
/// </summary>
|
||||
@ -30,13 +49,12 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The number of items in the current page.
|
||||
/// </summary>
|
||||
public int Count => Items.Count;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of items in the page.
|
||||
/// </summary>
|
||||
public ICollection<T> Items { get; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Page{T}"/>.
|
||||
/// </summary>
|
||||
@ -72,9 +90,9 @@ namespace Kyoo.Abstractions.Models
|
||||
query["afterID"] = items.Last().ID.ToString();
|
||||
Next = new Uri(url + query.ToQueryString());
|
||||
}
|
||||
|
||||
|
||||
query.Remove("afterID");
|
||||
First = new Uri(url + query.ToQueryString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <summary>
|
||||
@ -6,16 +24,16 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <remarks>
|
||||
/// This class is not serialized like other classes.
|
||||
/// Based on the <see cref="ForPeople"/> field, it is serialized like
|
||||
/// a show with two extra fields (<see cref="Role"/> and <see cref="Type"/>).
|
||||
/// a show with two extra fields (<see cref="Role"/> and <see cref="Type"/>).
|
||||
/// </remarks>
|
||||
public class PeopleRole : IResource
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug => ForPeople ? Show.Slug : People.Slug;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Should this role be used as a Show substitute (the value is <c>true</c>) or
|
||||
/// as a People substitute (the value is <c>false</c>).
|
||||
@ -26,30 +44,32 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The ID of the People playing the role.
|
||||
/// </summary>
|
||||
public int PeopleID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The people that played this role.
|
||||
/// </summary>
|
||||
public People People { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the Show where the People playing in.
|
||||
/// </summary>
|
||||
public int ShowID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The show where the People played in.
|
||||
/// </summary>
|
||||
public Show Show { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The type of work the person has done for the show.
|
||||
/// That can be something like "Actor", "Writer", "Music", "Voice Actor"...
|
||||
/// That can be something like "Actor", "Writer", "Music", "Voice Actor"...
|
||||
/// </summary>
|
||||
public string Type { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The role the People played.
|
||||
/// This is mostly used to inform witch character was played for actor and voice actors.
|
||||
/// This is mostly used to inform witch character was played for actor and voice actors.
|
||||
/// </summary>
|
||||
public string Role { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,22 @@
|
||||
using System;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
|
||||
@ -12,10 +30,10 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of this collection.
|
||||
/// </summary>
|
||||
@ -23,7 +41,7 @@ namespace Kyoo.Abstractions.Models
|
||||
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The path of this poster.
|
||||
/// By default, the http path for this poster is returned from the public API.
|
||||
@ -37,17 +55,17 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The description of this collection.
|
||||
/// </summary>
|
||||
public string Overview { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of shows contained in this collection.
|
||||
/// </summary>
|
||||
[LoadableRelation] public ICollection<Show> Shows { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of libraries that contains this collection.
|
||||
/// </summary>
|
||||
[LoadableRelation] public ICollection<Library> Libraries { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||
}
|
@ -1,4 +1,22 @@
|
||||
using System;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using JetBrains.Annotations;
|
||||
@ -22,15 +40,16 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
if (ShowSlug != null || Show != null)
|
||||
return GetSlug(ShowSlug ?? Show.Slug, SeasonNumber, EpisodeNumber, AbsoluteNumber);
|
||||
return ShowID != 0
|
||||
? GetSlug(ShowID.ToString(), SeasonNumber, EpisodeNumber, AbsoluteNumber)
|
||||
return ShowID != 0
|
||||
? GetSlug(ShowID.ToString(), SeasonNumber, EpisodeNumber, AbsoluteNumber)
|
||||
: null;
|
||||
}
|
||||
|
||||
[UsedImplicitly] [NotNull] private set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
|
||||
|
||||
Match match = Regex.Match(value, @"(?<show>.+)-s(?<season>\d+)e(?<episode>\d+)");
|
||||
|
||||
if (match.Success)
|
||||
@ -59,20 +78,22 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The slug of the Show that contain this episode. If this is not set, this episode is ill-formed.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public string ShowSlug { private get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the Show containing this episode.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public int ShowID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The show that contains this episode. This must be explicitly loaded via a call to <see cref="ILibraryManager.Load"/>.
|
||||
/// </summary>
|
||||
[LoadableRelation(nameof(ShowID))] public Show Show { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the Season containing this episode.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public int? SeasonID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The season that contains this episode.
|
||||
/// This must be explicitly loaded via a call to <see cref="ILibraryManager.Load"/>.
|
||||
@ -87,22 +108,22 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The season in witch this episode is in.
|
||||
/// </summary>
|
||||
public int? SeasonNumber { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The number of this episode in it's season.
|
||||
/// </summary>
|
||||
public int? EpisodeNumber { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season.
|
||||
/// </summary>
|
||||
public int? AbsoluteNumber { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The path of the video file for this episode. Any format supported by a <see cref="IFileSystem"/> is allowed.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public string Path { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
@ -114,17 +135,17 @@ namespace Kyoo.Abstractions.Models
|
||||
[SerializeAs("{HOST}/api/episodes/{Slug}/thumbnail")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Thumb => Images?.GetValueOrDefault(Models.Images.Thumbnail);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The title of this episode.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The overview of this episode.
|
||||
/// </summary>
|
||||
public string Overview { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The release date of this episode. It can be null if unknown.
|
||||
/// </summary>
|
||||
@ -137,7 +158,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The list of tracks this episode has. This lists video, audio and subtitles available.
|
||||
/// </summary>
|
||||
[EditableRelation] [LoadableRelation] public ICollection<Track> Tracks { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the slug of an episode.
|
||||
@ -157,8 +177,8 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </param>
|
||||
/// <returns>The slug corresponding to the given arguments</returns>
|
||||
/// <exception cref="ArgumentNullException">The given show slug was null.</exception>
|
||||
public static string GetSlug([NotNull] string showSlug,
|
||||
int? seasonNumber,
|
||||
public static string GetSlug([NotNull] string showSlug,
|
||||
int? seasonNumber,
|
||||
int? episodeNumber,
|
||||
int? absoluteNumber = null)
|
||||
{
|
@ -1,4 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
using Kyoo.Utils;
|
||||
|
||||
@ -11,15 +29,15 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of this genre.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of shows that have this genre.
|
||||
/// </summary>
|
||||
@ -28,11 +46,11 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <summary>
|
||||
/// Create a new, empty <see cref="Genre"/>.
|
||||
/// </summary>
|
||||
public Genre() {}
|
||||
|
||||
public Genre() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Genre"/> and specify it's <see cref="Name"/>.
|
||||
/// The <see cref="Slug"/> is automatically calculated from it's name.
|
||||
/// The <see cref="Slug"/> is automatically calculated from it's name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of this genre.</param>
|
||||
public Genre(string name)
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -14,7 +32,8 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <summary>
|
||||
/// The link to metadata providers that this show has. See <see cref="MetadataID"/> for more information.
|
||||
/// </summary>
|
||||
[EditableRelation] [LoadableRelation]
|
||||
[EditableRelation]
|
||||
[LoadableRelation]
|
||||
public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||
}
|
||||
|
||||
@ -25,7 +44,7 @@ namespace Kyoo.Abstractions.Models
|
||||
public static class MetadataExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve the internal provider's ID of an item using it's provider slug.
|
||||
/// Retrieve the internal provider's ID of an item using it's provider slug.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method will never return anything if the <see cref="IMetadata.ExternalIDs"/> are not loaded.
|
||||
@ -76,4 +95,4 @@ namespace Kyoo.Abstractions.Models
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
@ -12,10 +30,10 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You don't need to specify an ID manually when creating a new resource,
|
||||
/// this field is automatically assigned by the <see cref="IRepository{T}"/>.
|
||||
/// this field is automatically assigned by the <see cref="IRepository{T}"/>.
|
||||
/// </remarks>
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A human-readable identifier that can be used instead of an ID.
|
||||
/// A slug must be unique for a type of resource but it can be changed.
|
||||
@ -24,6 +42,6 @@ namespace Kyoo.Abstractions.Models
|
||||
/// There is no setter for a slug since it can be computed from other fields.
|
||||
/// For example, a season slug is {ShowSlug}-s{SeasonNumber}.
|
||||
/// </remarks>
|
||||
public string Slug { get; }
|
||||
public string Slug { get; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
|
||||
@ -16,7 +34,7 @@ namespace Kyoo.Abstractions.Models
|
||||
/// An arbitrary index should not be used, instead use indexes from <see cref="Models.Images"/>
|
||||
/// </remarks>
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
|
||||
// TODO remove Posters properties add them via the json serializer for every IThumbnails
|
||||
}
|
||||
|
||||
@ -46,4 +64,4 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </summary>
|
||||
public const int Trailer = 3;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
@ -10,15 +28,15 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of this library.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of paths that this library is responsible for. This is mainly used by the Scan task.
|
||||
/// </summary>
|
||||
@ -33,7 +51,7 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The list of shows in this library.
|
||||
/// </summary>
|
||||
[LoadableRelation] public ICollection<Show> Shows { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of collections in this library.
|
||||
/// </summary>
|
@ -1,25 +1,43 @@
|
||||
using System;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// An actor, voice actor, writer, animator, somebody who worked on a <see cref="Show"/>.
|
||||
/// An actor, voice actor, writer, animator, somebody who worked on a <see cref="Show"/>.
|
||||
/// </summary>
|
||||
public class People : IResource, IMetadata, IThumbnails
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of this person.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
@ -31,10 +49,10 @@ namespace Kyoo.Abstractions.Models
|
||||
[SerializeAs("{HOST}/api/people/{Slug}/poster")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of roles this person has played in. See <see cref="PeopleRole"/> for more information.
|
||||
/// </summary>
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
@ -14,15 +32,15 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of this provider.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public Dictionary<int, string> Images { get; set; }
|
||||
|
||||
@ -47,7 +65,7 @@ namespace Kyoo.Abstractions.Models
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Provider"/> and specify it's <see cref="Name"/>.
|
||||
/// The <see cref="Slug"/> is automatically calculated from it's name.
|
||||
/// The <see cref="Slug"/> is automatically calculated from it's name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of this provider.</param>
|
||||
/// <param name="logo">The logo of this provider.</param>
|
||||
@ -61,4 +79,4 @@ namespace Kyoo.Abstractions.Models
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,22 @@
|
||||
using System;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using JetBrains.Annotations;
|
||||
@ -8,12 +26,12 @@ using Kyoo.Abstractions.Models.Attributes;
|
||||
namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A season of a <see cref="Show"/>.
|
||||
/// A season of a <see cref="Show"/>.
|
||||
/// </summary>
|
||||
public class Season : IResource, IMetadata, IThumbnails
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
public int ID { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[Computed] public string Slug
|
||||
@ -24,10 +42,11 @@ namespace Kyoo.Abstractions.Models
|
||||
return $"{ShowID}-s{SeasonNumber}";
|
||||
return $"{ShowSlug ?? Show?.Slug}-s{SeasonNumber}";
|
||||
}
|
||||
|
||||
[UsedImplicitly] [NotNull] private set
|
||||
{
|
||||
Match match = Regex.Match(value ?? "", @"(?<show>.+)-s(?<season>\d+)");
|
||||
|
||||
Match match = Regex.Match(value ?? string.Empty, @"(?<show>.+)-s(?<season>\d+)");
|
||||
|
||||
if (!match.Success)
|
||||
throw new ArgumentException("Invalid season slug. Format: {showSlug}-s{seasonNumber}");
|
||||
ShowSlug = match.Groups["show"].Value;
|
||||
@ -39,11 +58,12 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The slug of the Show that contain this episode. If this is not set, this season is ill-formed.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public string ShowSlug { private get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the Show containing this season.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public int ShowID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The show that contains this season.
|
||||
/// This must be explicitly loaded via a call to <see cref="ILibraryManager.Load"/>.
|
||||
@ -59,17 +79,17 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The title of this season.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A quick overview of this season.
|
||||
/// </summary>
|
||||
public string Overview { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The starting air date of this season.
|
||||
/// </summary>
|
||||
public DateTime? StartDate { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The ending date of this season.
|
||||
/// </summary>
|
||||
@ -86,7 +106,7 @@ namespace Kyoo.Abstractions.Models
|
||||
[SerializeAs("{HOST}/api/seasons/{Slug}/thumb")]
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||
|
@ -1,4 +1,22 @@
|
||||
using System;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
@ -12,31 +30,31 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The title of this show.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of alternative titles of this show.
|
||||
/// </summary>
|
||||
[EditableRelation] public string[] Aliases { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The path of the root directory of this show.
|
||||
/// This can be any kind of path supported by <see cref="IFileSystem"/>
|
||||
/// </summary>
|
||||
[SerializeIgnore] public string Path { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The summary of this show.
|
||||
/// </summary>
|
||||
public string Overview { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Is this show airing, not aired yet or finished?
|
||||
/// </summary>
|
||||
@ -48,12 +66,12 @@ namespace Kyoo.Abstractions.Models
|
||||
/// TODO for now, this is set to a youtube url. It should be cached and converted to a local file.
|
||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||
public string TrailerUrl => Images?.GetValueOrDefault(Models.Images.Trailer);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The date this show started airing. It can be null if this is unknown.
|
||||
/// The date this show started airing. It can be null if this is unknown.
|
||||
/// </summary>
|
||||
public DateTime? StartAir { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The date this show finished airing.
|
||||
/// It must be after the <see cref="StartAir"/> but can be the same (example: for movies).
|
||||
@ -103,61 +121,91 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The ID of the Studio that made this show.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public int? StudioID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Studio that made this show.
|
||||
/// This must be explicitly loaded via a call to <see cref="ILibraryManager.Load"/>.
|
||||
/// </summary>
|
||||
[LoadableRelation(nameof(StudioID))] [EditableRelation] public Studio Studio { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of genres (themes) this show has.
|
||||
/// </summary>
|
||||
[LoadableRelation] [EditableRelation] public ICollection<Genre> Genres { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of people that made this show.
|
||||
/// </summary>
|
||||
[LoadableRelation] [EditableRelation] public ICollection<PeopleRole> People { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The different seasons in this show. If this is a movie, this list is always null or empty.
|
||||
/// </summary>
|
||||
[LoadableRelation] public ICollection<Season> Seasons { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of episodes in this show.
|
||||
/// If this is a movie, there will be a unique episode (with the seasonNumber and episodeNumber set to null).
|
||||
/// Having an episode is necessary to store metadata and tracks.
|
||||
/// </summary>
|
||||
[LoadableRelation] public ICollection<Episode> Episodes { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of libraries that contains this show.
|
||||
/// </summary>
|
||||
[LoadableRelation] public ICollection<Library> Libraries { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of collections that contains this show.
|
||||
/// </summary>
|
||||
[LoadableRelation] public ICollection<Collection> Collections { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnMerge(object merged)
|
||||
{
|
||||
if (People != null)
|
||||
{
|
||||
foreach (PeopleRole link in People)
|
||||
link.Show = this;
|
||||
}
|
||||
|
||||
if (Seasons != null)
|
||||
{
|
||||
foreach (Season season in Seasons)
|
||||
season.Show = this;
|
||||
}
|
||||
|
||||
if (Episodes != null)
|
||||
{
|
||||
foreach (Episode episode in Episodes)
|
||||
episode.Show = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The enum containing show's status.
|
||||
/// </summary>
|
||||
public enum Status { Unknown, Finished, Airing, Planned }
|
||||
public enum Status
|
||||
{
|
||||
/// <summary>
|
||||
/// The status of the show is not known.
|
||||
/// </summary>
|
||||
Unknown,
|
||||
|
||||
/// <summary>
|
||||
/// The show has finished airing.
|
||||
/// </summary>
|
||||
Finished,
|
||||
|
||||
/// <summary>
|
||||
/// The show is still actively airing.
|
||||
/// </summary>
|
||||
Airing,
|
||||
|
||||
/// <summary>
|
||||
/// This show has not aired yet but has been announced.
|
||||
/// </summary>
|
||||
Planned
|
||||
}
|
||||
}
|
@ -1,4 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
using Kyoo.Utils;
|
||||
|
||||
@ -11,15 +29,15 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of this studio.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of shows that are made by this studio.
|
||||
/// </summary>
|
||||
@ -27,7 +45,7 @@ namespace Kyoo.Abstractions.Models
|
||||
|
||||
/// <inheritdoc />
|
||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new, empty, <see cref="Studio"/>.
|
||||
/// </summary>
|
@ -1,4 +1,22 @@
|
||||
using System;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
@ -13,10 +31,30 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </summary>
|
||||
public enum StreamType
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of the stream is not known.
|
||||
/// </summary>
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The stream is a video.
|
||||
/// </summary>
|
||||
Video = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The stream is an audio.
|
||||
/// </summary>
|
||||
Audio = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The stream is a subtitle.
|
||||
/// </summary>
|
||||
Subtitle = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The stream is an attachement (a font, an image or something else).
|
||||
/// Only fonts are handled by kyoo but they are not saved to the database.
|
||||
/// </summary>
|
||||
Attachment = 4
|
||||
}
|
||||
|
||||
@ -27,7 +65,7 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
[Computed] public string Slug
|
||||
{
|
||||
@ -36,18 +74,21 @@ namespace Kyoo.Abstractions.Models
|
||||
string type = Type.ToString().ToLower();
|
||||
string index = TrackIndex != 0 ? $"-{TrackIndex}" : string.Empty;
|
||||
string episode = EpisodeSlug ?? Episode?.Slug ?? EpisodeID.ToString();
|
||||
return $"{episode}.{Language ?? "und"}{index}{(IsForced ? ".forced" : "")}.{type}";
|
||||
return $"{episode}.{Language ?? "und"}{index}{(IsForced ? ".forced" : string.Empty)}.{type}";
|
||||
}
|
||||
|
||||
[UsedImplicitly] private set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
Match match = Regex.Match(value,
|
||||
Match match = Regex.Match(value,
|
||||
@"(?<ep>[^\.]+)\.(?<lang>\w{0,3})(-(?<index>\d+))?(\.(?<forced>forced))?\.(?<type>\w+)(\.\w*)?");
|
||||
|
||||
if (!match.Success)
|
||||
{
|
||||
throw new ArgumentException("Invalid track slug. " +
|
||||
"Format: {episodeSlug}.{language}[-{index}][.forced].{type}[.{extension}]");
|
||||
}
|
||||
|
||||
EpisodeSlug = match.Groups["ep"].Value;
|
||||
Language = match.Groups["lang"].Value;
|
||||
@ -58,57 +99,57 @@ namespace Kyoo.Abstractions.Models
|
||||
Type = Enum.Parse<StreamType>(match.Groups["type"].Value, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The slug of the episode that contain this track. If this is not set, this track is ill-formed.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public string EpisodeSlug { private get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The title of the stream.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The language of this stream (as a ISO-639-2 language code)
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The codec of this stream.
|
||||
/// </summary>
|
||||
public string Codec { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Is this stream the default one of it's type?
|
||||
/// </summary>
|
||||
public bool IsDefault { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Is this stream tagged as forced?
|
||||
/// Is this stream tagged as forced?
|
||||
/// </summary>
|
||||
public bool IsForced { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Is this track extern to the episode's file?
|
||||
/// </summary>
|
||||
public bool IsExternal { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The path of this track.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public string Path { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The type of this stream.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public StreamType Type { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the episode that uses this track.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public int EpisodeID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The episode that uses this track.
|
||||
/// </summary>
|
||||
@ -126,7 +167,7 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
string language = GetLanguage(Language);
|
||||
string language = _GetLanguage(Language);
|
||||
|
||||
if (language == null)
|
||||
return $"Unknown (index: {TrackIndex})";
|
||||
@ -137,14 +178,14 @@ namespace Kyoo.Abstractions.Models
|
||||
name += " Forced";
|
||||
if (IsExternal)
|
||||
name += " (External)";
|
||||
if (Title is {Length: > 1})
|
||||
if (Title is { Length: > 1 })
|
||||
name += " - " + Title;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
//Converting mkv track language to c# system language tag.
|
||||
private static string GetLanguage(string mkvLanguage)
|
||||
// Converting mkv track language to c# system language tag.
|
||||
private static string _GetLanguage(string mkvLanguage)
|
||||
{
|
||||
// TODO delete this and have a real way to get the language string from the ISO-639-2.
|
||||
return mkvLanguage switch
|
||||
@ -160,12 +201,11 @@ namespace Kyoo.Abstractions.Models
|
||||
/// </summary>
|
||||
/// <param name="baseSlug">The slug to edit</param>
|
||||
/// <param name="type">The new type of this </param>
|
||||
/// <returns></returns>
|
||||
public static string BuildSlug(string baseSlug,
|
||||
StreamType type)
|
||||
/// <returns>The completed slug.</returns>
|
||||
public static string BuildSlug(string baseSlug, StreamType type)
|
||||
{
|
||||
return baseSlug.EndsWith($".{type}", StringComparison.InvariantCultureIgnoreCase)
|
||||
? baseSlug
|
||||
return baseSlug.EndsWith($".{type}", StringComparison.InvariantCultureIgnoreCase)
|
||||
? baseSlug
|
||||
: $"{baseSlug}.{type.ToString().ToLowerInvariant()}";
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
@ -9,30 +27,30 @@ namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int ID { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Slug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A username displayed to the user.
|
||||
/// </summary>
|
||||
public string Username { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The user email address.
|
||||
/// </summary>
|
||||
public string Email { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The user password (hashed, it can't be read like that). The hashing format is implementation defined.
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of permissions of the user. The format of this is implementation dependent.
|
||||
/// </summary>
|
||||
public string[] Permissions { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Arbitrary extra data that can be used by specific authentication implementations.
|
||||
/// </summary>
|
||||
@ -45,36 +63,10 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The list of shows the user has finished.
|
||||
/// </summary>
|
||||
public ICollection<Show> Watched { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of episodes the user is watching (stopped in progress or the next episode of the show)
|
||||
/// </summary>
|
||||
public ICollection<WatchedEpisode> CurrentlyWatching { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metadata of episode currently watching by an user
|
||||
/// </summary>
|
||||
public class WatchedEpisode
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID of the user that started watching this episode.
|
||||
/// </summary>
|
||||
public int UserID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the episode started.
|
||||
/// </summary>
|
||||
public int EpisodeID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Episode"/> started.
|
||||
/// </summary>
|
||||
public Episode Episode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Where the player has stopped watching the episode (between 0 and 100).
|
||||
/// </summary>
|
||||
public int WatchedPercentage { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
46
src/Kyoo.Abstractions/Models/Resources/WatchedEpisode.cs
Normal file
46
src/Kyoo.Abstractions/Models/Resources/WatchedEpisode.cs
Normal file
@ -0,0 +1,46 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata of episode currently watching by an user
|
||||
/// </summary>
|
||||
public class WatchedEpisode
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID of the user that started watching this episode.
|
||||
/// </summary>
|
||||
public int UserID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the episode started.
|
||||
/// </summary>
|
||||
public int EpisodeID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Episode"/> started.
|
||||
/// </summary>
|
||||
public Episode Episode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Where the player has stopped watching the episode (between 0 and 100).
|
||||
/// </summary>
|
||||
public int WatchedPercentage { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
@ -11,32 +29,32 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The query of the search request.
|
||||
/// </summary>
|
||||
public string Query { get; init; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The collections that matched the search.
|
||||
/// </summary>
|
||||
public ICollection<Collection> Collections { get; init; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The shows that matched the search.
|
||||
/// </summary>
|
||||
public ICollection<Show> Shows { get; init; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The episodes that matched the search.
|
||||
/// </summary>
|
||||
public ICollection<Episode> Episodes { get; init; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The people that matched the search.
|
||||
/// </summary>
|
||||
public ICollection<People> People { get; init; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The genres that matched the search.
|
||||
/// </summary>
|
||||
public ICollection<Genre> Genres { get; init; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The studios that matched the search.
|
||||
/// </summary>
|
35
src/Kyoo.Abstractions/Models/Utils/AsyncRef.cs
Normal file
35
src/Kyoo.Abstractions/Models/Utils/AsyncRef.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Kyoo.Abstractions.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A class wrapping a value that will be set after the completion of the task it is related to.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class replace the use of an out parameter on a task since tasks and out can't be combined.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The type of the value</typeparam>
|
||||
public class AsyncRef<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The value that will be set before the completion of the task.
|
||||
/// </summary>
|
||||
public T Value { get; set; }
|
||||
}
|
||||
}
|
54
src/Kyoo.Abstractions/Models/Utils/Pagination.cs
Normal file
54
src/Kyoo.Abstractions/Models/Utils/Pagination.cs
Normal file
@ -0,0 +1,54 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// Information about the pagination. How many items should be displayed and where to start.
|
||||
/// </summary>
|
||||
public readonly struct Pagination
|
||||
{
|
||||
/// <summary>
|
||||
/// The count of items to return.
|
||||
/// </summary>
|
||||
public int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Where to start? Using the given sort.
|
||||
/// </summary>
|
||||
public int AfterID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Pagination"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="count">Set the <see cref="Count"/> value</param>
|
||||
/// <param name="afterID">Set the <see cref="AfterID"/> value. If not specified, it will start from the start</param>
|
||||
public Pagination(int count, int afterID = 0)
|
||||
{
|
||||
Count = count;
|
||||
AfterID = afterID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly create a new pagination from a limit number.
|
||||
/// </summary>
|
||||
/// <param name="limit">Set the <see cref="Count"/> value</param>
|
||||
/// <returns>A new <see cref="Pagination"/> instance</returns>
|
||||
public static implicit operator Pagination(int limit) => new(limit);
|
||||
}
|
||||
}
|
88
src/Kyoo.Abstractions/Models/Utils/Sort.cs
Normal file
88
src/Kyoo.Abstractions/Models/Utils/Sort.cs
Normal file
@ -0,0 +1,88 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Kyoo.Utils;
|
||||
|
||||
namespace Kyoo.Abstractions.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// Information about how a query should be sorted. What factor should decide the sort and in which order.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">For witch type this sort applies</typeparam>
|
||||
public readonly struct Sort<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The sort key. This member will be used to sort the results.
|
||||
/// </summary>
|
||||
public Expression<Func<T, object>> Key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order.
|
||||
/// </summary>
|
||||
public bool Descendant { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Sort{T}"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="key">The sort key given. It is assigned to <see cref="Key"/>.</param>
|
||||
/// <param name="descendant">Should this be in descendant order? The default is false.</param>
|
||||
/// <exception cref="ArgumentException">If the given key is not a member.</exception>
|
||||
public Sort(Expression<Func<T, object>> key, bool descendant = false)
|
||||
{
|
||||
Key = key;
|
||||
Descendant = descendant;
|
||||
|
||||
if (!Utility.IsPropertyExpression(Key))
|
||||
throw new ArgumentException("The given sort key is not valid.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Sort{T}"/> instance from a key's name (case insensitive).
|
||||
/// </summary>
|
||||
/// <param name="sortBy">A key name with an optional order specifier. Format: "key:asc", "key:desc" or "key".</param>
|
||||
/// <exception cref="ArgumentException">An invalid key or sort specifier as been given.</exception>
|
||||
public Sort(string sortBy)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sortBy))
|
||||
{
|
||||
Key = null;
|
||||
Descendant = false;
|
||||
return;
|
||||
}
|
||||
|
||||
string key = sortBy.Contains(':') ? sortBy[..sortBy.IndexOf(':')] : sortBy;
|
||||
string order = sortBy.Contains(':') ? sortBy[(sortBy.IndexOf(':') + 1)..] : null;
|
||||
|
||||
ParameterExpression param = Expression.Parameter(typeof(T), "x");
|
||||
MemberExpression property = Expression.Property(param, key);
|
||||
Key = property.Type.IsValueType
|
||||
? Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param)
|
||||
: Expression.Lambda<Func<T, object>>(property, param);
|
||||
|
||||
Descendant = order switch
|
||||
{
|
||||
"desc" => true,
|
||||
"asc" => false,
|
||||
null => false,
|
||||
_ => throw new ArgumentException($"The sort order, if set, should be :asc or :desc but it was :{order}.")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,22 @@
|
||||
using System;
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -20,7 +38,7 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The ID of the episode associated with this item.
|
||||
/// </summary>
|
||||
public int EpisodeID { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The slug of this episode.
|
||||
/// </summary>
|
||||
@ -30,54 +48,54 @@ namespace Kyoo.Abstractions.Models
|
||||
/// The title of the show containing this episode.
|
||||
/// </summary>
|
||||
public string ShowTitle { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The slug of the show containing this episode
|
||||
/// </summary>
|
||||
public string ShowSlug { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The season in witch this episode is in.
|
||||
/// </summary>
|
||||
public int? SeasonNumber { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The number of this episode is it's season.
|
||||
/// </summary>
|
||||
public int? EpisodeNumber { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season.
|
||||
/// </summary>
|
||||
public int? AbsoluteNumber { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The title of this episode.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The release date of this episode. It can be null if unknown.
|
||||
/// </summary>
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The path of the video file for this episode. Any format supported by a <see cref="IFileSystem"/> is allowed.
|
||||
/// </summary>
|
||||
[SerializeIgnore] public string Path { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The episode that come before this one if you follow usual watch orders.
|
||||
/// If this is the first episode or this is a movie, it will be null.
|
||||
/// </summary>
|
||||
public Episode PreviousEpisode { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The episode that come after this one if you follow usual watch orders.
|
||||
/// If this is the last aired episode or this is a movie, it will be null.
|
||||
/// </summary>
|
||||
public Episode NextEpisode { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <c>true</c> if this is a movie, <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
@ -89,14 +107,14 @@ namespace Kyoo.Abstractions.Models
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/show/{ShowSlug}/poster")] public string Poster { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The path of this item's logo.
|
||||
/// By default, the http path for the logo is returned from the public API.
|
||||
/// This can be disabled using the internal query flag.
|
||||
/// </summary>
|
||||
[SerializeAs("{HOST}/api/show/{ShowSlug}/logo")] public string Logo { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The path of this item's backdrop.
|
||||
/// By default, the http path for the backdrop is returned from the public API.
|
||||
@ -109,34 +127,33 @@ namespace Kyoo.Abstractions.Models
|
||||
/// Common containers are mp4, mkv, avi and so on.
|
||||
/// </summary>
|
||||
public string Container { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The video track. See <see cref="Track"/> for more information.
|
||||
/// </summary>
|
||||
public Track Video { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of audio tracks. See <see cref="Track"/> for more information.
|
||||
/// </summary>
|
||||
public ICollection<Track> Audios { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of subtitles tracks. See <see cref="Track"/> for more information.
|
||||
/// </summary>
|
||||
public ICollection<Track> Subtitles { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The list of chapters. See <see cref="Chapter"/> for more information.
|
||||
/// </summary>
|
||||
public ICollection<Chapter> Chapters { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="WatchItem"/> from an <see cref="Episode"/>.
|
||||
/// </summary>
|
||||
/// <param name="ep">The episode to transform.</param>
|
||||
/// <param name="library">
|
||||
/// A library manager to retrieve the next and previous episode and load the show & tracks of the episode.
|
||||
/// A library manager to retrieve the next and previous episode and load the show and tracks of the episode.
|
||||
/// </param>
|
||||
/// <returns>A new WatchItem representing the given episode.</returns>
|
||||
public static async Task<WatchItem> FromEpisode(Episode ep, ILibraryManager library)
|
||||
@ -146,15 +163,15 @@ namespace Kyoo.Abstractions.Models
|
||||
|
||||
await library.Load(ep, x => x.Show);
|
||||
await library.Load(ep, x => x.Tracks);
|
||||
|
||||
|
||||
if (!ep.Show.IsMovie && ep.SeasonNumber != null && ep.EpisodeNumber != null)
|
||||
{
|
||||
if (ep.EpisodeNumber > 1)
|
||||
previous = await library.GetOrDefault(ep.ShowID, ep.SeasonNumber.Value, ep.EpisodeNumber.Value - 1);
|
||||
else if (ep.SeasonNumber > 1)
|
||||
{
|
||||
previous = (await library.GetAll(x => x.ShowID == ep.ShowID
|
||||
&& x.SeasonNumber == ep.SeasonNumber.Value - 1,
|
||||
previous = (await library.GetAll(x => x.ShowID == ep.ShowID
|
||||
&& x.SeasonNumber == ep.SeasonNumber.Value - 1,
|
||||
limit: 1,
|
||||
sort: new Sort<Episode>(x => x.EpisodeNumber, true))
|
||||
).FirstOrDefault();
|
||||
@ -167,12 +184,12 @@ namespace Kyoo.Abstractions.Models
|
||||
}
|
||||
else if (!ep.Show.IsMovie && ep.AbsoluteNumber != null)
|
||||
{
|
||||
previous = await library.GetOrDefault<Episode>(x => x.ShowID == ep.ShowID
|
||||
previous = await library.GetOrDefault<Episode>(x => x.ShowID == ep.ShowID
|
||||
&& x.AbsoluteNumber == ep.EpisodeNumber + 1);
|
||||
next = await library.GetOrDefault<Episode>(x => x.ShowID == ep.ShowID
|
||||
next = await library.GetOrDefault<Episode>(x => x.ShowID == ep.ShowID
|
||||
&& x.AbsoluteNumber == ep.AbsoluteNumber + 1);
|
||||
}
|
||||
|
||||
|
||||
return new WatchItem
|
||||
{
|
||||
EpisodeID = ep.ID,
|
||||
@ -188,19 +205,19 @@ namespace Kyoo.Abstractions.Models
|
||||
Container = PathIO.GetExtension(ep.Path)![1..],
|
||||
Video = ep.Tracks.FirstOrDefault(x => x.Type == StreamType.Video),
|
||||
Audios = ep.Tracks.Where(x => x.Type == StreamType.Audio).ToArray(),
|
||||
Subtitles = ep.Tracks.Where(x => x.Type == StreamType.Subtitle).ToArray(),
|
||||
Subtitles = ep.Tracks.Where(x => x.Type == StreamType.Subtitle).ToArray(),
|
||||
PreviousEpisode = previous,
|
||||
NextEpisode = next,
|
||||
Chapters = await GetChapters(ep.Path)
|
||||
Chapters = await _GetChapters(ep.Path)
|
||||
};
|
||||
}
|
||||
|
||||
// TODO move this method in a controller to support abstraction.
|
||||
// TODO use a IFileManager to retrieve and read files.
|
||||
private static async Task<ICollection<Chapter>> GetChapters(string episodePath)
|
||||
private static async Task<ICollection<Chapter>> _GetChapters(string episodePath)
|
||||
{
|
||||
string path = PathIO.Combine(
|
||||
PathIO.GetDirectoryName(episodePath)!,
|
||||
PathIO.GetDirectoryName(episodePath)!,
|
||||
"Chapters",
|
||||
PathIO.GetFileNameWithoutExtension(episodePath) + ".txt"
|
||||
);
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using Autofac;
|
||||
using Autofac.Builder;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
@ -30,7 +48,7 @@ namespace Kyoo.Abstractions
|
||||
/// <param name="builder">The container</param>
|
||||
/// <typeparam name="T">The type of the task</typeparam>
|
||||
/// <returns>The registration builder of this new provider. That can be used to edit the registration.</returns>
|
||||
public static IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle>
|
||||
public static IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle>
|
||||
RegisterProvider<T>(this ContainerBuilder builder)
|
||||
where T : class, IMetadataProvider
|
||||
{
|
||||
@ -46,7 +64,7 @@ namespace Kyoo.Abstractions
|
||||
/// If your repository implements a special interface, please use <see cref="RegisterRepository{T,T2}"/>
|
||||
/// </remarks>
|
||||
/// <returns>The initial container.</returns>
|
||||
public static IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle>
|
||||
public static IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle>
|
||||
RegisterRepository<T>(this ContainerBuilder builder)
|
||||
where T : IBaseRepository
|
||||
{
|
||||
@ -83,4 +101,4 @@ namespace Kyoo.Abstractions
|
||||
return configuration["basics:publicUrl"]?.TrimEnd('/') ?? "http://localhost:5000";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@ -16,7 +34,7 @@ namespace Kyoo.Utils
|
||||
/// </summary>
|
||||
/// <param name="self">The IEnumerable to map. If self is null, an empty list is returned</param>
|
||||
/// <param name="mapper">The function that will map each items</param>
|
||||
/// <typeparam name="T">The type of items in <see cref="self"/></typeparam>
|
||||
/// <typeparam name="T">The type of items in <paramref name="self"/></typeparam>
|
||||
/// <typeparam name="T2">The type of items in the returned list</typeparam>
|
||||
/// <returns>The list mapped.</returns>
|
||||
/// <exception cref="ArgumentNullException">The list or the mapper can't be null</exception>
|
||||
@ -42,19 +60,19 @@ namespace Kyoo.Utils
|
||||
}
|
||||
return Generator(self, mapper);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A map where the mapping function is asynchronous.
|
||||
/// Note: <see cref="SelectAsync{T,T2}"/> might interest you.
|
||||
/// Note: <see cref="SelectAsync{T,T2}"/> might interest you.
|
||||
/// </summary>
|
||||
/// <param name="self">The IEnumerable to map.</param>
|
||||
/// <param name="mapper">The asynchronous function that will map each items</param>
|
||||
/// <typeparam name="T">The type of items in <see cref="self"/></typeparam>
|
||||
/// <typeparam name="T2">The type of items in the returned list</typeparam>
|
||||
/// <returns>The list mapped as an AsyncEnumerable</returns>
|
||||
/// <exception cref="ArgumentNullException">The list or the mapper can't be null</exception>
|
||||
/// <param name="mapper">The asynchronous function that will map each items.</param>
|
||||
/// <typeparam name="T">The type of items in <paramref name="self"/>.</typeparam>
|
||||
/// <typeparam name="T2">The type of items in the returned list.</typeparam>
|
||||
/// <returns>The list mapped as an AsyncEnumerable.</returns>
|
||||
/// <exception cref="ArgumentNullException">The list or the mapper can't be null.</exception>
|
||||
[LinqTunnel]
|
||||
public static IAsyncEnumerable<T2> MapAsync<T, T2>([NotNull] this IEnumerable<T> self,
|
||||
public static IAsyncEnumerable<T2> MapAsync<T, T2>([NotNull] this IEnumerable<T> self,
|
||||
[NotNull] Func<T, int, Task<T2>> mapper)
|
||||
{
|
||||
if (self == null)
|
||||
@ -76,18 +94,18 @@ namespace Kyoo.Utils
|
||||
|
||||
return Generator(self, mapper);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// An asynchronous version of Select.
|
||||
/// </summary>
|
||||
/// <param name="self">The IEnumerable to map</param>
|
||||
/// <param name="mapper">The asynchronous function that will map each items</param>
|
||||
/// <typeparam name="T">The type of items in <see cref="self"/></typeparam>
|
||||
/// <typeparam name="T">The type of items in <paramref name="self"/></typeparam>
|
||||
/// <typeparam name="T2">The type of items in the returned list</typeparam>
|
||||
/// <returns>The list mapped as an AsyncEnumerable</returns>
|
||||
/// <exception cref="ArgumentNullException">The list or the mapper can't be null</exception>
|
||||
[LinqTunnel]
|
||||
public static IAsyncEnumerable<T2> SelectAsync<T, T2>([NotNull] this IEnumerable<T> self,
|
||||
public static IAsyncEnumerable<T2> SelectAsync<T, T2>([NotNull] this IEnumerable<T> self,
|
||||
[NotNull] Func<T, Task<T2>> mapper)
|
||||
{
|
||||
if (self == null)
|
||||
@ -159,7 +177,7 @@ namespace Kyoo.Utils
|
||||
do
|
||||
{
|
||||
yield return enumerator.Current;
|
||||
}
|
||||
}
|
||||
while (enumerator.MoveNext());
|
||||
}
|
||||
|
||||
@ -179,7 +197,7 @@ namespace Kyoo.Utils
|
||||
foreach (T i in self)
|
||||
action(i);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A foreach used as a function with a little specificity: the list can be null.
|
||||
/// </summary>
|
||||
@ -192,12 +210,13 @@ namespace Kyoo.Utils
|
||||
foreach (object i in self)
|
||||
action(i);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A foreach used as a function with a little specificity: the list can be null.
|
||||
/// </summary>
|
||||
/// <param name="self">The list to enumerate. If this is null, the function result in a no-op</param>
|
||||
/// <param name="action">The action to execute for each arguments</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public static async Task ForEachAsync([CanBeNull] this IEnumerable self, Func<object, Task> action)
|
||||
{
|
||||
if (self == null)
|
||||
@ -205,13 +224,14 @@ namespace Kyoo.Utils
|
||||
foreach (object i in self)
|
||||
await action(i);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A foreach used as a function with a little specificity: the list can be null.
|
||||
/// </summary>
|
||||
/// <param name="self">The list to enumerate. If this is null, the function result in a no-op</param>
|
||||
/// <param name="action">The asynchronous action to execute for each arguments</param>
|
||||
/// <typeparam name="T">The type of items in the list.</typeparam>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public static async Task ForEachAsync<T>([CanBeNull] this IEnumerable<T> self, Func<T, Task> action)
|
||||
{
|
||||
if (self == null)
|
||||
@ -219,13 +239,14 @@ namespace Kyoo.Utils
|
||||
foreach (T i in self)
|
||||
await action(i);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A foreach used as a function with a little specificity: the list can be null.
|
||||
/// </summary>
|
||||
/// <param name="self">The async list to enumerate. If this is null, the function result in a no-op</param>
|
||||
/// <param name="action">The action to execute for each arguments</param>
|
||||
/// <typeparam name="T">The type of items in the list.</typeparam>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public static async Task ForEachAsync<T>([CanBeNull] this IAsyncEnumerable<T> self, Action<T> action)
|
||||
{
|
||||
if (self == null)
|
||||
@ -233,7 +254,7 @@ namespace Kyoo.Utils
|
||||
await foreach (T i in self)
|
||||
action(i);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Split a list in a small chunk of data.
|
||||
/// </summary>
|
||||
@ -247,7 +268,7 @@ namespace Kyoo.Utils
|
||||
for (int i = 0; i < list.Count; i += countPerList)
|
||||
yield return list.GetRange(i, Math.Min(list.Count - i, countPerList));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Split a list in a small chunk of data.
|
||||
/// </summary>
|
||||
@ -260,7 +281,7 @@ namespace Kyoo.Utils
|
||||
{
|
||||
T[] ret = new T[countPerList];
|
||||
int i = 0;
|
||||
|
||||
|
||||
using IEnumerator<T> enumerator = list.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
@ -276,4 +297,4 @@ namespace Kyoo.Utils
|
||||
yield return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@ -21,10 +39,11 @@ namespace Kyoo.Utils
|
||||
/// <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 kept</param>
|
||||
/// <param name="isEqual">Equality function to compare items. If this is null, duplicated elements are kept</param>
|
||||
/// <typeparam name="T">The type of items in the lists to merge.</typeparam>
|
||||
/// <returns>The two list merged as an array</returns>
|
||||
[ContractAnnotation("first:notnull => notnull; second:notnull => notnull", true)]
|
||||
public static T[] MergeLists<T>([CanBeNull] IEnumerable<T> first,
|
||||
[CanBeNull] IEnumerable<T> second,
|
||||
[CanBeNull] IEnumerable<T> second,
|
||||
[CanBeNull] Func<T, T, bool> isEqual = null)
|
||||
{
|
||||
if (first == null)
|
||||
@ -82,7 +101,7 @@ namespace Kyoo.Utils
|
||||
{
|
||||
bool success = first.TryAdd(key, value);
|
||||
hasChanged |= success;
|
||||
|
||||
|
||||
if (success || first[key]?.Equals(default) == false || value?.Equals(default) != false)
|
||||
continue;
|
||||
first[key] = value;
|
||||
@ -145,14 +164,14 @@ namespace Kyoo.Utils
|
||||
/// <param name="first">The object to assign</param>
|
||||
/// <param name="second">The object containing new values</param>
|
||||
/// <typeparam name="T">Fields of T will be used</typeparam>
|
||||
/// <returns><see cref="first"/></returns>
|
||||
/// <returns><paramref name="first"/></returns>
|
||||
public static T Assign<T>(T first, T second)
|
||||
{
|
||||
Type type = typeof(T);
|
||||
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
||||
.Where(x => x.CanRead && x.CanWrite
|
||||
.Where(x => x.CanRead && x.CanWrite
|
||||
&& Attribute.GetCustomAttribute(x, typeof(NotMergeableAttribute)) == null);
|
||||
|
||||
|
||||
foreach (PropertyInfo property in properties)
|
||||
{
|
||||
object value = property.GetValue(second);
|
||||
@ -163,7 +182,7 @@ namespace Kyoo.Utils
|
||||
merge.OnMerge(second);
|
||||
return first;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set every non-default values of seconds to the corresponding property of second.
|
||||
/// Dictionaries are handled like anonymous objects with a property per key/pair value
|
||||
@ -188,17 +207,17 @@ namespace Kyoo.Utils
|
||||
/// Filter fields that will be merged
|
||||
/// </param>
|
||||
/// <typeparam name="T">Fields of T will be completed</typeparam>
|
||||
/// <returns><see cref="first"/></returns>
|
||||
/// <returns><paramref name="first"/></returns>
|
||||
/// <exception cref="ArgumentNullException">If first is null</exception>
|
||||
public static T Complete<T>([NotNull] T first,
|
||||
[CanBeNull] T second,
|
||||
public static T Complete<T>([NotNull] T first,
|
||||
[CanBeNull] T second,
|
||||
[InstantHandle] Func<PropertyInfo, bool> where = null)
|
||||
{
|
||||
if (first == null)
|
||||
throw new ArgumentNullException(nameof(first));
|
||||
if (second == null)
|
||||
return first;
|
||||
|
||||
|
||||
Type type = typeof(T);
|
||||
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
||||
.Where(x => x.CanRead && x.CanWrite
|
||||
@ -206,7 +225,7 @@ namespace Kyoo.Utils
|
||||
|
||||
if (where != null)
|
||||
properties = properties.Where(where);
|
||||
|
||||
|
||||
foreach (PropertyInfo property in properties)
|
||||
{
|
||||
object value = property.GetValue(second);
|
||||
@ -219,7 +238,8 @@ namespace Kyoo.Utils
|
||||
{
|
||||
Type[] dictionaryTypes = Utility.GetGenericDefinition(property.PropertyType, typeof(IDictionary<,>))
|
||||
.GenericTypeArguments;
|
||||
object[] parameters = {
|
||||
object[] parameters =
|
||||
{
|
||||
property.GetValue(first),
|
||||
value,
|
||||
false
|
||||
@ -242,7 +262,7 @@ namespace Kyoo.Utils
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will set missing values of <see cref="first"/> to the corresponding values of <see cref="second"/>.
|
||||
/// This will set missing values of <paramref name="first"/> to the corresponding values of <paramref name="second"/>.
|
||||
/// Enumerable will be merged (concatenated) and Dictionaries too.
|
||||
/// At the end, the OnMerge method of first will be called if first is a <see cref="IOnMerge"/>.
|
||||
/// </summary>
|
||||
@ -259,9 +279,9 @@ namespace Kyoo.Utils
|
||||
/// Filter fields that will be merged
|
||||
/// </param>
|
||||
/// <typeparam name="T">Fields of T will be merged</typeparam>
|
||||
/// <returns><see cref="first"/></returns>
|
||||
/// <returns><paramref name="first"/></returns>
|
||||
[ContractAnnotation("first:notnull => notnull; second:notnull => notnull", true)]
|
||||
public static T Merge<T>([CanBeNull] T first,
|
||||
public static T Merge<T>([CanBeNull] T first,
|
||||
[CanBeNull] T second,
|
||||
[InstantHandle] Func<PropertyInfo, bool> where = null)
|
||||
{
|
||||
@ -269,28 +289,29 @@ namespace Kyoo.Utils
|
||||
return second;
|
||||
if (second == null)
|
||||
return first;
|
||||
|
||||
|
||||
Type type = typeof(T);
|
||||
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
||||
.Where(x => x.CanRead && x.CanWrite
|
||||
.Where(x => x.CanRead && x.CanWrite
|
||||
&& Attribute.GetCustomAttribute(x, typeof(NotMergeableAttribute)) == null);
|
||||
|
||||
|
||||
if (where != null)
|
||||
properties = properties.Where(where);
|
||||
|
||||
|
||||
foreach (PropertyInfo property in properties)
|
||||
{
|
||||
object oldValue = property.GetValue(first);
|
||||
object newValue = property.GetValue(second);
|
||||
object defaultValue = property.PropertyType.GetClrDefault();
|
||||
|
||||
|
||||
if (oldValue?.Equals(defaultValue) != false)
|
||||
property.SetValue(first, newValue);
|
||||
else if (Utility.IsOfGenericType(property.PropertyType, typeof(IDictionary<,>)))
|
||||
{
|
||||
Type[] dictionaryTypes = Utility.GetGenericDefinition(property.PropertyType, typeof(IDictionary<,>))
|
||||
.GenericTypeArguments;
|
||||
object[] parameters = {
|
||||
object[] parameters =
|
||||
{
|
||||
oldValue,
|
||||
newValue,
|
||||
false
|
||||
@ -310,7 +331,7 @@ namespace Kyoo.Utils
|
||||
.GenericTypeArguments
|
||||
.First();
|
||||
Func<IResource, IResource, bool> equalityComparer = enumerableType.IsAssignableTo(typeof(IResource))
|
||||
? (x, y) => x.Slug == y.Slug
|
||||
? (x, y) => x.Slug == y.Slug
|
||||
: null;
|
||||
property.SetValue(first, Utility.RunGenericMethod<object>(
|
||||
typeof(Merger),
|
||||
@ -326,11 +347,11 @@ namespace Kyoo.Utils
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set every fields of <see cref="obj"/> to the default value.
|
||||
/// Set every fields of <paramref name="obj"/> to the default value.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to nullify</param>
|
||||
/// <typeparam name="T">Fields of T will be nullified</typeparam>
|
||||
/// <returns><see cref="obj"/></returns>
|
||||
/// <returns><paramref name="obj"/></returns>
|
||||
public static T Nullify<T>(T obj)
|
||||
{
|
||||
Type type = typeof(T);
|
||||
@ -344,4 +365,4 @@ namespace Kyoo.Utils
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
@ -17,75 +35,91 @@ namespace Kyoo.Utils
|
||||
{
|
||||
return action.Method;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a MethodInfo from a direct method.
|
||||
/// </summary>
|
||||
/// <param name="action">The method (without any arguments or return value.</param>
|
||||
/// <typeparam name="T">The first parameter of the action.</typeparam>
|
||||
/// <returns>The <see cref="MethodInfo"/> of the given method</returns>
|
||||
public static MethodInfo MethodOf<T>(Action<T> action)
|
||||
{
|
||||
return action.Method;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a MethodInfo from a direct method.
|
||||
/// </summary>
|
||||
/// <param name="action">The method (without any arguments or return value.</param>
|
||||
/// <typeparam name="T">The first parameter of the action.</typeparam>
|
||||
/// <typeparam name="T2">The second parameter of the action.</typeparam>
|
||||
/// <returns>The <see cref="MethodInfo"/> of the given method</returns>
|
||||
public static MethodInfo MethodOf<T, T2>(Action<T, T2> action)
|
||||
{
|
||||
return action.Method;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a MethodInfo from a direct method.
|
||||
/// </summary>
|
||||
/// <param name="action">The method (without any arguments or return value.</param>
|
||||
/// <typeparam name="T">The first parameter of the action.</typeparam>
|
||||
/// <typeparam name="T2">The second parameter of the action.</typeparam>
|
||||
/// <typeparam name="T3">The third parameter of the action.</typeparam>
|
||||
/// <returns>The <see cref="MethodInfo"/> of the given method</returns>
|
||||
public static MethodInfo MethodOf<T, T2, T3>(Action<T, T2, T3> action)
|
||||
{
|
||||
return action.Method;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a MethodInfo from a direct method.
|
||||
/// </summary>
|
||||
/// <param name="action">The method (without any arguments or return value.</param>
|
||||
/// <typeparam name="T">The return type of function.</typeparam>
|
||||
/// <returns>The <see cref="MethodInfo"/> of the given method</returns>
|
||||
public static MethodInfo MethodOf<T>(Func<T> action)
|
||||
{
|
||||
return action.Method;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a MethodInfo from a direct method.
|
||||
/// </summary>
|
||||
/// <param name="action">The method (without any arguments or return value.</param>
|
||||
/// <typeparam name="T">The first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The return type of function.</typeparam>
|
||||
/// <returns>The <see cref="MethodInfo"/> of the given method</returns>
|
||||
public static MethodInfo MethodOf<T, T2>(Func<T, T2> action)
|
||||
{
|
||||
return action.Method;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a MethodInfo from a direct method.
|
||||
/// </summary>
|
||||
/// <param name="action">The method (without any arguments or return value.</param>
|
||||
/// <typeparam name="T">The first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The return type of function.</typeparam>
|
||||
/// <returns>The <see cref="MethodInfo"/> of the given method</returns>
|
||||
public static MethodInfo MethodOf<T, T2, T3>(Func<T, T2, T3> action)
|
||||
{
|
||||
return action.Method;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a MethodInfo from a direct method.
|
||||
/// </summary>
|
||||
/// <param name="action">The method (without any arguments or return value.</param>
|
||||
/// <typeparam name="T">The first parameter of the function.</typeparam>
|
||||
/// <typeparam name="T2">The second parameter of the function.</typeparam>
|
||||
/// <typeparam name="T3">The third parameter of the function.</typeparam>
|
||||
/// <typeparam name="T4">The return type of function.</typeparam>
|
||||
/// <returns>The <see cref="MethodInfo"/> of the given method</returns>
|
||||
public static MethodInfo MethodOf<T, T2, T3, T4>(Func<T, T2, T3, T4> action)
|
||||
{
|
||||
return action.Method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
@ -18,7 +36,6 @@ namespace Kyoo.Utils
|
||||
/// </param>
|
||||
/// <typeparam name="T">The type of the item in the task.</typeparam>
|
||||
/// <returns>A continuation task wrapping the initial task and adding a continuation method.</returns>
|
||||
/// <exception cref="TaskCanceledException"></exception>
|
||||
/// <exception cref="TaskCanceledException">The source task has been canceled.</exception>
|
||||
public static Task<T> Then<T>(this Task<T> task, Action<T> then)
|
||||
{
|
||||
@ -66,4 +83,4 @@ namespace Kyoo.Utils
|
||||
return value ?? Task.FromResult<T>(default);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user