diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..01763e5f --- /dev/null +++ b/.editorconfig @@ -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 + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 83b3e507..a4a98525 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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 diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml new file mode 100644 index 00000000..4ac803f6 --- /dev/null +++ b/.github/workflows/coding-style.yml @@ -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' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 63b6d701..30ac6e3a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -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 diff --git a/.gitmodules b/.gitmodules index 3085af6a..94ad84ec 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 00000000..b7f88d9d --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,4 @@ +# Authors +Alphabetical order by first name. + +* Zoe Roux ([@AnonymusRaccoon](http://github.com/AnonymusRaccoon)) diff --git a/Dockerfile b/Dockerfile index 9158d2a0..051c3d63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 diff --git a/Kyoo.Abstractions/Controllers/IApplication.cs b/Kyoo.Abstractions/Controllers/IApplication.cs deleted file mode 100644 index 8e72280e..00000000 --- a/Kyoo.Abstractions/Controllers/IApplication.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Kyoo.Abstractions.Controllers -{ - /// - /// An interface that allow one to interact with the host and shutdown or restart the app. - /// - public interface IApplication - { - /// - /// Shutdown the process and stop gracefully. - /// - void Shutdown(); - - /// - /// Restart Kyoo from scratch, reload plugins, configurations and restart the web server. - /// - void Restart(); - - /// - /// Get the data directory - /// - /// Retrieve the data directory where runtime data should be stored - string GetDataDirectory(); - - /// - /// Retrieve the path of the json configuration file - /// (relative to the data directory, see ). - /// - /// The configuration file name. - string GetConfigFile(); - } -} \ No newline at end of file diff --git a/Kyoo.Abstractions/Controllers/ITranscoder.cs b/Kyoo.Abstractions/Controllers/ITranscoder.cs deleted file mode 100644 index d076b9f2..00000000 --- a/Kyoo.Abstractions/Controllers/ITranscoder.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Kyoo.Abstractions.Models; -using System.Threading.Tasks; - -namespace Kyoo.Abstractions.Controllers -{ - public interface ITranscoder - { - Task ExtractInfos(Episode episode, bool reextract); - Task Transmux(Episode episode); - Task Transcode(Episode episode); - } -} diff --git a/Kyoo.Abstractions/Controllers/StartupAction.cs b/Kyoo.Abstractions/Controllers/StartupAction.cs deleted file mode 100644 index fb2b29a5..00000000 --- a/Kyoo.Abstractions/Controllers/StartupAction.cs +++ /dev/null @@ -1,221 +0,0 @@ -using System; -using Microsoft.Extensions.DependencyInjection; - -namespace Kyoo.Abstractions.Controllers -{ - /// - /// A list of constant priorities used for 's . - /// It also contains helper methods for creating new . - /// - 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; - - /// - /// Create a new . - /// - /// The action to run - /// The priority of the new action - /// A new - public static StartupAction New(Action action, int priority) - => new(action, priority); - - /// - /// Create a new . - /// - /// The action to run - /// The priority of the new action - /// A dependency that this action will use. - /// A new - public static StartupAction New(Action action, int priority) - => new(action, priority); - - /// - /// Create a new . - /// - /// The action to run - /// The priority of the new action - /// A dependency that this action will use. - /// A second dependency that this action will use. - /// A new - public static StartupAction New(Action action, int priority) - => new(action, priority); - - /// - /// Create a new . - /// - /// The action to run - /// The priority of the new action - /// A dependency that this action will use. - /// A second dependency that this action will use. - /// A third dependency that this action will use. - /// A new - public static StartupAction New(Action action, int priority) - => new(action, priority); - } - - - /// - /// An action executed on kyoo's startup to initialize the asp-net container. - /// - /// - /// This is the base interface, see for a simpler use of this. - /// - public interface IStartupAction - { - /// - /// 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. - /// - int Priority { get; } - - /// - /// Run this action to configure the container, a service provider containing all services can be used. - /// - /// The service provider containing all services can be used. - void Run(IServiceProvider provider); - } - - /// - /// A with no dependencies. - /// - public class StartupAction : IStartupAction - { - /// - /// The action to execute at startup. - /// - private readonly Action _action; - - /// - public int Priority { get; } - - /// - /// Create a new . - /// - /// The action to execute on startup. - /// The priority of this action (see ). - public StartupAction(Action action, int priority) - { - _action = action; - Priority = priority; - } - - /// - public void Run(IServiceProvider provider) - { - _action.Invoke(); - } - } - - /// - /// A with one dependencies. - /// - /// The dependency to use. - public class StartupAction : IStartupAction - { - /// - /// The action to execute at startup. - /// - private readonly Action _action; - - /// - public int Priority { get; } - - /// - /// Create a new . - /// - /// The action to execute on startup. - /// The priority of this action (see ). - public StartupAction(Action action, int priority) - { - _action = action; - Priority = priority; - } - - /// - public void Run(IServiceProvider provider) - { - _action.Invoke(provider.GetRequiredService()); - } - } - - /// - /// A with two dependencies. - /// - /// The dependency to use. - /// The second dependency to use. - public class StartupAction : IStartupAction - { - /// - /// The action to execute at startup. - /// - private readonly Action _action; - - /// - public int Priority { get; } - - /// - /// Create a new . - /// - /// The action to execute on startup. - /// The priority of this action (see ). - public StartupAction(Action action, int priority) - { - _action = action; - Priority = priority; - } - - /// - public void Run(IServiceProvider provider) - { - _action.Invoke( - provider.GetRequiredService(), - provider.GetRequiredService() - ); - } - } - - /// - /// A with three dependencies. - /// - /// The dependency to use. - /// The second dependency to use. - /// The third dependency to use. - public class StartupAction : IStartupAction - { - /// - /// The action to execute at startup. - /// - private readonly Action _action; - - /// - public int Priority { get; } - - /// - /// Create a new . - /// - /// The action to execute on startup. - /// The priority of this action (see ). - public StartupAction(Action action, int priority) - { - _action = action; - Priority = priority; - } - - /// - public void Run(IServiceProvider provider) - { - _action.Invoke( - provider.GetRequiredService(), - provider.GetRequiredService(), - provider.GetRequiredService() - ); - } - } -} \ No newline at end of file diff --git a/Kyoo.Abstractions/Models/AsyncRef.cs b/Kyoo.Abstractions/Models/AsyncRef.cs deleted file mode 100644 index 26885f56..00000000 --- a/Kyoo.Abstractions/Models/AsyncRef.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Kyoo.Abstractions.Models -{ - /// - /// A class wrapping a value that will be set after the completion of the task it is related to. - /// - /// - /// This class replace the use of an out parameter on a task since tasks and out can't be combined. - /// - /// The type of the value - public class AsyncRef - { - /// - /// The value that will be set before the completion of the task. - /// - public T Value { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.Abstractions/Models/Attributes/ComputedAttribute.cs b/Kyoo.Abstractions/Models/Attributes/ComputedAttribute.cs deleted file mode 100644 index dbdfa09b..00000000 --- a/Kyoo.Abstractions/Models/Attributes/ComputedAttribute.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Kyoo.Abstractions.Models.Attributes -{ - /// - /// An attribute to inform that the property is computed automatically and can't be assigned manually. - /// - [AttributeUsage(AttributeTargets.Property)] - public class ComputedAttribute : NotMergeableAttribute { } -} \ No newline at end of file diff --git a/Kyoo.Abstractions/Models/Attributes/MergeAttributes.cs b/Kyoo.Abstractions/Models/Attributes/MergeAttributes.cs deleted file mode 100644 index 1cfc8e13..00000000 --- a/Kyoo.Abstractions/Models/Attributes/MergeAttributes.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Kyoo.Abstractions.Models.Attributes -{ - /// - /// Specify that a property can't be merged. - /// - [AttributeUsage(AttributeTargets.Property)] - public class NotMergeableAttribute : Attribute { } - - /// - /// An interface with a method called when this object is merged. - /// - public interface IOnMerge - { - /// - /// This function is called after the object has been merged. - /// - /// The object that has been merged with this. - void OnMerge(object merged); - } -} \ No newline at end of file diff --git a/Kyoo.Abstractions/Models/Attributes/PermissionAttribute.cs b/Kyoo.Abstractions/Models/Attributes/PermissionAttribute.cs deleted file mode 100644 index b343547a..00000000 --- a/Kyoo.Abstractions/Models/Attributes/PermissionAttribute.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.DependencyInjection; - -namespace Kyoo.Abstractions.Models.Permissions -{ - /// - /// The kind of permission needed. - /// - public enum Kind - { - Read, - Write, - Create, - Delete - } - - /// - /// The group of the permission. - /// - public enum Group - { - Overall, - Admin - } - - /// - /// Specify permissions needed for the API. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] - public class PermissionAttribute : Attribute, IFilterFactory - { - /// - /// The needed permission as string. - /// - public string Type { get; } - /// - /// The needed permission kind. - /// - public Kind Kind { get; } - /// - /// The group of this permission - /// - public Group Group { get; } - - /// - /// Ask a permission to run an action. - /// - /// - /// The type of the action - /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)). - /// - /// The kind of permission needed - /// - /// The group of this permission (allow grouped permission like overall.read - /// for all read permissions of this group) - /// - 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; - } - - /// - public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) - { - return serviceProvider.GetRequiredService().Create(this); - } - - /// - public bool IsReusable => true; - - /// - /// Return this permission attribute as a string - /// - /// The string representation. - public string AsPermissionString() - { - return Type; - } - } - - /// - /// Specify one part of a permissions needed for the API (the kind or the type). - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] - public class PartialPermissionAttribute : Attribute, IFilterFactory - { - /// - /// The needed permission type. - /// - public string Type { get; } - /// - /// The needed permission kind. - /// - public Kind Kind { get; } - - /// - /// Ask a permission to run an action. - /// - /// - /// 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. - /// - /// - /// The type of the action - /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)). - /// - public PartialPermissionAttribute(string type) - { - if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase)) - type = type[..^3]; - Type = type.ToLower(); - } - - /// - /// Ask a permission to run an action. - /// - /// - /// 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. - /// - /// The kind of permission needed - public PartialPermissionAttribute(Kind permission) - { - Kind = permission; - } - - /// - public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) - { - return serviceProvider.GetRequiredService().Create(this); - } - - /// - public bool IsReusable => true; - } - - - /// - /// A service to validate permissions - /// - public interface IPermissionValidator - { - /// - /// Create an IAuthorizationFilter that will be used to validate permissions. - /// This can registered with any lifetime. - /// - /// The permission attribute to validate - /// An authorization filter used to validate the permission - IFilterMetadata Create(PermissionAttribute attribute); - - /// - /// Create an IAuthorizationFilter that will be used to validate permissions. - /// This can registered with any lifetime. - /// - /// - /// A partial attribute to validate. See . - /// - /// An authorization filter used to validate the permission - IFilterMetadata Create(PartialPermissionAttribute attribute); - } -} \ No newline at end of file diff --git a/Kyoo.Authentication/Models/DTO/AccountUpdateRequest.cs b/Kyoo.Authentication/Models/DTO/AccountUpdateRequest.cs deleted file mode 100644 index ac135799..00000000 --- a/Kyoo.Authentication/Models/DTO/AccountUpdateRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Microsoft.AspNetCore.Http; - -namespace Kyoo.Authentication.Models.DTO -{ - /// - /// A model only used on account update requests. - /// - public class AccountUpdateRequest - { - /// - /// The new email address of the user - /// - [EmailAddress(ErrorMessage = "The email is invalid.")] - public string Email { get; set; } - - /// - /// The new username of the user. - /// - [MinLength(4, ErrorMessage = "The username must have at least 4 characters")] - public string Username { get; set; } - - /// - /// The picture icon. - /// - public IFormFile Picture { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.Authentication/Models/DTO/LoginRequest.cs b/Kyoo.Authentication/Models/DTO/LoginRequest.cs deleted file mode 100644 index 9bee4e04..00000000 --- a/Kyoo.Authentication/Models/DTO/LoginRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Kyoo.Authentication.Models.DTO -{ - /// - /// A model only used on login requests. - /// - public class LoginRequest - { - /// - /// The user's username. - /// - public string Username { get; set; } - - /// - /// The user's password. - /// - public string Password { get; set; } - - /// - /// Should the user stay logged in? If true a cookie will be put. - /// - public bool StayLoggedIn { get; set; } - - /// - /// The return url of the login flow. - /// - public string ReturnURL { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.Authentication/Models/DTO/OtacRequest.cs b/Kyoo.Authentication/Models/DTO/OtacRequest.cs deleted file mode 100644 index 0c007f78..00000000 --- a/Kyoo.Authentication/Models/DTO/OtacRequest.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Kyoo.Authentication.Models.DTO -{ - /// - /// A model to represent an otac request - /// - public class OtacRequest - { - /// - /// The One Time Access Code - /// - public string Otac { get; set; } - - /// - /// Should the user stay logged - /// - public bool StayLoggedIn { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.Authentication/Models/Options/AuthenticationOption.cs b/Kyoo.Authentication/Models/Options/AuthenticationOption.cs deleted file mode 100644 index 23e917aa..00000000 --- a/Kyoo.Authentication/Models/Options/AuthenticationOption.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Kyoo.Authentication.Models -{ - /// - /// The main authentication options. - /// - public class AuthenticationOption - { - /// - /// The path to get this option from the root configuration. - /// - public const string Path = "authentication"; - - /// - /// The options for certificates - /// - public CertificateOption Certificate { get; set; } - - /// - /// Options for permissions - /// - public PermissionOption Permissions { get; set; } - - /// - /// Root path of user's profile pictures. - /// - public string ProfilePicturePath { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.Authentication/Models/Options/CertificateOption.cs b/Kyoo.Authentication/Models/Options/CertificateOption.cs deleted file mode 100644 index 93d2a878..00000000 --- a/Kyoo.Authentication/Models/Options/CertificateOption.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Kyoo.Authentication.Models -{ - /// - /// A typed option model for the certificate - /// - public class CertificateOption - { - /// - /// The path to get this option from the root configuration. - /// - public const string Path = "authentication:certificate"; - - /// - /// The path of the certificate file. - /// - public string File { get; set; } - /// - /// The path of the old certificate file. - /// - public string OldFile { get; set; } - /// - /// The password of the certificates. - /// - public string Password { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.Authentication/Models/Options/PermissionOption.cs b/Kyoo.Authentication/Models/Options/PermissionOption.cs deleted file mode 100644 index 8d6c698d..00000000 --- a/Kyoo.Authentication/Models/Options/PermissionOption.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Kyoo.Authentication.Models -{ - /// - /// Permission options. - /// - public class PermissionOption - { - /// - /// The path to get this option from the root configuration. - /// - public const string Path = "authentication:permissions"; - - /// - /// The default permissions that will be given to a non-connected user. - /// - public string[] Default { get; set; } - - /// - /// Permissions applied to a new user. - /// - public string[] NewUser { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs b/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs deleted file mode 100644 index 914835bf..00000000 --- a/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Kyoo.Abstractions.Models.Permissions; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Logging; - -namespace Kyoo.Core.Controllers -{ - /// - /// A permission validator that always validate permissions. This effectively disable the permission system. - /// - public class PassthroughPermissionValidator : IPermissionValidator - { - // ReSharper disable once SuggestBaseTypeForParameter - public PassthroughPermissionValidator(ILogger logger) - { - logger.LogWarning("No permission validator has been enabled, all users will have all permissions"); - } - - /// - public IFilterMetadata Create(PermissionAttribute attribute) - { - return new PassthroughValidator(); - } - - /// - public IFilterMetadata Create(PartialPermissionAttribute attribute) - { - return new PassthroughValidator(); - } - - /// - /// An useless filter that does nothing. - /// - private class PassthroughValidator : IFilterMetadata { } - } -} \ No newline at end of file diff --git a/Kyoo.Core/Models/Options/MediaOptions.cs b/Kyoo.Core/Models/Options/MediaOptions.cs deleted file mode 100644 index 3133e8d2..00000000 --- a/Kyoo.Core/Models/Options/MediaOptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Kyoo.Core.Models.Options -{ - /// - /// Options for media registering. - /// - public class MediaOptions - { - /// - /// The path of this options - /// - public const string Path = "Media"; - - /// - /// A regex for episodes - /// - public string[] Regex { get; set; } - - /// - /// A regex for subtitles - /// - public string[] SubtitleRegex { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.Core/Models/Options/TaskOptions.cs b/Kyoo.Core/Models/Options/TaskOptions.cs deleted file mode 100644 index 89b77687..00000000 --- a/Kyoo.Core/Models/Options/TaskOptions.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using JetBrains.Annotations; - -namespace Kyoo.Core.Models.Options -{ - /// - /// Options related to tasks - /// - public class TaskOptions - { - /// - /// The path of this options - /// - public const string Path = "Tasks"; - - /// - /// The number of tasks that can be run concurrently. - /// - public int Parallels { get; set; } - - /// - /// The delay of tasks that should be automatically started at fixed times. - /// - [UsedImplicitly] - public Dictionary Scheduled { get; set; } = new(); - } -} \ No newline at end of file diff --git a/Kyoo.Core/Views/Helper/JsonSerializer.cs b/Kyoo.Core/Views/Helper/JsonSerializer.cs deleted file mode 100644 index 96d6d6ea..00000000 --- a/Kyoo.Core/Views/Helper/JsonSerializer.cs +++ /dev/null @@ -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(); - 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() != null) - property.ShouldSerialize = _ => false; - if (member.GetCustomAttribute() != 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(); - 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 - { - public override void WriteJson(JsonWriter writer, PeopleRole value, JsonSerializer serializer) - { - ICollection oldPeople = value.Show?.People; - ICollection 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, @"(? - { - 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. - } - } -} \ No newline at end of file diff --git a/Kyoo.Core/Views/SubtitleApi.cs b/Kyoo.Core/Views/SubtitleApi.cs deleted file mode 100644 index 04ddf1d5..00000000 --- a/Kyoo.Core/Views/SubtitleApi.cs +++ /dev/null @@ -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 GetSubtitle(int id) - { - Track subtitle = await _libraryManager.GetOrDefault(id); - return subtitle != null - ? _files.FileResult(subtitle.Path) - : NotFound(); - } - - [HttpGet("{id:int}.{extension}")] - [Permission(nameof(SubtitleApi), Kind.Read)] - public async Task GetSubtitle(int id, string extension) - { - Track subtitle = await _libraryManager.GetOrDefault(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 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.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 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 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 ConvertBlock(IList 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; - } - } -} diff --git a/Kyoo.Core/Views/WatchApi.cs b/Kyoo.Core/Views/WatchApi.cs deleted file mode 100644 index f310c258..00000000 --- a/Kyoo.Core/Views/WatchApi.cs +++ /dev/null @@ -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> GetWatchItem(string slug) - { - try - { - Episode item = await _libraryManager.Get(slug); - return await WatchItem.FromEpisode(item, _libraryManager); - } - catch (ItemNotFoundException) - { - return NotFound(); - } - } - } -} diff --git a/Kyoo.Host.Console/Program.cs b/Kyoo.Host.Console/Program.cs deleted file mode 100644 index 6d5edb49..00000000 --- a/Kyoo.Host.Console/Program.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading.Tasks; -using Kyoo.Core; -using Microsoft.AspNetCore.Hosting; - -namespace Kyoo.Host.Console -{ - /// - /// Program entrypoint. - /// - public static class Program - { - /// - /// The string representation of the environment used in . - /// -#if DEBUG - private const string Environment = "Development"; -#else - private const string Environment = "Production"; -#endif - - /// - /// Main function of the program - /// - /// Command line arguments - public static Task Main(string[] args) - { - Application application = new(Environment); - return application.Start(args); - } - } -} diff --git a/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.csproj b/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.csproj deleted file mode 100644 index 41ab83db..00000000 --- a/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - true - - - - - - - - - \ No newline at end of file diff --git a/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.linux.target b/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.linux.target deleted file mode 100644 index e60b9c2a..00000000 --- a/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.linux.target +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - net5.0 - NU1503 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Kyoo.Host.WindowsTrait/Program.cs b/Kyoo.Host.WindowsTrait/Program.cs deleted file mode 100644 index 65b9a2bc..00000000 --- a/Kyoo.Host.WindowsTrait/Program.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Threading.Tasks; -using Autofac; -using Kyoo.Core; - -namespace Kyoo.Host.WindowsTrait -{ - public static class Program - { - /// - /// The string representation of the environment used in IWebHostEnvironment. - /// -#if DEBUG - private const string Environment = "Development"; -#else - private const string Environment = "Production"; -#endif - - /// - /// 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. - /// - public static Task Main(string[] args) - { - Application application = new(Environment); - return application.Start(args, builder => - { - builder.RegisterType().As().SingleInstance(); - }); - } - } -} \ No newline at end of file diff --git a/Kyoo.Postgresql/Migrations/20210801171613_Initial.cs b/Kyoo.Postgresql/Migrations/20210801171613_Initial.cs deleted file mode 100644 index 1f336f4e..00000000 --- a/Kyoo.Postgresql/Migrations/20210801171613_Initial.cs +++ /dev/null @@ -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(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: false), - name = table.Column(type: "text", nullable: true), - images = table.Column>(type: "jsonb", nullable: true), - overview = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_collections", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "genres", - columns: table => new - { - id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: false), - name = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_genres", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "libraries", - columns: table => new - { - id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: false), - name = table.Column(type: "text", nullable: true), - paths = table.Column(type: "text[]", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_libraries", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "people", - columns: table => new - { - id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: false), - name = table.Column(type: "text", nullable: true), - images = table.Column>(type: "jsonb", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_people", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "providers", - columns: table => new - { - id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: false), - name = table.Column(type: "text", nullable: true), - images = table.Column>(type: "jsonb", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_providers", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "studios", - columns: table => new - { - id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: false), - name = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_studios", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "users", - columns: table => new - { - id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: false), - username = table.Column(type: "text", nullable: true), - email = table.Column(type: "text", nullable: true), - password = table.Column(type: "text", nullable: true), - permissions = table.Column(type: "text[]", nullable: true), - extra_data = table.Column>(type: "jsonb", nullable: true), - images = table.Column>(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(type: "integer", nullable: false), - library_id = table.Column(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(type: "integer", nullable: false), - provider_id = table.Column(type: "integer", nullable: false), - data_id = table.Column(type: "text", nullable: true), - link = table.Column(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(type: "integer", nullable: false), - provider_id = table.Column(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(type: "integer", nullable: false), - provider_id = table.Column(type: "integer", nullable: false), - data_id = table.Column(type: "text", nullable: true), - link = table.Column(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(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: false), - title = table.Column(type: "text", nullable: true), - aliases = table.Column(type: "text[]", nullable: true), - path = table.Column(type: "text", nullable: true), - overview = table.Column(type: "text", nullable: true), - status = table.Column(type: "status", nullable: false), - start_air = table.Column(type: "timestamp without time zone", nullable: true), - end_air = table.Column(type: "timestamp without time zone", nullable: true), - images = table.Column>(type: "jsonb", nullable: true), - is_movie = table.Column(type: "boolean", nullable: false), - studio_id = table.Column(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(type: "integer", nullable: false), - provider_id = table.Column(type: "integer", nullable: false), - data_id = table.Column(type: "text", nullable: true), - link = table.Column(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(type: "integer", nullable: false), - show_id = table.Column(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(type: "integer", nullable: false), - show_id = table.Column(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(type: "integer", nullable: false), - show_id = table.Column(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(type: "integer", nullable: false), - watched_id = table.Column(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(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - people_id = table.Column(type: "integer", nullable: false), - show_id = table.Column(type: "integer", nullable: false), - type = table.Column(type: "text", nullable: true), - role = table.Column(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(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: true), - show_id = table.Column(type: "integer", nullable: false), - season_number = table.Column(type: "integer", nullable: false), - title = table.Column(type: "text", nullable: true), - overview = table.Column(type: "text", nullable: true), - start_date = table.Column(type: "timestamp without time zone", nullable: true), - end_date = table.Column(type: "timestamp without time zone", nullable: true), - images = table.Column>(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(type: "integer", nullable: false), - provider_id = table.Column(type: "integer", nullable: false), - data_id = table.Column(type: "text", nullable: true), - link = table.Column(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(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: true), - show_id = table.Column(type: "integer", nullable: false), - season_id = table.Column(type: "integer", nullable: true), - season_number = table.Column(type: "integer", nullable: true), - episode_number = table.Column(type: "integer", nullable: true), - absolute_number = table.Column(type: "integer", nullable: true), - path = table.Column(type: "text", nullable: true), - images = table.Column>(type: "jsonb", nullable: true), - title = table.Column(type: "text", nullable: true), - overview = table.Column(type: "text", nullable: true), - release_date = table.Column(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(type: "integer", nullable: false), - provider_id = table.Column(type: "integer", nullable: false), - data_id = table.Column(type: "text", nullable: true), - link = table.Column(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(type: "integer", nullable: false), - provider_id = table.Column(type: "integer", nullable: false), - data_id = table.Column(type: "text", nullable: true), - link = table.Column(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(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - slug = table.Column(type: "text", nullable: true), - title = table.Column(type: "text", nullable: true), - language = table.Column(type: "text", nullable: true), - codec = table.Column(type: "text", nullable: true), - is_default = table.Column(type: "boolean", nullable: false), - is_forced = table.Column(type: "boolean", nullable: false), - is_external = table.Column(type: "boolean", nullable: false), - path = table.Column(type: "text", nullable: true), - type = table.Column(type: "stream_type", nullable: false), - episode_id = table.Column(type: "integer", nullable: false), - track_index = table.Column(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(type: "integer", nullable: false), - episode_id = table.Column(type: "integer", nullable: false), - watched_percentage = table.Column(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"); - } - } -} diff --git a/Kyoo.SqLite/Migrations/20210801171534_Initial.cs b/Kyoo.SqLite/Migrations/20210801171534_Initial.cs deleted file mode 100644 index a7e62b03..00000000 --- a/Kyoo.SqLite/Migrations/20210801171534_Initial.cs +++ /dev/null @@ -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(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: true), - Images = table.Column(type: "TEXT", nullable: true), - Overview = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Collections", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Genres", - columns: table => new - { - ID = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Genres", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Libraries", - columns: table => new - { - ID = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: true), - Paths = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Libraries", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "People", - columns: table => new - { - ID = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: true), - Images = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_People", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Providers", - columns: table => new - { - ID = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: true), - Images = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Providers", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Studios", - columns: table => new - { - ID = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Studios", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Users", - columns: table => new - { - ID = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: false), - Username = table.Column(type: "TEXT", nullable: true), - Email = table.Column(type: "TEXT", nullable: true), - Password = table.Column(type: "TEXT", nullable: true), - Permissions = table.Column(type: "TEXT", nullable: true), - ExtraData = table.Column(type: "TEXT", nullable: true), - Images = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Users", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "LinkLibraryCollection", - columns: table => new - { - CollectionID = table.Column(type: "INTEGER", nullable: false), - LibraryID = table.Column(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(type: "INTEGER", nullable: false), - ProviderID = table.Column(type: "INTEGER", nullable: false), - DataID = table.Column(type: "TEXT", nullable: true), - Link = table.Column(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(type: "INTEGER", nullable: false), - ProviderID = table.Column(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(type: "INTEGER", nullable: false), - ProviderID = table.Column(type: "INTEGER", nullable: false), - DataID = table.Column(type: "TEXT", nullable: true), - Link = table.Column(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(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: false), - Title = table.Column(type: "TEXT", nullable: true), - Aliases = table.Column(type: "TEXT", nullable: true), - Path = table.Column(type: "TEXT", nullable: true), - Overview = table.Column(type: "TEXT", nullable: true), - Status = table.Column(type: "INTEGER", nullable: false), - StartAir = table.Column(type: "TEXT", nullable: true), - EndAir = table.Column(type: "TEXT", nullable: true), - Images = table.Column(type: "TEXT", nullable: true), - IsMovie = table.Column(type: "INTEGER", nullable: false), - StudioID = table.Column(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(type: "INTEGER", nullable: false), - ProviderID = table.Column(type: "INTEGER", nullable: false), - DataID = table.Column(type: "TEXT", nullable: true), - Link = table.Column(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(type: "INTEGER", nullable: false), - ShowID = table.Column(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(type: "INTEGER", nullable: false), - ShowID = table.Column(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(type: "INTEGER", nullable: false), - ShowID = table.Column(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(type: "INTEGER", nullable: false), - WatchedID = table.Column(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(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - PeopleID = table.Column(type: "INTEGER", nullable: false), - ShowID = table.Column(type: "INTEGER", nullable: false), - Type = table.Column(type: "TEXT", nullable: true), - Role = table.Column(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(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: true), - ShowID = table.Column(type: "INTEGER", nullable: false), - SeasonNumber = table.Column(type: "INTEGER", nullable: false), - Title = table.Column(type: "TEXT", nullable: true), - Overview = table.Column(type: "TEXT", nullable: true), - StartDate = table.Column(type: "TEXT", nullable: true), - EndDate = table.Column(type: "TEXT", nullable: true), - Images = table.Column(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(type: "INTEGER", nullable: false), - ProviderID = table.Column(type: "INTEGER", nullable: false), - DataID = table.Column(type: "TEXT", nullable: true), - Link = table.Column(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(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: true), - ShowID = table.Column(type: "INTEGER", nullable: false), - SeasonID = table.Column(type: "INTEGER", nullable: true), - SeasonNumber = table.Column(type: "INTEGER", nullable: true), - EpisodeNumber = table.Column(type: "INTEGER", nullable: true), - AbsoluteNumber = table.Column(type: "INTEGER", nullable: true), - Path = table.Column(type: "TEXT", nullable: true), - Images = table.Column(type: "TEXT", nullable: true), - Title = table.Column(type: "TEXT", nullable: true), - Overview = table.Column(type: "TEXT", nullable: true), - ReleaseDate = table.Column(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(type: "INTEGER", nullable: false), - ProviderID = table.Column(type: "INTEGER", nullable: false), - DataID = table.Column(type: "TEXT", nullable: true), - Link = table.Column(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(type: "INTEGER", nullable: false), - ProviderID = table.Column(type: "INTEGER", nullable: false), - DataID = table.Column(type: "TEXT", nullable: true), - Link = table.Column(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(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Slug = table.Column(type: "TEXT", nullable: true), - Title = table.Column(type: "TEXT", nullable: true), - Language = table.Column(type: "TEXT", nullable: true), - Codec = table.Column(type: "TEXT", nullable: true), - IsDefault = table.Column(type: "INTEGER", nullable: false), - IsForced = table.Column(type: "INTEGER", nullable: false), - IsExternal = table.Column(type: "INTEGER", nullable: false), - Path = table.Column(type: "TEXT", nullable: true), - Type = table.Column(type: "INTEGER", nullable: false), - EpisodeID = table.Column(type: "INTEGER", nullable: false), - TrackIndex = table.Column(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(type: "INTEGER", nullable: false), - EpisodeID = table.Column(type: "INTEGER", nullable: false), - WatchedPercentage = table.Column(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"); - } - } -} diff --git a/Kyoo.TheMovieDb/TheMovieDbOptions.cs b/Kyoo.TheMovieDb/TheMovieDbOptions.cs deleted file mode 100644 index 2387f553..00000000 --- a/Kyoo.TheMovieDb/TheMovieDbOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Kyoo.TheMovieDb.Models -{ - /// - /// The option containing the api key for TheMovieDb. - /// - public class TheMovieDbOptions - { - /// - /// The path to get this option from the root configuration. - /// - public const string Path = "the-moviedb"; - - /// - /// The api key of TheMovieDb. - /// - public string ApiKey { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.TheTvdb/TvdbOption.cs b/Kyoo.TheTvdb/TvdbOption.cs deleted file mode 100644 index 9a884b24..00000000 --- a/Kyoo.TheTvdb/TvdbOption.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Kyoo.TheTvdb.Models -{ - /// - /// The option containing the api key for the tvdb. - /// - public class TvdbOption - { - /// - /// The path to get this option from the root configuration. - /// - public const string Path = "tvdb"; - - /// - /// The api key of the tvdb. - /// - public string ApiKey { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.ruleset b/Kyoo.ruleset new file mode 100644 index 00000000..f4a47d25 --- /dev/null +++ b/Kyoo.ruleset @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kyoo.sln b/Kyoo.sln index 39e1cc4e..faab841f 100644 --- a/Kyoo.sln +++ b/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 diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 00000000..b9d5b35c --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,29 @@ + + + true + true + true + + + + + + true + + + + + + + + + + + + true + CS1591;SA1600;SA1601 + true + $(MSBuildThisFileDirectory)../Kyoo.ruleset + + + diff --git a/Kyoo.Abstractions/.gitignore b/src/Kyoo.Abstractions/.gitignore similarity index 100% rename from Kyoo.Abstractions/.gitignore rename to src/Kyoo.Abstractions/.gitignore diff --git a/src/Kyoo.Abstractions/Controllers/IApplication.cs b/src/Kyoo.Abstractions/Controllers/IApplication.cs new file mode 100644 index 00000000..11c396dd --- /dev/null +++ b/src/Kyoo.Abstractions/Controllers/IApplication.cs @@ -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 . + +namespace Kyoo.Abstractions.Controllers +{ + /// + /// An interface that allow one to interact with the host and shutdown or restart the app. + /// + public interface IApplication + { + /// + /// Shutdown the process and stop gracefully. + /// + void Shutdown(); + + /// + /// Restart Kyoo from scratch, reload plugins, configurations and restart the web server. + /// + void Restart(); + + /// + /// Get the data directory. + /// + /// Retrieve the data directory where runtime data should be stored. + string GetDataDirectory(); + + /// + /// Retrieve the path of the json configuration file + /// (relative to the data directory, see ). + /// + /// The configuration file name. + string GetConfigFile(); + } +} diff --git a/Kyoo.Abstractions/Controllers/IConfigurationManager.cs b/src/Kyoo.Abstractions/Controllers/IConfigurationManager.cs similarity index 69% rename from Kyoo.Abstractions/Controllers/IConfigurationManager.cs rename to src/Kyoo.Abstractions/Controllers/IConfigurationManager.cs index 73c649d1..b5c57565 100644 --- a/Kyoo.Abstractions/Controllers/IConfigurationManager.cs +++ b/src/Kyoo.Abstractions/Controllers/IConfigurationManager.cs @@ -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 . + using System; using System.Threading.Tasks; using JetBrains.Annotations; @@ -14,12 +32,12 @@ namespace Kyoo.Abstractions.Controllers public interface IConfigurationManager { /// - /// Add an editable configuration to the editable configuration list + /// Add an editable configuration to the editable configuration list. /// /// The root path of the editable configuration. It should not be a nested type. - /// The type of the configuration + /// The type of the configuration. void AddTyped(string path); - + /// /// 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 /// The root path of the editable configuration. It should not be a nested type. /// The type of the configuration or null. void Register(string path, [CanBeNull] Type type); - + /// /// Get the value of a setting using it's path. /// - /// The path of the resource (can be separated by ':' or '__') + /// The path of the resource (can be separated by ':' or '__'). /// No setting found at the given path. - /// The value of the settings (if it's a strongly typed one, the given type is instantiated + /// The value of the settings (if it's a strongly typed one, the given type is instantiated. object GetValue(string path); - + /// /// Get the value of a setting using it's path. /// If your don't need a strongly typed value, see . /// - /// The path of the resource (can be separated by ':' or '__') + /// The path of the resource (can be separated by ':' or '__'). /// A type to strongly type your option. - /// If your type is not the same as the registered type + /// If your type is not the same as the registered type. /// No setting found at the given path. - /// The value of the settings (if it's a strongly typed one, the given type is instantiated + /// The value of the settings (if it's a strongly typed one, the given type is instantiated. T GetValue(string path); - + /// /// Edit the value of a setting using it's path. Save it to the json file. /// - /// The path of the resource (can be separated by ':' or '__') - /// The new value of the resource + /// The path of the resource (can be separated by ':' or '__'). + /// The new value of the resource. /// No setting found at the given path. + /// A representing the asynchronous operation. Task EditValue(string path, object value); } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Controllers/IFileSystem.cs b/src/Kyoo.Abstractions/Controllers/IFileSystem.cs similarity index 81% rename from Kyoo.Abstractions/Controllers/IFileSystem.cs rename to src/Kyoo.Abstractions/Controllers/IFileSystem.cs index 36c5dd3b..a8cfd96c 100644 --- a/Kyoo.Abstractions/Controllers/IFileSystem.cs +++ b/src/Kyoo.Abstractions/Controllers/IFileSystem.cs @@ -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 . + using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -8,7 +26,8 @@ using Microsoft.AspNetCore.Mvc; namespace Kyoo.Abstractions.Controllers { /// - /// 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). /// public interface IFileSystem { @@ -16,10 +35,10 @@ namespace Kyoo.Abstractions.Controllers /// /// 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. /// /// - /// 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. /// /// The path of the file. @@ -42,7 +61,7 @@ namespace Kyoo.Abstractions.Controllers /// If the file could not be found. /// A reader to read the file. public Task GetReader([NotNull] string path); - + /// /// Read a file present at . The reader can be used in an arbitrary context. /// To return files from an http endpoint, use . @@ -80,7 +99,7 @@ namespace Kyoo.Abstractions.Controllers /// The path of the directory /// Should the search be recursive or not. /// A list of files's path. - public Task> ListFiles([NotNull] string path, + public Task> ListFiles([NotNull] string path, SearchOption options = SearchOption.TopDirectoryOnly); /// @@ -100,4 +119,4 @@ namespace Kyoo.Abstractions.Controllers /// The extra directory of the resource. public Task GetExtraDirectory([NotNull] T resource); } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Controllers/IIdentifier.cs b/src/Kyoo.Abstractions/Controllers/IIdentifier.cs similarity index 62% rename from Kyoo.Abstractions/Controllers/IIdentifier.cs rename to src/Kyoo.Abstractions/Controllers/IIdentifier.cs index 8a9d07ed..dd7ce855 100644 --- a/Kyoo.Abstractions/Controllers/IIdentifier.cs +++ b/src/Kyoo.Abstractions/Controllers/IIdentifier.cs @@ -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 . + 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. /// Task<(Collection, Show, Season, Episode)> Identify(string path); - + /// /// Identify an external subtitle or track file from it's path and return the parsed metadata. /// @@ -34,4 +52,4 @@ namespace Kyoo.Abstractions.Controllers /// Task IdentifyTrack(string path); } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Controllers/ILibraryManager.cs b/src/Kyoo.Abstractions/Controllers/ILibraryManager.cs similarity index 82% rename from Kyoo.Abstractions/Controllers/ILibraryManager.cs rename to src/Kyoo.Abstractions/Controllers/ILibraryManager.cs index 856becb7..f4218760 100644 --- a/Kyoo.Abstractions/Controllers/ILibraryManager.cs +++ b/src/Kyoo.Abstractions/Controllers/ILibraryManager.cs @@ -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 . + +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 { /// - /// 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. /// public interface ILibraryManager { @@ -20,68 +38,69 @@ namespace Kyoo.Abstractions.Controllers /// The type you want /// If the item is not found /// The repository corresponding - IRepository GetRepository() where T : class, IResource; + IRepository GetRepository() + where T : class, IResource; /// /// The repository that handle libraries. /// ILibraryRepository LibraryRepository { get; } - + /// - /// The repository that handle libraries's items (a wrapper arround shows & collections). + /// The repository that handle libraries items (a wrapper around shows and collections). /// ILibraryItemRepository LibraryItemRepository { get; } - + /// /// The repository that handle collections. /// ICollectionRepository CollectionRepository { get; } - + /// /// The repository that handle shows. /// IShowRepository ShowRepository { get; } - + /// /// The repository that handle seasons. /// ISeasonRepository SeasonRepository { get; } - + /// /// The repository that handle episodes. /// IEpisodeRepository EpisodeRepository { get; } - + /// /// The repository that handle tracks. /// ITrackRepository TrackRepository { get; } - + /// /// The repository that handle people. /// IPeopleRepository PeopleRepository { get; } - + /// /// The repository that handle studios. /// IStudioRepository StudioRepository { get; } - + /// /// The repository that handle genres. /// IGenreRepository GenreRepository { get; } - + /// /// The repository that handle providers. /// IProviderRepository ProviderRepository { get; } - + /// /// The repository that handle users. /// IUserRepository UserRepository { get; } - + /// /// Get the resource by it's ID /// @@ -90,8 +109,9 @@ namespace Kyoo.Abstractions.Controllers /// If the item is not found /// The resource found [ItemNotNull] - Task Get(int id) where T : class, IResource; - + Task Get(int id) + where T : class, IResource; + /// /// Get the resource by it's slug /// @@ -100,8 +120,9 @@ namespace Kyoo.Abstractions.Controllers /// If the item is not found /// The resource found [ItemNotNull] - Task Get(string slug) where T : class, IResource; - + Task Get(string slug) + where T : class, IResource; + /// /// Get the resource by a filter function. /// @@ -110,7 +131,8 @@ namespace Kyoo.Abstractions.Controllers /// If the item is not found /// The first resource found that match the where function [ItemNotNull] - Task Get(Expression> where) where T : class, IResource; + Task Get(Expression> where) + where T : class, IResource; /// /// Get a season from it's showID and it's seasonNumber @@ -121,7 +143,7 @@ namespace Kyoo.Abstractions.Controllers /// The season found [ItemNotNull] Task Get(int showID, int seasonNumber); - + /// /// Get a season from it's show slug and it's seasonNumber /// @@ -131,7 +153,7 @@ namespace Kyoo.Abstractions.Controllers /// The season found [ItemNotNull] Task Get(string showSlug, int seasonNumber); - + /// /// Get a episode from it's showID, it's seasonNumber and it's episode number. /// @@ -142,7 +164,7 @@ namespace Kyoo.Abstractions.Controllers /// The episode found [ItemNotNull] Task Get(int showID, int seasonNumber, int episodeNumber); - + /// /// Get a episode from it's show slug, it's seasonNumber and it's episode number. /// @@ -161,8 +183,9 @@ namespace Kyoo.Abstractions.Controllers /// The type of the resource /// The resource found [ItemCanBeNull] - Task GetOrDefault(int id) where T : class, IResource; - + Task GetOrDefault(int id) + where T : class, IResource; + /// /// Get the resource by it's slug or null if it is not found. /// @@ -170,8 +193,9 @@ namespace Kyoo.Abstractions.Controllers /// The type of the resource /// The resource found [ItemCanBeNull] - Task GetOrDefault(string slug) where T : class, IResource; - + Task GetOrDefault(string slug) + where T : class, IResource; + /// /// Get the resource by a filter function or null if it is not found. /// @@ -179,7 +203,8 @@ namespace Kyoo.Abstractions.Controllers /// The type of the resource /// The first resource found that match the where function [ItemCanBeNull] - Task GetOrDefault(Expression> where) where T : class, IResource; + Task GetOrDefault(Expression> where) + where T : class, IResource; /// /// 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 /// The season found [ItemCanBeNull] Task GetOrDefault(int showID, int seasonNumber); - + /// /// Get a season from it's show slug and it's seasonNumber or null if it is not found. /// @@ -198,7 +223,7 @@ namespace Kyoo.Abstractions.Controllers /// The season found [ItemCanBeNull] Task GetOrDefault(string showSlug, int seasonNumber); - + /// /// Get a episode from it's showID, it's seasonNumber and it's episode number or null if it is not found. /// @@ -208,7 +233,7 @@ namespace Kyoo.Abstractions.Controllers /// The episode found [ItemCanBeNull] Task GetOrDefault(int showID, int seasonNumber, int episodeNumber); - + /// /// Get a episode from it's show slug, it's seasonNumber and it's episode number or null if it is not found. /// @@ -219,20 +244,19 @@ namespace Kyoo.Abstractions.Controllers [ItemCanBeNull] Task GetOrDefault(string showSlug, int seasonNumber, int episodeNumber); - /// /// Load a related resource /// /// The source object. /// A getter function for the member to load /// - /// true if you want to load the relation even if it is not null, false otherwise. + /// true if you want to load the relation even if it is not null, false otherwise. /// /// The type of the source object /// The related resource's type - /// The param + /// The param /// - /// + /// /// Task Load([NotNull] T obj, Expression> member, bool force = false) where T : class, IResource @@ -244,13 +268,13 @@ namespace Kyoo.Abstractions.Controllers /// The source object. /// A getter function for the member to load /// - /// true if you want to load the relation even if it is not null, false otherwise. + /// true if you want to load the relation even if it is not null, false otherwise. /// /// The type of the source object /// The related resource's type - /// The param + /// The param /// - /// + /// /// Task Load([NotNull] T obj, Expression>> member, bool force = false) where T : class, IResource @@ -262,10 +286,10 @@ namespace Kyoo.Abstractions.Controllers /// The source object. /// The name of the resource to load (case sensitive) /// - /// true if you want to load the relation even if it is not null, false otherwise. + /// true if you want to load the relation even if it is not null, false otherwise. /// /// The type of the source object - /// The param + /// The param /// /// /// @@ -273,33 +297,34 @@ namespace Kyoo.Abstractions.Controllers where T : class, IResource; /// - /// Load a related resource without specifing it's type. + /// Load a related resource without specifying it's type. /// /// The source object. /// The name of the resource to load (case sensitive) /// - /// true if you want to load the relation even if it is not null, false otherwise. + /// true if you want to load the relation even if it is not null, false otherwise. /// /// /// - /// + /// + /// A representing the asynchronous operation. Task Load([NotNull] IResource obj, string memberName, bool force = false); - + /// - /// Get items (A wrapper arround shows or collections) from a library. + /// Get items (A wrapper around shows or collections) from a library. /// /// The ID of the library /// A filter function - /// Sort informations (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetItemsFromLibrary(int id, Expression> where = null, Sort sort = default, Pagination limit = default); - + /// - /// Get items (A wrapper arround shows or collections) from a library. + /// Get items (A wrapper around shows or collections) from a library. /// /// The ID of the library /// A filter function @@ -311,22 +336,22 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetItemsFromLibrary(id, where, new Sort(sort), limit); - + /// - /// Get items (A wrapper arround shows or collections) from a library. + /// Get items (A wrapper around shows or collections) from a library. /// /// The slug of the library /// A filter function - /// Sort informations (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetItemsFromLibrary(string slug, Expression> where = null, Sort sort = default, Pagination limit = default); - + /// - /// Get items (A wrapper arround shows or collections) from a library. + /// Get items (A wrapper around shows or collections) from a library. /// /// The slug of the library /// A filter function @@ -338,21 +363,20 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetItemsFromLibrary(slug, where, new Sort(sort), limit); - - + /// /// Get people's roles from a show. /// /// The ID of the show /// A filter function - /// Sort informations (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetPeopleFromShow(int showID, - Expression> where = null, + Expression> where = null, Sort sort = default, Pagination limit = default); - + /// /// Get people's roles from a show. /// @@ -366,20 +390,20 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetPeopleFromShow(showID, where, new Sort(sort), limit); - + /// /// Get people's roles from a show. /// /// The slug of the show /// A filter function - /// Sort informations (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetPeopleFromShow(string showSlug, - Expression> where = null, + Expression> where = null, Sort sort = default, Pagination limit = default); - + /// /// Get people's roles from a show. /// @@ -393,21 +417,20 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetPeopleFromShow(showSlug, where, new Sort(sort), limit); - - + /// /// Get people's roles from a person. /// /// The id of the person /// A filter function - /// Sort informations (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetRolesFromPeople(int id, - Expression> where = null, + Expression> where = null, Sort sort = default, Pagination limit = default); - + /// /// Get people's roles from a person. /// @@ -421,20 +444,20 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetRolesFromPeople(id, where, new Sort(sort), limit); - + /// /// Get people's roles from a person. /// /// The slug of the person /// A filter function - /// Sort informations (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetRolesFromPeople(string slug, - Expression> where = null, + Expression> where = null, Sort sort = default, Pagination limit = default); - + /// /// Get people's roles from a person. /// @@ -449,35 +472,37 @@ namespace Kyoo.Abstractions.Controllers Pagination limit = default ) => GetRolesFromPeople(slug, where, new Sort(sort), limit); - /// /// Setup relations between a show, a library and a collection /// /// The show's ID to setup relations with /// The library's ID to setup relations with (optional) /// The collection's ID to setup relations with (optional) + /// A representing the asynchronous operation. Task AddShowLink(int showID, int? libraryID, int? collectionID); - + /// /// Setup relations between a show, a library and a collection /// /// The show to setup relations with /// The library to setup relations with (optional) /// The collection to setup relations with (optional) + /// A representing the asynchronous operation. Task AddShowLink([NotNull] Show show, Library library, Collection collection); /// /// Get all resources with filters /// /// A filter function - /// Sort informations (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// The type of resources to load /// A list of resources that match every filters Task> GetAll(Expression> where = null, Sort sort = default, - Pagination limit = default) where T : class, IResource; - + Pagination limit = default) + where T : class, IResource; + /// /// Get all resources with filters /// @@ -488,7 +513,8 @@ namespace Kyoo.Abstractions.Controllers /// A list of resources that match every filters Task> GetAll([Optional] Expression> where, Expression> sort, - Pagination limit = default) where T : class, IResource + Pagination limit = default) + where T : class, IResource { return GetAll(where, new Sort(sort), limit); } @@ -499,7 +525,8 @@ namespace Kyoo.Abstractions.Controllers /// A filter function /// The type of resources to load /// A list of resources that match every filters - Task GetCount(Expression> where = null) where T : class, IResource; + Task GetCount(Expression> where = null) + where T : class, IResource; /// /// Search for a resource @@ -507,33 +534,37 @@ namespace Kyoo.Abstractions.Controllers /// The search query /// The type of resources /// A list of 20 items that match the search query - Task> Search(string query) where T : class, IResource; + Task> Search(string query) + where T : class, IResource; /// /// Create a new resource. /// /// The item to register /// The type of resource - /// The resource registers and completed by database's informations (related items & so on) - Task Create([NotNull] T item) where T : class, IResource; - + /// The resource registers and completed by database's information (related items and so on) + Task Create([NotNull] T item) + where T : class, IResource; + /// /// Create a new resource if it does not exist already. If it does, the existing value is returned instead. /// /// The item to register /// The type of resource /// The newly created item or the existing value if it existed. - Task CreateIfNotExists([NotNull] T item) where T : class, IResource; - + Task CreateIfNotExists([NotNull] T item) + where T : class, IResource; + /// /// Edit a resource /// - /// The resourcce to edit, it's ID can't change. + /// The resource to edit, it's ID can't change. /// Should old properties of the resource be discarded or should null values considered as not changed? /// The type of resources /// If the item is not found - /// The resource edited and completed by database's informations (related items & so on) - Task Edit(T item, bool resetOld) where T : class, IResource; + /// The resource edited and completed by database's information (related items and so on) + Task Edit(T item, bool resetOld) + where T : class, IResource; /// /// Delete a resource. @@ -541,22 +572,28 @@ namespace Kyoo.Abstractions.Controllers /// The resource to delete /// The type of resource to delete /// If the item is not found - Task Delete(T item) where T : class, IResource; - + /// A representing the asynchronous operation. + Task Delete(T item) + where T : class, IResource; + /// /// Delete a resource by it's ID. /// /// The id of the resource to delete /// The type of resource to delete /// If the item is not found - Task Delete(int id) where T : class, IResource; - + /// A representing the asynchronous operation. + Task Delete(int id) + where T : class, IResource; + /// /// Delete a resource by it's slug. /// /// The slug of the resource to delete /// The type of resource to delete /// If the item is not found - Task Delete(string slug) where T : class, IResource; + /// A representing the asynchronous operation. + Task Delete(string slug) + where T : class, IResource; } } diff --git a/Kyoo.Abstractions/Controllers/IMetadataProvider.cs b/src/Kyoo.Abstractions/Controllers/IMetadataProvider.cs similarity index 73% rename from Kyoo.Abstractions/Controllers/IMetadataProvider.cs rename to src/Kyoo.Abstractions/Controllers/IMetadataProvider.cs index c04ac906..feb9d56d 100644 --- a/Kyoo.Abstractions/Controllers/IMetadataProvider.cs +++ b/src/Kyoo.Abstractions/Controllers/IMetadataProvider.cs @@ -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 . + 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 is given /// to make a precise search and give you every available properties, not to discard properties. /// + /// The type of resource to retrieve metadata for. /// A new containing metadata from your provider or null [ItemCanBeNull] Task Get([NotNull] T item) @@ -39,6 +58,7 @@ namespace Kyoo.Abstractions.Controllers /// Search for a specific type of items with a given query. /// /// The search query to use. + /// The type of resource to search metadata for. /// The list of items that could be found on this specific provider. [ItemNotNull] Task> Search(string query) @@ -62,7 +82,7 @@ namespace Kyoo.Abstractions.Controllers /// /// 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. /// public Provider Provider => null; diff --git a/src/Kyoo.Abstractions/Controllers/IPermissionValidator.cs b/src/Kyoo.Abstractions/Controllers/IPermissionValidator.cs new file mode 100644 index 00000000..363cecfe --- /dev/null +++ b/src/Kyoo.Abstractions/Controllers/IPermissionValidator.cs @@ -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 . + +using Kyoo.Abstractions.Models.Permissions; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace Kyoo.Abstractions.Controllers +{ + /// + /// A service to validate permissions. + /// + public interface IPermissionValidator + { + /// + /// Create an IAuthorizationFilter that will be used to validate permissions. + /// This can registered with any lifetime. + /// + /// The permission attribute to validate. + /// An authorization filter used to validate the permission. + IFilterMetadata Create(PermissionAttribute attribute); + + /// + /// Create an IAuthorizationFilter that will be used to validate permissions. + /// This can registered with any lifetime. + /// + /// + /// A partial attribute to validate. See . + /// + /// An authorization filter used to validate the permission. + IFilterMetadata Create(PartialPermissionAttribute attribute); + } +} diff --git a/Kyoo.Abstractions/Controllers/IPlugin.cs b/src/Kyoo.Abstractions/Controllers/IPlugin.cs similarity index 80% rename from Kyoo.Abstractions/Controllers/IPlugin.cs rename to src/Kyoo.Abstractions/Controllers/IPlugin.cs index 6fc2cc3c..55c5b6e4 100644 --- a/Kyoo.Abstractions/Controllers/IPlugin.cs +++ b/src/Kyoo.Abstractions/Controllers/IPlugin.cs @@ -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 . + using System; using System.Collections.Generic; using Autofac; @@ -20,28 +38,28 @@ namespace Kyoo.Abstractions.Controllers /// A slug to identify this plugin in queries. /// string Slug { get; } - + /// /// The name of the plugin /// string Name { get; } - + /// /// The description of this plugin. This will be displayed on the "installed plugins" page. /// string Description { get; } - + /// /// true if the plugin should be enabled, false otherwise. /// If a plugin is not enabled, no configure method will be called. /// This allow one to enable a plugin if a specific configuration value is set or if the environment contains - /// the right settings. + /// the right settings. /// /// /// By default, a plugin is always enabled. This method can be overriden to change this behavior. /// virtual bool Enabled => true; - + /// /// A list of types that will be available via the IOptions interfaces and will be listed inside /// an IConfiguration. @@ -64,7 +82,7 @@ namespace Kyoo.Abstractions.Controllers /// virtual IEnumerable ConfigureSteps => ArraySegment.Empty; - /// + /// /// A configure method that will be run on plugin's startup. /// /// The autofac service container to register services. @@ -72,7 +90,7 @@ namespace Kyoo.Abstractions.Controllers { // Skipped } - + /// /// A configure method that will be run on plugin's startup. /// This is available for libraries that build upon a , for more precise @@ -94,4 +112,4 @@ namespace Kyoo.Abstractions.Controllers // Skipped } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Controllers/IPluginManager.cs b/src/Kyoo.Abstractions/Controllers/IPluginManager.cs similarity index 70% rename from Kyoo.Abstractions/Controllers/IPluginManager.cs rename to src/Kyoo.Abstractions/Controllers/IPluginManager.cs index 795339a4..11aea0b4 100644 --- a/Kyoo.Abstractions/Controllers/IPluginManager.cs +++ b/src/Kyoo.Abstractions/Controllers/IPluginManager.cs @@ -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 . + using System; using System.Collections.Generic; using Kyoo.Abstractions.Models.Exceptions; @@ -17,14 +35,14 @@ namespace Kyoo.Abstractions.Controllers /// If no plugins match the query /// A plugin that match the queries public T GetPlugin(string name); - + /// /// Get all plugins of the given type. /// /// The type of plugins to get /// A list of plugins matching the given type or an empty list of none match. public ICollection GetPlugins(); - + /// /// Get all plugins currently running on Kyoo. This also includes deleted plugins if the app as not been restarted. /// @@ -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. /// public void LoadPlugins(ICollection plugins); - + /// /// Load plugins and their dependencies from the plugin directory. /// @@ -49,4 +67,4 @@ namespace Kyoo.Abstractions.Controllers /// public void LoadPlugins(params Type[] plugins); } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Controllers/IRepository.cs b/src/Kyoo.Abstractions/Controllers/IRepository.cs similarity index 82% rename from Kyoo.Abstractions/Controllers/IRepository.cs rename to src/Kyoo.Abstractions/Controllers/IRepository.cs index 45c866ba..805de8ec 100644 --- a/Kyoo.Abstractions/Controllers/IRepository.cs +++ b/src/Kyoo.Abstractions/Controllers/IRepository.cs @@ -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 . + 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 { - /// - /// Information about the pagination. How many items should be displayed and where to start. - /// - public readonly struct Pagination - { - /// - /// The count of items to return. - /// - public int Count { get; } - /// - /// Where to start? Using the given sort - /// - public int AfterID { get; } - - /// - /// Create a new instance. - /// - /// Set the value - /// Set the value. If not specified, it will start from the start - public Pagination(int count, int afterID = 0) - { - Count = count; - AfterID = afterID; - } - - /// - /// Implicitly create a new pagination from a limit number. - /// - /// Set the value - /// A new instance - public static implicit operator Pagination(int limit) => new(limit); - } - - /// - /// Information about how a query should be sorted. What factor should decide the sort and in which order. - /// - /// For witch type this sort applies - public readonly struct Sort - { - /// - /// The sort key. This member will be used to sort the results. - /// - public Expression> Key { get; } - /// - /// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order. - /// - public bool Descendant { get; } - - /// - /// Create a new instance. - /// - /// The sort key given. It is assigned to . - /// Should this be in descendant order? The default is false. - /// If the given key is not a member. - public Sort(Expression> key, bool descendant = false) - { - Key = key; - Descendant = descendant; - - if (!Utility.IsPropertyExpression(Key)) - throw new ArgumentException("The given sort key is not valid."); - } - - /// - /// Create a new instance from a key's name (case insensitive). - /// - /// A key name with an optional order specifier. Format: "key:asc", "key:desc" or "key". - /// An invalid key or sort specifier as been given. - 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>(Expression.Convert(property, typeof(object)), param) - : Expression.Lambda>(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}.") - }; - } - } - - /// - /// A base class for repositories. Every service implementing this will be handled by the . - /// - public interface IBaseRepository - { - /// - /// The type for witch this repository is responsible or null if non applicable. - /// - Type RepositoryType { get; } - } - /// /// A common repository for every resources. /// /// The resource's type that this repository manage. - public interface IRepository : IBaseRepository where T : class, IResource + public interface IRepository : IBaseRepository + where T : class, IResource { /// /// Get a resource from it's ID. @@ -131,6 +42,7 @@ namespace Kyoo.Abstractions.Controllers /// The resource found [ItemNotNull] Task Get(int id); + /// /// Get a resource from it's slug. /// @@ -139,6 +51,7 @@ namespace Kyoo.Abstractions.Controllers /// The resource found [ItemNotNull] Task Get(string slug); + /// /// Get the first resource that match the predicate. /// @@ -147,7 +60,7 @@ namespace Kyoo.Abstractions.Controllers /// The resource found [ItemNotNull] Task Get(Expression> where); - + /// /// Get a resource from it's ID or null if it is not found. /// @@ -155,6 +68,7 @@ namespace Kyoo.Abstractions.Controllers /// The resource found [ItemCanBeNull] Task GetOrDefault(int id); + /// /// Get a resource from it's slug or null if it is not found. /// @@ -162,6 +76,7 @@ namespace Kyoo.Abstractions.Controllers /// The resource found [ItemCanBeNull] Task GetOrDefault(string slug); + /// /// Get the first resource that match the predicate or null if it is not found. /// @@ -169,7 +84,7 @@ namespace Kyoo.Abstractions.Controllers /// The resource found [ItemCanBeNull] Task GetOrDefault(Expression> where); - + /// /// Search for resources. /// @@ -177,7 +92,7 @@ namespace Kyoo.Abstractions.Controllers /// A list of resources found [ItemNotNull] Task> Search(string query); - + /// /// Get every resources that match all filters /// @@ -186,9 +101,10 @@ namespace Kyoo.Abstractions.Controllers /// How pagination should be done (where to start and how many to return) /// A list of resources that match every filters [ItemNotNull] - Task> GetAll(Expression> where = null, + Task> GetAll(Expression> where = null, Sort sort = default, Pagination limit = default); + /// /// Get every resources that match all filters /// @@ -208,16 +124,15 @@ namespace Kyoo.Abstractions.Controllers /// A filter predicate /// How many resources matched that filter Task GetCount(Expression> where = null); - - + /// /// Create a new resource. /// /// The item to register - /// The resource registers and completed by database's information (related items & so on) + /// The resource registers and completed by database's information (related items and so on) [ItemNotNull] Task Create([NotNull] T obj); - + /// /// Create a new resource if it does not exist already. If it does, the existing value is returned instead. /// @@ -225,44 +140,61 @@ namespace Kyoo.Abstractions.Controllers /// The newly created item or the existing value if it existed. [ItemNotNull] Task CreateIfNotExists([NotNull] T obj); - + /// /// Edit a resource /// /// The resource to edit, it's ID can't change. /// Should old properties of the resource be discarded or should null values considered as not changed? /// If the item is not found - /// The resource edited and completed by database's information (related items & so on) + /// The resource edited and completed by database's information (related items and so on) [ItemNotNull] Task Edit([NotNull] T edited, bool resetOld); - + /// /// Delete a resource by it's ID /// /// The ID of the resource /// If the item is not found + /// A representing the asynchronous operation. Task Delete(int id); + /// /// Delete a resource by it's slug /// /// The slug of the resource /// If the item is not found + /// A representing the asynchronous operation. Task Delete(string slug); + /// /// Delete a resource /// /// The resource to delete /// If the item is not found + /// A representing the asynchronous operation. Task Delete([NotNull] T obj); - + /// /// Delete all resources that match the predicate. /// /// A predicate to filter resources to delete. Every resource that match this will be deleted. /// If the item is not found + /// A representing the asynchronous operation. Task DeleteAll([NotNull] Expression> where); } + /// + /// A base class for repositories. Every service implementing this will be handled by the . + /// + public interface IBaseRepository + { + /// + /// The type for witch this repository is responsible or null if non applicable. + /// + Type RepositoryType { get; } + } + /// /// A repository to handle shows. /// @@ -275,6 +207,7 @@ namespace Kyoo.Abstractions.Controllers /// The ID of the show /// The ID of the library (optional) /// The ID of the collection (optional) + /// A representing the asynchronous operation. Task AddShowLink(int showID, int? libraryID, int? collectionID); /// @@ -299,7 +232,7 @@ namespace Kyoo.Abstractions.Controllers /// If the item is not found /// The season found Task Get(int showID, int seasonNumber); - + /// /// Get a season from it's show slug and it's seasonNumber /// @@ -308,7 +241,7 @@ namespace Kyoo.Abstractions.Controllers /// If the item is not found /// The season found Task Get(string showSlug, int seasonNumber); - + /// /// Get a season from it's showID and it's seasonNumber or null if it is not found. /// @@ -316,7 +249,7 @@ namespace Kyoo.Abstractions.Controllers /// The season's number /// The season found Task GetOrDefault(int showID, int seasonNumber); - + /// /// Get a season from it's show slug and it's seasonNumber or null if it is not found. /// @@ -325,7 +258,7 @@ namespace Kyoo.Abstractions.Controllers /// The season found Task GetOrDefault(string showSlug, int seasonNumber); } - + /// /// The repository to handle episodes /// @@ -340,6 +273,7 @@ namespace Kyoo.Abstractions.Controllers /// If the item is not found /// The episode found Task Get(int showID, int seasonNumber, int episodeNumber); + /// /// Get a episode from it's show slug, it's seasonNumber and it's episode number. /// @@ -358,6 +292,7 @@ namespace Kyoo.Abstractions.Controllers /// The episode's number /// The episode found Task GetOrDefault(int showID, int seasonNumber, int episodeNumber); + /// /// Get a episode from it's show slug, it's seasonNumber and it's episode number or null if it is not found. /// @@ -366,7 +301,7 @@ namespace Kyoo.Abstractions.Controllers /// The episode's number /// The episode found Task GetOrDefault(string showSlug, int seasonNumber, int episodeNumber); - + /// /// Get a episode from it's showID and it's absolute number. /// @@ -375,6 +310,7 @@ namespace Kyoo.Abstractions.Controllers /// If the item is not found /// The episode found Task GetAbsolute(int showID, int absoluteNumber); + /// /// Get a episode from it's showID and it's absolute number. /// @@ -389,7 +325,7 @@ namespace Kyoo.Abstractions.Controllers /// A repository to handle tracks /// public interface ITrackRepository : IRepository { } - + /// /// A repository to handle libraries. /// @@ -405,13 +341,14 @@ namespace Kyoo.Abstractions.Controllers /// /// The ID of the library /// A filter function - /// Sort information (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters public Task> GetFromLibrary(int id, Expression> where = null, Sort sort = default, Pagination limit = default); + /// /// Get items (A wrapper around shows or collections) from a library. /// @@ -425,19 +362,20 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetFromLibrary(id, where, new Sort(sort), limit); - + /// /// Get items (A wrapper around shows or collections) from a library. /// /// The slug of the library /// A filter function - /// Sort information (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters public Task> GetFromLibrary(string slug, Expression> where = null, Sort sort = default, Pagination limit = default); + /// /// Get items (A wrapper around shows or collections) from a library. /// @@ -451,18 +389,18 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetFromLibrary(slug, where, new Sort(sort), limit); - } - + } + /// /// A repository for collections /// public interface ICollectionRepository : IRepository { } - + /// /// A repository for genres. /// public interface IGenreRepository : IRepository { } - + /// /// A repository for studios. /// @@ -478,13 +416,14 @@ namespace Kyoo.Abstractions.Controllers /// /// The ID of the show /// A filter function - /// Sort information (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetFromShow(int showID, - Expression> where = null, + Expression> where = null, Sort sort = default, Pagination limit = default); + /// /// Get people's roles from a show. /// @@ -498,19 +437,20 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetFromShow(showID, where, new Sort(sort), limit); - + /// /// Get people's roles from a show. /// /// The slug of the show /// A filter function - /// Sort information (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetFromShow(string showSlug, - Expression> where = null, + Expression> where = null, Sort sort = default, Pagination limit = default); + /// /// Get people's roles from a show. /// @@ -524,19 +464,20 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetFromShow(showSlug, where, new Sort(sort), limit); - + /// /// Get people's roles from a person. /// /// The id of the person /// A filter function - /// Sort information (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetFromPeople(int id, - Expression> where = null, + Expression> where = null, Sort sort = default, Pagination limit = default); + /// /// Get people's roles from a person. /// @@ -550,19 +491,20 @@ namespace Kyoo.Abstractions.Controllers Expression> sort, Pagination limit = default ) => GetFromPeople(id, where, new Sort(sort), limit); - + /// /// Get people's roles from a person. /// /// The slug of the person /// A filter function - /// Sort information (sort order & sort by) + /// Sort information (sort order and sort by) /// How many items to return and where to start /// A list of items that match every filters Task> GetFromPeople(string slug, - Expression> where = null, + Expression> where = null, Sort sort = default, Pagination limit = default); + /// /// Get people's roles from a person. /// @@ -587,11 +529,11 @@ namespace Kyoo.Abstractions.Controllers /// Get a list of external ids that match all filters /// /// A predicate to add arbitrary filter - /// Sort information (sort order & sort by) + /// Sort information (sort order and sort by) /// Pagination information (where to start and how many to get) /// The type of metadata to retrieve /// A filtered list of external ids. - Task> GetMetadataID(Expression> where = null, + Task> GetMetadataID(Expression> where = null, Sort sort = default, Pagination limit = default) where T : class, IMetadata; @@ -602,16 +544,18 @@ namespace Kyoo.Abstractions.Controllers /// A predicate to add arbitrary filter /// A sort by expression /// Pagination information (where to start and how many to get) + /// The type of metadata to retrieve /// A filtered list of external ids. Task> GetMetadataID([Optional] Expression> where, Expression> sort, Pagination limit = default - ) where T : class, IMetadata + ) + where T : class, IMetadata => GetMetadataID(where, new Sort(sort), limit); } - + /// /// A repository to handle users. /// - public interface IUserRepository : IRepository {} + public interface IUserRepository : IRepository { } } diff --git a/Kyoo.Abstractions/Controllers/ITask.cs b/src/Kyoo.Abstractions/Controllers/ITask.cs similarity index 83% rename from Kyoo.Abstractions/Controllers/ITask.cs rename to src/Kyoo.Abstractions/Controllers/ITask.cs index 79c8c778..7c9f749d 100644 --- a/Kyoo.Abstractions/Controllers/ITask.cs +++ b/src/Kyoo.Abstractions/Controllers/ITask.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -9,153 +27,6 @@ using Kyoo.Abstractions.Models.Exceptions; namespace Kyoo.Abstractions.Controllers { - /// - /// A single task parameter. This struct contains metadata to display and utility functions to get them in the task. - /// - /// This struct will be used to generate the swagger documentation of the task. - public record TaskParameter - { - /// - /// The name of this parameter. - /// - public string Name { get; init; } - - /// - /// The description of this parameter. - /// - public string Description { get; init; } - - /// - /// The type of this parameter. - /// - public Type Type { get; init; } - - /// - /// Is this parameter required or can it be ignored? - /// - public bool IsRequired { get; init; } - - /// - /// The default value of this object. - /// - public object DefaultValue { get; init; } - - /// - /// The value of the parameter. - /// - private object Value { get; init; } - - /// - /// Create a new task parameter. - /// - /// The name of the parameter - /// The description of the parameter - /// The type of the parameter. - /// A new task parameter. - public static TaskParameter Create(string name, string description) - { - return new TaskParameter - { - Name = name, - Description = description, - Type = typeof(T) - }; - } - - /// - /// Create a new required task parameter. - /// - /// The name of the parameter - /// The description of the parameter - /// The type of the parameter. - /// A new task parameter. - public static TaskParameter CreateRequired(string name, string description) - { - return new TaskParameter - { - Name = name, - Description = description, - Type = typeof(T), - IsRequired = true - }; - } - - /// - /// Create a parameter's value to give to a task. - /// - /// The name of the parameter - /// The value of the parameter. It's type will be used as parameter's type. - /// The type of the parameter - /// A TaskParameter that can be used as value. - public static TaskParameter CreateValue(string name, T value) - { - return new() - { - Name = name, - Type = typeof(T), - Value = value - }; - } - - /// - /// Create a parameter's value for the current parameter. - /// - /// The value to use - /// A new parameter's value for this current parameter - public TaskParameter CreateValue(object value) - { - return this with {Value = value}; - } - - /// - /// Get the value of this parameter. If the value is of the wrong type, it will be converted. - /// - /// The type of this parameter - /// The value of this parameter. - public T As() - { - if (typeof(T) == typeof(object)) - return (T)Value; - - if (Value is IResource resource) - { - if (typeof(T) == typeof(string)) - return (T)(object)resource.Slug; - if (typeof(T) == typeof(int)) - return (T)(object)resource.ID; - } - - return (T)Convert.ChangeType(Value, typeof(T)); - } - } - - /// - /// A parameters container implementing an indexer to allow simple usage of parameters. - /// - public class TaskParameters : List - { - /// - /// An indexer that return the parameter with the specified name. - /// - /// The name of the task (case sensitive) - public TaskParameter this[string name] => this.FirstOrDefault(x => x.Name == name); - - - /// - /// Create a new, empty, - /// - public TaskParameters() {} - - /// - /// Create a with an initial parameters content - /// - /// The list of parameters - public TaskParameters(IEnumerable parameters) - { - AddRange(parameters); - } - } - /// /// A common interface that tasks should implement. /// @@ -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. /// public TaskParameters GetParameters(); - + /// /// Start this task. /// @@ -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. /// + /// A representing the asynchronous operation. public Task Run([NotNull] TaskParameters arguments, [NotNull] IProgress progress, CancellationToken cancellationToken); } -} \ No newline at end of file + + /// + /// A single task parameter. This struct contains metadata to display and utility functions to get them in the task. + /// + /// This struct will be used to generate the swagger documentation of the task. + public record TaskParameter + { + /// + /// The name of this parameter. + /// + public string Name { get; init; } + + /// + /// The description of this parameter. + /// + public string Description { get; init; } + + /// + /// The type of this parameter. + /// + public Type Type { get; init; } + + /// + /// Is this parameter required or can it be ignored? + /// + public bool IsRequired { get; init; } + + /// + /// The default value of this object. + /// + public object DefaultValue { get; init; } + + /// + /// The value of the parameter. + /// + private object _Value { get; init; } + + /// + /// Create a new task parameter. + /// + /// The name of the parameter + /// The description of the parameter + /// The type of the parameter. + /// A new task parameter. + public static TaskParameter Create(string name, string description) + { + return new TaskParameter + { + Name = name, + Description = description, + Type = typeof(T) + }; + } + + /// + /// Create a new required task parameter. + /// + /// The name of the parameter + /// The description of the parameter + /// The type of the parameter. + /// A new task parameter. + public static TaskParameter CreateRequired(string name, string description) + { + return new TaskParameter + { + Name = name, + Description = description, + Type = typeof(T), + IsRequired = true + }; + } + + /// + /// Create a parameter's value to give to a task. + /// + /// The name of the parameter + /// The value of the parameter. It's type will be used as parameter's type. + /// The type of the parameter + /// A TaskParameter that can be used as value. + public static TaskParameter CreateValue(string name, T value) + { + return new() + { + Name = name, + Type = typeof(T), + _Value = value + }; + } + + /// + /// Create a parameter's value for the current parameter. + /// + /// The value to use + /// A new parameter's value for this current parameter + public TaskParameter CreateValue(object value) + { + return this with { _Value = value }; + } + + /// + /// Get the value of this parameter. If the value is of the wrong type, it will be converted. + /// + /// The type of this parameter + /// The value of this parameter. + public T As() + { + if (typeof(T) == typeof(object)) + return (T)_Value; + + if (_Value is IResource resource) + { + if (typeof(T) == typeof(string)) + return (T)(object)resource.Slug; + if (typeof(T) == typeof(int)) + return (T)(object)resource.ID; + } + + return (T)Convert.ChangeType(_Value, typeof(T)); + } + } + + /// + /// A parameters container implementing an indexer to allow simple usage of parameters. + /// + public class TaskParameters : List + { + /// + /// An indexer that return the parameter with the specified name. + /// + /// The name of the task (case sensitive) + public TaskParameter this[string name] => this.FirstOrDefault(x => x.Name == name); + + /// + /// Create a new, empty, + /// + public TaskParameters() { } + + /// + /// Create a with an initial parameters content. + /// + /// The list of parameters + public TaskParameters(IEnumerable parameters) + { + AddRange(parameters); + } + } +} diff --git a/Kyoo.Abstractions/Controllers/ITaskManager.cs b/src/Kyoo.Abstractions/Controllers/ITaskManager.cs similarity index 77% rename from Kyoo.Abstractions/Controllers/ITaskManager.cs rename to src/Kyoo.Abstractions/Controllers/ITaskManager.cs index 2a999aad..556f3631 100644 --- a/Kyoo.Abstractions/Controllers/ITaskManager.cs +++ b/src/Kyoo.Abstractions/Controllers/ITaskManager.cs @@ -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 . + using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -35,7 +53,7 @@ namespace Kyoo.Abstractions.Controllers /// /// The task could not be found. /// - void StartTask(string taskSlug, + void StartTask(string taskSlug, [NotNull] IProgress progress, Dictionary arguments = null, CancellationToken? cancellationToken = null); @@ -66,17 +84,17 @@ namespace Kyoo.Abstractions.Controllers Dictionary arguments = null, CancellationToken? cancellationToken = null) where T : ITask; - + /// /// Get all currently running tasks /// /// A list of currently running tasks. ICollection<(TaskMetadataAttribute, ITask)> GetRunningTasks(); - + /// /// Get all available tasks /// /// A list of every tasks that this instance know. ICollection GetAllTasks(); } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Controllers/IThumbnailsManager.cs b/src/Kyoo.Abstractions/Controllers/IThumbnailsManager.cs similarity index 63% rename from Kyoo.Abstractions/Controllers/IThumbnailsManager.cs rename to src/Kyoo.Abstractions/Controllers/IThumbnailsManager.cs index 54e5be0a..eb26335a 100644 --- a/Kyoo.Abstractions/Controllers/IThumbnailsManager.cs +++ b/src/Kyoo.Abstractions/Controllers/IThumbnailsManager.cs @@ -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 . + using System.Threading.Tasks; using JetBrains.Annotations; +using Kyoo.Abstractions.Models; namespace Kyoo.Abstractions.Controllers { @@ -24,7 +42,6 @@ namespace Kyoo.Abstractions.Controllers Task DownloadImages([NotNull] T item, bool alwaysDownload = false) where T : IThumbnails; - /// /// Retrieve the local path of an image of the given item. /// diff --git a/src/Kyoo.Abstractions/Controllers/ITranscoder.cs b/src/Kyoo.Abstractions/Controllers/ITranscoder.cs new file mode 100644 index 00000000..20213526 --- /dev/null +++ b/src/Kyoo.Abstractions/Controllers/ITranscoder.cs @@ -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 . + +using System.Threading.Tasks; +using Kyoo.Abstractions.Models; + +namespace Kyoo.Abstractions.Controllers +{ + public interface ITranscoder + { + Task ExtractInfos(Episode episode, bool reextract); + + Task Transmux(Episode episode); + + Task Transcode(Episode episode); + } +} diff --git a/src/Kyoo.Abstractions/Controllers/StartupAction.cs b/src/Kyoo.Abstractions/Controllers/StartupAction.cs new file mode 100644 index 00000000..8e381387 --- /dev/null +++ b/src/Kyoo.Abstractions/Controllers/StartupAction.cs @@ -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 . + +using System; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Extensions.DependencyInjection; + +namespace Kyoo.Abstractions.Controllers +{ + /// + /// A list of constant priorities used for 's . + /// It also contains helper methods for creating new . + /// + [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 + { + /// + /// The highest predefined priority existing for . + /// + public const int Before = 5000; + + /// + /// Items defining routing (see IApplicationBuilder.UseRouting use this priority. + /// + public const int Routing = 4000; + + /// + /// Actions defining new static files router use this priority. + /// + public const int StaticFiles = 3000; + + /// + /// Actions calling IApplicationBuilder.UseAuthentication use this priority. + /// + public const int Authentication = 2000; + + /// + /// Actions calling IApplicationBuilder.UseAuthorization use this priority. + /// + public const int Authorization = 1000; + + /// + /// Action adding endpoint should use this priority (with a negative modificator if there is a catchall). + /// + public const int Endpoint = 0; + + /// + /// The lowest predefined priority existing for . + /// It should run after all other actions. + /// + public const int After = -1000; + + /// + /// Create a new . + /// + /// The action to run + /// The priority of the new action + /// A new + public static StartupAction New(Action action, int priority) + => new(action, priority); + + /// + /// Create a new . + /// + /// The action to run + /// The priority of the new action + /// A dependency that this action will use. + /// A new + public static StartupAction New(Action action, int priority) + => new(action, priority); + + /// + /// Create a new . + /// + /// The action to run + /// The priority of the new action + /// A dependency that this action will use. + /// A second dependency that this action will use. + /// A new + public static StartupAction New(Action action, int priority) + => new(action, priority); + + /// + /// Create a new . + /// + /// The action to run + /// The priority of the new action + /// A dependency that this action will use. + /// A second dependency that this action will use. + /// A third dependency that this action will use. + /// A new + public static StartupAction New(Action action, int priority) + => new(action, priority); + + /// + /// A with no dependencies. + /// + public class StartupAction : IStartupAction + { + /// + /// The action to execute at startup. + /// + private readonly Action _action; + + /// + public int Priority { get; } + + /// + /// Create a new . + /// + /// The action to execute on startup. + /// The priority of this action (see ). + public StartupAction(Action action, int priority) + { + _action = action; + Priority = priority; + } + + /// + public void Run(IServiceProvider provider) + { + _action.Invoke(); + } + } + + /// + /// A with one dependencies. + /// + /// The dependency to use. + public class StartupAction : IStartupAction + { + /// + /// The action to execute at startup. + /// + private readonly Action _action; + + /// + public int Priority { get; } + + /// + /// Create a new . + /// + /// The action to execute on startup. + /// The priority of this action (see ). + public StartupAction(Action action, int priority) + { + _action = action; + Priority = priority; + } + + /// + public void Run(IServiceProvider provider) + { + _action.Invoke(provider.GetRequiredService()); + } + } + + /// + /// A with two dependencies. + /// + /// The dependency to use. + /// The second dependency to use. + public class StartupAction : IStartupAction + { + /// + /// The action to execute at startup. + /// + private readonly Action _action; + + /// + public int Priority { get; } + + /// + /// Create a new . + /// + /// The action to execute on startup. + /// The priority of this action (see ). + public StartupAction(Action action, int priority) + { + _action = action; + Priority = priority; + } + + /// + public void Run(IServiceProvider provider) + { + _action.Invoke( + provider.GetRequiredService(), + provider.GetRequiredService() + ); + } + } + + /// + /// A with three dependencies. + /// + /// The dependency to use. + /// The second dependency to use. + /// The third dependency to use. + public class StartupAction : IStartupAction + { + /// + /// The action to execute at startup. + /// + private readonly Action _action; + + /// + public int Priority { get; } + + /// + /// Create a new . + /// + /// The action to execute on startup. + /// The priority of this action (see ). + public StartupAction(Action action, int priority) + { + _action = action; + Priority = priority; + } + + /// + public void Run(IServiceProvider provider) + { + _action.Invoke( + provider.GetRequiredService(), + provider.GetRequiredService(), + provider.GetRequiredService() + ); + } + } + } + + /// + /// An action executed on kyoo's startup to initialize the asp-net container. + /// + /// + /// This is the base interface, see for a simpler use of this. + /// + public interface IStartupAction + { + /// + /// 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. + /// + int Priority { get; } + + /// + /// Run this action to configure the container, a service provider containing all services can be used. + /// + /// The service provider containing all services can be used. + void Run(IServiceProvider provider); + } +} diff --git a/Kyoo.Abstractions/Kyoo.Abstractions.csproj b/src/Kyoo.Abstractions/Kyoo.Abstractions.csproj similarity index 97% rename from Kyoo.Abstractions/Kyoo.Abstractions.csproj rename to src/Kyoo.Abstractions/Kyoo.Abstractions.csproj index 2c7ac85d..60af7d84 100644 --- a/Kyoo.Abstractions/Kyoo.Abstractions.csproj +++ b/src/Kyoo.Abstractions/Kyoo.Abstractions.csproj @@ -1,4 +1,4 @@ - + net5.0 diff --git a/src/Kyoo.Abstractions/Models/Attributes/ComputedAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/ComputedAttribute.cs new file mode 100644 index 00000000..fd4d37b5 --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Attributes/ComputedAttribute.cs @@ -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 . + +using System; + +namespace Kyoo.Abstractions.Models.Attributes +{ + /// + /// An attribute to inform that the property is computed automatically and can't be assigned manually. + /// + [AttributeUsage(AttributeTargets.Property)] + public class ComputedAttribute : NotMergeableAttribute { } +} diff --git a/src/Kyoo.Abstractions/Models/Attributes/EditableRelationAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/EditableRelationAttribute.cs new file mode 100644 index 00000000..5b78b3f8 --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Attributes/EditableRelationAttribute.cs @@ -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 . + +using System; +using Kyoo.Abstractions.Controllers; + +namespace Kyoo.Abstractions.Models.Attributes +{ + /// + /// The targeted relation can be edited via calls to the repository's method. + /// + [AttributeUsage(AttributeTargets.Property)] + public class EditableRelationAttribute : Attribute { } +} diff --git a/Kyoo.Abstractions/Models/Attributes/FileSystemMetadataAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/FileSystemMetadataAttribute.cs similarity index 68% rename from Kyoo.Abstractions/Models/Attributes/FileSystemMetadataAttribute.cs rename to src/Kyoo.Abstractions/Models/Attributes/FileSystemMetadataAttribute.cs index afab7bc1..207ab91c 100644 --- a/Kyoo.Abstractions/Models/Attributes/FileSystemMetadataAttribute.cs +++ b/src/Kyoo.Abstractions/Models/Attributes/FileSystemMetadataAttribute.cs @@ -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 . + 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. /// public string[] Scheme { get; } - + /// /// true if the scheme should be removed from the path before calling /// methods of this , false otherwise. /// public bool StripScheme { get; set; } - /// /// Create a new using the specified schemes. @@ -36,7 +53,7 @@ namespace Kyoo.Abstractions.Models.Attributes { Scheme = schemes; } - + /// /// Create a new using a dictionary of metadata. /// @@ -50,4 +67,4 @@ namespace Kyoo.Abstractions.Models.Attributes StripScheme = (bool)metadata[nameof(StripScheme)]; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Attributes/RelationAttributes.cs b/src/Kyoo.Abstractions/Models/Attributes/LoadableRelationAttribute.cs similarity index 50% rename from Kyoo.Abstractions/Models/Attributes/RelationAttributes.cs rename to src/Kyoo.Abstractions/Models/Attributes/LoadableRelationAttribute.cs index 943bd1fe..5bfb9e82 100644 --- a/Kyoo.Abstractions/Models/Attributes/RelationAttributes.cs +++ b/src/Kyoo.Abstractions/Models/Attributes/LoadableRelationAttribute.cs @@ -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 . + using System; using Kyoo.Abstractions.Controllers; namespace Kyoo.Abstractions.Models.Attributes { - /// - /// The targeted relation can be edited via calls to the repository's method. - /// - [AttributeUsage(AttributeTargets.Property)] - public class EditableRelationAttribute : Attribute { } - /// /// The targeted relation can be loaded via a call to . /// @@ -19,11 +31,11 @@ namespace Kyoo.Abstractions.Models.Attributes /// The name of the field containing the related resource's ID. /// public string RelationID { get; } - + /// /// Create a new . /// - public LoadableRelationAttribute() {} + public LoadableRelationAttribute() { } /// /// Create a new with a baking relationID field. @@ -34,4 +46,4 @@ namespace Kyoo.Abstractions.Models.Attributes RelationID = relationID; } } -} \ No newline at end of file +} diff --git a/src/Kyoo.Abstractions/Models/Attributes/NotMergeableAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/NotMergeableAttribute.cs new file mode 100644 index 00000000..c63acb06 --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Attributes/NotMergeableAttribute.cs @@ -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 . + +using System; + +namespace Kyoo.Abstractions.Models.Attributes +{ + /// + /// Specify that a property can't be merged. + /// + [AttributeUsage(AttributeTargets.Property)] + public class NotMergeableAttribute : Attribute { } + + /// + /// An interface with a method called when this object is merged. + /// + public interface IOnMerge + { + /// + /// This function is called after the object has been merged. + /// + /// The object that has been merged with this. + void OnMerge(object merged); + } +} diff --git a/src/Kyoo.Abstractions/Models/Attributes/Permission/PartialPermissionAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/Permission/PartialPermissionAttribute.cs new file mode 100644 index 00000000..58e6366a --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Attributes/Permission/PartialPermissionAttribute.cs @@ -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 . + +using System; +using Kyoo.Abstractions.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; + +namespace Kyoo.Abstractions.Models.Permissions +{ + /// + /// Specify one part of a permissions needed for the API (the kind or the type). + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] + public class PartialPermissionAttribute : Attribute, IFilterFactory + { + /// + /// The needed permission type. + /// + public string Type { get; } + + /// + /// The needed permission kind. + /// + public Kind Kind { get; } + + /// + /// Ask a permission to run an action. + /// + /// + /// 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. + /// + /// + /// The type of the action + /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)). + /// + public PartialPermissionAttribute(string type) + { + if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase)) + type = type[..^3]; + Type = type.ToLower(); + } + + /// + /// Ask a permission to run an action. + /// + /// + /// 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. + /// + /// The kind of permission needed. + public PartialPermissionAttribute(Kind permission) + { + Kind = permission; + } + + /// + public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) + { + return serviceProvider.GetRequiredService().Create(this); + } + + /// + public bool IsReusable => true; + } +} diff --git a/src/Kyoo.Abstractions/Models/Attributes/Permission/PermissionAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/Permission/PermissionAttribute.cs new file mode 100644 index 00000000..2cf85d2f --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Attributes/Permission/PermissionAttribute.cs @@ -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 . + +using System; +using Kyoo.Abstractions.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; + +namespace Kyoo.Abstractions.Models.Permissions +{ + /// + /// The kind of permission needed. + /// + public enum Kind + { + /// + /// Allow the user to read for this kind of data. + /// + Read, + + /// + /// Allow the user to write for this kind of data. + /// + Write, + + /// + /// Allow the user to create this kind of data. + /// + Create, + + /// + /// Allow the user to delete this kind od data. + /// + Delete + } + + /// + /// The group of the permission. + /// + public enum Group + { + /// + /// Allow all operations on basic items types. + /// + Overall, + + /// + /// Allow operation on sensitive items like libraries path, configurations and so on. + /// + Admin + } + + /// + /// Specify permissions needed for the API. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] + public class PermissionAttribute : Attribute, IFilterFactory + { + /// + /// The needed permission as string. + /// + public string Type { get; } + + /// + /// The needed permission kind. + /// + public Kind Kind { get; } + + /// + /// The group of this permission. + /// + public Group Group { get; } + + /// + /// Ask a permission to run an action. + /// + /// + /// The type of the action + /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)). + /// + /// The kind of permission needed. + /// + /// The group of this permission (allow grouped permission like overall.read + /// for all read permissions of this group). + /// + 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; + } + + /// + public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) + { + return serviceProvider.GetRequiredService().Create(this); + } + + /// + public bool IsReusable => true; + + /// + /// Return this permission attribute as a string. + /// + /// The string representation. + public string AsPermissionString() + { + return Type; + } + } +} diff --git a/src/Kyoo.Abstractions/Models/Attributes/Serializer/DeserializeIgnoreAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/Serializer/DeserializeIgnoreAttribute.cs new file mode 100644 index 00000000..e1ab8bcc --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Attributes/Serializer/DeserializeIgnoreAttribute.cs @@ -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 . + +using System; + +namespace Kyoo.Abstractions.Models.Attributes +{ + /// + /// Remove a property from the deserialization pipeline. The user can't input value for this property. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] + public class DeserializeIgnoreAttribute : Attribute { } +} diff --git a/Kyoo.Abstractions/Models/Attributes/SerializeAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/Serializer/SerializeAsAttribute.cs similarity index 59% rename from Kyoo.Abstractions/Models/Attributes/SerializeAttribute.cs rename to src/Kyoo.Abstractions/Models/Attributes/Serializer/SerializeAsAttribute.cs index d2f2eb68..6e2a8983 100644 --- a/Kyoo.Abstractions/Models/Attributes/SerializeAttribute.cs +++ b/src/Kyoo.Abstractions/Models/Attributes/Serializer/SerializeAsAttribute.cs @@ -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 . + using System; namespace Kyoo.Abstractions.Models.Attributes { - /// - /// Remove an property from the serialization pipeline. It will simply be skipped. - /// - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] - public class SerializeIgnoreAttribute : Attribute {} - - /// - /// Remove a property from the deserialization pipeline. The user can't input value for this property. - /// - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] - public class DeserializeIgnoreAttribute : Attribute {} - /// /// 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. /// public string Format { get; } - + /// /// Create a new with the selected format. /// @@ -42,4 +48,4 @@ namespace Kyoo.Abstractions.Models.Attributes Format = format; } } -} \ No newline at end of file +} diff --git a/src/Kyoo.Abstractions/Models/Attributes/Serializer/SerializeIgnoreAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/Serializer/SerializeIgnoreAttribute.cs new file mode 100644 index 00000000..9fc37750 --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Attributes/Serializer/SerializeIgnoreAttribute.cs @@ -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 . + +using System; + +namespace Kyoo.Abstractions.Models.Attributes +{ + /// + /// Remove an property from the serialization pipeline. It will simply be skipped. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] + public class SerializeIgnoreAttribute : Attribute { } +} diff --git a/Kyoo.Abstractions/Models/Attributes/TaskMetadataAttribute.cs b/src/Kyoo.Abstractions/Models/Attributes/TaskMetadataAttribute.cs similarity index 76% rename from Kyoo.Abstractions/Models/Attributes/TaskMetadataAttribute.cs rename to src/Kyoo.Abstractions/Models/Attributes/TaskMetadataAttribute.cs index 18cf7802..3683fe77 100644 --- a/Kyoo.Abstractions/Models/Attributes/TaskMetadataAttribute.cs +++ b/src/Kyoo.Abstractions/Models/Attributes/TaskMetadataAttribute.cs @@ -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 . + 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. /// public string Slug { get; } - + /// /// The name of the task that will be displayed to the user. /// public string Name { get; } - + /// /// A quick description of what this task will do. /// @@ -31,18 +49,17 @@ namespace Kyoo.Abstractions.Models.Attributes /// Should this task be automatically run at app startup? /// public bool RunOnStartup { get; set; } - + /// /// The priority of this task. Only used if is true. /// It allow one to specify witch task will be started first as tasked are run on a Priority's descending order. /// public int Priority { get; set; } - + /// /// true if this task should not be displayed to the user, false otherwise. /// public bool IsHidden { get; set; } - /// /// Create a new with the given slug, name and description. @@ -56,7 +73,7 @@ namespace Kyoo.Abstractions.Models.Attributes Name = name; Description = description; } - + /// /// Create a new using a dictionary of metadata. /// @@ -74,4 +91,4 @@ namespace Kyoo.Abstractions.Models.Attributes IsHidden = (bool)metadata[nameof(IsHidden)]; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Chapter.cs b/src/Kyoo.Abstractions/Models/Chapter.cs similarity index 58% rename from Kyoo.Abstractions/Models/Chapter.cs rename to src/Kyoo.Abstractions/Models/Chapter.cs index 4605e7b4..c03e1045 100644 --- a/Kyoo.Abstractions/Models/Chapter.cs +++ b/src/Kyoo.Abstractions/Models/Chapter.cs @@ -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 . + namespace Kyoo.Abstractions.Models { /// @@ -9,16 +27,16 @@ namespace Kyoo.Abstractions.Models /// The start time of the chapter (in second from the start of the episode). /// public float StartTime { get; set; } - + /// - /// 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). /// public float EndTime { get; set; } - + /// /// 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. /// public string Name { get; set; } @@ -35,4 +53,4 @@ namespace Kyoo.Abstractions.Models Name = name; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/ConfigurationReference.cs b/src/Kyoo.Abstractions/Models/ConfigurationReference.cs similarity index 80% rename from Kyoo.Abstractions/Models/ConfigurationReference.cs rename to src/Kyoo.Abstractions/Models/ConfigurationReference.cs index 676367e3..2272612f 100644 --- a/Kyoo.Abstractions/Models/ConfigurationReference.cs +++ b/src/Kyoo.Abstractions/Models/ConfigurationReference.cs @@ -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 . + using System; using System.Collections.Generic; using System.Reflection; @@ -21,7 +39,6 @@ namespace Kyoo.Abstractions.Models /// public Type Type { get; } - /// /// Create a new using a given path and type. /// This method does not create sub configuration resources. Please see @@ -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; } - + /// /// Return the list of configuration reference a type has. /// @@ -89,10 +105,9 @@ namespace Kyoo.Abstractions.Models return CreateReference(path, typeof(T)); } - public static ConfigurationReference CreateUntyped(string path) { return new(path, null); } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Exceptions/DuplicatedItemException.cs b/src/Kyoo.Abstractions/Models/Exceptions/DuplicatedItemException.cs similarity index 54% rename from Kyoo.Abstractions/Models/Exceptions/DuplicatedItemException.cs rename to src/Kyoo.Abstractions/Models/Exceptions/DuplicatedItemException.cs index 248ea2ba..ddb17cd5 100644 --- a/Kyoo.Abstractions/Models/Exceptions/DuplicatedItemException.cs +++ b/src/Kyoo.Abstractions/Models/Exceptions/DuplicatedItemException.cs @@ -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 . + using System; using System.Runtime.Serialization; @@ -15,7 +33,7 @@ namespace Kyoo.Abstractions.Models.Exceptions public DuplicatedItemException() : base("Already exists in the database.") { } - + /// /// Create a new with a custom message. /// @@ -23,9 +41,9 @@ namespace Kyoo.Abstractions.Models.Exceptions public DuplicatedItemException(string message) : base(message) { } - + /// - /// The serialization constructor + /// The serialization constructor. /// /// Serialization infos /// The serialization context @@ -33,4 +51,4 @@ namespace Kyoo.Abstractions.Models.Exceptions : base(info, context) { } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Exceptions/IdentificationFailedException.cs b/src/Kyoo.Abstractions/Models/Exceptions/IdentificationFailedException.cs similarity index 55% rename from Kyoo.Abstractions/Models/Exceptions/IdentificationFailedException.cs rename to src/Kyoo.Abstractions/Models/Exceptions/IdentificationFailedException.cs index 05740b42..0549c444 100644 --- a/Kyoo.Abstractions/Models/Exceptions/IdentificationFailedException.cs +++ b/src/Kyoo.Abstractions/Models/Exceptions/IdentificationFailedException.cs @@ -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 . + using System; using System.Runtime.Serialization; using Kyoo.Abstractions.Controllers; @@ -15,18 +33,18 @@ namespace Kyoo.Abstractions.Models.Exceptions /// public IdentificationFailedException() : base("An identification failed.") - {} - + { } + /// /// Create a new with a custom message. /// /// The message to use. public IdentificationFailedException(string message) : base(message) - {} - + { } + /// - /// The serialization constructor + /// The serialization constructor /// /// Serialization infos /// The serialization context @@ -34,4 +52,4 @@ namespace Kyoo.Abstractions.Models.Exceptions : base(info, context) { } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Exceptions/ItemNotFoundException.cs b/src/Kyoo.Abstractions/Models/Exceptions/ItemNotFoundException.cs similarity index 50% rename from Kyoo.Abstractions/Models/Exceptions/ItemNotFoundException.cs rename to src/Kyoo.Abstractions/Models/Exceptions/ItemNotFoundException.cs index 5a16e62e..96499762 100644 --- a/Kyoo.Abstractions/Models/Exceptions/ItemNotFoundException.cs +++ b/src/Kyoo.Abstractions/Models/Exceptions/ItemNotFoundException.cs @@ -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 . + using System; using System.Runtime.Serialization; @@ -12,7 +30,7 @@ namespace Kyoo.Abstractions.Models.Exceptions /// /// Create a default with no message. /// - public ItemNotFoundException() {} + public ItemNotFoundException() { } /// /// Create a new with a message @@ -21,9 +39,9 @@ namespace Kyoo.Abstractions.Models.Exceptions public ItemNotFoundException(string message) : base(message) { } - + /// - /// The serialization constructor + /// The serialization constructor /// /// Serialization infos /// The serialization context @@ -31,4 +49,4 @@ namespace Kyoo.Abstractions.Models.Exceptions : base(info, context) { } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Exceptions/TaskFailedException.cs b/src/Kyoo.Abstractions/Models/Exceptions/TaskFailedException.cs similarity index 59% rename from Kyoo.Abstractions/Models/Exceptions/TaskFailedException.cs rename to src/Kyoo.Abstractions/Models/Exceptions/TaskFailedException.cs index eebc784e..a40b962c 100644 --- a/Kyoo.Abstractions/Models/Exceptions/TaskFailedException.cs +++ b/src/Kyoo.Abstractions/Models/Exceptions/TaskFailedException.cs @@ -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 . + using System; using System.Runtime.Serialization; using Kyoo.Abstractions.Controllers; @@ -15,26 +33,26 @@ namespace Kyoo.Abstractions.Models.Exceptions /// public TaskFailedException() : base("A task failed.") - {} - + { } + /// /// Create a new with a custom message. /// /// The message to use. public TaskFailedException(string message) : base(message) - {} - + { } + /// /// Create a new wrapping another exception. /// /// The exception to wrap. public TaskFailedException(Exception exception) : base(exception) - {} - + { } + /// - /// The serialization constructor + /// The serialization constructor /// /// Serialization infos /// The serialization context @@ -42,4 +60,4 @@ namespace Kyoo.Abstractions.Models.Exceptions : base(info, context) { } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/LibraryItem.cs b/src/Kyoo.Abstractions/Models/LibraryItem.cs similarity index 76% rename from Kyoo.Abstractions/Models/LibraryItem.cs rename to src/Kyoo.Abstractions/Models/LibraryItem.cs index 802e98a3..c572f6a4 100644 --- a/Kyoo.Abstractions/Models/LibraryItem.cs +++ b/src/Kyoo.Abstractions/Models/LibraryItem.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq.Expressions; @@ -10,11 +28,22 @@ namespace Kyoo.Abstractions.Models /// public enum ItemType { + /// + /// The is a . + /// Show, + + /// + /// The is a Movie (a with equals to true). + /// Movie, + + /// + /// The is a . + /// Collection } - + /// /// A type union between and . /// This is used to list content put inside a library. @@ -23,30 +52,30 @@ namespace Kyoo.Abstractions.Models { /// public int ID { get; set; } - + /// public string Slug { get; set; } - + /// /// The title of the show or collection. /// public string Title { get; set; } - + /// /// The summary of the show or collection. /// public string Overview { get; set; } - + /// /// Is this show airing, not aired yet or finished? This is only applicable for shows. /// public Status? Status { get; set; } - + /// - /// 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. /// public DateTime? StartAir { get; set; } - + /// /// The date this show or collection finished airing. /// It must be after the but can be the same (example: for movies). @@ -64,17 +93,16 @@ namespace Kyoo.Abstractions.Models /// [SerializeAs("{HOST}/api/{Type:l}/{Slug}/poster")] public string Poster => Images?.GetValueOrDefault(Models.Images.Poster); - + /// /// The type of this item (ether a collection, a show or a movie). /// public ItemType Type { get; set; } - - + /// /// Create a new, empty . /// - public LibraryItem() {} + public LibraryItem() { } /// /// Create a from a show. @@ -92,7 +120,7 @@ namespace Kyoo.Abstractions.Models Images = show.Images; Type = show.IsMovie ? ItemType.Movie : ItemType.Show; } - + /// /// Create a from a collection /// @@ -125,7 +153,7 @@ namespace Kyoo.Abstractions.Models Images = x.Images, Type = x.IsMovie ? ItemType.Movie : ItemType.Show }; - + /// /// An expression to create a representing a collection. /// @@ -142,4 +170,4 @@ namespace Kyoo.Abstractions.Models Type = ItemType.Collection }; } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/MetadataID.cs b/src/Kyoo.Abstractions/Models/MetadataID.cs similarity index 60% rename from Kyoo.Abstractions/Models/MetadataID.cs rename to src/Kyoo.Abstractions/Models/MetadataID.cs index 5cdf08ea..dbf00a3e 100644 --- a/Kyoo.Abstractions/Models/MetadataID.cs +++ b/src/Kyoo.Abstractions/Models/MetadataID.cs @@ -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 . + using System; using System.Linq.Expressions; using Kyoo.Abstractions.Models.Attributes; @@ -9,6 +27,14 @@ namespace Kyoo.Abstractions.Models /// public class MetadataID { + /// + /// The expression to retrieve the unique ID of a MetadataID. This is an aggregate of the two resources IDs. + /// + public static Expression> PrimaryKey + { + get { return x => new { First = x.ResourceID, Second = x.ProviderID }; } + } + /// /// The ID of the resource which possess the metadata. /// @@ -33,13 +59,5 @@ namespace Kyoo.Abstractions.Models /// The URL of the resource on the external provider. /// public string Link { get; set; } - - /// - /// The expression to retrieve the unique ID of a MetadataID. This is an aggregate of the two resources IDs. - /// - public static Expression> PrimaryKey - { - get { return x => new { First = x.ResourceID, Second = x.ProviderID }; } - } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Page.cs b/src/Kyoo.Abstractions/Models/Page.cs similarity index 72% rename from Kyoo.Abstractions/Models/Page.cs rename to src/Kyoo.Abstractions/Models/Page.cs index 5dc37abb..848a4e21 100644 --- a/Kyoo.Abstractions/Models/Page.cs +++ b/src/Kyoo.Abstractions/Models/Page.cs @@ -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 . + 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. /// /// The type of resource contained in this page. - public class Page where T : IResource + public class Page + where T : IResource { /// /// The link of the current page. /// public Uri This { get; } - + /// /// The link of the first page. /// public Uri First { get; } - + /// /// The link of the next page. /// @@ -30,13 +49,12 @@ namespace Kyoo.Abstractions.Models /// The number of items in the current page. /// public int Count => Items.Count; - + /// /// The list of items in the page. /// public ICollection Items { get; } - - + /// /// Create a new . /// @@ -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()); } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/PeopleRole.cs b/src/Kyoo.Abstractions/Models/PeopleRole.cs similarity index 65% rename from Kyoo.Abstractions/Models/PeopleRole.cs rename to src/Kyoo.Abstractions/Models/PeopleRole.cs index 934daf7d..3a416927 100644 --- a/Kyoo.Abstractions/Models/PeopleRole.cs +++ b/src/Kyoo.Abstractions/Models/PeopleRole.cs @@ -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 . + namespace Kyoo.Abstractions.Models { /// @@ -6,16 +24,16 @@ namespace Kyoo.Abstractions.Models /// /// This class is not serialized like other classes. /// Based on the field, it is serialized like - /// a show with two extra fields ( and ). + /// a show with two extra fields ( and ). /// public class PeopleRole : IResource { /// public int ID { get; set; } - + /// public string Slug => ForPeople ? Show.Slug : People.Slug; - + /// /// Should this role be used as a Show substitute (the value is true) or /// as a People substitute (the value is false). @@ -26,30 +44,32 @@ namespace Kyoo.Abstractions.Models /// The ID of the People playing the role. /// public int PeopleID { get; set; } + /// /// The people that played this role. /// public People People { get; set; } - + /// /// The ID of the Show where the People playing in. /// public int ShowID { get; set; } + /// /// The show where the People played in. /// public Show Show { get; set; } - + /// /// 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"... /// public string Type { get; set; } - + /// /// 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. /// public string Role { get; set; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Resources/Collection.cs b/src/Kyoo.Abstractions/Models/Resources/Collection.cs similarity index 66% rename from Kyoo.Abstractions/Models/Resources/Collection.cs rename to src/Kyoo.Abstractions/Models/Resources/Collection.cs index faa7ac9f..5f48fee1 100644 --- a/Kyoo.Abstractions/Models/Resources/Collection.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Collection.cs @@ -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 . + +using System; using System.Collections.Generic; using Kyoo.Abstractions.Models.Attributes; @@ -12,10 +30,10 @@ namespace Kyoo.Abstractions.Models { /// public int ID { get; set; } - + /// public string Slug { get; set; } - + /// /// The name of this collection. /// @@ -23,7 +41,7 @@ namespace Kyoo.Abstractions.Models /// public Dictionary Images { get; set; } - + /// /// 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. /// public string Overview { get; set; } - + /// /// The list of shows contained in this collection. /// [LoadableRelation] public ICollection Shows { get; set; } - + /// /// The list of libraries that contains this collection. /// [LoadableRelation] public ICollection Libraries { get; set; } - + /// [EditableRelation] [LoadableRelation] public ICollection ExternalIDs { get; set; } } diff --git a/Kyoo.Abstractions/Models/Resources/Episode.cs b/src/Kyoo.Abstractions/Models/Resources/Episode.cs similarity index 85% rename from Kyoo.Abstractions/Models/Resources/Episode.cs rename to src/Kyoo.Abstractions/Models/Resources/Episode.cs index 65e1bd29..83f82b08 100644 --- a/Kyoo.Abstractions/Models/Resources/Episode.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Episode.cs @@ -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 . + +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, @"(?.+)-s(?\d+)e(?\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. /// [SerializeIgnore] public string ShowSlug { private get; set; } - + /// /// The ID of the Show containing this episode. /// [SerializeIgnore] public int ShowID { get; set; } + /// /// The show that contains this episode. This must be explicitly loaded via a call to . /// [LoadableRelation(nameof(ShowID))] public Show Show { get; set; } - + /// /// The ID of the Season containing this episode. /// [SerializeIgnore] public int? SeasonID { get; set; } + /// /// The season that contains this episode. /// This must be explicitly loaded via a call to . @@ -87,22 +108,22 @@ namespace Kyoo.Abstractions.Models /// The season in witch this episode is in. /// public int? SeasonNumber { get; set; } - + /// /// The number of this episode in it's season. /// public int? EpisodeNumber { get; set; } - + /// /// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season. /// public int? AbsoluteNumber { get; set; } - + /// /// The path of the video file for this episode. Any format supported by a is allowed. /// [SerializeIgnore] public string Path { get; set; } - + /// public Dictionary 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); - + /// /// The title of this episode. /// public string Title { get; set; } - + /// /// The overview of this episode. /// public string Overview { get; set; } - + /// /// The release date of this episode. It can be null if unknown. /// @@ -137,7 +158,6 @@ namespace Kyoo.Abstractions.Models /// The list of tracks this episode has. This lists video, audio and subtitles available. /// [EditableRelation] [LoadableRelation] public ICollection Tracks { get; set; } - /// /// Get the slug of an episode. @@ -157,8 +177,8 @@ namespace Kyoo.Abstractions.Models /// /// The slug corresponding to the given arguments /// The given show slug was null. - public static string GetSlug([NotNull] string showSlug, - int? seasonNumber, + public static string GetSlug([NotNull] string showSlug, + int? seasonNumber, int? episodeNumber, int? absoluteNumber = null) { diff --git a/Kyoo.Abstractions/Models/Resources/Genre.cs b/src/Kyoo.Abstractions/Models/Resources/Genre.cs similarity index 53% rename from Kyoo.Abstractions/Models/Resources/Genre.cs rename to src/Kyoo.Abstractions/Models/Resources/Genre.cs index 0cf2d9b3..5bf8ceee 100644 --- a/Kyoo.Abstractions/Models/Resources/Genre.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Genre.cs @@ -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 . + +using System.Collections.Generic; using Kyoo.Abstractions.Models.Attributes; using Kyoo.Utils; @@ -11,15 +29,15 @@ namespace Kyoo.Abstractions.Models { /// public int ID { get; set; } - + /// public string Slug { get; set; } - + /// /// The name of this genre. /// public string Name { get; set; } - + /// /// The list of shows that have this genre. /// @@ -28,11 +46,11 @@ namespace Kyoo.Abstractions.Models /// /// Create a new, empty . /// - public Genre() {} - + public Genre() { } + /// /// Create a new and specify it's . - /// The is automatically calculated from it's name. + /// The is automatically calculated from it's name. /// /// The name of this genre. public Genre(string name) diff --git a/Kyoo.Abstractions/Models/Resources/Interfaces/IMetadata.cs b/src/Kyoo.Abstractions/Models/Resources/Interfaces/IMetadata.cs similarity index 76% rename from Kyoo.Abstractions/Models/Resources/Interfaces/IMetadata.cs rename to src/Kyoo.Abstractions/Models/Resources/Interfaces/IMetadata.cs index b28d893a..44f072fa 100644 --- a/Kyoo.Abstractions/Models/Resources/Interfaces/IMetadata.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Interfaces/IMetadata.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -14,7 +32,8 @@ namespace Kyoo.Abstractions.Models /// /// The link to metadata providers that this show has. See for more information. /// - [EditableRelation] [LoadableRelation] + [EditableRelation] + [LoadableRelation] public ICollection ExternalIDs { get; set; } } @@ -25,7 +44,7 @@ namespace Kyoo.Abstractions.Models public static class MetadataExtension { /// - /// 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. /// /// /// This method will never return anything if the are not loaded. @@ -76,4 +95,4 @@ namespace Kyoo.Abstractions.Models return true; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs b/src/Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs similarity index 52% rename from Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs rename to src/Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs index bde5aef6..509006e5 100644 --- a/Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs @@ -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 . + using Kyoo.Abstractions.Controllers; namespace Kyoo.Abstractions.Models @@ -12,10 +30,10 @@ namespace Kyoo.Abstractions.Models /// /// /// You don't need to specify an ID manually when creating a new resource, - /// this field is automatically assigned by the . + /// this field is automatically assigned by the . /// public int ID { get; set; } - + /// /// 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}. /// - public string Slug { get; } + public string Slug { get; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs b/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs similarity index 65% rename from Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs rename to src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs index 670dbb51..e2d83e78 100644 --- a/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Interfaces/IThumbnails.cs @@ -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 . + 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 /// public Dictionary Images { get; set; } - + // TODO remove Posters properties add them via the json serializer for every IThumbnails } @@ -46,4 +64,4 @@ namespace Kyoo.Abstractions.Models /// public const int Trailer = 3; } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Resources/Library.cs b/src/Kyoo.Abstractions/Models/Resources/Library.cs similarity index 57% rename from Kyoo.Abstractions/Models/Resources/Library.cs rename to src/Kyoo.Abstractions/Models/Resources/Library.cs index fad1156e..a615b0f4 100644 --- a/Kyoo.Abstractions/Models/Resources/Library.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Library.cs @@ -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 . + +using System.Collections.Generic; using Kyoo.Abstractions.Models.Attributes; namespace Kyoo.Abstractions.Models @@ -10,15 +28,15 @@ namespace Kyoo.Abstractions.Models { /// public int ID { get; set; } - + /// public string Slug { get; set; } - + /// /// The name of this library. /// public string Name { get; set; } - + /// /// The list of paths that this library is responsible for. This is mainly used by the Scan task. /// @@ -33,7 +51,7 @@ namespace Kyoo.Abstractions.Models /// The list of shows in this library. /// [LoadableRelation] public ICollection Shows { get; set; } - + /// /// The list of collections in this library. /// diff --git a/Kyoo.Abstractions/Models/Resources/People.cs b/src/Kyoo.Abstractions/Models/Resources/People.cs similarity index 61% rename from Kyoo.Abstractions/Models/Resources/People.cs rename to src/Kyoo.Abstractions/Models/Resources/People.cs index ce46c6a7..e1070545 100644 --- a/Kyoo.Abstractions/Models/Resources/People.cs +++ b/src/Kyoo.Abstractions/Models/Resources/People.cs @@ -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 . + +using System; using System.Collections.Generic; using Kyoo.Abstractions.Models.Attributes; namespace Kyoo.Abstractions.Models { /// - /// An actor, voice actor, writer, animator, somebody who worked on a . + /// An actor, voice actor, writer, animator, somebody who worked on a . /// public class People : IResource, IMetadata, IThumbnails { /// public int ID { get; set; } - + /// public string Slug { get; set; } - + /// /// The name of this person. /// public string Name { get; set; } - + /// public Dictionary 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); - + /// [EditableRelation] [LoadableRelation] public ICollection ExternalIDs { get; set; } - + /// /// The list of roles this person has played in. See for more information. /// diff --git a/Kyoo.Abstractions/Models/Resources/Provider.cs b/src/Kyoo.Abstractions/Models/Resources/Provider.cs similarity index 70% rename from Kyoo.Abstractions/Models/Resources/Provider.cs rename to src/Kyoo.Abstractions/Models/Resources/Provider.cs index d1a34223..74401045 100644 --- a/Kyoo.Abstractions/Models/Resources/Provider.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Provider.cs @@ -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 . + using System; using System.Collections.Generic; using Kyoo.Abstractions.Controllers; @@ -14,15 +32,15 @@ namespace Kyoo.Abstractions.Models { /// public int ID { get; set; } - + /// public string Slug { get; set; } - + /// /// The name of this provider. /// public string Name { get; set; } - + /// public Dictionary Images { get; set; } @@ -47,7 +65,7 @@ namespace Kyoo.Abstractions.Models /// /// Create a new and specify it's . - /// The is automatically calculated from it's name. + /// The is automatically calculated from it's name. /// /// The name of this provider. /// The logo of this provider. @@ -61,4 +79,4 @@ namespace Kyoo.Abstractions.Models }; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Models/Resources/Season.cs b/src/Kyoo.Abstractions/Models/Resources/Season.cs similarity index 74% rename from Kyoo.Abstractions/Models/Resources/Season.cs rename to src/Kyoo.Abstractions/Models/Resources/Season.cs index d60da6d8..f219f483 100644 --- a/Kyoo.Abstractions/Models/Resources/Season.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Season.cs @@ -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 . + +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 { /// - /// A season of a . + /// A season of a . /// public class Season : IResource, IMetadata, IThumbnails { /// - public int ID { get; set; } + public int ID { get; set; } /// [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 ?? "", @"(?.+)-s(?\d+)"); - + Match match = Regex.Match(value ?? string.Empty, @"(?.+)-s(?\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. /// [SerializeIgnore] public string ShowSlug { private get; set; } - + /// /// The ID of the Show containing this season. /// [SerializeIgnore] public int ShowID { get; set; } + /// /// The show that contains this season. /// This must be explicitly loaded via a call to . @@ -59,17 +79,17 @@ namespace Kyoo.Abstractions.Models /// The title of this season. /// public string Title { get; set; } - + /// /// A quick overview of this season. /// public string Overview { get; set; } - + /// /// The starting air date of this season. /// public DateTime? StartDate { get; set; } - + /// /// The ending date of this season. /// @@ -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); - + /// [EditableRelation] [LoadableRelation] public ICollection ExternalIDs { get; set; } diff --git a/Kyoo.Abstractions/Models/Resources/Show.cs b/src/Kyoo.Abstractions/Models/Resources/Show.cs similarity index 81% rename from Kyoo.Abstractions/Models/Resources/Show.cs rename to src/Kyoo.Abstractions/Models/Resources/Show.cs index 77f18d99..87e00052 100644 --- a/Kyoo.Abstractions/Models/Resources/Show.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Show.cs @@ -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 . + +using System; using System.Collections.Generic; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models.Attributes; @@ -12,31 +30,31 @@ namespace Kyoo.Abstractions.Models { /// public int ID { get; set; } - + /// public string Slug { get; set; } - + /// /// The title of this show. /// public string Title { get; set; } - + /// /// The list of alternative titles of this show. /// [EditableRelation] public string[] Aliases { get; set; } - + /// /// The path of the root directory of this show. /// This can be any kind of path supported by /// [SerializeIgnore] public string Path { get; set; } - + /// /// The summary of this show. /// public string Overview { get; set; } - + /// /// Is this show airing, not aired yet or finished? /// @@ -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); - + /// - /// 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. /// public DateTime? StartAir { get; set; } - + /// /// The date this show finished airing. /// It must be after the 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. /// [SerializeIgnore] public int? StudioID { get; set; } + /// /// The Studio that made this show. /// This must be explicitly loaded via a call to . /// [LoadableRelation(nameof(StudioID))] [EditableRelation] public Studio Studio { get; set; } - + /// /// The list of genres (themes) this show has. /// [LoadableRelation] [EditableRelation] public ICollection Genres { get; set; } - + /// /// The list of people that made this show. /// [LoadableRelation] [EditableRelation] public ICollection People { get; set; } - + /// /// The different seasons in this show. If this is a movie, this list is always null or empty. /// [LoadableRelation] public ICollection Seasons { get; set; } - + /// /// 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. /// [LoadableRelation] public ICollection Episodes { get; set; } - + /// /// The list of libraries that contains this show. /// [LoadableRelation] public ICollection Libraries { get; set; } - + /// /// The list of collections that contains this show. /// [LoadableRelation] public ICollection Collections { get; set; } - + /// 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; + } } } /// /// The enum containing show's status. /// - public enum Status { Unknown, Finished, Airing, Planned } + public enum Status + { + /// + /// The status of the show is not known. + /// + Unknown, + + /// + /// The show has finished airing. + /// + Finished, + + /// + /// The show is still actively airing. + /// + Airing, + + /// + /// This show has not aired yet but has been announced. + /// + Planned + } } diff --git a/Kyoo.Abstractions/Models/Resources/Studio.cs b/src/Kyoo.Abstractions/Models/Resources/Studio.cs similarity index 56% rename from Kyoo.Abstractions/Models/Resources/Studio.cs rename to src/Kyoo.Abstractions/Models/Resources/Studio.cs index fbc4934b..4bfcf5d0 100644 --- a/Kyoo.Abstractions/Models/Resources/Studio.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Studio.cs @@ -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 . + +using System.Collections.Generic; using Kyoo.Abstractions.Models.Attributes; using Kyoo.Utils; @@ -11,15 +29,15 @@ namespace Kyoo.Abstractions.Models { /// public int ID { get; set; } - + /// public string Slug { get; set; } - + /// /// The name of this studio. /// public string Name { get; set; } - + /// /// The list of shows that are made by this studio. /// @@ -27,7 +45,7 @@ namespace Kyoo.Abstractions.Models /// [EditableRelation] [LoadableRelation] public ICollection ExternalIDs { get; set; } - + /// /// Create a new, empty, . /// diff --git a/Kyoo.Abstractions/Models/Resources/Track.cs b/src/Kyoo.Abstractions/Models/Resources/Track.cs similarity index 71% rename from Kyoo.Abstractions/Models/Resources/Track.cs rename to src/Kyoo.Abstractions/Models/Resources/Track.cs index 4f94b7f3..e6d5d7e1 100644 --- a/Kyoo.Abstractions/Models/Resources/Track.cs +++ b/src/Kyoo.Abstractions/Models/Resources/Track.cs @@ -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 . + +using System; using System.Globalization; using System.Linq; using System.Text.RegularExpressions; @@ -13,10 +31,30 @@ namespace Kyoo.Abstractions.Models /// public enum StreamType { + /// + /// The type of the stream is not known. + /// Unknown = 0, + + /// + /// The stream is a video. + /// Video = 1, + + /// + /// The stream is an audio. + /// Audio = 2, + + /// + /// The stream is a subtitle. + /// Subtitle = 3, + + /// + /// 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. + /// Attachment = 4 } @@ -27,7 +65,7 @@ namespace Kyoo.Abstractions.Models { /// public int ID { get; set; } - + /// [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, @"(?[^\.]+)\.(?\w{0,3})(-(?\d+))?(\.(?forced))?\.(?\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(match.Groups["type"].Value, true); } } - + /// /// The slug of the episode that contain this track. If this is not set, this track is ill-formed. /// [SerializeIgnore] public string EpisodeSlug { private get; set; } - + /// /// The title of the stream. /// public string Title { get; set; } - + /// /// The language of this stream (as a ISO-639-2 language code) /// public string Language { get; set; } - + /// /// The codec of this stream. /// public string Codec { get; set; } - - + /// /// Is this stream the default one of it's type? /// public bool IsDefault { get; set; } - + /// - /// Is this stream tagged as forced? + /// Is this stream tagged as forced? /// public bool IsForced { get; set; } - + /// /// Is this track extern to the episode's file? /// public bool IsExternal { get; set; } - + /// /// The path of this track. /// [SerializeIgnore] public string Path { get; set; } - + /// /// The type of this stream. /// [SerializeIgnore] public StreamType Type { get; set; } - + /// /// The ID of the episode that uses this track. /// [SerializeIgnore] public int EpisodeID { get; set; } + /// /// The episode that uses this track. /// @@ -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 /// /// The slug to edit /// The new type of this - /// - public static string BuildSlug(string baseSlug, - StreamType type) + /// The completed slug. + 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()}"; } } diff --git a/Kyoo.Abstractions/Models/Resources/User.cs b/src/Kyoo.Abstractions/Models/Resources/User.cs similarity index 64% rename from Kyoo.Abstractions/Models/Resources/User.cs rename to src/Kyoo.Abstractions/Models/Resources/User.cs index 8e61cb64..69c7dfa4 100644 --- a/Kyoo.Abstractions/Models/Resources/User.cs +++ b/src/Kyoo.Abstractions/Models/Resources/User.cs @@ -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 . + using System.Collections.Generic; namespace Kyoo.Abstractions.Models @@ -9,30 +27,30 @@ namespace Kyoo.Abstractions.Models { /// public int ID { get; set; } - + /// public string Slug { get; set; } - + /// /// A username displayed to the user. /// public string Username { get; set; } - + /// /// The user email address. /// public string Email { get; set; } - + /// /// The user password (hashed, it can't be read like that). The hashing format is implementation defined. /// public string Password { get; set; } - + /// /// The list of permissions of the user. The format of this is implementation dependent. /// public string[] Permissions { get; set; } - + /// /// Arbitrary extra data that can be used by specific authentication implementations. /// @@ -45,36 +63,10 @@ namespace Kyoo.Abstractions.Models /// The list of shows the user has finished. /// public ICollection Watched { get; set; } - + /// /// The list of episodes the user is watching (stopped in progress or the next episode of the show) /// public ICollection CurrentlyWatching { get; set; } } - - /// - /// Metadata of episode currently watching by an user - /// - public class WatchedEpisode - { - /// - /// The ID of the user that started watching this episode. - /// - public int UserID { get; set; } - - /// - /// The ID of the episode started. - /// - public int EpisodeID { get; set; } - - /// - /// The started. - /// - public Episode Episode { get; set; } - - /// - /// Where the player has stopped watching the episode (between 0 and 100). - /// - public int WatchedPercentage { get; set; } - } -} \ No newline at end of file +} diff --git a/src/Kyoo.Abstractions/Models/Resources/WatchedEpisode.cs b/src/Kyoo.Abstractions/Models/Resources/WatchedEpisode.cs new file mode 100644 index 00000000..631c417f --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Resources/WatchedEpisode.cs @@ -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 . + +namespace Kyoo.Abstractions.Models +{ + /// + /// Metadata of episode currently watching by an user + /// + public class WatchedEpisode + { + /// + /// The ID of the user that started watching this episode. + /// + public int UserID { get; set; } + + /// + /// The ID of the episode started. + /// + public int EpisodeID { get; set; } + + /// + /// The started. + /// + public Episode Episode { get; set; } + + /// + /// Where the player has stopped watching the episode (between 0 and 100). + /// + public int WatchedPercentage { get; set; } + } +} diff --git a/Kyoo.Abstractions/Models/SearchResult.cs b/src/Kyoo.Abstractions/Models/SearchResult.cs similarity index 55% rename from Kyoo.Abstractions/Models/SearchResult.cs rename to src/Kyoo.Abstractions/Models/SearchResult.cs index 9b1b5006..0f42a077 100644 --- a/Kyoo.Abstractions/Models/SearchResult.cs +++ b/src/Kyoo.Abstractions/Models/SearchResult.cs @@ -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 . + +using System.Collections.Generic; namespace Kyoo.Abstractions.Models { @@ -11,32 +29,32 @@ namespace Kyoo.Abstractions.Models /// The query of the search request. /// public string Query { get; init; } - + /// /// The collections that matched the search. /// public ICollection Collections { get; init; } - + /// /// The shows that matched the search. /// public ICollection Shows { get; init; } - + /// /// The episodes that matched the search. /// public ICollection Episodes { get; init; } - + /// /// The people that matched the search. /// public ICollection People { get; init; } - + /// /// The genres that matched the search. /// public ICollection Genres { get; init; } - + /// /// The studios that matched the search. /// diff --git a/src/Kyoo.Abstractions/Models/Utils/AsyncRef.cs b/src/Kyoo.Abstractions/Models/Utils/AsyncRef.cs new file mode 100644 index 00000000..18ffd7d1 --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Utils/AsyncRef.cs @@ -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 . + +namespace Kyoo.Abstractions.Models +{ + /// + /// A class wrapping a value that will be set after the completion of the task it is related to. + /// + /// + /// This class replace the use of an out parameter on a task since tasks and out can't be combined. + /// + /// The type of the value + public class AsyncRef + { + /// + /// The value that will be set before the completion of the task. + /// + public T Value { get; set; } + } +} diff --git a/src/Kyoo.Abstractions/Models/Utils/Pagination.cs b/src/Kyoo.Abstractions/Models/Utils/Pagination.cs new file mode 100644 index 00000000..652991a1 --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Utils/Pagination.cs @@ -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 . + +namespace Kyoo.Abstractions.Controllers +{ + /// + /// Information about the pagination. How many items should be displayed and where to start. + /// + public readonly struct Pagination + { + /// + /// The count of items to return. + /// + public int Count { get; } + + /// + /// Where to start? Using the given sort. + /// + public int AfterID { get; } + + /// + /// Create a new instance. + /// + /// Set the value + /// Set the value. If not specified, it will start from the start + public Pagination(int count, int afterID = 0) + { + Count = count; + AfterID = afterID; + } + + /// + /// Implicitly create a new pagination from a limit number. + /// + /// Set the value + /// A new instance + public static implicit operator Pagination(int limit) => new(limit); + } +} diff --git a/src/Kyoo.Abstractions/Models/Utils/Sort.cs b/src/Kyoo.Abstractions/Models/Utils/Sort.cs new file mode 100644 index 00000000..e68c8a8e --- /dev/null +++ b/src/Kyoo.Abstractions/Models/Utils/Sort.cs @@ -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 . + +using System; +using System.Linq.Expressions; +using Kyoo.Utils; + +namespace Kyoo.Abstractions.Controllers +{ + /// + /// Information about how a query should be sorted. What factor should decide the sort and in which order. + /// + /// For witch type this sort applies + public readonly struct Sort + { + /// + /// The sort key. This member will be used to sort the results. + /// + public Expression> Key { get; } + + /// + /// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order. + /// + public bool Descendant { get; } + + /// + /// Create a new instance. + /// + /// The sort key given. It is assigned to . + /// Should this be in descendant order? The default is false. + /// If the given key is not a member. + public Sort(Expression> key, bool descendant = false) + { + Key = key; + Descendant = descendant; + + if (!Utility.IsPropertyExpression(Key)) + throw new ArgumentException("The given sort key is not valid."); + } + + /// + /// Create a new instance from a key's name (case insensitive). + /// + /// A key name with an optional order specifier. Format: "key:asc", "key:desc" or "key". + /// An invalid key or sort specifier as been given. + 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>(Expression.Convert(property, typeof(object)), param) + : Expression.Lambda>(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}.") + }; + } + } +} diff --git a/Kyoo.Abstractions/Models/WatchItem.cs b/src/Kyoo.Abstractions/Models/WatchItem.cs similarity index 86% rename from Kyoo.Abstractions/Models/WatchItem.cs rename to src/Kyoo.Abstractions/Models/WatchItem.cs index 3f48a636..8c4daab9 100644 --- a/Kyoo.Abstractions/Models/WatchItem.cs +++ b/src/Kyoo.Abstractions/Models/WatchItem.cs @@ -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 . + +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. /// public int EpisodeID { get; set; } - + /// /// The slug of this episode. /// @@ -30,54 +48,54 @@ namespace Kyoo.Abstractions.Models /// The title of the show containing this episode. /// public string ShowTitle { get; set; } - + /// /// The slug of the show containing this episode /// public string ShowSlug { get; set; } - + /// /// The season in witch this episode is in. /// public int? SeasonNumber { get; set; } - + /// /// The number of this episode is it's season. /// public int? EpisodeNumber { get; set; } - + /// /// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season. /// public int? AbsoluteNumber { get; set; } - + /// /// The title of this episode. /// public string Title { get; set; } - + /// /// The release date of this episode. It can be null if unknown. /// public DateTime? ReleaseDate { get; set; } - + /// /// The path of the video file for this episode. Any format supported by a is allowed. /// [SerializeIgnore] public string Path { get; set; } - + /// /// 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. /// public Episode PreviousEpisode { get; set; } - + /// /// 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. /// public Episode NextEpisode { get; set; } - + /// /// true if this is a movie, false otherwise. /// @@ -89,14 +107,14 @@ namespace Kyoo.Abstractions.Models /// This can be disabled using the internal query flag. /// [SerializeAs("{HOST}/api/show/{ShowSlug}/poster")] public string Poster { get; set; } - + /// /// 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. /// [SerializeAs("{HOST}/api/show/{ShowSlug}/logo")] public string Logo { get; set; } - + /// /// 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. /// public string Container { get; set; } - + /// /// The video track. See for more information. /// public Track Video { get; set; } - + /// /// The list of audio tracks. See for more information. /// public ICollection Audios { get; set; } - + /// /// The list of subtitles tracks. See for more information. /// public ICollection Subtitles { get; set; } - + /// /// The list of chapters. See for more information. /// public ICollection Chapters { get; set; } - /// /// Create a from an . /// /// The episode to transform. /// - /// 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. /// /// A new WatchItem representing the given episode. public static async Task 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(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(x => x.ShowID == ep.ShowID + previous = await library.GetOrDefault(x => x.ShowID == ep.ShowID && x.AbsoluteNumber == ep.EpisodeNumber + 1); - next = await library.GetOrDefault(x => x.ShowID == ep.ShowID + next = await library.GetOrDefault(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> GetChapters(string episodePath) + private static async Task> _GetChapters(string episodePath) { string path = PathIO.Combine( - PathIO.GetDirectoryName(episodePath)!, + PathIO.GetDirectoryName(episodePath)!, "Chapters", PathIO.GetFileNameWithoutExtension(episodePath) + ".txt" ); diff --git a/Kyoo.Abstractions/Module.cs b/src/Kyoo.Abstractions/Module.cs similarity index 79% rename from Kyoo.Abstractions/Module.cs rename to src/Kyoo.Abstractions/Module.cs index dcc5bc18..102b9e2e 100644 --- a/Kyoo.Abstractions/Module.cs +++ b/src/Kyoo.Abstractions/Module.cs @@ -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 . + using Autofac; using Autofac.Builder; using Kyoo.Abstractions.Controllers; @@ -30,7 +48,7 @@ namespace Kyoo.Abstractions /// The container /// The type of the task /// The registration builder of this new provider. That can be used to edit the registration. - public static IRegistrationBuilder + public static IRegistrationBuilder RegisterProvider(this ContainerBuilder builder) where T : class, IMetadataProvider { @@ -46,7 +64,7 @@ namespace Kyoo.Abstractions /// If your repository implements a special interface, please use /// /// The initial container. - public static IRegistrationBuilder + public static IRegistrationBuilder RegisterRepository(this ContainerBuilder builder) where T : IBaseRepository { @@ -83,4 +101,4 @@ namespace Kyoo.Abstractions return configuration["basics:publicUrl"]?.TrimEnd('/') ?? "http://localhost:5000"; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Utility/EnumerableExtensions.cs b/src/Kyoo.Abstractions/Utility/EnumerableExtensions.cs similarity index 85% rename from Kyoo.Abstractions/Utility/EnumerableExtensions.cs rename to src/Kyoo.Abstractions/Utility/EnumerableExtensions.cs index 9bd81157..34ba106a 100644 --- a/Kyoo.Abstractions/Utility/EnumerableExtensions.cs +++ b/src/Kyoo.Abstractions/Utility/EnumerableExtensions.cs @@ -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 . + using System; using System.Collections; using System.Collections.Generic; @@ -16,7 +34,7 @@ namespace Kyoo.Utils /// /// The IEnumerable to map. If self is null, an empty list is returned /// The function that will map each items - /// The type of items in + /// The type of items in /// The type of items in the returned list /// The list mapped. /// The list or the mapper can't be null @@ -42,19 +60,19 @@ namespace Kyoo.Utils } return Generator(self, mapper); } - + /// /// A map where the mapping function is asynchronous. - /// Note: might interest you. + /// Note: might interest you. /// /// The IEnumerable to map. - /// The asynchronous function that will map each items - /// The type of items in - /// The type of items in the returned list - /// The list mapped as an AsyncEnumerable - /// The list or the mapper can't be null + /// The asynchronous function that will map each items. + /// The type of items in . + /// The type of items in the returned list. + /// The list mapped as an AsyncEnumerable. + /// The list or the mapper can't be null. [LinqTunnel] - public static IAsyncEnumerable MapAsync([NotNull] this IEnumerable self, + public static IAsyncEnumerable MapAsync([NotNull] this IEnumerable self, [NotNull] Func> mapper) { if (self == null) @@ -76,18 +94,18 @@ namespace Kyoo.Utils return Generator(self, mapper); } - + /// /// An asynchronous version of Select. /// /// The IEnumerable to map /// The asynchronous function that will map each items - /// The type of items in + /// The type of items in /// The type of items in the returned list /// The list mapped as an AsyncEnumerable /// The list or the mapper can't be null [LinqTunnel] - public static IAsyncEnumerable SelectAsync([NotNull] this IEnumerable self, + public static IAsyncEnumerable SelectAsync([NotNull] this IEnumerable self, [NotNull] Func> 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); } - + /// /// A foreach used as a function with a little specificity: the list can be null. /// @@ -192,12 +210,13 @@ namespace Kyoo.Utils foreach (object i in self) action(i); } - + /// /// A foreach used as a function with a little specificity: the list can be null. /// /// The list to enumerate. If this is null, the function result in a no-op /// The action to execute for each arguments + /// A representing the asynchronous operation. public static async Task ForEachAsync([CanBeNull] this IEnumerable self, Func action) { if (self == null) @@ -205,13 +224,14 @@ namespace Kyoo.Utils foreach (object i in self) await action(i); } - + /// /// A foreach used as a function with a little specificity: the list can be null. /// /// The list to enumerate. If this is null, the function result in a no-op /// The asynchronous action to execute for each arguments /// The type of items in the list. + /// A representing the asynchronous operation. public static async Task ForEachAsync([CanBeNull] this IEnumerable self, Func action) { if (self == null) @@ -219,13 +239,14 @@ namespace Kyoo.Utils foreach (T i in self) await action(i); } - + /// /// A foreach used as a function with a little specificity: the list can be null. /// /// The async list to enumerate. If this is null, the function result in a no-op /// The action to execute for each arguments /// The type of items in the list. + /// A representing the asynchronous operation. public static async Task ForEachAsync([CanBeNull] this IAsyncEnumerable self, Action action) { if (self == null) @@ -233,7 +254,7 @@ namespace Kyoo.Utils await foreach (T i in self) action(i); } - + /// /// Split a list in a small chunk of data. /// @@ -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)); } - + /// /// Split a list in a small chunk of data. /// @@ -260,7 +281,7 @@ namespace Kyoo.Utils { T[] ret = new T[countPerList]; int i = 0; - + using IEnumerator enumerator = list.GetEnumerator(); while (enumerator.MoveNext()) { @@ -276,4 +297,4 @@ namespace Kyoo.Utils yield return ret; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Utility/Merger.cs b/src/Kyoo.Abstractions/Utility/Merger.cs similarity index 88% rename from Kyoo.Abstractions/Utility/Merger.cs rename to src/Kyoo.Abstractions/Utility/Merger.cs index fe00a924..f8bb8286 100644 --- a/Kyoo.Abstractions/Utility/Merger.cs +++ b/src/Kyoo.Abstractions/Utility/Merger.cs @@ -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 . + using System; using System.Collections; using System.Collections.Generic; @@ -21,10 +39,11 @@ namespace Kyoo.Utils /// The first enumerable to merge /// The second enumerable to merge, if items from this list are equals to one from the first, they are not kept /// Equality function to compare items. If this is null, duplicated elements are kept + /// The type of items in the lists to merge. /// The two list merged as an array [ContractAnnotation("first:notnull => notnull; second:notnull => notnull", true)] public static T[] MergeLists([CanBeNull] IEnumerable first, - [CanBeNull] IEnumerable second, + [CanBeNull] IEnumerable second, [CanBeNull] Func 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 /// The object to assign /// The object containing new values /// Fields of T will be used - /// + /// public static T Assign(T first, T second) { Type type = typeof(T); IEnumerable 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; } - + /// /// 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 /// /// Fields of T will be completed - /// + /// /// If first is null - public static T Complete([NotNull] T first, - [CanBeNull] T second, + public static T Complete([NotNull] T first, + [CanBeNull] T second, [InstantHandle] Func where = null) { if (first == null) throw new ArgumentNullException(nameof(first)); if (second == null) return first; - + Type type = typeof(T); IEnumerable 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 } /// - /// This will set missing values of to the corresponding values of . + /// This will set missing values of to the corresponding values of . /// Enumerable will be merged (concatenated) and Dictionaries too. /// At the end, the OnMerge method of first will be called if first is a . /// @@ -259,9 +279,9 @@ namespace Kyoo.Utils /// Filter fields that will be merged /// /// Fields of T will be merged - /// + /// [ContractAnnotation("first:notnull => notnull; second:notnull => notnull", true)] - public static T Merge([CanBeNull] T first, + public static T Merge([CanBeNull] T first, [CanBeNull] T second, [InstantHandle] Func where = null) { @@ -269,28 +289,29 @@ namespace Kyoo.Utils return second; if (second == null) return first; - + Type type = typeof(T); IEnumerable 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 equalityComparer = enumerableType.IsAssignableTo(typeof(IResource)) - ? (x, y) => x.Slug == y.Slug + ? (x, y) => x.Slug == y.Slug : null; property.SetValue(first, Utility.RunGenericMethod( typeof(Merger), @@ -326,11 +347,11 @@ namespace Kyoo.Utils } /// - /// Set every fields of to the default value. + /// Set every fields of to the default value. /// /// The object to nullify /// Fields of T will be nullified - /// + /// public static T Nullify(T obj) { Type type = typeof(T); @@ -344,4 +365,4 @@ namespace Kyoo.Utils return obj; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Utility/MethodOfUtils.cs b/src/Kyoo.Abstractions/Utility/MethodOfUtils.cs similarity index 59% rename from Kyoo.Abstractions/Utility/MethodOfUtils.cs rename to src/Kyoo.Abstractions/Utility/MethodOfUtils.cs index 30a1ce4c..5a0629de 100644 --- a/Kyoo.Abstractions/Utility/MethodOfUtils.cs +++ b/src/Kyoo.Abstractions/Utility/MethodOfUtils.cs @@ -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 . + using System; using System.Reflection; @@ -17,75 +35,91 @@ namespace Kyoo.Utils { return action.Method; } - + /// /// Get a MethodInfo from a direct method. /// /// The method (without any arguments or return value. + /// The first parameter of the action. /// The of the given method public static MethodInfo MethodOf(Action action) { return action.Method; } - + /// /// Get a MethodInfo from a direct method. /// /// The method (without any arguments or return value. + /// The first parameter of the action. + /// The second parameter of the action. /// The of the given method public static MethodInfo MethodOf(Action action) { return action.Method; } - + /// /// Get a MethodInfo from a direct method. /// /// The method (without any arguments or return value. + /// The first parameter of the action. + /// The second parameter of the action. + /// The third parameter of the action. /// The of the given method public static MethodInfo MethodOf(Action action) { return action.Method; } - + /// /// Get a MethodInfo from a direct method. /// /// The method (without any arguments or return value. + /// The return type of function. /// The of the given method public static MethodInfo MethodOf(Func action) { return action.Method; } - + /// /// Get a MethodInfo from a direct method. /// /// The method (without any arguments or return value. + /// The first parameter of the function. + /// The return type of function. /// The of the given method public static MethodInfo MethodOf(Func action) { return action.Method; } - + /// /// Get a MethodInfo from a direct method. /// /// The method (without any arguments or return value. + /// The first parameter of the function. + /// The second parameter of the function. + /// The return type of function. /// The of the given method public static MethodInfo MethodOf(Func action) { return action.Method; } - + /// /// Get a MethodInfo from a direct method. /// /// The method (without any arguments or return value. + /// The first parameter of the function. + /// The second parameter of the function. + /// The third parameter of the function. + /// The return type of function. /// The of the given method public static MethodInfo MethodOf(Func action) { return action.Method; } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Utility/TaskUtils.cs b/src/Kyoo.Abstractions/Utility/TaskUtils.cs similarity index 76% rename from Kyoo.Abstractions/Utility/TaskUtils.cs rename to src/Kyoo.Abstractions/Utility/TaskUtils.cs index 91413f2c..69da84cc 100644 --- a/Kyoo.Abstractions/Utility/TaskUtils.cs +++ b/src/Kyoo.Abstractions/Utility/TaskUtils.cs @@ -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 . + using System; using System.Threading.Tasks; using JetBrains.Annotations; @@ -18,7 +36,6 @@ namespace Kyoo.Utils /// /// The type of the item in the task. /// A continuation task wrapping the initial task and adding a continuation method. - /// /// The source task has been canceled. public static Task Then(this Task task, Action then) { @@ -66,4 +83,4 @@ namespace Kyoo.Utils return value ?? Task.FromResult(default); } } -} \ No newline at end of file +} diff --git a/Kyoo.Abstractions/Utility/Utility.cs b/src/Kyoo.Abstractions/Utility/Utility.cs similarity index 88% rename from Kyoo.Abstractions/Utility/Utility.cs rename to src/Kyoo.Abstractions/Utility/Utility.cs index d1bb91b1..5c0dcc80 100644 --- a/Kyoo.Abstractions/Utility/Utility.cs +++ b/src/Kyoo.Abstractions/Utility/Utility.cs @@ -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 . + using System; using System.Collections.Generic; using System.Globalization; @@ -26,9 +44,9 @@ namespace Kyoo.Utils if (ex == null) return false; return ex.Body is MemberExpression || - ex.Body.NodeType == ExpressionType.Convert && ((UnaryExpression)ex.Body).Operand is MemberExpression; + (ex.Body.NodeType == ExpressionType.Convert && ((UnaryExpression)ex.Body).Operand is MemberExpression); } - + /// /// Get the name of a property. Useful for selectors as members ex: Load(x => x.Shows) /// @@ -51,7 +69,7 @@ namespace Kyoo.Utils /// The member value /// The owner of this member /// The value boxed as an object - /// if or is null. + /// if or is null. /// The member is not a field or a property. public static object GetValue([NotNull] this MemberInfo member, [NotNull] object obj) { @@ -66,9 +84,9 @@ namespace Kyoo.Utils _ => throw new ArgumentException($"Can't get value of a non property/field (member: {member}).") }; } - + /// - /// Slugify a string (Replace spaces by -, Uniformize accents é -> e) + /// Slugify a string (Replace spaces by -, Uniformize accents) /// /// The string to slugify /// The slug version of the given string @@ -78,7 +96,7 @@ namespace Kyoo.Utils return null; str = str.ToLowerInvariant(); - + string normalizedString = str.Normalize(NormalizationForm.FormD); StringBuilder stringBuilder = new(); foreach (char c in normalizedString) @@ -90,7 +108,7 @@ namespace Kyoo.Utils str = stringBuilder.ToString().Normalize(NormalizationForm.FormC); str = Regex.Replace(str, @"\s", "-", RegexOptions.Compiled); - str = Regex.Replace(str, @"[^\w\s\p{Pd}]", "", RegexOptions.Compiled); + str = Regex.Replace(str, @"[^\w\s\p{Pd}]", string.Empty, RegexOptions.Compiled); str = str.Trim('-', '_'); str = Regex.Replace(str, @"([-_]){2,}", "$1", RegexOptions.Compiled); return str; @@ -104,7 +122,7 @@ namespace Kyoo.Utils public static object GetClrDefault(this Type type) { return type.IsValueType - ? Activator.CreateInstance(type) + ? Activator.CreateInstance(type) : null; } @@ -113,7 +131,7 @@ namespace Kyoo.Utils /// /// The starting type /// A list of types - /// can't be null + /// can't be null public static IEnumerable GetInheritanceTree([NotNull] this Type type) { if (type == null) @@ -123,9 +141,9 @@ namespace Kyoo.Utils } /// - /// Check if inherit from a generic type . + /// Check if inherit from a generic type . /// - /// Does this object's type is a + /// Does this object's type is a /// The generic type to check against (Only generic types are supported like typeof(IEnumerable<>). /// True if obj inherit from genericType. False otherwise /// obj and genericType can't be null @@ -135,9 +153,9 @@ namespace Kyoo.Utils throw new ArgumentNullException(nameof(obj)); return IsOfGenericType(obj.GetType(), genericType); } - + /// - /// Check if inherit from a generic type . + /// Check if inherit from a generic type . /// /// The type to check /// The generic type to check against (Only generic types are supported like typeof(IEnumerable<>). @@ -160,14 +178,14 @@ namespace Kyoo.Utils } /// - /// Get the generic definition of . + /// Get the generic definition of . /// For example, calling this function with List<string> and typeof(IEnumerable<>) will return IEnumerable<string> /// /// The type to check /// The generic type to check against (Only generic types are supported like typeof(IEnumerable<>). /// The generic definition of genericType that type inherit or null if type does not implement the generic type. - /// and can't be null - /// must be a generic type + /// and can't be null + /// must be a generic type public static Type GetGenericDefinition([NotNull] Type type, [NotNull] Type genericType) { if (type == null) @@ -201,15 +219,15 @@ namespace Kyoo.Utils /// The list of generic parameters. /// /// - /// The list of parameters. + /// The list of parameters. /// /// No method match the given constraints. /// The method handle of the matching method. [PublicAPI] [NotNull] - public static MethodInfo GetMethod([NotNull] Type type, + public static MethodInfo GetMethod([NotNull] Type type, BindingFlags flag, - string name, + string name, [NotNull] Type[] generics, [NotNull] object[] args) { @@ -219,7 +237,7 @@ namespace Kyoo.Utils throw new ArgumentNullException(nameof(generics)); if (args == null) throw new ArgumentNullException(nameof(args)); - + MethodInfo[] methods = type.GetMethods(flag | BindingFlags.Public) .Where(x => x.Name == name) .Where(x => x.GetGenericArguments().Length == generics.Length) @@ -234,7 +252,7 @@ namespace Kyoo.Utils // return x.GetGenericArguments().All(y => y.IsAssignableFrom(generics[i++])); // }) // .IfEmpty(() => throw new NullReferenceException($"No method {name} match the generics specified.")) - + // TODO this won't work for Type because T is specified in arguments but not in the parameters type. // .Where(x => // { @@ -249,7 +267,7 @@ namespace Kyoo.Utils return methods[0]; throw new ArgumentException($"Multiple methods named {name} match the generics and parameters constraints."); } - + /// /// Run a generic static method for a runtime . /// @@ -276,14 +294,14 @@ namespace Kyoo.Utils /// /// public static T RunGenericMethod( - [NotNull] Type owner, + [NotNull] Type owner, [NotNull] string methodName, [NotNull] Type type, params object[] args) { - return RunGenericMethod(owner, methodName, new[] {type}, args); + return RunGenericMethod(owner, methodName, new[] { type }, args); } - + /// /// Run a generic static method for a multiple runtime . /// If your generic method only needs one type, see @@ -313,7 +331,7 @@ namespace Kyoo.Utils /// [PublicAPI] public static T RunGenericMethod( - [NotNull] Type owner, + [NotNull] Type owner, [NotNull] string methodName, [NotNull] Type[] types, params object[] args) @@ -361,7 +379,7 @@ namespace Kyoo.Utils [NotNull] Type type, params object[] args) { - return RunGenericMethod(instance, methodName, new[] {type}, args); + return RunGenericMethod(instance, methodName, new[] { type }, args); } /// @@ -392,7 +410,7 @@ namespace Kyoo.Utils /// /// public static T RunGenericMethod( - [NotNull] object instance, + [NotNull] object instance, [NotNull] string methodName, [NotNull] Type[] types, params object[] args) @@ -436,4 +454,4 @@ namespace Kyoo.Utils return $"{type.Name[..type.Name.IndexOf('`')]}<{generics}>"; } } -} \ No newline at end of file +} diff --git a/Kyoo.Authentication/AuthenticationModule.cs b/src/Kyoo.Authentication/AuthenticationModule.cs similarity index 82% rename from Kyoo.Authentication/AuthenticationModule.cs rename to src/Kyoo.Authentication/AuthenticationModule.cs index 805b01cd..82a224fa 100644 --- a/Kyoo.Authentication/AuthenticationModule.cs +++ b/src/Kyoo.Authentication/AuthenticationModule.cs @@ -1,5 +1,24 @@ -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 . + +using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; @@ -9,7 +28,6 @@ using IdentityServer4.Models; using IdentityServer4.Services; using Kyoo.Abstractions; using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models.Permissions; using Kyoo.Authentication.Models; using Kyoo.Authentication.Views; using Microsoft.AspNetCore.Builder; @@ -32,10 +50,10 @@ namespace Kyoo.Authentication { /// public string Slug => "auth"; - + /// public string Name => "Authentication"; - + /// public string Description => "Enable OpenID authentication for Kyoo."; @@ -47,7 +65,6 @@ namespace Kyoo.Authentication { CertificateOption.Path, typeof(CertificateOption) } }; - /// /// The configuration to use. /// @@ -63,15 +80,16 @@ namespace Kyoo.Authentication /// private readonly IWebHostEnvironment _environment; - /// /// Create a new authentication module instance and use the given configuration and environment. /// /// The configuration to use /// The logger used to allow IdentityServer to log things /// The environment information to check if the app runs in debug mode + [SuppressMessage("ReSharper", "ContextualLoggerProblem", + Justification = "The logger is used for a dependency that is not created via the container.")] public AuthenticationModule(IConfiguration configuration, - ILogger logger, + ILogger logger, IWebHostEnvironment environment) { _configuration = configuration; @@ -82,7 +100,7 @@ namespace Kyoo.Authentication /// public void Configure(ContainerBuilder builder) { - builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); DefaultCorsPolicyService cors = new(_logger) { @@ -100,16 +118,14 @@ namespace Kyoo.Authentication IdentityModelEventSource.ShowPII = true; services.AddControllers(); - - // TODO handle direct-videos with bearers (probably add a cookie and a app.Use to translate that for videos) - - // TODO Check if tokens should be stored. + // TODO handle direct-videos with bearers (probably add a cookie and a app.Use to translate that for videos) + // TODO Check if tokens should be stored. List clients = new(); _configuration.GetSection("authentication:clients").Bind(clients); CertificateOption certificateOptions = new(); _configuration.GetSection(CertificateOption.Path).Bind(certificateOptions); - + clients.AddRange(IdentityContext.GetClients()); foreach (Client client in clients) { @@ -131,7 +147,7 @@ namespace Kyoo.Authentication .AddInMemoryClients(clients) .AddProfileService() .AddSigninKeys(certificateOptions); - + services.AddAuthentication() .AddJwtBearer(options => { @@ -181,4 +197,4 @@ namespace Kyoo.Authentication SA.New(app => app.UseAuthorization(), SA.Authorization) }; } -} \ No newline at end of file +} diff --git a/Kyoo.Authentication/Controllers/Certificates.cs b/src/Kyoo.Authentication/Controllers/Certificates.cs similarity index 67% rename from Kyoo.Authentication/Controllers/Certificates.cs rename to src/Kyoo.Authentication/Controllers/Certificates.cs index 906890c4..05cb87cd 100644 --- a/Kyoo.Authentication/Controllers/Certificates.cs +++ b/src/Kyoo.Authentication/Controllers/Certificates.cs @@ -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 . + using System; using System.IO; using System.Security.Cryptography.X509Certificates; @@ -23,27 +41,27 @@ namespace Kyoo.Authentication { /// /// Add the certificate file to the identity server. If the certificate will expire soon, automatically renew it. - /// If no certificate exists, one is generated. + /// If no certificate exists, one is generated. /// /// The identity server that will be modified. /// The certificate options - /// - public static IIdentityServerBuilder AddSigninKeys(this IIdentityServerBuilder builder, + /// The initial builder to allow chain-calls. + public static IIdentityServerBuilder AddSigninKeys(this IIdentityServerBuilder builder, CertificateOption options) { - X509Certificate2 certificate = GetCertificate(options); + X509Certificate2 certificate = _GetCertificate(options); builder.AddSigningCredential(certificate); - + if (certificate.NotAfter.AddDays(-7) <= DateTime.UtcNow) { Console.WriteLine("Signin certificate will expire soon, renewing it."); if (File.Exists(options.OldFile)) File.Delete(options.OldFile); File.Move(options.File, options.OldFile); - builder.AddValidationKey(GenerateCertificate(options.File, options.Password)); + builder.AddValidationKey(_GenerateCertificate(options.File, options.Password)); } else if (File.Exists(options.OldFile)) - builder.AddValidationKey(GetExistingCredential(options.OldFile, options.Password)); + builder.AddValidationKey(_GetExistingCredential(options.OldFile, options.Password)); return builder; } @@ -52,11 +70,11 @@ namespace Kyoo.Authentication /// /// The certificate options /// A valid certificate - private static X509Certificate2 GetCertificate(CertificateOption options) + private static X509Certificate2 _GetCertificate(CertificateOption options) { - return File.Exists(options.File) - ? GetExistingCredential(options.File, options.Password) - : GenerateCertificate(options.File, options.Password); + return File.Exists(options.File) + ? _GetExistingCredential(options.File, options.Password) + : _GenerateCertificate(options.File, options.Password); } /// @@ -65,37 +83,36 @@ namespace Kyoo.Authentication /// The path of the certificate /// The password of the certificate /// The loaded certificate - private static X509Certificate2 GetExistingCredential(string file, string password) + private static X509Certificate2 _GetExistingCredential(string file, string password) { - return new X509Certificate2(file, password, - X509KeyStorageFlags.MachineKeySet | + X509KeyStorageFlags storeFlags = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | - X509KeyStorageFlags.Exportable - ); + X509KeyStorageFlags.Exportable; + return new X509Certificate2(file, password, storeFlags); } /// - /// Generate a new certificate key and put it in the file at . + /// Generate a new certificate key and put it in the file at . /// /// The path of the output file /// The password of the new certificate /// The generated certificate - private static X509Certificate2 GenerateCertificate(string file, string password) + private static X509Certificate2 _GenerateCertificate(string file, string password) { SecureRandom random = new(); - + X509V3CertificateGenerator certificateGenerator = new(); - certificateGenerator.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, + certificateGenerator.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random)); certificateGenerator.SetIssuerDN(new X509Name($"C=NL, O=SDG, CN=Kyoo")); certificateGenerator.SetSubjectDN(new X509Name($"C=NL, O=SDG, CN=Kyoo")); certificateGenerator.SetNotBefore(DateTime.UtcNow.Date); certificateGenerator.SetNotAfter(DateTime.UtcNow.Date.AddMonths(3)); - + KeyGenerationParameters keyGenerationParameters = new(random, 2048); RsaKeyPairGenerator keyPairGenerator = new(); keyPairGenerator.Init(keyGenerationParameters); - + AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair(); certificateGenerator.SetPublicKey(subjectKeyPair.Public); @@ -104,7 +121,7 @@ namespace Kyoo.Authentication X509Certificate bouncyCert = certificateGenerator.Generate(signatureFactory); Pkcs12Store store = new Pkcs12StoreBuilder().Build(); - store.SetKeyEntry("Kyoo_key", new AsymmetricKeyEntry(subjectKeyPair.Private), new [] + store.SetKeyEntry("Kyoo_key", new AsymmetricKeyEntry(subjectKeyPair.Private), new[] { new X509CertificateEntry(bouncyCert) }); @@ -117,4 +134,4 @@ namespace Kyoo.Authentication return certificate; } } -} \ No newline at end of file +} diff --git a/Kyoo.Authentication/Controllers/PasswordUtils.cs b/src/Kyoo.Authentication/Controllers/PasswordUtils.cs similarity index 68% rename from Kyoo.Authentication/Controllers/PasswordUtils.cs rename to src/Kyoo.Authentication/Controllers/PasswordUtils.cs index d28aaa99..fb2982ba 100644 --- a/Kyoo.Authentication/Controllers/PasswordUtils.cs +++ b/src/Kyoo.Authentication/Controllers/PasswordUtils.cs @@ -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 . + using System; using System.Linq; using System.Security.Cryptography; @@ -51,4 +69,4 @@ namespace Kyoo.Authentication return hash.SequenceEqual(validHash.Skip(16)); } } -} \ No newline at end of file +} diff --git a/Kyoo.Authentication/Controllers/PremissionValidator.cs b/src/Kyoo.Authentication/Controllers/PermissionValidator.cs similarity index 67% rename from Kyoo.Authentication/Controllers/PremissionValidator.cs rename to src/Kyoo.Authentication/Controllers/PermissionValidator.cs index d34f5e57..2f4a84f4 100644 --- a/Kyoo.Authentication/Controllers/PremissionValidator.cs +++ b/src/Kyoo.Authentication/Controllers/PermissionValidator.cs @@ -1,7 +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 . + using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Authentication.Models; using Microsoft.AspNetCore.Authentication; @@ -15,9 +34,9 @@ namespace Kyoo.Authentication { /// /// A permission validator to validate permission with user Permission array - /// or the default array from the configurations if the user is not logged. + /// or the default array from the configurations if the user is not logged. /// - public class PermissionValidatorFactory : IPermissionValidator + public class PermissionValidator : IPermissionValidator { /// /// The permissions options to retrieve default permissions. @@ -25,10 +44,10 @@ namespace Kyoo.Authentication private readonly IOptionsMonitor _options; /// - /// Create a new factory with the given options + /// Create a new factory with the given options. /// /// The option containing default values. - public PermissionValidatorFactory(IOptionsMonitor options) + public PermissionValidator(IOptionsMonitor options) { _options = options; } @@ -36,46 +55,49 @@ namespace Kyoo.Authentication /// public IFilterMetadata Create(PermissionAttribute attribute) { - return new PermissionValidator(attribute.Type, attribute.Kind, attribute.Group, _options); + return new PermissionValidatorFilter(attribute.Type, attribute.Kind, attribute.Group, _options); } - + /// public IFilterMetadata Create(PartialPermissionAttribute attribute) { - return new PermissionValidator((object)attribute.Type ?? attribute.Kind, _options); + return new PermissionValidatorFilter((object)attribute.Type ?? attribute.Kind, _options); } /// - /// The authorization filter used by + /// The authorization filter used by . /// - private class PermissionValidator : IAsyncAuthorizationFilter + private class PermissionValidatorFilter : IAsyncAuthorizationFilter { /// - /// The permission to validate + /// The permission to validate. /// private readonly string _permission; + /// - /// The kind of permission needed + /// The kind of permission needed. /// private readonly Kind? _kind; /// - /// The group of he permission + /// The group of he permission. /// private readonly Group _group = Group.Overall; + /// /// The permissions options to retrieve default permissions. /// private readonly IOptionsMonitor _options; /// - /// Create a new permission validator with the given options + /// Create a new permission validator with the given options. /// - /// The permission to validate - /// The kind of permission needed - /// The group of the permission + /// The permission to validate. + /// The kind of permission needed. + /// The group of the permission. /// The option containing default values. - public PermissionValidator(string permission, Kind kind, Group group, IOptionsMonitor options) + public PermissionValidatorFilter(string permission, Kind kind, Group group, + IOptionsMonitor options) { _permission = permission; _kind = kind; @@ -84,11 +106,11 @@ namespace Kyoo.Authentication } /// - /// Create a new permission validator with the given options + /// Create a new permission validator with the given options. /// - /// The partial permission to validate + /// The partial permission to validate. /// The option containing default values. - public PermissionValidator(object partialInfo, IOptionsMonitor options) + public PermissionValidatorFilter(object partialInfo, IOptionsMonitor options) { if (partialInfo is Kind kind) _kind = kind; @@ -99,7 +121,6 @@ namespace Kyoo.Authentication _options = options; } - /// public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { @@ -127,8 +148,10 @@ namespace Kyoo.Authentication "are not supported."); } if (permission == null || kind == null) + { throw new ArgumentException("The permission type or kind is still missing after two partial " + "permission attributes, this is unsupported."); + } } string permStr = $"{permission.ToLower()}.{kind.ToString()!.ToLower()}"; @@ -149,4 +172,4 @@ namespace Kyoo.Authentication } } } -} \ No newline at end of file +} diff --git a/Kyoo.Authentication/Extensions.cs b/src/Kyoo.Authentication/Extensions.cs similarity index 55% rename from Kyoo.Authentication/Extensions.cs rename to src/Kyoo.Authentication/Extensions.cs index ca37cd09..73b9deed 100644 --- a/Kyoo.Authentication/Extensions.cs +++ b/src/Kyoo.Authentication/Extensions.cs @@ -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 . + using System.Collections.Generic; using System.Linq; using System.Security.Claims; @@ -28,16 +46,16 @@ namespace Kyoo.Authentication } /// - /// Convert a user to an . + /// Convert a user to an IdentityServerUser. /// - /// The user to convert + /// The user to convert. /// The corresponding identity server user. public static IdentityServerUser ToIdentityUser(this User user) { - return new(user.ID.ToString()) + return new IdentityServerUser(user.ID.ToString()) { DisplayName = user.Username, - AdditionalClaims = new[] {new Claim("permissions", string.Join(',', user.Permissions))} + AdditionalClaims = new[] { new Claim("permissions", string.Join(',', user.Permissions)) } }; } @@ -51,4 +69,4 @@ namespace Kyoo.Authentication return user.Claims.FirstOrDefault(x => x.Type == "permissions")?.Value.Split(','); } } -} \ No newline at end of file +} diff --git a/Kyoo.Authentication/Kyoo.Authentication.csproj b/src/Kyoo.Authentication/Kyoo.Authentication.csproj similarity index 100% rename from Kyoo.Authentication/Kyoo.Authentication.csproj rename to src/Kyoo.Authentication/Kyoo.Authentication.csproj diff --git a/src/Kyoo.Authentication/Models/DTO/AccountUpdateRequest.cs b/src/Kyoo.Authentication/Models/DTO/AccountUpdateRequest.cs new file mode 100644 index 00000000..8833f4cc --- /dev/null +++ b/src/Kyoo.Authentication/Models/DTO/AccountUpdateRequest.cs @@ -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 . + +using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Http; + +namespace Kyoo.Authentication.Models.DTO +{ + /// + /// A model only used on account update requests. + /// + public class AccountUpdateRequest + { + /// + /// The new email address of the user + /// + [EmailAddress(ErrorMessage = "The email is invalid.")] + public string Email { get; set; } + + /// + /// The new username of the user. + /// + [MinLength(4, ErrorMessage = "The username must have at least 4 characters")] + public string Username { get; set; } + + /// + /// The picture icon. + /// + public IFormFile Picture { get; set; } + } +} diff --git a/src/Kyoo.Authentication/Models/DTO/LoginRequest.cs b/src/Kyoo.Authentication/Models/DTO/LoginRequest.cs new file mode 100644 index 00000000..80159361 --- /dev/null +++ b/src/Kyoo.Authentication/Models/DTO/LoginRequest.cs @@ -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 . + +namespace Kyoo.Authentication.Models.DTO +{ + /// + /// A model only used on login requests. + /// + public class LoginRequest + { + /// + /// The user's username. + /// + public string Username { get; set; } + + /// + /// The user's password. + /// + public string Password { get; set; } + + /// + /// Should the user stay logged in? If true a cookie will be put. + /// + public bool StayLoggedIn { get; set; } + + /// + /// The return url of the login flow. + /// + public string ReturnURL { get; set; } + } +} diff --git a/src/Kyoo.Authentication/Models/DTO/OtacRequest.cs b/src/Kyoo.Authentication/Models/DTO/OtacRequest.cs new file mode 100644 index 00000000..c9794e81 --- /dev/null +++ b/src/Kyoo.Authentication/Models/DTO/OtacRequest.cs @@ -0,0 +1,36 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +namespace Kyoo.Authentication.Models.DTO +{ + /// + /// A model to represent an otac request + /// + public class OtacRequest + { + /// + /// The One Time Access Code + /// + public string Otac { get; set; } + + /// + /// Should the user stay logged + /// + public bool StayLoggedIn { get; set; } + } +} diff --git a/Kyoo.Authentication/Models/DTO/RegisterRequest.cs b/src/Kyoo.Authentication/Models/DTO/RegisterRequest.cs similarity index 56% rename from Kyoo.Authentication/Models/DTO/RegisterRequest.cs rename to src/Kyoo.Authentication/Models/DTO/RegisterRequest.cs index 1e505bb7..776ba2a7 100644 --- a/Kyoo.Authentication/Models/DTO/RegisterRequest.cs +++ b/src/Kyoo.Authentication/Models/DTO/RegisterRequest.cs @@ -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 . + using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Kyoo.Abstractions.Models; @@ -15,24 +33,23 @@ namespace Kyoo.Authentication.Models.DTO /// [EmailAddress(ErrorMessage = "The email must be a valid email address")] public string Email { get; set; } - + /// - /// The user's username. + /// The user's username. /// [MinLength(4, ErrorMessage = "The username must have at least {1} characters")] public string Username { get; set; } - + /// /// The user's password. /// [MinLength(8, ErrorMessage = "The password must have at least {1} characters")] public string Password { get; set; } - /// /// Convert this register request to a new class. /// - /// + /// A user representing this request. public User ToUser() { return new User @@ -44,5 +61,5 @@ namespace Kyoo.Authentication.Models.DTO ExtraData = new Dictionary() }; } - } -} \ No newline at end of file + } +} diff --git a/Kyoo.Authentication/Models/IdentityContext.cs b/src/Kyoo.Authentication/Models/IdentityContext.cs similarity index 73% rename from Kyoo.Authentication/Models/IdentityContext.cs rename to src/Kyoo.Authentication/Models/IdentityContext.cs index e6ca3353..4c946653 100644 --- a/Kyoo.Authentication/Models/IdentityContext.cs +++ b/src/Kyoo.Authentication/Models/IdentityContext.cs @@ -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 . + using System.Collections.Generic; using System.Linq; using IdentityServer4.Models; @@ -24,7 +42,7 @@ namespace Kyoo.Authentication } /// - /// The list of officially supported clients. + /// Get the list of officially supported clients. /// /// /// You can add custom clients in the settings.json file. @@ -42,13 +60,13 @@ namespace Kyoo.Authentication AllowedGrantTypes = GrantTypes.Code, RequirePkce = true, RequireClientSecret = false, - + AllowAccessTokensViaBrowser = true, AllowOfflineAccess = true, RequireConsent = false, - + AllowedScopes = { "openid", "profile", "kyoo.read", "kyoo.write", "kyoo.play", "kyoo.admin" }, - RedirectUris = { "/", "/silent.html" }, + RedirectUris = { "/", "/silent.html" }, PostLogoutRedirectUris = { "/logout" } } }; @@ -84,7 +102,7 @@ namespace Kyoo.Authentication } }; } - + /// /// The list of APIs (this is used to create Audiences) /// @@ -100,4 +118,4 @@ namespace Kyoo.Authentication }; } } -} \ No newline at end of file +} diff --git a/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs b/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs new file mode 100644 index 00000000..1b43281f --- /dev/null +++ b/src/Kyoo.Authentication/Models/Options/AuthenticationOption.cs @@ -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 . + +namespace Kyoo.Authentication.Models +{ + /// + /// The main authentication options. + /// + public class AuthenticationOption + { + /// + /// The path to get this option from the root configuration. + /// + public const string Path = "authentication"; + + /// + /// The options for certificates + /// + public CertificateOption Certificate { get; set; } + + /// + /// Options for permissions + /// + public PermissionOption Permissions { get; set; } + + /// + /// Root path of user's profile pictures. + /// + public string ProfilePicturePath { get; set; } + } +} diff --git a/src/Kyoo.Authentication/Models/Options/CertificateOption.cs b/src/Kyoo.Authentication/Models/Options/CertificateOption.cs new file mode 100644 index 00000000..8e697a7f --- /dev/null +++ b/src/Kyoo.Authentication/Models/Options/CertificateOption.cs @@ -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 . + +namespace Kyoo.Authentication.Models +{ + /// + /// A typed option model for the certificate + /// + public class CertificateOption + { + /// + /// The path to get this option from the root configuration. + /// + public const string Path = "authentication:certificate"; + + /// + /// The path of the certificate file. + /// + public string File { get; set; } + + /// + /// The path of the old certificate file. + /// + public string OldFile { get; set; } + + /// + /// The password of the certificates. + /// + public string Password { get; set; } + } +} diff --git a/src/Kyoo.Authentication/Models/Options/PermissionOption.cs b/src/Kyoo.Authentication/Models/Options/PermissionOption.cs new file mode 100644 index 00000000..985a864d --- /dev/null +++ b/src/Kyoo.Authentication/Models/Options/PermissionOption.cs @@ -0,0 +1,41 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +namespace Kyoo.Authentication.Models +{ + /// + /// Permission options. + /// + public class PermissionOption + { + /// + /// The path to get this option from the root configuration. + /// + public const string Path = "authentication:permissions"; + + /// + /// The default permissions that will be given to a non-connected user. + /// + public string[] Default { get; set; } + + /// + /// Permissions applied to a new user. + /// + public string[] NewUser { get; set; } + } +} diff --git a/Kyoo.Authentication/Views/AccountApi.cs b/src/Kyoo.Authentication/Views/AccountApi.cs similarity index 81% rename from Kyoo.Authentication/Views/AccountApi.cs rename to src/Kyoo.Authentication/Views/AccountApi.cs index 1e369e31..af569655 100644 --- a/Kyoo.Authentication/Views/AccountApi.cs +++ b/src/Kyoo.Authentication/Views/AccountApi.cs @@ -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 . + using System; using System.Collections.Generic; using System.Globalization; @@ -33,16 +51,17 @@ namespace Kyoo.Authentication.Views /// The repository to handle users. /// private readonly IUserRepository _users; + /// /// A file manager to send profile pictures /// private readonly IFileSystem _files; + /// /// Options about authentication. Those options are monitored and reloads are supported. /// private readonly IOptions _options; - /// /// Create a new handle to handle login/users requests. /// @@ -57,10 +76,9 @@ namespace Kyoo.Authentication.Views _files = files; _options = options; } - - + /// - /// Register a new user and return a OTAC to connect to it. + /// Register a new user and return a OTAC to connect to it. /// /// The DTO register request /// A OTAC to connect to this new account @@ -78,10 +96,10 @@ namespace Kyoo.Authentication.Views } catch (DuplicatedItemException) { - return Conflict(new {Errors = new {Duplicate = new[] {"A user with this name already exists"}}}); + return Conflict(new { Errors = new { Duplicate = new[] { "A user with this name already exists" } } }); } - return Ok(new {Otac = user.ExtraData["otac"]}); + return Ok(new { Otac = user.ExtraData["otac"] }); } /// @@ -89,7 +107,7 @@ namespace Kyoo.Authentication.Views /// /// Should the user stay logged /// Authentication properties based on a stay login - private static AuthenticationProperties StayLogged(bool stayLogged) + private static AuthenticationProperties _StayLogged(bool stayLogged) { if (!stayLogged) return null; @@ -99,11 +117,12 @@ namespace Kyoo.Authentication.Views ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(1) }; } - + /// /// Login the user. /// /// The DTO login request + /// TODO [HttpPost("login")] public async Task Login([FromBody] LoginRequest login) { @@ -114,38 +133,41 @@ namespace Kyoo.Authentication.Views if (!PasswordUtils.CheckPassword(login.Password, user.Password)) return Unauthorized(); - await HttpContext.SignInAsync(user.ToIdentityUser(), StayLogged(login.StayLoggedIn)); + await HttpContext.SignInAsync(user.ToIdentityUser(), _StayLogged(login.StayLoggedIn)); return Ok(new { RedirectUrl = login.ReturnURL, IsOk = true }); } - + /// /// Use a OTAC to login a user. /// /// The OTAC request + /// TODO [HttpPost("otac-login")] public async Task OtacLogin([FromBody] OtacRequest otac) { // TODO once hstore (Dictionary accessor) are supported, use them. // We retrieve all users, this is inefficient. - User user = (await _users.GetAll()).FirstOrDefault(x => x.ExtraData.GetValueOrDefault("otac") == otac.Otac); + User user = (await _users.GetAll()).FirstOrDefault(x => x.ExtraData.GetValueOrDefault("otac") == otac.Otac); if (user == null) return Unauthorized(); if (DateTime.ParseExact(user.ExtraData["otac-expire"], "s", CultureInfo.InvariantCulture) <= - DateTime.UtcNow) + DateTime.UtcNow) { return BadRequest(new { - code = "ExpiredOTAC", description = "The OTAC has expired. Try to login with your password." + code = "ExpiredOTAC", + description = "The OTAC has expired. Try to login with your password." }); } - - await HttpContext.SignInAsync(user.ToIdentityUser(), StayLogged(otac.StayLoggedIn)); + + await HttpContext.SignInAsync(user.ToIdentityUser(), _StayLogged(otac.StayLoggedIn)); return Ok(); } - + /// /// Sign out an user /// + /// TODO [HttpGet("logout")] [Authorize] public async Task Logout() @@ -170,7 +192,7 @@ namespace Kyoo.Authentication.Views User user = await _users.GetOrDefault(int.Parse(context.Subject.GetSubjectId())); context.IsActive = user != null; } - + /// /// Get the user's profile picture. /// @@ -185,7 +207,7 @@ namespace Kyoo.Authentication.Views string path = Path.Combine(_options.Value.ProfilePicturePath, user.ID.ToString()); return _files.FileResult(path); } - + /// /// Update profile information (email, username, profile picture...) /// @@ -222,4 +244,4 @@ namespace Kyoo.Authentication.Views return _options.Value.Permissions.Default ?? Array.Empty(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/.gitignore b/src/Kyoo.Core/.gitignore similarity index 100% rename from Kyoo.Core/.gitignore rename to src/Kyoo.Core/.gitignore diff --git a/Kyoo.Core/Application.cs b/src/Kyoo.Core/Application.cs similarity index 87% rename from Kyoo.Core/Application.cs rename to src/Kyoo.Core/Application.cs index d3a2553f..7b0f4961 100644 --- a/Kyoo.Core/Application.cs +++ b/src/Kyoo.Core/Application.cs @@ -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 . + +using System; using System.Collections.Generic; using System.IO; using System.Threading; @@ -21,8 +39,18 @@ using ILogger = Serilog.ILogger; namespace Kyoo.Core { + /// + /// The main implementation of . + /// Hosts of kyoo (main functions) generally only create a new + /// and return . + /// public class Application : IApplication { + /// + /// The environment in witch Kyoo will run (ether "Production" or "Development"). + /// + private readonly string _environment; + /// /// The path to the data directory. /// @@ -32,23 +60,17 @@ namespace Kyoo.Core /// Should the application restart after a shutdown? /// private bool _shouldRestart; - + /// /// The cancellation token source used to allow the app to be shutdown or restarted. /// private CancellationTokenSource _tokenSource; - /// - /// The environment in witch Kyoo will run (ether "Production" or "Development"). - /// - private readonly string _environment; - /// /// The logger used for startup and error messages. /// private ILogger _logger; - /// /// Create a new that will use the specified environment. /// @@ -58,7 +80,6 @@ namespace Kyoo.Core _environment = environment; } - /// /// Start the application with the given console args. /// This is generally called from the Main entrypoint of Kyoo. @@ -80,28 +101,28 @@ namespace Kyoo.Core public async Task Start(string[] args, Action configure) { _dataDir = _SetupDataDir(args); - + LoggerConfiguration config = new(); _ConfigureLogging(config, null, null); Log.Logger = config.CreateBootstrapLogger(); _logger = Log.Logger.ForContext(); AppDomain.CurrentDomain.ProcessExit += (_, _) => Log.CloseAndFlush(); - AppDomain.CurrentDomain.UnhandledException += (_, ex) + AppDomain.CurrentDomain.UnhandledException += (_, ex) => Log.Fatal(ex.ExceptionObject as Exception, "Unhandled exception"); - + do { IHost host = _CreateWebHostBuilder(args) .ConfigureContainer(configure) .Build(); - + _tokenSource = new CancellationTokenSource(); await _StartWithHost(host, _tokenSource.Token); - } + } while (_shouldRestart); } - + /// public void Shutdown() { @@ -122,7 +143,6 @@ namespace Kyoo.Core return _dataDir; } - /// public string GetConfigFile() { @@ -132,7 +152,7 @@ namespace Kyoo.Core /// /// Parse the data directory from environment variables and command line arguments, create it if necessary. /// Set the current directory to said data folder and place a default configuration file if it does not already - /// exists. + /// exists. /// /// The command line arguments /// The current data directory. @@ -155,17 +175,20 @@ namespace Kyoo.Core .AddCommandLine(args) .Build(); - string path = parsed.GetValue("datadir") - ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Kyoo"); + string path = parsed.GetValue("datadir"); + path ??= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Kyoo"); + path = Path.GetFullPath(path); if (!Directory.Exists(path)) Directory.CreateDirectory(path); Environment.CurrentDirectory = path; if (!File.Exists(GetConfigFile())) + { File.Copy(Path.Join(AppDomain.CurrentDomain.BaseDirectory, GetConfigFile()), GetConfigFile()); - + } + return path; } @@ -217,7 +240,7 @@ namespace Kyoo.Core .UseStartup(host => PluginsStartup.FromWebHost(host, new LoggerFactory().AddSerilog())) ); } - + /// /// Register settings.json, environment variables and command lines arguments as configuration. /// @@ -287,4 +310,4 @@ namespace Kyoo.Core .Enrich.FromLogContext(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/ConfigurationManager.cs b/src/Kyoo.Core/Controllers/ConfigurationManager.cs similarity index 86% rename from Kyoo.Core/Controllers/ConfigurationManager.cs rename to src/Kyoo.Core/Controllers/ConfigurationManager.cs index 7f5432f1..760e3a95 100644 --- a/Kyoo.Core/Controllers/ConfigurationManager.cs +++ b/src/Kyoo.Core/Controllers/ConfigurationManager.cs @@ -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 . + using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -17,7 +35,7 @@ namespace Kyoo.Core.Controllers public class ConfigurationManager : IConfigurationManager { /// - /// The configuration to retrieve and edit. + /// The configuration to retrieve and edit. /// private readonly IConfiguration _configuration; @@ -44,6 +62,24 @@ namespace Kyoo.Core.Controllers _references = references.ToDictionary(x => x.Path, x => x.Type, StringComparer.OrdinalIgnoreCase); } + /// + /// Transform the configuration section in nested expando objects. + /// + /// The section to convert + /// The converted section + private static object _ToUntyped(IConfigurationSection config) + { + ExpandoObject obj = new(); + + foreach (IConfigurationSection section in config.GetChildren()) + { + obj.TryAdd(section.Key, _ToUntyped(section)); + } + + if (!obj.Any()) + return config.Value; + return obj; + } /// public void AddTyped(string path) @@ -58,7 +94,7 @@ namespace Kyoo.Core.Controllers ConfigurationReference config = ConfigurationReference.CreateUntyped(path); _references.Add(config.Path, config.Type); } - + /// public void Register(string path, Type type) { @@ -98,7 +134,7 @@ namespace Kyoo.Core.Controllers throw new ArgumentException($"The configuration at {path} is not editable or readable."); throw new ItemNotFoundException($"No configuration exists for the name: {path}"); } - + /// public object GetValue(string path) { @@ -120,11 +156,13 @@ namespace Kyoo.Core.Controllers // TODO handle lists and dictionaries. Type type = _GetType(path); if (typeof(T).IsAssignableFrom(type)) + { throw new InvalidCastException($"The type {typeof(T).Name} is not valid for " + $"a resource of type {type.Name}."); + } return (T)GetValue(path); } - + /// public async Task EditValue(string path, object value) { @@ -133,7 +171,7 @@ namespace Kyoo.Core.Controllers value = JObject.FromObject(value).ToObject(type); if (value == null) throw new ArgumentException("Invalid value format."); - + ExpandoObject config = _ToObject(_configuration); IDictionary configDic = config; configDic[path] = value; @@ -141,14 +179,15 @@ namespace Kyoo.Core.Controllers await using StreamWriter writer = new(_application.GetConfigFile()); await writer.WriteAsync(obj.ToString()); } - + /// /// Transform a configuration to a strongly typed object (the root configuration is an /// but child elements are using strong types. /// /// The configuration to transform /// A strongly typed representation of the configuration. - [SuppressMessage("ReSharper", "RedundantJumpStatement")] + [SuppressMessage("ReSharper", "RedundantJumpStatement", + Justification = "A catch block should not be empty.")] private ExpandoObject _ToObject(IConfiguration config) { ExpandoObject obj = new(); @@ -169,27 +208,8 @@ namespace Kyoo.Core.Controllers continue; } } - - return obj; - } - /// - /// Transform the configuration section in nested expando objects. - /// - /// The section to convert - /// The converted section - private static object _ToUntyped(IConfigurationSection config) - { - ExpandoObject obj = new(); - - foreach (IConfigurationSection section in config.GetChildren()) - { - obj.TryAdd(section.Key, _ToUntyped(section)); - } - - if (!obj.Any()) - return config.Value; return obj; } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/FileSystems/FileSystemComposite.cs b/src/Kyoo.Core/Controllers/FileSystems/FileSystemComposite.cs similarity index 88% rename from Kyoo.Core/Controllers/FileSystems/FileSystemComposite.cs rename to src/Kyoo.Core/Controllers/FileSystems/FileSystemComposite.cs index 4a715602..343b4277 100644 --- a/Kyoo.Core/Controllers/FileSystems/FileSystemComposite.cs +++ b/src/Kyoo.Core/Controllers/FileSystems/FileSystemComposite.cs @@ -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 . + using System; using System.Collections.Generic; using System.IO; @@ -7,8 +25,8 @@ using System.Threading.Tasks; using Autofac.Features.Metadata; using JetBrains.Annotations; using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models; +using Kyoo.Abstractions.Models.Attributes; using Kyoo.Core.Models.Options; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; @@ -31,12 +49,12 @@ namespace Kyoo.Core.Controllers /// (only if the option is set to metadata in show) /// private readonly ILibraryManager _libraryManager; - + /// /// Options to check if the metadata should be kept in the show directory or in a kyoo's directory. /// private readonly IOptionsMonitor _options; - + /// /// Create a new from a list of mapped to their /// metadata. @@ -45,7 +63,7 @@ namespace Kyoo.Core.Controllers /// The library manager used to load shows to retrieve their path. /// The options to use. public FileSystemComposite(ICollection, FileSystemMetadataAttribute>> fileSystems, - ILibraryManager libraryManager, + ILibraryManager libraryManager, IOptionsMonitor options) { _fileSystems = fileSystems; @@ -53,7 +71,6 @@ namespace Kyoo.Core.Controllers _options = options; } - /// /// Retrieve the file system that should be used for a given path. /// @@ -76,7 +93,7 @@ namespace Kyoo.Core.Controllers { usablePath = path; Meta, FileSystemMetadataAttribute> defaultFs = _fileSystems - .SingleOrDefault(x => x.Metadata.Scheme.Contains("")); + .SingleOrDefault(x => x.Metadata.Scheme.Contains(string.Empty)); if (defaultFs == null) throw new ArgumentException($"No file system registered for the default scheme."); return defaultFs.Value.Invoke(); @@ -159,7 +176,7 @@ namespace Kyoo.Core.Controllers return _GetFileSystemForPath(path, out string relativePath) .Exists(relativePath); } - + /// public async Task GetExtraDirectory(T resource) { @@ -191,11 +208,11 @@ namespace Kyoo.Core.Controllers Season season => await GetExtraDirectory(season.Show), Episode episode => await GetExtraDirectory(episode.Show), Track track => await GetExtraDirectory(track.Episode), - IResource res => Combine(_options.CurrentValue.MetadataPath, + IResource res => Combine(_options.CurrentValue.MetadataPath, typeof(T).Name.ToLowerInvariant(), res.Slug), _ => Combine(_options.CurrentValue.MetadataPath, typeof(T).Name.ToLowerInvariant()) }; return await CreateDirectory(path); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/FileSystems/HttpFileSystem.cs b/src/Kyoo.Core/Controllers/FileSystems/HttpFileSystem.cs similarity index 54% rename from Kyoo.Core/Controllers/FileSystems/HttpFileSystem.cs rename to src/Kyoo.Core/Controllers/FileSystems/HttpFileSystem.cs index 0b5618fa..662d1825 100644 --- a/Kyoo.Core/Controllers/FileSystems/HttpFileSystem.cs +++ b/src/Kyoo.Core/Controllers/FileSystems/HttpFileSystem.cs @@ -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 . + using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -14,7 +32,7 @@ namespace Kyoo.Core.Controllers /// /// A for http/https links. /// - [FileSystemMetadata(new [] {"http", "https"})] + [FileSystemMetadata(new[] { "http", "https" })] public class HttpFileSystem : IFileSystem { /// @@ -30,8 +48,7 @@ namespace Kyoo.Core.Controllers { _clientFactory = factory; } - - + /// public IActionResult FileResult(string path, bool rangeSupport = false, string type = null) { @@ -46,7 +63,7 @@ namespace Kyoo.Core.Controllers HttpClient client = _clientFactory.CreateClient(); return client.GetStreamAsync(path); } - + /// public async Task GetReader(string path, AsyncRef mime) { @@ -92,46 +109,48 @@ namespace Kyoo.Core.Controllers { throw new NotSupportedException("Extras can not be stored inside an http filesystem."); } - } - - /// - /// An to proxy an http request. - /// - // TODO remove this suppress message once the class has been implemented. - [SuppressMessage("ReSharper", "NotAccessedField.Local")] - public class HttpForwardResult : IActionResult - { - /// - /// The path of the request to forward. - /// - private readonly Uri _path; - /// - /// Should the proxied result support ranges requests? - /// - private readonly bool _rangeSupport; - /// - /// If not null, override the content type of the resulting request. - /// - private readonly string _type; /// - /// Create a new . + /// An to proxy an http request. /// - /// The path of the request to forward. - /// Should the proxied result support ranges requests? - /// If not null, override the content type of the resulting request. - public HttpForwardResult(Uri path, bool rangeSupport, string type = null) + // TODO remove this suppress message once the class has been implemented. + [SuppressMessage("ReSharper", "NotAccessedField.Local", Justification = "Not Implemented Yet.")] + public class HttpForwardResult : IActionResult { - _path = path; - _rangeSupport = rangeSupport; - _type = type; - } + /// + /// The path of the request to forward. + /// + private readonly Uri _path; - /// - public Task ExecuteResultAsync(ActionContext context) - { - // TODO implement that, example: https://github.com/twitchax/AspNetCore.Proxy/blob/14dd0f212d7abb43ca1bf8c890d5efb95db66acb/src/Core/Extensions/Http.cs#L15 - throw new NotImplementedException(); + /// + /// Should the proxied result support ranges requests? + /// + private readonly bool _rangeSupport; + + /// + /// If not null, override the content type of the resulting request. + /// + private readonly string _type; + + /// + /// Create a new . + /// + /// The path of the request to forward. + /// Should the proxied result support ranges requests? + /// If not null, override the content type of the resulting request. + public HttpForwardResult(Uri path, bool rangeSupport, string type = null) + { + _path = path; + _rangeSupport = rangeSupport; + _type = type; + } + + /// + public Task ExecuteResultAsync(ActionContext context) + { + // TODO implement that, example: https://github.com/twitchax/AspNetCore.Proxy/blob/14dd0f212d7abb43ca1bf8c890d5efb95db66acb/src/Core/Extensions/Http.cs#L15 + throw new NotImplementedException(); + } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/FileSystems/LocalFileSystem.cs b/src/Kyoo.Core/Controllers/FileSystems/LocalFileSystem.cs similarity index 82% rename from Kyoo.Core/Controllers/FileSystems/LocalFileSystem.cs rename to src/Kyoo.Core/Controllers/FileSystems/LocalFileSystem.cs index 3c75717f..67bcc97c 100644 --- a/Kyoo.Core/Controllers/FileSystems/LocalFileSystem.cs +++ b/src/Kyoo.Core/Controllers/FileSystems/LocalFileSystem.cs @@ -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 . + using System; using System.Collections.Generic; using System.IO; @@ -15,7 +33,7 @@ namespace Kyoo.Core.Controllers /// /// A for the local filesystem (using System.IO). /// - [FileSystemMetadata(new [] {"", "file"}, StripScheme = true)] + [FileSystemMetadata(new[] { "", "file" }, StripScheme = true)] public class LocalFileSystem : IFileSystem { /// @@ -51,7 +69,7 @@ namespace Kyoo.Core.Controllers return contentType; throw new NotImplementedException($"Can't get the content type of the file at: {path}"); } - + /// public IActionResult FileResult(string path, bool rangeSupport = false, string type = null) { @@ -72,7 +90,7 @@ namespace Kyoo.Core.Controllers throw new ArgumentNullException(nameof(path)); return Task.FromResult(File.OpenRead(path)); } - + /// public Task GetReader(string path, AsyncRef mime) { @@ -99,19 +117,19 @@ namespace Kyoo.Core.Controllers Directory.CreateDirectory(path); return Task.FromResult(path); } - + /// public string Combine(params string[] paths) { return Path.Combine(paths); } - + /// public Task> ListFiles(string path, SearchOption options = SearchOption.TopDirectoryOnly) { if (path == null) throw new ArgumentNullException(nameof(path)); - string[] ret = Directory.Exists(path) + string[] ret = Directory.Exists(path) ? Directory.GetFiles(path, "*", options) : Array.Empty(); return Task.FromResult>(ret); @@ -122,7 +140,7 @@ namespace Kyoo.Core.Controllers { return Task.FromResult(File.Exists(path) || Directory.Exists(path)); } - + /// public Task GetExtraDirectory(T resource) { @@ -138,4 +156,4 @@ namespace Kyoo.Core.Controllers }); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/LibraryManager.cs b/src/Kyoo.Core/Controllers/LibraryManager.cs similarity index 84% rename from Kyoo.Core/Controllers/LibraryManager.cs rename to src/Kyoo.Core/Controllers/LibraryManager.cs index e7759f0a..a6cd9f44 100644 --- a/Kyoo.Core/Controllers/LibraryManager.cs +++ b/src/Kyoo.Core/Controllers/LibraryManager.cs @@ -1,5 +1,24 @@ -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 . + +using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; @@ -16,33 +35,43 @@ namespace Kyoo.Core.Controllers /// The list of repositories /// private readonly IBaseRepository[] _repositories; - + /// public ILibraryRepository LibraryRepository { get; } + /// public ILibraryItemRepository LibraryItemRepository { get; } + /// public ICollectionRepository CollectionRepository { get; } + /// public IShowRepository ShowRepository { get; } + /// public ISeasonRepository SeasonRepository { get; } + /// public IEpisodeRepository EpisodeRepository { get; } + /// public ITrackRepository TrackRepository { get; } + /// public IPeopleRepository PeopleRepository { get; } + /// public IStudioRepository StudioRepository { get; } + /// public IGenreRepository GenreRepository { get; } + /// public IProviderRepository ProviderRepository { get; } + /// public IUserRepository UserRepository { get; } - - + /// /// Create a new instance with every repository available. /// @@ -82,7 +111,7 @@ namespace Kyoo.Core.Controllers } /// - public Task Get(string slug) + public Task Get(string slug) where T : class, IResource { return GetRepository().Get(slug); @@ -120,19 +149,19 @@ namespace Kyoo.Core.Controllers } /// - public async Task GetOrDefault(int id) + public async Task GetOrDefault(int id) where T : class, IResource { return await GetRepository().GetOrDefault(id); } - + /// - public async Task GetOrDefault(string slug) + public async Task GetOrDefault(string slug) where T : class, IResource { return await GetRepository().GetOrDefault(slug); } - + /// public async Task GetOrDefault(Expression> where) where T : class, IResource @@ -145,19 +174,19 @@ namespace Kyoo.Core.Controllers { return await SeasonRepository.GetOrDefault(showID, seasonNumber); } - + /// public async Task GetOrDefault(string showSlug, int seasonNumber) { return await SeasonRepository.GetOrDefault(showSlug, seasonNumber); } - + /// public async Task GetOrDefault(int showID, int seasonNumber, int episodeNumber) { return await EpisodeRepository.GetOrDefault(showID, seasonNumber, episodeNumber); } - + /// public async Task GetOrDefault(string showSlug, int seasonNumber, int episodeNumber) { @@ -173,9 +202,9 @@ namespace Kyoo.Core.Controllers /// A setter function to store the owner of a releated object loaded /// The type of the owner object /// The type of the related object - private static async Task SetRelation(T1 obj, - Task> loader, - Action> setter, + private static async Task _SetRelation(T1 obj, + Task> loader, + Action> setter, Action inverse) { ICollection loaded = await loader; @@ -213,6 +242,10 @@ namespace Kyoo.Core.Controllers } /// + [SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1507:CodeMustNotContainMultipleBlankLinesInARow", + Justification = "Separate the code by semantics and simplify the code read.")] + [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1107:Code should not contain multiple statements on one line", + Justification = "Assing IDs and Values in the same line.")] public Task Load(IResource obj, string memberName, bool force = false) { if (obj == null) @@ -230,61 +263,61 @@ namespace Kyoo.Core.Controllers (Library l, nameof(Library.Providers)) => ProviderRepository .GetAll(x => x.Libraries.Any(y => y.ID == obj.ID)) .Then(x => l.Providers = x), - + (Library l, nameof(Library.Shows)) => ShowRepository .GetAll(x => x.Libraries.Any(y => y.ID == obj.ID)) - .Then(x => l.Shows = x), - + .Then(x => l.Shows = x), + (Library l, nameof(Library.Collections)) => CollectionRepository .GetAll(x => x.Libraries.Any(y => y.ID == obj.ID)) - .Then(x => l.Collections = x), - - - (Collection c, nameof(Collection.ExternalIDs)) => SetRelation(c, + .Then(x => l.Collections = x), + + + (Collection c, nameof(Collection.ExternalIDs)) => _SetRelation(c, ProviderRepository.GetMetadataID(x => x.ResourceID == obj.ID), (x, y) => x.ExternalIDs = y, (x, y) => { x.ResourceID = y.ID; }), - + (Collection c, nameof(Collection.Shows)) => ShowRepository .GetAll(x => x.Collections.Any(y => y.ID == obj.ID)) - .Then(x => c.Shows = x), - + .Then(x => c.Shows = x), + (Collection c, nameof(Collection.Libraries)) => LibraryRepository .GetAll(x => x.Collections.Any(y => y.ID == obj.ID)) - .Then(x => c.Libraries = x), - - - (Show s, nameof(Show.ExternalIDs)) => SetRelation(s, + .Then(x => c.Libraries = x), + + + (Show s, nameof(Show.ExternalIDs)) => _SetRelation(s, ProviderRepository.GetMetadataID(x => x.ResourceID == obj.ID), (x, y) => x.ExternalIDs = y, (x, y) => { x.ResourceID = y.ID; }), - + (Show s, nameof(Show.Genres)) => GenreRepository .GetAll(x => x.Shows.Any(y => y.ID == obj.ID)) .Then(x => s.Genres = x), - + (Show s, nameof(Show.People)) => PeopleRepository .GetFromShow(obj.ID) .Then(x => s.People = x), - - (Show s, nameof(Show.Seasons)) => SetRelation(s, + + (Show s, nameof(Show.Seasons)) => _SetRelation(s, SeasonRepository.GetAll(x => x.Show.ID == obj.ID), (x, y) => x.Seasons = y, (x, y) => { x.Show = y; x.ShowID = y.ID; }), - - (Show s, nameof(Show.Episodes)) => SetRelation(s, + + (Show s, nameof(Show.Episodes)) => _SetRelation(s, EpisodeRepository.GetAll(x => x.Show.ID == obj.ID), (x, y) => x.Episodes = y, (x, y) => { x.Show = y; x.ShowID = y.ID; }), - + (Show s, nameof(Show.Libraries)) => LibraryRepository .GetAll(x => x.Shows.Any(y => y.ID == obj.ID)) .Then(x => s.Libraries = x), - + (Show s, nameof(Show.Collections)) => CollectionRepository .GetAll(x => x.Shows.Any(y => y.ID == obj.ID)) .Then(x => s.Collections = x), - + (Show s, nameof(Show.Studio)) => StudioRepository .GetOrDefault(x => x.Shows.Any(y => y.ID == obj.ID)) .Then(x => @@ -292,18 +325,18 @@ namespace Kyoo.Core.Controllers s.Studio = x; s.StudioID = x?.ID ?? 0; }), - - - (Season s, nameof(Season.ExternalIDs)) => SetRelation(s, + + + (Season s, nameof(Season.ExternalIDs)) => _SetRelation(s, ProviderRepository.GetMetadataID(x => x.ResourceID == obj.ID), (x, y) => x.ExternalIDs = y, (x, y) => { x.ResourceID = y.ID; }), - - (Season s, nameof(Season.Episodes)) => SetRelation(s, + + (Season s, nameof(Season.Episodes)) => _SetRelation(s, EpisodeRepository.GetAll(x => x.Season.ID == obj.ID), (x, y) => x.Episodes = y, (x, y) => { x.Season = y; x.SeasonID = y.ID; }), - + (Season s, nameof(Season.Show)) => ShowRepository .GetOrDefault(x => x.Seasons.Any(y => y.ID == obj.ID)) .Then(x => @@ -311,18 +344,18 @@ namespace Kyoo.Core.Controllers s.Show = x; s.ShowID = x?.ID ?? 0; }), - - - (Episode e, nameof(Episode.ExternalIDs)) => SetRelation(e, - ProviderRepository.GetMetadataID(x => x.ResourceID == obj.ID), + + + (Episode e, nameof(Episode.ExternalIDs)) => _SetRelation(e, + ProviderRepository.GetMetadataID(x => x.ResourceID == obj.ID), (x, y) => x.ExternalIDs = y, (x, y) => { x.ResourceID = y.ID; }), - - (Episode e, nameof(Episode.Tracks)) => SetRelation(e, + + (Episode e, nameof(Episode.Tracks)) => _SetRelation(e, TrackRepository.GetAll(x => x.Episode.ID == obj.ID), (x, y) => x.Tracks = y, (x, y) => { x.Episode = y; x.EpisodeID = y.ID; }), - + (Episode e, nameof(Episode.Show)) => ShowRepository .GetOrDefault(x => x.Episodes.Any(y => y.ID == obj.ID)) .Then(x => @@ -330,7 +363,7 @@ namespace Kyoo.Core.Controllers e.Show = x; e.ShowID = x?.ID ?? 0; }), - + (Episode e, nameof(Episode.Season)) => SeasonRepository .GetOrDefault(x => x.Episodes.Any(y => y.ID == e.ID)) .Then(x => @@ -338,8 +371,8 @@ namespace Kyoo.Core.Controllers e.Season = x; e.SeasonID = x?.ID ?? 0; }), - - + + (Track t, nameof(Track.Episode)) => EpisodeRepository .GetOrDefault(x => x.Tracks.Any(y => y.ID == obj.ID)) .Then(x => @@ -347,62 +380,62 @@ namespace Kyoo.Core.Controllers t.Episode = x; t.EpisodeID = x?.ID ?? 0; }), - - + + (Genre g, nameof(Genre.Shows)) => ShowRepository .GetAll(x => x.Genres.Any(y => y.ID == obj.ID)) .Then(x => g.Shows = x), - - + + (Studio s, nameof(Studio.Shows)) => ShowRepository .GetAll(x => x.Studio.ID == obj.ID) .Then(x => s.Shows = x), - - (Studio s, nameof(Studio.ExternalIDs)) => SetRelation(s, + + (Studio s, nameof(Studio.ExternalIDs)) => _SetRelation(s, ProviderRepository.GetMetadataID(x => x.ResourceID == obj.ID), (x, y) => x.ExternalIDs = y, (x, y) => { x.ResourceID = y.ID; }), - - - (People p, nameof(People.ExternalIDs)) => SetRelation(p, + + + (People p, nameof(People.ExternalIDs)) => _SetRelation(p, ProviderRepository.GetMetadataID(x => x.ResourceID == obj.ID), (x, y) => x.ExternalIDs = y, (x, y) => { x.ResourceID = y.ID; }), - + (People p, nameof(People.Roles)) => PeopleRepository .GetFromPeople(obj.ID) .Then(x => p.Roles = x), - - + + (Provider p, nameof(Provider.Libraries)) => LibraryRepository .GetAll(x => x.Providers.Any(y => y.ID == obj.ID)) .Then(x => p.Libraries = x), - + _ => throw new ArgumentException($"Couldn't find a way to load {memberName} of {obj.Slug}.") }; } /// - public Task> GetItemsFromLibrary(int id, - Expression> where = null, - Sort sort = default, + public Task> GetItemsFromLibrary(int id, + Expression> where = null, + Sort sort = default, Pagination limit = default) { return LibraryItemRepository.GetFromLibrary(id, where, sort, limit); } /// - public Task> GetItemsFromLibrary(string slug, - Expression> where = null, - Sort sort = default, + public Task> GetItemsFromLibrary(string slug, + Expression> where = null, + Sort sort = default, Pagination limit = default) { return LibraryItemRepository.GetFromLibrary(slug, where, sort, limit); } /// - public Task> GetPeopleFromShow(int showID, + public Task> GetPeopleFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default) @@ -411,16 +444,16 @@ namespace Kyoo.Core.Controllers } /// - public Task> GetPeopleFromShow(string showSlug, + public Task> GetPeopleFromShow(string showSlug, Expression> where = null, - Sort sort = default, + Sort sort = default, Pagination limit = default) { return PeopleRepository.GetFromShow(showSlug, where, sort, limit); } /// - public Task> GetRolesFromPeople(int id, + public Task> GetRolesFromPeople(int id, Expression> where = null, Sort sort = default, Pagination limit = default) @@ -454,7 +487,7 @@ namespace Kyoo.Core.Controllers /// public Task> GetAll(Expression> where = null, Sort sort = default, - Pagination limit = default) + Pagination limit = default) where T : class, IResource { return GetRepository().GetAll(where, sort, limit); @@ -468,19 +501,19 @@ namespace Kyoo.Core.Controllers } /// - public Task> Search(string query) + public Task> Search(string query) where T : class, IResource { return GetRepository().Search(query); } /// - public Task Create(T item) + public Task Create(T item) where T : class, IResource { return GetRepository().Create(item); } - + /// public Task CreateIfNotExists(T item) where T : class, IResource @@ -496,21 +529,21 @@ namespace Kyoo.Core.Controllers } /// - public Task Delete(T item) + public Task Delete(T item) where T : class, IResource { return GetRepository().Delete(item); } /// - public Task Delete(int id) + public Task Delete(int id) where T : class, IResource { return GetRepository().Delete(id); } /// - public Task Delete(string slug) + public Task Delete(string slug) where T : class, IResource { return GetRepository().Delete(slug); diff --git a/src/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs b/src/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs new file mode 100644 index 00000000..97b73ec2 --- /dev/null +++ b/src/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs @@ -0,0 +1,56 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.Diagnostics.CodeAnalysis; +using Kyoo.Abstractions.Controllers; +using Kyoo.Abstractions.Models.Permissions; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Logging; + +namespace Kyoo.Core.Controllers +{ + /// + /// A permission validator that always validate permissions. This effectively disable the permission system. + /// + public class PassthroughPermissionValidator : IPermissionValidator + { + [SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor", + Justification = "ILogger should include the typeparam for context.")] + public PassthroughPermissionValidator(ILogger logger) + { + logger.LogWarning("No permission validator has been enabled, all users will have all permissions"); + } + + /// + public IFilterMetadata Create(PermissionAttribute attribute) + { + return new PassthroughValidator(); + } + + /// + public IFilterMetadata Create(PartialPermissionAttribute attribute) + { + return new PassthroughValidator(); + } + + /// + /// An useless filter that does nothing. + /// + private class PassthroughValidator : IFilterMetadata { } + } +} diff --git a/Kyoo.Core/Controllers/PluginManager.cs b/src/Kyoo.Core/Controllers/PluginManager.cs similarity index 85% rename from Kyoo.Core/Controllers/PluginManager.cs rename to src/Kyoo.Core/Controllers/PluginManager.cs index 7fc2c6cf..80464d97 100644 --- a/Kyoo.Core/Controllers/PluginManager.cs +++ b/src/Kyoo.Core/Controllers/PluginManager.cs @@ -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 . + using System; using System.Collections.Generic; using System.IO; @@ -22,15 +40,17 @@ namespace Kyoo.Core.Controllers /// The service provider. It allow plugin's activation. /// private readonly IServiceProvider _provider; + /// /// The configuration to get the plugin's directory. /// private readonly IOptions _options; + /// - /// The logger used by this class. + /// The logger used by this class. /// private readonly ILogger _logger; - + /// /// The list of plugins that are currently loaded. /// @@ -74,7 +94,7 @@ namespace Kyoo.Core.Controllers /// /// The path of the dll /// The list of dlls in hte assembly - private IPlugin[] LoadPlugin(string path) + private IPlugin[] _LoadPlugin(string path) { path = Path.GetFullPath(path); try @@ -93,7 +113,7 @@ namespace Kyoo.Core.Controllers return Array.Empty(); } } - + /// public void LoadPlugins(ICollection plugins) { @@ -104,7 +124,7 @@ namespace Kyoo.Core.Controllers _logger.LogTrace("Loading new plugins..."); string[] pluginsPaths = Directory.GetFiles(pluginFolder, "*.dll", SearchOption.AllDirectories); _plugins.AddRange(plugins - .Concat(pluginsPaths.SelectMany(LoadPlugin)) + .Concat(pluginsPaths.SelectMany(_LoadPlugin)) .Where(x => x.Enabled) .GroupBy(x => x.Name) .Select(x => x.First()) @@ -172,4 +192,4 @@ namespace Kyoo.Core.Controllers } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/ProviderComposite.cs b/src/Kyoo.Core/Controllers/ProviderComposite.cs similarity index 75% rename from Kyoo.Core/Controllers/ProviderComposite.cs rename to src/Kyoo.Core/Controllers/ProviderComposite.cs index 1032b022..e44da72e 100644 --- a/Kyoo.Core/Controllers/ProviderComposite.cs +++ b/src/Kyoo.Core/Controllers/ProviderComposite.cs @@ -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 . + +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -19,16 +37,15 @@ namespace Kyoo.Core.Controllers /// private readonly ICollection _providers; - /// - /// The list of selected providers. If no provider has been selected, this is null. - /// - private ICollection _selectedProviders; - /// /// The logger used to print errors. /// private readonly ILogger _logger; + /// + /// The list of selected providers. If no provider has been selected, this is null. + /// + private ICollection _selectedProviders; /// /// Create a new with a list of available providers. @@ -40,7 +57,6 @@ namespace Kyoo.Core.Controllers _providers = providers.ToArray(); _logger = logger; } - /// public override void UseProviders(IEnumerable providers) @@ -71,9 +87,9 @@ namespace Kyoo.Core.Controllers { ret = Merger.Merge(ret, await provider.Get(ret)); } - catch (Exception ex) + catch (Exception ex) { - _logger.LogError(ex, "The provider {Provider} could not get a {Type}", + _logger.LogError(ex, "The provider {Provider} could not get a {Type}", provider.Provider.Name, typeof(T).Name); } } @@ -85,16 +101,16 @@ namespace Kyoo.Core.Controllers public override async Task> Search(string query) { List ret = new(); - + foreach (IMetadataProvider provider in _GetProviders()) { try { ret.AddRange(await provider.Search(query)); } - catch (Exception ex) + catch (Exception ex) { - _logger.LogError(ex, "The provider {Provider} could not search for {Type}", + _logger.LogError(ex, "The provider {Provider} could not search for {Type}", provider.Provider.Name, typeof(T).Name); } } diff --git a/Kyoo.Core/Controllers/RegexIdentifier.cs b/src/Kyoo.Core/Controllers/RegexIdentifier.cs similarity index 78% rename from Kyoo.Core/Controllers/RegexIdentifier.cs rename to src/Kyoo.Core/Controllers/RegexIdentifier.cs index 1032d4bb..f4931338 100644 --- a/Kyoo.Core/Controllers/RegexIdentifier.cs +++ b/src/Kyoo.Core/Controllers/RegexIdentifier.cs @@ -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 . + using System; using System.Collections.Generic; using System.IO; @@ -23,6 +41,7 @@ namespace Kyoo.Core.Controllers /// The configuration of kyoo to retrieve the identifier regex. /// private readonly IOptionsMonitor _configuration; + /// /// The library manager used to retrieve libraries paths. /// @@ -53,7 +72,7 @@ namespace Kyoo.Core.Controllers .FirstOrDefault(); return path[(libraryPath?.Length ?? 0)..]; } - + /// public async Task<(Collection, Show, Season, Episode)> Identify(string path) { @@ -77,21 +96,21 @@ namespace Kyoo.Core.Controllers Slug = Utility.ToSlug(match.Groups["Show"].Value), Title = match.Groups["Show"].Value, Path = Path.GetDirectoryName(path), - StartAir = match.Groups["StartYear"].Success - ? new DateTime(int.Parse(match.Groups["StartYear"].Value), 1, 1) + StartAir = match.Groups["StartYear"].Success + ? new DateTime(int.Parse(match.Groups["StartYear"].Value), 1, 1) : null }, season: null, episode: new Episode { - SeasonNumber = match.Groups["Season"].Success - ? int.Parse(match.Groups["Season"].Value) + SeasonNumber = match.Groups["Season"].Success + ? int.Parse(match.Groups["Season"].Value) : null, - EpisodeNumber = match.Groups["Episode"].Success - ? int.Parse(match.Groups["Episode"].Value) + EpisodeNumber = match.Groups["Episode"].Success + ? int.Parse(match.Groups["Episode"].Value) : null, - AbsoluteNumber = match.Groups["Absolute"].Success - ? int.Parse(match.Groups["Absolute"].Value) + AbsoluteNumber = match.Groups["Absolute"].Success + ? int.Parse(match.Groups["Absolute"].Value) : null, Path = path } @@ -100,7 +119,6 @@ namespace Kyoo.Core.Controllers if (ret.episode.SeasonNumber.HasValue) ret.season = new Season { SeasonNumber = ret.episode.SeasonNumber.Value }; - if (ret.episode.SeasonNumber == null && ret.episode.EpisodeNumber == null && ret.episode.AbsoluteNumber == null) { @@ -140,4 +158,4 @@ namespace Kyoo.Core.Controllers }); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs b/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs similarity index 79% rename from Kyoo.Core/Controllers/Repositories/CollectionRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs index f6d1e220..f105c6da 100644 --- a/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -19,12 +37,12 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; - + /// /// A provider repository to handle externalID creation and deletion /// private readonly IProviderRepository _providers; - + /// protected override Expression> DefaultSort => x => x.Name; @@ -58,12 +76,12 @@ namespace Kyoo.Core.Controllers await _database.SaveChangesAsync($"Trying to insert a duplicated collection (slug {obj.Slug} already exists)."); return obj; } - + /// protected override async Task Validate(Collection resource) { await base.Validate(resource); - + if (string.IsNullOrEmpty(resource.Slug)) throw new ArgumentException("The collection's slug must be set and not empty"); if (string.IsNullOrEmpty(resource.Name)) @@ -72,7 +90,7 @@ namespace Kyoo.Core.Controllers if (resource.ExternalIDs != null) { foreach (MetadataID id in resource.ExternalIDs) - { + { id.Provider = _database.LocalEntity(id.Provider.Slug) ?? await _providers.CreateIfNotExists(id.Provider); id.ProviderID = id.Provider.ID; @@ -80,12 +98,12 @@ namespace Kyoo.Core.Controllers _database.MetadataIds().AttachRange(resource.ExternalIDs); } } - + /// protected override async Task EditRelations(Collection resource, Collection changed, bool resetOld) { await Validate(changed); - + if (changed.ExternalIDs != null || resetOld) { await Database.Entry(resource).Collection(x => x.ExternalIDs).LoadAsync(); @@ -103,4 +121,4 @@ namespace Kyoo.Core.Controllers await _database.SaveChangesAsync(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs b/src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs similarity index 84% rename from Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs index f19acdb2..f2042c65 100644 --- a/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -21,19 +39,20 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; + /// /// A provider repository to handle externalID creation and deletion /// private readonly IProviderRepository _providers; + /// /// A track repository to handle creation and deletion of tracks related to the current episode. /// private readonly ITrackRepository _tracks; - + /// protected override Expression> DefaultSort => x => x.EpisodeNumber; - /// /// Create a new . /// @@ -42,27 +61,27 @@ namespace Kyoo.Core.Controllers /// A track repository public EpisodeRepository(DatabaseContext database, IProviderRepository providers, - ITrackRepository tracks) + ITrackRepository tracks) : base(database) { _database = database; _providers = providers; _tracks = tracks; } - + /// public Task GetOrDefault(int showID, int seasonNumber, int episodeNumber) { - return _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID - && x.SeasonNumber == seasonNumber + return _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID + && x.SeasonNumber == seasonNumber && x.EpisodeNumber == episodeNumber); } /// public Task GetOrDefault(string showSlug, int seasonNumber, int episodeNumber) { - return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug - && x.SeasonNumber == seasonNumber + return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug + && x.SeasonNumber == seasonNumber && x.EpisodeNumber == episodeNumber); } @@ -87,14 +106,14 @@ namespace Kyoo.Core.Controllers /// public Task GetAbsolute(int showID, int absoluteNumber) { - return _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID + return _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID && x.AbsoluteNumber == absoluteNumber); } /// public Task GetAbsolute(string showSlug, int absoluteNumber) { - return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug + return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug && x.AbsoluteNumber == absoluteNumber); } @@ -108,14 +127,14 @@ namespace Kyoo.Core.Controllers .Take(20) .ToListAsync(); } - + /// public override async Task Create(Episode obj) { await base.Create(obj); _database.Entry(obj).State = EntityState.Added; await _database.SaveChangesAsync($"Trying to insert a duplicated episode (slug {obj.Slug} already exists)."); - return await ValidateTracks(obj); + return await _ValidateTracks(obj); } /// @@ -127,7 +146,7 @@ namespace Kyoo.Core.Controllers { await _tracks.DeleteAll(x => x.EpisodeID == resource.ID); resource.Tracks = changed.Tracks; - await ValidateTracks(resource); + await _ValidateTracks(resource); } if (changed.ExternalIDs != null || resetOld) @@ -141,12 +160,12 @@ namespace Kyoo.Core.Controllers /// Set track's index and ensure that every tracks is well-formed. /// /// The resource to fix. - /// The parameter is returned. - private async Task ValidateTracks(Episode resource) + /// The parameter is returned. + private async Task _ValidateTracks(Episode resource) { if (resource.Tracks == null) return resource; - + resource.Tracks = await resource.Tracks.SelectAsync(x => { x.Episode = resource; @@ -156,7 +175,7 @@ namespace Kyoo.Core.Controllers _database.Tracks.AttachRange(resource.Tracks); return resource; } - + /// protected override async Task Validate(Episode resource) { @@ -164,8 +183,10 @@ namespace Kyoo.Core.Controllers if (resource.ShowID <= 0) { if (resource.Show == null) + { throw new ArgumentException($"Can't store an episode not related " + $"to any show (showID: {resource.ShowID})."); + } resource.ShowID = resource.Show.ID; } @@ -180,17 +201,17 @@ namespace Kyoo.Core.Controllers _database.MetadataIds().AttachRange(resource.ExternalIDs); } } - + /// public override async Task Delete(Episode obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); - + _database.Entry(obj).State = EntityState.Deleted; await obj.Tracks.ForEachAsync(x => _tracks.Delete(x)); obj.ExternalIDs.ForEach(x => _database.Entry(x).State = EntityState.Deleted); await _database.SaveChangesAsync(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/GenreRepository.cs b/src/Kyoo.Core/Controllers/Repositories/GenreRepository.cs similarity index 68% rename from Kyoo.Core/Controllers/Repositories/GenreRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/GenreRepository.cs index f72b13e7..eb12a4c4 100644 --- a/Kyoo.Core/Controllers/Repositories/GenreRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/GenreRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -19,11 +37,10 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; - + /// protected override Expression> DefaultSort => x => x.Slug; - - + /// /// Create a new . /// @@ -63,4 +80,4 @@ namespace Kyoo.Core.Controllers await _database.SaveChangesAsync(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs b/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs similarity index 72% rename from Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs index ba075c09..833a06cc 100644 --- a/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -20,6 +38,7 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; + /// /// A lazy loaded library repository to validate queries (check if a library does exist) /// @@ -28,13 +47,12 @@ namespace Kyoo.Core.Controllers /// protected override Expression> DefaultSort => x => x.Title; - /// /// Create a new . /// /// The database instance /// A lazy loaded library repository - public LibraryItemRepository(DatabaseContext database, + public LibraryItemRepository(DatabaseContext database, Lazy libraries) : base(database) { @@ -42,13 +60,12 @@ namespace Kyoo.Core.Controllers _libraries = libraries; } - /// public override Task GetOrDefault(int id) { return _database.LibraryItems.FirstOrDefaultAsync(x => x.ID == id); } - + /// public override Task GetOrDefault(string slug) { @@ -83,36 +100,36 @@ namespace Kyoo.Core.Controllers } /// - public override Task Create(LibraryItem obj) + public override Task Create(LibraryItem obj) => throw new InvalidOperationException(); - + /// - public override Task CreateIfNotExists(LibraryItem obj) + public override Task CreateIfNotExists(LibraryItem obj) => throw new InvalidOperationException(); - + /// - public override Task Edit(LibraryItem obj, bool resetOld) + public override Task Edit(LibraryItem obj, bool resetOld) => throw new InvalidOperationException(); - + /// - public override Task Delete(int id) + public override Task Delete(int id) => throw new InvalidOperationException(); - + /// - public override Task Delete(string slug) + public override Task Delete(string slug) => throw new InvalidOperationException(); - + /// - public override Task Delete(LibraryItem obj) + public override Task Delete(LibraryItem obj) => throw new InvalidOperationException(); /// - /// Get a basic queryable for a library with the right mapping from shows & collections. + /// Get a basic queryable for a library with the right mapping from shows and collections. /// Shows contained in a collection are excluded. /// /// Only items that are part of a library that match this predicate will be returned. /// A queryable containing items that are part of a library matching the selector. - private IQueryable LibraryRelatedQuery(Expression> selector) + private IQueryable _LibraryRelatedQuery(Expression> selector) => _database.Libraries .Where(selector) .SelectMany(x => x.Shows) @@ -125,11 +142,11 @@ namespace Kyoo.Core.Controllers /// public async Task> GetFromLibrary(int id, - Expression> where = null, - Sort sort = default, + Expression> where = null, + Sort sort = default, Pagination limit = default) { - ICollection items = await ApplyFilters(LibraryRelatedQuery(x => x.ID == id), + ICollection items = await ApplyFilters(_LibraryRelatedQuery(x => x.ID == id), where, sort, limit); @@ -137,14 +154,14 @@ namespace Kyoo.Core.Controllers throw new ItemNotFoundException(); return items; } - + /// public async Task> GetFromLibrary(string slug, - Expression> where = null, - Sort sort = default, + Expression> where = null, + Sort sort = default, Pagination limit = default) { - ICollection items = await ApplyFilters(LibraryRelatedQuery(x => x.Slug == slug), + ICollection items = await ApplyFilters(_LibraryRelatedQuery(x => x.Slug == slug), where, sort, limit); @@ -153,4 +170,4 @@ namespace Kyoo.Core.Controllers return items; } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/LibraryRepository.cs b/src/Kyoo.Core/Controllers/Repositories/LibraryRepository.cs similarity index 79% rename from Kyoo.Core/Controllers/Repositories/LibraryRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/LibraryRepository.cs index 1e835114..494273ff 100644 --- a/Kyoo.Core/Controllers/Repositories/LibraryRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/LibraryRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -20,15 +38,15 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; + /// /// A provider repository to handle externalID creation and deletion /// private readonly IProviderRepository _providers; - + /// protected override Expression> DefaultSort => x => x.ID; - /// /// Create a new instance. /// @@ -41,7 +59,6 @@ namespace Kyoo.Core.Controllers _providers = providers; } - /// public override async Task> Search(string query) { @@ -65,14 +82,14 @@ namespace Kyoo.Core.Controllers protected override async Task Validate(Library resource) { await base.Validate(resource); - + if (string.IsNullOrEmpty(resource.Slug)) throw new ArgumentException("The library's slug must be set and not empty"); if (string.IsNullOrEmpty(resource.Name)) throw new ArgumentException("The library's name must be set and not empty"); if (resource.Paths == null || !resource.Paths.Any()) throw new ArgumentException("The library should have a least one path."); - + if (resource.Providers != null) { resource.Providers = await resource.Providers @@ -99,9 +116,9 @@ namespace Kyoo.Core.Controllers { if (obj == null) throw new ArgumentNullException(nameof(obj)); - + _database.Entry(obj).State = EntityState.Deleted; await _database.SaveChangesAsync(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/LocalRepository.cs b/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs similarity index 83% rename from Kyoo.Core/Controllers/Repositories/LocalRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs index 55c6e259..efc017d7 100644 --- a/Kyoo.Core/Controllers/Repositories/LocalRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -8,8 +26,8 @@ using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Exceptions; -using Kyoo.Utils; using Kyoo.Core.Api; +using Kyoo.Utils; using Microsoft.EntityFrameworkCore; namespace Kyoo.Core.Controllers @@ -24,18 +42,17 @@ namespace Kyoo.Core.Controllers /// /// The Entity Framework's Database handle. /// - protected readonly DbContext Database; + protected DbContext Database { get; } /// /// The default sort order that will be used for this resource's type. /// protected abstract Expression> DefaultSort { get; } - - + /// /// Create a new base with the given database handle. /// - /// A database connection to load resources of type + /// A database connection to load resources of type protected LocalRepository(DbContext database) { Database = database; @@ -57,7 +74,7 @@ namespace Kyoo.Core.Controllers throw new ItemNotFoundException($"No {typeof(T).Name} found with the id {id}"); return ret; } - + /// public virtual async Task Get(int id) { @@ -84,19 +101,19 @@ namespace Kyoo.Core.Controllers throw new ItemNotFoundException($"No {typeof(T).Name} found with the given predicate."); return ret; } - + /// public virtual Task GetOrDefault(int id) { return Database.Set().FirstOrDefaultAsync(x => x.ID == id); } - + /// public virtual Task GetOrDefault(string slug) { return Database.Set().FirstOrDefaultAsync(x => x.Slug == slug); } - + /// public virtual Task GetOrDefault(Expression> where) { @@ -105,7 +122,7 @@ namespace Kyoo.Core.Controllers /// public abstract Task> Search(string query); - + /// public virtual Task> GetAll(Expression> where = null, Sort sort = default, @@ -113,49 +130,50 @@ namespace Kyoo.Core.Controllers { return ApplyFilters(Database.Set(), where, sort, limit); } - + /// - /// Apply filters to a query to ease sort, pagination & where queries for resources of this repository + /// Apply filters to a query to ease sort, pagination and where queries for resources of this repository /// /// The base query to filter. /// An expression to filter based on arbitrary conditions - /// The sort settings (sort order & sort by) + /// The sort settings (sort order and sort by) /// Pagination information (where to start and how many to get) /// The filtered query protected Task> ApplyFilters(IQueryable query, Expression> where = null, - Sort sort = default, + Sort sort = default, Pagination limit = default) { return ApplyFilters(query, GetOrDefault, DefaultSort, where, sort, limit); } - + /// - /// Apply filters to a query to ease sort, pagination & where queries for any resources types. - /// For resources of type , see + /// Apply filters to a query to ease sort, pagination and where queries for any resources types. + /// For resources of type , see /// + /// The base query to filter. /// A function to asynchronously get a resource from the database using it's ID. /// The default sort order of this resource's type. - /// The base query to filter. /// An expression to filter based on arbitrary conditions - /// The sort settings (sort order & sort by) + /// The sort settings (sort order and sort by) /// Pagination information (where to start and how many to get) + /// The type of items to query. /// The filtered query protected async Task> ApplyFilters(IQueryable query, Func> get, Expression> defaultSort, Expression> where = null, - Sort sort = default, + Sort sort = default, Pagination limit = default) { if (where != null) query = query.Where(where); - + Expression> sortKey = sort.Key ?? defaultSort; Expression sortExpression = sortKey.Body.NodeType == ExpressionType.Convert ? ((UnaryExpression)sortKey.Body).Operand : sortKey.Body; - + if (typeof(Enum).IsAssignableFrom(sortExpression.Type)) throw new ArgumentException("Invalid sort key."); @@ -205,7 +223,7 @@ namespace Kyoo.Core.Controllers T old = await GetOrDefault(obj.Slug); if (old != null) return old; - + return await Create(obj); } catch (DuplicatedItemException) @@ -225,7 +243,7 @@ namespace Kyoo.Core.Controllers try { T old = await GetWithTracking(edited.ID); - + if (resetOld) old = Merger.Nullify(old); Merger.Complete(old, edited, x => x.GetCustomAttribute() == null); @@ -239,7 +257,7 @@ namespace Kyoo.Core.Controllers Database.ChangeTracker.Clear(); } } - + /// /// An overridable method to edit relation of a resource. /// @@ -247,17 +265,18 @@ namespace Kyoo.Core.Controllers /// The non edited resource /// /// - /// The new version of . - /// This item will be saved on the database and replace + /// The new version of . + /// This item will be saved on the database and replace /// /// /// A boolean to indicate if all values of resource should be discarded or not. /// + /// A representing the asynchronous operation. protected virtual Task EditRelations(T resource, T changed, bool resetOld) { return Validate(resource); } - + /// /// A method called just before saving a new resource to the database. /// It is also called on the default implementation of @@ -266,6 +285,7 @@ namespace Kyoo.Core.Controllers /// /// You can throw this if the resource is illegal and should not be saved. /// + /// A representing the asynchronous operation. protected virtual Task Validate(T resource) { if (typeof(T).GetProperty(nameof(resource.Slug))!.GetCustomAttribute() != null) @@ -278,7 +298,7 @@ namespace Kyoo.Core.Controllers { MethodInfo setter = typeof(T).GetProperty(nameof(resource.Slug))!.GetSetMethod(); if (setter != null) - setter.Invoke(resource, new object[] {resource.Slug + '!'}); + setter.Invoke(resource, new object[] { resource.Slug + '!' }); else throw new ArgumentException("Resources slug can't be number only."); } @@ -306,7 +326,7 @@ namespace Kyoo.Core.Controllers /// public abstract Task Delete(T obj); - + /// public async Task DeleteAll(Expression> where) { @@ -314,4 +334,4 @@ namespace Kyoo.Core.Controllers await Delete(resource); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/PeopleRepository.cs b/src/Kyoo.Core/Controllers/Repositories/PeopleRepository.cs similarity index 84% rename from Kyoo.Core/Controllers/Repositories/PeopleRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/PeopleRepository.cs index 9b8eb38f..09809426 100644 --- a/Kyoo.Core/Controllers/Repositories/PeopleRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/PeopleRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -21,15 +39,17 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; + /// /// A provider repository to handle externalID creation and deletion /// private readonly IProviderRepository _providers; + /// /// A lazy loaded show repository to validate requests from shows. /// private readonly Lazy _shows; - + /// protected override Expression> DefaultSort => x => x.Name; @@ -41,14 +61,13 @@ namespace Kyoo.Core.Controllers /// A lazy loaded show repository public PeopleRepository(DatabaseContext database, IProviderRepository providers, - Lazy shows) + Lazy shows) : base(database) { _database = database; _providers = providers; _shows = shows; } - /// public override async Task> Search(string query) @@ -89,7 +108,7 @@ namespace Kyoo.Core.Controllers { foreach (PeopleRole role in resource.Roles) { - role.Show = _database.LocalEntity(role.Show.Slug) + role.Show = _database.LocalEntity(role.Show.Slug) ?? await _shows.Value.CreateIfNotExists(role.Show); role.ShowID = role.Show.ID; _database.Entry(role).State = EntityState.Added; @@ -101,7 +120,7 @@ namespace Kyoo.Core.Controllers protected override async Task EditRelations(People resource, People changed, bool resetOld) { await Validate(changed); - + if (changed.Roles != null || resetOld) { await Database.Entry(resource).Collection(x => x.Roles).LoadAsync(); @@ -120,7 +139,7 @@ namespace Kyoo.Core.Controllers { if (obj == null) throw new ArgumentNullException(nameof(obj)); - + _database.Entry(obj).State = EntityState.Deleted; obj.ExternalIDs.ForEach(x => _database.Entry(x).State = EntityState.Deleted); obj.Roles.ForEach(x => _database.Entry(x).State = EntityState.Deleted); @@ -128,9 +147,9 @@ namespace Kyoo.Core.Controllers } /// - public async Task> GetFromShow(int showID, - Expression> where = null, - Sort sort = default, + public async Task> GetFromShow(int showID, + Expression> where = null, + Sort sort = default, Pagination limit = default) { ICollection people = await ApplyFilters(_database.PeopleRoles @@ -151,7 +170,7 @@ namespace Kyoo.Core.Controllers /// public async Task> GetFromShow(string showSlug, Expression> where = null, - Sort sort = default, + Sort sort = default, Pagination limit = default) { ICollection people = await ApplyFilters(_database.PeopleRoles @@ -169,11 +188,11 @@ namespace Kyoo.Core.Controllers role.ForPeople = true; return people; } - + /// public async Task> GetFromPeople(int id, Expression> where = null, - Sort sort = default, + Sort sort = default, Pagination limit = default) { ICollection roles = await ApplyFilters(_database.PeopleRoles @@ -188,11 +207,11 @@ namespace Kyoo.Core.Controllers throw new ItemNotFoundException(); return roles; } - + /// public async Task> GetFromPeople(string slug, Expression> where = null, - Sort sort = default, + Sort sort = default, Pagination limit = default) { ICollection roles = await ApplyFilters(_database.PeopleRoles @@ -208,4 +227,4 @@ namespace Kyoo.Core.Controllers return roles; } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/ProviderRepository.cs b/src/Kyoo.Core/Controllers/Repositories/ProviderRepository.cs similarity index 73% rename from Kyoo.Core/Controllers/Repositories/ProviderRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/ProviderRepository.cs index 321b11d3..f8787658 100644 --- a/Kyoo.Core/Controllers/Repositories/ProviderRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/ProviderRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -20,7 +38,6 @@ namespace Kyoo.Core.Controllers /// private readonly DatabaseContext _database; - /// /// Create a new . /// @@ -79,4 +96,4 @@ namespace Kyoo.Core.Controllers limit); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs b/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs similarity index 80% rename from Kyoo.Core/Controllers/Repositories/SeasonRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs index 1a22fe15..3a85e98a 100644 --- a/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -20,6 +38,7 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; + /// /// A provider repository to handle externalID creation and deletion /// @@ -28,7 +47,6 @@ namespace Kyoo.Core.Controllers /// protected override Expression> DefaultSort => x => x.SeasonNumber; - /// /// Create a new . /// @@ -50,7 +68,7 @@ namespace Kyoo.Core.Controllers throw new ItemNotFoundException($"No season {seasonNumber} found for the show {showID}"); return ret; } - + /// public async Task Get(string showSlug, int seasonNumber) { @@ -63,14 +81,14 @@ namespace Kyoo.Core.Controllers /// public Task GetOrDefault(int showID, int seasonNumber) { - return _database.Seasons.FirstOrDefaultAsync(x => x.ShowID == showID + return _database.Seasons.FirstOrDefaultAsync(x => x.ShowID == showID && x.SeasonNumber == seasonNumber); } /// public Task GetOrDefault(string showSlug, int seasonNumber) { - return _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug + return _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug && x.SeasonNumber == seasonNumber); } @@ -100,8 +118,10 @@ namespace Kyoo.Core.Controllers if (resource.ShowID <= 0) { if (resource.Show == null) - throw new ArgumentException( - $"Can't store a season not related to any show (showID: {resource.ShowID})."); + { + throw new ArgumentException($"Can't store a season not related to any show " + + $"(showID: {resource.ShowID})."); + } resource.ShowID = resource.Show.ID; } @@ -121,14 +141,14 @@ namespace Kyoo.Core.Controllers protected override async Task EditRelations(Season resource, Season changed, bool resetOld) { await Validate(changed); - + if (changed.ExternalIDs != null || resetOld) { await Database.Entry(resource).Collection(x => x.ExternalIDs).LoadAsync(); resource.ExternalIDs = changed.ExternalIDs; } } - + /// public override async Task Delete(Season obj) { @@ -139,4 +159,4 @@ namespace Kyoo.Core.Controllers await _database.SaveChangesAsync(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/ShowRepository.cs b/src/Kyoo.Core/Controllers/Repositories/ShowRepository.cs similarity index 86% rename from Kyoo.Core/Controllers/Repositories/ShowRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/ShowRepository.cs index dca498c7..fd86446e 100644 --- a/Kyoo.Core/Controllers/Repositories/ShowRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/ShowRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -5,8 +23,8 @@ using System.Linq.Expressions; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; -using Kyoo.Utils; using Kyoo.Database; +using Kyoo.Utils; using Microsoft.EntityFrameworkCore; namespace Kyoo.Core.Controllers @@ -20,18 +38,22 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; + /// /// A studio repository to handle creation/validation of related studios. /// private readonly IStudioRepository _studios; + /// /// A people repository to handle creation/validation of related people. /// private readonly IPeopleRepository _people; + /// /// A genres repository to handle creation/validation of related genres. /// private readonly IGenreRepository _genres; + /// /// A provider repository to handle externalID creation and deletion /// @@ -50,8 +72,8 @@ namespace Kyoo.Core.Controllers /// A provider repository public ShowRepository(DatabaseContext database, IStudioRepository studios, - IPeopleRepository people, - IGenreRepository genres, + IPeopleRepository people, + IGenreRepository genres, IProviderRepository providers) : base(database) { @@ -61,7 +83,6 @@ namespace Kyoo.Core.Controllers _genres = genres; _providers = providers; } - /// public override async Task> Search(string query) @@ -82,7 +103,7 @@ namespace Kyoo.Core.Controllers await _database.SaveChangesAsync($"Trying to insert a duplicated show (slug {obj.Slug} already exists)."); return obj; } - + /// protected override async Task Validate(Show resource) { @@ -128,7 +149,7 @@ namespace Kyoo.Core.Controllers protected override async Task EditRelations(Show resource, Show changed, bool resetOld) { await Validate(changed); - + if (changed.Aliases != null || resetOld) resource.Aliases = changed.Aliases; @@ -137,7 +158,7 @@ namespace Kyoo.Core.Controllers await Database.Entry(resource).Reference(x => x.Studio).LoadAsync(); resource.Studio = changed.Studio; } - + if (changed.Genres != null || resetOld) { await Database.Entry(resource).Collection(x => x.Genres).LoadAsync(); @@ -177,7 +198,7 @@ namespace Kyoo.Core.Controllers await _database.SaveIfNoDuplicates(); } } - + /// public Task GetSlug(int showID) { @@ -185,7 +206,7 @@ namespace Kyoo.Core.Controllers .Select(x => x.Slug) .FirstOrDefaultAsync(); } - + /// public override async Task Delete(Show obj) { @@ -193,4 +214,4 @@ namespace Kyoo.Core.Controllers await _database.SaveChangesAsync(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/StudioRepository.cs b/src/Kyoo.Core/Controllers/Repositories/StudioRepository.cs similarity index 78% rename from Kyoo.Core/Controllers/Repositories/StudioRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/StudioRepository.cs index 185e4420..77da65d5 100644 --- a/Kyoo.Core/Controllers/Repositories/StudioRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/StudioRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -19,16 +37,15 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; - + /// /// A provider repository to handle externalID creation and deletion /// private readonly IProviderRepository _providers; - + /// protected override Expression> DefaultSort => x => x.Name; - /// /// Create a new . /// @@ -40,7 +57,7 @@ namespace Kyoo.Core.Controllers _database = database; _providers = providers; } - + /// public override async Task> Search(string query) { @@ -59,7 +76,7 @@ namespace Kyoo.Core.Controllers await _database.SaveChangesAsync($"Trying to insert a duplicated studio (slug {obj.Slug} already exists)."); return obj; } - + /// protected override async Task Validate(Studio resource) { @@ -75,7 +92,7 @@ namespace Kyoo.Core.Controllers _database.MetadataIds().AttachRange(resource.ExternalIDs); } } - + /// protected override async Task EditRelations(Studio resource, Studio changed, bool resetOld) { @@ -93,9 +110,9 @@ namespace Kyoo.Core.Controllers { if (obj == null) throw new ArgumentNullException(nameof(obj)); - + _database.Entry(obj).State = EntityState.Deleted; await _database.SaveChangesAsync(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/Repositories/TrackRepository.cs b/src/Kyoo.Core/Controllers/Repositories/TrackRepository.cs similarity index 69% rename from Kyoo.Core/Controllers/Repositories/TrackRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/TrackRepository.cs index c6b7889c..9930b17f 100644 --- a/Kyoo.Core/Controllers/Repositories/TrackRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/TrackRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq.Expressions; @@ -18,16 +36,15 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; - + /// protected override Expression> DefaultSort => x => x.TrackIndex; - /// /// Create a new . /// /// The database handle - public TrackRepository(DatabaseContext database) + public TrackRepository(DatabaseContext database) : base(database) { _database = database; @@ -47,8 +64,10 @@ namespace Kyoo.Core.Controllers { resource.EpisodeID = resource.Episode?.ID ?? 0; if (resource.EpisodeID <= 0) + { throw new ArgumentException("Can't store a track not related to any episode " + $"(episodeID: {resource.EpisodeID})."); + } } } @@ -69,7 +88,7 @@ namespace Kyoo.Core.Controllers { if (obj == null) throw new ArgumentNullException(nameof(obj)); - + _database.Entry(obj).State = EntityState.Deleted; await _database.SaveChangesAsync(); } diff --git a/Kyoo.Core/Controllers/Repositories/UserRepository.cs b/src/Kyoo.Core/Controllers/Repositories/UserRepository.cs similarity index 68% rename from Kyoo.Core/Controllers/Repositories/UserRepository.cs rename to src/Kyoo.Core/Controllers/Repositories/UserRepository.cs index 1b267ab6..d9fba4df 100644 --- a/Kyoo.Core/Controllers/Repositories/UserRepository.cs +++ b/src/Kyoo.Core/Controllers/Repositories/UserRepository.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -19,11 +37,10 @@ namespace Kyoo.Core.Controllers /// The database handle /// private readonly DatabaseContext _database; - + /// protected override Expression> DefaultSort => x => x.Username; - - + /// /// Create a new /// @@ -33,7 +50,7 @@ namespace Kyoo.Core.Controllers { _database = database; } - + /// public override async Task> Search(string query) { @@ -43,7 +60,7 @@ namespace Kyoo.Core.Controllers .Take(20) .ToListAsync(); } - + /// public override async Task Create(User obj) { @@ -58,9 +75,9 @@ namespace Kyoo.Core.Controllers { if (obj == null) throw new ArgumentNullException(nameof(obj)); - + _database.Entry(obj).State = EntityState.Deleted; await _database.SaveChangesAsync(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/TaskManager.cs b/src/Kyoo.Core/Controllers/TaskManager.cs similarity index 86% rename from Kyoo.Core/Controllers/TaskManager.cs rename to src/Kyoo.Core/Controllers/TaskManager.cs index af1d24e6..334576e4 100644 --- a/Kyoo.Core/Controllers/TaskManager.cs +++ b/src/Kyoo.Core/Controllers/TaskManager.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -32,7 +50,7 @@ namespace Kyoo.Core.Controllers /// The metadata for this task (the slug, and other useful information). /// public TaskMetadataAttribute Metadata { get; set; } - + /// /// The function used to create the task object. /// @@ -53,27 +71,28 @@ namespace Kyoo.Core.Controllers /// The task currently queued. /// public ManagedTask Task { get; init; } - + /// - /// The progress reporter that this task should use. + /// The progress reporter that this task should use. /// public IProgress ProgressReporter { get; init; } - + /// /// The arguments to give to run the task with. /// public Dictionary Arguments { get; init; } - + /// /// A token informing the task that it should be cancelled or not. /// public CancellationToken? CancellationToken { get; init; } } - + /// /// The configuration instance used to get schedule information /// private readonly IOptionsMonitor _options; + /// /// The logger instance. /// @@ -83,19 +102,21 @@ namespace Kyoo.Core.Controllers /// The list of tasks and their next scheduled run. /// private readonly List _tasks; + /// /// The queue of tasks that should be run as soon as possible. /// private readonly Queue _queuedTasks = new(); - /// - /// The currently running task. - /// - private (TaskMetadataAttribute, ITask)? _runningTask; + /// /// The cancellation token used to cancel the running task when the runner should shutdown. /// private readonly CancellationTokenSource _taskToken = new(); + /// + /// The currently running task. + /// + private (TaskMetadataAttribute, ITask)? _runningTask; /// /// Create a new . @@ -113,27 +134,27 @@ namespace Kyoo.Core.Controllers { Factory = x.Value, Metadata = x.Metadata, - ScheduledDate = GetNextTaskDate(x.Metadata.Slug) + ScheduledDate = _GetNextTaskDate(x.Metadata.Slug) }).ToList(); - + if (_tasks.Any()) _logger.LogTrace("Task manager initiated with: {Tasks}", _tasks.Select(x => x.Metadata.Name)); else _logger.LogInformation("Task manager initiated without any tasks"); } - - + /// /// Triggered when the application host is ready to start the service. /// /// Start the runner in another thread. /// Indicates that the start process has been aborted. + /// A representing the asynchronous operation. public override Task StartAsync(CancellationToken cancellationToken) { Task.Run(() => base.StartAsync(cancellationToken), CancellationToken.None); return Task.CompletedTask; } - + /// public override Task StopAsync(CancellationToken cancellationToken) { @@ -145,10 +166,11 @@ namespace Kyoo.Core.Controllers /// The runner that will host tasks and run queued tasks. /// /// A token to stop the runner + /// A representing the asynchronous operation. protected override async Task ExecuteAsync(CancellationToken cancellationToken) { _EnqueueStartupTasks(); - + while (!cancellationToken.IsCancellationRequested) { if (_queuedTasks.Any()) @@ -160,19 +182,19 @@ namespace Kyoo.Core.Controllers } catch (TaskFailedException ex) { - _logger.LogWarning("The task \"{Task}\" failed: {Message}", + _logger.LogWarning("The task \"{Task}\" failed: {Message}", task.Task.Metadata.Name, ex.Message); } catch (Exception e) { - _logger.LogError(e, "An unhandled exception occured while running the task {Task}", + _logger.LogError(e, "An unhandled exception occured while running the task {Task}", task.Task.Metadata.Name); } } else { await Task.Delay(1000, cancellationToken); - QueueScheduledTasks(); + _QueueScheduledTasks(); } } } @@ -188,7 +210,7 @@ namespace Kyoo.Core.Controllers /// If the number of arguments is invalid, if an argument can't be converted or if the task finds the argument /// invalid. /// - private async Task _RunTask(ManagedTask task, + private async Task _RunTask(ManagedTask task, [NotNull] IProgress progress, Dictionary arguments, CancellationToken? cancellationToken = null) @@ -215,19 +237,21 @@ namespace Kyoo.Core.Controllers .FirstOrDefault(y => string.Equals(y.Key, x.Name, StringComparison.OrdinalIgnoreCase)) .Value; if (value == null && x.IsRequired) + { throw new ArgumentException($"The argument {x.Name} is required to run " + $"{task.Metadata.Name} but it was not specified."); + } return x.CreateValue(value ?? x.DefaultValue); })); - _logger.LogInformation("Task starting: {Task} ({Parameters})", + _logger.LogInformation("Task starting: {Task} ({Parameters})", task.Metadata.Name, args.ToDictionary(x => x.Name, x => x.As())); - + CancellationToken token = cancellationToken != null ? CancellationTokenSource.CreateLinkedTokenSource(_taskToken.Token, cancellationToken.Value).Token : _taskToken.Token; await taskObj.Value.Run(args, progress, token); - + _logger.LogInformation("Task finished: {Task}", task.Metadata.Name); _runningTask = null; } @@ -236,7 +260,7 @@ namespace Kyoo.Core.Controllers /// /// Start tasks that are scheduled for start. /// - private void QueueScheduledTasks() + private void _QueueScheduledTasks() { IEnumerable tasksToQueue = _tasks.Where(x => x.ScheduledDate <= DateTime.Now) .Select(x => x.Metadata.Slug); @@ -261,13 +285,13 @@ namespace Kyoo.Core.Controllers } /// - public void StartTask(string taskSlug, + public void StartTask(string taskSlug, IProgress progress, Dictionary arguments = null, CancellationToken? cancellationToken = null) { arguments ??= new Dictionary(); - + int index = _tasks.FindIndex(x => x.Metadata.Slug == taskSlug); if (index == -1) throw new ItemNotFoundException($"No task found with the slug {taskSlug}"); @@ -276,13 +300,13 @@ namespace Kyoo.Core.Controllers Task = _tasks[index], ProgressReporter = progress, Arguments = arguments, - CancellationToken = cancellationToken + CancellationToken = cancellationToken }); - _tasks[index].ScheduledDate = GetNextTaskDate(taskSlug); + _tasks[index].ScheduledDate = _GetNextTaskDate(taskSlug); } /// - public void StartTask(IProgress progress, + public void StartTask(IProgress progress, Dictionary arguments = null, CancellationToken? cancellationToken = null) where T : ITask @@ -298,18 +322,18 @@ namespace Kyoo.Core.Controllers /// /// The slug of the task /// The next date. - private DateTime GetNextTaskDate(string taskSlug) + private DateTime _GetNextTaskDate(string taskSlug) { if (_options.CurrentValue.Scheduled.TryGetValue(taskSlug, out TimeSpan delay)) return DateTime.Now + delay; return DateTime.MaxValue; } - + /// public ICollection<(TaskMetadataAttribute, ITask)> GetRunningTasks() { - return _runningTask == null - ? ArraySegment<(TaskMetadataAttribute, ITask)>.Empty + return _runningTask == null + ? ArraySegment<(TaskMetadataAttribute, ITask)>.Empty : new[] { _runningTask.Value }; } @@ -319,4 +343,4 @@ namespace Kyoo.Core.Controllers return _tasks.Select(x => x.Metadata).ToArray(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Controllers/ThumbnailsManager.cs b/src/Kyoo.Core/Controllers/ThumbnailsManager.cs similarity index 83% rename from Kyoo.Core/Controllers/ThumbnailsManager.cs rename to src/Kyoo.Core/Controllers/ThumbnailsManager.cs index d82db69f..7ed9e829 100644 --- a/Kyoo.Core/Controllers/ThumbnailsManager.cs +++ b/src/Kyoo.Core/Controllers/ThumbnailsManager.cs @@ -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 . + +using System; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -18,6 +36,7 @@ namespace Kyoo.Core.Controllers /// The file manager used to download the image if the file is distant /// private readonly IFileSystem _files; + /// /// A logger to report errors. /// @@ -28,7 +47,7 @@ namespace Kyoo.Core.Controllers /// /// The file manager to use. /// A logger to report errors - public ThumbnailsManager(IFileSystem files, + public ThumbnailsManager(IFileSystem files, ILogger logger) { _files = files; @@ -66,7 +85,7 @@ namespace Kyoo.Core.Controllers } /// - public async Task DownloadImages(T item, bool alwaysDownload = false) + public async Task DownloadImages(T item, bool alwaysDownload = false) where T : IThumbnails { if (item == null) @@ -82,9 +101,9 @@ namespace Kyoo.Core.Controllers { string localPath = await _GetPrivateImagePath(item, id); if (alwaysDownload || !await _files.Exists(localPath)) - ret |= await _DownloadImage(image, localPath, $"The image n°{id} of {name}"); + ret |= await _DownloadImage(image, localPath, $"The image n {id} of {name}"); } - + return ret; } @@ -99,7 +118,7 @@ namespace Kyoo.Core.Controllers { if (item == null) throw new ArgumentNullException(nameof(item)); - + string directory = await _files.GetExtraDirectory(item); string imageName = imageID switch { @@ -109,7 +128,7 @@ namespace Kyoo.Core.Controllers Images.Trailer => "trailer", _ => $"{imageID}" }; - + switch (item) { case Season season: @@ -123,7 +142,7 @@ namespace Kyoo.Core.Controllers return _files.Combine(directory, imageName); } - + /// public async Task GetImagePath(T item, int imageID) where T : IThumbnails diff --git a/Kyoo.Core/Controllers/Transcoder.cs b/src/Kyoo.Core/Controllers/Transcoder.cs similarity index 81% rename from Kyoo.Core/Controllers/Transcoder.cs rename to src/Kyoo.Core/Controllers/Transcoder.cs index 1f2f8d08..a29966ba 100644 --- a/Kyoo.Core/Controllers/Transcoder.cs +++ b/src/Kyoo.Core/Controllers/Transcoder.cs @@ -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 . + using System; using System.IO; using System.Runtime.InteropServices; @@ -6,15 +24,12 @@ using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Core.Models.Options; using Microsoft.Extensions.Options; -using Stream = Kyoo.Core.Models.Watch.Stream; // We use threads so tasks are not always awaited. #pragma warning disable 4014 namespace Kyoo.Core.Controllers { - public class BadTranscoderException : Exception {} - public class Transcoder : ITranscoder { private static class TranscoderAPI @@ -26,7 +41,7 @@ namespace Kyoo.Core.Controllers public static int Init() => init(); - [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl, + [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] private static extern int transmux(string path, string outpath, out float playableDuration); @@ -37,9 +52,9 @@ namespace Kyoo.Core.Controllers return transmux(path, outPath, out playableDuration); } - [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl, + [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] - private static extern IntPtr extract_infos(string path, + private static extern IntPtr extract_infos(string path, string outpath, out uint length, out uint trackCount, @@ -48,17 +63,16 @@ namespace Kyoo.Core.Controllers [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] private static extern void free_streams(IntPtr streams, uint count); - public static Track[] ExtractInfos(string path, string outPath, bool reextract) { path = path.Replace('\\', '/'); outPath = outPath.Replace('\\', '/'); - + int size = Marshal.SizeOf(); IntPtr ptr = extract_infos(path, outPath, out uint arrayLength, out uint trackCount, reextract); IntPtr streamsPtr = ptr; Track[] tracks; - + if (trackCount > 0 && ptr != IntPtr.Zero) { tracks = new Track[trackCount]; @@ -84,6 +98,8 @@ namespace Kyoo.Core.Controllers } } + public class BadTranscoderException : Exception { } + private readonly IFileSystem _files; private readonly IOptions _options; private readonly Lazy _library; @@ -113,7 +129,7 @@ namespace Kyoo.Core.Controllers { if (!File.Exists(episode.Path)) throw new ArgumentException("Path does not exists. Can't transcode."); - + string folder = Path.Combine(_options.Value.TransmuxPath, episode.Slug); string manifest = Path.Combine(folder, episode.Slug + ".m3u8"); float playableDuration = 0; @@ -130,12 +146,12 @@ namespace Kyoo.Core.Controllers await Console.Error.WriteLineAsync($"Access to the path {manifest} is denied. Please change your transmux path in the config."); return null; } - + Task.Factory.StartNew(() => { transmuxFailed = TranscoderAPI.Transmux(episode.Path, manifest, out playableDuration) != 0; }, TaskCreationOptions.LongRunning); - while (playableDuration < 10 || !File.Exists(manifest) && !transmuxFailed) + while (playableDuration < 10 || (!File.Exists(manifest) && !transmuxFailed)) await Task.Delay(10); return transmuxFailed ? null : manifest; } diff --git a/Kyoo.Core/CoreModule.cs b/src/Kyoo.Core/CoreModule.cs similarity index 88% rename from Kyoo.Core/CoreModule.cs rename to src/Kyoo.Core/CoreModule.cs index ef0961cc..fa7f9819 100644 --- a/Kyoo.Core/CoreModule.cs +++ b/src/Kyoo.Core/CoreModule.cs @@ -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 . + using System; using System.Collections.Generic; using Autofac; @@ -6,7 +24,6 @@ using Autofac.Core.Registration; using Autofac.Extras.AttributeMetadata; using Kyoo.Abstractions; using Kyoo.Abstractions.Controllers; -using Kyoo.Abstractions.Models.Permissions; using Kyoo.Core.Api; using Kyoo.Core.Controllers; using Kyoo.Core.Models.Options; @@ -29,10 +46,10 @@ namespace Kyoo.Core { /// public string Slug => "core"; - + /// public string Name => "Core"; - + /// public string Description => "The core module containing default implementations."; @@ -46,13 +63,11 @@ namespace Kyoo.Core { "logging", null } }; - /// /// The configuration to use. /// private readonly IConfiguration _configuration; - /// /// Create a new core module instance and use the given configuration. /// @@ -66,11 +81,11 @@ namespace Kyoo.Core public void Configure(ContainerBuilder builder) { builder.RegisterModule(); - + builder.RegisterComposite().InstancePerLifetimeScope(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); - + builder.RegisterType().As().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); @@ -78,7 +93,7 @@ namespace Kyoo.Core builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().SingleInstance(); - + builder.RegisterComposite(); builder.Register(x => (AProviderComposite)x.Resolve()); @@ -106,7 +121,7 @@ namespace Kyoo.Core builder.RegisterType().As() .IfNotRegistered(typeof(IPermissionValidator)); - + builder.RegisterType().As().SingleInstance() .OnActivating(x => { @@ -117,7 +132,7 @@ namespace Kyoo.Core x.Instance.Mappings[".m3u8"] = "application/x-mpegurl"; }); } - + /// public void Configure(IServiceCollection services) { @@ -130,12 +145,12 @@ namespace Kyoo.Core x.SerializerSettings.ContractResolver = new JsonPropertyIgnorer(publicUrl); x.SerializerSettings.Converters.Add(new PeopleRoleConverter()); }); - + services.AddResponseCompression(x => { x.EnableForHttps = true; }); - + services.AddHttpClient(); } @@ -158,4 +173,4 @@ namespace Kyoo.Core SA.New(app => app.UseEndpoints(x => x.MapControllers()), SA.Endpoint) }; } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Helper.cs b/src/Kyoo.Core/Helper.cs similarity index 55% rename from Kyoo.Core/Helper.cs rename to src/Kyoo.Core/Helper.cs index 570e22d6..42f767b7 100644 --- a/Kyoo.Core/Helper.cs +++ b/src/Kyoo.Core/Helper.cs @@ -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 . + using System.Net.Http; using System.Threading.Tasks; using Newtonsoft.Json; @@ -23,4 +41,4 @@ namespace Kyoo.Core return JsonConvert.DeserializeObject(content); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Kyoo.Core.csproj b/src/Kyoo.Core/Kyoo.Core.csproj similarity index 90% rename from Kyoo.Core/Kyoo.Core.csproj rename to src/Kyoo.Core/Kyoo.Core.csproj index 917b5a31..75db8e82 100644 --- a/Kyoo.Core/Kyoo.Core.csproj +++ b/src/Kyoo.Core/Kyoo.Core.csproj @@ -1,4 +1,4 @@ - + net5.0 @@ -9,12 +9,6 @@ https://github.com/AnonymusRaccoon/Kyoo default - - - true - true - true - transcoder.dll @@ -58,16 +52,16 @@ - + PreserveNewest false - + - + diff --git a/Kyoo.Core/Models/FileExtensions.cs b/src/Kyoo.Core/Models/FileExtensions.cs similarity index 65% rename from Kyoo.Core/Models/FileExtensions.cs rename to src/Kyoo.Core/Models/FileExtensions.cs index 26e520d1..e28c9007 100644 --- a/Kyoo.Core/Models/FileExtensions.cs +++ b/src/Kyoo.Core/Models/FileExtensions.cs @@ -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 . + using System.Collections.Generic; using System.Collections.Immutable; using System.IO; @@ -17,7 +35,7 @@ namespace Kyoo.Core.Models.Watch ".mkv", ".flv", ".vob", - ".ogg", + ".ogg", ".ogv", ".avi", ".mts", @@ -25,7 +43,7 @@ namespace Kyoo.Core.Models.Watch ".ts", ".mov", ".qt", - ".asf", + ".asf", ".mp4", ".m4p", ".m4v", @@ -48,14 +66,14 @@ namespace Kyoo.Core.Models.Watch { return VideoExtensions.Contains(Path.GetExtension(filePath)); } - + /// /// The dictionary of known subtitles extensions and the name of the subtitle codec. /// - public static readonly ImmutableDictionary SubtitleExtensions = new Dictionary + public static readonly ImmutableDictionary SubtitleExtensions = new Dictionary { - {".ass", "ass"}, - {".str", "subrip"} + { ".ass", "ass" }, + { ".str", "subrip" } }.ToImmutableDictionary(); /// @@ -68,4 +86,4 @@ namespace Kyoo.Core.Models.Watch return SubtitleExtensions.ContainsKey(Path.GetExtension(filePath)); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Models/Options/BasicOptions.cs b/src/Kyoo.Core/Models/Options/BasicOptions.cs similarity index 70% rename from Kyoo.Core/Models/Options/BasicOptions.cs rename to src/Kyoo.Core/Models/Options/BasicOptions.cs index 5bb108f8..2fa00249 100644 --- a/Kyoo.Core/Models/Options/BasicOptions.cs +++ b/src/Kyoo.Core/Models/Options/BasicOptions.cs @@ -1,5 +1,23 @@ -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 . + using System; +using Kyoo.Abstractions.Models; namespace Kyoo.Core.Models.Options { @@ -32,7 +50,7 @@ namespace Kyoo.Core.Models.Options /// The temporary folder to cache transmuxed file. /// public string TransmuxPath { get; set; } = "cached/transmux"; - + /// /// The temporary folder to cache transcoded file. /// @@ -55,4 +73,4 @@ namespace Kyoo.Core.Models.Options /// public string MetadataPath { get; set; } = "metadata/"; } -} \ No newline at end of file +} diff --git a/src/Kyoo.Core/Models/Options/MediaOptions.cs b/src/Kyoo.Core/Models/Options/MediaOptions.cs new file mode 100644 index 00000000..32b54a24 --- /dev/null +++ b/src/Kyoo.Core/Models/Options/MediaOptions.cs @@ -0,0 +1,41 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +namespace Kyoo.Core.Models.Options +{ + /// + /// Options for media registering. + /// + public class MediaOptions + { + /// + /// The path of this options + /// + public const string Path = "Media"; + + /// + /// A regex for episodes + /// + public string[] Regex { get; set; } + + /// + /// A regex for subtitles + /// + public string[] SubtitleRegex { get; set; } + } +} diff --git a/src/Kyoo.Core/Models/Options/TaskOptions.cs b/src/Kyoo.Core/Models/Options/TaskOptions.cs new file mode 100644 index 00000000..48dd13ee --- /dev/null +++ b/src/Kyoo.Core/Models/Options/TaskOptions.cs @@ -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 . + +using System; +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace Kyoo.Core.Models.Options +{ + /// + /// Options related to tasks + /// + public class TaskOptions + { + /// + /// The path of this options + /// + public const string Path = "Tasks"; + + /// + /// The number of tasks that can be run concurrently. + /// + public int Parallels { get; set; } + + /// + /// The delay of tasks that should be automatically started at fixed times. + /// + [UsedImplicitly] + public Dictionary Scheduled { get; set; } = new(); + } +} diff --git a/Kyoo.Core/Models/Stream.cs b/src/Kyoo.Core/Models/Stream.cs similarity index 55% rename from Kyoo.Core/Models/Stream.cs rename to src/Kyoo.Core/Models/Stream.cs index 2980adae..ff6979d6 100644 --- a/Kyoo.Core/Models/Stream.cs +++ b/src/Kyoo.Core/Models/Stream.cs @@ -1,6 +1,23 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + using System.Runtime.InteropServices; using Kyoo.Abstractions.Models; -using Kyoo.Abstractions.Models.Attributes; namespace Kyoo.Core.Models.Watch { @@ -8,43 +25,42 @@ namespace Kyoo.Core.Models.Watch /// The unmanaged stream that the transcoder will return. /// [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public class Stream + public struct Stream { /// /// The title of the stream. /// - public string Title { get; set; } - + public string Title; + /// /// The language of this stream (as a ISO-639-2 language code) /// - public string Language { get; set; } - + public string Language; + /// /// The codec of this stream. /// - public string Codec { get; set; } - + public string Codec; + /// /// Is this stream the default one of it's type? /// [MarshalAs(UnmanagedType.I1)] public bool IsDefault; /// - /// Is this stream tagged as forced? + /// Is this stream tagged as forced? /// [MarshalAs(UnmanagedType.I1)] public bool IsForced; - + /// /// The path of this track. /// - [SerializeIgnore] public string Path { get; set; } - + public string Path; + /// /// The type of this stream. /// - [SerializeIgnore] public StreamType Type { get; set; } - + public StreamType Type; /// /// Create a track from this stream. @@ -65,4 +81,4 @@ namespace Kyoo.Core.Models.Watch }; } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/PluginsStartup.cs b/src/Kyoo.Core/PluginsStartup.cs similarity index 90% rename from Kyoo.Core/PluginsStartup.cs rename to src/Kyoo.Core/PluginsStartup.cs index 470c9a4f..1a554a8b 100644 --- a/Kyoo.Core/PluginsStartup.cs +++ b/src/Kyoo.Core/PluginsStartup.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -61,6 +79,27 @@ namespace Kyoo.Core ); } + /// + /// Create a new from a webhost. + /// This is meant to be used from . + /// + /// The context of the web host. + /// + /// The logger factory used to log while the application is setting itself up. + /// + /// A new . + public static PluginsStartup FromWebHost(WebHostBuilderContext host, + ILoggerFactory logger) + { + HostServiceProvider hostProvider = new(host.HostingEnvironment, host.Configuration, logger); + PluginManager plugins = new( + hostProvider, + Options.Create(host.Configuration.GetSection(BasicOptions.Path).Get()), + logger.CreateLogger() + ); + return new PluginsStartup(plugins, host.Configuration); + } + /// /// Configure the services context via the . /// @@ -69,7 +108,7 @@ namespace Kyoo.Core { foreach (IPlugin plugin in _plugins.GetAllPlugins()) plugin.Configure(services); - + IEnumerable> configTypes = _plugins.GetAllPlugins() .SelectMany(x => x.Configuration) .Where(x => x.Value != null); @@ -92,7 +131,7 @@ namespace Kyoo.Core { builder.RegisterInstance(_plugins).As().ExternallyOwned(); builder.RegisterTask(); - + foreach (IPlugin plugin in _plugins.GetAllPlugins()) plugin.Configure(builder); } @@ -125,29 +164,7 @@ namespace Kyoo.Core foreach ((string path, Type type) in pluginConfig) config.Register(path, type); } - - - /// - /// Create a new from a webhost. - /// This is meant to be used from . - /// - /// The context of the web host. - /// - /// The logger factory used to log while the application is setting itself up. - /// - /// A new . - public static PluginsStartup FromWebHost(WebHostBuilderContext host, - ILoggerFactory logger) - { - HostServiceProvider hostProvider = new(host.HostingEnvironment, host.Configuration, logger); - PluginManager plugins = new( - hostProvider, - Options.Create(host.Configuration.GetSection(BasicOptions.Path).Get()), - logger.CreateLogger() - ); - return new PluginsStartup(plugins, host.Configuration); - } - + /// /// A simple host service provider used to activate plugins instance. /// The same services as a generic host are available and an has been added. @@ -158,18 +175,17 @@ namespace Kyoo.Core /// The host environment that could be used by plugins to configure themself. /// private readonly IWebHostEnvironment _hostEnvironment; - + /// /// The configuration context. /// private readonly IConfiguration _configuration; - + /// /// A logger factory used to create a logger for the plugin manager. /// private readonly ILoggerFactory _loggerFactory; - /// /// Create a new that will return given services when asked. /// diff --git a/Kyoo.Core/Tasks/Crawler.cs b/src/Kyoo.Core/Tasks/Crawler.cs similarity index 78% rename from Kyoo.Core/Tasks/Crawler.cs rename to src/Kyoo.Core/Tasks/Crawler.cs index 3633fbb3..1a5d6e9e 100644 --- a/Kyoo.Core/Tasks/Crawler.cs +++ b/src/Kyoo.Core/Tasks/Crawler.cs @@ -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 . + +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -22,14 +40,17 @@ namespace Kyoo.Core.Tasks /// The library manager used to get libraries and providers to use. /// private readonly ILibraryManager _libraryManager; + /// - /// The file manager used walk inside directories and check they existences. + /// The file manager used walk inside directories and check they existences. /// private readonly IFileSystem _fileSystem; + /// - /// A task manager used to create sub tasks for each episode to add to the database. + /// A task manager used to create sub tasks for each episode to add to the database. /// private readonly ITaskManager _taskManager; + /// /// The logger used to inform the current status to the console. /// @@ -52,8 +73,7 @@ namespace Kyoo.Core.Tasks _taskManager = taskManager; _logger = logger; } - - + /// public TaskParameters GetParameters() { @@ -67,9 +87,9 @@ namespace Kyoo.Core.Tasks public async Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) { string argument = arguments["slug"].As(); - ICollection libraries = argument == null + ICollection libraries = argument == null ? await _libraryManager.GetAll() - : new [] { await _libraryManager.GetOrDefault(argument)}; + : new[] { await _libraryManager.GetOrDefault(argument) }; if (argument != null && libraries.First() == null) throw new ArgumentException($"No library found with the name {argument}"); @@ -79,7 +99,7 @@ namespace Kyoo.Core.Tasks progress.Report(0); float percent = 0; - + ICollection episodes = await _libraryManager.GetAll(); ICollection tracks = await _libraryManager.GetAll(); foreach (Library library in libraries) @@ -87,19 +107,19 @@ namespace Kyoo.Core.Tasks IProgress reporter = new Progress(x => { // ReSharper disable once AccessToModifiedClosure - progress.Report(percent + x / libraries.Count); + progress.Report(percent + (x / libraries.Count)); }); - await Scan(library, episodes, tracks, reporter, cancellationToken); + await _Scan(library, episodes, tracks, reporter, cancellationToken); percent += 100f / libraries.Count; - + if (cancellationToken.IsCancellationRequested) return; } - + progress.Report(100); } - private async Task Scan(Library library, + private async Task _Scan(Library library, IEnumerable episodes, IEnumerable tracks, IProgress progress, @@ -109,20 +129,19 @@ namespace Kyoo.Core.Tasks foreach (string path in library.Paths) { ICollection files = await _fileSystem.ListFiles(path, SearchOption.AllDirectories); - + if (cancellationToken.IsCancellationRequested) return; // We try to group episodes by shows to register one episode of each show first. // This speeds up the scan process because further episodes of a show are registered when all metadata - // of the show has already been fetched. + // of the show has already been fetched. List> shows = files .Where(FileExtensions.IsVideo) .Where(x => episodes.All(y => y.Path != x)) .GroupBy(Path.GetDirectoryName) .ToList(); - - + string[] paths = shows.Select(x => x.First()) .Concat(shows.SelectMany(x => x.Skip(1))) .ToArray(); @@ -130,9 +149,9 @@ namespace Kyoo.Core.Tasks IProgress reporter = new Progress(x => { // ReSharper disable once AccessToModifiedClosure - progress.Report((percent + x / paths.Length - 10) / library.Paths.Length); + progress.Report((percent + (x / paths.Length) - 10) / library.Paths.Length); }); - + foreach (string episodePath in paths) { _taskManager.StartTask(reporter, new Dictionary @@ -143,7 +162,6 @@ namespace Kyoo.Core.Tasks percent += 100f / paths.Length; } - string[] subtitles = files .Where(FileExtensions.IsSubtitle) .Where(x => !x.Contains("Extra")) @@ -153,9 +171,9 @@ namespace Kyoo.Core.Tasks reporter = new Progress(x => { // ReSharper disable once AccessToModifiedClosure - progress.Report((90 + (percent + x / subtitles.Length)) / library.Paths.Length); + progress.Report((90 + (percent + (x / subtitles.Length))) / library.Paths.Length); }); - + foreach (string trackPath in subtitles) { _taskManager.StartTask(reporter, new Dictionary diff --git a/Kyoo.Core/Tasks/ExtractMetadata.cs b/src/Kyoo.Core/Tasks/ExtractMetadata.cs similarity index 78% rename from Kyoo.Core/Tasks/ExtractMetadata.cs rename to src/Kyoo.Core/Tasks/ExtractMetadata.cs index d3e339cb..a12e24e1 100644 --- a/Kyoo.Core/Tasks/ExtractMetadata.cs +++ b/src/Kyoo.Core/Tasks/ExtractMetadata.cs @@ -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 . + // using System; // using System.Collections.Generic; // using System.Linq; @@ -22,7 +40,7 @@ // private ILibraryManager _library; // private IThumbnailsManager _thumbnails; // private ITranscoder _transcoder; -// +// // public async Task Run(IServiceProvider serviceProvider, CancellationToken token, string arguments = null) // { // string[] args = arguments?.Split('/'); @@ -33,13 +51,13 @@ // string slug = args[1]; // bool thumbs = args.Length < 3 || string.Equals(args[2], "thumbnails", StringComparison.InvariantCultureIgnoreCase); // bool subs = args.Length < 3 || string.Equals(args[2], "subs", StringComparison.InvariantCultureIgnoreCase); -// +// // using IServiceScope serviceScope = serviceProvider.CreateScope(); // _library = serviceScope.ServiceProvider.GetService(); // _thumbnails = serviceScope.ServiceProvider.GetService(); // _transcoder = serviceScope.ServiceProvider.GetService(); // int id; -// +// // switch (args[0].ToLowerInvariant()) // { // case "show": @@ -51,15 +69,15 @@ // break; // case "season": // case "seasons": -// Season season = await (int.TryParse(slug, out id) -// ? _library!.Get(id) +// Season season = await (int.TryParse(slug, out id) +// ? _library!.Get(id) // : _library!.Get(slug)); // await ExtractSeason(season, thumbs, subs, token); // break; // case "episode": // case "episodes": -// Episode episode = await (int.TryParse(slug, out id) -// ? _library!.Get(id) +// Episode episode = await (int.TryParse(slug, out id) +// ? _library!.Get(id) // : _library!.Get(slug)); // await ExtractEpisode(episode, thumbs, subs); // break; @@ -91,7 +109,7 @@ // await ExtractEpisode(episode, thumbs, subs); // } // } -// +// // private async Task ExtractEpisode(Episode episode, bool thumbs, bool subs) // { // if (thumbs) @@ -106,7 +124,7 @@ // await _library.Edit(episode, false); // } // } -// +// // public Task> GetPossibleParameters() // { // return Task.FromResult>(null); @@ -117,4 +135,4 @@ // return null; // } // } -// } \ No newline at end of file +// } diff --git a/Kyoo.Core/Tasks/Housekeeping.cs b/src/Kyoo.Core/Tasks/Housekeeping.cs similarity index 74% rename from Kyoo.Core/Tasks/Housekeeping.cs rename to src/Kyoo.Core/Tasks/Housekeeping.cs index 38d1c9f4..a13bbb77 100644 --- a/Kyoo.Core/Tasks/Housekeeping.cs +++ b/src/Kyoo.Core/Tasks/Housekeeping.cs @@ -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 . + using System; using System.Threading; using System.Threading.Tasks; @@ -18,12 +36,14 @@ namespace Kyoo.Core.Tasks /// The library manager used to get libraries or remove deleted episodes. /// private readonly ILibraryManager _libraryManager; + /// - /// The file manager used walk inside directories and check they existences. + /// The file manager used walk inside directories and check they existences. /// private readonly IFileSystem _fileSystem; + /// - /// The logger used to inform the user that episodes has been removed. + /// The logger used to inform the user that episodes has been removed. /// private readonly ILogger _logger; @@ -57,10 +77,10 @@ namespace Kyoo.Core.Tasks { progress.Report(count / delCount * 100); count++; - + if (await _fileSystem.Exists(show.Path)) continue; - _logger.LogWarning("Show {Name}'s folder has been deleted (was {Path}), removing it from kyoo", + _logger.LogWarning("Show {Name}'s folder has been deleted (was {Path}), removing it from kyoo", show.Title, show.Path); await _libraryManager.Delete(show); } @@ -69,15 +89,15 @@ namespace Kyoo.Core.Tasks { progress.Report(count / delCount * 100); count++; - + if (await _fileSystem.Exists(episode.Path)) continue; - _logger.LogWarning("Episode {Slug}'s file has been deleted (was {Path}), removing it from kyoo", + _logger.LogWarning("Episode {Slug}'s file has been deleted (was {Path}), removing it from kyoo", episode.Slug, episode.Path); await _libraryManager.Delete(episode); } - + progress.Report(100); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Tasks/MetadataProviderLoader.cs b/src/Kyoo.Core/Tasks/MetadataProviderLoader.cs similarity index 65% rename from Kyoo.Core/Tasks/MetadataProviderLoader.cs rename to src/Kyoo.Core/Tasks/MetadataProviderLoader.cs index cfe398ae..7c004268 100644 --- a/Kyoo.Core/Tasks/MetadataProviderLoader.cs +++ b/src/Kyoo.Core/Tasks/MetadataProviderLoader.cs @@ -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 . + using System; using System.Collections.Generic; using System.Threading; @@ -16,31 +34,33 @@ namespace Kyoo.Core.Tasks public class MetadataProviderLoader : ITask { /// - /// The provider repository used to create in-db providers from metadata providers. + /// The provider repository used to create in-db providers from metadata providers. /// private readonly IProviderRepository _providers; + /// /// The thumbnail manager used to download providers logo. /// private readonly IThumbnailsManager _thumbnails; + /// /// The list of metadata providers to register. /// private readonly ICollection _metadataProviders; /// - /// Create a new task. + /// Create a new task. /// /// - /// The provider repository used to create in-db providers from metadata providers. + /// The provider repository used to create in-db providers from metadata providers. /// /// - /// The thumbnail manager used to download providers logo. + /// The thumbnail manager used to download providers logo. /// /// - /// The list of metadata providers to register. + /// The list of metadata providers to register. /// - public MetadataProviderLoader(IProviderRepository providers, + public MetadataProviderLoader(IProviderRepository providers, IThumbnailsManager thumbnails, ICollection metadataProviders) { @@ -49,7 +69,6 @@ namespace Kyoo.Core.Tasks _metadataProviders = metadataProviders; } - /// public TaskParameters GetParameters() { @@ -61,7 +80,7 @@ namespace Kyoo.Core.Tasks { float percent = 0; progress.Report(0); - + foreach (IMetadataProvider provider in _metadataProviders) { if (string.IsNullOrEmpty(provider.Provider.Slug)) @@ -74,4 +93,4 @@ namespace Kyoo.Core.Tasks progress.Report(100); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Tasks/PluginInitializer.cs b/src/Kyoo.Core/Tasks/PluginInitializer.cs similarity index 69% rename from Kyoo.Core/Tasks/PluginInitializer.cs rename to src/Kyoo.Core/Tasks/PluginInitializer.cs index a5b36b6d..1b455c7c 100644 --- a/Kyoo.Core/Tasks/PluginInitializer.cs +++ b/src/Kyoo.Core/Tasks/PluginInitializer.cs @@ -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 . + using System; using System.Collections.Generic; using System.Threading; @@ -10,7 +28,7 @@ namespace Kyoo.Core.Tasks /// /// A task run on Kyoo's startup to initialize plugins /// - [TaskMetadata("plugin-init", "Plugin Initializer", "A task to initialize plugins.", + [TaskMetadata("plugin-init", "Plugin Initializer", "A task to initialize plugins.", RunOnStartup = true, Priority = int.MaxValue, IsHidden = true)] public class PluginInitializer : ITask { @@ -18,6 +36,7 @@ namespace Kyoo.Core.Tasks /// The plugin manager used to retrieve plugins to initialize them. /// private readonly IPluginManager _pluginManager; + /// /// The service provider given to each method. /// @@ -33,14 +52,13 @@ namespace Kyoo.Core.Tasks _pluginManager = pluginManager; _provider = provider; } - /// public TaskParameters GetParameters() { return new(); } - + /// public Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) { @@ -51,13 +69,13 @@ namespace Kyoo.Core.Tasks foreach (IPlugin plugin in plugins) { plugin.Initialize(_provider); - + progress.Report(count / plugins.Count * 100); count++; } - + progress.Report(100); return Task.CompletedTask; } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Tasks/ReScan.cs b/src/Kyoo.Core/Tasks/ReScan.cs similarity index 85% rename from Kyoo.Core/Tasks/ReScan.cs rename to src/Kyoo.Core/Tasks/ReScan.cs index a4a62786..87bfbada 100644 --- a/Kyoo.Core/Tasks/ReScan.cs +++ b/src/Kyoo.Core/Tasks/ReScan.cs @@ -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 . + // using System; // using System.Collections.Generic; // using System.Linq; @@ -17,8 +35,8 @@ // public string HelpMessage => null; // public bool RunOnStartup => false; // public int Priority => 0; -// -// +// +// // private IServiceProvider _serviceProvider; // private IThumbnailsManager _thumbnailsManager; // private IProviderManager _providerManager; @@ -31,7 +49,7 @@ // _thumbnailsManager = serviceProvider.GetService(); // _providerManager = serviceProvider.GetService(); // _database = serviceScope.ServiceProvider.GetService(); -// +// // if (arguments == null || !arguments.Contains('/')) // return; // @@ -50,7 +68,7 @@ // private async Task ReScanShow(string slug) // { // Show old; -// +// // using (IServiceScope serviceScope = _serviceProvider.CreateScope()) // { // ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService(); @@ -71,7 +89,7 @@ // if (orphans.Any()) // await Task.WhenAll(orphans.Select(x => ReScanEpisode(old, x))); // } -// +// // private async Task ReScanSeason(string seasonSlug) // { // string[] infos = seasonSlug.Split('-'); @@ -124,4 +142,4 @@ // return null; // } // } -// } \ No newline at end of file +// } diff --git a/Kyoo.Core/Tasks/RegisterEpisode.cs b/src/Kyoo.Core/Tasks/RegisterEpisode.cs similarity index 88% rename from Kyoo.Core/Tasks/RegisterEpisode.cs rename to src/Kyoo.Core/Tasks/RegisterEpisode.cs index d713a9d1..5ad39046 100644 --- a/Kyoo.Core/Tasks/RegisterEpisode.cs +++ b/src/Kyoo.Core/Tasks/RegisterEpisode.cs @@ -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 . + using System; using System.Linq; using System.Threading; @@ -19,18 +37,22 @@ namespace Kyoo.Core.Tasks /// An identifier to extract metadata from paths. /// private readonly IIdentifier _identifier; + /// /// The library manager used to register the episode. /// private readonly ILibraryManager _libraryManager; + /// /// A metadata provider to retrieve the metadata of the new episode (and related items if they do not exist). /// private readonly AProviderComposite _metadataProvider; + /// /// The thumbnail manager used to download images. /// private readonly IThumbnailsManager _thumbnailsManager; + /// /// The transcoder used to extract subtitles and metadata. /// @@ -76,7 +98,7 @@ namespace Kyoo.Core.Tasks TaskParameter.CreateRequired("library", "The library in witch the episode is") }; } - + /// public async Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) { @@ -148,7 +170,7 @@ namespace Kyoo.Core.Tasks throw new TaskFailedException(ex); } } - + /// /// Retrieve the equivalent item if it already exists in the database, /// if it does not, fill metadata using the metadata provider, download images and register the item to the @@ -172,7 +194,7 @@ namespace Kyoo.Core.Tasks item = await _metadataProvider.Get(item); await _thumbnailsManager.DownloadImages(item); - + switch (item) { case Show show when show.People != null: @@ -187,4 +209,4 @@ namespace Kyoo.Core.Tasks return await _libraryManager.CreateIfNotExists(item); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Tasks/RegisterSubtitle.cs b/src/Kyoo.Core/Tasks/RegisterSubtitle.cs similarity index 76% rename from Kyoo.Core/Tasks/RegisterSubtitle.cs rename to src/Kyoo.Core/Tasks/RegisterSubtitle.cs index 3b931ab7..ae1380fb 100644 --- a/Kyoo.Core/Tasks/RegisterSubtitle.cs +++ b/src/Kyoo.Core/Tasks/RegisterSubtitle.cs @@ -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 . + using System; using System.Threading; using System.Threading.Tasks; @@ -18,6 +36,7 @@ namespace Kyoo.Core.Tasks /// An identifier to extract metadata from paths. /// private readonly IIdentifier _identifier; + /// /// The library manager used to register the episode. /// @@ -42,7 +61,7 @@ namespace Kyoo.Core.Tasks TaskParameter.CreateRequired("path", "The path of the subtitle file") }; } - + /// public async Task Run(TaskParameters arguments, IProgress progress, CancellationToken cancellationToken) { @@ -80,4 +99,4 @@ namespace Kyoo.Core.Tasks } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/CollectionApi.cs b/src/Kyoo.Core/Views/CollectionApi.cs similarity index 81% rename from Kyoo.Core/Views/CollectionApi.cs rename to src/Kyoo.Core/Views/CollectionApi.cs index 56af8b0a..db4ac5bc 100644 --- a/Kyoo.Core/Views/CollectionApi.cs +++ b/src/Kyoo.Core/Views/CollectionApi.cs @@ -1,13 +1,31 @@ -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 . + +using System; using System.Collections.Generic; using System.Linq; -using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Core.Models.Options; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; namespace Kyoo.Core.Api @@ -22,17 +40,17 @@ namespace Kyoo.Core.Api private readonly IFileSystem _files; private readonly IThumbnailsManager _thumbs; - public CollectionApi(ILibraryManager libraryManager, - IFileSystem files, + public CollectionApi(ILibraryManager libraryManager, + IFileSystem files, IThumbnailsManager thumbs, - IOptions options) + IOptions options) : base(libraryManager.CollectionRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; _files = files; _thumbs = thumbs; } - + [HttpGet("{id:int}/show")] [HttpGet("{id:int}/shows")] [PartialPermission(Kind.Read)] @@ -55,10 +73,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{slug}/show")] [HttpGet("{slug}/shows")] [PartialPermission(Kind.Read)] @@ -81,10 +99,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{id:int}/library")] [HttpGet("{id:int}/libraries")] [PartialPermission(Kind.Read)] @@ -107,10 +125,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{slug}/library")] [HttpGet("{slug}/libraries")] [PartialPermission(Kind.Read)] @@ -133,10 +151,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{slug}/poster")] public async Task GetPoster(string slug) { @@ -150,7 +168,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{slug}/logo")] public async Task GetLogo(string slug) { @@ -164,7 +182,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{slug}/backdrop")] [HttpGet("{slug}/thumbnail")] public async Task GetBackdrop(string slug) @@ -180,4 +198,4 @@ namespace Kyoo.Core.Api } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/ConfigurationApi.cs b/src/Kyoo.Core/Views/ConfigurationApi.cs similarity index 76% rename from Kyoo.Core/Views/ConfigurationApi.cs rename to src/Kyoo.Core/Views/ConfigurationApi.cs index 0b20df11..204634cd 100644 --- a/Kyoo.Core/Views/ConfigurationApi.cs +++ b/src/Kyoo.Core/Views/ConfigurationApi.cs @@ -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 . + using System; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; @@ -77,4 +95,4 @@ namespace Kyoo.Core.Api } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/EpisodeApi.cs b/src/Kyoo.Core/Views/EpisodeApi.cs similarity index 85% rename from Kyoo.Core/Views/EpisodeApi.cs rename to src/Kyoo.Core/Views/EpisodeApi.cs index c4fdf566..37591b99 100644 --- a/Kyoo.Core/Views/EpisodeApi.cs +++ b/src/Kyoo.Core/Views/EpisodeApi.cs @@ -1,5 +1,22 @@ -using System; -using Microsoft.AspNetCore.Mvc; +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -8,6 +25,7 @@ using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Core.Models.Options; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; namespace Kyoo.Core.Api @@ -25,7 +43,7 @@ namespace Kyoo.Core.Api public EpisodeApi(ILibraryManager libraryManager, IOptions options, IFileSystem files, - IThumbnailsManager thumbnails) + IThumbnailsManager thumbnails) : base(libraryManager.EpisodeRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; @@ -37,12 +55,12 @@ namespace Kyoo.Core.Api [PartialPermission(Kind.Read)] public async Task> GetShow(int episodeID) { - Show ret = await _libraryManager.GetOrDefault(x => x.Episodes.Any(y => y.ID == episodeID)); + Show ret = await _libraryManager.GetOrDefault(x => x.Episodes.Any(y => y.ID == episodeID)); if (ret == null) return NotFound(); return ret; } - + [HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}/show")] [PartialPermission(Kind.Read)] public async Task> GetShow(string showSlug, int seasonNumber, int episodeNumber) @@ -52,7 +70,7 @@ namespace Kyoo.Core.Api return NotFound(); return ret; } - + [HttpGet("{showID:int}-{seasonNumber:int}e{episodeNumber:int}/show")] [PartialPermission(Kind.Read)] public async Task> GetShow(int showID, int seasonNumber, int episodeNumber) @@ -62,7 +80,7 @@ namespace Kyoo.Core.Api return NotFound(); return ret; } - + [HttpGet("{episodeID:int}/season")] [PartialPermission(Kind.Read)] public async Task> GetSeason(int episodeID) @@ -72,7 +90,7 @@ namespace Kyoo.Core.Api return NotFound(); return ret; } - + [HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}/season")] [PartialPermission(Kind.Read)] public async Task> GetSeason(string showSlug, int seasonNumber, int episodeNumber) @@ -86,7 +104,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{showID:int}-{seasonNumber:int}e{episodeNumber:int}/season")] [PartialPermission(Kind.Read)] public async Task> GetSeason(int showID, int seasonNumber, int episodeNumber) @@ -100,7 +118,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{episodeID:int}/track")] [HttpGet("{episodeID:int}/tracks")] [PartialPermission(Kind.Read)] @@ -123,10 +141,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{showID:int}-s{seasonNumber:int}e{episodeNumber:int}/track")] [HttpGet("{showID:int}-s{seasonNumber:int}e{episodeNumber:int}/tracks")] [PartialPermission(Kind.Read)] @@ -141,7 +159,7 @@ namespace Kyoo.Core.Api try { ICollection resources = await _libraryManager.GetAll( - ApiHelper.ParseWhere(where, x => x.Episode.ShowID == showID + ApiHelper.ParseWhere(where, x => x.Episode.ShowID == showID && x.Episode.SeasonNumber == seasonNumber && x.Episode.EpisodeNumber == episodeNumber), new Sort(sortBy), @@ -153,10 +171,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{slug}-s{seasonNumber:int}e{episodeNumber:int}/track")] [HttpGet("{slug}-s{seasonNumber:int}e{episodeNumber:int}/tracks")] [PartialPermission(Kind.Read)] @@ -171,7 +189,7 @@ namespace Kyoo.Core.Api try { ICollection resources = await _libraryManager.GetAll( - ApiHelper.ParseWhere(where, x => x.Episode.Show.Slug == slug + ApiHelper.ParseWhere(where, x => x.Episode.Show.Slug == slug && x.Episode.SeasonNumber == seasonNumber && x.Episode.EpisodeNumber == episodeNumber), new Sort(sortBy), @@ -183,10 +201,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{id:int}/thumbnail")] [HttpGet("{id:int}/backdrop")] public async Task GetThumb(int id) @@ -201,7 +219,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{slug}/thumbnail")] [HttpGet("{slug}/backdrop")] public async Task GetThumb(string slug) @@ -217,4 +235,4 @@ namespace Kyoo.Core.Api } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/GenreApi.cs b/src/Kyoo.Core/Views/GenreApi.cs similarity index 71% rename from Kyoo.Core/Views/GenreApi.cs rename to src/Kyoo.Core/Views/GenreApi.cs index d6e6a678..3ec1c7ed 100644 --- a/Kyoo.Core/Views/GenreApi.cs +++ b/src/Kyoo.Core/Views/GenreApi.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -24,7 +42,7 @@ namespace Kyoo.Core.Api { _libraryManager = libraryManager; } - + [HttpGet("{id:int}/show")] [HttpGet("{id:int}/shows")] [PartialPermission(Kind.Read)] @@ -47,10 +65,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{slug}/show")] [HttpGet("{slug}/shows")] [PartialPermission(Kind.Read)] @@ -73,8 +91,8 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/Helper/ApiHelper.cs b/src/Kyoo.Core/Views/Helper/ApiHelper.cs similarity index 74% rename from Kyoo.Core/Views/Helper/ApiHelper.cs rename to src/Kyoo.Core/Views/Helper/ApiHelper.cs index 31e545c6..7365c5a7 100644 --- a/Kyoo.Core/Views/Helper/ApiHelper.cs +++ b/src/Kyoo.Core/Views/Helper/ApiHelper.cs @@ -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 . + using System; using System.Collections; using System.Collections.Generic; @@ -21,8 +39,8 @@ namespace Kyoo.Core.Api } return operand(left, right); } - - public static Expression> ParseWhere(Dictionary where, + + public static Expression> ParseWhere(Dictionary where, Expression> defaultWhere = null) { if (where == null || where.Count == 0) @@ -35,7 +53,7 @@ namespace Kyoo.Core.Api { if (key == null || desired == null) throw new ArgumentException("Invalid key/value pair. Can't be null."); - + string value = desired; string operand = "eq"; if (desired.Contains(':')) @@ -68,15 +86,15 @@ namespace Kyoo.Core.Api valueExpr = Expression.Constant(val, property.PropertyType); } - + Expression condition = operand switch { - "eq" when isList => ContainsResourceExpression(propertyExpr, value), - "ctn" => ContainsResourceExpression(propertyExpr, value), - - "eq" when valueExpr == null => ResourceEqual(propertyExpr, value), - "not" when valueExpr == null => ResourceEqual(propertyExpr, value, true), - + "eq" when isList => _ContainsResourceExpression(propertyExpr, value), + "ctn" => _ContainsResourceExpression(propertyExpr, value), + + "eq" when valueExpr == null => _ResourceEqual(propertyExpr, value), + "not" when valueExpr == null => _ResourceEqual(propertyExpr, value, true), + "eq" => Expression.Equal(propertyExpr, valueExpr), "not" => Expression.NotEqual(propertyExpr, valueExpr!), "lt" => StringCompatibleExpression(Expression.LessThan, propertyExpr, valueExpr), @@ -95,7 +113,7 @@ namespace Kyoo.Core.Api return Expression.Lambda>(expression!, param); } - private static Expression ResourceEqual(Expression parameter, string value, bool notEqual = false) + private static Expression _ResourceEqual(Expression parameter, string value, bool notEqual = false) { MemberExpression field; ConstantExpression valueConst; @@ -110,19 +128,19 @@ namespace Kyoo.Core.Api valueConst = Expression.Constant(value); } - return notEqual - ? Expression.NotEqual(field, valueConst) + return notEqual + ? Expression.NotEqual(field, valueConst) : Expression.Equal(field, valueConst); } - - private static Expression ContainsResourceExpression(MemberExpression xProperty, string value) + + private static Expression _ContainsResourceExpression(MemberExpression xProperty, string value) { // x => x.PROPERTY.Any(y => y.Slug == value) Expression ret = null; ParameterExpression y = Expression.Parameter(xProperty.Type.GenericTypeArguments.First(), "y"); foreach (string val in value.Split(',')) { - LambdaExpression lambda = Expression.Lambda(ResourceEqual(y, val), y); + LambdaExpression lambda = Expression.Lambda(_ResourceEqual(y, val), y); Expression iteration = Expression.Call(typeof(Enumerable), "Any", xProperty.Type.GenericTypeArguments, xProperty, lambda); @@ -134,4 +152,4 @@ namespace Kyoo.Core.Api return ret; } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/Helper/CrudApi.cs b/src/Kyoo.Core/Views/Helper/CrudApi.cs similarity index 80% rename from Kyoo.Core/Views/Helper/CrudApi.cs rename to src/Kyoo.Core/Views/Helper/CrudApi.cs index ab1eef72..c621b993 100644 --- a/Kyoo.Core/Views/Helper/CrudApi.cs +++ b/src/Kyoo.Core/Views/Helper/CrudApi.cs @@ -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 . + +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -12,10 +30,12 @@ namespace Kyoo.Core.Api { [ApiController] [ResourceView] - public class CrudApi : ControllerBase where T : class, IResource + public class CrudApi : ControllerBase + where T : class, IResource { private readonly IRepository _repository; - protected readonly Uri BaseURL; + + protected Uri BaseURL { get; } public CrudApi(IRepository repository, Uri baseURL) { @@ -23,7 +43,6 @@ namespace Kyoo.Core.Api BaseURL = baseURL; } - [HttpGet("{id:int}")] [PartialPermission(Kind.Read)] public virtual async Task> Get(int id) @@ -54,10 +73,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet] [PartialPermission(Kind.Read)] public virtual async Task>> GetAll([FromQuery] string sortBy, @@ -75,7 +94,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -98,7 +117,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } catch (DuplicatedItemException) { @@ -106,7 +125,7 @@ namespace Kyoo.Core.Api return Conflict(existing); } } - + [HttpPut] [PartialPermission(Kind.Write)] public virtual async Task> Edit([FromQuery] bool resetOld, [FromBody] T resource) @@ -140,7 +159,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpPut("{slug}")] [PartialPermission(Kind.Write)] public virtual async Task> Edit(string slug, [FromQuery] bool resetOld, [FromBody] T resource) @@ -172,7 +191,7 @@ namespace Kyoo.Core.Api return Ok(); } - + [HttpDelete("{slug}")] [PartialPermission(Kind.Delete)] public virtual async Task Delete(string slug) @@ -188,7 +207,7 @@ namespace Kyoo.Core.Api return Ok(); } - + [PartialPermission(Kind.Delete)] public virtual async Task Delete(Dictionary where) { @@ -204,4 +223,4 @@ namespace Kyoo.Core.Api return Ok(); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/Helper/ResourceViewAttribute.cs b/src/Kyoo.Core/Views/Helper/ResourceViewAttribute.cs similarity index 78% rename from Kyoo.Core/Views/Helper/ResourceViewAttribute.cs rename to src/Kyoo.Core/Views/Helper/ResourceViewAttribute.cs index ad4d9055..abf215b7 100644 --- a/Kyoo.Core/Views/Helper/ResourceViewAttribute.cs +++ b/src/Kyoo.Core/Views/Helper/ResourceViewAttribute.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -40,7 +58,7 @@ namespace Kyoo.Core.Api type = Utility.GetGenericDefinition(type, typeof(Task<>))?.GetGenericArguments()[0] ?? type; type = Utility.GetGenericDefinition(type, typeof(ActionResult<>))?.GetGenericArguments()[0] ?? type; type = Utility.GetGenericDefinition(type, typeof(Page<>))?.GetGenericArguments()[0] ?? type; - + PropertyInfo[] properties = type.GetProperties() .Where(x => x.GetCustomAttribute() != null) .ToArray(); @@ -77,11 +95,11 @@ namespace Kyoo.Core.Api public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { if (context.Result is ObjectResult result) - await LoadResultRelations(context, result); + await _LoadResultRelations(context, result); await base.OnResultExecutionAsync(context, next); } - private static async Task LoadResultRelations(ActionContext context, ObjectResult result) + private static async Task _LoadResultRelations(ActionContext context, ObjectResult result) { if (result.DeclaredType == null) return; @@ -90,7 +108,6 @@ namespace Kyoo.Core.Api ICollection fields = (ICollection)context.HttpContext.Items["fields"]; Type pageType = Utility.GetGenericDefinition(result.DeclaredType, typeof(Page<>)); - if (pageType != null) { foreach (IResource resource in ((dynamic)result.Value).Items) @@ -106,4 +123,4 @@ namespace Kyoo.Core.Api } } } -} \ No newline at end of file +} diff --git a/src/Kyoo.Core/Views/Helper/Serializers/JsonPropertyIgnorer.cs b/src/Kyoo.Core/Views/Helper/Serializers/JsonPropertyIgnorer.cs new file mode 100644 index 00000000..d5f23fce --- /dev/null +++ b/src/Kyoo.Core/Views/Helper/Serializers/JsonPropertyIgnorer.cs @@ -0,0 +1,89 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System; +using System.Collections; +using System.Reflection; +using Kyoo.Abstractions.Models; +using Kyoo.Abstractions.Models.Attributes; +using Kyoo.Utils; +using Newtonsoft.Json; +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(); + 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() != null) + property.ShouldSerialize = _ => false; + if (member.GetCustomAttribute() != 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(); + 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; + } + } +} diff --git a/src/Kyoo.Core/Views/Helper/Serializers/PeopleRoleConverter.cs b/src/Kyoo.Core/Views/Helper/Serializers/PeopleRoleConverter.cs new file mode 100644 index 00000000..447efccd --- /dev/null +++ b/src/Kyoo.Core/Views/Helper/Serializers/PeopleRoleConverter.cs @@ -0,0 +1,58 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System; +using System.Collections.Generic; +using Kyoo.Abstractions.Models; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Kyoo.Core.Api +{ + public class PeopleRoleConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, PeopleRole value, JsonSerializer serializer) + { + ICollection oldPeople = value.Show?.People; + ICollection 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(); + } + } +} diff --git a/src/Kyoo.Core/Views/Helper/Serializers/SerializeAsProvider.cs b/src/Kyoo.Core/Views/Helper/Serializers/SerializeAsProvider.cs new file mode 100644 index 00000000..b16e63ac --- /dev/null +++ b/src/Kyoo.Core/Views/Helper/Serializers/SerializeAsProvider.cs @@ -0,0 +1,77 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using Newtonsoft.Json.Serialization; + +namespace Kyoo.Core.Api +{ + 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, @"(? + { + 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. + } + } +} diff --git a/Kyoo.Core/Views/LibraryApi.cs b/src/Kyoo.Core/Views/LibraryApi.cs similarity index 81% rename from Kyoo.Core/Views/LibraryApi.cs rename to src/Kyoo.Core/Views/LibraryApi.cs index 60991589..0199aa3c 100644 --- a/Kyoo.Core/Views/LibraryApi.cs +++ b/src/Kyoo.Core/Views/LibraryApi.cs @@ -1,12 +1,30 @@ -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 . + +using System; using System.Collections.Generic; using System.Linq; -using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Core.Models.Options; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; namespace Kyoo.Core.Api @@ -32,12 +50,14 @@ namespace Kyoo.Core.Api { ActionResult result = await base.Create(resource); if (result.Value != null) + { _taskManager.StartTask("scan", - new Progress(), - new Dictionary {{"slug", result.Value.Slug}}); + new Progress(), + new Dictionary { { "slug", result.Value.Slug } }); + } return result; } - + [HttpGet("{id:int}/show")] [HttpGet("{id:int}/shows")] [PartialPermission(Kind.Read)] @@ -60,7 +80,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -86,10 +106,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{id:int}/collection")] [HttpGet("{id:int}/collections")] [PartialPermission(Kind.Read)] @@ -112,7 +132,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -138,10 +158,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{id:int}/item")] [HttpGet("{id:int}/items")] [PartialPermission(Kind.Read)] @@ -164,10 +184,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{slug}/item")] [HttpGet("{slug}/items")] [PartialPermission(Kind.Read)] @@ -190,8 +210,8 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/LibraryItemApi.cs b/src/Kyoo.Core/Views/LibraryItemApi.cs similarity index 63% rename from Kyoo.Core/Views/LibraryItemApi.cs rename to src/Kyoo.Core/Views/LibraryItemApi.cs index 207eae9c..1b1137fb 100644 --- a/Kyoo.Core/Views/LibraryItemApi.cs +++ b/src/Kyoo.Core/Views/LibraryItemApi.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -21,7 +39,6 @@ namespace Kyoo.Core.Api private readonly ILibraryItemRepository _libraryItems; private readonly Uri _baseURL; - public LibraryItemApi(ILibraryItemRepository libraryItems, IOptions options) { _libraryItems = libraryItems; @@ -42,7 +59,7 @@ namespace Kyoo.Core.Api new Sort(sortBy), new Pagination(limit, afterID)); - return new Page(resources, + return new Page(resources, new Uri(_baseURL, Request.Path), Request.Query.ToDictionary(x => x.Key, x => x.Value.ToString(), StringComparer.InvariantCultureIgnoreCase), limit); @@ -53,8 +70,8 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/PeopleApi.cs b/src/Kyoo.Core/Views/PeopleApi.cs similarity index 75% rename from Kyoo.Core/Views/PeopleApi.cs rename to src/Kyoo.Core/Views/PeopleApi.cs index 5135aa86..2d810927 100644 --- a/Kyoo.Core/Views/PeopleApi.cs +++ b/src/Kyoo.Core/Views/PeopleApi.cs @@ -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 . + +using System; using System.Collections.Generic; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; @@ -23,7 +41,7 @@ namespace Kyoo.Core.Api public PeopleApi(ILibraryManager libraryManager, IOptions options, IFileSystem files, - IThumbnailsManager thumbs) + IThumbnailsManager thumbs) : base(libraryManager.PeopleRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; @@ -55,7 +73,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -83,10 +101,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{id:int}/poster")] public async Task GetPeopleIcon(int id) { @@ -95,7 +113,7 @@ namespace Kyoo.Core.Api return NotFound(); return _files.FileResult(await _thumbs.GetImagePath(people, Images.Poster)); } - + [HttpGet("{slug}/poster")] public async Task GetPeopleIcon(string slug) { @@ -105,4 +123,4 @@ namespace Kyoo.Core.Api return _files.FileResult(await _thumbs.GetImagePath(people, Images.Poster)); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/ProviderApi.cs b/src/Kyoo.Core/Views/ProviderApi.cs similarity index 65% rename from Kyoo.Core/Views/ProviderApi.cs rename to src/Kyoo.Core/Views/ProviderApi.cs index 431fefed..582c4d3d 100644 --- a/Kyoo.Core/Views/ProviderApi.cs +++ b/src/Kyoo.Core/Views/ProviderApi.cs @@ -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 . + using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; @@ -17,7 +35,7 @@ namespace Kyoo.Core.Api private readonly IThumbnailsManager _thumbnails; private readonly ILibraryManager _libraryManager; private readonly IFileSystem _files; - + public ProviderApi(ILibraryManager libraryManager, IOptions options, IFileSystem files, @@ -28,7 +46,7 @@ namespace Kyoo.Core.Api _files = files; _thumbnails = thumbnails; } - + [HttpGet("{id:int}/logo")] public async Task GetLogo(int id) { @@ -37,7 +55,7 @@ namespace Kyoo.Core.Api return NotFound(); return _files.FileResult(await _thumbnails.GetImagePath(provider, Images.Logo)); } - + [HttpGet("{slug}/logo")] public async Task GetLogo(string slug) { @@ -47,4 +65,4 @@ namespace Kyoo.Core.Api return _files.FileResult(await _thumbnails.GetImagePath(provider, Images.Logo)); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/SearchApi.cs b/src/Kyoo.Core/Views/SearchApi.cs similarity index 74% rename from Kyoo.Core/Views/SearchApi.cs rename to src/Kyoo.Core/Views/SearchApi.cs index a6e17c91..fc180483 100644 --- a/Kyoo.Core/Views/SearchApi.cs +++ b/src/Kyoo.Core/Views/SearchApi.cs @@ -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 . + +using System.Collections.Generic; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; @@ -38,7 +56,7 @@ namespace Kyoo.Core.Api Studios = await _libraryManager.Search(query) }; } - + [HttpGet("collection")] [HttpGet("collections")] [Permission(nameof(Collection), Kind.Read)] @@ -46,7 +64,7 @@ namespace Kyoo.Core.Api { return _libraryManager.Search(query); } - + [HttpGet("show")] [HttpGet("shows")] [Permission(nameof(Show), Kind.Read)] @@ -54,7 +72,7 @@ namespace Kyoo.Core.Api { return _libraryManager.Search(query); } - + [HttpGet("episode")] [HttpGet("episodes")] [Permission(nameof(Episode), Kind.Read)] @@ -62,14 +80,14 @@ namespace Kyoo.Core.Api { return _libraryManager.Search(query); } - + [HttpGet("people")] [Permission(nameof(People), Kind.Read)] public Task> SearchPeople(string query) { return _libraryManager.Search(query); } - + [HttpGet("genre")] [HttpGet("genres")] [Permission(nameof(Genre), Kind.Read)] @@ -77,7 +95,7 @@ namespace Kyoo.Core.Api { return _libraryManager.Search(query); } - + [HttpGet("studio")] [HttpGet("studios")] [Permission(nameof(Studio), Kind.Read)] @@ -86,4 +104,4 @@ namespace Kyoo.Core.Api return _libraryManager.Search(query); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/SeasonApi.cs b/src/Kyoo.Core/Views/SeasonApi.cs similarity index 84% rename from Kyoo.Core/Views/SeasonApi.cs rename to src/Kyoo.Core/Views/SeasonApi.cs index f7be874a..126603ea 100644 --- a/Kyoo.Core/Views/SeasonApi.cs +++ b/src/Kyoo.Core/Views/SeasonApi.cs @@ -1,12 +1,30 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + using System; using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; using System.Linq; +using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Core.Models.Options; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; namespace Kyoo.Core.Api @@ -31,7 +49,7 @@ namespace Kyoo.Core.Api _thumbs = thumbs; _files = files; } - + [HttpGet("{seasonID:int}/episode")] [HttpGet("{seasonID:int}/episodes")] [PartialPermission(Kind.Read)] @@ -54,10 +72,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{showSlug}-s{seasonNumber:int}/episode")] [HttpGet("{showSlug}-s{seasonNumber:int}/episodes")] [PartialPermission(Kind.Read)] @@ -71,7 +89,7 @@ namespace Kyoo.Core.Api try { ICollection resources = await _libraryManager.GetAll( - ApiHelper.ParseWhere(where, x => x.Show.Slug == showSlug + ApiHelper.ParseWhere(where, x => x.Show.Slug == showSlug && x.SeasonNumber == seasonNumber), new Sort(sortBy), new Pagination(limit, afterID)); @@ -82,10 +100,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{showID:int}-s{seasonNumber:int}/episode")] [HttpGet("{showID:int}-s{seasonNumber:int}/episodes")] [PartialPermission(Kind.Read)] @@ -109,10 +127,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{seasonID:int}/show")] [PartialPermission(Kind.Read)] public async Task> GetShow(int seasonID) @@ -122,7 +140,7 @@ namespace Kyoo.Core.Api return NotFound(); return ret; } - + [HttpGet("{showSlug}-s{seasonNumber:int}/show")] [PartialPermission(Kind.Read)] public async Task> GetShow(string showSlug, int seasonNumber) @@ -132,7 +150,7 @@ namespace Kyoo.Core.Api return NotFound(); return ret; } - + [HttpGet("{showID:int}-s{seasonNumber:int}/show")] [PartialPermission(Kind.Read)] public async Task> GetShow(int showID, int seasonNumber) @@ -142,7 +160,7 @@ namespace Kyoo.Core.Api return NotFound(); return ret; } - + [HttpGet("{id:int}/poster")] public async Task GetPoster(int id) { @@ -152,7 +170,7 @@ namespace Kyoo.Core.Api await _libraryManager.Load(season, x => x.Show); return _files.FileResult(await _thumbs.GetImagePath(season, Images.Poster)); } - + [HttpGet("{slug}/poster")] public async Task GetPoster(string slug) { @@ -163,4 +181,4 @@ namespace Kyoo.Core.Api return _files.FileResult(await _thumbs.GetImagePath(season, Images.Poster)); } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/ShowApi.cs b/src/Kyoo.Core/Views/ShowApi.cs similarity index 89% rename from Kyoo.Core/Views/ShowApi.cs rename to src/Kyoo.Core/Views/ShowApi.cs index fe0aaeee..4ebe06da 100644 --- a/Kyoo.Core/Views/ShowApi.cs +++ b/src/Kyoo.Core/Views/ShowApi.cs @@ -1,5 +1,22 @@ -using System; -using Microsoft.AspNetCore.Mvc; +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -9,6 +26,7 @@ using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Core.Models.Options; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; namespace Kyoo.Core.Api @@ -26,7 +44,7 @@ namespace Kyoo.Core.Api private readonly IThumbnailsManager _thumbs; public ShowApi(ILibraryManager libraryManager, - IFileSystem files, + IFileSystem files, IThumbnailsManager thumbs, IOptions options) : base(libraryManager.ShowRepository, options.Value.PublicUrl) @@ -58,7 +76,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -84,10 +102,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{showID:int}/episode")] [HttpGet("{showID:int}/episodes")] [PartialPermission(Kind.Read)] @@ -110,7 +128,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -136,10 +154,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{showID:int}/people")] [PartialPermission(Kind.Read)] public async Task>> GetPeople(int showID, @@ -161,7 +179,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -186,10 +204,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{showID:int}/genre")] [HttpGet("{showID:int}/genres")] [PartialPermission(Kind.Read)] @@ -212,7 +230,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -238,10 +256,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{showID:int}/studio")] [PartialPermission(Kind.Read)] public async Task> GetStudio(int showID) @@ -269,7 +287,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{showID:int}/library")] [HttpGet("{showID:int}/libraries")] [PartialPermission(Kind.Read)] @@ -292,7 +310,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -318,10 +336,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{showID:int}/collection")] [HttpGet("{showID:int}/collections")] [PartialPermission(Kind.Read)] @@ -344,7 +362,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -370,7 +388,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } @@ -392,7 +410,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{showSlug}/font/{slug}")] [HttpGet("{showSlug}/fonts/{slug}")] [PartialPermission(Kind.Read)] @@ -423,7 +441,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{slug}/logo")] public async Task GetLogo(string slug) { @@ -437,7 +455,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{slug}/backdrop")] [HttpGet("{slug}/thumbnail")] public async Task GetBackdrop(string slug) diff --git a/Kyoo.Core/Views/StudioApi.cs b/src/Kyoo.Core/Views/StudioApi.cs similarity index 70% rename from Kyoo.Core/Views/StudioApi.cs rename to src/Kyoo.Core/Views/StudioApi.cs index 87a06a11..f7bd9c77 100644 --- a/Kyoo.Core/Views/StudioApi.cs +++ b/src/Kyoo.Core/Views/StudioApi.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -24,7 +42,7 @@ namespace Kyoo.Core.Api { _libraryManager = libraryManager; } - + [HttpGet("{id:int}/show")] [HttpGet("{id:int}/shows")] [PartialPermission(Kind.Read)] @@ -47,10 +65,10 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } - + [HttpGet("{slug}/show")] [HttpGet("{slug}/shows")] [PartialPermission(Kind.Read)] @@ -66,15 +84,15 @@ namespace Kyoo.Core.Api ApiHelper.ParseWhere(where, x => x.Studio.Slug == slug), new Sort(sortBy), new Pagination(limit, afterID)); - + if (!resources.Any() && await _libraryManager.GetOrDefault(slug) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } } -} \ No newline at end of file +} diff --git a/src/Kyoo.Core/Views/SubtitleApi.cs b/src/Kyoo.Core/Views/SubtitleApi.cs new file mode 100644 index 00000000..784a9022 --- /dev/null +++ b/src/Kyoo.Core/Views/SubtitleApi.cs @@ -0,0 +1,159 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Abstractions.Controllers; +using Kyoo.Abstractions.Models; +using Kyoo.Abstractions.Models.Permissions; +using Microsoft.AspNetCore.Mvc; + +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 GetSubtitle(int id) + { + Track subtitle = await _libraryManager.GetOrDefault(id); + return subtitle != null + ? _files.FileResult(subtitle.Path) + : NotFound(); + } + + [HttpGet("{id:int}.{extension}")] + [Permission(nameof(SubtitleApi), Kind.Read)] + public async Task GetSubtitle(int id, string extension) + { + Track subtitle = await _libraryManager.GetOrDefault(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 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.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 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(string.Empty); + await writer.WriteLineAsync(string.Empty); + + using StreamReader reader = new(await _files.GetReader(_path)); + string line; + while ((line = await reader.ReadLineAsync()) != null) + { + if (line == string.Empty) + { + lines.Add(string.Empty); + IEnumerable 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 _ConvertBlock(IList 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; + } + } + } +} diff --git a/Kyoo.Core/Views/TaskApi.cs b/src/Kyoo.Core/Views/TaskApi.cs similarity index 54% rename from Kyoo.Core/Views/TaskApi.cs rename to src/Kyoo.Core/Views/TaskApi.cs index 4bb5b534..d7b91427 100644 --- a/Kyoo.Core/Views/TaskApi.cs +++ b/src/Kyoo.Core/Views/TaskApi.cs @@ -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 . + +using System; using System.Collections.Generic; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models.Exceptions; @@ -19,14 +37,13 @@ namespace Kyoo.Core.Api _taskManager = taskManager; } - [HttpGet] [Permission(nameof(TaskApi), Kind.Read)] public ActionResult> GetTasks() { return Ok(_taskManager.GetAllTasks()); } - + [HttpGet("{taskSlug}")] [HttpPut("{taskSlug}")] [Permission(nameof(TaskApi), Kind.Create)] @@ -43,7 +60,7 @@ namespace Kyoo.Core.Api } catch (ArgumentException ex) { - return BadRequest(new {Error = ex.Message}); + return BadRequest(new { Error = ex.Message }); } } } diff --git a/Kyoo.Core/Views/TrackApi.cs b/src/Kyoo.Core/Views/TrackApi.cs similarity index 63% rename from Kyoo.Core/Views/TrackApi.cs rename to src/Kyoo.Core/Views/TrackApi.cs index 6d16f632..7075bcbc 100644 --- a/Kyoo.Core/Views/TrackApi.cs +++ b/src/Kyoo.Core/Views/TrackApi.cs @@ -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 . + using System.Linq; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; @@ -37,7 +55,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - + [HttpGet("{slug}/episode")] [PartialPermission(Kind.Read)] public async Task> GetEpisode(string slug) @@ -52,4 +70,4 @@ namespace Kyoo.Core.Api } } } -} \ No newline at end of file +} diff --git a/Kyoo.Core/Views/VideoApi.cs b/src/Kyoo.Core/Views/VideoApi.cs similarity index 78% rename from Kyoo.Core/Views/VideoApi.cs rename to src/Kyoo.Core/Views/VideoApi.cs index b2fa82df..e5c205e4 100644 --- a/Kyoo.Core/Views/VideoApi.cs +++ b/src/Kyoo.Core/Views/VideoApi.cs @@ -1,11 +1,29 @@ -using System.IO; -using Microsoft.AspNetCore.Mvc; +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.IO; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Core.Models.Options; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Options; @@ -20,8 +38,8 @@ namespace Kyoo.Core.Api private readonly IOptions _options; private readonly IFileSystem _files; - public VideoApi(ILibraryManager libraryManager, - ITranscoder transcoder, + public VideoApi(ILibraryManager libraryManager, + ITranscoder transcoder, IOptions options, IFileSystem files) { @@ -40,10 +58,9 @@ namespace Kyoo.Core.Api ctx.HttpContext.Response.Headers.Add("Expires", "0"); } - + // TODO enable the following line, this is disabled since the web app can't use bearers. [Permission("video", Kind.Read)] [HttpGet("{slug}")] [HttpGet("direct/{slug}")] - // TODO enable the following line, this is disabled since the web app can't use bearers. [Permission("video", Kind.Read)] public async Task Direct(string slug) { try @@ -94,8 +111,7 @@ namespace Kyoo.Core.Api return NotFound(); } } - - + [HttpGet("transmux/{episodeLink}/segments/{chunk}")] [Permission("video", Kind.Read)] public IActionResult GetTransmuxedChunk(string episodeLink, string chunk) @@ -104,7 +120,7 @@ namespace Kyoo.Core.Api path = Path.Combine(path, "segments", chunk); return PhysicalFile(path, "video/MP2T"); } - + [HttpGet("transcode/{episodeLink}/segments/{chunk}")] [Permission("video", Kind.Read)] public IActionResult GetTranscodedChunk(string episodeLink, string chunk) @@ -114,4 +130,4 @@ namespace Kyoo.Core.Api return PhysicalFile(path, "video/MP2T"); } } -} \ No newline at end of file +} diff --git a/src/Kyoo.Core/Views/WatchApi.cs b/src/Kyoo.Core/Views/WatchApi.cs new file mode 100644 index 00000000..74dba487 --- /dev/null +++ b/src/Kyoo.Core/Views/WatchApi.cs @@ -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 . + +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> GetWatchItem(string slug) + { + try + { + Episode item = await _libraryManager.Get(slug); + return await WatchItem.FromEpisode(item, _libraryManager); + } + catch (ItemNotFoundException) + { + return NotFound(); + } + } + } +} diff --git a/Kyoo.Core/settings.json b/src/Kyoo.Core/settings.json similarity index 100% rename from Kyoo.Core/settings.json rename to src/Kyoo.Core/settings.json diff --git a/Kyoo.Database/DatabaseContext.cs b/src/Kyoo.Database/DatabaseContext.cs similarity index 92% rename from Kyoo.Database/DatabaseContext.cs rename to src/Kyoo.Database/DatabaseContext.cs index 282cb93c..2b77aa7f 100644 --- a/Kyoo.Database/DatabaseContext.cs +++ b/src/Kyoo.Database/DatabaseContext.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -26,38 +44,47 @@ namespace Kyoo.Database /// All libraries of Kyoo. See . /// public DbSet Libraries { get; set; } + /// /// All collections of Kyoo. See . /// public DbSet Collections { get; set; } + /// /// All shows of Kyoo. See . /// public DbSet Shows { get; set; } + /// /// All seasons of Kyoo. See . /// public DbSet Seasons { get; set; } + /// /// All episodes of Kyoo. See . /// public DbSet Episodes { get; set; } + /// /// All tracks of Kyoo. See . /// public DbSet Tracks { get; set; } + /// /// All genres of Kyoo. See . /// public DbSet Genres { get; set; } + /// /// All people of Kyoo. See . /// public DbSet People { get; set; } + /// /// All studios of Kyoo. See . /// public DbSet Studios { get; set; } + /// /// All providers of Kyoo. See . /// @@ -67,19 +94,19 @@ namespace Kyoo.Database /// The list of registered users. /// public DbSet Users { get; set; } - + /// /// All people's role. See . /// public DbSet PeopleRoles { get; set; } - + /// - /// Episodes with a watch percentage. See + /// Episodes with a watch percentage. See . /// public DbSet WatchedEpisodes { get; set; } - + /// - /// The list of library items (shows and collections that are part of a library - or the global one) + /// The list of library items (shows and collections that are part of a library - or the global one). /// /// /// This set is ready only, on most database this will be a view. @@ -105,6 +132,7 @@ namespace Kyoo.Database /// The ID of the second resource. /// The first resource type of the relation. It is the owner of the second /// The second resource type of the relation. It is the contained resource. + /// A representing the asynchronous operation. public async Task AddLinks(int first, int second) where T1 : class, IResource where T2 : class, IResource @@ -117,7 +145,6 @@ namespace Kyoo.Database }); } - /// /// The default constructor /// @@ -130,7 +157,7 @@ namespace Kyoo.Database protected DatabaseContext(DbContextOptions options) : base(options) { } - + /// /// Get the name of the metadata table of the given type. /// @@ -177,7 +204,7 @@ namespace Kyoo.Database { modelBuilder.SharedTypeEntity(MetadataName()) .HasKey(MetadataID.PrimaryKey); - + modelBuilder.SharedTypeEntity(MetadataName()) .HasOne() .WithMany(x => x.ExternalIDs) @@ -194,7 +221,7 @@ namespace Kyoo.Database /// The second navigation expression from T2 to T /// The owning type of the relationship /// The owned type of the relationship - private void _HasManyToMany(ModelBuilder modelBuilder, + private void _HasManyToMany(ModelBuilder modelBuilder, Expression>> firstNavigation, Expression>> secondNavigation) where T : class, IResource @@ -209,7 +236,7 @@ namespace Kyoo.Database .HasOne() .WithMany() .HasForeignKey(LinkNameFk()) - .OnDelete(DeleteBehavior.Cascade), + .OnDelete(DeleteBehavior.Cascade), x => x .HasOne() .WithMany() @@ -217,8 +244,7 @@ namespace Kyoo.Database .OnDelete(DeleteBehavior.Cascade) ); } - - + /// /// Set database parameters to support every types of Kyoo. /// @@ -257,7 +283,7 @@ namespace Kyoo.Database _HasManyToMany(modelBuilder, x => x.Shows, x => x.Libraries); _HasManyToMany(modelBuilder, x => x.Shows, x => x.Collections); _HasManyToMany(modelBuilder, x => x.Genres, x => x.Shows); - + modelBuilder.Entity() .HasMany(x => x.Watched) .WithMany("Users") @@ -269,7 +295,7 @@ namespace Kyoo.Database _HasMetadata(modelBuilder); _HasMetadata(modelBuilder); _HasMetadata(modelBuilder); - + modelBuilder.Entity() .HasKey(x => new { User = x.UserID, Episode = x.EpisodeID }); @@ -281,7 +307,7 @@ namespace Kyoo.Database modelBuilder.Entity().Property(x => x.Slug).IsRequired(); modelBuilder.Entity().Property(x => x.Slug).IsRequired(); modelBuilder.Entity().Property(x => x.Slug).IsRequired(); - + modelBuilder.Entity() .HasIndex(x => x.Slug) .IsUnique(); @@ -304,19 +330,19 @@ namespace Kyoo.Database .HasIndex(x => x.Slug) .IsUnique(); modelBuilder.Entity() - .HasIndex(x => new {x.ShowID, x.SeasonNumber}) + .HasIndex(x => new { x.ShowID, x.SeasonNumber }) .IsUnique(); modelBuilder.Entity() .HasIndex(x => x.Slug) .IsUnique(); modelBuilder.Entity() - .HasIndex(x => new {x.ShowID, x.SeasonNumber, x.EpisodeNumber, x.AbsoluteNumber}) + .HasIndex(x => new { x.ShowID, x.SeasonNumber, x.EpisodeNumber, x.AbsoluteNumber }) .IsUnique(); modelBuilder.Entity() .HasIndex(x => x.Slug) .IsUnique(); modelBuilder.Entity() - .HasIndex(x => new {x.EpisodeID, x.Type, x.Language, x.TrackIndex, x.IsForced}) + .HasIndex(x => new { x.EpisodeID, x.Type, x.Language, x.TrackIndex, x.IsForced }) .IsUnique(); modelBuilder.Entity() .HasIndex(x => x.Slug) @@ -340,7 +366,7 @@ namespace Kyoo.Database /// Return a new or an in cache temporary object wih the same ID as the one given /// /// If a resource with the same ID is found in the database, it will be used. - /// will be used otherwise + /// will be used otherwise /// The type of the resource /// A resource that is now tracked by this context. public T GetTemporaryObject(T model) @@ -394,7 +420,7 @@ namespace Kyoo.Database throw; } } - + /// /// Save changes that are applied to this context. /// @@ -425,8 +451,8 @@ namespace Kyoo.Database /// A to observe while waiting for the task to complete /// A duplicated item has been found. /// The number of state entries written to the database. - public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, - CancellationToken cancellationToken = new()) + public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, + CancellationToken cancellationToken = default) { try { @@ -447,7 +473,7 @@ namespace Kyoo.Database /// A to observe while waiting for the task to complete /// A duplicated item has been found. /// The number of state entries written to the database. - public override async Task SaveChangesAsync(CancellationToken cancellationToken = new()) + public override async Task SaveChangesAsync(CancellationToken cancellationToken = default) { try { @@ -461,7 +487,7 @@ namespace Kyoo.Database throw; } } - + /// /// Save changes that are applied to this context. /// @@ -471,7 +497,7 @@ namespace Kyoo.Database /// A duplicated item has been found. /// The number of state entries written to the database. public async Task SaveChangesAsync(string duplicateMessage, - CancellationToken cancellationToken = new()) + CancellationToken cancellationToken = default) { try { @@ -492,7 +518,7 @@ namespace Kyoo.Database /// /// A to observe while waiting for the task to complete /// The number of state entries written to the database or -1 if a duplicate exist. - public async Task SaveIfNoDuplicates(CancellationToken cancellationToken = new()) + public async Task SaveIfNoDuplicates(CancellationToken cancellationToken = default) { try { @@ -507,7 +533,7 @@ namespace Kyoo.Database /// /// Return the first resource with the given slug that is currently tracked by this context. /// This allow one to limit redundant calls to during the - /// same transaction and prevent fails from EF when two same entities are being tracked. + /// same transaction and prevent fails from EF when two same entities are being tracked. /// /// The slug of the resource to check /// The type of entity to check @@ -531,14 +557,14 @@ namespace Kyoo.Database /// /// Delete every changes that are on this context. /// - private void DiscardChanges() + public void DiscardChanges() { foreach (EntityEntry entry in ChangeTracker.Entries().Where(x => x.State != EntityState.Detached)) { entry.State = EntityState.Detached; } } - + /// /// Perform a case insensitive like operation. /// @@ -548,4 +574,4 @@ namespace Kyoo.Database /// An expression representing the like query. It can directly be passed to a where call. public abstract Expression> Like(Expression> query, string format); } -} \ No newline at end of file +} diff --git a/Kyoo.Database/Extensions.cs b/src/Kyoo.Database/Extensions.cs similarity index 61% rename from Kyoo.Database/Extensions.cs rename to src/Kyoo.Database/Extensions.cs index 57c72417..93afb00c 100644 --- a/Kyoo.Database/Extensions.cs +++ b/src/Kyoo.Database/Extensions.cs @@ -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 . + using System.Data.Common; using Microsoft.Extensions.Configuration; @@ -22,7 +40,7 @@ namespace Kyoo.Database builder[child.Key] = child.Value; return builder.ConnectionString; } - + /// /// Get the name of the selected database. /// @@ -33,4 +51,4 @@ namespace Kyoo.Database return config.GetValue("database:enabled"); } } -} \ No newline at end of file +} diff --git a/Kyoo.Database/Kyoo.Database.csproj b/src/Kyoo.Database/Kyoo.Database.csproj similarity index 91% rename from Kyoo.Database/Kyoo.Database.csproj rename to src/Kyoo.Database/Kyoo.Database.csproj index 9a64194a..a8fd3c51 100644 --- a/Kyoo.Database/Kyoo.Database.csproj +++ b/src/Kyoo.Database/Kyoo.Database.csproj @@ -1,4 +1,4 @@ - + net5.0 @@ -6,7 +6,6 @@ Kyoo.Database Zoe Roux https://github.com/AnonymusRaccoon/Kyoo - Library default diff --git a/Kyoo.Host.Console/Kyoo.Host.Console.csproj b/src/Kyoo.Host.Console/Kyoo.Host.Console.csproj similarity index 100% rename from Kyoo.Host.Console/Kyoo.Host.Console.csproj rename to src/Kyoo.Host.Console/Kyoo.Host.Console.csproj diff --git a/src/Kyoo.Host.Console/Program.cs b/src/Kyoo.Host.Console/Program.cs new file mode 100644 index 00000000..e90bd4d4 --- /dev/null +++ b/src/Kyoo.Host.Console/Program.cs @@ -0,0 +1,50 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.Threading.Tasks; +using Kyoo.Core; +using Microsoft.AspNetCore.Hosting; + +namespace Kyoo.Host.Console +{ + /// + /// Program entrypoint. + /// + public static class Program + { + /// + /// The string representation of the environment used in . + /// +#if DEBUG + private const string Environment = "Development"; +#else + private const string Environment = "Production"; +#endif + + /// + /// Main function of the program + /// + /// Command line arguments + /// A representing the lifetime of the program. + public static Task Main(string[] args) + { + Application application = new(Environment); + return application.Start(args); + } + } +} diff --git a/src/Kyoo.Host.Console/Properties/launchSettings.json b/src/Kyoo.Host.Console/Properties/launchSettings.json new file mode 100644 index 00000000..53ae9e22 --- /dev/null +++ b/src/Kyoo.Host.Console/Properties/launchSettings.json @@ -0,0 +1,20 @@ +{ + "profiles": { + "Console Host": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "KYOO_DATADIR": "./bin/KyooData" + }, + "applicationUrl": "http://localhost:5000" + }, + "Console Host (Browser)": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "KYOO_DATADIR": "./bin/KyooData" + }, + "applicationUrl": "http://localhost:5000" + } + } +} diff --git a/src/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.Skipped.target b/src/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.Skipped.target new file mode 100644 index 00000000..62ab4d53 --- /dev/null +++ b/src/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.Skipped.target @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.target b/src/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.csproj similarity index 50% rename from Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.target rename to src/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.csproj index d0f97e34..084b6541 100644 --- a/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.target +++ b/src/Kyoo.Host.WindowsTrait/Kyoo.Host.WindowsTrait.csproj @@ -1,24 +1,31 @@ - - + + - + WinExe net5.0-windows true Kyoo.WindowsHost - - + - - - + PreserveNewest + + + net5.0 + NU1503 + + + + + + + + diff --git a/src/Kyoo.Host.WindowsTrait/Program.cs b/src/Kyoo.Host.WindowsTrait/Program.cs new file mode 100644 index 00000000..dc194d2d --- /dev/null +++ b/src/Kyoo.Host.WindowsTrait/Program.cs @@ -0,0 +1,52 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.Threading.Tasks; +using Autofac; +using Kyoo.Core; + +namespace Kyoo.Host.WindowsTrait +{ + public static class Program + { + /// + /// The string representation of the environment used in IWebHostEnvironment. + /// +#if DEBUG + private const string Environment = "Development"; +#else + private const string Environment = "Production"; +#endif + + /// + /// 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. + /// + /// Command line arguments + /// A representing the lifetime of the program. + public static Task Main(string[] args) + { + Application application = new(Environment); + return application.Start(args, builder => + { + builder.RegisterType().As().SingleInstance(); + }); + } + } +} diff --git a/Kyoo.Host.WindowsTrait/SystemTrait.cs b/src/Kyoo.Host.WindowsTrait/SystemTrait.cs similarity index 77% rename from Kyoo.Host.WindowsTrait/SystemTrait.cs rename to src/Kyoo.Host.WindowsTrait/SystemTrait.cs index 34708f86..14ea12d4 100644 --- a/Kyoo.Host.WindowsTrait/SystemTrait.cs +++ b/src/Kyoo.Host.WindowsTrait/SystemTrait.cs @@ -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 . + +using System; using System.Diagnostics; using System.Drawing; using System.IO; @@ -25,13 +43,12 @@ namespace Kyoo.Host.WindowsTrait /// The options containing the . /// private readonly IOptions _options; - + /// /// The thread where the trait is running. /// private Thread _thread; - - + /// /// Create a new . /// @@ -42,7 +59,7 @@ namespace Kyoo.Host.WindowsTrait _application = application; _options = options; } - + /// public void Start() { @@ -56,7 +73,7 @@ namespace Kyoo.Host.WindowsTrait /// public void Dispose() { - System.Windows.Forms.Application.Exit(); + Application.Exit(); _thread?.Join(); _thread = null; } @@ -73,12 +90,12 @@ namespace Kyoo.Host.WindowsTrait private readonly IApplication _application; /// - /// The options containing the . - /// + /// The options containing the . + /// private readonly IOptions _options; - + /// - /// The Icon that is displayed in the window's bar. + /// The Icon that is displayed in the window's bar. /// private readonly NotifyIcon _icon; @@ -93,12 +110,14 @@ namespace Kyoo.Host.WindowsTrait _options = options; AppDomain.CurrentDomain.ProcessExit += (_, _) => Dispose(); - System.Windows.Forms.Application.ApplicationExit += (_, _) => Dispose(); + Application.ApplicationExit += (_, _) => Dispose(); - _icon = new NotifyIcon(); - _icon.Text = "Kyoo"; - _icon.Icon = new Icon(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "kyoo.ico")); - _icon.Visible = true; + _icon = new NotifyIcon + { + Text = "Kyoo", + Icon = new Icon(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "kyoo.ico")), + Visible = true + }; _icon.MouseClick += (_, e) => { if (e.Button != MouseButtons.Left) @@ -124,7 +143,7 @@ namespace Kyoo.Host.WindowsTrait public static void Run(IApplication application, IOptions options) { using InternalSystemTrait trait = new(application, options); - System.Windows.Forms.Application.Run(trait); + Application.Run(trait); } /// @@ -160,4 +179,4 @@ namespace Kyoo.Host.WindowsTrait } } } -} \ No newline at end of file +} diff --git a/Kyoo.Host.WindowsTrait/kyoo.ico b/src/Kyoo.Host.WindowsTrait/kyoo.ico similarity index 99% rename from Kyoo.Host.WindowsTrait/kyoo.ico rename to src/Kyoo.Host.WindowsTrait/kyoo.ico index 61e16024..8bfcd8c3 100644 Binary files a/Kyoo.Host.WindowsTrait/kyoo.ico and b/src/Kyoo.Host.WindowsTrait/kyoo.ico differ diff --git a/Kyoo.Postgresql/Kyoo.Postgresql.csproj b/src/Kyoo.Postgresql/Kyoo.Postgresql.csproj similarity index 100% rename from Kyoo.Postgresql/Kyoo.Postgresql.csproj rename to src/Kyoo.Postgresql/Kyoo.Postgresql.csproj diff --git a/Kyoo.Postgresql/Migrations/20210801171613_Initial.Designer.cs b/src/Kyoo.Postgresql/Migrations/20210801171613_Initial.Designer.cs similarity index 99% rename from Kyoo.Postgresql/Migrations/20210801171613_Initial.Designer.cs rename to src/Kyoo.Postgresql/Migrations/20210801171613_Initial.Designer.cs index 958d1951..0f7db480 100644 --- a/Kyoo.Postgresql/Migrations/20210801171613_Initial.Designer.cs +++ b/src/Kyoo.Postgresql/Migrations/20210801171613_Initial.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using System.Collections.Generic; using Kyoo.Abstractions.Models; diff --git a/src/Kyoo.Postgresql/Migrations/20210801171613_Initial.cs b/src/Kyoo.Postgresql/Migrations/20210801171613_Initial.cs new file mode 100644 index 00000000..47e1e42e --- /dev/null +++ b/src/Kyoo.Postgresql/Migrations/20210801171613_Initial.cs @@ -0,0 +1,864 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System; +using System.Collections.Generic; +using Kyoo.Abstractions.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(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: false), + name = table.Column(type: "text", nullable: true), + images = table.Column>(type: "jsonb", nullable: true), + overview = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_collections", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "genres", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: false), + name = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_genres", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "libraries", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: false), + name = table.Column(type: "text", nullable: true), + paths = table.Column(type: "text[]", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_libraries", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "people", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: false), + name = table.Column(type: "text", nullable: true), + images = table.Column>(type: "jsonb", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_people", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "providers", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: false), + name = table.Column(type: "text", nullable: true), + images = table.Column>(type: "jsonb", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_providers", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "studios", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: false), + name = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_studios", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "users", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: false), + username = table.Column(type: "text", nullable: true), + email = table.Column(type: "text", nullable: true), + password = table.Column(type: "text", nullable: true), + permissions = table.Column(type: "text[]", nullable: true), + extra_data = table.Column>(type: "jsonb", nullable: true), + images = table.Column>(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(type: "integer", nullable: false), + library_id = table.Column(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(type: "integer", nullable: false), + provider_id = table.Column(type: "integer", nullable: false), + data_id = table.Column(type: "text", nullable: true), + link = table.Column(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(type: "integer", nullable: false), + provider_id = table.Column(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(type: "integer", nullable: false), + provider_id = table.Column(type: "integer", nullable: false), + data_id = table.Column(type: "text", nullable: true), + link = table.Column(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(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: false), + title = table.Column(type: "text", nullable: true), + aliases = table.Column(type: "text[]", nullable: true), + path = table.Column(type: "text", nullable: true), + overview = table.Column(type: "text", nullable: true), + status = table.Column(type: "status", nullable: false), + start_air = table.Column(type: "timestamp without time zone", nullable: true), + end_air = table.Column(type: "timestamp without time zone", nullable: true), + images = table.Column>(type: "jsonb", nullable: true), + is_movie = table.Column(type: "boolean", nullable: false), + studio_id = table.Column(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(type: "integer", nullable: false), + provider_id = table.Column(type: "integer", nullable: false), + data_id = table.Column(type: "text", nullable: true), + link = table.Column(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(type: "integer", nullable: false), + show_id = table.Column(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(type: "integer", nullable: false), + show_id = table.Column(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(type: "integer", nullable: false), + show_id = table.Column(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(type: "integer", nullable: false), + watched_id = table.Column(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(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + people_id = table.Column(type: "integer", nullable: false), + show_id = table.Column(type: "integer", nullable: false), + type = table.Column(type: "text", nullable: true), + role = table.Column(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(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: true), + show_id = table.Column(type: "integer", nullable: false), + season_number = table.Column(type: "integer", nullable: false), + title = table.Column(type: "text", nullable: true), + overview = table.Column(type: "text", nullable: true), + start_date = table.Column(type: "timestamp without time zone", nullable: true), + end_date = table.Column(type: "timestamp without time zone", nullable: true), + images = table.Column>(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(type: "integer", nullable: false), + provider_id = table.Column(type: "integer", nullable: false), + data_id = table.Column(type: "text", nullable: true), + link = table.Column(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(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: true), + show_id = table.Column(type: "integer", nullable: false), + season_id = table.Column(type: "integer", nullable: true), + season_number = table.Column(type: "integer", nullable: true), + episode_number = table.Column(type: "integer", nullable: true), + absolute_number = table.Column(type: "integer", nullable: true), + path = table.Column(type: "text", nullable: true), + images = table.Column>(type: "jsonb", nullable: true), + title = table.Column(type: "text", nullable: true), + overview = table.Column(type: "text", nullable: true), + release_date = table.Column(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(type: "integer", nullable: false), + provider_id = table.Column(type: "integer", nullable: false), + data_id = table.Column(type: "text", nullable: true), + link = table.Column(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(type: "integer", nullable: false), + provider_id = table.Column(type: "integer", nullable: false), + data_id = table.Column(type: "text", nullable: true), + link = table.Column(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(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + slug = table.Column(type: "text", nullable: true), + title = table.Column(type: "text", nullable: true), + language = table.Column(type: "text", nullable: true), + codec = table.Column(type: "text", nullable: true), + is_default = table.Column(type: "boolean", nullable: false), + is_forced = table.Column(type: "boolean", nullable: false), + is_external = table.Column(type: "boolean", nullable: false), + path = table.Column(type: "text", nullable: true), + type = table.Column(type: "stream_type", nullable: false), + episode_id = table.Column(type: "integer", nullable: false), + track_index = table.Column(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(type: "integer", nullable: false), + episode_id = table.Column(type: "integer", nullable: false), + watched_percentage = table.Column(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"); + } + } +} diff --git a/Kyoo.Postgresql/Migrations/20210801171641_Triggers.Designer.cs b/src/Kyoo.Postgresql/Migrations/20210801171641_Triggers.Designer.cs similarity index 99% rename from Kyoo.Postgresql/Migrations/20210801171641_Triggers.Designer.cs rename to src/Kyoo.Postgresql/Migrations/20210801171641_Triggers.Designer.cs index 02738ac0..51d369e9 100644 --- a/Kyoo.Postgresql/Migrations/20210801171641_Triggers.Designer.cs +++ b/src/Kyoo.Postgresql/Migrations/20210801171641_Triggers.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using System.Collections.Generic; using Kyoo.Abstractions.Models; diff --git a/Kyoo.Postgresql/Migrations/20210801171641_Triggers.cs b/src/Kyoo.Postgresql/Migrations/20210801171641_Triggers.cs similarity index 87% rename from Kyoo.Postgresql/Migrations/20210801171641_Triggers.cs rename to src/Kyoo.Postgresql/Migrations/20210801171641_Triggers.cs index 6ee2961c..c1723610 100644 --- a/Kyoo.Postgresql/Migrations/20210801171641_Triggers.cs +++ b/src/Kyoo.Postgresql/Migrations/20210801171641_Triggers.cs @@ -1,4 +1,22 @@ -using Microsoft.EntityFrameworkCore.Migrations; +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using Microsoft.EntityFrameworkCore.Migrations; namespace Kyoo.Postgresql.Migrations { @@ -21,13 +39,12 @@ namespace Kyoo.Postgresql.Migrations RETURN NEW; END $$;"); - + // language=PostgreSQL migrationBuilder.Sql(@" CREATE TRIGGER season_slug_trigger BEFORE INSERT OR UPDATE OF season_number, show_id ON seasons FOR EACH ROW EXECUTE PROCEDURE season_slug_update();"); - - + // language=PostgreSQL migrationBuilder.Sql(@" CREATE FUNCTION episode_slug_update() @@ -46,14 +63,13 @@ namespace Kyoo.Postgresql.Migrations RETURN NEW; END $$;"); - + // language=PostgreSQL migrationBuilder.Sql(@" CREATE TRIGGER episode_slug_trigger BEFORE INSERT OR UPDATE OF absolute_number, episode_number, season_number, show_id ON episodes FOR EACH ROW EXECUTE PROCEDURE episode_slug_update();"); - // language=PostgreSQL migrationBuilder.Sql(@" CREATE FUNCTION show_slug_update() @@ -74,7 +90,7 @@ namespace Kyoo.Postgresql.Migrations migrationBuilder.Sql(@" CREATE TRIGGER show_slug_trigger AFTER UPDATE OF slug ON shows FOR EACH ROW EXECUTE PROCEDURE show_slug_update();"); - + // language=PostgreSQL migrationBuilder.Sql(@" CREATE FUNCTION episode_update_tracks_slug() @@ -102,7 +118,7 @@ namespace Kyoo.Postgresql.Migrations migrationBuilder.Sql(@" CREATE TRIGGER episode_track_slug_trigger AFTER UPDATE OF slug ON episodes FOR EACH ROW EXECUTE PROCEDURE episode_update_tracks_slug();"); - + // language=PostgreSQL migrationBuilder.Sql(@" CREATE FUNCTION track_slug_update() @@ -137,7 +153,6 @@ namespace Kyoo.Postgresql.Migrations BEFORE INSERT OR UPDATE OF episode_id, is_forced, language, track_index, type ON tracks FOR EACH ROW EXECUTE PROCEDURE track_slug_update();"); - // language=PostgreSQL migrationBuilder.Sql(@" CREATE VIEW library_items AS @@ -183,4 +198,4 @@ namespace Kyoo.Postgresql.Migrations migrationBuilder.Sql(@"DROP VIEW library_items;"); } } -} \ No newline at end of file +} diff --git a/Kyoo.Postgresql/Migrations/PostgresContextModelSnapshot.cs b/src/Kyoo.Postgresql/Migrations/PostgresContextModelSnapshot.cs similarity index 99% rename from Kyoo.Postgresql/Migrations/PostgresContextModelSnapshot.cs rename to src/Kyoo.Postgresql/Migrations/PostgresContextModelSnapshot.cs index a3b33778..94f265f1 100644 --- a/Kyoo.Postgresql/Migrations/PostgresContextModelSnapshot.cs +++ b/src/Kyoo.Postgresql/Migrations/PostgresContextModelSnapshot.cs @@ -1,4 +1,4 @@ -// +// using System; using System.Collections.Generic; using Kyoo.Abstractions.Models; diff --git a/Kyoo.Postgresql/PostgresContext.cs b/src/Kyoo.Postgresql/PostgresContext.cs similarity index 84% rename from Kyoo.Postgresql/PostgresContext.cs rename to src/Kyoo.Postgresql/PostgresContext.cs index c8477169..ee29d437 100644 --- a/Kyoo.Postgresql/PostgresContext.cs +++ b/src/Kyoo.Postgresql/PostgresContext.cs @@ -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 . + using System; using System.Globalization; using System.Linq.Expressions; @@ -31,14 +49,13 @@ namespace Kyoo.Postgresql /// private readonly bool _skipConfigure; - static PostgresContext() { NpgsqlConnection.GlobalTypeMapper.MapEnum(); NpgsqlConnection.GlobalTypeMapper.MapEnum(); NpgsqlConnection.GlobalTypeMapper.MapEnum(); } - + /// /// A basic constructor that set default values (query tracker behaviors, mapping enums...) /// @@ -102,7 +119,7 @@ namespace Kyoo.Postgresql modelBuilder.Entity() .Property(x => x.ExtraData) .HasColumnType("jsonb"); - + modelBuilder.Entity() .Property(x => x.Images) .HasColumnType("jsonb"); @@ -127,7 +144,7 @@ namespace Kyoo.Postgresql modelBuilder.Entity() .Property(x => x.Images) .HasColumnType("jsonb"); - + base.OnModelCreating(modelBuilder); } @@ -137,14 +154,14 @@ namespace Kyoo.Postgresql SnakeCaseNameRewriter rewriter = new(CultureInfo.InvariantCulture); return rewriter.RewriteName(typeof(T).Name + nameof(MetadataID)); } - + /// protected override string LinkName() { SnakeCaseNameRewriter rewriter = new(CultureInfo.InvariantCulture); return rewriter.RewriteName("Link" + typeof(T).Name + typeof(T2).Name); } - + /// protected override string LinkNameFk() { @@ -155,7 +172,7 @@ namespace Kyoo.Postgresql /// protected override bool IsDuplicateException(Exception ex) { - return ex.InnerException is PostgresException {SqlState: PostgresErrorCodes.UniqueViolation}; + return ex.InnerException is PostgresException { SqlState: PostgresErrorCodes.UniqueViolation }; } /// @@ -167,4 +184,4 @@ namespace Kyoo.Postgresql return Expression.Lambda>(call, query.Parameters); } } -} \ No newline at end of file +} diff --git a/Kyoo.Postgresql/PostgresModule.cs b/src/Kyoo.Postgresql/PostgresModule.cs similarity index 74% rename from Kyoo.Postgresql/PostgresModule.cs rename to src/Kyoo.Postgresql/PostgresModule.cs index 295faf96..ebe200eb 100644 --- a/Kyoo.Postgresql/PostgresModule.cs +++ b/src/Kyoo.Postgresql/PostgresModule.cs @@ -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 . + +using System; using System.Collections.Generic; using Kyoo.Abstractions.Controllers; using Kyoo.Database; @@ -24,7 +42,7 @@ namespace Kyoo.Postgresql /// public string Description => "A database context for postgresql."; - + /// public Dictionary Configuration => new(); @@ -51,7 +69,7 @@ namespace Kyoo.Postgresql _configuration = configuration; _environment = env; } - + /// public void Configure(IServiceCollection services) { @@ -74,4 +92,4 @@ namespace Kyoo.Postgresql conn.ReloadTypes(); } } -} \ No newline at end of file +} diff --git a/Kyoo.SqLite/Kyoo.SqLite.csproj b/src/Kyoo.SqLite/Kyoo.SqLite.csproj similarity index 100% rename from Kyoo.SqLite/Kyoo.SqLite.csproj rename to src/Kyoo.SqLite/Kyoo.SqLite.csproj diff --git a/Kyoo.SqLite/Migrations/20210801171534_Initial.Designer.cs b/src/Kyoo.SqLite/Migrations/20210801171534_Initial.Designer.cs similarity index 99% rename from Kyoo.SqLite/Migrations/20210801171534_Initial.Designer.cs rename to src/Kyoo.SqLite/Migrations/20210801171534_Initial.Designer.cs index 0443a20d..d01507a7 100644 --- a/Kyoo.SqLite/Migrations/20210801171534_Initial.Designer.cs +++ b/src/Kyoo.SqLite/Migrations/20210801171534_Initial.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using Kyoo.SqLite; using Microsoft.EntityFrameworkCore; diff --git a/src/Kyoo.SqLite/Migrations/20210801171534_Initial.cs b/src/Kyoo.SqLite/Migrations/20210801171534_Initial.cs new file mode 100644 index 00000000..ee965602 --- /dev/null +++ b/src/Kyoo.SqLite/Migrations/20210801171534_Initial.cs @@ -0,0 +1,856 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System; +using 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(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true), + Images = table.Column(type: "TEXT", nullable: true), + Overview = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Collections", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Genres", + columns: table => new + { + ID = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Genres", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Libraries", + columns: table => new + { + ID = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true), + Paths = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Libraries", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "People", + columns: table => new + { + ID = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true), + Images = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_People", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Providers", + columns: table => new + { + ID = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true), + Images = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Providers", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Studios", + columns: table => new + { + ID = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Studios", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + ID = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: false), + Username = table.Column(type: "TEXT", nullable: true), + Email = table.Column(type: "TEXT", nullable: true), + Password = table.Column(type: "TEXT", nullable: true), + Permissions = table.Column(type: "TEXT", nullable: true), + ExtraData = table.Column(type: "TEXT", nullable: true), + Images = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "LinkLibraryCollection", + columns: table => new + { + CollectionID = table.Column(type: "INTEGER", nullable: false), + LibraryID = table.Column(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(type: "INTEGER", nullable: false), + ProviderID = table.Column(type: "INTEGER", nullable: false), + DataID = table.Column(type: "TEXT", nullable: true), + Link = table.Column(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(type: "INTEGER", nullable: false), + ProviderID = table.Column(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(type: "INTEGER", nullable: false), + ProviderID = table.Column(type: "INTEGER", nullable: false), + DataID = table.Column(type: "TEXT", nullable: true), + Link = table.Column(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(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: false), + Title = table.Column(type: "TEXT", nullable: true), + Aliases = table.Column(type: "TEXT", nullable: true), + Path = table.Column(type: "TEXT", nullable: true), + Overview = table.Column(type: "TEXT", nullable: true), + Status = table.Column(type: "INTEGER", nullable: false), + StartAir = table.Column(type: "TEXT", nullable: true), + EndAir = table.Column(type: "TEXT", nullable: true), + Images = table.Column(type: "TEXT", nullable: true), + IsMovie = table.Column(type: "INTEGER", nullable: false), + StudioID = table.Column(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(type: "INTEGER", nullable: false), + ProviderID = table.Column(type: "INTEGER", nullable: false), + DataID = table.Column(type: "TEXT", nullable: true), + Link = table.Column(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(type: "INTEGER", nullable: false), + ShowID = table.Column(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(type: "INTEGER", nullable: false), + ShowID = table.Column(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(type: "INTEGER", nullable: false), + ShowID = table.Column(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(type: "INTEGER", nullable: false), + WatchedID = table.Column(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(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PeopleID = table.Column(type: "INTEGER", nullable: false), + ShowID = table.Column(type: "INTEGER", nullable: false), + Type = table.Column(type: "TEXT", nullable: true), + Role = table.Column(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(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: true), + ShowID = table.Column(type: "INTEGER", nullable: false), + SeasonNumber = table.Column(type: "INTEGER", nullable: false), + Title = table.Column(type: "TEXT", nullable: true), + Overview = table.Column(type: "TEXT", nullable: true), + StartDate = table.Column(type: "TEXT", nullable: true), + EndDate = table.Column(type: "TEXT", nullable: true), + Images = table.Column(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(type: "INTEGER", nullable: false), + ProviderID = table.Column(type: "INTEGER", nullable: false), + DataID = table.Column(type: "TEXT", nullable: true), + Link = table.Column(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(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: true), + ShowID = table.Column(type: "INTEGER", nullable: false), + SeasonID = table.Column(type: "INTEGER", nullable: true), + SeasonNumber = table.Column(type: "INTEGER", nullable: true), + EpisodeNumber = table.Column(type: "INTEGER", nullable: true), + AbsoluteNumber = table.Column(type: "INTEGER", nullable: true), + Path = table.Column(type: "TEXT", nullable: true), + Images = table.Column(type: "TEXT", nullable: true), + Title = table.Column(type: "TEXT", nullable: true), + Overview = table.Column(type: "TEXT", nullable: true), + ReleaseDate = table.Column(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(type: "INTEGER", nullable: false), + ProviderID = table.Column(type: "INTEGER", nullable: false), + DataID = table.Column(type: "TEXT", nullable: true), + Link = table.Column(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(type: "INTEGER", nullable: false), + ProviderID = table.Column(type: "INTEGER", nullable: false), + DataID = table.Column(type: "TEXT", nullable: true), + Link = table.Column(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(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Slug = table.Column(type: "TEXT", nullable: true), + Title = table.Column(type: "TEXT", nullable: true), + Language = table.Column(type: "TEXT", nullable: true), + Codec = table.Column(type: "TEXT", nullable: true), + IsDefault = table.Column(type: "INTEGER", nullable: false), + IsForced = table.Column(type: "INTEGER", nullable: false), + IsExternal = table.Column(type: "INTEGER", nullable: false), + Path = table.Column(type: "TEXT", nullable: true), + Type = table.Column(type: "INTEGER", nullable: false), + EpisodeID = table.Column(type: "INTEGER", nullable: false), + TrackIndex = table.Column(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(type: "INTEGER", nullable: false), + EpisodeID = table.Column(type: "INTEGER", nullable: false), + WatchedPercentage = table.Column(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"); + } + } +} diff --git a/Kyoo.SqLite/Migrations/20210801171544_Triggers.Designer.cs b/src/Kyoo.SqLite/Migrations/20210801171544_Triggers.Designer.cs similarity index 99% rename from Kyoo.SqLite/Migrations/20210801171544_Triggers.Designer.cs rename to src/Kyoo.SqLite/Migrations/20210801171544_Triggers.Designer.cs index 05c1c174..0ca18ed6 100644 --- a/Kyoo.SqLite/Migrations/20210801171544_Triggers.Designer.cs +++ b/src/Kyoo.SqLite/Migrations/20210801171544_Triggers.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using Kyoo.SqLite; using Microsoft.EntityFrameworkCore; diff --git a/Kyoo.SqLite/Migrations/20210801171544_Triggers.cs b/src/Kyoo.SqLite/Migrations/20210801171544_Triggers.cs similarity index 87% rename from Kyoo.SqLite/Migrations/20210801171544_Triggers.cs rename to src/Kyoo.SqLite/Migrations/20210801171544_Triggers.cs index 789bc182..bbb1cc92 100644 --- a/Kyoo.SqLite/Migrations/20210801171544_Triggers.cs +++ b/src/Kyoo.SqLite/Migrations/20210801171544_Triggers.cs @@ -1,4 +1,22 @@ -using Microsoft.EntityFrameworkCore.Migrations; +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using Microsoft.EntityFrameworkCore.Migrations; namespace Kyoo.SqLite.Migrations { @@ -20,7 +38,7 @@ namespace Kyoo.SqLite.Migrations UPDATE Seasons SET Slug = (SELECT Slug from Shows WHERE ID = ShowID) || '-s' || SeasonNumber WHERE ID == new.ID; END"); - + // language=SQLite migrationBuilder.Sql(@" CREATE TRIGGER EpisodeSlugInsert AFTER INSERT ON Episodes FOR EACH ROW @@ -134,7 +152,6 @@ namespace Kyoo.SqLite.Migrations WHERE EpisodeID = NEW.ID; END;"); - // language=SQLite migrationBuilder.Sql(@" CREATE TRIGGER ShowSlugUpdate AFTER UPDATE OF Slug ON Shows FOR EACH ROW @@ -149,8 +166,7 @@ namespace Kyoo.SqLite.Migrations END WHERE ShowID = new.ID; END;"); - - + // language=SQLite migrationBuilder.Sql(@" CREATE VIEW LibraryItems AS @@ -184,4 +200,4 @@ namespace Kyoo.SqLite.Migrations migrationBuilder.Sql("DROP TRIGGER ShowSlugUpdate;"); } } -} \ No newline at end of file +} diff --git a/Kyoo.SqLite/Migrations/SqLiteContextModelSnapshot.cs b/src/Kyoo.SqLite/Migrations/SqLiteContextModelSnapshot.cs similarity index 99% rename from Kyoo.SqLite/Migrations/SqLiteContextModelSnapshot.cs rename to src/Kyoo.SqLite/Migrations/SqLiteContextModelSnapshot.cs index 50c96524..c70f4f42 100644 --- a/Kyoo.SqLite/Migrations/SqLiteContextModelSnapshot.cs +++ b/src/Kyoo.SqLite/Migrations/SqLiteContextModelSnapshot.cs @@ -1,4 +1,4 @@ -// +// using System; using Kyoo.SqLite; using Microsoft.EntityFrameworkCore; diff --git a/Kyoo.SqLite/SqLiteContext.cs b/src/Kyoo.SqLite/SqLiteContext.cs similarity index 86% rename from Kyoo.SqLite/SqLiteContext.cs rename to src/Kyoo.SqLite/SqLiteContext.cs index 87aa5637..a19151bf 100644 --- a/Kyoo.SqLite/SqLiteContext.cs +++ b/src/Kyoo.SqLite/SqLiteContext.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq.Expressions; @@ -96,7 +114,7 @@ namespace Kyoo.SqLite modelBuilder.Entity() .Property(x => x.Permissions) .HasConversion(arrayConvertor); - + modelBuilder.Entity() .Property(x => x.Status) .HasConversion(); @@ -110,7 +128,7 @@ namespace Kyoo.SqLite modelBuilder.Entity() .Property(x => x.ExtraData) .HasConversion(extraDataConvertor); - + ValueConverter, string> jsonConvertor = new( x => JsonConvert.SerializeObject(x), x => JsonConvert.DeserializeObject>(x)); @@ -138,8 +156,7 @@ namespace Kyoo.SqLite modelBuilder.Entity() .Property(x => x.Images) .HasConversion(jsonConvertor); - - + modelBuilder.Entity() .ToView("LibraryItems") .HasKey(x => x.ID); @@ -151,13 +168,13 @@ namespace Kyoo.SqLite { return typeof(T).Name + nameof(MetadataID); } - + /// protected override string LinkName() { return "Link" + typeof(T).Name + typeof(T2).Name; } - + /// protected override string LinkNameFk() { @@ -167,8 +184,8 @@ namespace Kyoo.SqLite /// protected override bool IsDuplicateException(Exception ex) { - return ex.InnerException is SqliteException { SqliteExtendedErrorCode: 2067 /*SQLITE_CONSTRAINT_UNIQUE*/} - or SqliteException { SqliteExtendedErrorCode: 1555 /*SQLITE_CONSTRAINT_PRIMARYKEY*/}; + return ex.InnerException is SqliteException { SqliteExtendedErrorCode: 2067 /* SQLITE_CONSTRAINT_UNIQUE */ } + or SqliteException { SqliteExtendedErrorCode: 1555 /* SQLITE_CONSTRAINT_PRIMARYKEY */ }; } /// @@ -180,4 +197,4 @@ namespace Kyoo.SqLite return Expression.Lambda>(call, query.Parameters); } } -} \ No newline at end of file +} diff --git a/Kyoo.SqLite/SqLiteModule.cs b/src/Kyoo.SqLite/SqLiteModule.cs similarity index 73% rename from Kyoo.SqLite/SqLiteModule.cs rename to src/Kyoo.SqLite/SqLiteModule.cs index 9a1dc76b..90b741c4 100644 --- a/Kyoo.SqLite/SqLiteModule.cs +++ b/src/Kyoo.SqLite/SqLiteModule.cs @@ -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 . + +using System; using System.Collections.Generic; using Kyoo.Abstractions.Controllers; using Kyoo.Database; @@ -23,14 +41,13 @@ namespace Kyoo.SqLite /// public string Description => "A database context for sqlite."; - + /// public Dictionary Configuration => new(); - + /// public bool Enabled => _configuration.GetSelectedDatabase() == "sqlite"; - /// /// The configuration to use. The database connection string is pulled from it. /// @@ -52,7 +69,6 @@ namespace Kyoo.SqLite _environment = env; } - /// public void Configure(IServiceCollection services) { @@ -71,4 +87,4 @@ namespace Kyoo.SqLite context.Database.Migrate(); } } -} \ No newline at end of file +} diff --git a/Kyoo.TheMovieDb/Convertors/CollectionConvertors.cs b/src/Kyoo.TheMovieDb/Convertors/CollectionConvertors.cs similarity index 75% rename from Kyoo.TheMovieDb/Convertors/CollectionConvertors.cs rename to src/Kyoo.TheMovieDb/Convertors/CollectionConvertors.cs index 47c88f41..de9718a2 100644 --- a/Kyoo.TheMovieDb/Convertors/CollectionConvertors.cs +++ b/src/Kyoo.TheMovieDb/Convertors/CollectionConvertors.cs @@ -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 . + using System.Collections.Generic; using Kyoo.Abstractions.Models; using Kyoo.Utils; @@ -32,7 +50,7 @@ namespace Kyoo.TheMovieDb ? $"https://image.tmdb.org/t/p/original{collection.BackdropPath}" : null }, - ExternalIDs = new [] + ExternalIDs = new[] { new MetadataID { @@ -43,7 +61,7 @@ namespace Kyoo.TheMovieDb } }; } - + /// /// Convert a into a . /// @@ -65,7 +83,7 @@ namespace Kyoo.TheMovieDb ? $"https://image.tmdb.org/t/p/original{collection.BackdropPath}" : null }, - ExternalIDs = new [] + ExternalIDs = new[] { new MetadataID { @@ -77,4 +95,4 @@ namespace Kyoo.TheMovieDb }; } } -} \ No newline at end of file +} diff --git a/Kyoo.TheMovieDb/Convertors/EpisodeConvertors.cs b/src/Kyoo.TheMovieDb/Convertors/EpisodeConvertors.cs similarity index 61% rename from Kyoo.TheMovieDb/Convertors/EpisodeConvertors.cs rename to src/Kyoo.TheMovieDb/Convertors/EpisodeConvertors.cs index efee43df..76fbaa7c 100644 --- a/Kyoo.TheMovieDb/Convertors/EpisodeConvertors.cs +++ b/src/Kyoo.TheMovieDb/Convertors/EpisodeConvertors.cs @@ -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 . + using System.Collections.Generic; using Kyoo.Abstractions.Models; using TMDbLib.Objects.TvShows; @@ -27,11 +45,11 @@ namespace Kyoo.TheMovieDb ReleaseDate = episode.AirDate, Images = new Dictionary { - [Images.Thumbnail] = episode.StillPath != null - ? $"https://image.tmdb.org/t/p/original{episode.StillPath}" + [Images.Thumbnail] = episode.StillPath != null + ? $"https://image.tmdb.org/t/p/original{episode.StillPath}" : null }, - ExternalIDs = new [] + ExternalIDs = new[] { new MetadataID { @@ -44,4 +62,4 @@ namespace Kyoo.TheMovieDb }; } } -} \ No newline at end of file +} diff --git a/Kyoo.TheMovieDb/Convertors/MovieConvertors.cs b/src/Kyoo.TheMovieDb/Convertors/MovieConvertors.cs similarity index 79% rename from Kyoo.TheMovieDb/Convertors/MovieConvertors.cs rename to src/Kyoo.TheMovieDb/Convertors/MovieConvertors.cs index d123ca28..8e46a8e0 100644 --- a/Kyoo.TheMovieDb/Convertors/MovieConvertors.cs +++ b/src/Kyoo.TheMovieDb/Convertors/MovieConvertors.cs @@ -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 . + using System.Collections.Generic; using System.Linq; using Kyoo.Abstractions.Models; @@ -50,7 +68,7 @@ namespace Kyoo.TheMovieDb .Select(x => x.ToPeople(provider)) .Concat(movie.Credits.Crew.Select(x => x.ToPeople(provider))) .ToArray(), - ExternalIDs = new [] + ExternalIDs = new[] { new MetadataID { @@ -61,7 +79,7 @@ namespace Kyoo.TheMovieDb } }; } - + /// /// Convert a into a . /// @@ -87,7 +105,7 @@ namespace Kyoo.TheMovieDb : null, }, IsMovie = true, - ExternalIDs = new [] + ExternalIDs = new[] { new MetadataID { @@ -99,4 +117,4 @@ namespace Kyoo.TheMovieDb }; } } -} \ No newline at end of file +} diff --git a/Kyoo.TheMovieDb/Convertors/PeopleConvertors.cs b/src/Kyoo.TheMovieDb/Convertors/PeopleConvertors.cs similarity index 82% rename from Kyoo.TheMovieDb/Convertors/PeopleConvertors.cs rename to src/Kyoo.TheMovieDb/Convertors/PeopleConvertors.cs index 61c57db9..aada3bd6 100644 --- a/Kyoo.TheMovieDb/Convertors/PeopleConvertors.cs +++ b/src/Kyoo.TheMovieDb/Convertors/PeopleConvertors.cs @@ -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 . + using System.Collections.Generic; using Kyoo.Abstractions.Models; using Kyoo.Utils; @@ -5,8 +23,8 @@ using TMDbLib.Objects.General; using TMDbLib.Objects.People; using TMDbLib.Objects.Search; using Images = Kyoo.Abstractions.Models.Images; -using TvCast = TMDbLib.Objects.TvShows.Cast; using MovieCast = TMDbLib.Objects.Movies.Cast; +using TvCast = TMDbLib.Objects.TvShows.Cast; namespace Kyoo.TheMovieDb { @@ -31,8 +49,8 @@ namespace Kyoo.TheMovieDb Name = cast.Name, Images = new Dictionary { - [Images.Poster] = cast.ProfilePath != null - ? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}" + [Images.Poster] = cast.ProfilePath != null + ? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}" : null }, ExternalIDs = new[] @@ -49,7 +67,7 @@ namespace Kyoo.TheMovieDb Role = cast.Character }; } - + /// /// Convert a to a . /// @@ -66,8 +84,8 @@ namespace Kyoo.TheMovieDb Name = cast.Name, Images = new Dictionary { - [Images.Poster] = cast.ProfilePath != null - ? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}" + [Images.Poster] = cast.ProfilePath != null + ? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}" : null }, ExternalIDs = new[] @@ -84,7 +102,7 @@ namespace Kyoo.TheMovieDb Role = cast.Character }; } - + /// /// Convert a to a . /// @@ -101,8 +119,8 @@ namespace Kyoo.TheMovieDb Name = crew.Name, Images = new Dictionary { - [Images.Poster] = crew.ProfilePath != null - ? $"https://image.tmdb.org/t/p/original{crew.ProfilePath}" + [Images.Poster] = crew.ProfilePath != null + ? $"https://image.tmdb.org/t/p/original{crew.ProfilePath}" : null }, ExternalIDs = new[] @@ -119,7 +137,7 @@ namespace Kyoo.TheMovieDb Role = crew.Job }; } - + /// /// Convert a to a . /// @@ -134,8 +152,8 @@ namespace Kyoo.TheMovieDb Name = person.Name, Images = new Dictionary { - [Images.Poster] = person.ProfilePath != null - ? $"https://image.tmdb.org/t/p/original{person.ProfilePath}" + [Images.Poster] = person.ProfilePath != null + ? $"https://image.tmdb.org/t/p/original{person.ProfilePath}" : null }, ExternalIDs = new[] @@ -149,7 +167,7 @@ namespace Kyoo.TheMovieDb } }; } - + /// /// Convert a to a . /// @@ -164,8 +182,8 @@ namespace Kyoo.TheMovieDb Name = person.Name, Images = new Dictionary { - [Images.Poster] = person.ProfilePath != null - ? $"https://image.tmdb.org/t/p/original{person.ProfilePath}" + [Images.Poster] = person.ProfilePath != null + ? $"https://image.tmdb.org/t/p/original{person.ProfilePath}" : null }, ExternalIDs = new[] @@ -180,4 +198,4 @@ namespace Kyoo.TheMovieDb }; } } -} \ No newline at end of file +} diff --git a/Kyoo.TheMovieDb/Convertors/SeasonConvertors.cs b/src/Kyoo.TheMovieDb/Convertors/SeasonConvertors.cs similarity index 59% rename from Kyoo.TheMovieDb/Convertors/SeasonConvertors.cs rename to src/Kyoo.TheMovieDb/Convertors/SeasonConvertors.cs index 8c5dc7a1..12bc7bd0 100644 --- a/Kyoo.TheMovieDb/Convertors/SeasonConvertors.cs +++ b/src/Kyoo.TheMovieDb/Convertors/SeasonConvertors.cs @@ -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 . + using System.Collections.Generic; using Kyoo.Abstractions.Models; using TMDbLib.Objects.TvShows; @@ -26,11 +44,11 @@ namespace Kyoo.TheMovieDb StartDate = season.AirDate, Images = new Dictionary { - [Images.Poster] = season.PosterPath != null + [Images.Poster] = season.PosterPath != null ? $"https://image.tmdb.org/t/p/original{season.PosterPath}" : null }, - ExternalIDs = new [] + ExternalIDs = new[] { new MetadataID { @@ -42,4 +60,4 @@ namespace Kyoo.TheMovieDb }; } } -} \ No newline at end of file +} diff --git a/Kyoo.TheMovieDb/Convertors/ShowConvertors.cs b/src/Kyoo.TheMovieDb/Convertors/ShowConvertors.cs similarity index 77% rename from Kyoo.TheMovieDb/Convertors/ShowConvertors.cs rename to src/Kyoo.TheMovieDb/Convertors/ShowConvertors.cs index 99ccc046..41be3235 100644 --- a/Kyoo.TheMovieDb/Convertors/ShowConvertors.cs +++ b/src/Kyoo.TheMovieDb/Convertors/ShowConvertors.cs @@ -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 . + using System.Collections.Generic; using System.Linq; using Kyoo.Abstractions.Models; @@ -49,7 +67,7 @@ namespace Kyoo.TheMovieDb .Select(x => x.ToPeople(provider)) .Concat(tv.Credits.Crew.Select(x => x.ToPeople(provider))) .ToArray(), - ExternalIDs = new [] + ExternalIDs = new[] { new MetadataID { @@ -60,7 +78,7 @@ namespace Kyoo.TheMovieDb } }; } - + /// /// Convert a to a . /// @@ -75,7 +93,7 @@ namespace Kyoo.TheMovieDb Title = tv.Name, Overview = tv.Overview, StartAir = tv.FirstAirDate, - Images = new Dictionary + Images = new Dictionary { [Images.Poster] = tv.PosterPath != null ? $"https://image.tmdb.org/t/p/original{tv.PosterPath}" @@ -84,7 +102,7 @@ namespace Kyoo.TheMovieDb ? $"https://image.tmdb.org/t/p/original{tv.BackdropPath}" : null, }, - ExternalIDs = new [] + ExternalIDs = new[] { new MetadataID { @@ -96,4 +114,4 @@ namespace Kyoo.TheMovieDb }; } } -} \ No newline at end of file +} diff --git a/Kyoo.TheMovieDb/Convertors/StudioConvertors.cs b/src/Kyoo.TheMovieDb/Convertors/StudioConvertors.cs similarity index 67% rename from Kyoo.TheMovieDb/Convertors/StudioConvertors.cs rename to src/Kyoo.TheMovieDb/Convertors/StudioConvertors.cs index 22f2ef9d..4c2f8d09 100644 --- a/Kyoo.TheMovieDb/Convertors/StudioConvertors.cs +++ b/src/Kyoo.TheMovieDb/Convertors/StudioConvertors.cs @@ -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 . + using Kyoo.Abstractions.Models; using Kyoo.Utils; using TMDbLib.Objects.Companies; @@ -22,7 +40,7 @@ namespace Kyoo.TheMovieDb { Slug = Utility.ToSlug(company.Name), Name = company.Name, - ExternalIDs = new [] + ExternalIDs = new[] { new MetadataID { @@ -58,4 +76,4 @@ namespace Kyoo.TheMovieDb }; } } -} \ No newline at end of file +} diff --git a/Kyoo.TheMovieDb/Kyoo.TheMovieDb.csproj b/src/Kyoo.TheMovieDb/Kyoo.TheMovieDb.csproj similarity index 100% rename from Kyoo.TheMovieDb/Kyoo.TheMovieDb.csproj rename to src/Kyoo.TheMovieDb/Kyoo.TheMovieDb.csproj diff --git a/Kyoo.TheMovieDb/PluginTmdb.cs b/src/Kyoo.TheMovieDb/PluginTmdb.cs similarity index 68% rename from Kyoo.TheMovieDb/PluginTmdb.cs rename to src/Kyoo.TheMovieDb/PluginTmdb.cs index 9af1a267..72d16f19 100644 --- a/Kyoo.TheMovieDb/PluginTmdb.cs +++ b/src/Kyoo.TheMovieDb/PluginTmdb.cs @@ -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 . + using System; using System.Collections.Generic; using Autofac; @@ -14,24 +32,6 @@ namespace Kyoo.TheMovieDb /// public class PluginTmdb : IPlugin { - /// - public string Slug => "the-moviedb"; - - /// - public string Name => "TheMovieDb"; - - /// - public string Description => "A metadata provider for TheMovieDB."; - - /// - public bool Enabled => !string.IsNullOrEmpty(_configuration.GetValue("the-moviedb:apikey")); - - /// - public Dictionary Configuration => new() - { - { TheMovieDbOptions.Path, typeof(TheMovieDbOptions) } - }; - /// /// The configuration used to check if the api key is present or not. /// @@ -46,14 +46,34 @@ namespace Kyoo.TheMovieDb { _configuration = configuration; if (!Enabled) + { logger.LogWarning("No API key configured for TheMovieDB provider. " + "To enable TheMovieDB, specify one in the setting the-moviedb:APIKEY "); + } } + /// + public string Slug => "the-moviedb"; + + /// + public string Name => "TheMovieDb"; + + /// + public string Description => "A metadata provider for TheMovieDB."; + + /// + public bool Enabled => !string.IsNullOrEmpty(_configuration.GetValue("the-moviedb:apikey")); + + /// + public Dictionary Configuration => new() + { + { TheMovieDbOptions.Path, typeof(TheMovieDbOptions) } + }; + /// public void Configure(ContainerBuilder builder) { builder.RegisterProvider(); } } -} \ No newline at end of file +} diff --git a/src/Kyoo.TheMovieDb/TheMovieDbOptions.cs b/src/Kyoo.TheMovieDb/TheMovieDbOptions.cs new file mode 100644 index 00000000..7167c902 --- /dev/null +++ b/src/Kyoo.TheMovieDb/TheMovieDbOptions.cs @@ -0,0 +1,36 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +namespace Kyoo.TheMovieDb.Models +{ + /// + /// The option containing the api key for TheMovieDb. + /// + public class TheMovieDbOptions + { + /// + /// The path to get this option from the root configuration. + /// + public const string Path = "the-moviedb"; + + /// + /// The api key of TheMovieDb. + /// + public string ApiKey { get; set; } + } +} diff --git a/Kyoo.TheMovieDb/ProviderTmdb.cs b/src/Kyoo.TheMovieDb/TheMovieDbProvider.cs similarity index 82% rename from Kyoo.TheMovieDb/ProviderTmdb.cs rename to src/Kyoo.TheMovieDb/TheMovieDbProvider.cs index 7d8c4057..a68ca206 100644 --- a/Kyoo.TheMovieDb/ProviderTmdb.cs +++ b/src/Kyoo.TheMovieDb/TheMovieDbProvider.cs @@ -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 . + +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -23,6 +41,7 @@ namespace Kyoo.TheMovieDb /// The API key used to authenticate with TheMovieDb API. /// private readonly IOptions _apiKey; + /// /// The logger to use in ase of issue. /// @@ -43,17 +62,16 @@ namespace Kyoo.TheMovieDb /// /// Create a new using the given api key. /// - /// The api key + /// The api key. /// The logger to use in case of issue. public TheMovieDbProvider(IOptions apiKey, ILogger logger) { _apiKey = apiKey; _logger = logger; } - /// - public Task Get(T item) + public Task Get(T item) where T : class, IResource { return item switch @@ -71,8 +89,8 @@ namespace Kyoo.TheMovieDb /// /// Get a collection using it's id, if the id is not present in the collection, fallback to a name search. /// - /// The collection to search for - /// A collection containing metadata from TheMovieDb + /// The collection to search for. + /// A collection containing metadata from TheMovieDb. private async Task _GetCollection(Collection collection) { if (!collection.TryGetID(Provider.Slug, out int id)) @@ -89,8 +107,8 @@ namespace Kyoo.TheMovieDb /// /// Get a show using it's id, if the id is not present in the show, fallback to a title search. /// - /// The show to search for - /// A show containing metadata from TheMovieDb + /// The show to search for. + /// A show containing metadata from TheMovieDb. private async Task _GetShow(Show show) { if (!show.TryGetID(Provider.Slug, out int id)) @@ -100,26 +118,26 @@ namespace Kyoo.TheMovieDb if (found?.TryGetID(Provider.Slug, out id) != true) return found; } - + TMDbClient client = new(_apiKey.Value.ApiKey); - + if (show.IsMovie) { return (await client .GetMovieAsync(id, MovieMethods.AlternativeTitles | MovieMethods.Videos | MovieMethods.Credits)) ?.ToShow(Provider); } - + return (await client .GetTvShowAsync(id, TvShowMethods.AlternativeTitles | TvShowMethods.Videos | TvShowMethods.Credits)) ?.ToShow(Provider); } - + /// /// Get a season using it's show and it's season number. /// /// The season to retrieve metadata for. - /// A season containing metadata from TheMovieDb + /// A season containing metadata from TheMovieDb. private async Task _GetSeason(Season season) { if (season.Show == null) @@ -131,7 +149,7 @@ namespace Kyoo.TheMovieDb if (!season.Show.TryGetID(Provider.Slug, out int id)) return null; - + TMDbClient client = new(_apiKey.Value.ApiKey); return (await client.GetTvSeasonAsync(id, season.SeasonNumber)) .ToSeason(id, Provider); @@ -139,10 +157,10 @@ namespace Kyoo.TheMovieDb /// /// Get an episode using it's show, it's season number and it's episode number. - /// Absolute numbering is not supported. + /// Absolute numbering is not supported. /// /// The episode to retrieve metadata for. - /// An episode containing metadata from TheMovieDb + /// An episode containing metadata from TheMovieDb. private async Task _GetEpisode(Episode episode) { if (episode.Show == null) @@ -151,20 +169,20 @@ namespace Kyoo.TheMovieDb "This is unsupported"); return null; } - if (!episode.Show.TryGetID(Provider.Slug, out int id) + if (!episode.Show.TryGetID(Provider.Slug, out int id) || episode.SeasonNumber == null || episode.EpisodeNumber == null) return null; - + TMDbClient client = new(_apiKey.Value.ApiKey); return (await client.GetTvEpisodeAsync(id, episode.SeasonNumber.Value, episode.EpisodeNumber.Value)) ?.ToEpisode(id, Provider); } - + /// /// Get a person using it's id, if the id is not present in the person, fallback to a name search. /// - /// The person to search for - /// A person containing metadata from TheMovieDb + /// The person to search for. + /// A person containing metadata from TheMovieDb. private async Task _GetPerson(People person) { if (!person.TryGetID(Provider.Slug, out int id)) @@ -177,12 +195,12 @@ namespace Kyoo.TheMovieDb TMDbClient client = new(_apiKey.Value.ApiKey); return (await client.GetPersonAsync(id)).ToPeople(Provider); } - + /// /// Get a studio using it's id, if the id is not present in the studio, fallback to a name search. /// - /// The studio to search for - /// A studio containing metadata from TheMovieDb + /// The studio to search for. + /// A studio containing metadata from TheMovieDb. private async Task _GetStudio(Studio studio) { if (!studio.TryGetID(Provider.Slug, out int id)) @@ -195,9 +213,9 @@ namespace Kyoo.TheMovieDb TMDbClient client = new(_apiKey.Value.ApiKey); return (await client.GetCompanyAsync(id)).ToStudio(Provider); } - + /// - public async Task> Search(string query) + public async Task> Search(string query) where T : class, IResource { if (typeof(T) == typeof(Collection)) @@ -248,7 +266,7 @@ namespace Kyoo.TheMovieDb .Where(x => x != null) .ToArray(); } - + /// /// Search for people using there name as a query. /// @@ -262,7 +280,7 @@ namespace Kyoo.TheMovieDb .Select(x => x.ToPeople(Provider)) .ToArray(); } - + /// /// Search for studios using there name as a query. /// @@ -277,4 +295,4 @@ namespace Kyoo.TheMovieDb .ToArray(); } } -} \ No newline at end of file +} diff --git a/Kyoo.TheTvdb/Convertors.cs b/src/Kyoo.TheTvdb/Convertors.cs similarity index 78% rename from Kyoo.TheTvdb/Convertors.cs rename to src/Kyoo.TheTvdb/Convertors.cs index d53dfe62..f8f7e50d 100644 --- a/Kyoo.TheTvdb/Convertors.cs +++ b/src/Kyoo.TheTvdb/Convertors.cs @@ -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 . + using System; using System.Collections.Generic; using System.Globalization; @@ -14,7 +32,7 @@ namespace Kyoo.TheTvdb public static class Convertors { /// - /// Convert the string representation of the status in the tvdb API to a Kyoo's enum. + /// Convert the string representation of the status in the tvdb API to a Kyoo's enum. /// /// The string representing the status. /// A kyoo value or null. @@ -40,9 +58,9 @@ namespace Kyoo.TheTvdb ? parsed : null; } - + /// - /// Convert a series search to a show. + /// Convert a series search to a show. /// /// The search result /// The provider representing the tvdb inside kyoo @@ -60,7 +78,7 @@ namespace Kyoo.TheTvdb Images = new Dictionary { [Images.Poster] = !string.IsNullOrEmpty(result.Poster) - ? $"https://www.thetvdb.com{result.Poster}" + ? $"https://www.thetvdb.com{result.Poster}" : null, }, ExternalIDs = new[] @@ -74,7 +92,7 @@ namespace Kyoo.TheTvdb } }; } - + /// /// Convert a tvdb series to a kyoo show. /// @@ -94,10 +112,10 @@ namespace Kyoo.TheTvdb Images = new Dictionary { [Images.Poster] = !string.IsNullOrEmpty(series.Poster) - ? $"https://www.thetvdb.com/banners/{series.Poster}" + ? $"https://www.thetvdb.com/banners/{series.Poster}" : null, [Images.Thumbnail] = !string.IsNullOrEmpty(series.FanArt) - ? $"https://www.thetvdb.com/banners/{series.FanArt}" + ? $"https://www.thetvdb.com/banners/{series.FanArt}" : null }, Genres = series.Genre.Select(y => new Genre(y)).ToList(), @@ -112,7 +130,7 @@ namespace Kyoo.TheTvdb } }; } - + /// /// Convert a tvdb actor to a kyoo . /// @@ -126,10 +144,10 @@ namespace Kyoo.TheTvdb { Slug = Utility.ToSlug(actor.Name), Name = actor.Name, - Images = new Dictionary + Images = new Dictionary { - [Images.Poster] = !string.IsNullOrEmpty(actor.Image) - ? $"https://www.thetvdb.com/banners/{actor.Image}" + [Images.Poster] = !string.IsNullOrEmpty(actor.Image) + ? $"https://www.thetvdb.com/banners/{actor.Image}" : null } }, @@ -155,8 +173,8 @@ namespace Kyoo.TheTvdb Overview = episode.Overview, Images = new Dictionary { - [Images.Thumbnail] = !string.IsNullOrEmpty(episode.Filename) - ? $"https://www.thetvdb.com/banners/{episode.Filename}" + [Images.Thumbnail] = !string.IsNullOrEmpty(episode.Filename) + ? $"https://www.thetvdb.com/banners/{episode.Filename}" : null }, ExternalIDs = new[] @@ -171,4 +189,4 @@ namespace Kyoo.TheTvdb }; } } -} \ No newline at end of file +} diff --git a/Kyoo.TheTvdb/Kyoo.TheTvdb.csproj b/src/Kyoo.TheTvdb/Kyoo.TheTvdb.csproj similarity index 100% rename from Kyoo.TheTvdb/Kyoo.TheTvdb.csproj rename to src/Kyoo.TheTvdb/Kyoo.TheTvdb.csproj diff --git a/Kyoo.TheTvdb/PluginTvdb.cs b/src/Kyoo.TheTvdb/PluginTvdb.cs similarity index 69% rename from Kyoo.TheTvdb/PluginTvdb.cs rename to src/Kyoo.TheTvdb/PluginTvdb.cs index 75feee76..29b05bc8 100644 --- a/Kyoo.TheTvdb/PluginTvdb.cs +++ b/src/Kyoo.TheTvdb/PluginTvdb.cs @@ -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 . + using System; using System.Collections.Generic; using Autofac; @@ -47,8 +65,10 @@ namespace Kyoo.TheTvdb { _configuration = configuration; if (!Enabled) + { logger.LogWarning("No API key configured for TVDB provider. " + "To enable TVDB, specify one in the setting TVDB:APIKEY "); + } } /// @@ -58,4 +78,4 @@ namespace Kyoo.TheTvdb builder.RegisterProvider(); } } -} \ No newline at end of file +} diff --git a/Kyoo.TheTvdb/ProviderTvdb.cs b/src/Kyoo.TheTvdb/ProviderTvdb.cs similarity index 77% rename from Kyoo.TheTvdb/ProviderTvdb.cs rename to src/Kyoo.TheTvdb/ProviderTvdb.cs index ae983720..7666fd77 100644 --- a/Kyoo.TheTvdb/ProviderTvdb.cs +++ b/src/Kyoo.TheTvdb/ProviderTvdb.cs @@ -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 . + +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -34,11 +52,10 @@ namespace Kyoo.TheTvdb Name = "TheTVDB", Images = new Dictionary { - [Images.Logo] = "https://www.thetvdb.com/images/logo.png" + [Images.Logo] = "https://www.thetvdb.com/images/logo.png" } }; - - + /// /// Create a new using a tvdb client and an api key. /// @@ -59,9 +76,9 @@ namespace Kyoo.TheTvdb return _client.Authentication.AuthenticateAsync(_apiKey.Value.ApiKey); return _client.Authentication.RefreshTokenAsync(); } - + /// - public async Task Get(T item) + public async Task Get(T item) where T : class, IResource { await _Authenticate(); @@ -72,7 +89,7 @@ namespace Kyoo.TheTvdb _ => null }; } - + /// /// Retrieve metadata about a show. /// @@ -83,7 +100,7 @@ namespace Kyoo.TheTvdb { if (show.IsMovie) return null; - + if (!int.TryParse(show.GetID(Provider.Slug), out int id)) { Show found = (await _SearchShow(show.Title)).FirstOrDefault(); @@ -93,7 +110,7 @@ namespace Kyoo.TheTvdb } TvDbResponse series = await _client.Series.GetAsync(id); Show ret = series.Data.ToShow(Provider); - + TvDbResponse people = await _client.Series.GetActorsAsync(id); ret.People = people.Data.Select(x => x.ToPeopleRole()).ToArray(); return ret; @@ -110,14 +127,14 @@ namespace Kyoo.TheTvdb if (!int.TryParse(episode.Show?.GetID(Provider.Slug), out int id)) return null; EpisodeQuery query = episode.AbsoluteNumber != null - ? new EpisodeQuery {AbsoluteNumber = episode.AbsoluteNumber} - : new EpisodeQuery {AiredSeason = episode.SeasonNumber, AiredEpisode = episode.EpisodeNumber}; + ? new EpisodeQuery { AbsoluteNumber = episode.AbsoluteNumber } + : new EpisodeQuery { AiredSeason = episode.SeasonNumber, AiredEpisode = episode.EpisodeNumber }; TvDbResponse episodes = await _client.Series.GetEpisodesAsync(id, 0, query); return episodes.Data.FirstOrDefault()?.ToEpisode(Provider); } /// - public async Task> Search(string query) + public async Task> Search(string query) where T : class, IResource { await _Authenticate(); @@ -125,7 +142,7 @@ namespace Kyoo.TheTvdb return (await _SearchShow(query) as ICollection)!; return ArraySegment.Empty; } - + /// /// Search for shows in the tvdb. /// @@ -145,4 +162,4 @@ namespace Kyoo.TheTvdb } } } -} \ No newline at end of file +} diff --git a/src/Kyoo.TheTvdb/TvdbOption.cs b/src/Kyoo.TheTvdb/TvdbOption.cs new file mode 100644 index 00000000..d454af62 --- /dev/null +++ b/src/Kyoo.TheTvdb/TvdbOption.cs @@ -0,0 +1,36 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +namespace Kyoo.TheTvdb.Models +{ + /// + /// The option containing the api key for the tvdb. + /// + public class TvdbOption + { + /// + /// The path to get this option from the root configuration. + /// + public const string Path = "tvdb"; + + /// + /// The api key of the tvdb. + /// + public string ApiKey { get; set; } + } +} diff --git a/Kyoo.Transcoder b/src/Kyoo.Transcoder similarity index 100% rename from Kyoo.Transcoder rename to src/Kyoo.Transcoder diff --git a/Kyoo.WebApp/Front b/src/Kyoo.WebApp/Front similarity index 100% rename from Kyoo.WebApp/Front rename to src/Kyoo.WebApp/Front diff --git a/Kyoo.WebApp/Kyoo.WebApp.csproj b/src/Kyoo.WebApp/Kyoo.WebApp.csproj similarity index 100% rename from Kyoo.WebApp/Kyoo.WebApp.csproj rename to src/Kyoo.WebApp/Kyoo.WebApp.csproj diff --git a/Kyoo.WebApp/WebAppModule.cs b/src/Kyoo.WebApp/WebAppModule.cs similarity index 81% rename from Kyoo.WebApp/WebAppModule.cs rename to src/Kyoo.WebApp/WebAppModule.cs index a83910cb..53bce725 100644 --- a/Kyoo.WebApp/WebAppModule.cs +++ b/src/Kyoo.WebApp/WebAppModule.cs @@ -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 . + using System; using System.Collections.Generic; using System.IO; @@ -21,7 +39,7 @@ namespace Kyoo.WebApp { /// public string Slug => "webapp"; - + /// public string Name => "WebApp"; @@ -41,8 +59,10 @@ namespace Kyoo.WebApp public WebAppModule(ILogger logger) { if (!Enabled) - logger.LogError("The web app files could not be found, it will be disabled. " + + { + logger.LogError("The web app files could not be found, it will be disabled. " + "If you cloned the project, you probably forgot to use the --recurse flag"); + } } /// @@ -53,7 +73,7 @@ namespace Kyoo.WebApp x.RootPath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "wwwroot"); }); } - + /// public IEnumerable ConfigureSteps => new IStartupAction[] { @@ -72,7 +92,7 @@ namespace Kyoo.WebApp }, SA.StaticFiles), SA.New(app => { - app.Use((ctx, next) => + app.Use((ctx, next) => { ctx.Response.Headers.Remove("X-Powered-By"); ctx.Response.Headers.Remove("Server"); @@ -90,7 +110,7 @@ namespace Kyoo.WebApp app.UseSpa(spa => { spa.Options.SourcePath = _GetSpaSourcePath(); - + if (env.IsDevelopment()) spa.UseAngularCliServer("start"); }); @@ -112,4 +132,4 @@ namespace Kyoo.WebApp return Directory.Exists(path) ? path : null; } } -} \ No newline at end of file +} diff --git a/Kyoo.WebLogin/index.html b/src/Kyoo.WebLogin/index.html similarity index 100% rename from Kyoo.WebLogin/index.html rename to src/Kyoo.WebLogin/index.html diff --git a/Kyoo.WebLogin/lib/bootstrap.min.css b/src/Kyoo.WebLogin/lib/bootstrap.min.css similarity index 100% rename from Kyoo.WebLogin/lib/bootstrap.min.css rename to src/Kyoo.WebLogin/lib/bootstrap.min.css diff --git a/Kyoo.WebLogin/lib/bootstrap.min.js b/src/Kyoo.WebLogin/lib/bootstrap.min.js similarity index 100% rename from Kyoo.WebLogin/lib/bootstrap.min.js rename to src/Kyoo.WebLogin/lib/bootstrap.min.js diff --git a/Kyoo.WebLogin/lib/jquery.min.js b/src/Kyoo.WebLogin/lib/jquery.min.js similarity index 100% rename from Kyoo.WebLogin/lib/jquery.min.js rename to src/Kyoo.WebLogin/lib/jquery.min.js diff --git a/Kyoo.WebLogin/login.css b/src/Kyoo.WebLogin/login.css similarity index 100% rename from Kyoo.WebLogin/login.css rename to src/Kyoo.WebLogin/login.css diff --git a/Kyoo.WebLogin/login.js b/src/Kyoo.WebLogin/login.js similarity index 100% rename from Kyoo.WebLogin/login.js rename to src/Kyoo.WebLogin/login.js diff --git a/Kyoo.WebLogin/material-icons.css b/src/Kyoo.WebLogin/material-icons.css similarity index 100% rename from Kyoo.WebLogin/material-icons.css rename to src/Kyoo.WebLogin/material-icons.css diff --git a/stylecop.json b/stylecop.json new file mode 100644 index 00000000..4a27621c --- /dev/null +++ b/stylecop.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "copyrightText": "Kyoo - A portable and vast media library solution.\nCopyright (c) Kyoo.\n\nSee AUTHORS.md and LICENSE file in the project root for full license information.\n\nKyoo is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\nany later version.\n\nKyoo is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with Kyoo. If not, see .", + "xmlHeader": false + } + } +} diff --git a/tests/Kyoo.Tests/Database/RepositoryActivator.cs b/tests/Kyoo.Tests/Database/RepositoryActivator.cs index 267bafb7..e049fcda 100644 --- a/tests/Kyoo.Tests/Database/RepositoryActivator.cs +++ b/tests/Kyoo.Tests/Database/RepositoryActivator.cs @@ -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 . + using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -13,13 +31,12 @@ namespace Kyoo.Tests public TestContext Context { get; } public ILibraryManager LibraryManager { get; } - private readonly List _databases = new(); - + public RepositoryActivator(ITestOutputHelper output, PostgresFixture postgres = null) { - Context = postgres == null - ? new SqLiteTestContext(output) + Context = postgres == null + ? new SqLiteTestContext(output) : new PostgresTestContext(postgres, output); ProviderRepository provider = new(_NewContext()); @@ -27,11 +44,11 @@ namespace Kyoo.Tests CollectionRepository collection = new(_NewContext(), provider); GenreRepository genre = new(_NewContext()); StudioRepository studio = new(_NewContext(), provider); - PeopleRepository people = new(_NewContext(), provider, + PeopleRepository people = new(_NewContext(), provider, new Lazy(() => LibraryManager.ShowRepository)); ShowRepository show = new(_NewContext(), studio, people, genre, provider); SeasonRepository season = new(_NewContext(), provider); - LibraryItemRepository libraryItem = new(_NewContext(), + LibraryItemRepository libraryItem = new(_NewContext(), new Lazy(() => LibraryManager.LibraryRepository)); TrackRepository track = new(_NewContext()); EpisodeRepository episode = new(_NewContext(), provider, track); @@ -75,4 +92,4 @@ namespace Kyoo.Tests await Context.DisposeAsync(); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/RepositoryTests.cs b/tests/Kyoo.Tests/Database/RepositoryTests.cs index 536673b3..b8454751 100644 --- a/tests/Kyoo.Tests/Database/RepositoryTests.cs +++ b/tests/Kyoo.Tests/Database/RepositoryTests.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -48,20 +66,20 @@ namespace Kyoo.Tests T value = await _repository.Get(TestSample.Get().ID); KAssert.DeepEqual(TestSample.Get(), value); } - + [Fact] public async Task GetBySlugTest() { T value = await _repository.Get(TestSample.Get().Slug); KAssert.DeepEqual(TestSample.Get(), value); } - + [Fact] public async Task GetByFakeIdTest() { await Assert.ThrowsAsync(() => _repository.Get(2)); } - + [Fact] public async Task GetByFakeSlugTest() { @@ -74,21 +92,21 @@ namespace Kyoo.Tests await _repository.Delete(TestSample.Get().ID); Assert.Equal(0, await _repository.GetCount()); } - + [Fact] public async Task DeleteBySlugTest() { await _repository.Delete(TestSample.Get().Slug); Assert.Equal(0, await _repository.GetCount()); } - + [Fact] public async Task DeleteByValueTest() { await _repository.Delete(TestSample.Get()); Assert.Equal(0, await _repository.GetCount()); } - + [Fact] public async Task CreateTest() { @@ -100,19 +118,19 @@ namespace Kyoo.Tests await _repository.Create(expected); KAssert.DeepEqual(expected, await _repository.Get(expected.Slug)); } - + [Fact] public async Task CreateNullTest() { await Assert.ThrowsAsync(() => _repository.Create(null!)); } - + [Fact] public async Task CreateIfNotExistNullTest() { await Assert.ThrowsAsync(() => _repository.CreateIfNotExists(null!)); } - + [Fact] public async Task CreateIfNotExistTest() { @@ -121,17 +139,17 @@ namespace Kyoo.Tests await _repository.Delete(TestSample.Get()); KAssert.DeepEqual(expected, await _repository.CreateIfNotExists(TestSample.Get())); } - + [Fact] public async Task EditNullTest() { await Assert.ThrowsAsync(() => _repository.Edit(null!, false)); } - + [Fact] public async Task EditNonExistingTest() { - await Assert.ThrowsAsync(() => _repository.Edit(new T {ID = 56}, false)); + await Assert.ThrowsAsync(() => _repository.Edit(new T { ID = 56 }, false)); } [Fact] @@ -145,19 +163,19 @@ namespace Kyoo.Tests { KAssert.DeepEqual(TestSample.Get(), await _repository.Get(x => x.Slug == TestSample.Get().Slug)); } - + [Fact] public async Task GetExpressionNotFoundTest() { await Assert.ThrowsAsync(() => _repository.Get(x => x.Slug == "non-existing")); } - + [Fact] public async Task GetExpressionNullTest() { await Assert.ThrowsAsync(() => _repository.Get((Expression>)null!)); } - + [Fact] public async Task GetOrDefaultTest() { @@ -172,7 +190,7 @@ namespace Kyoo.Tests string slug = TestSample.Get().Slug[2..4]; Assert.Equal(1, await _repository.GetCount(x => x.Slug.Contains(slug))); } - + [Fact] public async Task GetAllTest() { @@ -181,7 +199,7 @@ namespace Kyoo.Tests Assert.Equal(1, ret.Count); KAssert.DeepEqual(TestSample.Get(), ret.First()); } - + [Fact] public async Task DeleteAllTest() { @@ -190,4 +208,4 @@ namespace Kyoo.Tests Assert.Equal(0, await _repository.GetCount()); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/CollectionsTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/CollectionsTests.cs index f28cef94..ce3408d3 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/CollectionsTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/CollectionsTests.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -39,15 +57,15 @@ namespace Kyoo.Tests.Database { _repository = Repositories.LibraryManager.CollectionRepository; } - + [Fact] public async Task CreateWithEmptySlugTest() { Collection collection = TestSample.GetNew(); - collection.Slug = ""; + collection.Slug = string.Empty; await Assert.ThrowsAsync(() => _repository.Create(collection)); } - + [Fact] public async Task CreateWithNumberSlugTest() { @@ -56,7 +74,7 @@ namespace Kyoo.Tests.Database Collection ret = await _repository.Create(collection); Assert.Equal("2!", ret.Slug); } - + [Fact] public async Task CreateWithoutNameTest() { @@ -64,7 +82,7 @@ namespace Kyoo.Tests.Database collection.Name = null; await Assert.ThrowsAsync(() => _repository.Create(collection)); } - + [Fact] public async Task CreateWithExternalIdTest() { @@ -85,14 +103,14 @@ namespace Kyoo.Tests.Database } }; await _repository.Create(collection); - + Collection retrieved = await _repository.Get(2); await Repositories.LibraryManager.Load(retrieved, x => x.ExternalIDs); Assert.Equal(2, retrieved.ExternalIDs.Count); KAssert.DeepEqual(collection.ExternalIDs.First(), retrieved.ExternalIDs.First()); KAssert.DeepEqual(collection.ExternalIDs.Last(), retrieved.ExternalIDs.Last()); } - + [Fact] public async Task EditTest() { @@ -103,13 +121,13 @@ namespace Kyoo.Tests.Database [Images.Poster] = "new-poster" }; await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); Collection retrieved = await database.Collections.FirstAsync(); - + KAssert.DeepEqual(value, retrieved); } - + [Fact] public async Task EditMetadataTest() { @@ -124,13 +142,13 @@ namespace Kyoo.Tests.Database }, }; await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); Collection retrieved = await database.Collections .Include(x => x.ExternalIDs) .ThenInclude(x => x.Provider) .FirstAsync(); - + KAssert.DeepEqual(value, retrieved); } @@ -166,7 +184,7 @@ namespace Kyoo.Tests.Database DataID = "id" }); await _repository.Edit(value, false); - + { await using DatabaseContext database = Repositories.Context.New(); Collection retrieved = await database.Collections @@ -177,7 +195,7 @@ namespace Kyoo.Tests.Database KAssert.DeepEqual(value, retrieved); } } - + [Theory] [InlineData("test")] [InlineData("super")] @@ -196,4 +214,4 @@ namespace Kyoo.Tests.Database KAssert.DeepEqual(value, ret.First()); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/EpisodeTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/EpisodeTests.cs index 0aff5ec7..58befa98 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/EpisodeTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/EpisodeTests.cs @@ -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 . + using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -19,7 +37,6 @@ namespace Kyoo.Tests.Database } } - namespace PostgreSQL { [Collection(nameof(Postgresql))] @@ -39,7 +56,7 @@ namespace Kyoo.Tests.Database { _repository = repositories.LibraryManager.EpisodeRepository; } - + [Fact] public async Task SlugEditTest() { @@ -54,7 +71,7 @@ namespace Kyoo.Tests.Database episode = await _repository.Get(1); Assert.Equal("new-slug-s1e1", episode.Slug); } - + [Fact] public async Task SeasonNumberEditTest() { @@ -70,7 +87,7 @@ namespace Kyoo.Tests.Database episode = await _repository.Get(1); Assert.Equal($"{TestSample.Get().Slug}-s2e1", episode.Slug); } - + [Fact] public async Task EpisodeNumberEditTest() { @@ -86,7 +103,7 @@ namespace Kyoo.Tests.Database episode = await _repository.Get(1); Assert.Equal($"{TestSample.Get().Slug}-s1e2", episode.Slug); } - + [Fact] public async Task EpisodeCreationSlugTest() { @@ -102,17 +119,17 @@ namespace Kyoo.Tests.Database [Fact] public void AbsoluteSlugTest() { - Assert.Equal($"{TestSample.Get().Slug}-{TestSample.GetAbsoluteEpisode().AbsoluteNumber}", + Assert.Equal($"{TestSample.Get().Slug}-{TestSample.GetAbsoluteEpisode().AbsoluteNumber}", TestSample.GetAbsoluteEpisode().Slug); } - + [Fact] public async Task EpisodeCreationAbsoluteSlugTest() { Episode episode = await _repository.Create(TestSample.GetAbsoluteEpisode()); Assert.Equal($"{TestSample.Get().Slug}-{TestSample.GetAbsoluteEpisode().AbsoluteNumber}", episode.Slug); } - + [Fact] public async Task SlugEditAbsoluteTest() { @@ -126,8 +143,7 @@ namespace Kyoo.Tests.Database episode = await _repository.Get(2); Assert.Equal($"new-slug-3", episode.Slug); } - - + [Fact] public async Task AbsoluteNumberEditTest() { @@ -142,7 +158,7 @@ namespace Kyoo.Tests.Database episode = await _repository.Get(2); Assert.Equal($"{TestSample.Get().Slug}-56", episode.Slug); } - + [Fact] public async Task AbsoluteToNormalEditTest() { @@ -158,7 +174,7 @@ namespace Kyoo.Tests.Database episode = await _repository.Get(2); Assert.Equal($"{TestSample.Get().Slug}-s1e2", episode.Slug); } - + [Fact] public async Task NormalToAbsoluteEditTest() { @@ -170,7 +186,7 @@ namespace Kyoo.Tests.Database episode = await _repository.Get(1); Assert.Equal($"{TestSample.Get().Slug}-12", episode.Slug); } - + [Fact] public async Task MovieEpisodeTest() { @@ -179,7 +195,7 @@ namespace Kyoo.Tests.Database episode = await _repository.Get(3); Assert.Equal(TestSample.Get().Slug, episode.Slug); } - + [Fact] public async Task MovieEpisodeEditTest() { @@ -192,7 +208,7 @@ namespace Kyoo.Tests.Database Episode episode = await _repository.Get(3); Assert.Equal("john-wick", episode.Slug); } - + [Fact] public async Task CreateWithExternalIdTest() { @@ -213,14 +229,14 @@ namespace Kyoo.Tests.Database } }; await _repository.Create(value); - + Episode retrieved = await _repository.Get(2); await Repositories.LibraryManager.Load(retrieved, x => x.ExternalIDs); Assert.Equal(2, retrieved.ExternalIDs.Count); KAssert.DeepEqual(value.ExternalIDs.First(), retrieved.ExternalIDs.First()); KAssert.DeepEqual(value.ExternalIDs.Last(), retrieved.ExternalIDs.Last()); } - + [Fact] public async Task EditTest() { @@ -231,13 +247,13 @@ namespace Kyoo.Tests.Database [Images.Poster] = "new-poster" }; await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); Episode retrieved = await database.Episodes.FirstAsync(); - + KAssert.DeepEqual(value, retrieved); } - + [Fact] public async Task EditMetadataTest() { @@ -252,13 +268,13 @@ namespace Kyoo.Tests.Database }, }; await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); Episode retrieved = await database.Episodes .Include(x => x.ExternalIDs) .ThenInclude(x => x.Provider) .FirstAsync(); - + KAssert.DeepEqual(value, retrieved); } @@ -294,7 +310,7 @@ namespace Kyoo.Tests.Database DataID = "id" }); await _repository.Edit(value, false); - + { await using DatabaseContext database = Repositories.Context.New(); Episode retrieved = await database.Episodes @@ -305,7 +321,7 @@ namespace Kyoo.Tests.Database KAssert.DeepEqual(value, retrieved); } } - + [Theory] [InlineData("test")] [InlineData("super")] @@ -325,4 +341,4 @@ namespace Kyoo.Tests.Database KAssert.DeepEqual(value, ret.First()); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/GenreTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/GenreTests.cs index 0b5d8489..22211a3d 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/GenreTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/GenreTests.cs @@ -1,3 +1,22 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.Diagnostics.CodeAnalysis; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Xunit; @@ -26,6 +45,7 @@ namespace Kyoo.Tests.Database public abstract class AGenreTests : RepositoryTests { + [SuppressMessage("ReSharper", "NotAccessedField.Local")] private readonly IGenreRepository _repository; protected AGenreTests(RepositoryActivator repositories) @@ -34,4 +54,4 @@ namespace Kyoo.Tests.Database _repository = Repositories.LibraryManager.GenreRepository; } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/LibraryItemTest.cs b/tests/Kyoo.Tests/Database/SpecificTests/LibraryItemTest.cs index d370996a..2002e5ef 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/LibraryItemTest.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/LibraryItemTest.cs @@ -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 . + using System; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; @@ -16,7 +34,6 @@ namespace Kyoo.Tests.Database } } - namespace PostgreSQL { [Collection(nameof(Postgresql))] @@ -26,12 +43,12 @@ namespace Kyoo.Tests.Database : base(new RepositoryActivator(output, postgres)) { } } } - + public abstract class ALibraryItemTest { private readonly ILibraryItemRepository _repository; private readonly RepositoryActivator _repositories; - + protected ALibraryItemTest(RepositoryActivator repositories) { _repositories = repositories; @@ -43,7 +60,7 @@ namespace Kyoo.Tests.Database { Assert.Equal(2, await _repository.GetCount()); } - + [Fact] public async Task GetShowTests() { @@ -51,7 +68,7 @@ namespace Kyoo.Tests.Database LibraryItem actual = await _repository.Get(1); KAssert.DeepEqual(expected, actual); } - + [Fact] public async Task GetCollectionTests() { @@ -59,7 +76,7 @@ namespace Kyoo.Tests.Database LibraryItem actual = await _repository.Get(-1); KAssert.DeepEqual(expected, actual); } - + [Fact] public async Task GetShowSlugTests() { @@ -67,7 +84,7 @@ namespace Kyoo.Tests.Database LibraryItem actual = await _repository.Get(TestSample.Get().Slug); KAssert.DeepEqual(expected, actual); } - + [Fact] public async Task GetCollectionSlugTests() { @@ -75,7 +92,7 @@ namespace Kyoo.Tests.Database LibraryItem actual = await _repository.Get(TestSample.Get().Slug); KAssert.DeepEqual(expected, actual); } - + [Fact] public async Task GetDuplicatedSlugTests() { @@ -87,4 +104,4 @@ namespace Kyoo.Tests.Database await Assert.ThrowsAsync(() => _repository.Get(TestSample.Get().Slug)); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/LibraryTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/LibraryTests.cs index a1a3d131..d440537b 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/LibraryTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/LibraryTests.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -48,15 +66,15 @@ namespace Kyoo.Tests.Database library.Paths = null; await Assert.ThrowsAsync(() => _repository.Create(library)); } - + [Fact] public async Task CreateWithEmptySlugTest() { Library library = TestSample.GetNew(); - library.Slug = ""; + library.Slug = string.Empty; await Assert.ThrowsAsync(() => _repository.Create(library)); } - + [Fact] public async Task CreateWithNumberSlugTest() { @@ -65,7 +83,7 @@ namespace Kyoo.Tests.Database Library ret = await _repository.Create(library); Assert.Equal("2!", ret.Slug); } - + [Fact] public async Task CreateWithoutNameTest() { @@ -73,7 +91,7 @@ namespace Kyoo.Tests.Database library.Name = null; await Assert.ThrowsAsync(() => _repository.Create(library)); } - + [Fact] public async Task CreateWithProvider() { @@ -90,16 +108,16 @@ namespace Kyoo.Tests.Database public async Task EditTest() { Library value = await _repository.Get(TestSample.Get().Slug); - value.Paths = new [] {"/super", "/test"}; + value.Paths = new[] { "/super", "/test" }; value.Name = "New Title"; Library edited = await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); Library show = await database.Libraries.FirstAsync(); - + KAssert.DeepEqual(show, edited); } - + [Fact] public async Task EditProvidersTest() { @@ -109,17 +127,17 @@ namespace Kyoo.Tests.Database TestSample.GetNew() }; Library edited = await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); Library show = await database.Libraries .Include(x => x.Providers) .FirstAsync(); - + show.Providers.ForEach(x => x.Libraries = null); edited.Providers.ForEach(x => x.Libraries = null); KAssert.DeepEqual(show, edited); } - + [Fact] public async Task AddProvidersTest() { @@ -127,17 +145,17 @@ namespace Kyoo.Tests.Database await Repositories.LibraryManager.Load(value, x => x.Providers); value.Providers.Add(TestSample.GetNew()); Library edited = await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); Library show = await database.Libraries .Include(x => x.Providers) .FirstAsync(); - + show.Providers.ForEach(x => x.Libraries = null); edited.Providers.ForEach(x => x.Libraries = null); KAssert.DeepEqual(show, edited); } - + [Theory] [InlineData("test")] [InlineData("super")] @@ -150,11 +168,11 @@ namespace Kyoo.Tests.Database { Slug = "super-test", Name = "This is a test title", - Paths = new [] {"path"} + Paths = new[] { "path" } }; await _repository.Create(value); ICollection ret = await _repository.Search(query); KAssert.DeepEqual(value, ret.First()); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/PeopleTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/PeopleTests.cs index 669f6f91..4b416ec7 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/PeopleTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/PeopleTests.cs @@ -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 . + using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -38,7 +56,7 @@ namespace Kyoo.Tests.Database { _repository = Repositories.LibraryManager.PeopleRepository; } - + [Fact] public async Task CreateWithExternalIdTest() { @@ -59,14 +77,14 @@ namespace Kyoo.Tests.Database } }; await _repository.Create(value); - + People retrieved = await _repository.Get(2); await Repositories.LibraryManager.Load(retrieved, x => x.ExternalIDs); Assert.Equal(2, retrieved.ExternalIDs.Count); KAssert.DeepEqual(value.ExternalIDs.First(), retrieved.ExternalIDs.First()); KAssert.DeepEqual(value.ExternalIDs.Last(), retrieved.ExternalIDs.Last()); } - + [Fact] public async Task EditTest() { @@ -77,13 +95,13 @@ namespace Kyoo.Tests.Database [Images.Poster] = "new-poster" }; await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); People retrieved = await database.People.FirstAsync(); - + KAssert.DeepEqual(value, retrieved); } - + [Fact] public async Task EditMetadataTest() { @@ -98,13 +116,13 @@ namespace Kyoo.Tests.Database }, }; await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); People retrieved = await database.People .Include(x => x.ExternalIDs) .ThenInclude(x => x.Provider) .FirstAsync(); - + KAssert.DeepEqual(value, retrieved); } @@ -140,7 +158,7 @@ namespace Kyoo.Tests.Database DataID = "id" }); await _repository.Edit(value, false); - + { await using DatabaseContext database = Repositories.Context.New(); People retrieved = await database.People @@ -151,7 +169,7 @@ namespace Kyoo.Tests.Database KAssert.DeepEqual(value, retrieved); } } - + [Theory] [InlineData("Me")] [InlineData("me")] @@ -168,4 +186,4 @@ namespace Kyoo.Tests.Database KAssert.DeepEqual(value, ret.First()); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/ProviderTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/ProviderTests.cs index 06edde1b..62d33528 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/ProviderTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/ProviderTests.cs @@ -1,3 +1,22 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.Diagnostics.CodeAnalysis; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Xunit; @@ -26,6 +45,7 @@ namespace Kyoo.Tests.Database public abstract class AProviderTests : RepositoryTests { + [SuppressMessage("ReSharper", "NotAccessedField.Local")] private readonly IProviderRepository _repository; protected AProviderTests(RepositoryActivator repositories) @@ -34,4 +54,4 @@ namespace Kyoo.Tests.Database _repository = Repositories.LibraryManager.ProviderRepository; } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/SanityTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/SanityTests.cs index efbdbd26..5748177a 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/SanityTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/SanityTests.cs @@ -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 . + using System; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; @@ -10,10 +28,10 @@ namespace Kyoo.Tests.Database public class GlobalTests : IDisposable, IAsyncDisposable { private readonly RepositoryActivator _repositories; - + public GlobalTests(ITestOutputHelper output) { - _repositories = new RepositoryActivator(output); + _repositories = new RepositoryActivator(output); } public void Dispose() @@ -26,7 +44,7 @@ namespace Kyoo.Tests.Database { return _repositories.DisposeAsync(); } - + [Fact] [SuppressMessage("ReSharper", "EqualExpressionComparison")] public void SampleTest() @@ -34,4 +52,4 @@ namespace Kyoo.Tests.Database Assert.False(ReferenceEquals(TestSample.Get(), TestSample.Get())); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/SeasonTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/SeasonTests.cs index 54d164a9..1bfeeb2b 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/SeasonTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/SeasonTests.cs @@ -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 . + using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -19,7 +37,6 @@ namespace Kyoo.Tests.Database } } - namespace PostgreSQL { [Collection(nameof(Postgresql))] @@ -54,7 +71,7 @@ namespace Kyoo.Tests.Database season = await _repository.Get(1); Assert.Equal("new-slug-s1", season.Slug); } - + [Fact] public async Task SeasonNumberEditTest() { @@ -69,7 +86,7 @@ namespace Kyoo.Tests.Database season = await _repository.Get(1); Assert.Equal("anohana-s2", season.Slug); } - + [Fact] public async Task SeasonCreationSlugTest() { @@ -80,7 +97,7 @@ namespace Kyoo.Tests.Database }); Assert.Equal($"{TestSample.Get().Slug}-s2", season.Slug); } - + [Fact] public async Task CreateWithExternalIdTest() { @@ -101,14 +118,14 @@ namespace Kyoo.Tests.Database } }; await _repository.Create(season); - + Season retrieved = await _repository.Get(2); await Repositories.LibraryManager.Load(retrieved, x => x.ExternalIDs); Assert.Equal(2, retrieved.ExternalIDs.Count); KAssert.DeepEqual(season.ExternalIDs.First(), retrieved.ExternalIDs.First()); KAssert.DeepEqual(season.ExternalIDs.Last(), retrieved.ExternalIDs.Last()); } - + [Fact] public async Task EditTest() { @@ -119,13 +136,13 @@ namespace Kyoo.Tests.Database [Images.Poster] = "new-poster" }; await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); Season retrieved = await database.Seasons.FirstAsync(); - + KAssert.DeepEqual(value, retrieved); } - + [Fact] public async Task EditMetadataTest() { @@ -140,13 +157,13 @@ namespace Kyoo.Tests.Database }, }; await _repository.Edit(value, false); - + await using DatabaseContext database = Repositories.Context.New(); Season retrieved = await database.Seasons .Include(x => x.ExternalIDs) .ThenInclude(x => x.Provider) .FirstAsync(); - + KAssert.DeepEqual(value, retrieved); } @@ -182,7 +199,7 @@ namespace Kyoo.Tests.Database DataID = "id" }); await _repository.Edit(value, false); - + { await using DatabaseContext database = Repositories.Context.New(); Season retrieved = await database.Seasons @@ -193,7 +210,7 @@ namespace Kyoo.Tests.Database KAssert.DeepEqual(value, retrieved); } } - + [Theory] [InlineData("test")] [InlineData("super")] @@ -212,4 +229,4 @@ namespace Kyoo.Tests.Database KAssert.DeepEqual(value, ret.First()); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/ShowTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/ShowTests.cs index b502e125..12c1cead 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/ShowTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/ShowTests.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -41,7 +59,7 @@ namespace Kyoo.Tests.Database { _repository = Repositories.LibraryManager.ShowRepository; } - + [Fact] public async Task EditTest() { @@ -50,32 +68,32 @@ namespace Kyoo.Tests.Database value.Title = "New Title"; Show edited = await _repository.Edit(value, false); KAssert.DeepEqual(value, edited); - + await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows.FirstAsync(); - + KAssert.DeepEqual(show, value); } - + [Fact] public async Task EditGenreTest() { Show value = await _repository.Get(TestSample.Get().Slug); - value.Genres = new[] {new Genre("test")}; + value.Genres = new[] { new Genre("test") }; Show edited = await _repository.Edit(value, false); - + Assert.Equal(value.Slug, edited.Slug); - Assert.Equal(value.Genres.Select(x => new{x.Slug, x.Name}), edited.Genres.Select(x => new{x.Slug, x.Name})); - + Assert.Equal(value.Genres.Select(x => new { x.Slug, x.Name }), edited.Genres.Select(x => new { x.Slug, x.Name })); + await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.Genres) .FirstAsync(); - + Assert.Equal(value.Slug, show.Slug); - Assert.Equal(value.Genres.Select(x => new{x.Slug, x.Name}), show.Genres.Select(x => new{x.Slug, x.Name})); + Assert.Equal(value.Genres.Select(x => new { x.Slug, x.Name }), show.Genres.Select(x => new { x.Slug, x.Name })); } - + [Fact] public async Task AddGenreTest() { @@ -83,55 +101,55 @@ namespace Kyoo.Tests.Database await Repositories.LibraryManager.Load(value, x => x.Genres); value.Genres.Add(new Genre("test")); Show edited = await _repository.Edit(value, false); - + Assert.Equal(value.Slug, edited.Slug); - Assert.Equal(value.Genres.Select(x => new{x.Slug, x.Name}), edited.Genres.Select(x => new{x.Slug, x.Name})); - + Assert.Equal(value.Genres.Select(x => new { x.Slug, x.Name }), edited.Genres.Select(x => new { x.Slug, x.Name })); + await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.Genres) .FirstAsync(); - + Assert.Equal(value.Slug, show.Slug); - Assert.Equal(value.Genres.Select(x => new{x.Slug, x.Name}), show.Genres.Select(x => new{x.Slug, x.Name})); + Assert.Equal(value.Genres.Select(x => new { x.Slug, x.Name }), show.Genres.Select(x => new { x.Slug, x.Name })); } - + [Fact] public async Task EditStudioTest() { Show value = await _repository.Get(TestSample.Get().Slug); value.Studio = new Studio("studio"); Show edited = await _repository.Edit(value, false); - + Assert.Equal(value.Slug, edited.Slug); Assert.Equal("studio", edited.Studio.Slug); - + await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.Studio) .FirstAsync(); - + Assert.Equal(value.Slug, show.Slug); Assert.Equal("studio", show.Studio.Slug); } - + [Fact] public async Task EditAliasesTest() { Show value = await _repository.Get(TestSample.Get().Slug); - value.Aliases = new[] {"NiceNewAlias", "SecondAlias"}; + value.Aliases = new[] { "NiceNewAlias", "SecondAlias" }; Show edited = await _repository.Edit(value, false); - + Assert.Equal(value.Slug, edited.Slug); Assert.Equal(value.Aliases, edited.Aliases); - + await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows.FirstAsync(); - + Assert.Equal(value.Slug, show.Slug); Assert.Equal(value.Aliases, show.Aliases); } - + [Fact] public async Task EditPeopleTest() { @@ -148,25 +166,25 @@ namespace Kyoo.Tests.Database } }; Show edited = await _repository.Edit(value, false); - + Assert.Equal(value.Slug, edited.Slug); Assert.Equal(edited.People.First().ShowID, value.ID); Assert.Equal( - value.People.Select(x => new{x.Role, x.Slug, x.People.Name}), - edited.People.Select(x => new{x.Role, x.Slug, x.People.Name})); - + value.People.Select(x => new { x.Role, x.Slug, x.People.Name }), + edited.People.Select(x => new { x.Role, x.Slug, x.People.Name })); + await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.People) .ThenInclude(x => x.People) .FirstAsync(); - + Assert.Equal(value.Slug, show.Slug); Assert.Equal( - value.People.Select(x => new{x.Role, x.Slug, x.People.Name}), - show.People.Select(x => new{x.Role, x.Slug, x.People.Name})); + value.People.Select(x => new { x.Role, x.Slug, x.People.Name }), + show.People.Select(x => new { x.Role, x.Slug, x.People.Name })); } - + [Fact] public async Task EditExternalIDsTest() { @@ -180,24 +198,24 @@ namespace Kyoo.Tests.Database } }; Show edited = await _repository.Edit(value, false); - + Assert.Equal(value.Slug, edited.Slug); Assert.Equal( - value.ExternalIDs.Select(x => new {x.DataID, x.Provider.Slug}), - edited.ExternalIDs.Select(x => new {x.DataID, x.Provider.Slug})); - + value.ExternalIDs.Select(x => new { x.DataID, x.Provider.Slug }), + edited.ExternalIDs.Select(x => new { x.DataID, x.Provider.Slug })); + await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.ExternalIDs) .ThenInclude(x => x.Provider) .FirstAsync(); - + Assert.Equal(value.Slug, show.Slug); Assert.Equal( - value.ExternalIDs.Select(x => new {x.DataID, x.Provider.Slug}), - show.ExternalIDs.Select(x => new {x.DataID, x.Provider.Slug})); + value.ExternalIDs.Select(x => new { x.DataID, x.Provider.Slug }), + show.ExternalIDs.Select(x => new { x.DataID, x.Provider.Slug })); } - + [Fact] public async Task EditResetOldTest() { @@ -207,12 +225,12 @@ namespace Kyoo.Tests.Database ID = value.ID, Title = "Reset" }; - + await Assert.ThrowsAsync(() => _repository.Edit(newValue, true)); - + newValue.Slug = "reset"; Show edited = await _repository.Edit(newValue, true); - + Assert.Equal(value.ID, edited.ID); Assert.Null(edited.Overview); Assert.Equal("reset", edited.Slug); @@ -223,7 +241,7 @@ namespace Kyoo.Tests.Database Assert.Null(edited.Genres); Assert.Null(edited.Studio); } - + [Fact] public async Task CreateWithRelationsTest() { @@ -259,7 +277,7 @@ namespace Kyoo.Tests.Database expected.Studio = new Studio("studio"); Show created = await _repository.Create(expected); KAssert.DeepEqual(expected, created); - + await using DatabaseContext context = Repositories.Context.New(); Show retrieved = await context.Shows .Include(x => x.ExternalIDs) @@ -269,14 +287,14 @@ namespace Kyoo.Tests.Database .ThenInclude(x => x.People) .Include(x => x.Studio) .FirstAsync(x => x.ID == created.ID); - retrieved.People.ForEach(x => + retrieved.People.ForEach(x => { x.Show = null; x.People.Roles = null; }); retrieved.Studio.Shows = null; retrieved.Genres.ForEach(x => x.Shows = null); - + expected.Genres.ForEach(x => x.Shows = null); expected.People.ForEach(x => { @@ -286,7 +304,7 @@ namespace Kyoo.Tests.Database retrieved.Should().BeEquivalentTo(expected); } - + [Fact] public async Task CreateWithExternalID() { @@ -322,14 +340,14 @@ namespace Kyoo.Tests.Database Show created = await _repository.Create(test); Assert.Equal("300!", created.Slug); } - + [Fact] public async Task GetSlugTest() { Show reference = TestSample.Get(); Assert.Equal(reference.Slug, await _repository.GetSlug(reference.ID)); } - + [Theory] [InlineData("test")] [InlineData("super")] @@ -341,13 +359,13 @@ namespace Kyoo.Tests.Database Show value = new() { Slug = "super-test", - Title = "This is a test title²" + Title = "This is a test title?" }; await _repository.Create(value); ICollection ret = await _repository.Search(query); KAssert.DeepEqual(value, ret.First()); } - + [Fact] public async Task DeleteShowWithEpisodeAndSeason() { @@ -368,7 +386,7 @@ namespace Kyoo.Tests.Database { await Repositories.LibraryManager.Create(TestSample.GetNew()); await _repository.AddShowLink(1, 2, null); - + await using DatabaseContext context = Repositories.Context.New(); Show show = context.Shows .Include(x => x.Libraries) @@ -376,4 +394,4 @@ namespace Kyoo.Tests.Database Assert.Contains(2, show.Libraries.Select(x => x.ID)); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/StudioTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/StudioTests.cs index 8b64bded..b024d435 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/StudioTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/StudioTests.cs @@ -1,3 +1,22 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.Diagnostics.CodeAnalysis; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Xunit; @@ -26,6 +45,7 @@ namespace Kyoo.Tests.Database public abstract class AStudioTests : RepositoryTests { + [SuppressMessage("ReSharper", "NotAccessedField.Local")] private readonly IStudioRepository _repository; protected AStudioTests(RepositoryActivator repositories) @@ -34,4 +54,4 @@ namespace Kyoo.Tests.Database _repository = Repositories.LibraryManager.StudioRepository; } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/TrackTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/TrackTests.cs index 2bf7cc17..7a97d7ca 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/TrackTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/TrackTests.cs @@ -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 . + using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; @@ -15,7 +33,6 @@ namespace Kyoo.Tests.Database } } - namespace PostgreSQL { [Collection(nameof(Postgresql))] @@ -35,7 +52,7 @@ namespace Kyoo.Tests.Database { _repository = repositories.LibraryManager.TrackRepository; } - + [Fact] public async Task SlugEditTest() { @@ -47,7 +64,7 @@ namespace Kyoo.Tests.Database Track track = await _repository.Get(1); Assert.Equal("new-slug-s1e1.eng-1.subtitle", track.Slug); } - + [Fact] public async Task UndefinedLanguageSlugTest() { @@ -63,4 +80,4 @@ namespace Kyoo.Tests.Database Assert.Equal("anohana-s1e1.und.video", track.Slug); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/SpecificTests/UserTests.cs b/tests/Kyoo.Tests/Database/SpecificTests/UserTests.cs index a9f7b0bc..5228356a 100644 --- a/tests/Kyoo.Tests/Database/SpecificTests/UserTests.cs +++ b/tests/Kyoo.Tests/Database/SpecificTests/UserTests.cs @@ -1,3 +1,22 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.Diagnostics.CodeAnalysis; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Xunit; @@ -26,6 +45,7 @@ namespace Kyoo.Tests.Database public abstract class AUserTests : RepositoryTests { + [SuppressMessage("ReSharper", "NotAccessedField.Local")] private readonly IUserRepository _repository; protected AUserTests(RepositoryActivator repositories) @@ -34,4 +54,4 @@ namespace Kyoo.Tests.Database _repository = Repositories.LibraryManager.UserRepository; } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Database/TestContext.cs b/tests/Kyoo.Tests/Database/TestContext.cs index 79d873c4..933bda0d 100644 --- a/tests/Kyoo.Tests/Database/TestContext.cs +++ b/tests/Kyoo.Tests/Database/TestContext.cs @@ -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 . + using System; using System.Threading.Tasks; using Kyoo.Database; @@ -18,7 +36,7 @@ namespace Kyoo.Tests /// The internal sqlite connection used by all context returned by this class. /// private readonly SqliteConnection _connection; - + /// /// The context's options that specify to use an in memory Sqlite database. /// @@ -28,7 +46,7 @@ namespace Kyoo.Tests { _connection = new SqliteConnection("DataSource=:memory:"); _connection.Open(); - + _context = new DbContextOptionsBuilder() .UseSqlite(_connection) .UseLoggerFactory(LoggerFactory.Create(x => @@ -39,12 +57,12 @@ namespace Kyoo.Tests .EnableSensitiveDataLogging() .EnableDetailedErrors() .Options; - + using DatabaseContext context = New(); context.Database.Migrate(); TestSample.FillDatabase(context); } - + public override void Dispose() { _connection.Close(); @@ -60,30 +78,30 @@ namespace Kyoo.Tests return new SqLiteContext(_context); } } - + [CollectionDefinition(nameof(Postgresql))] public class PostgresCollection : ICollectionFixture - {} + { } public sealed class PostgresFixture : IDisposable { private readonly DbContextOptions _options; - + public string Template { get; } public string Connection => PostgresTestContext.GetConnectionString(Template); - + public PostgresFixture() { // TODO Assert.Skip when postgres is not available. (this needs xunit v3) - + string id = Guid.NewGuid().ToString().Replace('-', '_'); Template = $"kyoo_template_{id}"; - + _options = new DbContextOptionsBuilder() .UseNpgsql(Connection) .Options; - + using PostgresContext context = new(_options); context.Database.Migrate(); @@ -94,19 +112,19 @@ namespace Kyoo.Tests TestSample.FillDatabase(context); conn.Close(); } - + public void Dispose() { using PostgresContext context = new(_options); context.Database.EnsureDeleted(); } } - + public sealed class PostgresTestContext : TestContext { private readonly NpgsqlConnection _connection; private readonly DbContextOptions _context; - + public PostgresTestContext(PostgresFixture template, ITestOutputHelper output) { string id = Guid.NewGuid().ToString().Replace('-', '_'); @@ -133,7 +151,7 @@ namespace Kyoo.Tests .EnableDetailedErrors() .Options; } - + public static string GetConnectionString(string database) { string server = Environment.GetEnvironmentVariable("POSTGRES_HOST") ?? "127.0.0.1"; @@ -142,7 +160,7 @@ namespace Kyoo.Tests string password = Environment.GetEnvironmentVariable("POSTGRES_PASSWORD") ?? "kyooPassword"; return $"Server={server};Port={port};Database={database};User ID={username};Password={password};Include Error Detail=true"; } - + public override void Dispose() { using DatabaseContext db = New(); @@ -162,8 +180,7 @@ namespace Kyoo.Tests return new PostgresContext(_context); } } - - + /// /// Class responsible to fill and create in memory databases for unit tests. /// @@ -172,18 +189,18 @@ namespace Kyoo.Tests /// /// Add an arbitrary data to the test context. /// - public void Add(T obj) + public void Add(T obj) where T : class { using DatabaseContext context = New(); context.Set().Add(obj); context.SaveChanges(); } - + /// /// Add an arbitrary data to the test context. /// - public async Task AddAsync(T obj) + public async Task AddAsync(T obj) where T : class { await using DatabaseContext context = New(); diff --git a/tests/Kyoo.Tests/Database/TestSample.cs b/tests/Kyoo.Tests/Database/TestSample.cs index 2cf72abd..13b9a0e9 100644 --- a/tests/Kyoo.Tests/Database/TestSample.cs +++ b/tests/Kyoo.Tests/Database/TestSample.cs @@ -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 . + using System; using System.Collections.Generic; using Kyoo.Abstractions.Models; @@ -16,7 +34,7 @@ namespace Kyoo.Tests ID = 2, Slug = "new-library", Name = "New Library", - Paths = new [] {"/a/random/path"} + Paths = new[] { "/a/random/path" } } }, { @@ -121,8 +139,7 @@ namespace Kyoo.Tests } } }; - - + private static readonly Dictionary> Samples = new() { { @@ -132,7 +149,7 @@ namespace Kyoo.Tests ID = 1, Slug = "deck", Name = "Deck", - Paths = new[] {"/path/to/deck"} + Paths = new[] { "/path/to/deck" } } }, { @@ -190,7 +207,7 @@ namespace Kyoo.Tests Title = "Season 1", Overview = "The first season", StartDate = new DateTime(2020, 06, 05), - EndDate = new DateTime(2020, 07, 05), + EndDate = new DateTime(2020, 07, 05), Images = new Dictionary { [Images.Poster] = "Poster", @@ -297,7 +314,7 @@ namespace Kyoo.Tests Username = "User", Email = "user@im-a-user.com", Password = "MD5-encoded", - Permissions = new [] {"overall.read"} + Permissions = new[] { "overall.read" } } } }; @@ -306,7 +323,7 @@ namespace Kyoo.Tests { return (T)Samples[typeof(T)](); } - + public static T GetNew() { return (T)NewSamples[typeof(T)](); @@ -317,7 +334,7 @@ namespace Kyoo.Tests Collection collection = Get(); collection.ID = 0; context.Collections.Add(collection); - + Show show = Get(); show.ID = 0; show.StudioID = 0; @@ -345,26 +362,26 @@ namespace Kyoo.Tests Studio studio = Get(); studio.ID = 0; - studio.Shows = new List {show}; + studio.Shows = new List { show }; context.Studios.Add(studio); Genre genre = Get(); genre.ID = 0; - genre.Shows = new List {show}; + genre.Shows = new List { show }; context.Genres.Add(genre); People people = Get(); people.ID = 0; context.People.Add(people); - + Provider provider = Get(); provider.ID = 0; context.Providers.Add(provider); - + Library library = Get(); library.ID = 0; - library.Collections = new List {collection}; - library.Providers = new List {provider}; + library.Collections = new List { collection }; + library.Providers = new List { provider }; context.Libraries.Add(library); User user = Get(); @@ -417,4 +434,4 @@ namespace Kyoo.Tests }; } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Identifier/IdentifierTests.cs b/tests/Kyoo.Tests/Identifier/IdentifierTests.cs index 3ab526d6..2a4da53e 100644 --- a/tests/Kyoo.Tests/Identifier/IdentifierTests.cs +++ b/tests/Kyoo.Tests/Identifier/IdentifierTests.cs @@ -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 . + using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; @@ -14,13 +32,13 @@ namespace Kyoo.Tests.Identifier { private readonly Mock _manager; private readonly IIdentifier _identifier; - + public Identifier() { Mock> options = new(); options.Setup(x => x.CurrentValue).Returns(new MediaOptions { - Regex = new [] + Regex = new[] { "^\\/?(?.+)?\\/(?.+?)(?: \\((?\\d+)\\))?\\/\\k(?: \\(\\d+\\))? S(?\\d+)E(?\\d+)\\..*$", "^\\/?(?.+)?\\/(?.+?)(?: \\((?\\d+)\\))?\\/\\k(?: \\(\\d+\\))? (?\\d+)\\..*$", @@ -31,12 +49,11 @@ namespace Kyoo.Tests.Identifier "^(?.+)\\.(?\\w{1,3})\\.(?default\\.)?(?forced\\.)?.*$" } }); - + _manager = new Mock(); _identifier = new RegexIdentifier(options.Object, _manager.Object); } - - + [Fact] public async Task EpisodeIdentification() { @@ -56,7 +73,7 @@ namespace Kyoo.Tests.Identifier Assert.Equal(1, episode.EpisodeNumber); Assert.Null(episode.AbsoluteNumber); } - + [Fact] public async Task EpisodeIdentificationWithoutLibraryTrailingSlash() { @@ -76,7 +93,7 @@ namespace Kyoo.Tests.Identifier Assert.Equal(1, episode.EpisodeNumber); Assert.Null(episode.AbsoluteNumber); } - + [Fact] public async Task EpisodeIdentificationMultiplePaths() { @@ -96,7 +113,7 @@ namespace Kyoo.Tests.Identifier Assert.Equal(1, episode.EpisodeNumber); Assert.Null(episode.AbsoluteNumber); } - + [Fact] public async Task AbsoluteEpisodeIdentification() { @@ -116,7 +133,7 @@ namespace Kyoo.Tests.Identifier Assert.Null(episode.EpisodeNumber); Assert.Equal(100, episode.AbsoluteNumber); } - + [Fact] public async Task MovieEpisodeIdentification() { @@ -137,7 +154,7 @@ namespace Kyoo.Tests.Identifier Assert.Null(episode.EpisodeNumber); Assert.Null(episode.AbsoluteNumber); } - + [Fact] public async Task InvalidEpisodeIdentification() { @@ -147,7 +164,7 @@ namespace Kyoo.Tests.Identifier }); await Assert.ThrowsAsync(() => _identifier.Identify("/invalid/path")); } - + [Fact] public async Task SubtitleIdentification() { @@ -163,7 +180,7 @@ namespace Kyoo.Tests.Identifier Assert.False(track.IsForced); Assert.StartsWith("/kyoo/Library/Collection/Show (2000)/Show", track.Episode.Path); } - + [Fact] public async Task SubtitleIdentificationUnknownCodec() { @@ -179,7 +196,7 @@ namespace Kyoo.Tests.Identifier Assert.False(track.IsForced); Assert.StartsWith("/kyoo/Library/Collection/Show (2000)/Show", track.Episode.Path); } - + [Fact] public async Task InvalidSubtitleIdentification() { @@ -190,4 +207,4 @@ namespace Kyoo.Tests.Identifier await Assert.ThrowsAsync(() => _identifier.IdentifyTrack("/invalid/path")); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Identifier/ProviderTests.cs b/tests/Kyoo.Tests/Identifier/ProviderTests.cs index 384e6b79..f0e9fb96 100644 --- a/tests/Kyoo.Tests/Identifier/ProviderTests.cs +++ b/tests/Kyoo.Tests/Identifier/ProviderTests.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -15,7 +33,7 @@ namespace Kyoo.Tests.Identifier public class ProviderTests { private readonly ILoggerFactory _factory; - + public ProviderTests(ITestOutputHelper output) { _factory = LoggerFactory.Create(x => @@ -24,7 +42,7 @@ namespace Kyoo.Tests.Identifier x.AddXunit(output); }); } - + [Fact] public async Task NoProviderGetTest() { @@ -38,7 +56,7 @@ namespace Kyoo.Tests.Identifier Show ret = await provider.Get(show); KAssert.DeepEqual(show, ret); } - + [Fact] public async Task NoProviderSearchTest() { @@ -47,7 +65,7 @@ namespace Kyoo.Tests.Identifier ICollection ret = await provider.Search("show"); Assert.Empty(ret); } - + [Fact] public async Task OneProviderGetTest() { @@ -60,14 +78,14 @@ namespace Kyoo.Tests.Identifier mock.Setup(x => x.Get(show)).ReturnsAsync(new Show { Title = "title", - Genres = new[] { new Genre("ToMerge")} + Genres = new[] { new Genre("ToMerge") } }); - AProviderComposite provider = new ProviderComposite(new [] + AProviderComposite provider = new ProviderComposite(new[] { mock.Object }, _factory.CreateLogger()); - + Show ret = await provider.Get(show); Assert.Equal(4, ret.ID); Assert.Equal("title", ret.Title); @@ -75,7 +93,7 @@ namespace Kyoo.Tests.Identifier Assert.Contains("genre", ret.Genres.Select(x => x.Slug)); Assert.Contains("tomerge", ret.Genres.Select(x => x.Slug)); } - + [Fact] public async Task FailingProviderGetTest() { @@ -85,34 +103,34 @@ namespace Kyoo.Tests.Identifier Genres = new[] { new Genre("genre") } }; Mock mock = new(); - mock.Setup(x => x.Provider).Returns(new Provider("mock", "")); + mock.Setup(x => x.Provider).Returns(new Provider("mock", string.Empty)); mock.Setup(x => x.Get(show)).ReturnsAsync(new Show { Title = "title", - Genres = new[] { new Genre("ToMerge")} + Genres = new[] { new Genre("ToMerge") } }); - + Mock mockTwo = new(); - mockTwo.Setup(x => x.Provider).Returns(new Provider("mockTwo", "")); + mockTwo.Setup(x => x.Provider).Returns(new Provider("mockTwo", string.Empty)); mockTwo.Setup(x => x.Get(show)).ReturnsAsync(new Show { Title = "title2", Status = Status.Finished, - Genres = new[] { new Genre("ToMerge")} + Genres = new[] { new Genre("ToMerge") } }); - + Mock mockFailing = new(); - mockFailing.Setup(x => x.Provider).Returns(new Provider("mockFail", "")); + mockFailing.Setup(x => x.Provider).Returns(new Provider("mockFail", string.Empty)); mockFailing.Setup(x => x.Get(show)).Throws(); - - AProviderComposite provider = new ProviderComposite(new [] + + AProviderComposite provider = new ProviderComposite(new[] { mock.Object, mockTwo.Object, mockFailing.Object }, _factory.CreateLogger()); - + Show ret = await provider.Get(show); Assert.Equal(4, ret.ID); Assert.Equal("title", ret.Title); @@ -122,4 +140,4 @@ namespace Kyoo.Tests.Identifier Assert.Contains("tomerge", ret.Genres.Select(x => x.Slug)); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Identifier/Tvdb/ConvertorTests.cs b/tests/Kyoo.Tests/Identifier/Tvdb/ConvertorTests.cs index 48e6cf56..cb0aa847 100644 --- a/tests/Kyoo.Tests/Identifier/Tvdb/ConvertorTests.cs +++ b/tests/Kyoo.Tests/Identifier/Tvdb/ConvertorTests.cs @@ -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 . + using System; using System.Linq; using Kyoo.Abstractions.Models; @@ -25,7 +43,7 @@ namespace Kyoo.Tests.Identifier.Tvdb }; Provider provider = TestSample.Get(); Show show = result.ToShow(provider); - + Assert.Equal("slug", show.Slug); Assert.Equal("name", show.Title); Assert.Single(show.Aliases); @@ -85,15 +103,15 @@ namespace Kyoo.Tests.Identifier.Tvdb Poster = "poster", FanArt = "fanart", Id = 5, - Genre = new [] + Genre = new[] { "Action", - "Test With Spéàacial characters" + "Test With Sp??acial characters" } }; Provider provider = TestSample.Get(); Show show = result.ToShow(provider); - + Assert.Equal("slug", show.Slug); Assert.Equal("name", show.Title); Assert.Single(show.Aliases); @@ -110,8 +128,8 @@ namespace Kyoo.Tests.Identifier.Tvdb Assert.Equal(2, show.Genres.Count); Assert.Equal("action", show.Genres.ToArray()[0].Slug); Assert.Equal("Action", show.Genres.ToArray()[0].Name); - Assert.Equal("Test With Spéàacial characters", show.Genres.ToArray()[1].Name); - Assert.Equal("test-with-speaacial-characters", show.Genres.ToArray()[1].Slug); + Assert.Equal("Test With Sp??acial characters", show.Genres.ToArray()[1].Name); + Assert.Equal("test-with-spacial-characters", show.Genres.ToArray()[1].Slug); } [Fact] @@ -125,13 +143,13 @@ namespace Kyoo.Tests.Identifier.Tvdb Role = "role" }; PeopleRole people = actor.ToPeopleRole(); - + Assert.Equal("name", people.Slug); Assert.Equal("Name", people.People.Name); Assert.Equal("role", people.Role); Assert.Equal("https://www.thetvdb.com/banners/image", people.People.Images[Images.Poster]); } - + [Fact] public void EpisodeRecordToEpisode() { @@ -147,7 +165,7 @@ namespace Kyoo.Tests.Identifier.Tvdb }; Provider provider = TestSample.Get(); Episode episode = record.ToEpisode(provider); - + Assert.Equal("title", episode.Title); Assert.Equal(2, episode.SeasonNumber); Assert.Equal(3, episode.EpisodeNumber); @@ -156,4 +174,4 @@ namespace Kyoo.Tests.Identifier.Tvdb Assert.Equal("https://www.thetvdb.com/banners/thumb", episode.Images[Images.Thumbnail]); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/KAssert.cs b/tests/Kyoo.Tests/KAssert.cs index e4c2e28f..e6edb5c6 100644 --- a/tests/Kyoo.Tests/KAssert.cs +++ b/tests/Kyoo.Tests/KAssert.cs @@ -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 . + using FluentAssertions; using JetBrains.Annotations; using Xunit.Sdk; @@ -29,7 +47,7 @@ namespace Kyoo.Tests { throw new XunitException(); } - + /// /// Explicitly fail a test. /// @@ -40,4 +58,4 @@ namespace Kyoo.Tests throw new XunitException(message); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Kyoo.Tests.csproj b/tests/Kyoo.Tests/Kyoo.Tests.csproj index 02627f91..330c41f7 100644 --- a/tests/Kyoo.Tests/Kyoo.Tests.csproj +++ b/tests/Kyoo.Tests/Kyoo.Tests.csproj @@ -32,10 +32,10 @@ - - - - + + + + diff --git a/tests/Kyoo.Tests/Utility/EnumerableTests.cs b/tests/Kyoo.Tests/Utility/EnumerableTests.cs index 627de26b..b2a444ad 100644 --- a/tests/Kyoo.Tests/Utility/EnumerableTests.cs +++ b/tests/Kyoo.Tests/Utility/EnumerableTests.cs @@ -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 . + using System; using System.Collections.Generic; using System.Linq; @@ -12,18 +30,18 @@ namespace Kyoo.Tests.Utility [Fact] public void MapTest() { - int[] list = {1, 2, 3, 4}; + int[] list = { 1, 2, 3, 4 }; Assert.All(list.Map((x, i) => (x, i)), x => Assert.Equal(x.x - 1, x.i)); Assert.Throws(() => list.Map(((Func)null)!)); list = null; Assert.Throws(() => list!.Map((x, _) => x + 1)); } - + [Fact] public async Task MapAsyncTest() { - int[] list = {1, 2, 3, 4}; - await foreach((int x, int i) in list.MapAsync((x, i) => Task.FromResult((x, i)))) + int[] list = { 1, 2, 3, 4 }; + await foreach ((int x, int i) in list.MapAsync((x, i) => Task.FromResult((x, i)))) { Assert.Equal(x - 1, i); } @@ -31,13 +49,13 @@ namespace Kyoo.Tests.Utility list = null; Assert.Throws(() => list!.MapAsync((x, _) => Task.FromResult(x + 1))); } - + [Fact] public async Task SelectAsyncTest() { - int[] list = {1, 2, 3, 4}; + int[] list = { 1, 2, 3, 4 }; int i = 2; - await foreach(int x in list.SelectAsync(x => Task.FromResult(x + 1))) + await foreach (int x in list.SelectAsync(x => Task.FromResult(x + 1))) { Assert.Equal(i++, x); } @@ -45,28 +63,28 @@ namespace Kyoo.Tests.Utility list = null; Assert.Throws(() => list!.SelectAsync(x => Task.FromResult(x + 1))); } - + [Fact] public async Task ToListAsyncTest() { - int[] expected = {1, 2, 3, 4}; + int[] expected = { 1, 2, 3, 4 }; IAsyncEnumerable list = expected.SelectAsync(Task.FromResult); Assert.Equal(expected, await list.ToListAsync()); list = null; await Assert.ThrowsAsync(() => list!.ToListAsync()); } - + [Fact] public void IfEmptyTest() { - int[] list = {1, 2, 3, 4}; + int[] list = { 1, 2, 3, 4 }; list = list.IfEmpty(() => KAssert.Fail("Empty action should not be triggered.")).ToArray(); Assert.Throws(() => list.IfEmpty(null!).ToList()); list = null; - Assert.Throws(() => list!.IfEmpty(() => {}).ToList()); + Assert.Throws(() => list!.IfEmpty(() => { }).ToList()); list = Array.Empty(); Assert.Throws(() => list.IfEmpty(() => throw new ArgumentException()).ToList()); - Assert.Empty(list.IfEmpty(() => {})); + Assert.Empty(list.IfEmpty(() => { })); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Utility/MergerTests.cs b/tests/Kyoo.Tests/Utility/MergerTests.cs index 2765c7e2..dd9c71a2 100644 --- a/tests/Kyoo.Tests/Utility/MergerTests.cs +++ b/tests/Kyoo.Tests/Utility/MergerTests.cs @@ -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 . + using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -24,7 +42,7 @@ namespace Kyoo.Tests.Utility Assert.Null(genre.Name); Assert.Null(genre.Slug); } - + [Fact] public void MergeTest() { @@ -42,7 +60,7 @@ namespace Kyoo.Tests.Utility Assert.Equal("test", genre.Name); Assert.Null(genre.Slug); } - + [Fact] [SuppressMessage("ReSharper", "ExpressionIsAlwaysNull")] public void MergeNullTests() @@ -65,7 +83,7 @@ namespace Kyoo.Tests.Utility throw exception; } } - + [Fact] public void OnMergeTest() { @@ -81,25 +99,25 @@ namespace Kyoo.Tests.Utility Assert.True(ReferenceEquals(test2, ex.Data[0])); } } - + private class Test { public int ID { get; set; } public int[] Numbers { get; set; } } - + [Fact] public void GlobalMergeListTest() { Test test = new() { ID = 5, - Numbers = new [] { 1 } + Numbers = new[] { 1 } }; Test test2 = new() { - Numbers = new [] { 3 } + Numbers = new[] { 3 } }; Test ret = Merger.Merge(test, test2); Assert.True(ReferenceEquals(test, ret)); @@ -109,18 +127,18 @@ namespace Kyoo.Tests.Utility Assert.Equal(1, ret.Numbers[0]); Assert.Equal(3, ret.Numbers[1]); } - + [Fact] public void GlobalMergeListDuplicatesTest() { Test test = new() { ID = 5, - Numbers = new [] { 1 } + Numbers = new[] { 1 } }; Test test2 = new() { - Numbers = new [] + Numbers = new[] { 1, 3, @@ -137,14 +155,14 @@ namespace Kyoo.Tests.Utility Assert.Equal(3, ret.Numbers[2]); Assert.Equal(3, ret.Numbers[3]); } - + private class MergeDictionaryTest { public int ID { get; set; } public Dictionary Dictionary { get; set; } } - + [Fact] public void GlobalMergeDictionariesTest() { @@ -171,7 +189,7 @@ namespace Kyoo.Tests.Utility Assert.Equal("two", ret.Dictionary[2]); Assert.Equal("third", ret.Dictionary[3]); } - + [Fact] public void GlobalMergeDictionariesDuplicatesTest() { @@ -199,21 +217,21 @@ namespace Kyoo.Tests.Utility Assert.Equal("two", ret.Dictionary[2]); Assert.Equal("third", ret.Dictionary[3]); } - + [Fact] public void GlobalMergeListDuplicatesResourcesTest() { Show test = new() { ID = 5, - Genres = new [] { new Genre("test") } + Genres = new[] { new Genre("test") } }; Show test2 = new() { - Genres = new [] + Genres = new[] { new Genre("test"), - new Genre("test2") + new Genre("test2") } }; Show ret = Merger.Merge(test, test2); @@ -229,18 +247,15 @@ namespace Kyoo.Tests.Utility public void MergeListTest() { int[] first = { 1 }; - int[] second = { - 3, - 3 - }; + int[] second = { 3, 3 }; int[] ret = Merger.MergeLists(first, second); - + Assert.Equal(3, ret.Length); Assert.Equal(1, ret[0]); Assert.Equal(3, ret[1]); Assert.Equal(3, ret[2]); } - + [Fact] public void MergeListDuplicateTest() { @@ -251,29 +266,26 @@ namespace Kyoo.Tests.Utility 3 }; int[] ret = Merger.MergeLists(first, second); - + Assert.Equal(4, ret.Length); Assert.Equal(1, ret[0]); Assert.Equal(1, ret[1]); Assert.Equal(3, ret[2]); Assert.Equal(3, ret[3]); } - + [Fact] public void MergeListDuplicateCustomEqualityTest() { int[] first = { 1 }; - int[] second = { - 3, - 2 - }; + int[] second = { 3, 2 }; int[] ret = Merger.MergeLists(first, second, (x, y) => x % 2 == y % 2); - + Assert.Equal(2, ret.Length); Assert.Equal(1, ret[0]); Assert.Equal(2, ret[1]); } - + [Fact] public void MergeDictionariesTest() { @@ -287,13 +299,13 @@ namespace Kyoo.Tests.Utility [3] = "third", }; IDictionary ret = Merger.MergeDictionaries(first, second); - + Assert.Equal(3, ret.Count); Assert.Equal("test", ret[1]); Assert.Equal("value", ret[5]); Assert.Equal("third", ret[3]); } - + [Fact] public void MergeDictionariesDuplicateTest() { @@ -308,13 +320,13 @@ namespace Kyoo.Tests.Utility [5] = "new-value", }; IDictionary ret = Merger.MergeDictionaries(first, second); - + Assert.Equal(3, ret.Count); Assert.Equal("test", ret[1]); Assert.Equal("value", ret[5]); Assert.Equal("third", ret[3]); } - + [Fact] public void CompleteTest() { @@ -333,7 +345,7 @@ namespace Kyoo.Tests.Utility Assert.Equal("test", genre.Name); Assert.Null(genre.Slug); } - + [Fact] public void CompleteDictionaryTest() { @@ -346,7 +358,7 @@ namespace Kyoo.Tests.Utility [Images.Logo] = "logo", [Images.Poster] = "poster" } - + }; Collection collection2 = new() { @@ -388,7 +400,7 @@ namespace Kyoo.Tests.Utility Assert.Equal("thumbnails", ret[Images.Thumbnail]); Assert.Equal("logo", ret[Images.Logo]); } - + [Fact] public void CompleteDictionaryEqualTest() { @@ -409,8 +421,9 @@ namespace Kyoo.Tests.Utility private class TestMergeSetter { public Dictionary Backing; - - [UsedImplicitly] public Dictionary Dictionary + + [UsedImplicitly] + public Dictionary Dictionary { get => Backing; set @@ -438,7 +451,7 @@ namespace Kyoo.Tests.Utility Merger.Complete(first, second); // This should no call the setter of first so the test should pass. } - + [Fact] public void MergeDictionaryNoChangeNoSetTest() { @@ -456,7 +469,7 @@ namespace Kyoo.Tests.Utility Merger.Merge(first, second); // This should no call the setter of first so the test should pass. } - + [Fact] public void MergeDictionaryNullValue() { @@ -477,7 +490,7 @@ namespace Kyoo.Tests.Utility Assert.Equal("thumbnails", ret[Images.Thumbnail]); Assert.Equal("logo", ret[Images.Logo]); } - + [Fact] public void MergeDictionaryNullValueNoChange() { @@ -496,7 +509,7 @@ namespace Kyoo.Tests.Utility Assert.Null(ret[Images.Poster]); Assert.Equal("logo", ret[Images.Logo]); } - + [Fact] public void CompleteDictionaryNullValue() { @@ -517,7 +530,7 @@ namespace Kyoo.Tests.Utility Assert.Equal("thumbnails", ret[Images.Thumbnail]); Assert.Equal("logo", ret[Images.Logo]); } - + [Fact] public void CompleteDictionaryNullValueNoChange() { @@ -537,4 +550,4 @@ namespace Kyoo.Tests.Utility Assert.Equal("logo", ret[Images.Logo]); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Utility/TaskTests.cs b/tests/Kyoo.Tests/Utility/TaskTests.cs index 47cbbf69..e00ca321 100644 --- a/tests/Kyoo.Tests/Utility/TaskTests.cs +++ b/tests/Kyoo.Tests/Utility/TaskTests.cs @@ -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 . + using System; using System.Threading; using System.Threading.Tasks; @@ -21,7 +39,7 @@ namespace Kyoo.Tests.Utility await Assert.ThrowsAsync(() => Task.FromResult(1) .Then(_ => throw new ArgumentException())); Assert.Equal(1, await Task.FromResult(1) - .Then(_ => {})); + .Then(_ => { })); static async Task Faulted() { @@ -39,9 +57,9 @@ namespace Kyoo.Tests.Utility CancellationTokenSource token = new(); token.Cancel(); await Assert.ThrowsAsync(() => Task.Run(Infinite, token.Token) - .Then(_ => {})); + .Then(_ => { })); } - + [Fact] public async Task MapTest() { @@ -74,4 +92,4 @@ namespace Kyoo.Tests.Utility .Map(x => x)); } } -} \ No newline at end of file +} diff --git a/tests/Kyoo.Tests/Utility/UtilityTests.cs b/tests/Kyoo.Tests/Utility/UtilityTests.cs index 262337d0..ab7805f6 100644 --- a/tests/Kyoo.Tests/Utility/UtilityTests.cs +++ b/tests/Kyoo.Tests/Utility/UtilityTests.cs @@ -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 . + using System; using System.Linq.Expressions; using System.Reflection; @@ -24,7 +42,7 @@ namespace Kyoo.Tests.Utility Expression> call = x => x.GetID("test"); Assert.False(KUtility.IsPropertyExpression(call)); } - + [Fact] public void GetPropertyName_Test() { @@ -35,47 +53,47 @@ namespace Kyoo.Tests.Utility Assert.Equal("ID", KUtility.GetPropertyName(memberCast)); Assert.Throws(() => KUtility.GetPropertyName(null)); } - + [Fact] public void GetMethodTest() { MethodInfo method = KUtility.GetMethod(typeof(UtilityTests), - BindingFlags.Instance | BindingFlags.Public, + BindingFlags.Instance | BindingFlags.Public, nameof(GetMethodTest), Array.Empty(), Array.Empty()); Assert.Equal(MethodBase.GetCurrentMethod(), method); } - + [Fact] public void GetMethodInvalidGenericsTest() { Assert.Throws(() => KUtility.GetMethod(typeof(UtilityTests), - BindingFlags.Instance | BindingFlags.Public, + BindingFlags.Instance | BindingFlags.Public, nameof(GetMethodTest), - new [] { typeof(KUtility) }, + new[] { typeof(KUtility) }, Array.Empty())); } - + [Fact] public void GetMethodInvalidParamsTest() { Assert.Throws(() => KUtility.GetMethod(typeof(UtilityTests), - BindingFlags.Instance | BindingFlags.Public, + BindingFlags.Instance | BindingFlags.Public, nameof(GetMethodTest), Array.Empty(), new object[] { this })); } - + [Fact] public void GetMethodTest2() { MethodInfo method = KUtility.GetMethod(typeof(Merger), - BindingFlags.Static | BindingFlags.Public, + BindingFlags.Static | BindingFlags.Public, nameof(Merger.MergeLists), - new [] { typeof(string) }, + new[] { typeof(string) }, new object[] { "string", "string2", null }); Assert.Equal(nameof(Merger.MergeLists), method.Name); } } -} \ No newline at end of file +}