From 77bf623611f6ca01beddae8688fe1a83901e8f52 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 17 Jan 2020 00:25:07 +0100 Subject: [PATCH 01/11] Starting to rework the app to expose the API for plugins. --- .../Controllers}/ICrawler.cs | 0 .../Controllers}/ILibraryManager.cs | 0 .../Controllers}/IMetadataProvider.cs | 0 .../Controllers}/IThumbnailsManager.cs | 0 .../Controllers}/ITranscoder.cs | 0 Kyoo.Common/Kyoo.Common.csproj | 12 ++++ {Kyoo => Kyoo.Common}/Models/Collection.cs | 0 {Kyoo => Kyoo.Common}/Models/Episode.cs | 0 {Kyoo => Kyoo.Common}/Models/Genre.cs | 0 Kyoo.Common/Models/ImageTypes.cs | 4 ++ {Kyoo => Kyoo.Common}/Models/Library.cs | 0 {Kyoo => Kyoo.Common}/Models/People.cs | 0 {Kyoo => Kyoo.Common}/Models/SearchResult.cs | 0 {Kyoo => Kyoo.Common}/Models/Season.cs | 0 {Kyoo => Kyoo.Common}/Models/Show.cs | 0 {Kyoo => Kyoo.Common}/Models/Studio.cs | 0 {Kyoo => Kyoo.Common}/Models/Track.cs | 0 {Kyoo => Kyoo.Common}/Models/WatchItem.cs | 0 .../Plugins}/MetadataAttribute.cs | 5 +- Kyoo.Common/Utility/ImageHelper.cs | 28 +++++++++ .../Utility/Slugifier.cs | 0 Kyoo.sln | 6 ++ Kyoo.sln.DotSettings | 6 +- .../Crawler => Controllers}/Crawler.cs | 0 .../LibraryManager.cs | 0 .../Implementations/TheTvDB/HelperTvDB.cs | 0 .../TheTvDB/ProviderTheTvDB.cs | 0 .../MetadataProvider/ProviderManager.cs | 0 .../ThumbnailsManager.cs | 0 .../Transcoder/Transcoder.cs | 0 .../Transcoder/TranscoderAPI.cs | 0 .../AdminController.cs | 0 .../CollectionController.cs | 0 .../EpisodesController.cs | 0 .../LibrariesController.cs | 0 .../PeopleController.cs | 0 .../SearchController.cs | 0 .../ShowsController.cs | 0 .../SubtitleController.cs | 0 .../ThumbnailController.cs | 0 .../VideoController.cs | 0 .../WatchController.cs | 0 .../MetadataProvider/ProviderHelper.cs | 60 ------------------- Kyoo/Kyoo.csproj | 4 ++ Kyoo/Kyoo.csproj.DotSettings | 3 + MetadataProvider/MetadataProvider.csproj | 11 ++++ 46 files changed, 74 insertions(+), 65 deletions(-) rename {Kyoo/InternalAPI/Crawler => Kyoo.Common/Controllers}/ICrawler.cs (100%) rename {Kyoo/InternalAPI/LibraryManager => Kyoo.Common/Controllers}/ILibraryManager.cs (100%) rename {Kyoo/InternalAPI/MetadataProvider => Kyoo.Common/Controllers}/IMetadataProvider.cs (100%) rename {Kyoo/InternalAPI/ThumbnailsManager => Kyoo.Common/Controllers}/IThumbnailsManager.cs (100%) rename {Kyoo/InternalAPI/Transcoder => Kyoo.Common/Controllers}/ITranscoder.cs (100%) create mode 100644 Kyoo.Common/Kyoo.Common.csproj rename {Kyoo => Kyoo.Common}/Models/Collection.cs (100%) rename {Kyoo => Kyoo.Common}/Models/Episode.cs (100%) rename {Kyoo => Kyoo.Common}/Models/Genre.cs (100%) create mode 100644 Kyoo.Common/Models/ImageTypes.cs rename {Kyoo => Kyoo.Common}/Models/Library.cs (100%) rename {Kyoo => Kyoo.Common}/Models/People.cs (100%) rename {Kyoo => Kyoo.Common}/Models/SearchResult.cs (100%) rename {Kyoo => Kyoo.Common}/Models/Season.cs (100%) rename {Kyoo => Kyoo.Common}/Models/Show.cs (100%) rename {Kyoo => Kyoo.Common}/Models/Studio.cs (100%) rename {Kyoo => Kyoo.Common}/Models/Track.cs (100%) rename {Kyoo => Kyoo.Common}/Models/WatchItem.cs (100%) rename {Kyoo/InternalAPI/MetadataProvider => Kyoo.Common/Plugins}/MetadataAttribute.cs (76%) create mode 100644 Kyoo.Common/Utility/ImageHelper.cs rename {Kyoo/InternalAPI => Kyoo.Common}/Utility/Slugifier.cs (100%) rename Kyoo/{InternalAPI/Crawler => Controllers}/Crawler.cs (100%) rename Kyoo/{InternalAPI/LibraryManager => Controllers}/LibraryManager.cs (100%) rename Kyoo/{InternalAPI => Controllers}/MetadataProvider/Implementations/TheTvDB/HelperTvDB.cs (100%) rename Kyoo/{InternalAPI => Controllers}/MetadataProvider/Implementations/TheTvDB/ProviderTheTvDB.cs (100%) rename Kyoo/{InternalAPI => Controllers}/MetadataProvider/ProviderManager.cs (100%) rename Kyoo/{InternalAPI/ThumbnailsManager => Controllers}/ThumbnailsManager.cs (100%) rename Kyoo/{InternalAPI => Controllers}/Transcoder/Transcoder.cs (100%) rename Kyoo/{InternalAPI => Controllers}/Transcoder/TranscoderAPI.cs (100%) rename Kyoo/{Controllers => HTML_API}/AdminController.cs (100%) rename Kyoo/{Controllers => HTML_API}/CollectionController.cs (100%) rename Kyoo/{Controllers => HTML_API}/EpisodesController.cs (100%) rename Kyoo/{Controllers => HTML_API}/LibrariesController.cs (100%) rename Kyoo/{Controllers => HTML_API}/PeopleController.cs (100%) rename Kyoo/{Controllers => HTML_API}/SearchController.cs (100%) rename Kyoo/{Controllers => HTML_API}/ShowsController.cs (100%) rename Kyoo/{Controllers => HTML_API}/SubtitleController.cs (100%) rename Kyoo/{Controllers => HTML_API}/ThumbnailController.cs (100%) rename Kyoo/{Controllers => HTML_API}/VideoController.cs (100%) rename Kyoo/{Controllers => HTML_API}/WatchController.cs (100%) delete mode 100644 Kyoo/InternalAPI/MetadataProvider/ProviderHelper.cs create mode 100644 MetadataProvider/MetadataProvider.csproj diff --git a/Kyoo/InternalAPI/Crawler/ICrawler.cs b/Kyoo.Common/Controllers/ICrawler.cs similarity index 100% rename from Kyoo/InternalAPI/Crawler/ICrawler.cs rename to Kyoo.Common/Controllers/ICrawler.cs diff --git a/Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs similarity index 100% rename from Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs rename to Kyoo.Common/Controllers/ILibraryManager.cs diff --git a/Kyoo/InternalAPI/MetadataProvider/IMetadataProvider.cs b/Kyoo.Common/Controllers/IMetadataProvider.cs similarity index 100% rename from Kyoo/InternalAPI/MetadataProvider/IMetadataProvider.cs rename to Kyoo.Common/Controllers/IMetadataProvider.cs diff --git a/Kyoo/InternalAPI/ThumbnailsManager/IThumbnailsManager.cs b/Kyoo.Common/Controllers/IThumbnailsManager.cs similarity index 100% rename from Kyoo/InternalAPI/ThumbnailsManager/IThumbnailsManager.cs rename to Kyoo.Common/Controllers/IThumbnailsManager.cs diff --git a/Kyoo/InternalAPI/Transcoder/ITranscoder.cs b/Kyoo.Common/Controllers/ITranscoder.cs similarity index 100% rename from Kyoo/InternalAPI/Transcoder/ITranscoder.cs rename to Kyoo.Common/Controllers/ITranscoder.cs diff --git a/Kyoo.Common/Kyoo.Common.csproj b/Kyoo.Common/Kyoo.Common.csproj new file mode 100644 index 00000000..e87868c0 --- /dev/null +++ b/Kyoo.Common/Kyoo.Common.csproj @@ -0,0 +1,12 @@ + + + + netcoreapp3.0 + + + + + + + + diff --git a/Kyoo/Models/Collection.cs b/Kyoo.Common/Models/Collection.cs similarity index 100% rename from Kyoo/Models/Collection.cs rename to Kyoo.Common/Models/Collection.cs diff --git a/Kyoo/Models/Episode.cs b/Kyoo.Common/Models/Episode.cs similarity index 100% rename from Kyoo/Models/Episode.cs rename to Kyoo.Common/Models/Episode.cs diff --git a/Kyoo/Models/Genre.cs b/Kyoo.Common/Models/Genre.cs similarity index 100% rename from Kyoo/Models/Genre.cs rename to Kyoo.Common/Models/Genre.cs diff --git a/Kyoo.Common/Models/ImageTypes.cs b/Kyoo.Common/Models/ImageTypes.cs new file mode 100644 index 00000000..fc643362 --- /dev/null +++ b/Kyoo.Common/Models/ImageTypes.cs @@ -0,0 +1,4 @@ +namespace Kyoo.Models +{ + public enum ImageType { Poster, Background, Thumbnail, Logo } +} \ No newline at end of file diff --git a/Kyoo/Models/Library.cs b/Kyoo.Common/Models/Library.cs similarity index 100% rename from Kyoo/Models/Library.cs rename to Kyoo.Common/Models/Library.cs diff --git a/Kyoo/Models/People.cs b/Kyoo.Common/Models/People.cs similarity index 100% rename from Kyoo/Models/People.cs rename to Kyoo.Common/Models/People.cs diff --git a/Kyoo/Models/SearchResult.cs b/Kyoo.Common/Models/SearchResult.cs similarity index 100% rename from Kyoo/Models/SearchResult.cs rename to Kyoo.Common/Models/SearchResult.cs diff --git a/Kyoo/Models/Season.cs b/Kyoo.Common/Models/Season.cs similarity index 100% rename from Kyoo/Models/Season.cs rename to Kyoo.Common/Models/Season.cs diff --git a/Kyoo/Models/Show.cs b/Kyoo.Common/Models/Show.cs similarity index 100% rename from Kyoo/Models/Show.cs rename to Kyoo.Common/Models/Show.cs diff --git a/Kyoo/Models/Studio.cs b/Kyoo.Common/Models/Studio.cs similarity index 100% rename from Kyoo/Models/Studio.cs rename to Kyoo.Common/Models/Studio.cs diff --git a/Kyoo/Models/Track.cs b/Kyoo.Common/Models/Track.cs similarity index 100% rename from Kyoo/Models/Track.cs rename to Kyoo.Common/Models/Track.cs diff --git a/Kyoo/Models/WatchItem.cs b/Kyoo.Common/Models/WatchItem.cs similarity index 100% rename from Kyoo/Models/WatchItem.cs rename to Kyoo.Common/Models/WatchItem.cs diff --git a/Kyoo/InternalAPI/MetadataProvider/MetadataAttribute.cs b/Kyoo.Common/Plugins/MetadataAttribute.cs similarity index 76% rename from Kyoo/InternalAPI/MetadataProvider/MetadataAttribute.cs rename to Kyoo.Common/Plugins/MetadataAttribute.cs index cd72a719..35199691 100644 --- a/Kyoo/InternalAPI/MetadataProvider/MetadataAttribute.cs +++ b/Kyoo.Common/Plugins/MetadataAttribute.cs @@ -5,9 +5,6 @@ namespace Kyoo.InternalAPI.MetadataProvider [AttributeUsage(AttributeTargets.Class)] public class MetaProvider : Attribute { - public MetaProvider() - { - - } + public MetaProvider() { } } } diff --git a/Kyoo.Common/Utility/ImageHelper.cs b/Kyoo.Common/Utility/ImageHelper.cs new file mode 100644 index 00000000..c9b075e7 --- /dev/null +++ b/Kyoo.Common/Utility/ImageHelper.cs @@ -0,0 +1,28 @@ +using Kyoo.Models; + +namespace Kyoo.InternalAPI.Utility +{ + public static class ImageHelper + { + public static void SetImage(Show show, string imgUrl, ImageType type) + { + switch(type) + { + case ImageType.Poster: + show.ImgPrimary = imgUrl; + break; + case ImageType.Thumbnail: + show.ImgThumb = imgUrl; + break; + case ImageType.Logo: + show.ImgLogo = imgUrl; + break; + case ImageType.Background: + show.ImgBackdrop = imgUrl; + break; + default: + break; + } + } + } +} \ No newline at end of file diff --git a/Kyoo/InternalAPI/Utility/Slugifier.cs b/Kyoo.Common/Utility/Slugifier.cs similarity index 100% rename from Kyoo/InternalAPI/Utility/Slugifier.cs rename to Kyoo.Common/Utility/Slugifier.cs diff --git a/Kyoo.sln b/Kyoo.sln index d11b3041..12f6f2ad 100644 --- a/Kyoo.sln +++ b/Kyoo.sln @@ -1,6 +1,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kyoo", "Kyoo\Kyoo.csproj", "{0F8275B6-C7DD-42DF-A168-755C81B1C329}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Common", "Kyoo.Common\Kyoo.Common.csproj", "{BAB2CAE1-AC28-4509-AA3E-8DC75BD59220}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -11,5 +13,9 @@ Global {0F8275B6-C7DD-42DF-A168-755C81B1C329}.Debug|Any CPU.Build.0 = Debug|Any CPU {0F8275B6-C7DD-42DF-A168-755C81B1C329}.Release|Any CPU.ActiveCfg = Release|Any CPU {0F8275B6-C7DD-42DF-A168-755C81B1C329}.Release|Any CPU.Build.0 = Release|Any CPU + {BAB2CAE1-AC28-4509-AA3E-8DC75BD59220}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAB2CAE1-AC28-4509-AA3E-8DC75BD59220}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAB2CAE1-AC28-4509-AA3E-8DC75BD59220}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAB2CAE1-AC28-4509-AA3E-8DC75BD59220}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Kyoo.sln.DotSettings b/Kyoo.sln.DotSettings index c1483371..f0549f01 100644 --- a/Kyoo.sln.DotSettings +++ b/Kyoo.sln.DotSettings @@ -4,4 +4,8 @@ UseExplicitType UseExplicitType API - DB \ No newline at end of file + DB + True + True + True + True \ No newline at end of file diff --git a/Kyoo/InternalAPI/Crawler/Crawler.cs b/Kyoo/Controllers/Crawler.cs similarity index 100% rename from Kyoo/InternalAPI/Crawler/Crawler.cs rename to Kyoo/Controllers/Crawler.cs diff --git a/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs similarity index 100% rename from Kyoo/InternalAPI/LibraryManager/LibraryManager.cs rename to Kyoo/Controllers/LibraryManager.cs diff --git a/Kyoo/InternalAPI/MetadataProvider/Implementations/TheTvDB/HelperTvDB.cs b/Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/HelperTvDB.cs similarity index 100% rename from Kyoo/InternalAPI/MetadataProvider/Implementations/TheTvDB/HelperTvDB.cs rename to Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/HelperTvDB.cs diff --git a/Kyoo/InternalAPI/MetadataProvider/Implementations/TheTvDB/ProviderTheTvDB.cs b/Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/ProviderTheTvDB.cs similarity index 100% rename from Kyoo/InternalAPI/MetadataProvider/Implementations/TheTvDB/ProviderTheTvDB.cs rename to Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/ProviderTheTvDB.cs diff --git a/Kyoo/InternalAPI/MetadataProvider/ProviderManager.cs b/Kyoo/Controllers/MetadataProvider/ProviderManager.cs similarity index 100% rename from Kyoo/InternalAPI/MetadataProvider/ProviderManager.cs rename to Kyoo/Controllers/MetadataProvider/ProviderManager.cs diff --git a/Kyoo/InternalAPI/ThumbnailsManager/ThumbnailsManager.cs b/Kyoo/Controllers/ThumbnailsManager.cs similarity index 100% rename from Kyoo/InternalAPI/ThumbnailsManager/ThumbnailsManager.cs rename to Kyoo/Controllers/ThumbnailsManager.cs diff --git a/Kyoo/InternalAPI/Transcoder/Transcoder.cs b/Kyoo/Controllers/Transcoder/Transcoder.cs similarity index 100% rename from Kyoo/InternalAPI/Transcoder/Transcoder.cs rename to Kyoo/Controllers/Transcoder/Transcoder.cs diff --git a/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs b/Kyoo/Controllers/Transcoder/TranscoderAPI.cs similarity index 100% rename from Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs rename to Kyoo/Controllers/Transcoder/TranscoderAPI.cs diff --git a/Kyoo/Controllers/AdminController.cs b/Kyoo/HTML_API/AdminController.cs similarity index 100% rename from Kyoo/Controllers/AdminController.cs rename to Kyoo/HTML_API/AdminController.cs diff --git a/Kyoo/Controllers/CollectionController.cs b/Kyoo/HTML_API/CollectionController.cs similarity index 100% rename from Kyoo/Controllers/CollectionController.cs rename to Kyoo/HTML_API/CollectionController.cs diff --git a/Kyoo/Controllers/EpisodesController.cs b/Kyoo/HTML_API/EpisodesController.cs similarity index 100% rename from Kyoo/Controllers/EpisodesController.cs rename to Kyoo/HTML_API/EpisodesController.cs diff --git a/Kyoo/Controllers/LibrariesController.cs b/Kyoo/HTML_API/LibrariesController.cs similarity index 100% rename from Kyoo/Controllers/LibrariesController.cs rename to Kyoo/HTML_API/LibrariesController.cs diff --git a/Kyoo/Controllers/PeopleController.cs b/Kyoo/HTML_API/PeopleController.cs similarity index 100% rename from Kyoo/Controllers/PeopleController.cs rename to Kyoo/HTML_API/PeopleController.cs diff --git a/Kyoo/Controllers/SearchController.cs b/Kyoo/HTML_API/SearchController.cs similarity index 100% rename from Kyoo/Controllers/SearchController.cs rename to Kyoo/HTML_API/SearchController.cs diff --git a/Kyoo/Controllers/ShowsController.cs b/Kyoo/HTML_API/ShowsController.cs similarity index 100% rename from Kyoo/Controllers/ShowsController.cs rename to Kyoo/HTML_API/ShowsController.cs diff --git a/Kyoo/Controllers/SubtitleController.cs b/Kyoo/HTML_API/SubtitleController.cs similarity index 100% rename from Kyoo/Controllers/SubtitleController.cs rename to Kyoo/HTML_API/SubtitleController.cs diff --git a/Kyoo/Controllers/ThumbnailController.cs b/Kyoo/HTML_API/ThumbnailController.cs similarity index 100% rename from Kyoo/Controllers/ThumbnailController.cs rename to Kyoo/HTML_API/ThumbnailController.cs diff --git a/Kyoo/Controllers/VideoController.cs b/Kyoo/HTML_API/VideoController.cs similarity index 100% rename from Kyoo/Controllers/VideoController.cs rename to Kyoo/HTML_API/VideoController.cs diff --git a/Kyoo/Controllers/WatchController.cs b/Kyoo/HTML_API/WatchController.cs similarity index 100% rename from Kyoo/Controllers/WatchController.cs rename to Kyoo/HTML_API/WatchController.cs diff --git a/Kyoo/InternalAPI/MetadataProvider/ProviderHelper.cs b/Kyoo/InternalAPI/MetadataProvider/ProviderHelper.cs deleted file mode 100644 index 82e5220e..00000000 --- a/Kyoo/InternalAPI/MetadataProvider/ProviderHelper.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Kyoo.InternalAPI.Utility; -using Kyoo.Models; -using System.Collections.Generic; - -namespace Kyoo.InternalAPI.MetadataProvider -{ - public abstract class ProviderHelper - { - public abstract string Provider { get; } - - public string GetID(string externalIDs) - { - if (externalIDs?.Contains(Provider) == true) - { - int startIndex = externalIDs.IndexOf(Provider) + Provider.Length + 1; //The + 1 is for the '=' - return externalIDs.Substring(startIndex, externalIDs.IndexOf('|', startIndex) - startIndex); - } - else - return null; - } - - public string ToSlug(string showTitle) - { - return Slugifier.ToSlug(showTitle); - } - - public enum ImageType { Poster, Background, Thumbnail, Logo } - - public void SetImage(Show show, string imgUrl, ImageType type) - { - switch(type) - { - case ImageType.Poster: - show.ImgPrimary = imgUrl; - break; - case ImageType.Thumbnail: - show.ImgThumb = imgUrl; - break; - case ImageType.Logo: - show.ImgLogo = imgUrl; - break; - case ImageType.Background: - show.ImgBackdrop = imgUrl; - break; - default: - break; - } - } - - public IEnumerable GetGenres(string[] input) - { - List genres = new List(); - - foreach (string genre in input) - genres.Add(new Genre(ToSlug(genre), genre)); - - return genres; - } - } -} diff --git a/Kyoo/Kyoo.csproj b/Kyoo/Kyoo.csproj index 795b09a7..ac60fce7 100644 --- a/Kyoo/Kyoo.csproj +++ b/Kyoo/Kyoo.csproj @@ -45,6 +45,10 @@ Always + + + + diff --git a/Kyoo/Kyoo.csproj.DotSettings b/Kyoo/Kyoo.csproj.DotSettings index 74a9e4de..bc646adf 100644 --- a/Kyoo/Kyoo.csproj.DotSettings +++ b/Kyoo/Kyoo.csproj.DotSettings @@ -1,4 +1,7 @@  + True + True + True True True True diff --git a/MetadataProvider/MetadataProvider.csproj b/MetadataProvider/MetadataProvider.csproj new file mode 100644 index 00000000..4342747a --- /dev/null +++ b/MetadataProvider/MetadataProvider.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp3.0 + + + + + + + From ce98686f4f2ec7d2f3c33479156622af1d42dae5 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 17 Jan 2020 00:45:35 +0100 Subject: [PATCH 02/11] Removing TheTVDB implementation (new git) --- Kyoo.Common/.gitignore | 233 +++++++++++++ .../Implementations/TheTvDB/HelperTvDB.cs | 68 ---- .../TheTvDB/ProviderTheTvDB.cs | 325 ------------------ .../{MetadataProvider => }/ProviderManager.cs | 2 - Kyoo/{HTML_API => HtmlAPI}/AdminController.cs | 0 .../CollectionController.cs | 0 .../EpisodesController.cs | 0 .../LibrariesController.cs | 0 .../{HTML_API => HtmlAPI}/PeopleController.cs | 0 .../{HTML_API => HtmlAPI}/SearchController.cs | 0 Kyoo/{HTML_API => HtmlAPI}/ShowsController.cs | 0 .../SubtitleController.cs | 0 .../ThumbnailController.cs | 0 Kyoo/{HTML_API => HtmlAPI}/VideoController.cs | 0 Kyoo/{HTML_API => HtmlAPI}/WatchController.cs | 0 Kyoo/Kyoo.csproj | 7 + MetadataProvider/MetadataProvider.csproj | 11 - 17 files changed, 240 insertions(+), 406 deletions(-) create mode 100644 Kyoo.Common/.gitignore delete mode 100644 Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/HelperTvDB.cs delete mode 100644 Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/ProviderTheTvDB.cs rename Kyoo/Controllers/{MetadataProvider => }/ProviderManager.cs (99%) rename Kyoo/{HTML_API => HtmlAPI}/AdminController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/CollectionController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/EpisodesController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/LibrariesController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/PeopleController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/SearchController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/ShowsController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/SubtitleController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/ThumbnailController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/VideoController.cs (100%) rename Kyoo/{HTML_API => HtmlAPI}/WatchController.cs (100%) delete mode 100644 MetadataProvider/MetadataProvider.csproj diff --git a/Kyoo.Common/.gitignore b/Kyoo.Common/.gitignore new file mode 100644 index 00000000..877ccf42 --- /dev/null +++ b/Kyoo.Common/.gitignore @@ -0,0 +1,233 @@ +## PROJECT CUSTOM IGNORES + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +bin/ +Bin/ +obj/ +Obj/ + +# Visual Studio 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Microsoft Azure ApplicationInsights config file +ApplicationInsights.config + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +orleans.codegen.cs + +/node_modules + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ diff --git a/Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/HelperTvDB.cs b/Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/HelperTvDB.cs deleted file mode 100644 index 37678244..00000000 --- a/Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/HelperTvDB.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Kyoo.Models; -using Newtonsoft.Json; -using System; -using System.Diagnostics; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; - -namespace Kyoo.InternalAPI.MetadataProvider.TheTvDB -{ - public class HelperTvDB : ProviderHelper - { - public override string Provider => "TvDB"; - - private string token; - private DateTime tokenDate; - - protected async Task Authentificate() - { - if (DateTime.Now.Subtract(tokenDate) < TimeSpan.FromDays(1)) - return token; - - HttpClient client = new HttpClient(); - HttpContent content = new StringContent("{ \"apikey\": \"IM2OXA8UHUIU0GH6\" }", Encoding.UTF8, "application/json"); - - try - { - HttpResponseMessage response = await client.PostAsync("https://api.thetvdb.com/login", content); - - if (response.StatusCode == HttpStatusCode.OK) - { - string resp = await response.Content.ReadAsStringAsync(); - var obj = new {Token = ""}; - - token = JsonConvert.DeserializeAnonymousType(resp, obj).Token; - tokenDate = DateTime.UtcNow; - return token; - } - Debug.WriteLine("&Couldn't authentificate in TheTvDB API.\nError status: " + response.StatusCode + " Message: " + response.RequestMessage); - } - catch (WebException ex) - { - Debug.WriteLine("&Couldn't authentificate in TheTvDB API.\nError status: " + ex.Status); - return null; - } - return null; - } - - - protected static long? GetYear(string firstAired) - { - if (firstAired?.Length >= 4 && long.TryParse(firstAired.Substring(0, 4), out long year)) - return year; - - return null; - } - - public Status? GetStatus(string status) - { - if (status == "Ended") - return Status.Finished; - if (status == "Continuing") - return Status.Airing; - return null; - } - } -} diff --git a/Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/ProviderTheTvDB.cs b/Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/ProviderTheTvDB.cs deleted file mode 100644 index d9b5d6e4..00000000 --- a/Kyoo/Controllers/MetadataProvider/Implementations/TheTvDB/ProviderTheTvDB.cs +++ /dev/null @@ -1,325 +0,0 @@ -using Kyoo.InternalAPI.MetadataProvider.TheTvDB; -using Kyoo.InternalAPI.Utility; -using Kyoo.Models; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using System.Web; -#pragma warning disable 1998 - -namespace Kyoo.InternalAPI.MetadataProvider -{ - [MetaProvider] - public class ProviderTheTvDB : HelperTvDB, IMetadataProvider - { - public async Task GetCollectionFromName(string name) - { - return new Collection(-1, Slugifier.ToSlug(name), name, null, null); - } - - public async Task GetShowFromName(string showName, string showPath) - { - string token = await Authentificate(); - - if (token != null) - { - WebRequest request = WebRequest.Create("https://api.thetvdb.com/search/series?name=" + HttpUtility.UrlEncode(showName)); - request.Method = "GET"; - request.Timeout = 12000; - request.ContentType = "application/json"; - request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token); - - try - { - HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); - - if (response.StatusCode == HttpStatusCode.OK) - { - Stream stream = response.GetResponseStream(); - if (stream != null) - { - using StreamReader reader = new StreamReader(stream); - string content = await reader.ReadToEndAsync(); - stream.Close(); - response.Close(); - - dynamic obj = JsonConvert.DeserializeObject(content); - dynamic data = obj.data[0]; - - Show show = new Show(-1, - ToSlug(showName), - (string) data.seriesName, - ((JArray) data.aliases).ToObject>(), - showPath, - (string) data.overview, - null, //trailer - null, //genres (no info with this request) - GetStatus((string) data.status), - GetYear((string) data.firstAired), - null, //endYear - string.Format("{0}={1}|", Provider, (string) data.id)); - return (await GetShowByID(GetID(show.ExternalIDs))).Set(show.Slug, show.Path) ?? show; - } - } - else - { - Debug.WriteLine("&TheTvDB Provider couldn't work for this show: " + showName + ".\nError Code: " + response.StatusCode + " Message: " + response.StatusDescription); - response.Close(); - } - } - catch (WebException ex) - { - Debug.WriteLine("&TheTvDB Provider couldn't work for this show: " + showName + ".\nError Code: " + ex.Status); - } - } - - return new Show() { Slug = ToSlug(showName), Title = showName, Path = showPath }; - } - - public async Task GetShowByID(string id) - { - string token = await Authentificate(); - - if (token == null) - return null; - - WebRequest request = WebRequest.Create("https://api.thetvdb.com/series/" + id); - request.Method = "GET"; - request.Timeout = 12000; - request.ContentType = "application/json"; - request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token); - - try - { - HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); - - if (response.StatusCode == HttpStatusCode.OK) - { - Stream stream = response.GetResponseStream(); - if (stream != null) - { - using StreamReader reader = new StreamReader(stream); - string content = await reader.ReadToEndAsync(); - stream.Close(); - response.Close(); - - dynamic model = JsonConvert.DeserializeObject(content); - dynamic data = model.data; - - Show show = new Show(-1, - null, //Slug - (string) data.seriesName, - ((JArray) data.aliases).ToObject>(), - null, //Path - (string) data.overview, - null, //Trailer - GetGenres(((JArray) data.genre).ToObject()), - GetStatus((string) data.status), - GetYear((string) data.firstAired), - null, //endYear - $"TvDB={id}|"); - await GetImages(show); - return show; - } - } - Debug.WriteLine("&TheTvDB Provider couldn't work for the show with the id: " + id + ".\nError Code: " + response.StatusCode + " Message: " + response.StatusDescription); - response.Close(); - return null; - } - catch(WebException ex) - { - Debug.WriteLine("&TheTvDB Provider couldn't work for the show with the id: " + id + ".\nError Code: " + ex.Status); - return null; - } - } - - public async Task GetImages(Show show) - { - Debug.WriteLine("&Getting images for: " + show.Title); - string id = GetID(show.ExternalIDs); - - if (id == null) - return show; - - string token = await Authentificate(); - - if (token == null) - return show; - - Dictionary imageTypes = new Dictionary { { ImageType.Poster, "poster" }, { ImageType.Background, "fanart" } }; - - foreach (KeyValuePair type in imageTypes) - { - try - { - WebRequest request = WebRequest.Create("https://api.thetvdb.com/series/" + id + "/images/query?keyType=" + type.Value); - request.Method = "GET"; - request.Timeout = 12000; - request.ContentType = "application/json"; - request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token); - - HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); - - if (response.StatusCode == HttpStatusCode.OK) - { - Stream stream = response.GetResponseStream(); - if (stream != null) - { - using StreamReader reader = new StreamReader(stream); - string content = await reader.ReadToEndAsync(); - stream.Close(); - response.Close(); - - dynamic model = JsonConvert.DeserializeObject(content); - //Should implement language selection here - dynamic data = ((IEnumerable) model.data) - .OrderByDescending(x => x.ratingsInfo.average) - .ThenByDescending(x => x.ratingsInfo.count).FirstOrDefault(); - if (data != null) - SetImage(show, "https://www.thetvdb.com/banners/" + data.fileName, type.Key); - } - } - else - { - Debug.WriteLine("&TheTvDB Provider couldn't get " + type + " for the show with the id: " + id + ".\nError Code: " + response.StatusCode + " Message: " + response.StatusDescription); - response.Close(); - } - } - catch (WebException ex) - { - Debug.WriteLine("&TheTvDB Provider couldn't get " + type + " for the show with the id: " + id + ".\nError Code: " + ex.Status); - } - } - - return show; - } - - public async Task GetSeason(string showName, long seasonNumber) - { - return new Season(-1, -1, seasonNumber, "Season " + seasonNumber, null, null, null, null); - } - - public Task GetSeasonImage(string showName, long seasonNumber) - { - return null; - } - - public async Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath) - { - string id = GetID(externalIDs); - - if (id == null) - return new Episode(seasonNumber, episodeNumber, absoluteNumber, null, null, null, -1, null, externalIDs); - - string token = await Authentificate(); - - if (token == null) - return new Episode(seasonNumber, episodeNumber, absoluteNumber, null, null, null, -1, null, externalIDs); - - WebRequest request; - if (absoluteNumber != -1) - request = WebRequest.Create("https://api.thetvdb.com/series/" + id + "/episodes/query?absoluteNumber=" + absoluteNumber); - else - request = WebRequest.Create("https://api.thetvdb.com/series/" + id + "/episodes/query?airedSeason=" + seasonNumber + "&airedEpisode=" + episodeNumber); - - request.Method = "GET"; - request.Timeout = 12000; - request.ContentType = "application/json"; - request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token); - - try - { - HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); - - if (response.StatusCode == HttpStatusCode.OK) - { - Stream stream = response.GetResponseStream(); - if (stream != null) - { - using StreamReader reader = new StreamReader(stream); - string content = await reader.ReadToEndAsync(); - stream.Close(); - response.Close(); - - dynamic data = JsonConvert.DeserializeObject(content); - dynamic episode = data.data[0]; - - DateTime dateTime = DateTime.ParseExact((string)episode.firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture); - - if (absoluteNumber == -1) - absoluteNumber = (long?)episode.absoluteNumber ?? -1; - else - { - seasonNumber = episode.airedSeason; - episodeNumber = episode.airedEpisodeNumber; - } - - return new Episode(seasonNumber, episodeNumber, absoluteNumber, (string)episode.episodeName, (string)episode.overview, dateTime, -1, "https://www.thetvdb.com/banners/" + episode.filename, string.Format("TvDB={0}|", episode.id)); - } - } - Debug.WriteLine("&TheTvDB Provider couldn't work for the episode number: " + episodeNumber + ".\nError Code: " + response.StatusCode + " Message: " + response.StatusDescription); - response.Close(); - return new Episode(seasonNumber, episodeNumber, absoluteNumber, null, null, null, -1, null, externalIDs); - } - catch (WebException ex) - { - Debug.WriteLine("&TheTvDB Provider couldn't work for the episode number: " + episodeNumber + ".\nError Code: " + ex.Status); - return new Episode(seasonNumber, episodeNumber, absoluteNumber, null, null, null, -1, null, externalIDs); - } - } - - public async Task> GetPeople(string externalIDs) - { - string id = GetID(externalIDs); - - if (id == null) - return null; - - string token = await Authentificate(); - - if (token == null) - return null; - - WebRequest request = WebRequest.Create("https://api.thetvdb.com/series/" + id + "/actors"); - request.Method = "GET"; - request.Timeout = 12000; - request.ContentType = "application/json"; - request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token); - - try - { - HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); - - if (response.StatusCode == HttpStatusCode.OK) - { - Stream stream = response.GetResponseStream(); - if (stream != null) - { - using StreamReader reader = new StreamReader(stream); - string content = await reader.ReadToEndAsync(); - stream.Close(); - response.Close(); - - dynamic data = JsonConvert.DeserializeObject(content); - return (((IEnumerable)data.data).OrderBy(x => x.sortOrder)).ToList().ConvertAll(x => { return new People(-1, ToSlug((string)x.name), (string)x.name, (string)x.role, null, "https://www.thetvdb.com/banners/" + (string)x.image, string.Format("TvDB={0}|", x.id)); }); - } - } - Debug.WriteLine("&TheTvDB Provider couldn't work for the actors of the show: " + id + ".\nError Code: " + response.StatusCode + " Message: " + response.StatusDescription); - response.Close(); - return null; - } - catch (WebException ex) - { - Debug.WriteLine("&TheTvDB Provider couldn't work for the actors of the show: " + id + ".\nError Code: " + ex.Status); - return null; - } - } - } -} diff --git a/Kyoo/Controllers/MetadataProvider/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs similarity index 99% rename from Kyoo/Controllers/MetadataProvider/ProviderManager.cs rename to Kyoo/Controllers/ProviderManager.cs index 4847ebed..cc2ea92e 100644 --- a/Kyoo/Controllers/MetadataProvider/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -27,8 +27,6 @@ namespace Kyoo.InternalAPI void LoadProviders() { providers.Clear(); - providers.Add(new ProviderTheTvDB()); - string pluginFolder = config.GetValue("providerPlugins"); if (Directory.Exists(pluginFolder)) diff --git a/Kyoo/HTML_API/AdminController.cs b/Kyoo/HtmlAPI/AdminController.cs similarity index 100% rename from Kyoo/HTML_API/AdminController.cs rename to Kyoo/HtmlAPI/AdminController.cs diff --git a/Kyoo/HTML_API/CollectionController.cs b/Kyoo/HtmlAPI/CollectionController.cs similarity index 100% rename from Kyoo/HTML_API/CollectionController.cs rename to Kyoo/HtmlAPI/CollectionController.cs diff --git a/Kyoo/HTML_API/EpisodesController.cs b/Kyoo/HtmlAPI/EpisodesController.cs similarity index 100% rename from Kyoo/HTML_API/EpisodesController.cs rename to Kyoo/HtmlAPI/EpisodesController.cs diff --git a/Kyoo/HTML_API/LibrariesController.cs b/Kyoo/HtmlAPI/LibrariesController.cs similarity index 100% rename from Kyoo/HTML_API/LibrariesController.cs rename to Kyoo/HtmlAPI/LibrariesController.cs diff --git a/Kyoo/HTML_API/PeopleController.cs b/Kyoo/HtmlAPI/PeopleController.cs similarity index 100% rename from Kyoo/HTML_API/PeopleController.cs rename to Kyoo/HtmlAPI/PeopleController.cs diff --git a/Kyoo/HTML_API/SearchController.cs b/Kyoo/HtmlAPI/SearchController.cs similarity index 100% rename from Kyoo/HTML_API/SearchController.cs rename to Kyoo/HtmlAPI/SearchController.cs diff --git a/Kyoo/HTML_API/ShowsController.cs b/Kyoo/HtmlAPI/ShowsController.cs similarity index 100% rename from Kyoo/HTML_API/ShowsController.cs rename to Kyoo/HtmlAPI/ShowsController.cs diff --git a/Kyoo/HTML_API/SubtitleController.cs b/Kyoo/HtmlAPI/SubtitleController.cs similarity index 100% rename from Kyoo/HTML_API/SubtitleController.cs rename to Kyoo/HtmlAPI/SubtitleController.cs diff --git a/Kyoo/HTML_API/ThumbnailController.cs b/Kyoo/HtmlAPI/ThumbnailController.cs similarity index 100% rename from Kyoo/HTML_API/ThumbnailController.cs rename to Kyoo/HtmlAPI/ThumbnailController.cs diff --git a/Kyoo/HTML_API/VideoController.cs b/Kyoo/HtmlAPI/VideoController.cs similarity index 100% rename from Kyoo/HTML_API/VideoController.cs rename to Kyoo/HtmlAPI/VideoController.cs diff --git a/Kyoo/HTML_API/WatchController.cs b/Kyoo/HtmlAPI/WatchController.cs similarity index 100% rename from Kyoo/HTML_API/WatchController.cs rename to Kyoo/HtmlAPI/WatchController.cs diff --git a/Kyoo/Kyoo.csproj b/Kyoo/Kyoo.csproj index ac60fce7..09b88261 100644 --- a/Kyoo/Kyoo.csproj +++ b/Kyoo/Kyoo.csproj @@ -29,6 +29,8 @@ + + @@ -44,11 +46,16 @@ Always + + + + + diff --git a/MetadataProvider/MetadataProvider.csproj b/MetadataProvider/MetadataProvider.csproj deleted file mode 100644 index 4342747a..00000000 --- a/MetadataProvider/MetadataProvider.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - netcoreapp3.0 - - - - - - - From 9d37426764fd2fd925989a34103fe121eefd1e5d Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 18 Jan 2020 00:42:49 +0100 Subject: [PATCH 03/11] Adding a plugin manager --- Kyoo.Common/Controllers/ICrawler.cs | 2 +- Kyoo.Common/Controllers/ILibraryManager.cs | 2 +- Kyoo.Common/Controllers/IMetadataProvider.cs | 2 +- Kyoo.Common/Controllers/IPluginManager.cs | 11 ++++ Kyoo.Common/Controllers/IThumbnailsManager.cs | 2 +- Kyoo.Common/Controllers/ITranscoder.cs | 2 +- Kyoo.Common/Models/Collection.cs | 2 +- Kyoo.Common/Models/Plugin.cs | 7 +++ Kyoo.Common/Models/Show.cs | 2 +- Kyoo.Common/Models/WatchItem.cs | 2 +- Kyoo.Common/Plugins/MetadataAttribute.cs | 10 ---- Kyoo.Common/Utility/ImageHelper.cs | 2 +- Kyoo.Common/Utility/Slugifier.cs | 2 +- Kyoo/Controllers/Crawler.cs | 6 +-- Kyoo/Controllers/LibraryManager.cs | 2 +- Kyoo/Controllers/PluginManager.cs | 54 +++++++++++++++++++ Kyoo/Controllers/ProviderManager.cs | 51 +++--------------- Kyoo/Controllers/ThumbnailsManager.cs | 2 +- Kyoo/Controllers/Transcoder/Transcoder.cs | 5 +- Kyoo/Controllers/Transcoder/TranscoderAPI.cs | 2 +- Kyoo/HtmlAPI/AdminController.cs | 2 +- Kyoo/HtmlAPI/CollectionController.cs | 2 +- Kyoo/HtmlAPI/EpisodesController.cs | 2 +- Kyoo/HtmlAPI/LibrariesController.cs | 2 +- Kyoo/HtmlAPI/PeopleController.cs | 2 +- Kyoo/HtmlAPI/SearchController.cs | 2 +- Kyoo/HtmlAPI/ShowsController.cs | 2 +- Kyoo/HtmlAPI/SubtitleController.cs | 4 +- Kyoo/HtmlAPI/ThumbnailController.cs | 5 +- Kyoo/HtmlAPI/VideoController.cs | 2 +- Kyoo/HtmlAPI/WatchController.cs | 2 +- Kyoo/Startup.cs | 9 ++-- 32 files changed, 113 insertions(+), 93 deletions(-) create mode 100644 Kyoo.Common/Controllers/IPluginManager.cs create mode 100644 Kyoo.Common/Models/Plugin.cs delete mode 100644 Kyoo.Common/Plugins/MetadataAttribute.cs create mode 100644 Kyoo/Controllers/PluginManager.cs diff --git a/Kyoo.Common/Controllers/ICrawler.cs b/Kyoo.Common/Controllers/ICrawler.cs index 30514f7f..bbb6d4dc 100644 --- a/Kyoo.Common/Controllers/ICrawler.cs +++ b/Kyoo.Common/Controllers/ICrawler.cs @@ -1,7 +1,7 @@ using System.Threading; using System.Threading.Tasks; -namespace Kyoo.InternalAPI +namespace Kyoo.Controllers { public interface ICrawler { diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index a85cceb3..3e40d923 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -2,7 +2,7 @@ using Kyoo.Models.Watch; using System.Collections.Generic; -namespace Kyoo.InternalAPI +namespace Kyoo.Controllers { public interface ILibraryManager { diff --git a/Kyoo.Common/Controllers/IMetadataProvider.cs b/Kyoo.Common/Controllers/IMetadataProvider.cs index 1a53a4b5..1b46283f 100644 --- a/Kyoo.Common/Controllers/IMetadataProvider.cs +++ b/Kyoo.Common/Controllers/IMetadataProvider.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Kyoo.InternalAPI +namespace Kyoo.Controllers { public interface IMetadataProvider { diff --git a/Kyoo.Common/Controllers/IPluginManager.cs b/Kyoo.Common/Controllers/IPluginManager.cs new file mode 100644 index 00000000..815c8395 --- /dev/null +++ b/Kyoo.Common/Controllers/IPluginManager.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Kyoo.Controllers +{ + public interface IPluginManager + { + public T GetPlugin(string name); + public IEnumerable GetPlugins(); + public void ReloadPlugins(); + } +} \ No newline at end of file diff --git a/Kyoo.Common/Controllers/IThumbnailsManager.cs b/Kyoo.Common/Controllers/IThumbnailsManager.cs index 4d11d7f3..ac88cc40 100644 --- a/Kyoo.Common/Controllers/IThumbnailsManager.cs +++ b/Kyoo.Common/Controllers/IThumbnailsManager.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Kyoo.InternalAPI.ThumbnailsManager +namespace Kyoo.Controllers.ThumbnailsManager { public interface IThumbnailsManager { diff --git a/Kyoo.Common/Controllers/ITranscoder.cs b/Kyoo.Common/Controllers/ITranscoder.cs index bea35952..861cd492 100644 --- a/Kyoo.Common/Controllers/ITranscoder.cs +++ b/Kyoo.Common/Controllers/ITranscoder.cs @@ -2,7 +2,7 @@ using Kyoo.Models; using Kyoo.Models.Watch; using System.Threading.Tasks; -namespace Kyoo.InternalAPI +namespace Kyoo.Controllers { public interface ITranscoder { diff --git a/Kyoo.Common/Models/Collection.cs b/Kyoo.Common/Models/Collection.cs index 0ac1ad3b..2c520313 100644 --- a/Kyoo.Common/Models/Collection.cs +++ b/Kyoo.Common/Models/Collection.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Newtonsoft.Json; using System.Collections.Generic; diff --git a/Kyoo.Common/Models/Plugin.cs b/Kyoo.Common/Models/Plugin.cs new file mode 100644 index 00000000..c79de89c --- /dev/null +++ b/Kyoo.Common/Models/Plugin.cs @@ -0,0 +1,7 @@ +namespace Kyoo.Models +{ + public interface IPlugin + { + public string Name { get; } + } +} \ No newline at end of file diff --git a/Kyoo.Common/Models/Show.cs b/Kyoo.Common/Models/Show.cs index b2c267ee..7b975413 100644 --- a/Kyoo.Common/Models/Show.cs +++ b/Kyoo.Common/Models/Show.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Newtonsoft.Json; using System.Collections.Generic; diff --git a/Kyoo.Common/Models/WatchItem.cs b/Kyoo.Common/Models/WatchItem.cs index 4d092aa4..5ef7d5ab 100644 --- a/Kyoo.Common/Models/WatchItem.cs +++ b/Kyoo.Common/Models/WatchItem.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Newtonsoft.Json; using System; using System.Collections.Generic; diff --git a/Kyoo.Common/Plugins/MetadataAttribute.cs b/Kyoo.Common/Plugins/MetadataAttribute.cs deleted file mode 100644 index 35199691..00000000 --- a/Kyoo.Common/Plugins/MetadataAttribute.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Kyoo.InternalAPI.MetadataProvider -{ - [AttributeUsage(AttributeTargets.Class)] - public class MetaProvider : Attribute - { - public MetaProvider() { } - } -} diff --git a/Kyoo.Common/Utility/ImageHelper.cs b/Kyoo.Common/Utility/ImageHelper.cs index c9b075e7..d75bd30d 100644 --- a/Kyoo.Common/Utility/ImageHelper.cs +++ b/Kyoo.Common/Utility/ImageHelper.cs @@ -1,6 +1,6 @@ using Kyoo.Models; -namespace Kyoo.InternalAPI.Utility +namespace Kyoo.Controllers.Utility { public static class ImageHelper { diff --git a/Kyoo.Common/Utility/Slugifier.cs b/Kyoo.Common/Utility/Slugifier.cs index 395c4d77..22cbc4f3 100644 --- a/Kyoo.Common/Utility/Slugifier.cs +++ b/Kyoo.Common/Utility/Slugifier.cs @@ -1,6 +1,6 @@ using System.Text.RegularExpressions; -namespace Kyoo.InternalAPI.Utility +namespace Kyoo.Controllers.Utility { public class Slugifier { diff --git a/Kyoo/Controllers/Crawler.cs b/Kyoo/Controllers/Crawler.cs index 89ff7daf..3a3662ef 100644 --- a/Kyoo/Controllers/Crawler.cs +++ b/Kyoo/Controllers/Crawler.cs @@ -1,5 +1,4 @@ -using Kyoo.InternalAPI.Utility; -using Kyoo.Models; +using Kyoo.Models; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Diagnostics; @@ -8,9 +7,10 @@ using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Kyoo.Controllers.Utility; using Kyoo.Models.Watch; -namespace Kyoo.InternalAPI +namespace Kyoo.Controllers { public class Crawler : ICrawler { diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 69d9c630..e55c5f5e 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -7,7 +7,7 @@ using System.Data.SQLite; using System.Diagnostics; using System.IO; -namespace Kyoo.InternalAPI +namespace Kyoo.Controllers { public class LibraryManager : ILibraryManager { diff --git a/Kyoo/Controllers/PluginManager.cs b/Kyoo/Controllers/PluginManager.cs new file mode 100644 index 00000000..78d2444d --- /dev/null +++ b/Kyoo/Controllers/PluginManager.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Kyoo.Models; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Kyoo.Controllers +{ + public class PluginManager : IPluginManager + { + private readonly IServiceProvider provider; + private readonly IConfiguration config; + private List plugins; + + public PluginManager(IServiceProvider provider, IConfiguration config) + { + this.provider = provider; + this.config = config; + ReloadPlugins(); + } + + public T GetPlugin(string name) + { + return (T)(from plugin in plugins where plugin.Name == name && plugin is T + select plugin).FirstOrDefault(); + } + + public IEnumerable GetPlugins() + { + return from plugin in plugins where plugin is T + select (T)plugin; + } + + public void ReloadPlugins() + { + string pluginFolder = config.GetValue("plugins"); + + if (!Directory.Exists(pluginFolder)) + return; + string[] pluginsPaths = Directory.GetFiles(pluginFolder); + + plugins = pluginsPaths.Select(path => + { + Assembly ass = Assembly.LoadFile(path); + return (from type in ass.GetTypes() + where typeof(IPlugin).IsAssignableFrom(type) + select (IPlugin)ActivatorUtilities.CreateInstance(provider, type, null)).FirstOrDefault(); + }).Where(x => x != null).ToList(); + } + } +} \ No newline at end of file diff --git a/Kyoo/Controllers/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs index cc2ea92e..4cf11925 100644 --- a/Kyoo/Controllers/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -1,6 +1,4 @@ -using Kyoo.InternalAPI.MetadataProvider; -using Kyoo.InternalAPI.ThumbnailsManager; -using Kyoo.Models; +using Kyoo.Models; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; @@ -8,56 +6,21 @@ using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using Kyoo.Controllers.ThumbnailsManager; -namespace Kyoo.InternalAPI +namespace Kyoo.Controllers { public class ProviderManager : IMetadataProvider { - private readonly List providers = new List(); + private readonly IEnumerable providers; private readonly IThumbnailsManager thumbnailsManager; private readonly IConfiguration config; - public ProviderManager(IThumbnailsManager thumbnailsManager, IConfiguration configuration) + public ProviderManager(IThumbnailsManager thumbnailsManager, IPluginManager pluginManager, IConfiguration config) { this.thumbnailsManager = thumbnailsManager; - config = configuration; - LoadProviders(); - } - - void LoadProviders() - { - providers.Clear(); - string pluginFolder = config.GetValue("providerPlugins"); - - if (Directory.Exists(pluginFolder)) - { - string[] pluginsPaths = Directory.GetFiles(pluginFolder); - List plugins = new List(); - List types = new List(); - - for (int i = 0; i < pluginsPaths.Length; i++) - { - plugins.Add(Assembly.LoadFile(pluginsPaths[i])); - types.AddRange(plugins[i].GetTypes()); - } - - List providersPlugins = types.FindAll(x => - { - object[] atr = x.GetCustomAttributes(typeof(MetaProvider), false); - - if (atr == null || atr.Length == 0) - return false; - - List interfaces = new List(x.GetInterfaces()); - - if (interfaces.Contains(typeof(IMetadataProvider))) - return true; - - return false; - }); - - providers.AddRange(providersPlugins.ConvertAll(x => Activator.CreateInstance(x) as IMetadataProvider)); - } + this.config = config; + providers = pluginManager.GetPlugins(); } public Show Merge(IEnumerable shows) diff --git a/Kyoo/Controllers/ThumbnailsManager.cs b/Kyoo/Controllers/ThumbnailsManager.cs index 94b11fd3..3e0a468c 100644 --- a/Kyoo/Controllers/ThumbnailsManager.cs +++ b/Kyoo/Controllers/ThumbnailsManager.cs @@ -7,7 +7,7 @@ using System.IO; using System.Net; using System.Threading.Tasks; -namespace Kyoo.InternalAPI.ThumbnailsManager +namespace Kyoo.Controllers.ThumbnailsManager { public class ThumbnailsManager : IThumbnailsManager { diff --git a/Kyoo/Controllers/Transcoder/Transcoder.cs b/Kyoo/Controllers/Transcoder/Transcoder.cs index cae60986..47811e4f 100644 --- a/Kyoo/Controllers/Transcoder/Transcoder.cs +++ b/Kyoo/Controllers/Transcoder/Transcoder.cs @@ -1,14 +1,15 @@ using System; using Kyoo.Models; -using Kyoo.InternalAPI.TranscoderLink; using Microsoft.Extensions.Configuration; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Threading.Tasks; +using Kyoo.Controllers.TranscoderLink; + #pragma warning disable 4014 -namespace Kyoo.InternalAPI +namespace Kyoo.Controllers { public class Transcoder : ITranscoder { diff --git a/Kyoo/Controllers/Transcoder/TranscoderAPI.cs b/Kyoo/Controllers/Transcoder/TranscoderAPI.cs index 27c13f31..b95c0584 100644 --- a/Kyoo/Controllers/Transcoder/TranscoderAPI.cs +++ b/Kyoo/Controllers/Transcoder/TranscoderAPI.cs @@ -5,7 +5,7 @@ using Kyoo.Models; using Kyoo.Models.Watch; // ReSharper disable InconsistentNaming -namespace Kyoo.InternalAPI.TranscoderLink +namespace Kyoo.Controllers.TranscoderLink { public static class TranscoderAPI { diff --git a/Kyoo/HtmlAPI/AdminController.cs b/Kyoo/HtmlAPI/AdminController.cs index 976f9140..fdd006c6 100644 --- a/Kyoo/HtmlAPI/AdminController.cs +++ b/Kyoo/HtmlAPI/AdminController.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; diff --git a/Kyoo/HtmlAPI/CollectionController.cs b/Kyoo/HtmlAPI/CollectionController.cs index 9e1a84e1..8d1a8543 100644 --- a/Kyoo/HtmlAPI/CollectionController.cs +++ b/Kyoo/HtmlAPI/CollectionController.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; diff --git a/Kyoo/HtmlAPI/EpisodesController.cs b/Kyoo/HtmlAPI/EpisodesController.cs index ac2ac30e..b3876234 100644 --- a/Kyoo/HtmlAPI/EpisodesController.cs +++ b/Kyoo/HtmlAPI/EpisodesController.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; diff --git a/Kyoo/HtmlAPI/LibrariesController.cs b/Kyoo/HtmlAPI/LibrariesController.cs index a2c05df3..c142f00e 100644 --- a/Kyoo/HtmlAPI/LibrariesController.cs +++ b/Kyoo/HtmlAPI/LibrariesController.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; diff --git a/Kyoo/HtmlAPI/PeopleController.cs b/Kyoo/HtmlAPI/PeopleController.cs index 9c08379f..2e93b8b5 100644 --- a/Kyoo/HtmlAPI/PeopleController.cs +++ b/Kyoo/HtmlAPI/PeopleController.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Diagnostics; diff --git a/Kyoo/HtmlAPI/SearchController.cs b/Kyoo/HtmlAPI/SearchController.cs index 1dd08d17..e070ab41 100644 --- a/Kyoo/HtmlAPI/SearchController.cs +++ b/Kyoo/HtmlAPI/SearchController.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; diff --git a/Kyoo/HtmlAPI/ShowsController.cs b/Kyoo/HtmlAPI/ShowsController.cs index 97f7ecae..436f6c45 100644 --- a/Kyoo/HtmlAPI/ShowsController.cs +++ b/Kyoo/HtmlAPI/ShowsController.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; diff --git a/Kyoo/HtmlAPI/SubtitleController.cs b/Kyoo/HtmlAPI/SubtitleController.cs index c3487a42..747e6cc0 100644 --- a/Kyoo/HtmlAPI/SubtitleController.cs +++ b/Kyoo/HtmlAPI/SubtitleController.cs @@ -1,8 +1,6 @@ -using Kyoo.InternalAPI; -using Kyoo.Models; +using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Threading.Tasks; diff --git a/Kyoo/HtmlAPI/ThumbnailController.cs b/Kyoo/HtmlAPI/ThumbnailController.cs index 74100b7a..6c0bd2ba 100644 --- a/Kyoo/HtmlAPI/ThumbnailController.cs +++ b/Kyoo/HtmlAPI/ThumbnailController.cs @@ -1,11 +1,10 @@ -using Kyoo.InternalAPI; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using System.IO; namespace Kyoo.Controllers { - public class ThumbnailController : Controller + public class ThumbnailController : ControllerBase { private readonly ILibraryManager libraryManager; private readonly string peoplePath; diff --git a/Kyoo/HtmlAPI/VideoController.cs b/Kyoo/HtmlAPI/VideoController.cs index c5ebc43c..b58da90f 100644 --- a/Kyoo/HtmlAPI/VideoController.cs +++ b/Kyoo/HtmlAPI/VideoController.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; diff --git a/Kyoo/HtmlAPI/WatchController.cs b/Kyoo/HtmlAPI/WatchController.cs index 0de4d726..a1eadf95 100644 --- a/Kyoo/HtmlAPI/WatchController.cs +++ b/Kyoo/HtmlAPI/WatchController.cs @@ -1,4 +1,4 @@ -using Kyoo.InternalAPI; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Diagnostics; diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index 71ea8672..f2b74b67 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -1,5 +1,5 @@ -using Kyoo.InternalAPI; -using Kyoo.InternalAPI.ThumbnailsManager; +using Kyoo.Controllers; +using Kyoo.Controllers.ThumbnailsManager; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.SpaServices.AngularCli; @@ -30,12 +30,9 @@ namespace Kyoo }); services.AddControllers().AddNewtonsoftJson(); - - //Services needed in the private and in the public API + services.AddSingleton(); services.AddSingleton(); - - //Services used to get informations about files and register them services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); From 3d79d41a60490a1184e071a30c2f5fa04789c447 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 18 Jan 2020 17:34:07 +0100 Subject: [PATCH 04/11] Creating the provider manager --- Kyoo.Common/Controllers/ICrawler.cs | 4 +- Kyoo.Common/Controllers/ILibraryManager.cs | 4 +- Kyoo.Common/Controllers/IMetadataProvider.cs | 6 +- Kyoo.Common/Controllers/IProviderManager.cs | 15 ++ Kyoo.Common/Controllers/IThumbnailsManager.cs | 2 +- Kyoo.Common/Models/Collection.cs | 98 ++++++---- Kyoo.Common/Models/Episode.cs | 33 +++- Kyoo.Common/Models/Library.cs | 11 +- Kyoo.Common/Models/People.cs | 23 ++- Kyoo.Common/Models/Season.cs | 24 ++- Kyoo.Common/Models/Show.cs | 46 ++++- Kyoo.Common/Utility/IMergable.cs | 9 + Kyoo/Controllers/Crawler.cs | 167 ++++++------------ Kyoo/Controllers/LibraryManager.cs | 27 +-- Kyoo/Controllers/ProviderManager.cs | 135 +++++--------- Kyoo/Controllers/ThumbnailsManager.cs | 10 +- Kyoo/HtmlAPI/AdminController.cs | 6 +- Kyoo/Startup.cs | 2 +- 18 files changed, 343 insertions(+), 279 deletions(-) create mode 100644 Kyoo.Common/Controllers/IProviderManager.cs create mode 100644 Kyoo.Common/Utility/IMergable.cs diff --git a/Kyoo.Common/Controllers/ICrawler.cs b/Kyoo.Common/Controllers/ICrawler.cs index bbb6d4dc..6dc29922 100644 --- a/Kyoo.Common/Controllers/ICrawler.cs +++ b/Kyoo.Common/Controllers/ICrawler.cs @@ -5,8 +5,8 @@ namespace Kyoo.Controllers { public interface ICrawler { - Task Start(bool watch); + void Start(); - Task StopAsync(); + void Cancel(); } } diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index 3e40d923..b920219b 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -63,9 +63,9 @@ namespace Kyoo.Controllers long GetOrCreateGenre(Genre genre); long GetOrCreateStudio(Studio studio); - void RegisterShowPeople(long showID, List actors); + void RegisterShowPeople(long showID, IEnumerable actors); void AddShowToCollection(long showID, long collectionID); - void RegisterInLibrary(long showID, string libraryPath); + void RegisterInLibrary(long showID, Library library); void RemoveEpisode(Episode episode); void ClearSubtitles(long episodeID); diff --git a/Kyoo.Common/Controllers/IMetadataProvider.cs b/Kyoo.Common/Controllers/IMetadataProvider.cs index 1b46283f..878129bb 100644 --- a/Kyoo.Common/Controllers/IMetadataProvider.cs +++ b/Kyoo.Common/Controllers/IMetadataProvider.cs @@ -6,18 +6,18 @@ namespace Kyoo.Controllers { public interface IMetadataProvider { + public string Name { get; } + //For the collection Task GetCollectionFromName(string name); //For the show Task GetShowByID(string id); Task GetShowFromName(string showName, string showPath); - Task GetImages(Show show); - Task> GetPeople(string id); + Task> GetPeople(string id); //For the seasons Task GetSeason(string showName, long seasonNumber); - Task GetSeasonImage(string showName, long seasonNumber); //For the episodes Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath); diff --git a/Kyoo.Common/Controllers/IProviderManager.cs b/Kyoo.Common/Controllers/IProviderManager.cs new file mode 100644 index 00000000..3f775013 --- /dev/null +++ b/Kyoo.Common/Controllers/IProviderManager.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Kyoo.Models; + +namespace Kyoo.Controllers +{ + public interface IProviderManager + { + Task GetCollectionFromName(string name, Library library); + Task GetShowFromName(string showName, string showPath, Library library); + Task GetSeason(string showName, long seasonNumber, Library library); + Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath, Library library); + Task> GetPeople(string showExternalIDs, Library library); + } +} \ No newline at end of file diff --git a/Kyoo.Common/Controllers/IThumbnailsManager.cs b/Kyoo.Common/Controllers/IThumbnailsManager.cs index ac88cc40..4144f1ec 100644 --- a/Kyoo.Common/Controllers/IThumbnailsManager.cs +++ b/Kyoo.Common/Controllers/IThumbnailsManager.cs @@ -7,7 +7,7 @@ namespace Kyoo.Controllers.ThumbnailsManager public interface IThumbnailsManager { Task Validate(Show show); - Task> Validate(List actors); + Task> Validate(IEnumerable actors); Task Validate(Episode episode); } } diff --git a/Kyoo.Common/Models/Collection.cs b/Kyoo.Common/Models/Collection.cs index 2c520313..81ade2a7 100644 --- a/Kyoo.Common/Models/Collection.cs +++ b/Kyoo.Common/Models/Collection.cs @@ -1,50 +1,76 @@ using Kyoo.Controllers; using Newtonsoft.Json; using System.Collections.Generic; +using System.Linq; +using Kyoo.Utility; namespace Kyoo.Models { - public class Collection + public class Collection : IMergable + { - [JsonIgnore] public long id; - public string Slug; - public string Name; - public string Poster; - public string Overview; - [JsonIgnore] public string ImgPrimary; - public IEnumerable Shows; + [JsonIgnore] public long id = -1; + public string Slug; + public string Name; + public string Poster; + public string Overview; + [JsonIgnore] public string ImgPrimary; + public IEnumerable Shows; - public Collection() { } + public Collection() + { + } - public Collection(long id, string slug, string name, string overview, string imgPrimary) - { - this.id = id; - Slug = slug; - Name = name; - Overview = overview; - ImgPrimary = imgPrimary; - } + public Collection(long id, string slug, string name, string overview, string imgPrimary) + { + this.id = id; + Slug = slug; + Name = name; + Overview = overview; + ImgPrimary = imgPrimary; + } - public static Collection FromReader(System.Data.SQLite.SQLiteDataReader reader) - { - Collection col = new Collection((long)reader["id"], - reader["slug"] as string, - reader["name"] as string, - reader["overview"] as string, - reader["imgPrimary"] as string); - col.Poster = "poster/" + col.Slug; - return col; - } + public static Collection FromReader(System.Data.SQLite.SQLiteDataReader reader) + { + Collection col = new Collection((long) reader["id"], + reader["slug"] as string, + reader["name"] as string, + reader["overview"] as string, + reader["imgPrimary"] as string); + col.Poster = "poster/" + col.Slug; + return col; + } - public Show AsShow() - { - return new Show(-1, Slug, Name, null, null, Overview, null, null, null, null, null, null); - } + public Show AsShow() + { + return new Show(-1, Slug, Name, null, null, Overview, null, null, null, null, null, null); + } - public Collection SetShows(ILibraryManager libraryManager) - { - Shows = libraryManager.GetShowsInCollection(id); - return this; - } + public Collection SetShows(ILibraryManager libraryManager) + { + Shows = libraryManager.GetShowsInCollection(id); + return this; + } + + public Collection Merge(Collection collection) + { + if (id == -1) + id = collection.id; + if (Slug == null) + Slug = collection.Slug; + if (Name == null) + Name = collection.Name; + if (Poster == null) + Poster = collection.Poster; + if (Overview == null) + Overview = collection.Overview; + if (ImgPrimary == null) + ImgPrimary = collection.ImgPrimary; + if (Shows == null) + Shows = collection.Shows; + else + Shows = Shows.Concat(collection.Shows); + return this; + } } } diff --git a/Kyoo.Common/Models/Episode.cs b/Kyoo.Common/Models/Episode.cs index 58661490..c7d53dbc 100644 --- a/Kyoo.Common/Models/Episode.cs +++ b/Kyoo.Common/Models/Episode.cs @@ -1,9 +1,10 @@ using Newtonsoft.Json; using System; +using Kyoo.Utility; namespace Kyoo.Models { - public class Episode + public class Episode : IMergable { [JsonIgnore] public long id; [JsonIgnore] public long ShowID; @@ -97,5 +98,35 @@ namespace Kyoo.Models { return showSlug + "-s" + seasonNumber + "e" + episodeNumber; } + + public Episode Merge(Episode other) + { + if (id == -1) + id = other.id; + if (ShowID == -1) + ShowID = other.ShowID; + if (SeasonID == -1) + SeasonID = other.SeasonID; + if (seasonNumber == -1) + seasonNumber = other.seasonNumber; + if (episodeNumber == -1) + episodeNumber = other.episodeNumber; + if (absoluteNumber == -1) + absoluteNumber = other.absoluteNumber; + if (Path == null) + Path = other.Path; + if (Title == null) + Title = other.Title; + if (Overview == null) + Overview = other.Overview; + if (ReleaseDate == null) + ReleaseDate = other.ReleaseDate; + if (Runtime == -1) + Runtime = other.Runtime; + if (ImgPrimary == null) + ImgPrimary = other.ImgPrimary; + ExternalIDs += '|' + other.ExternalIDs; + return this; + } } } diff --git a/Kyoo.Common/Models/Library.cs b/Kyoo.Common/Models/Library.cs index 638091c9..c0a0fe8b 100644 --- a/Kyoo.Common/Models/Library.cs +++ b/Kyoo.Common/Models/Library.cs @@ -7,14 +7,16 @@ namespace Kyoo.Models [JsonIgnore] public readonly long id; public string Slug; public string Name; - public string Path; + public string[] Paths; + public string[] Providers; - public Library(long id, string slug, string name, string path) + public Library(long id, string slug, string name, string[] paths, string[] providers) { this.id = id; Slug = slug; Name = name; - Path = path; + Paths = paths; + Providers = providers; } public static Library FromReader(System.Data.SQLite.SQLiteDataReader reader) @@ -22,7 +24,8 @@ namespace Kyoo.Models return new Library((long)reader["id"], reader["slug"] as string, reader["name"] as string, - reader["path"] as string); + (reader["path"] as string)?.Split('|'), + (reader["providers"] as string)?.Split('|')); } } } diff --git a/Kyoo.Common/Models/People.cs b/Kyoo.Common/Models/People.cs index 79003c23..abb44c53 100644 --- a/Kyoo.Common/Models/People.cs +++ b/Kyoo.Common/Models/People.cs @@ -1,8 +1,9 @@ -using Newtonsoft.Json; +using Kyoo.Utility; +using Newtonsoft.Json; namespace Kyoo.Models { - public class People + public class People : IMergable { [JsonIgnore] public long id; public string slug; @@ -52,5 +53,23 @@ namespace Kyoo.Models reader["imgPrimary"] as string, reader["externalIDs"] as string); } + + public People Merge(People other) + { + if (id == -1) + id = other.id; + if (slug == null) + slug = other.slug; + if (Name == null) + Name = other.Name; + if (Role == null) + Role = other.Role; + if (Type == null) + Type = other.Type; + if (imgPrimary == null) + imgPrimary = other.imgPrimary; + externalIDs += '|' + other.externalIDs; + return this; + } } } diff --git a/Kyoo.Common/Models/Season.cs b/Kyoo.Common/Models/Season.cs index c555d932..6c9133f1 100644 --- a/Kyoo.Common/Models/Season.cs +++ b/Kyoo.Common/Models/Season.cs @@ -1,8 +1,10 @@ -using Newtonsoft.Json; +using System.Linq; +using Kyoo.Utility; +using Newtonsoft.Json; namespace Kyoo.Models { - public class Season + public class Season : IMergable { [JsonIgnore] public readonly long id; [JsonIgnore] public long ShowID; @@ -40,5 +42,23 @@ namespace Kyoo.Models reader["imgPrimary"] as string, reader["externalIDs"] as string); } + + public Season Merge(Season other) + { + if (ShowID == -1) + ShowID = other.ShowID; + if (seasonNumber == -1) + seasonNumber = other.seasonNumber; + if (Title == null) + Title = other.Title; + if (Overview == null) + Overview = other.Overview; + if (year == null) + year = other.year; + if (ImgPrimary == null) + ImgPrimary = other.ImgPrimary; + ExternalIDs += '|' + other.ExternalIDs; + return this; + } } } diff --git a/Kyoo.Common/Models/Show.cs b/Kyoo.Common/Models/Show.cs index 7b975413..bd179283 100644 --- a/Kyoo.Common/Models/Show.cs +++ b/Kyoo.Common/Models/Show.cs @@ -1,10 +1,12 @@ using Kyoo.Controllers; using Newtonsoft.Json; using System.Collections.Generic; +using System.Linq; +using Kyoo.Utility; namespace Kyoo.Models { - public class Show + public class Show : IMergable { [JsonIgnore] public long id = -1; @@ -111,7 +113,7 @@ namespace Kyoo.Models return new Show((long)reader["id"], reader["slug"] as string, reader["title"] as string, - (reader["aliases"] as string)?.Split('|') ?? null, + (reader["aliases"] as string)?.Split('|'), reader["path"] as string, reader["overview"] as string, reader["trailerUrl"] as string, @@ -161,6 +163,46 @@ namespace Kyoo.Models seasons = manager.GetSeasons(id); return this; } + + public Show Merge(Show other) + { + if (id == -1) + id = other.id; + if (Slug == null) + Slug = other.Slug; + if (Title == null) + Title = other.Title; + if (Aliases == null) + Aliases = other.Aliases; + else + Aliases = Aliases.Concat(other.Aliases); + if (Genres == null) + Genres = other.Genres; + else + Genres = Genres.Concat(other.Genres); + if (Path == null) + Path = other.Path; + if (Overview == null) + Overview = other.Overview; + if (TrailerUrl == null) + TrailerUrl = other.TrailerUrl; + if (Status == null) + Status = other.Status; + if (StartYear == null) + StartYear = other.StartYear; + if (EndYear == null) + EndYear = other.EndYear; + if (ImgPrimary == null) + ImgPrimary = other.ImgPrimary; + if (ImgThumb == null) + ImgThumb = other.ImgThumb; + if (ImgLogo == null) + ImgLogo = other.ImgLogo; + if (ImgBackdrop == null) + ImgBackdrop = other.ImgBackdrop; + ExternalIDs += '|' + other.ExternalIDs; + return this; + } } public enum Status { Finished, Airing } diff --git a/Kyoo.Common/Utility/IMergable.cs b/Kyoo.Common/Utility/IMergable.cs new file mode 100644 index 00000000..3c56420b --- /dev/null +++ b/Kyoo.Common/Utility/IMergable.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Kyoo.Utility +{ + public interface IMergable + { + public T Merge(T other); + } +} \ No newline at end of file diff --git a/Kyoo/Controllers/Crawler.cs b/Kyoo/Controllers/Crawler.cs index 3a3662ef..a2591c45 100644 --- a/Kyoo/Controllers/Crawler.cs +++ b/Kyoo/Controllers/Crawler.cs @@ -14,16 +14,15 @@ namespace Kyoo.Controllers { public class Crawler : ICrawler { - private static ICrawler runningCrawler; - private bool isScanning; + private bool isRunning; private readonly CancellationTokenSource cancellation; private readonly ILibraryManager libraryManager; - private readonly IMetadataProvider metadataProvider; + private readonly IProviderManager metadataProvider; private readonly ITranscoder transcoder; private readonly IConfiguration config; - public Crawler(ILibraryManager libraryManager, IMetadataProvider metadataProvider, ITranscoder transcoder, IConfiguration configuration) + public Crawler(ILibraryManager libraryManager, IProviderManager metadataProvider, ITranscoder transcoder, IConfiguration configuration) { this.libraryManager = libraryManager; this.metadataProvider = metadataProvider; @@ -32,30 +31,27 @@ namespace Kyoo.Controllers cancellation = new CancellationTokenSource(); } - public async Task Start(bool watch) + public void Start() { - if (runningCrawler == null) - { - runningCrawler = this; - await StartAsync(watch, cancellation.Token); - } - else if (runningCrawler is Crawler crawler) - { - if (!crawler.isScanning) - { - await crawler.StopAsync(); - runningCrawler = this; - await StartAsync(watch, cancellation.Token); - } - } + if (isRunning) + return; + isRunning = true; + StartAsync(cancellation.Token); } - private Task StartAsync(bool watch, CancellationToken cancellationToken) + public void Cancel() + { + if (!isRunning) + return; + isRunning = false; + cancellation.Cancel(); + } + + private async void StartAsync(CancellationToken cancellationToken) { IEnumerable episodes = libraryManager.GetAllEpisodes(); - IEnumerable libraryPaths = libraryManager.GetLibrariesPath(); + IEnumerable libraries = libraryManager.GetLibraries(); - isScanning = true; Debug.WriteLine("&Crawler started"); foreach (Episode episode in episodes) { @@ -63,106 +59,46 @@ namespace Kyoo.Controllers libraryManager.RemoveEpisode(episode); } - foreach (string path in libraryPaths) - { - Scan(path, cancellationToken); + foreach (Library library in libraries) + await Scan(library, cancellationToken); - if(watch) - Watch(path, cancellationToken); - } - - isScanning = false; - if (watch) - while (!cancellationToken.IsCancellationRequested); + isRunning = false; Debug.WriteLine("&Crawler stopped"); - runningCrawler = null; - return null; } - private async void Scan(string folderPath, CancellationToken cancellationToken) + private async Task Scan(Library library, CancellationToken cancellationToken) { - string[] files = Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories); + IEnumerable files = new List(); + files = library.Paths.Aggregate(files, (current, path) => + current.Concat(Directory.GetFiles(path, "*", SearchOption.AllDirectories))); foreach (string file in files) { if (cancellationToken.IsCancellationRequested) return; - - if (IsVideo(file)) - { - Debug.WriteLine("&Registering episode at: " + file); - await ExtractEpisodeData(file, folderPath); - } + if (!IsVideo(file)) + continue; + await RegisterFile(file, library); } } - private void Watch(string folderPath, CancellationToken cancellationToken) + private async Task RegisterFile(string path, Library library) { - Debug.WriteLine("Folder watching not implemented yet."); - //Debug.WriteLine("&Watching " + folderPath + " for changes"); - //using (FileSystemWatcher watcher = new FileSystemWatcher()) - //{ - // watcher.Path = folderPath; - // watcher.IncludeSubdirectories = true; - // watcher.NotifyFilter = NotifyFilters.LastAccess - // | NotifyFilters.LastWrite - // | NotifyFilters.FileName - // | NotifyFilters.Size - // | NotifyFilters.DirectoryName; - - // watcher.Created += FileCreated; - // watcher.Changed += FileChanged; - // watcher.Renamed += FileRenamed; - // watcher.Deleted += FileDeleted; - - - // watcher.EnableRaisingEvents = true; - - // while (!cancellationToken.IsCancellationRequested); - //} - } - - //private void FileCreated(object sender, FileSystemEventArgs e) - //{ - // Debug.WriteLine("&File Created at " + e.FullPath); - // if (IsVideo(e.FullPath)) - // { - // Debug.WriteLine("&Created file is a video"); - // _ = TryRegisterEpisode(e.FullPath); - // } - //} - - //private void FileChanged(object sender, FileSystemEventArgs e) - //{ - // Debug.WriteLine("&File Changed at " + e.FullPath); - //} - - //private void FileRenamed(object sender, RenamedEventArgs e) - //{ - // Debug.WriteLine("&File Renamed at " + e.FullPath); - //} - - //private void FileDeleted(object sender, FileSystemEventArgs e) - //{ - // Debug.WriteLine("&File Deleted at " + e.FullPath); - //} - - private async Task ExtractEpisodeData(string episodePath, string libraryPath) - { - if (!libraryManager.IsEpisodeRegistered(episodePath)) + if (!libraryManager.IsEpisodeRegistered(path)) { - string relativePath = episodePath.Substring(libraryPath.Length); + string relativePath = path.Substring(library.Paths.Length); string patern = config.GetValue("regex"); Regex regex = new Regex(patern, RegexOptions.IgnoreCase); Match match = regex.Match(relativePath); - string showPath = Path.GetDirectoryName(episodePath); + string showPath = Path.GetDirectoryName(path); string collectionName = match.Groups["Collection"]?.Value; string showName = match.Groups["ShowTitle"].Value; bool seasonSuccess = long.TryParse(match.Groups["Season"].Value, out long seasonNumber); bool episodeSucess = long.TryParse(match.Groups["Episode"].Value, out long episodeNumber); long absoluteNumber = -1; + Debug.WriteLine("&Registering episode at: " + path); if (!seasonSuccess || !episodeSucess) { //Considering that the episode is using absolute path. @@ -182,37 +118,37 @@ namespace Kyoo.Controllers } } - Show show = await RegisterOrGetShow(collectionName, showName, showPath, libraryPath); + Show show = await RegisterOrGetShow(collectionName, showName, showPath, library); if (show != null) - await RegisterEpisode(show, seasonNumber, episodeNumber, absoluteNumber, episodePath); + await RegisterEpisode(show, seasonNumber, episodeNumber, absoluteNumber, path, library); } } - private async Task RegisterOrGetShow(string collectionName, string showTitle, string showPath, string libraryPath) + private async Task RegisterOrGetShow(string collectionName, string showTitle, string showPath, Library library) { string showProviderIDs; if (!libraryManager.IsShowRegistered(showPath, out long showID)) { - Show show = await metadataProvider.GetShowFromName(showTitle, showPath); + Show show = await metadataProvider.GetShowFromName(showTitle, showPath, library); showProviderIDs = show.ExternalIDs; showID = libraryManager.RegisterShow(show); if (showID == -1) return null; - libraryManager.RegisterInLibrary(showID, libraryPath); + libraryManager.RegisterInLibrary(showID, library); if (!string.IsNullOrEmpty(collectionName)) { if (!libraryManager.IsCollectionRegistered(Slugifier.ToSlug(collectionName), out long collectionID)) { - Collection collection = await metadataProvider.GetCollectionFromName(collectionName); + Collection collection = await metadataProvider.GetCollectionFromName(collectionName, library); collectionID = libraryManager.RegisterCollection(collection); } libraryManager.AddShowToCollection(showID, collectionID); } - List actors = await metadataProvider.GetPeople(show.ExternalIDs); + IEnumerable actors = await metadataProvider.GetPeople(show.ExternalIDs, library); libraryManager.RegisterShowPeople(showID, actors); } else @@ -221,27 +157,27 @@ namespace Kyoo.Controllers return new Show { id = showID, ExternalIDs = showProviderIDs, Title = showTitle }; } - private async Task RegisterEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath) + private async Task RegisterEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath, Library library) { long seasonID = -1; if (seasonNumber != -1) { if (!libraryManager.IsSeasonRegistered(show.id, seasonNumber, out seasonID)) { - Season season = await metadataProvider.GetSeason(show.Title, seasonNumber); + Season season = await metadataProvider.GetSeason(show.Title, seasonNumber, library); season.ShowID = show.id; seasonID = libraryManager.RegisterSeason(season); } } - Episode episode = await metadataProvider.GetEpisode(show.ExternalIDs, seasonNumber, episodeNumber, absoluteNumber, episodePath); + Episode episode = await metadataProvider.GetEpisode(show.ExternalIDs, seasonNumber, episodeNumber, absoluteNumber, episodePath, library); episode.ShowID = show.id; if (seasonID == -1) { if (!libraryManager.IsSeasonRegistered(show.id, episode.seasonNumber, out seasonID)) { - Season season = await metadataProvider.GetSeason(show.Title, episode.seasonNumber); + Season season = await metadataProvider.GetSeason(show.Title, episode.seasonNumber, library); season.ShowID = show.id; seasonID = libraryManager.RegisterSeason(season); } @@ -263,18 +199,15 @@ namespace Kyoo.Controllers libraryManager.RegisterTrack(track); } - if (episode.Path.EndsWith(".mkv")) + if (episode.Path.EndsWith(".mkv") && CountExtractedSubtitles(episode) != subcount) { - if (CountExtractedSubtitles(episode) != subcount) + Track[] subtitles = await transcoder.ExtractSubtitles(episode.Path); + if (subtitles != null) { - Track[] subtitles = await transcoder.ExtractSubtitles(episode.Path); - if (subtitles != null) + foreach (Track track in subtitles) { - foreach (Track track in subtitles) - { - track.episodeID = episode.id; - libraryManager.RegisterTrack(track); - } + track.episodeID = episode.id; + libraryManager.RegisterTrack(track); } } } diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index e55c5f5e..33a00035 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -29,7 +29,7 @@ namespace Kyoo.Controllers sqlConnection = new SQLiteConnection($"Data Source={databasePath};Version=3"); sqlConnection.Open(); - string createStatement = @"CREATE TABLE shows( + const string createStatement = @"CREATE TABLE shows( id INTEGER PRIMARY KEY UNIQUE, slug TEXT UNIQUE, title TEXT, @@ -92,7 +92,8 @@ namespace Kyoo.Controllers id INTEGER PRIMARY KEY UNIQUE, slug TEXT UNIQUE, name TEXT, - path TEXT + path TEXT, + providers TEXT ); CREATE TABLE librariesLinks( libraryID INTEGER, @@ -209,10 +210,11 @@ namespace Kyoo.Controllers public string GetShowExternalIDs(long showID) { - string query = string.Format("SELECT * FROM shows WHERE id = {0};", showID); - + string query = "SELECT * FROM shows WHERE id = $showID;"; + using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) { + cmd.Parameters.AddWithValue("$showID", showID); SQLiteDataReader reader = cmd.ExecuteReader(); if (reader.Read()) @@ -949,13 +951,14 @@ namespace Kyoo.Controllers } } - public void RegisterInLibrary(long showID, string libraryPath) + public void RegisterInLibrary(long showID, Library library) { - string query = "INSERT INTO librariesLinks (libraryID, showID) SELECT id, $showID FROM libraries WHERE libraries.path = $libraryPath;"; + string query = + "INSERT INTO librariesLinks (libraryID, showID) SELECT id, $showID FROM libraries WHERE libraries.id = $libraryID;"; using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) { - cmd.Parameters.AddWithValue("$libraryPath", libraryPath); + cmd.Parameters.AddWithValue("$libraryID", library.id); cmd.Parameters.AddWithValue("$showID", showID); cmd.ExecuteNonQuery(); } @@ -1102,21 +1105,21 @@ namespace Kyoo.Controllers } } - public void RegisterShowPeople(long showID, List people) + public void RegisterShowPeople(long showID, IEnumerable people) { if (people == null) return; string linkQuery = "INSERT INTO peopleLinks (peopleID, showID, role, type) VALUES($peopleID, $showID, $role, $type);"; - for (int i = 0; i < people.Count; i++) + foreach (People peop in people) { using (SQLiteCommand cmd = new SQLiteCommand(linkQuery, sqlConnection)) { - cmd.Parameters.AddWithValue("$peopleID", GetOrCreatePeople(people[i])); + cmd.Parameters.AddWithValue("$peopleID", GetOrCreatePeople(peop)); cmd.Parameters.AddWithValue("$showID", showID); - cmd.Parameters.AddWithValue("$role", people[i].Role); - cmd.Parameters.AddWithValue("$type", people[i].Type); + cmd.Parameters.AddWithValue("$role", peop.Role); + cmd.Parameters.AddWithValue("$type", peop.Type); cmd.ExecuteNonQuery(); } } diff --git a/Kyoo/Controllers/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs index 4cf11925..7a1635d8 100644 --- a/Kyoo/Controllers/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -1,124 +1,87 @@ -using Kyoo.Models; -using Microsoft.Extensions.Configuration; -using System; +using System; +using Kyoo.Models; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Reflection; using System.Threading.Tasks; using Kyoo.Controllers.ThumbnailsManager; +using Kyoo.Utility; namespace Kyoo.Controllers { - public class ProviderManager : IMetadataProvider + public class ProviderManager : IProviderManager { private readonly IEnumerable providers; private readonly IThumbnailsManager thumbnailsManager; - private readonly IConfiguration config; - public ProviderManager(IThumbnailsManager thumbnailsManager, IPluginManager pluginManager, IConfiguration config) + public ProviderManager(IThumbnailsManager thumbnailsManager, IPluginManager pluginManager) { this.thumbnailsManager = thumbnailsManager; - this.config = config; providers = pluginManager.GetPlugins(); } - public Show Merge(IEnumerable shows) + public async Task GetMetadata(Func> providerCall, Library library, string what) where T : IMergable, new() { - return shows.FirstOrDefault(); - } - - public Season Merge(IEnumerable seasons) - { - return seasons.FirstOrDefault(); - } - - public Episode Merge(IEnumerable episodes) - { - return episodes.FirstOrDefault(); //Should do something if the return is null; - } - - //For all the following methods, it should use all providers and merge the data. - - public Task GetCollectionFromName(string name) - { - return providers[0].GetCollectionFromName(name); - } - - public Task GetImages(Show show) - { - return providers[0].GetImages(show); - } - - public async Task GetSeason(string showName, int seasonNumber) - { - List datas = new List(); - for (int i = 0; i < providers.Count; i++) + T ret = new T(); + + foreach (IMetadataProvider provider in providers.OrderBy(provider => Array.IndexOf(library.Providers, provider.Name))) { - datas.Add(await providers[i].GetSeason(showName, seasonNumber)); + try + { + if (library.Providers.Contains(provider.Name)) + ret = ret.Merge(await providerCall(provider)); + } catch (Exception ex) { + Console.Error.WriteLine($"The provider {provider.Name} coudln't work for {what}. (Excepetion: {ex.Message}"); + } } - - return Merge(datas); + return ret; } - - public async Task GetShowByID(string id) + + public async Task> GetMetadata(Func>> providerCall, Library library, string what) { - List datas = new List(); - for (int i = 0; i < providers.Count; i++) + List ret = new List(); + + foreach (IMetadataProvider provider in providers.OrderBy(provider => Array.IndexOf(library.Providers, provider.Name))) { - datas.Add(await providers[i].GetShowByID(id)); + try + { + if (library.Providers.Contains(provider.Name)) + ret.AddRange(await providerCall(provider)); + } catch (Exception ex) { + Console.Error.WriteLine($"The provider {provider.Name} coudln't work for {what}. (Excepetion: {ex.Message}"); + } } - - return Merge(datas); + return ret; + } + + public async Task GetCollectionFromName(string name, Library library) + { + return await GetMetadata(provider => provider.GetCollectionFromName(name), library, $"the collection {name}"); } - public async Task GetShowFromName(string showName, string showPath) + public async Task GetShowFromName(string showName, string showPath, Library library) { - List datas = new List(); - for (int i = 0; i < providers.Count; i++) - { - datas.Add(await providers[i].GetShowFromName(showName, showPath)); - } - - Show show = Merge(datas); - return await thumbnailsManager.Validate(show); + Show show = await GetMetadata(provider => provider.GetShowFromName(showName, showPath), library, $"the show {showName}"); + await thumbnailsManager.Validate(show); + return show; } - public async Task GetSeason(string showName, long seasonNumber) + public async Task GetSeason(string showName, long seasonNumber, Library library) { - List datas = new List(); - for (int i = 0; i < providers.Count; i++) - { - datas.Add(await providers[i].GetSeason(showName, seasonNumber)); - } - - return Merge(datas); + return await GetMetadata(provider => provider.GetSeason(showName, seasonNumber), library, $"the season ${seasonNumber} of {showName}"); } - public Task GetSeasonImage(string showName, long seasonNumber) + public async Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath, Library library) { - //Should select the best provider for this show. - - return providers[0].GetSeasonImage(showName, seasonNumber); + Episode episode = await GetMetadata(provider => provider.GetEpisode(externalIDs, seasonNumber, episodeNumber, absoluteNumber, episodePath), library, $"the episode at {episodePath}"); + await thumbnailsManager.Validate(episode); + return episode; } - public async Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath) + public async Task> GetPeople(string showExternalIDs, Library library) { - List datas = new List(); - for (int i = 0; i < providers.Count; i++) - { - datas.Add(await providers[i].GetEpisode(externalIDs, seasonNumber, episodeNumber, absoluteNumber, episodePath)); - } - - Episode episode = Merge(datas); - episode.Path = episodePath; - return await thumbnailsManager.Validate(episode); - } - - public async Task> GetPeople(string id) - { - List actors = await providers[0].GetPeople(id); - return await thumbnailsManager.Validate(actors); + IEnumerable people = await GetMetadata(provider => provider.GetPeople(showExternalIDs), library, $"unknown data"); + people = await thumbnailsManager.Validate(people); + return people; } } } diff --git a/Kyoo/Controllers/ThumbnailsManager.cs b/Kyoo/Controllers/ThumbnailsManager.cs index 3e0a468c..a3d25b65 100644 --- a/Kyoo/Controllers/ThumbnailsManager.cs +++ b/Kyoo/Controllers/ThumbnailsManager.cs @@ -67,20 +67,20 @@ namespace Kyoo.Controllers.ThumbnailsManager return show; } - public async Task> Validate(List people) + public async Task> Validate(IEnumerable people) { - for (int i = 0; i < people?.Count; i++) + foreach (People peop in people) { string root = config.GetValue("peoplePath"); Directory.CreateDirectory(root); - string localThumb = root + "/" + people[i].slug + ".jpg"; - if (people[i].imgPrimary != null && !File.Exists(localThumb)) + string localThumb = root + "/" + peop.slug + ".jpg"; + if (peop.imgPrimary != null && !File.Exists(localThumb)) { try { using WebClient client = new WebClient(); - await client.DownloadFileTaskAsync(new Uri(people[i].imgPrimary), localThumb); + await client.DownloadFileTaskAsync(new Uri(peop.imgPrimary), localThumb); } catch (WebException) { diff --git a/Kyoo/HtmlAPI/AdminController.cs b/Kyoo/HtmlAPI/AdminController.cs index fdd006c6..2ac4ce86 100644 --- a/Kyoo/HtmlAPI/AdminController.cs +++ b/Kyoo/HtmlAPI/AdminController.cs @@ -18,10 +18,10 @@ namespace Kyoo.Controllers this.crawler = crawler; } - [HttpGet("scan/{watch}")] - public IActionResult ScanLibrary(bool watch) + [HttpGet("scan")] + public IActionResult ScanLibrary() { - crawler.Start(watch); + crawler.Start(); return Ok("Scanning"); } } diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index f2b74b67..b7fedf32 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -35,7 +35,7 @@ namespace Kyoo services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. From 523c5a652e1768419fdd63cd0b29c01e777ba6b5 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 19 Jan 2020 01:05:55 +0100 Subject: [PATCH 05/11] Adding a nuget package for Kyoo.Common and adding an http client factory in the DI --- Kyoo.Common/Kyoo.Common.csproj | 9 +++++++++ Kyoo/Startup.cs | 1 + 2 files changed, 10 insertions(+) diff --git a/Kyoo.Common/Kyoo.Common.csproj b/Kyoo.Common/Kyoo.Common.csproj index e87868c0..9f34812e 100644 --- a/Kyoo.Common/Kyoo.Common.csproj +++ b/Kyoo.Common/Kyoo.Common.csproj @@ -2,6 +2,15 @@ netcoreapp3.0 + true + Kyoo.Common + Anonymus Raccoon + Base package to create plugins for Kyoo. + https://github.com/AnonymusRaccoon/Kyoo + https://github.com/AnonymusRaccoon/Kyoo + SDG + GPL-3.0-or-later + true diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index b7fedf32..3ac22f6f 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -30,6 +30,7 @@ namespace Kyoo }); services.AddControllers().AddNewtonsoftJson(); + services.AddHttpClient(); services.AddSingleton(); services.AddSingleton(); From c0ab6f898a3bf4ac6e4fe7d8584753663aa9e03e Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 19 Jan 2020 01:15:03 +0100 Subject: [PATCH 06/11] Removing paths parameters from the metadataprovider --- Kyoo.Common/Controllers/IMetadataProvider.cs | 4 ++-- Kyoo.Common/Controllers/IProviderManager.cs | 4 ++-- Kyoo/Controllers/Crawler.cs | 6 ++++-- Kyoo/Controllers/ProviderManager.cs | 8 ++++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Kyoo.Common/Controllers/IMetadataProvider.cs b/Kyoo.Common/Controllers/IMetadataProvider.cs index 878129bb..9c144254 100644 --- a/Kyoo.Common/Controllers/IMetadataProvider.cs +++ b/Kyoo.Common/Controllers/IMetadataProvider.cs @@ -13,13 +13,13 @@ namespace Kyoo.Controllers //For the show Task GetShowByID(string id); - Task GetShowFromName(string showName, string showPath); + Task GetShowFromName(string showName); Task> GetPeople(string id); //For the seasons Task GetSeason(string showName, long seasonNumber); //For the episodes - Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath); + Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber); } } diff --git a/Kyoo.Common/Controllers/IProviderManager.cs b/Kyoo.Common/Controllers/IProviderManager.cs index 3f775013..bbb02a60 100644 --- a/Kyoo.Common/Controllers/IProviderManager.cs +++ b/Kyoo.Common/Controllers/IProviderManager.cs @@ -7,9 +7,9 @@ namespace Kyoo.Controllers public interface IProviderManager { Task GetCollectionFromName(string name, Library library); - Task GetShowFromName(string showName, string showPath, Library library); + Task GetShowFromName(string showName, Library library); Task GetSeason(string showName, long seasonNumber, Library library); - Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath, Library library); + Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, Library library); Task> GetPeople(string showExternalIDs, Library library); } } \ No newline at end of file diff --git a/Kyoo/Controllers/Crawler.cs b/Kyoo/Controllers/Crawler.cs index a2591c45..80e25dac 100644 --- a/Kyoo/Controllers/Crawler.cs +++ b/Kyoo/Controllers/Crawler.cs @@ -130,7 +130,8 @@ namespace Kyoo.Controllers if (!libraryManager.IsShowRegistered(showPath, out long showID)) { - Show show = await metadataProvider.GetShowFromName(showTitle, showPath, library); + Show show = await metadataProvider.GetShowFromName(showTitle, library); + show.Path = showPath; showProviderIDs = show.ExternalIDs; showID = libraryManager.RegisterShow(show); @@ -170,8 +171,9 @@ namespace Kyoo.Controllers } } - Episode episode = await metadataProvider.GetEpisode(show.ExternalIDs, seasonNumber, episodeNumber, absoluteNumber, episodePath, library); + Episode episode = await metadataProvider.GetEpisode(show.ExternalIDs, seasonNumber, episodeNumber, absoluteNumber, library); episode.ShowID = show.id; + episode.Path = episodePath; if (seasonID == -1) { diff --git a/Kyoo/Controllers/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs index 7a1635d8..f1b2b542 100644 --- a/Kyoo/Controllers/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -58,9 +58,9 @@ namespace Kyoo.Controllers return await GetMetadata(provider => provider.GetCollectionFromName(name), library, $"the collection {name}"); } - public async Task GetShowFromName(string showName, string showPath, Library library) + public async Task GetShowFromName(string showName, Library library) { - Show show = await GetMetadata(provider => provider.GetShowFromName(showName, showPath), library, $"the show {showName}"); + Show show = await GetMetadata(provider => provider.GetShowFromName(showName), library, $"the show {showName}"); await thumbnailsManager.Validate(show); return show; } @@ -70,9 +70,9 @@ namespace Kyoo.Controllers return await GetMetadata(provider => provider.GetSeason(showName, seasonNumber), library, $"the season ${seasonNumber} of {showName}"); } - public async Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath, Library library) + public async Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, Library library) { - Episode episode = await GetMetadata(provider => provider.GetEpisode(externalIDs, seasonNumber, episodeNumber, absoluteNumber, episodePath), library, $"the episode at {episodePath}"); + Episode episode = await GetMetadata(provider => provider.GetEpisode(externalIDs, seasonNumber, episodeNumber, absoluteNumber), library, $"an episode"); await thumbnailsManager.Validate(episode); return episode; } From 899adb2b9dcc2ae5cb60f9aa745e0795ad9f7b2a Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 21 Jan 2020 23:20:18 +0100 Subject: [PATCH 07/11] Refactorying a bit --- Kyoo.Common/Kyoo.Common.csproj | 1 + Kyoo.Common/Models/Collection.cs | 1 - Kyoo.Common/Models/Episode.cs | 1 - Kyoo.Common/Models/People.cs | 3 +- Kyoo.Common/Models/Season.cs | 4 +- Kyoo.Common/Models/Show.cs | 12 +++++- Kyoo.Common/Utility.cs | 62 +++++++++++++++++++++++++++++ Kyoo.Common/Utility/IMergable.cs | 9 ----- Kyoo.Common/Utility/ImageHelper.cs | 28 ------------- Kyoo.Common/Utility/Slugifier.cs | 34 ---------------- Kyoo/Controllers/Crawler.cs | 3 +- Kyoo/Controllers/ProviderManager.cs | 1 - 12 files changed, 76 insertions(+), 83 deletions(-) create mode 100644 Kyoo.Common/Utility.cs delete mode 100644 Kyoo.Common/Utility/IMergable.cs delete mode 100644 Kyoo.Common/Utility/ImageHelper.cs delete mode 100644 Kyoo.Common/Utility/Slugifier.cs diff --git a/Kyoo.Common/Kyoo.Common.csproj b/Kyoo.Common/Kyoo.Common.csproj index 9f34812e..ab4dc7c5 100644 --- a/Kyoo.Common/Kyoo.Common.csproj +++ b/Kyoo.Common/Kyoo.Common.csproj @@ -11,6 +11,7 @@ SDG GPL-3.0-or-later true + 1.0.2 diff --git a/Kyoo.Common/Models/Collection.cs b/Kyoo.Common/Models/Collection.cs index 81ade2a7..fb1c6d59 100644 --- a/Kyoo.Common/Models/Collection.cs +++ b/Kyoo.Common/Models/Collection.cs @@ -2,7 +2,6 @@ using Newtonsoft.Json; using System.Collections.Generic; using System.Linq; -using Kyoo.Utility; namespace Kyoo.Models { diff --git a/Kyoo.Common/Models/Episode.cs b/Kyoo.Common/Models/Episode.cs index c7d53dbc..ba75b521 100644 --- a/Kyoo.Common/Models/Episode.cs +++ b/Kyoo.Common/Models/Episode.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json; using System; -using Kyoo.Utility; namespace Kyoo.Models { diff --git a/Kyoo.Common/Models/People.cs b/Kyoo.Common/Models/People.cs index abb44c53..0626e75e 100644 --- a/Kyoo.Common/Models/People.cs +++ b/Kyoo.Common/Models/People.cs @@ -1,5 +1,4 @@ -using Kyoo.Utility; -using Newtonsoft.Json; +using Newtonsoft.Json; namespace Kyoo.Models { diff --git a/Kyoo.Common/Models/Season.cs b/Kyoo.Common/Models/Season.cs index 6c9133f1..bc149ee3 100644 --- a/Kyoo.Common/Models/Season.cs +++ b/Kyoo.Common/Models/Season.cs @@ -1,6 +1,4 @@ -using System.Linq; -using Kyoo.Utility; -using Newtonsoft.Json; +using Newtonsoft.Json; namespace Kyoo.Models { diff --git a/Kyoo.Common/Models/Show.cs b/Kyoo.Common/Models/Show.cs index bd179283..34d3016d 100644 --- a/Kyoo.Common/Models/Show.cs +++ b/Kyoo.Common/Models/Show.cs @@ -1,8 +1,8 @@ -using Kyoo.Controllers; +using System; +using Kyoo.Controllers; using Newtonsoft.Json; using System.Collections.Generic; using System.Linq; -using Kyoo.Utility; namespace Kyoo.Models { @@ -127,6 +127,14 @@ namespace Kyoo.Models reader["externalIDs"] as string); } + public string GetID(string provider) + { + if (ExternalIDs?.Contains(provider) != true) + return null; + int startIndex = ExternalIDs.IndexOf(provider, StringComparison.Ordinal) + provider.Length + 1; //The + 1 is for the '=' + return ExternalIDs.Substring(startIndex, ExternalIDs.IndexOf('|', startIndex) - startIndex); + } + public Show Set(string slug, string path) { Slug = slug; diff --git a/Kyoo.Common/Utility.cs b/Kyoo.Common/Utility.cs new file mode 100644 index 00000000..e161e132 --- /dev/null +++ b/Kyoo.Common/Utility.cs @@ -0,0 +1,62 @@ +using System.Text.RegularExpressions; +using Kyoo.Models; + +namespace Kyoo +{ + public interface IMergable + { + public T Merge(T other); + } + + public static class Utility + { + public static string ToSlug(string name) + { + if (name == null) + return null; + + //First to lower case + name = name.ToLowerInvariant(); + + //Remove all accents + //var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(showTitle); + //showTitle = Encoding.ASCII.GetString(bytes); + + //Replace spaces + name = Regex.Replace(name, @"\s", "-", RegexOptions.Compiled); + + //Remove invalid chars + name = Regex.Replace(name, @"[^\w\s\p{Pd}]", "", RegexOptions.Compiled); + + //Trim dashes from end + name = name.Trim('-', '_'); + + //Replace double occurences of - or \_ + name = Regex.Replace(name, @"([-_]){2,}", "$1", RegexOptions.Compiled); + + return name; + } + + + public static void SetImage(Show show, string imgUrl, ImageType type) + { + switch(type) + { + case ImageType.Poster: + show.ImgPrimary = imgUrl; + break; + case ImageType.Thumbnail: + show.ImgThumb = imgUrl; + break; + case ImageType.Logo: + show.ImgLogo = imgUrl; + break; + case ImageType.Background: + show.ImgBackdrop = imgUrl; + break; + default: + break; + } + } + } +} \ No newline at end of file diff --git a/Kyoo.Common/Utility/IMergable.cs b/Kyoo.Common/Utility/IMergable.cs deleted file mode 100644 index 3c56420b..00000000 --- a/Kyoo.Common/Utility/IMergable.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace Kyoo.Utility -{ - public interface IMergable - { - public T Merge(T other); - } -} \ No newline at end of file diff --git a/Kyoo.Common/Utility/ImageHelper.cs b/Kyoo.Common/Utility/ImageHelper.cs deleted file mode 100644 index d75bd30d..00000000 --- a/Kyoo.Common/Utility/ImageHelper.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Kyoo.Models; - -namespace Kyoo.Controllers.Utility -{ - public static class ImageHelper - { - public static void SetImage(Show show, string imgUrl, ImageType type) - { - switch(type) - { - case ImageType.Poster: - show.ImgPrimary = imgUrl; - break; - case ImageType.Thumbnail: - show.ImgThumb = imgUrl; - break; - case ImageType.Logo: - show.ImgLogo = imgUrl; - break; - case ImageType.Background: - show.ImgBackdrop = imgUrl; - break; - default: - break; - } - } - } -} \ No newline at end of file diff --git a/Kyoo.Common/Utility/Slugifier.cs b/Kyoo.Common/Utility/Slugifier.cs deleted file mode 100644 index 22cbc4f3..00000000 --- a/Kyoo.Common/Utility/Slugifier.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Text.RegularExpressions; - -namespace Kyoo.Controllers.Utility -{ - public class Slugifier - { - public static string ToSlug(string showTitle) - { - if (showTitle == null) - return null; - - //First to lower case - showTitle = showTitle.ToLowerInvariant(); - - //Remove all accents - //var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(showTitle); - //showTitle = Encoding.ASCII.GetString(bytes); - - //Replace spaces - showTitle = Regex.Replace(showTitle, @"\s", "-", RegexOptions.Compiled); - - //Remove invalid chars - showTitle = Regex.Replace(showTitle, @"[^\w\s\p{Pd}]", "", RegexOptions.Compiled); - - //Trim dashes from end - showTitle = showTitle.Trim('-', '_'); - - //Replace double occurences of - or \_ - showTitle = Regex.Replace(showTitle, @"([-_]){2,}", "$1", RegexOptions.Compiled); - - return showTitle; - } - } -} diff --git a/Kyoo/Controllers/Crawler.cs b/Kyoo/Controllers/Crawler.cs index 80e25dac..d67ba985 100644 --- a/Kyoo/Controllers/Crawler.cs +++ b/Kyoo/Controllers/Crawler.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using Kyoo.Controllers.Utility; using Kyoo.Models.Watch; namespace Kyoo.Controllers @@ -141,7 +140,7 @@ namespace Kyoo.Controllers libraryManager.RegisterInLibrary(showID, library); if (!string.IsNullOrEmpty(collectionName)) { - if (!libraryManager.IsCollectionRegistered(Slugifier.ToSlug(collectionName), out long collectionID)) + if (!libraryManager.IsCollectionRegistered(Utility.ToSlug(collectionName), out long collectionID)) { Collection collection = await metadataProvider.GetCollectionFromName(collectionName, library); collectionID = libraryManager.RegisterCollection(collection); diff --git a/Kyoo/Controllers/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs index f1b2b542..8aeba1cf 100644 --- a/Kyoo/Controllers/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Kyoo.Controllers.ThumbnailsManager; -using Kyoo.Utility; namespace Kyoo.Controllers { From 3e9da31ac58f98498868b6be91dddf2a82dd33eb Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 25 Jan 2020 00:14:09 +0100 Subject: [PATCH 08/11] Making the plugin manager start on app startup --- Kyoo.Common/Controllers/IMetadataProvider.cs | 4 ++-- Kyoo.Common/Controllers/IProviderManager.cs | 4 ++-- Kyoo.Common/Kyoo.Common.csproj | 4 ++-- Kyoo.Common/Models/Show.cs | 4 +++- Kyoo/Controllers/Crawler.cs | 4 ++-- Kyoo/Controllers/PluginManager.cs | 1 - Kyoo/Controllers/ProviderManager.cs | 8 ++++---- Kyoo/Program.cs | 17 +++++++++++++++-- Kyoo/Startup.cs | 3 ++- Kyoo/appsettings.json | 2 +- 10 files changed, 33 insertions(+), 18 deletions(-) diff --git a/Kyoo.Common/Controllers/IMetadataProvider.cs b/Kyoo.Common/Controllers/IMetadataProvider.cs index 9c144254..d7ce5a52 100644 --- a/Kyoo.Common/Controllers/IMetadataProvider.cs +++ b/Kyoo.Common/Controllers/IMetadataProvider.cs @@ -14,12 +14,12 @@ namespace Kyoo.Controllers //For the show Task GetShowByID(string id); Task GetShowFromName(string showName); - Task> GetPeople(string id); + Task> GetPeople(Show show); //For the seasons Task GetSeason(string showName, long seasonNumber); //For the episodes - Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber); + Task GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber); } } diff --git a/Kyoo.Common/Controllers/IProviderManager.cs b/Kyoo.Common/Controllers/IProviderManager.cs index bbb02a60..8f51b8a1 100644 --- a/Kyoo.Common/Controllers/IProviderManager.cs +++ b/Kyoo.Common/Controllers/IProviderManager.cs @@ -9,7 +9,7 @@ namespace Kyoo.Controllers Task GetCollectionFromName(string name, Library library); Task GetShowFromName(string showName, Library library); Task GetSeason(string showName, long seasonNumber, Library library); - Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, Library library); - Task> GetPeople(string showExternalIDs, Library library); + Task GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber, Library library); + Task> GetPeople(Show show, Library library); } } \ No newline at end of file diff --git a/Kyoo.Common/Kyoo.Common.csproj b/Kyoo.Common/Kyoo.Common.csproj index ab4dc7c5..1cc85725 100644 --- a/Kyoo.Common/Kyoo.Common.csproj +++ b/Kyoo.Common/Kyoo.Common.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.0 @@ -11,7 +11,7 @@ SDG GPL-3.0-or-later true - 1.0.2 + 1.0.5 diff --git a/Kyoo.Common/Models/Show.cs b/Kyoo.Common/Models/Show.cs index 34d3016d..c84f3595 100644 --- a/Kyoo.Common/Models/Show.cs +++ b/Kyoo.Common/Models/Show.cs @@ -132,9 +132,11 @@ namespace Kyoo.Models if (ExternalIDs?.Contains(provider) != true) return null; int startIndex = ExternalIDs.IndexOf(provider, StringComparison.Ordinal) + provider.Length + 1; //The + 1 is for the '=' + if (ExternalIDs.IndexOf('|', startIndex) == -1) + return ExternalIDs.Substring(startIndex); return ExternalIDs.Substring(startIndex, ExternalIDs.IndexOf('|', startIndex) - startIndex); } - + public Show Set(string slug, string path) { Slug = slug; diff --git a/Kyoo/Controllers/Crawler.cs b/Kyoo/Controllers/Crawler.cs index d67ba985..95353e3a 100644 --- a/Kyoo/Controllers/Crawler.cs +++ b/Kyoo/Controllers/Crawler.cs @@ -148,7 +148,7 @@ namespace Kyoo.Controllers libraryManager.AddShowToCollection(showID, collectionID); } - IEnumerable actors = await metadataProvider.GetPeople(show.ExternalIDs, library); + IEnumerable actors = await metadataProvider.GetPeople(show, library); libraryManager.RegisterShowPeople(showID, actors); } else @@ -170,7 +170,7 @@ namespace Kyoo.Controllers } } - Episode episode = await metadataProvider.GetEpisode(show.ExternalIDs, seasonNumber, episodeNumber, absoluteNumber, library); + Episode episode = await metadataProvider.GetEpisode(show, seasonNumber, episodeNumber, absoluteNumber, library); episode.ShowID = show.id; episode.Path = episodePath; diff --git a/Kyoo/Controllers/PluginManager.cs b/Kyoo/Controllers/PluginManager.cs index 78d2444d..4bd26fec 100644 --- a/Kyoo/Controllers/PluginManager.cs +++ b/Kyoo/Controllers/PluginManager.cs @@ -19,7 +19,6 @@ namespace Kyoo.Controllers { this.provider = provider; this.config = config; - ReloadPlugins(); } public T GetPlugin(string name) diff --git a/Kyoo/Controllers/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs index 8aeba1cf..28ef23a5 100644 --- a/Kyoo/Controllers/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -69,16 +69,16 @@ namespace Kyoo.Controllers return await GetMetadata(provider => provider.GetSeason(showName, seasonNumber), library, $"the season ${seasonNumber} of {showName}"); } - public async Task GetEpisode(string externalIDs, long seasonNumber, long episodeNumber, long absoluteNumber, Library library) + public async Task GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber, Library library) { - Episode episode = await GetMetadata(provider => provider.GetEpisode(externalIDs, seasonNumber, episodeNumber, absoluteNumber), library, $"an episode"); + Episode episode = await GetMetadata(provider => provider.GetEpisode(show, seasonNumber, episodeNumber, absoluteNumber), library, $"an episode"); await thumbnailsManager.Validate(episode); return episode; } - public async Task> GetPeople(string showExternalIDs, Library library) + public async Task> GetPeople(Show show, Library library) { - IEnumerable people = await GetMetadata(provider => provider.GetPeople(showExternalIDs), library, $"unknown data"); + IEnumerable people = await GetMetadata(provider => provider.GetPeople(show), library, $"unknown data"); people = await thumbnailsManager.Validate(people); return people; } diff --git a/Kyoo/Program.cs b/Kyoo/Program.cs index 06c7b1e2..925d7334 100644 --- a/Kyoo/Program.cs +++ b/Kyoo/Program.cs @@ -1,14 +1,27 @@ +using System.Threading.Tasks; +using Kyoo.Controllers; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Kyoo { public class Program { - public static void Main(string[] args) + public static async Task Main(string[] args) { - CreateWebHostBuilder(args).Build().Run(); + IWebHost host = CreateWebHostBuilder(args).Build(); + + using (IServiceScope serviceScope = host.Services.CreateScope()) + { + IPluginManager pluginManager = serviceScope.ServiceProvider.GetService(); + pluginManager.ReloadPlugins(); + + ICrawler crawler = serviceScope.ServiceProvider.GetService(); + crawler.Start(); + } + await host.RunAsync(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index 3ac22f6f..a60f4445 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -32,11 +32,12 @@ namespace Kyoo services.AddControllers().AddNewtonsoftJson(); services.AddHttpClient(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/Kyoo/appsettings.json b/Kyoo/appsettings.json index af27c3fe..7cd9243d 100644 --- a/Kyoo/appsettings.json +++ b/Kyoo/appsettings.json @@ -12,7 +12,7 @@ "transmuxTempPath": "/tmp/cached/kyoo/transmux", "transcodeTempPath": "/tmp/cached/kyoo/transcode", "peoplePath": "/tmp/people", - "plugins": "/tmp/plugins", + "plugins": "plugins/", "regex": "^(\\/(?.+?))?\\/.*\\/(?.+?) S(?\\d+)E(?\\d+)", "absoluteRegex": ".*\\/(?.+?) (?\\d+)" } From 8b8e89d123657e3423339c76b1aa6226c44587d1 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 25 Jan 2020 02:04:20 +0100 Subject: [PATCH 09/11] Adding default values when no data providers can Work. Cleaning up everything --- Kyoo.Common/Controllers/IMetadataProvider.cs | 2 +- Kyoo.Common/Controllers/IProviderManager.cs | 2 +- Kyoo.Common/Models/Collection.cs | 14 +-- Kyoo.Common/Models/Episode.cs | 52 +++++---- Kyoo.Common/Models/Genre.cs | 4 +- Kyoo.Common/Models/Library.cs | 4 +- Kyoo.Common/Models/People.cs | 40 +++---- Kyoo.Common/Models/SearchResult.cs | 12 +- Kyoo.Common/Models/Season.cs | 22 ++-- Kyoo.Common/Models/Show.cs | 38 +++---- Kyoo.Common/Models/Studio.cs | 4 +- Kyoo.Common/Models/Track.cs | 2 +- Kyoo.Common/Models/WatchItem.cs | 56 +++++----- Kyoo/Controllers/Crawler.cs | 111 ++++++++++--------- Kyoo/Controllers/LibraryManager.cs | 44 ++++---- Kyoo/Controllers/PluginManager.cs | 18 ++- Kyoo/Controllers/ProviderManager.cs | 4 +- Kyoo/Controllers/ThumbnailsManager.cs | 48 ++++---- Kyoo/HtmlAPI/LibrariesController.cs | 2 +- Kyoo/HtmlAPI/PeopleController.cs | 6 +- Kyoo/HtmlAPI/SearchController.cs | 12 +- Kyoo/HtmlAPI/SubtitleController.cs | 8 +- Kyoo/Startup.cs | 2 +- 23 files changed, 264 insertions(+), 243 deletions(-) diff --git a/Kyoo.Common/Controllers/IMetadataProvider.cs b/Kyoo.Common/Controllers/IMetadataProvider.cs index d7ce5a52..0813418c 100644 --- a/Kyoo.Common/Controllers/IMetadataProvider.cs +++ b/Kyoo.Common/Controllers/IMetadataProvider.cs @@ -17,7 +17,7 @@ namespace Kyoo.Controllers Task> GetPeople(Show show); //For the seasons - Task GetSeason(string showName, long seasonNumber); + Task GetSeason(Show show, long seasonNumber); //For the episodes Task GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber); diff --git a/Kyoo.Common/Controllers/IProviderManager.cs b/Kyoo.Common/Controllers/IProviderManager.cs index 8f51b8a1..0da49676 100644 --- a/Kyoo.Common/Controllers/IProviderManager.cs +++ b/Kyoo.Common/Controllers/IProviderManager.cs @@ -8,7 +8,7 @@ namespace Kyoo.Controllers { Task GetCollectionFromName(string name, Library library); Task GetShowFromName(string showName, Library library); - Task GetSeason(string showName, long seasonNumber, Library library); + Task GetSeason(Show show, long seasonNumber, Library library); Task GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber, Library library); Task> GetPeople(Show show, Library library); } diff --git a/Kyoo.Common/Models/Collection.cs b/Kyoo.Common/Models/Collection.cs index fb1c6d59..c2e7a3b1 100644 --- a/Kyoo.Common/Models/Collection.cs +++ b/Kyoo.Common/Models/Collection.cs @@ -8,7 +8,7 @@ namespace Kyoo.Models public class Collection : IMergable { - [JsonIgnore] public long id = -1; + [JsonIgnore] public long ID = -1; public string Slug; public string Name; public string Poster; @@ -16,13 +16,11 @@ namespace Kyoo.Models [JsonIgnore] public string ImgPrimary; public IEnumerable Shows; - public Collection() - { - } + public Collection() { } public Collection(long id, string slug, string name, string overview, string imgPrimary) { - this.id = id; + ID = id; Slug = slug; Name = name; Overview = overview; @@ -47,14 +45,14 @@ namespace Kyoo.Models public Collection SetShows(ILibraryManager libraryManager) { - Shows = libraryManager.GetShowsInCollection(id); + Shows = libraryManager.GetShowsInCollection(ID); return this; } public Collection Merge(Collection collection) { - if (id == -1) - id = collection.id; + if (ID == -1) + ID = collection.ID; if (Slug == null) Slug = collection.Slug; if (Name == null) diff --git a/Kyoo.Common/Models/Episode.cs b/Kyoo.Common/Models/Episode.cs index ba75b521..f650ded4 100644 --- a/Kyoo.Common/Models/Episode.cs +++ b/Kyoo.Common/Models/Episode.cs @@ -5,13 +5,13 @@ namespace Kyoo.Models { public class Episode : IMergable { - [JsonIgnore] public long id; + [JsonIgnore] public long ID; [JsonIgnore] public long ShowID; [JsonIgnore] public long SeasonID; - public long seasonNumber; - public long episodeNumber; - public long absoluteNumber; + public long SeasonNumber; + public long EpisodeNumber; + public long AbsoluteNumber; [JsonIgnore] public string Path; public string Title; public string Overview; @@ -27,16 +27,24 @@ namespace Kyoo.Models public string Thumb; //Used in the API response only - public Episode() { } + public Episode() + { + ID = -1; + ShowID = -1; + SeasonID = -1; + SeasonNumber = -1; + EpisodeNumber = -1; + AbsoluteNumber = -1; + } public Episode(long seasonNumber, long episodeNumber, long absoluteNumber, string title, string overview, DateTime? releaseDate, long runtime, string imgPrimary, string externalIDs) { - id = -1; + ID = -1; ShowID = -1; SeasonID = -1; - this.seasonNumber = seasonNumber; - this.episodeNumber = episodeNumber; - this.absoluteNumber = absoluteNumber; + SeasonNumber = seasonNumber; + EpisodeNumber = episodeNumber; + AbsoluteNumber = absoluteNumber; Title = title; Overview = overview; ReleaseDate = releaseDate; @@ -47,12 +55,12 @@ namespace Kyoo.Models public Episode(long id, long showID, long seasonID, long seasonNumber, long episodeNumber, long absoluteNumber, string path, string title, string overview, DateTime? releaseDate, long runtime, string imgPrimary, string externalIDs) { - this.id = id; + ID = id; ShowID = showID; SeasonID = seasonID; - this.seasonNumber = seasonNumber; - this.episodeNumber = episodeNumber; - this.absoluteNumber = absoluteNumber; + SeasonNumber = seasonNumber; + EpisodeNumber = episodeNumber; + AbsoluteNumber = absoluteNumber; Path = path; Title = title; Overview = overview; @@ -82,7 +90,7 @@ namespace Kyoo.Models public Episode SetThumb(string showSlug) { - Link = GetSlug(showSlug, seasonNumber, episodeNumber); + Link = GetSlug(showSlug, SeasonNumber, EpisodeNumber); Thumb = "thumb/" + Link; return this; } @@ -100,18 +108,18 @@ namespace Kyoo.Models public Episode Merge(Episode other) { - if (id == -1) - id = other.id; + if (ID == -1) + ID = other.ID; if (ShowID == -1) ShowID = other.ShowID; if (SeasonID == -1) SeasonID = other.SeasonID; - if (seasonNumber == -1) - seasonNumber = other.seasonNumber; - if (episodeNumber == -1) - episodeNumber = other.episodeNumber; - if (absoluteNumber == -1) - absoluteNumber = other.absoluteNumber; + if (SeasonNumber == -1) + SeasonNumber = other.SeasonNumber; + if (EpisodeNumber == -1) + EpisodeNumber = other.EpisodeNumber; + if (AbsoluteNumber == -1) + AbsoluteNumber = other.AbsoluteNumber; if (Path == null) Path = other.Path; if (Title == null) diff --git a/Kyoo.Common/Models/Genre.cs b/Kyoo.Common/Models/Genre.cs index 93ff9d8f..233c9f01 100644 --- a/Kyoo.Common/Models/Genre.cs +++ b/Kyoo.Common/Models/Genre.cs @@ -4,7 +4,7 @@ namespace Kyoo.Models { public class Genre { - [JsonIgnore] public readonly long id; + [JsonIgnore] public readonly long ID; public string Slug; public string Name; @@ -16,7 +16,7 @@ namespace Kyoo.Models public Genre(long id, string slug, string name) { - this.id = id; + this.ID = id; Slug = slug; Name = name; } diff --git a/Kyoo.Common/Models/Library.cs b/Kyoo.Common/Models/Library.cs index c0a0fe8b..6b4db9af 100644 --- a/Kyoo.Common/Models/Library.cs +++ b/Kyoo.Common/Models/Library.cs @@ -4,7 +4,7 @@ namespace Kyoo.Models { public class Library { - [JsonIgnore] public readonly long id; + [JsonIgnore] public readonly long ID; public string Slug; public string Name; public string[] Paths; @@ -12,7 +12,7 @@ namespace Kyoo.Models public Library(long id, string slug, string name, string[] paths, string[] providers) { - this.id = id; + ID = id; Slug = slug; Name = name; Paths = paths; diff --git a/Kyoo.Common/Models/People.cs b/Kyoo.Common/Models/People.cs index 0626e75e..0738c577 100644 --- a/Kyoo.Common/Models/People.cs +++ b/Kyoo.Common/Models/People.cs @@ -4,33 +4,35 @@ namespace Kyoo.Models { public class People : IMergable { - [JsonIgnore] public long id; - public string slug; + [JsonIgnore] public long ID = -1; + public string Slug; public string Name; public string Role; //Dynamic data not stored as it in the database public string Type; //Dynamic data not stored as it in the database ---- Null for now - [JsonIgnore] public string imgPrimary; + [JsonIgnore] public string ImgPrimary; - public string externalIDs; + public string ExternalIDs; + + public People() {} public People(long id, string slug, string name, string imgPrimary, string externalIDs) { - this.id = id; - this.slug = slug; + ID = id; + Slug = slug; Name = name; - this.imgPrimary = imgPrimary; - this.externalIDs = externalIDs; + ImgPrimary = imgPrimary; + ExternalIDs = externalIDs; } public People(long id, string slug, string name, string role, string type, string imgPrimary, string externalIDs) { - this.id = id; - this.slug = slug; + ID = id; + Slug = slug; Name = name; Role = role; Type = type; - this.imgPrimary = imgPrimary; - this.externalIDs = externalIDs; + ImgPrimary = imgPrimary; + ExternalIDs = externalIDs; } public static People FromReader(System.Data.SQLite.SQLiteDataReader reader) @@ -55,19 +57,19 @@ namespace Kyoo.Models public People Merge(People other) { - if (id == -1) - id = other.id; - if (slug == null) - slug = other.slug; + if (ID == -1) + ID = other.ID; + if (Slug == null) + Slug = other.Slug; if (Name == null) Name = other.Name; if (Role == null) Role = other.Role; if (Type == null) Type = other.Type; - if (imgPrimary == null) - imgPrimary = other.imgPrimary; - externalIDs += '|' + other.externalIDs; + if (ImgPrimary == null) + ImgPrimary = other.ImgPrimary; + ExternalIDs += '|' + other.ExternalIDs; return this; } } diff --git a/Kyoo.Common/Models/SearchResult.cs b/Kyoo.Common/Models/SearchResult.cs index 5462c904..306814b8 100644 --- a/Kyoo.Common/Models/SearchResult.cs +++ b/Kyoo.Common/Models/SearchResult.cs @@ -4,11 +4,11 @@ namespace Kyoo.Models { public class SearchResult { - public string query; - public IEnumerable shows; - public IEnumerable episodes; - public IEnumerable people; - public IEnumerable genres; - public IEnumerable studios; + public string Query; + public IEnumerable Shows; + public IEnumerable Episodes; + public IEnumerable People; + public IEnumerable Genres; + public IEnumerable Studios; } } diff --git a/Kyoo.Common/Models/Season.cs b/Kyoo.Common/Models/Season.cs index bc149ee3..38225c56 100644 --- a/Kyoo.Common/Models/Season.cs +++ b/Kyoo.Common/Models/Season.cs @@ -4,13 +4,13 @@ namespace Kyoo.Models { public class Season : IMergable { - [JsonIgnore] public readonly long id; - [JsonIgnore] public long ShowID; + [JsonIgnore] public readonly long ID = -1; + [JsonIgnore] public long ShowID = -1; - public long seasonNumber; + public long SeasonNumber = -1; public string Title; public string Overview; - public long? year; + public long? Year; [JsonIgnore] public string ImgPrimary; public string ExternalIDs; @@ -19,12 +19,12 @@ namespace Kyoo.Models public Season(long id, long showID, long seasonNumber, string title, string overview, long? year, string imgPrimary, string externalIDs) { - this.id = id; + ID = id; ShowID = showID; - this.seasonNumber = seasonNumber; + SeasonNumber = seasonNumber; Title = title; Overview = overview; - this.year = year; + Year = year; ImgPrimary = imgPrimary; ExternalIDs = externalIDs; } @@ -45,14 +45,14 @@ namespace Kyoo.Models { if (ShowID == -1) ShowID = other.ShowID; - if (seasonNumber == -1) - seasonNumber = other.seasonNumber; + if (SeasonNumber == -1) + SeasonNumber = other.SeasonNumber; if (Title == null) Title = other.Title; if (Overview == null) Overview = other.Overview; - if (year == null) - year = other.year; + if (Year == null) + Year = other.Year; if (ImgPrimary == null) ImgPrimary = other.ImgPrimary; ExternalIDs += '|' + other.ExternalIDs; diff --git a/Kyoo.Common/Models/Show.cs b/Kyoo.Common/Models/Show.cs index c84f3595..53146e49 100644 --- a/Kyoo.Common/Models/Show.cs +++ b/Kyoo.Common/Models/Show.cs @@ -8,7 +8,7 @@ namespace Kyoo.Models { public class Show : IMergable { - [JsonIgnore] public long id = -1; + [JsonIgnore] public long ID = -1; public string Slug; public string Title; @@ -30,27 +30,21 @@ namespace Kyoo.Models public string ExternalIDs; //Used in the rest API excusively. - public Studio studio; - public IEnumerable directors; - public IEnumerable people; - public IEnumerable seasons; + public Studio Studio; + public IEnumerable Directors; + public IEnumerable People; + public IEnumerable Seasons; public bool IsCollection; public string GetAliases() { - if (Aliases == null) - return null; - - return string.Join('|', Aliases); + return Aliases == null ? null : string.Join('|', Aliases); } public string GetGenres() { - if (Genres == null) - return null; - - return string.Join('|', Genres); + return Genres == null ? null : string.Join('|', Genres); } @@ -58,7 +52,7 @@ namespace Kyoo.Models public Show(long id, string slug, string title, IEnumerable aliases, string path, string overview, string trailerUrl, IEnumerable genres, Status? status, long? startYear, long? endYear, string externalIDs) { - this.id = id; + ID = id; Slug = slug; Title = title; Aliases = aliases; @@ -75,7 +69,7 @@ namespace Kyoo.Models public Show(long id, string slug, string title, IEnumerable aliases, string path, string overview, string trailerUrl, Status? status, long? startYear, long? endYear, string imgPrimary, string imgThumb, string imgLogo, string imgBackdrop, string externalIDs) { - this.id = id; + ID = id; Slug = slug; Title = title; Aliases = aliases; @@ -146,38 +140,38 @@ namespace Kyoo.Models public Show SetGenres(ILibraryManager manager) { - Genres = manager.GetGenreForShow(id); + Genres = manager.GetGenreForShow(ID); return this; } public Show SetStudio(ILibraryManager manager) { - studio = manager.GetStudio(id); + Studio = manager.GetStudio(ID); return this; } public Show SetDirectors(ILibraryManager manager) { - directors = manager.GetDirectors(id); + Directors = manager.GetDirectors(ID); return this; } public Show SetPeople(ILibraryManager manager) { - people = manager.GetPeople(id); + People = manager.GetPeople(ID); return this; } public Show SetSeasons(ILibraryManager manager) { - seasons = manager.GetSeasons(id); + Seasons = manager.GetSeasons(ID); return this; } public Show Merge(Show other) { - if (id == -1) - id = other.id; + if (ID == -1) + ID = other.ID; if (Slug == null) Slug = other.Slug; if (Title == null) diff --git a/Kyoo.Common/Models/Studio.cs b/Kyoo.Common/Models/Studio.cs index 6fea773a..7c45fdc9 100644 --- a/Kyoo.Common/Models/Studio.cs +++ b/Kyoo.Common/Models/Studio.cs @@ -4,7 +4,7 @@ namespace Kyoo.Models { public class Studio { - [JsonIgnore] public readonly long id; + [JsonIgnore] public readonly long ID = -1; public string Slug; public string Name; @@ -16,7 +16,7 @@ namespace Kyoo.Models public Studio(long id, string slug, string name) { - this.id = id; + this.ID = id; Slug = slug; Name = name; } diff --git a/Kyoo.Common/Models/Track.cs b/Kyoo.Common/Models/Track.cs index 54f26ee0..f716f0bf 100644 --- a/Kyoo.Common/Models/Track.cs +++ b/Kyoo.Common/Models/Track.cs @@ -58,7 +58,7 @@ namespace Kyoo.Models public string DisplayName; public string Link; - [JsonIgnore] public long episodeID; + [JsonIgnore] public long EpisodeID; [JsonIgnore] public bool IsExternal; public Track(StreamType type, string title, string language, bool isDefault, bool isForced, string codec, bool isExternal, string path) diff --git a/Kyoo.Common/Models/WatchItem.cs b/Kyoo.Common/Models/WatchItem.cs index 5ef7d5ab..34eb0964 100644 --- a/Kyoo.Common/Models/WatchItem.cs +++ b/Kyoo.Common/Models/WatchItem.cs @@ -7,33 +7,33 @@ namespace Kyoo.Models { public class WatchItem { - [JsonIgnore] public readonly long episodeID; + [JsonIgnore] public readonly long EpisodeID = -1; public string ShowTitle; public string ShowSlug; - public long seasonNumber; - public long episodeNumber; + public long SeasonNumber; + public long EpisodeNumber; public string Title; public string Link; public DateTime? ReleaseDate; [JsonIgnore] public string Path; - public string previousEpisode; - public Episode nextEpisode; + public string PreviousEpisode; + public Episode NextEpisode; - public string container; - public Track video; - public IEnumerable audios; - public IEnumerable subtitles; + public string Container; + public Track Video; + public IEnumerable Audios; + public IEnumerable Subtitles; public WatchItem() { } public WatchItem(long episodeID, string showTitle, string showSlug, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path) { - this.episodeID = episodeID; + EpisodeID = episodeID; ShowTitle = showTitle; ShowSlug = showSlug; - this.seasonNumber = seasonNumber; - this.episodeNumber = episodeNumber; + SeasonNumber = seasonNumber; + EpisodeNumber = episodeNumber; Title = title; ReleaseDate = releaseDate; Path = path; @@ -43,8 +43,8 @@ namespace Kyoo.Models public WatchItem(long episodeID, string showTitle, string showSlug, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path, Track[] audios, Track[] subtitles) : this(episodeID, showTitle, showSlug, seasonNumber, episodeNumber, title, releaseDate, path) { - this.audios = audios; - this.subtitles = subtitles; + Audios = audios; + Subtitles = subtitles; } public static WatchItem FromReader(System.Data.SQLite.SQLiteDataReader reader) @@ -61,35 +61,35 @@ namespace Kyoo.Models public WatchItem SetStreams(ILibraryManager libraryManager) { - (Track video, IEnumerable audios, IEnumerable subtitles) streams = libraryManager.GetStreams(episodeID, Link); + (Track video, IEnumerable audios, IEnumerable subtitles) streams = libraryManager.GetStreams(EpisodeID, Link); - container = Path.Substring(Path.LastIndexOf('.') + 1); - video = streams.video; - audios = streams.audios; - subtitles = streams.subtitles; + Container = Path.Substring(Path.LastIndexOf('.') + 1); + Video = streams.video; + Audios = streams.audios; + Subtitles = streams.subtitles; return this; } public WatchItem SetPrevious(ILibraryManager libraryManager) { - long lastEp = episodeNumber - 1; + long lastEp = EpisodeNumber - 1; if(lastEp > 0) - previousEpisode = ShowSlug + "-s" + seasonNumber + "e" + lastEp; - else if(seasonNumber > 1) + PreviousEpisode = ShowSlug + "-s" + SeasonNumber + "e" + lastEp; + else if(SeasonNumber > 1) { - int seasonCount = libraryManager.GetSeasonCount(ShowSlug, seasonNumber - 1); - previousEpisode = ShowSlug + "-s" + (seasonNumber - 1) + "e" + seasonCount; + int seasonCount = libraryManager.GetSeasonCount(ShowSlug, SeasonNumber - 1); + PreviousEpisode = ShowSlug + "-s" + (SeasonNumber - 1) + "e" + seasonCount; } return this; } public WatchItem SetNext(ILibraryManager libraryManager) { - long seasonCount = libraryManager.GetSeasonCount(ShowSlug, seasonNumber); - if (episodeNumber >= seasonCount) - nextEpisode = libraryManager.GetEpisode(ShowSlug, seasonNumber + 1, 1); + long seasonCount = libraryManager.GetSeasonCount(ShowSlug, SeasonNumber); + if (EpisodeNumber >= seasonCount) + NextEpisode = libraryManager.GetEpisode(ShowSlug, SeasonNumber + 1, 1); else - nextEpisode = libraryManager.GetEpisode(ShowSlug, seasonNumber, episodeNumber + 1); + NextEpisode = libraryManager.GetEpisode(ShowSlug, SeasonNumber, EpisodeNumber + 1); return this; } diff --git a/Kyoo/Controllers/Crawler.cs b/Kyoo/Controllers/Crawler.cs index 95353e3a..38f1ad2a 100644 --- a/Kyoo/Controllers/Crawler.cs +++ b/Kyoo/Controllers/Crawler.cs @@ -1,4 +1,5 @@ -using Kyoo.Models; +using System; +using Kyoo.Models; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Diagnostics; @@ -67,25 +68,25 @@ namespace Kyoo.Controllers private async Task Scan(Library library, CancellationToken cancellationToken) { - IEnumerable files = new List(); - - files = library.Paths.Aggregate(files, (current, path) => - current.Concat(Directory.GetFiles(path, "*", SearchOption.AllDirectories))); - foreach (string file in files) + Console.WriteLine($"Scanning library {library.Name} at {string.Concat(library.Paths)}"); + foreach (string path in library.Paths) { - if (cancellationToken.IsCancellationRequested) - return; - if (!IsVideo(file)) - continue; - await RegisterFile(file, library); + foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories)) + { + if (cancellationToken.IsCancellationRequested) + return; + if (!IsVideo(file)) + continue; + string relativePath = file.Substring(path.Length); + await RegisterFile(file, relativePath, library); + } } } - private async Task RegisterFile(string path, Library library) + private async Task RegisterFile(string path, string relativePath, Library library) { if (!libraryManager.IsEpisodeRegistered(path)) { - string relativePath = path.Substring(library.Paths.Length); string patern = config.GetValue("regex"); Regex regex = new Regex(patern, RegexOptions.IgnoreCase); Match match = regex.Match(relativePath); @@ -97,7 +98,7 @@ namespace Kyoo.Controllers bool episodeSucess = long.TryParse(match.Groups["Episode"].Value, out long episodeNumber); long absoluteNumber = -1; - Debug.WriteLine("&Registering episode at: " + path); + Console.WriteLine("&Registering episode at: " + path); if (!seasonSuccess || !episodeSucess) { //Considering that the episode is using absolute path. @@ -112,7 +113,7 @@ namespace Kyoo.Controllers if (!absoluteSucess) { - Debug.WriteLine("&Couldn't find basic data for the episode (regexs didn't match)" + relativePath); + Console.WriteLine("&Couldn't find basic data for the episode (regexs didn't match) " + relativePath); return; } } @@ -120,6 +121,8 @@ namespace Kyoo.Controllers Show show = await RegisterOrGetShow(collectionName, showName, showPath, library); if (show != null) await RegisterEpisode(show, seasonNumber, episodeNumber, absoluteNumber, path, library); + else + Console.Error.WriteLine($"Coudld not get informations about the show ${showName}."); } } @@ -131,6 +134,8 @@ namespace Kyoo.Controllers { Show show = await metadataProvider.GetShowFromName(showTitle, library); show.Path = showPath; + show.Title = show.Title ?? showTitle; + show.Slug = show.Slug ?? Utility.ToSlug(showTitle); showProviderIDs = show.ExternalIDs; showID = libraryManager.RegisterShow(show); @@ -143,6 +148,7 @@ namespace Kyoo.Controllers if (!libraryManager.IsCollectionRegistered(Utility.ToSlug(collectionName), out long collectionID)) { Collection collection = await metadataProvider.GetCollectionFromName(collectionName, library); + collection.Name = collection.Name ?? collectionName; collectionID = libraryManager.RegisterCollection(collection); } libraryManager.AddShowToCollection(showID, collectionID); @@ -154,38 +160,40 @@ namespace Kyoo.Controllers else showProviderIDs = libraryManager.GetShowExternalIDs(showID); - return new Show { id = showID, ExternalIDs = showProviderIDs, Title = showTitle }; + return new Show { ID = showID, ExternalIDs = showProviderIDs, Title = showTitle }; } + private async Task RegisterSeason(Show show, long seasonNumber, Library library) + { + if (!libraryManager.IsSeasonRegistered(show.ID, seasonNumber, out long seasonID)) + { + Season season = await metadataProvider.GetSeason(show, seasonNumber, library); + season.ShowID = show.ID; + season.SeasonNumber = season.SeasonNumber == -1 ? seasonNumber : season.SeasonNumber; + season.Title ??= $"Season {season.SeasonNumber}"; + seasonID = libraryManager.RegisterSeason(season); + } + + return seasonID; + } + private async Task RegisterEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath, Library library) { long seasonID = -1; if (seasonNumber != -1) - { - if (!libraryManager.IsSeasonRegistered(show.id, seasonNumber, out seasonID)) - { - Season season = await metadataProvider.GetSeason(show.Title, seasonNumber, library); - season.ShowID = show.id; - seasonID = libraryManager.RegisterSeason(season); - } - } + seasonID = await RegisterSeason(show, seasonNumber, library); Episode episode = await metadataProvider.GetEpisode(show, seasonNumber, episodeNumber, absoluteNumber, library); - episode.ShowID = show.id; + episode.ShowID = show.ID; episode.Path = episodePath; + episode.SeasonNumber = episode.SeasonNumber != -1 ? episode.SeasonNumber : seasonNumber; + episode.EpisodeNumber = episode.EpisodeNumber != -1 ? episode.EpisodeNumber : episodeNumber; + episode.AbsoluteNumber = episode.AbsoluteNumber != -1 ? episode.AbsoluteNumber : absoluteNumber; if (seasonID == -1) - { - if (!libraryManager.IsSeasonRegistered(show.id, episode.seasonNumber, out seasonID)) - { - Season season = await metadataProvider.GetSeason(show.Title, episode.seasonNumber, library); - season.ShowID = show.id; - seasonID = libraryManager.RegisterSeason(season); - } - } - + seasonID = await RegisterSeason(show, seasonNumber, library); episode.SeasonID = seasonID; - episode.id = libraryManager.RegisterEpisode(episode); + episode.ID = libraryManager.RegisterEpisode(episode); Track[] tracks = await transcoder.GetTrackInfo(episode.Path); int subcount = 0; @@ -196,7 +204,7 @@ namespace Kyoo.Controllers subcount++; continue; } - track.episodeID = episode.id; + track.EpisodeID = episode.ID; libraryManager.RegisterTrack(track); } @@ -207,7 +215,7 @@ namespace Kyoo.Controllers { foreach (Track track in subtitles) { - track.episodeID = episode.id; + track.EpisodeID = episode.ID; libraryManager.RegisterTrack(track); } } @@ -225,22 +233,21 @@ namespace Kyoo.Controllers { string episodeLink = Path.GetFileNameWithoutExtension(episode.Path); - if (sub.Contains(episodeLink)) - { - string language = sub.Substring(Path.GetDirectoryName(sub).Length + episodeLink.Length + 2, 3); - bool isDefault = sub.Contains("default"); - bool isForced = sub.Contains("forced"); - Track track = new Track(StreamType.Subtitle, null, language, isDefault, isForced, null, false, sub) { episodeID = episode.id }; + if (!sub.Contains(episodeLink)) + continue; + string language = sub.Substring(Path.GetDirectoryName(sub).Length + episodeLink.Length + 2, 3); + bool isDefault = sub.Contains("default"); + bool isForced = sub.Contains("forced"); + Track track = new Track(StreamType.Subtitle, null, language, isDefault, isForced, null, false, sub) { EpisodeID = episode.ID }; - if (Path.GetExtension(sub) == ".ass") - track.Codec = "ass"; - else if (Path.GetExtension(sub) == ".srt") - track.Codec = "subrip"; - else - track.Codec = null; - libraryManager.RegisterTrack(track); - subcount++; - } + if (Path.GetExtension(sub) == ".ass") + track.Codec = "ass"; + else if (Path.GetExtension(sub) == ".srt") + track.Codec = "subrip"; + else + track.Codec = null; + libraryManager.RegisterTrack(track); + subcount++; } return subcount; } diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 33a00035..309106b3 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -837,7 +837,7 @@ namespace Kyoo.Controllers Genre existingGenre = GetGenreBySlug(genre.Slug); if (existingGenre != null) - return existingGenre.id; + return existingGenre.ID; string query = "INSERT INTO genres (slug, name) VALUES($slug, $name);"; using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) @@ -866,7 +866,7 @@ namespace Kyoo.Controllers Studio existingStudio = GetStudioBySlug(studio.Slug); if (existingStudio != null) - return existingStudio.id; + return existingStudio.ID; string query = "INSERT INTO studios (slug, name) VALUES($slug, $name);"; using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) @@ -892,20 +892,20 @@ namespace Kyoo.Controllers public long GetOrCreatePeople(People people) { - People existingPeople = GetPeopleBySlug(people.slug); + People existingPeople = GetPeopleBySlug(people.Slug); if (existingPeople != null) - return existingPeople.id; + return existingPeople.ID; string query = "INSERT INTO people (slug, name, imgPrimary, externalIDs) VALUES($slug, $name, $imgPrimary, $externalIDs);"; using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) { try { - cmd.Parameters.AddWithValue("$slug", people.slug); + cmd.Parameters.AddWithValue("$slug", people.Slug); cmd.Parameters.AddWithValue("$name", people.Name); - cmd.Parameters.AddWithValue("$imgPrimary", people.imgPrimary); - cmd.Parameters.AddWithValue("$externalIDs", people.externalIDs); + cmd.Parameters.AddWithValue("$imgPrimary", people.ImgPrimary); + cmd.Parameters.AddWithValue("$externalIDs", people.ExternalIDs); cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT LAST_INSERT_ROWID()"; @@ -915,7 +915,7 @@ namespace Kyoo.Controllers { Console.Error.WriteLine("SQL error while trying to insert a people ({0}).", people.Name); cmd.CommandText = "SELECT * FROM people WHERE slug = $slug"; - cmd.Parameters.AddWithValue("$slug", people.slug); + cmd.Parameters.AddWithValue("$slug", people.Slug); return (long)cmd.ExecuteScalar(); } @@ -958,7 +958,7 @@ namespace Kyoo.Controllers using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) { - cmd.Parameters.AddWithValue("$libraryID", library.id); + cmd.Parameters.AddWithValue("$libraryID", library.ID); cmd.Parameters.AddWithValue("$showID", showID); cmd.ExecuteNonQuery(); } @@ -1002,10 +1002,10 @@ namespace Kyoo.Controllers } } - if (show.studio != null) + if (show.Studio != null) { cmd.CommandText = "INSERT INTO studiosLinks (studioID, showID) VALUES($studioID, $showID);"; - long studioID = GetOrCreateStudio(show.studio); + long studioID = GetOrCreateStudio(show.Studio); cmd.Parameters.AddWithValue("$studioID", studioID); cmd.Parameters.AddWithValue("$showID", showID); cmd.ExecuteNonQuery(); @@ -1029,10 +1029,10 @@ namespace Kyoo.Controllers try { cmd.Parameters.AddWithValue("$showID", season.ShowID); - cmd.Parameters.AddWithValue("$seasonNumber", season.seasonNumber); + cmd.Parameters.AddWithValue("$seasonNumber", season.SeasonNumber); cmd.Parameters.AddWithValue("$title", season.Title); cmd.Parameters.AddWithValue("$overview", season.Overview); - cmd.Parameters.AddWithValue("$year", season.year); + cmd.Parameters.AddWithValue("$year", season.Year); cmd.Parameters.AddWithValue("$imgPrimary", season.ImgPrimary); cmd.Parameters.AddWithValue("$externalIDs", season.ExternalIDs); cmd.ExecuteNonQuery(); @@ -1045,7 +1045,7 @@ namespace Kyoo.Controllers Console.Error.WriteLine("SQL error while trying to insert a season ({0}), season probably already registered.", season.Title); cmd.CommandText = "SELECT * FROM seasons WHERE showID = $showID AND seasonNumber = $seasonNumber"; cmd.Parameters.AddWithValue("$showID", season.ShowID); - cmd.Parameters.AddWithValue("$seasonNumber", season.seasonNumber); + cmd.Parameters.AddWithValue("$seasonNumber", season.SeasonNumber); return (long)cmd.ExecuteScalar(); } } @@ -1060,9 +1060,9 @@ namespace Kyoo.Controllers { cmd.Parameters.AddWithValue("$showID", episode.ShowID); cmd.Parameters.AddWithValue("$seasonID", episode.SeasonID); - cmd.Parameters.AddWithValue("$seasonNUmber", episode.seasonNumber); - cmd.Parameters.AddWithValue("$episodeNumber", episode.episodeNumber); - cmd.Parameters.AddWithValue("$absoluteNumber", episode.absoluteNumber); + cmd.Parameters.AddWithValue("$seasonNUmber", episode.SeasonNumber); + cmd.Parameters.AddWithValue("$episodeNumber", episode.EpisodeNumber); + cmd.Parameters.AddWithValue("$absoluteNumber", episode.AbsoluteNumber); cmd.Parameters.AddWithValue("$path", episode.Path); cmd.Parameters.AddWithValue("$title", episode.Title); cmd.Parameters.AddWithValue("$overview", episode.Overview); @@ -1080,8 +1080,8 @@ namespace Kyoo.Controllers Console.Error.WriteLine("SQL error while trying to insert an episode ({0}), episode probably already registered.", episode.Link); cmd.CommandText = "SELECT * FROM episodes WHERE showID = $showID AND seasonNumber = $seasonNumber AND episodeNumber = $episodeNumber"; cmd.Parameters.AddWithValue("$showID", episode.ShowID); - cmd.Parameters.AddWithValue("$seasonNumber", episode.seasonNumber); - cmd.Parameters.AddWithValue("$episodeNumber", episode.episodeNumber); + cmd.Parameters.AddWithValue("$seasonNumber", episode.SeasonNumber); + cmd.Parameters.AddWithValue("$episodeNumber", episode.EpisodeNumber); return (long)cmd.ExecuteScalar(); } } @@ -1092,7 +1092,7 @@ namespace Kyoo.Controllers string query = "INSERT INTO tracks (episodeID, streamType, title, language, codec, isDefault, isForced, isExternal, path) VALUES($episodeID, $streamType, $title, $language, $codec, $isDefault, $isForced, $isExternal, $path);"; using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) { - cmd.Parameters.AddWithValue("$episodeID", track.episodeID); + cmd.Parameters.AddWithValue("$episodeID", track.EpisodeID); cmd.Parameters.AddWithValue("$streamType", track.Type); cmd.Parameters.AddWithValue("$title", track.Title); cmd.Parameters.AddWithValue("$language", track.Language); @@ -1167,11 +1167,11 @@ namespace Kyoo.Controllers using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) { - cmd.Parameters.AddWithValue("$episodeID", episode.id); + cmd.Parameters.AddWithValue("$episodeID", episode.ID); cmd.ExecuteNonQuery(); } - if (GetEpisodes(episode.ShowID, episode.seasonNumber).Count == 0) + if (GetEpisodes(episode.ShowID, episode.SeasonNumber).Count == 0) RemoveSeason(episode.ShowID, episode.SeasonID); } diff --git a/Kyoo/Controllers/PluginManager.cs b/Kyoo/Controllers/PluginManager.cs index 4bd26fec..c93b7083 100644 --- a/Kyoo/Controllers/PluginManager.cs +++ b/Kyoo/Controllers/PluginManager.cs @@ -43,11 +43,19 @@ namespace Kyoo.Controllers plugins = pluginsPaths.Select(path => { - Assembly ass = Assembly.LoadFile(path); - return (from type in ass.GetTypes() - where typeof(IPlugin).IsAssignableFrom(type) - select (IPlugin)ActivatorUtilities.CreateInstance(provider, type, null)).FirstOrDefault(); - }).Where(x => x != null).ToList(); + try + { + Assembly ass = Assembly.LoadFile(Path.GetFullPath(path)); + return (from type in ass.GetTypes() + where typeof(IPlugin).IsAssignableFrom(type) + select (IPlugin) ActivatorUtilities.CreateInstance(provider, type)).FirstOrDefault(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error loading the plugin at ${path}.\nException: {ex.Message}"); + return null; + } + }).Where(x => x != null).ToList(); } } } \ No newline at end of file diff --git a/Kyoo/Controllers/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs index 28ef23a5..c05e5ec1 100644 --- a/Kyoo/Controllers/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -64,9 +64,9 @@ namespace Kyoo.Controllers return show; } - public async Task GetSeason(string showName, long seasonNumber, Library library) + public async Task GetSeason(Show show, long seasonNumber, Library library) { - return await GetMetadata(provider => provider.GetSeason(showName, seasonNumber), library, $"the season ${seasonNumber} of {showName}"); + return await GetMetadata(provider => provider.GetSeason(show, seasonNumber), library, $"the season ${seasonNumber} of {show.Title}"); } public async Task GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber, Library library) diff --git a/Kyoo/Controllers/ThumbnailsManager.cs b/Kyoo/Controllers/ThumbnailsManager.cs index a3d25b65..fed87f8a 100644 --- a/Kyoo/Controllers/ThumbnailsManager.cs +++ b/Kyoo/Controllers/ThumbnailsManager.cs @@ -20,6 +20,8 @@ namespace Kyoo.Controllers.ThumbnailsManager public async Task Validate(Show show) { + if (show == null || show.Path == null) + return null; string localThumb = Path.Combine(show.Path, "poster.jpg"); string localLogo = Path.Combine(show.Path, "logo.png"); string localBackdrop = Path.Combine(show.Path, "backdrop.jpg"); @@ -69,23 +71,24 @@ namespace Kyoo.Controllers.ThumbnailsManager public async Task> Validate(IEnumerable people) { + if (people == null) + return null; foreach (People peop in people) { string root = config.GetValue("peoplePath"); Directory.CreateDirectory(root); - string localThumb = root + "/" + peop.slug + ".jpg"; - if (peop.imgPrimary != null && !File.Exists(localThumb)) + string localThumb = root + "/" + peop.Slug + ".jpg"; + if (peop.ImgPrimary == null || File.Exists(localThumb)) + continue; + try { - try - { - using WebClient client = new WebClient(); - await client.DownloadFileTaskAsync(new Uri(peop.imgPrimary), localThumb); - } - catch (WebException) - { - Console.Error.WriteLine("Couldn't download an image."); - } + using WebClient client = new WebClient(); + await client.DownloadFileTaskAsync(new Uri(peop.ImgPrimary), localThumb); + } + catch (WebException) + { + Console.Error.WriteLine("Couldn't download an image."); } } @@ -94,18 +97,19 @@ namespace Kyoo.Controllers.ThumbnailsManager public async Task Validate(Episode episode) { - string localThumb = Path.ChangeExtension(episode.Path, "jpg"); - if (episode.ImgPrimary != null && !File.Exists(localThumb)) + if (episode == null || episode.Path == null) + return null; + string localThumb = Path.ChangeExtension(episode.Path, "jpg"); + if (episode.ImgPrimary == null || File.Exists(localThumb)) + return episode; + try { - try - { - using WebClient client = new WebClient(); - await client.DownloadFileTaskAsync(new Uri(episode.ImgPrimary), localThumb); - } - catch (WebException) - { - Console.Error.WriteLine("Couldn't download an image."); - } + using WebClient client = new WebClient(); + await client.DownloadFileTaskAsync(new Uri(episode.ImgPrimary), localThumb); + } + catch (WebException) + { + Console.Error.WriteLine("Couldn't download an image."); } return episode; diff --git a/Kyoo/HtmlAPI/LibrariesController.cs b/Kyoo/HtmlAPI/LibrariesController.cs index c142f00e..4c4faee0 100644 --- a/Kyoo/HtmlAPI/LibrariesController.cs +++ b/Kyoo/HtmlAPI/LibrariesController.cs @@ -30,7 +30,7 @@ namespace Kyoo.Controllers if (library == null) return NotFound(); - return libraryManager.GetShowsInLibrary(library.id); + return libraryManager.GetShowsInLibrary(library.ID); } } } \ No newline at end of file diff --git a/Kyoo/HtmlAPI/PeopleController.cs b/Kyoo/HtmlAPI/PeopleController.cs index 2e93b8b5..bd133892 100644 --- a/Kyoo/HtmlAPI/PeopleController.cs +++ b/Kyoo/HtmlAPI/PeopleController.cs @@ -23,10 +23,10 @@ namespace Kyoo.Controllers if (people == null) return NotFound(); - Collection collection = new Collection(0, people.slug, people.Name, null, null) + Collection collection = new Collection(0, people.Slug, people.Name, null, null) { - Shows = libraryManager.GetShowsByPeople(people.id), - Poster = "peopleimg/" + people.slug + Shows = libraryManager.GetShowsByPeople(people.ID), + Poster = "peopleimg/" + people.Slug }; return collection; } diff --git a/Kyoo/HtmlAPI/SearchController.cs b/Kyoo/HtmlAPI/SearchController.cs index e070ab41..6a33330f 100644 --- a/Kyoo/HtmlAPI/SearchController.cs +++ b/Kyoo/HtmlAPI/SearchController.cs @@ -20,12 +20,12 @@ namespace Kyoo.Controllers { SearchResult result = new SearchResult { - query = query, - shows = libraryManager.GetShows(query), - episodes = libraryManager.SearchEpisodes(query), - people = libraryManager.SearchPeople(query), - genres = libraryManager.SearchGenres(query), - studios = libraryManager.SearchStudios(query) + Query = query, + Shows = libraryManager.GetShows(query), + Episodes = libraryManager.SearchEpisodes(query), + People = libraryManager.SearchPeople(query), + Genres = libraryManager.SearchGenres(query), + Studios = libraryManager.SearchStudios(query) }; return result; } diff --git a/Kyoo/HtmlAPI/SubtitleController.cs b/Kyoo/HtmlAPI/SubtitleController.cs index 747e6cc0..178c354c 100644 --- a/Kyoo/HtmlAPI/SubtitleController.cs +++ b/Kyoo/HtmlAPI/SubtitleController.cs @@ -50,12 +50,12 @@ namespace Kyoo.Controllers public async Task ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber) { Episode episode = libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); - libraryManager.ClearSubtitles(episode.id); + libraryManager.ClearSubtitles(episode.ID); Track[] tracks = await transcoder.ExtractSubtitles(episode.Path); foreach (Track track in tracks) { - track.episodeID = episode.id; + track.EpisodeID = episode.ID; libraryManager.RegisterTrack(track); } @@ -68,12 +68,12 @@ namespace Kyoo.Controllers List episodes = libraryManager.GetEpisodes(showSlug); foreach (Episode episode in episodes) { - libraryManager.ClearSubtitles(episode.id); + libraryManager.ClearSubtitles(episode.ID); Track[] tracks = await transcoder.ExtractSubtitles(episode.Path); foreach (Track track in tracks) { - track.episodeID = episode.id; + track.EpisodeID = episode.ID; libraryManager.RegisterTrack(track); } } diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index a60f4445..b62bff68 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -32,12 +32,12 @@ namespace Kyoo services.AddControllers().AddNewtonsoftJson(); services.AddHttpClient(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. From 87d01c604405ea6c2c80813ef3543936be171c45 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 25 Jan 2020 15:59:32 +0100 Subject: [PATCH 10/11] Finishing the plugin manager and the provider manager --- Kyoo.Common/Kyoo.Common.csproj | 2 +- Kyoo.Common/Models/Collection.cs | 2 ++ Kyoo.Common/Models/Episode.cs | 2 ++ Kyoo.Common/Models/Genre.cs | 2 +- Kyoo.Common/Models/People.cs | 2 ++ Kyoo.Common/Models/Season.cs | 2 ++ Kyoo.Common/Models/Show.cs | 2 ++ Kyoo.Common/Models/Studio.cs | 2 +- Kyoo.Common/Models/Track.cs | 2 +- Kyoo/Controllers/LibraryManager.cs | 3 +-- Kyoo/Controllers/PluginManager.cs | 10 +++++++--- Kyoo/Controllers/ProviderManager.cs | 8 ++++---- Kyoo/Kyoo.csproj | 1 + transcoder | 2 +- 14 files changed, 28 insertions(+), 14 deletions(-) diff --git a/Kyoo.Common/Kyoo.Common.csproj b/Kyoo.Common/Kyoo.Common.csproj index 1cc85725..131dda1e 100644 --- a/Kyoo.Common/Kyoo.Common.csproj +++ b/Kyoo.Common/Kyoo.Common.csproj @@ -11,7 +11,7 @@ SDG GPL-3.0-or-later true - 1.0.5 + 1.0.6 diff --git a/Kyoo.Common/Models/Collection.cs b/Kyoo.Common/Models/Collection.cs index c2e7a3b1..74d63518 100644 --- a/Kyoo.Common/Models/Collection.cs +++ b/Kyoo.Common/Models/Collection.cs @@ -51,6 +51,8 @@ namespace Kyoo.Models public Collection Merge(Collection collection) { + if (collection == null) + return this; if (ID == -1) ID = collection.ID; if (Slug == null) diff --git a/Kyoo.Common/Models/Episode.cs b/Kyoo.Common/Models/Episode.cs index f650ded4..3ad3aada 100644 --- a/Kyoo.Common/Models/Episode.cs +++ b/Kyoo.Common/Models/Episode.cs @@ -108,6 +108,8 @@ namespace Kyoo.Models public Episode Merge(Episode other) { + if (other == null) + return this; if (ID == -1) ID = other.ID; if (ShowID == -1) diff --git a/Kyoo.Common/Models/Genre.cs b/Kyoo.Common/Models/Genre.cs index 233c9f01..e80fa2c0 100644 --- a/Kyoo.Common/Models/Genre.cs +++ b/Kyoo.Common/Models/Genre.cs @@ -16,7 +16,7 @@ namespace Kyoo.Models public Genre(long id, string slug, string name) { - this.ID = id; + ID = id; Slug = slug; Name = name; } diff --git a/Kyoo.Common/Models/People.cs b/Kyoo.Common/Models/People.cs index 0738c577..4c189f99 100644 --- a/Kyoo.Common/Models/People.cs +++ b/Kyoo.Common/Models/People.cs @@ -57,6 +57,8 @@ namespace Kyoo.Models public People Merge(People other) { + if (other == null) + return this; if (ID == -1) ID = other.ID; if (Slug == null) diff --git a/Kyoo.Common/Models/Season.cs b/Kyoo.Common/Models/Season.cs index 38225c56..5ff2bee5 100644 --- a/Kyoo.Common/Models/Season.cs +++ b/Kyoo.Common/Models/Season.cs @@ -43,6 +43,8 @@ namespace Kyoo.Models public Season Merge(Season other) { + if (other == null) + return this; if (ShowID == -1) ShowID = other.ShowID; if (SeasonNumber == -1) diff --git a/Kyoo.Common/Models/Show.cs b/Kyoo.Common/Models/Show.cs index 53146e49..00cbfafa 100644 --- a/Kyoo.Common/Models/Show.cs +++ b/Kyoo.Common/Models/Show.cs @@ -170,6 +170,8 @@ namespace Kyoo.Models public Show Merge(Show other) { + if (other == null) + return this; if (ID == -1) ID = other.ID; if (Slug == null) diff --git a/Kyoo.Common/Models/Studio.cs b/Kyoo.Common/Models/Studio.cs index 7c45fdc9..48f6d68c 100644 --- a/Kyoo.Common/Models/Studio.cs +++ b/Kyoo.Common/Models/Studio.cs @@ -16,7 +16,7 @@ namespace Kyoo.Models public Studio(long id, string slug, string name) { - this.ID = id; + ID = id; Slug = slug; Name = name; } diff --git a/Kyoo.Common/Models/Track.cs b/Kyoo.Common/Models/Track.cs index f716f0bf..6c403fde 100644 --- a/Kyoo.Common/Models/Track.cs +++ b/Kyoo.Common/Models/Track.cs @@ -94,7 +94,7 @@ namespace Kyoo.Models if (language == "fre") language = "fra"; - DisplayName = CultureInfo.GetCultures(CultureTypes.NeutralCultures).FirstOrDefault(x => x.ThreeLetterISOLanguageName == language)?.DisplayName ?? language; + DisplayName = CultureInfo.GetCultures(CultureTypes.NeutralCultures).FirstOrDefault(x => x.ThreeLetterISOLanguageName == language)?.EnglishName ?? language; Link = "/subtitle/" + episodeSlug + "." + Language; if (IsForced) diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 309106b3..0c3003ca 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -18,10 +18,9 @@ namespace Kyoo.Controllers { string databasePath = configuration.GetValue("databasePath"); - Debug.WriteLine("&Library Manager init, databasePath: " + databasePath); if (!File.Exists(databasePath)) { - Debug.WriteLine("&Database doesn't exist, creating one."); + Console.WriteLine($"Creating the database at {databasePath}."); if (!Directory.Exists(Path.GetDirectoryName(databasePath))) Directory.CreateDirectory(databasePath); diff --git a/Kyoo/Controllers/PluginManager.cs b/Kyoo/Controllers/PluginManager.cs index c93b7083..3c41fa0e 100644 --- a/Kyoo/Controllers/PluginManager.cs +++ b/Kyoo/Controllers/PluginManager.cs @@ -22,13 +22,17 @@ namespace Kyoo.Controllers } public T GetPlugin(string name) - { + { + if (plugins == null) + return default; return (T)(from plugin in plugins where plugin.Name == name && plugin is T select plugin).FirstOrDefault(); } public IEnumerable GetPlugins() - { + { + if (plugins == null) + return null; return from plugin in plugins where plugin is T select (T)plugin; } @@ -52,7 +56,7 @@ namespace Kyoo.Controllers } catch (Exception ex) { - Console.Error.WriteLine($"Error loading the plugin at ${path}.\nException: {ex.Message}"); + Console.Error.WriteLine($"Error loading the plugin at {path}.\nException: {ex.Message}"); return null; } }).Where(x => x != null).ToList(); diff --git a/Kyoo/Controllers/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs index c05e5ec1..bf743f50 100644 --- a/Kyoo/Controllers/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -29,7 +29,7 @@ namespace Kyoo.Controllers if (library.Providers.Contains(provider.Name)) ret = ret.Merge(await providerCall(provider)); } catch (Exception ex) { - Console.Error.WriteLine($"The provider {provider.Name} coudln't work for {what}. (Excepetion: {ex.Message}"); + Console.Error.WriteLine($"The provider {provider.Name} coudln't work for {what}. (Exception: {ex.Message}"); } } return ret; @@ -66,19 +66,19 @@ namespace Kyoo.Controllers public async Task GetSeason(Show show, long seasonNumber, Library library) { - return await GetMetadata(provider => provider.GetSeason(show, seasonNumber), library, $"the season ${seasonNumber} of {show.Title}"); + return await GetMetadata(provider => provider.GetSeason(show, seasonNumber), library, $"the season {seasonNumber} of {show.Title}"); } public async Task GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber, Library library) { - Episode episode = await GetMetadata(provider => provider.GetEpisode(show, seasonNumber, episodeNumber, absoluteNumber), library, $"an episode"); + Episode episode = await GetMetadata(provider => provider.GetEpisode(show, seasonNumber, episodeNumber, absoluteNumber), library, "an episode"); await thumbnailsManager.Validate(episode); return episode; } public async Task> GetPeople(Show show, Library library) { - IEnumerable people = await GetMetadata(provider => provider.GetPeople(show), library, $"unknown data"); + IEnumerable people = await GetMetadata(provider => provider.GetPeople(show), library, "unknown data"); people = await thumbnailsManager.Validate(people); return people; } diff --git a/Kyoo/Kyoo.csproj b/Kyoo/Kyoo.csproj index 09b88261..d5ffa11a 100644 --- a/Kyoo/Kyoo.csproj +++ b/Kyoo/Kyoo.csproj @@ -17,6 +17,7 @@ + diff --git a/transcoder b/transcoder index d8f72ff8..bedf98f8 160000 --- a/transcoder +++ b/transcoder @@ -1 +1 @@ -Subproject commit d8f72ff87020f2d38a4552f6083ef0659bf1f2be +Subproject commit bedf98f85d2cf669a1d1c4af35271841133cfec2 From 24e701be38f6324084e9caa9c72e703d74207afb Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 25 Jan 2020 16:29:23 +0100 Subject: [PATCH 11/11] Removing old UT --- Unit Tests/Kyoo-InternalAPI/Library-Tests.cs | 21 ---------- .../Kyoo-InternalAPI/Thumbnails-Tests.cs | 40 ------------------- Unit Tests/Unit Tests.csproj | 29 -------------- Unit Tests/appsettings.json | 18 --------- 4 files changed, 108 deletions(-) delete mode 100644 Unit Tests/Kyoo-InternalAPI/Library-Tests.cs delete mode 100644 Unit Tests/Kyoo-InternalAPI/Thumbnails-Tests.cs delete mode 100644 Unit Tests/Unit Tests.csproj delete mode 100644 Unit Tests/appsettings.json diff --git a/Unit Tests/Kyoo-InternalAPI/Library-Tests.cs b/Unit Tests/Kyoo-InternalAPI/Library-Tests.cs deleted file mode 100644 index b3c061ff..00000000 --- a/Unit Tests/Kyoo-InternalAPI/Library-Tests.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Kyoo.InternalAPI; -using Microsoft.Extensions.Configuration; -using NUnit.Framework; - -namespace UnitTests.Kyoo_InternalAPI -{ - public class LibraryTests - { - private IConfiguration config; - private ILibraryManager libraryManager; - - [SetUp] - public void Setup() - { - config = new ConfigurationBuilder() - .AddJsonFile("appsettings.json") - .Build(); - libraryManager = new LibraryManager(config); - } - } -} diff --git a/Unit Tests/Kyoo-InternalAPI/Thumbnails-Tests.cs b/Unit Tests/Kyoo-InternalAPI/Thumbnails-Tests.cs deleted file mode 100644 index 8229a107..00000000 --- a/Unit Tests/Kyoo-InternalAPI/Thumbnails-Tests.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Kyoo.InternalAPI; -using Kyoo.InternalAPI.ThumbnailsManager; -using Kyoo.Models; -using Microsoft.Extensions.Configuration; -using NUnit.Framework; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace UnitTests.Kyoo_InternalAPI -{ - public class ThumbnailsTests - { - private IConfiguration config; - - [SetUp] - public void Setup() - { - config = new ConfigurationBuilder() - .AddJsonFile("appsettings.json") - .Build(); - } - - [Test] - public async Task DownloadShowImages() - { - LibraryManager library = new LibraryManager(config); - ThumbnailsManager manager = new ThumbnailsManager(config); - Show show = library.GetShowBySlug(library.GetShows().FirstOrDefault().Slug); - Debug.WriteLine("&Show: " + show.Path); - string posterPath = Path.Combine(show.Path, "poster.jpg"); - File.Delete(posterPath); - - await manager.Validate(show); - long posterLength = new FileInfo(posterPath).Length; - Assert.IsTrue(posterLength > 0, "Poster size is zero for the tested show (" + posterPath + ")"); - } - } -} diff --git a/Unit Tests/Unit Tests.csproj b/Unit Tests/Unit Tests.csproj deleted file mode 100644 index 779d6470..00000000 --- a/Unit Tests/Unit Tests.csproj +++ /dev/null @@ -1,29 +0,0 @@ - - - - netcoreapp3.1 - UnitTests - - false - - UnitTests - - - - - - - - - - - - - - - - PreserveNewest - - - - diff --git a/Unit Tests/appsettings.json b/Unit Tests/appsettings.json deleted file mode 100644 index 6fb127c3..00000000 --- a/Unit Tests/appsettings.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "server.urls": "http://0.0.0.0:5000", - "https_port": 44300, - "Logging": { - "LogLevel": { - "Default": "Warning" - } - }, - "AllowedHosts": "*", - - "databasePath": "C://Projects/database.db", - "tempPath": "C:\\\\Projects\\temp", - "peoplePath": "D:\\\\Videos\\People", - "plugins": "C:\\Projects\\Kyoo\\Debug", - "providerPlugins": "C://Projects/Plugins/Providers", - "regex": "^(\\\\(?.+?))?\\\\.*\\\\(?.+?) S(?\\d+)E(?\\d+)", - "absoluteRegex": ".*\\\\(?.+?) (?\\d+)" -}