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.