Finishing to rework the manager to use EF and reworking the crawler to use the new API

This commit is contained in:
Zoe Roux 2020-02-08 01:40:26 +01:00
parent a2a494d907
commit b2471c99ae
15 changed files with 179 additions and 552 deletions

View File

@ -54,16 +54,12 @@ namespace Kyoo.Controllers
long RegisterShow(Show show); long RegisterShow(Show show);
long RegisterSeason(Season season); long RegisterSeason(Season season);
long RegisterEpisode(Episode episode); long RegisterEpisode(Episode episode);
void RegisterTrack(Track track); long RegisterTrack(Track track);
void RegisterShowLinks(Library library, Collection collection, Show show);
long GetOrCreateGenre(Genre genre); void RemoveShow(long showID);
long GetOrCreateStudio(Studio studio); void RemoveSeason(long seasonID);
void RemoveEpisode(long episodeID);
void RegisterShowPeople(long showID, IEnumerable<People> actors);
void AddShowToCollection(long showID, long collectionID);
void RegisterInLibrary(long showID, Library library);
void RemoveEpisode(Episode episode);
void ClearSubtitles(long episodeID); void ClearSubtitles(long episodeID);
} }
} }

View File

@ -16,7 +16,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.112" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,5 +1,4 @@
using Kyoo.Controllers; using Newtonsoft.Json;
using Newtonsoft.Json;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -7,7 +6,7 @@ namespace Kyoo.Models
{ {
public class Collection : IMergable<Collection> public class Collection : IMergable<Collection>
{ {
[JsonIgnore] public long ID { get; set; } = -1; [JsonIgnore] public long ID { get; set; }
public string Slug { get; set; } public string Slug { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Poster { get; set; } public string Poster { get; set; }
@ -17,40 +16,22 @@ namespace Kyoo.Models
public Collection() { } public Collection() { }
public Collection(long id, string slug, string name, string overview, string imgPrimary) public Collection(string slug, string name, string overview, string imgPrimary)
{ {
ID = id;
Slug = slug; Slug = slug;
Name = name; Name = name;
Overview = overview; Overview = overview;
ImgPrimary = imgPrimary; 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 Show AsShow() public Show AsShow()
{ {
return new Show(-1, Slug, Name, null, null, Overview, null, null, null, null, null, null) return new Show(Slug, Name, null, null, Overview, null, null, null, null, null, null)
{ {
IsCollection = true IsCollection = true
}; };
} }
public Collection SetShows(ILibraryManager libraryManager)
{
Shows = libraryManager.GetShowsInCollection(ID);
return this;
}
public Collection Merge(Collection collection) public Collection Merge(Collection collection)
{ {
if (collection == null) if (collection == null)

View File

@ -1,5 +1,6 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic;
namespace Kyoo.Models namespace Kyoo.Models
{ {
@ -7,9 +8,9 @@ namespace Kyoo.Models
{ {
[JsonIgnore] public long ID { get; set; } [JsonIgnore] public long ID { get; set; }
[JsonIgnore] public long ShowID { get; set; } [JsonIgnore] public long ShowID { get; set; }
public virtual Show Show { get; set; } [JsonIgnore] public virtual Show Show { get; set; }
[JsonIgnore] public long SeasonID { get; set; } [JsonIgnore] public long SeasonID { get; set; }
public virtual Season Season { get; set; } [JsonIgnore] public virtual Season Season { get; set; }
public long SeasonNumber { get; set; } public long SeasonNumber { get; set; }
public long EpisodeNumber { get; set; } public long EpisodeNumber { get; set; }
@ -24,6 +25,8 @@ namespace Kyoo.Models
[JsonIgnore] public string ImgPrimary { get; set; } [JsonIgnore] public string ImgPrimary { get; set; }
public string ExternalIDs { get; set; } public string ExternalIDs { get; set; }
public IEnumerable<Track> Tracks { get; set; }
public string ShowTitle; //Used in the API response only public string ShowTitle; //Used in the API response only
public string Link; //Used in the API response only public string Link; //Used in the API response only
public string Thumb; //Used in the API response only public string Thumb; //Used in the API response only
@ -31,9 +34,6 @@ namespace Kyoo.Models
public Episode() public Episode()
{ {
ID = -1;
ShowID = -1;
SeasonID = -1;
SeasonNumber = -1; SeasonNumber = -1;
EpisodeNumber = -1; EpisodeNumber = -1;
AbsoluteNumber = -1; AbsoluteNumber = -1;
@ -41,9 +41,6 @@ namespace Kyoo.Models
public Episode(long seasonNumber, long episodeNumber, long absoluteNumber, string title, string overview, DateTime? releaseDate, long runtime, string imgPrimary, string externalIDs) public Episode(long seasonNumber, long episodeNumber, long absoluteNumber, string title, string overview, DateTime? releaseDate, long runtime, string imgPrimary, string externalIDs)
{ {
ID = -1;
ShowID = -1;
SeasonID = -1;
SeasonNumber = seasonNumber; SeasonNumber = seasonNumber;
EpisodeNumber = episodeNumber; EpisodeNumber = episodeNumber;
AbsoluteNumber = absoluteNumber; AbsoluteNumber = absoluteNumber;
@ -55,9 +52,8 @@ namespace Kyoo.Models
ExternalIDs = externalIDs; ExternalIDs = externalIDs;
} }
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) public Episode(long showID, long seasonID, long seasonNumber, long episodeNumber, long absoluteNumber, string path, string title, string overview, DateTime? releaseDate, long runtime, string imgPrimary, string externalIDs)
{ {
ID = id;
ShowID = showID; ShowID = showID;
SeasonID = seasonID; SeasonID = seasonID;
SeasonNumber = seasonNumber; SeasonNumber = seasonNumber;
@ -72,37 +68,6 @@ namespace Kyoo.Models
ExternalIDs = externalIDs; ExternalIDs = externalIDs;
} }
public static Episode FromReader(System.Data.SQLite.SQLiteDataReader reader)
{
return new Episode((long)reader["id"],
(long)reader["showID"],
(long)reader["seasonID"],
(long)reader["seasonNumber"],
(long)reader["episodeNumber"],
(long)reader["absoluteNumber"],
reader["path"] as string,
reader["title"] as string,
reader["overview"] as string,
reader["releaseDate"] as DateTime?,
(long)reader["runtime"],
reader["imgPrimary"] as string,
reader["externalIDs"] as string);
}
public Episode SetThumb(string showSlug)
{
Link = GetSlug(showSlug, SeasonNumber, EpisodeNumber);
Thumb = "thumb/" + Link;
return this;
}
public Episode SetShowTitle(string showTite)
{
ShowTitle = showTite;
return this;
}
public static string GetSlug(string showSlug, long seasonNumber, long episodeNumber) public static string GetSlug(string showSlug, long seasonNumber, long episodeNumber)
{ {
return showSlug + "-s" + seasonNumber + "e" + episodeNumber; return showSlug + "-s" + seasonNumber + "e" + episodeNumber;

View File

@ -20,12 +20,5 @@ namespace Kyoo.Models
Slug = slug; Slug = slug;
Name = name; Name = name;
} }
public static Genre FromReader(System.Data.SQLite.SQLiteDataReader reader)
{
return new Genre((long)reader["id"],
reader["slug"] as string,
reader["name"] as string);
}
} }
} }

View File

@ -1,11 +1,10 @@
using System.Collections.Generic; using Newtonsoft.Json;
using Newtonsoft.Json;
namespace Kyoo.Models namespace Kyoo.Models
{ {
public class Library public class Library
{ {
[JsonIgnore] public long Id { get; set; } [JsonIgnore] public long ID { get; set; }
public string Slug { get; set; } public string Slug { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string[] Paths { get; set; } public string[] Paths { get; set; }
@ -13,22 +12,12 @@ namespace Kyoo.Models
public Library() { } public Library() { }
public Library(long id, string slug, string name, string[] paths, string[] providers) public Library(string slug, string name, string[] paths, string[] providers)
{ {
Id = id;
Slug = slug; Slug = slug;
Name = name; Name = name;
Paths = paths; Paths = paths;
Providers = providers; Providers = providers;
} }
public static Library FromReader(System.Data.SQLite.SQLiteDataReader reader)
{
return new Library((long)reader["id"],
reader["slug"] as string,
reader["name"] as string,
(reader["path"] as string)?.Split('|'),
(reader["providers"] as string)?.Split('|'));
}
} }
} }

View File

@ -1,12 +1,11 @@
using System.Collections; using System.Collections.Generic;
using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Kyoo.Models namespace Kyoo.Models
{ {
public class People : IMergable<People> public class People : IMergable<People>
{ {
[JsonIgnore] public long ID { get; set; } = -1; [JsonIgnore] public long ID { get; set; }
public string Slug { get; set; } public string Slug { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Role; public string Role;
@ -18,18 +17,16 @@ namespace Kyoo.Models
public People() {} public People() {}
public People(long id, string slug, string name, string imgPrimary, string externalIDs) public People(string slug, string name, string imgPrimary, string externalIDs)
{ {
ID = id;
Slug = slug; Slug = slug;
Name = name; Name = name;
ImgPrimary = imgPrimary; ImgPrimary = imgPrimary;
ExternalIDs = externalIDs; ExternalIDs = externalIDs;
} }
public People(long id, string slug, string name, string role, string type, string imgPrimary, string externalIDs) public People(string slug, string name, string role, string type, string imgPrimary, string externalIDs)
{ {
ID = id;
Slug = slug; Slug = slug;
Name = name; Name = name;
Role = role; Role = role;
@ -45,6 +42,19 @@ namespace Kyoo.Models
return this; return this;
} }
public PeopleLink ToLink(Show show)
{
return new PeopleLink
{
People = this,
PeopleID = ID,
Role = Role,
Type = Type,
Show = show,
ShowID = show.ID
};
}
public People Merge(People other) public People Merge(People other)
{ {
if (other == null) if (other == null)

View File

@ -1,13 +1,12 @@
using System.Collections; using System.Collections.Generic;
using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Kyoo.Models namespace Kyoo.Models
{ {
public class Season : IMergable<Season> public class Season : IMergable<Season>
{ {
[JsonIgnore] public long ID { get; set; } = -1; [JsonIgnore] public long ID { get; set; }
[JsonIgnore] public long ShowID { get; set; } = -1; [JsonIgnore] public long ShowID { get; set; }
public long SeasonNumber { get; set; } = -1; public long SeasonNumber { get; set; } = -1;
public string Title { get; set; } public string Title { get; set; }
@ -17,14 +16,13 @@ namespace Kyoo.Models
[JsonIgnore] public string ImgPrimary { get; set; } [JsonIgnore] public string ImgPrimary { get; set; }
public string ExternalIDs { get; set; } public string ExternalIDs { get; set; }
public virtual Show Show { get; set; } [JsonIgnore] public virtual Show Show { get; set; }
public virtual IEnumerable<Episode> Episodes { get; set; } [JsonIgnore] public virtual IEnumerable<Episode> Episodes { get; set; }
public Season() { } public Season() { }
public Season(long id, long showID, long seasonNumber, string title, string overview, long? year, string imgPrimary, string externalIDs) public Season(long showID, long seasonNumber, string title, string overview, long? year, string imgPrimary, string externalIDs)
{ {
ID = id;
ShowID = showID; ShowID = showID;
SeasonNumber = seasonNumber; SeasonNumber = seasonNumber;
Title = title; Title = title;
@ -34,18 +32,6 @@ namespace Kyoo.Models
ExternalIDs = externalIDs; ExternalIDs = externalIDs;
} }
public static Season FromReader(System.Data.SQLite.SQLiteDataReader reader)
{
return new Season((long)reader["id"],
(long)reader["showID"],
(long)reader["seasonNumber"],
reader["title"] as string,
reader["overview"] as string,
reader["year"] as long?,
reader["imgPrimary"] as string,
reader["externalIDs"] as string);
}
public Season Merge(Season other) public Season Merge(Season other)
{ {
if (other == null) if (other == null)

View File

@ -1,5 +1,4 @@
using System; using System;
using Kyoo.Controllers;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -32,9 +31,9 @@ namespace Kyoo.Models
public IEnumerable<Genre> Genres; public IEnumerable<Genre> Genres;
public virtual Studio Studio { get; set; } public virtual Studio Studio { get; set; }
public virtual IEnumerable<PeopleLink> People { get; set; } [JsonIgnore] public virtual IEnumerable<PeopleLink> People { get; set; }
public virtual IEnumerable<Season> Seasons { get; set; } [JsonIgnore] public virtual IEnumerable<Season> Seasons { get; set; }
public virtual IEnumerable<Episode> Episodes { get; set; } [JsonIgnore] public virtual IEnumerable<Episode> Episodes { get; set; }
public string GetAliases() public string GetAliases()
@ -50,9 +49,8 @@ namespace Kyoo.Models
public Show() { } public Show() { }
public Show(long id, string slug, string title, IEnumerable<string> aliases, string path, string overview, string trailerUrl, IEnumerable<Genre> genres, Status? status, long? startYear, long? endYear, string externalIDs) public Show(string slug, string title, IEnumerable<string> aliases, string path, string overview, string trailerUrl, IEnumerable<Genre> genres, Status? status, long? startYear, long? endYear, string externalIDs)
{ {
ID = id;
Slug = slug; Slug = slug;
Title = title; Title = title;
Aliases = aliases.ToArray(); Aliases = aliases.ToArray();
@ -67,9 +65,8 @@ namespace Kyoo.Models
IsCollection = false; IsCollection = false;
} }
public Show(long id, string slug, string title, IEnumerable<string> aliases, string path, string overview, string trailerUrl, Status? status, long? startYear, long? endYear, string imgPrimary, string imgThumb, string imgLogo, string imgBackdrop, string externalIDs) public Show(string slug, string title, IEnumerable<string> aliases, string path, string overview, string trailerUrl, Status? status, long? startYear, long? endYear, string imgPrimary, string imgThumb, string imgLogo, string imgBackdrop, string externalIDs)
{ {
ID = id;
Slug = slug; Slug = slug;
Title = title; Title = title;
Aliases = aliases.ToArray(); Aliases = aliases.ToArray();
@ -87,40 +84,6 @@ namespace Kyoo.Models
IsCollection = false; IsCollection = false;
} }
public static Show FromQueryReader(System.Data.SQLite.SQLiteDataReader reader, bool containsAliases = false)
{
Show show = new Show()
{
Slug = reader["slug"] as string,
Title = reader["title"] as string,
StartYear = reader["startYear"] as long?,
EndYear = reader["endYear"] as long?,
IsCollection = reader["'0'"] as string == "1"
};
if (containsAliases)
show.Aliases = (reader["aliases"] as string)?.Split('|');
return show;
}
public static Show FromReader(System.Data.SQLite.SQLiteDataReader reader)
{
return new Show((long)reader["id"],
reader["slug"] as string,
reader["title"] as string,
(reader["aliases"] as string)?.Split('|'),
reader["path"] as string,
reader["overview"] as string,
reader["trailerUrl"] as string,
reader["status"] as Status?,
reader["startYear"] as long?,
reader["endYear"] as long?,
reader["imgPrimary"] as string,
reader["imgThumb"] as string,
reader["imgLogo"] as string,
reader["imgBackdrop"] as string,
reader["externalIDs"] as string);
}
public string GetID(string provider) public string GetID(string provider)
{ {
if (ExternalIDs?.Contains(provider) != true) if (ExternalIDs?.Contains(provider) != true)
@ -131,43 +94,6 @@ namespace Kyoo.Models
return ExternalIDs.Substring(startIndex, ExternalIDs.IndexOf('|', startIndex) - startIndex); return ExternalIDs.Substring(startIndex, ExternalIDs.IndexOf('|', startIndex) - startIndex);
} }
public Show Set(string slug, string path)
{
Slug = slug;
Path = path;
return this;
}
public Show SetGenres(ILibraryManager manager)
{
Genres = manager.GetGenreForShow(ID);
return this;
}
public Show SetStudio(ILibraryManager manager)
{
Studio = manager.GetStudio(ID);
return this;
}
public Show SetDirectors(ILibraryManager manager)
{
//Directors = manager.GetDirectors(ID);
return this;
}
public Show SetPeople(ILibraryManager manager)
{
//People = manager.GetPeople(ID);
return this;
}
public Show SetSeasons(ILibraryManager manager)
{
Seasons = manager.GetSeasons(ID);
return this;
}
public Show Merge(Show other) public Show Merge(Show other)
{ {
if (other == null) if (other == null)

View File

@ -4,7 +4,7 @@ namespace Kyoo.Models
{ {
public class Studio public class Studio
{ {
[JsonIgnore] public long ID { get; set; } = -1; [JsonIgnore] public long ID { get; set; }
public string Slug { get; set; } public string Slug { get; set; }
public string Name { get; set; } public string Name { get; set; }
@ -16,20 +16,6 @@ namespace Kyoo.Models
Name = name; Name = name;
} }
public Studio(long id, string slug, string name)
{
ID = id;
Slug = slug;
Name = name;
}
public static Studio FromReader(System.Data.SQLite.SQLiteDataReader reader)
{
return new Studio((long)reader["id"],
reader["slug"] as string,
reader["name"] as string);
}
public static Studio Default() public static Studio Default()
{ {
return new Studio("unknow", "Unknow Studio"); return new Studio("unknow", "Unknow Studio");

View File

@ -88,18 +88,6 @@ namespace Kyoo.Models
IsExternal = false; IsExternal = false;
} }
public static Track FromReader(System.Data.SQLite.SQLiteDataReader reader)
{
return new Track((StreamType)Enum.ToObject(typeof(StreamType), reader["streamType"]),
reader["title"] as string,
reader["language"] as string,
reader["isDefault"] as bool? ?? false,
reader["isForced"] as bool? ?? false,
reader["codec"] as string,
reader["isExternal"] as bool? ?? false,
reader["path"] as string);
}
public Track SetLink(string episodeSlug) public Track SetLink(string episodeSlug)
{ {
if (Type == StreamType.Subtitle) if (Type == StreamType.Subtitle)

View File

@ -13,50 +13,50 @@ namespace Kyoo.Controllers
{ {
public class Crawler : ICrawler public class Crawler : ICrawler
{ {
private bool isRunning; private bool _isRunning;
private readonly CancellationTokenSource cancellation; private readonly CancellationTokenSource _cancellation;
private readonly ILibraryManager libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IProviderManager metadataProvider; private readonly IProviderManager _metadataProvider;
private readonly ITranscoder transcoder; private readonly ITranscoder _transcoder;
private readonly IConfiguration config; private readonly IConfiguration _config;
public Crawler(ILibraryManager libraryManager, IProviderManager metadataProvider, ITranscoder transcoder, IConfiguration configuration) public Crawler(ILibraryManager libraryManager, IProviderManager metadataProvider, ITranscoder transcoder, IConfiguration configuration)
{ {
this.libraryManager = libraryManager; _libraryManager = libraryManager;
this.metadataProvider = metadataProvider; _metadataProvider = metadataProvider;
this.transcoder = transcoder; _transcoder = transcoder;
config = configuration; _config = configuration;
cancellation = new CancellationTokenSource(); _cancellation = new CancellationTokenSource();
} }
public void Start() public void Start()
{ {
if (isRunning) if (_isRunning)
return; return;
isRunning = true; _isRunning = true;
StartAsync(cancellation.Token); StartAsync(_cancellation.Token);
} }
public void Cancel() public void Cancel()
{ {
if (!isRunning) if (!_isRunning)
return; return;
isRunning = false; _isRunning = false;
cancellation.Cancel(); _cancellation.Cancel();
} }
private async void StartAsync(CancellationToken cancellationToken) private async void StartAsync(CancellationToken cancellationToken)
{ {
try try
{ {
IEnumerable<Episode> episodes = libraryManager.GetAllEpisodes(); IEnumerable<Episode> episodes = _libraryManager.GetAllEpisodes();
IEnumerable<Library> libraries = libraryManager.GetLibraries(); IEnumerable<Library> libraries = _libraryManager.GetLibraries();
foreach (Episode episode in episodes) foreach (Episode episode in episodes)
{ {
if (!File.Exists(episode.Path)) if (!File.Exists(episode.Path))
libraryManager.RemoveEpisode(episode); _libraryManager.RemoveEpisode(episode.ID);
} }
foreach (Library library in libraries) foreach (Library library in libraries)
@ -66,7 +66,7 @@ namespace Kyoo.Controllers
{ {
Console.Error.WriteLine($"Unknown exception thrown durring libraries scan.\nException: {ex.Message}"); Console.Error.WriteLine($"Unknown exception thrown durring libraries scan.\nException: {ex.Message}");
} }
isRunning = false; _isRunning = false;
Console.WriteLine("Scan finished!"); Console.WriteLine("Scan finished!");
} }
@ -79,7 +79,7 @@ namespace Kyoo.Controllers
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
return; return;
if (!IsVideo(file)) if (!IsVideo(file) || _libraryManager.IsEpisodeRegistered(file, out long _))
continue; continue;
string relativePath = file.Substring(path.Length); string relativePath = file.Substring(path.Length);
await RegisterFile(file, relativePath, library); await RegisterFile(file, relativePath, library);
@ -89,9 +89,7 @@ namespace Kyoo.Controllers
private async Task RegisterFile(string path, string relativePath, Library library) private async Task RegisterFile(string path, string relativePath, Library library)
{ {
if (!libraryManager.IsEpisodeRegistered(path, out long _)) string patern = _config.GetValue<string>("regex");
{
string patern = config.GetValue<string>("regex");
Regex regex = new Regex(patern, RegexOptions.IgnoreCase); Regex regex = new Regex(patern, RegexOptions.IgnoreCase);
Match match = regex.Match(relativePath); Match match = regex.Match(relativePath);
@ -109,7 +107,7 @@ namespace Kyoo.Controllers
seasonNumber = -1; seasonNumber = -1;
episodeNumber = -1; episodeNumber = -1;
regex = new Regex(config.GetValue<string>("absoluteRegex")); regex = new Regex(_config.GetValue<string>("absoluteRegex"));
match = regex.Match(relativePath); match = regex.Match(relativePath);
showName = match.Groups["ShowTitle"].Value; showName = match.Groups["ShowTitle"].Value;
@ -122,103 +120,65 @@ namespace Kyoo.Controllers
} }
} }
Show show = await RegisterOrGetShow(collectionName, showName, showPath, library); Collection collection = await GetCollection(collectionName, library);
if (show != null) Show show = await GetShow(showName, showPath, library);
await RegisterEpisode(show, seasonNumber, episodeNumber, absoluteNumber, path, library); Season season = await GetSeason(show, seasonNumber, library);
else Episode episode = await GetEpisode(show, season, episodeNumber, absoluteNumber, path, library);
Console.Error.WriteLine($"Coudld not get informations about the show {showName}."); _libraryManager.RegisterEpisode(episode);
} _libraryManager.RegisterShowLinks(library, collection, show);
} }
private async Task<Show> RegisterOrGetShow(string collectionName, string showTitle, string showPath, Library library) private async Task<Collection> GetCollection(string collectionName, Library library)
{ {
string showProviderIDs; if (string.IsNullOrEmpty(collectionName))
return await Task.FromResult<Collection>(null);
if (_libraryManager.IsCollectionRegistered(Utility.ToSlug(collectionName), out long collectionID))
return new Collection {ID = collectionID};
return await _metadataProvider.GetCollectionFromName(collectionName, library);
}
if (!libraryManager.IsShowRegistered(showPath, out long showID)) private async Task<Show> GetShow(string showTitle, string showPath, Library library)
{ {
Show show = await metadataProvider.GetShowFromName(showTitle, showPath, library); if (_libraryManager.IsShowRegistered(showPath, out long showID))
showProviderIDs = show.ExternalIDs; return new Show { ID = showID, Title = showTitle, ExternalIDs = _libraryManager.GetShowExternalIDs(showID) };
showID = libraryManager.RegisterShow(show); Show show = await _metadataProvider.GetShowFromName(showTitle, showPath, library);
show.People = from people in await _metadataProvider.GetPeople(show, library) select people.ToLink(show);
return show;
}
if (showID == -1) private async Task<Season> GetSeason(Show show, long seasonNumber, Library library)
return null;
libraryManager.RegisterInLibrary(showID, library);
if (!string.IsNullOrEmpty(collectionName))
{ {
if (!libraryManager.IsCollectionRegistered(Utility.ToSlug(collectionName), out long collectionID)) if (_libraryManager.IsSeasonRegistered(show.ID, seasonNumber, out long seasonID))
return await Task.FromResult(new Season {ID = seasonID, ShowID = show.ID, Show = show});
Season season = await _metadataProvider.GetSeason(show, seasonNumber, library);
season.Show = show;
season.ShowID = show.ID;
return season;
}
private async Task<Episode> GetEpisode(Show show, Season season, long episodeNumber, long absoluteNumber, string episodePath, Library library)
{ {
Collection collection = await metadataProvider.GetCollectionFromName(collectionName, library); Episode episode = await _metadataProvider.GetEpisode(show, episodePath, season.SeasonNumber, episodeNumber, absoluteNumber, library);
collectionID = libraryManager.RegisterCollection(collection); episode.ShowID = show.ID;
} episode.Show = show;
libraryManager.AddShowToCollection(showID, collectionID); episode.SeasonID = season.ID;
episode.Season = season;
IEnumerable<Track> tracks = await _transcoder.GetTrackInfo(episode.Path);
List<Track> epTracks = tracks.Where(x => x.Type != StreamType.Subtitle).Concat(GetExtractedSubtitles(episode)).ToList();
if (epTracks.Count(x => !x.IsExternal) < tracks.Count())
epTracks.AddRange(await _transcoder.ExtractSubtitles(episode.Path));
episode.Tracks = epTracks;
return episode;
} }
IEnumerable<People> actors = await metadataProvider.GetPeople(show, library); private static IEnumerable<Track> GetExtractedSubtitles(Episode episode)
libraryManager.RegisterShowPeople(showID, actors);
}
else
showProviderIDs = libraryManager.GetShowExternalIDs(showID);
return new Show { ID = showID, ExternalIDs = showProviderIDs, Title = showTitle };
}
private async Task<long> RegisterSeason(Show show, long seasonNumber, Library library)
{
if (libraryManager.IsSeasonRegistered(show.ID, seasonNumber, out long seasonID))
return seasonID;
Season season = await metadataProvider.GetSeason(show, seasonNumber, library);
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)
seasonID = await RegisterSeason(show, seasonNumber, library);
Episode episode = await metadataProvider.GetEpisode(show, episodePath, seasonNumber, episodeNumber, absoluteNumber, library);
if (seasonID == -1)
seasonID = await RegisterSeason(show, seasonNumber, library);
episode.SeasonID = seasonID;
episode.ID = libraryManager.RegisterEpisode(episode);
Track[] tracks = await transcoder.GetTrackInfo(episode.Path);
int subcount = 0;
foreach (Track track in tracks)
{
if (track.Type == StreamType.Subtitle)
{
subcount++;
continue;
}
track.EpisodeID = episode.ID;
libraryManager.RegisterTrack(track);
}
if (episode.Path.EndsWith(".mkv") && CountExtractedSubtitles(episode) != subcount)
{
Track[] subtitles = await transcoder.ExtractSubtitles(episode.Path);
if (subtitles != null)
{
foreach (Track track in subtitles)
{
track.EpisodeID = episode.ID;
libraryManager.RegisterTrack(track);
}
}
}
}
private int CountExtractedSubtitles(Episode episode)
{ {
string path = Path.Combine(Path.GetDirectoryName(episode.Path), "Subtitles"); string path = Path.Combine(Path.GetDirectoryName(episode.Path), "Subtitles");
int subcount = 0; List<Track> tracks = new List<Track>();
if (!Directory.Exists(path)) if (!Directory.Exists(path))
return 0; return tracks;
foreach (string sub in Directory.EnumerateFiles(path, "", SearchOption.AllDirectories)) foreach (string sub in Directory.EnumerateFiles(path, "", SearchOption.AllDirectories))
{ {
string episodeLink = Path.GetFileNameWithoutExtension(episode.Path); string episodeLink = Path.GetFileNameWithoutExtension(episode.Path);
@ -236,10 +196,9 @@ namespace Kyoo.Controllers
track.Codec = "subrip"; track.Codec = "subrip";
else else
track.Codec = null; track.Codec = null;
libraryManager.RegisterTrack(track); tracks.Add(track);
subcount++;
} }
return subcount; return tracks;
} }
private static readonly string[] VideoExtensions = { ".webm", ".mkv", ".flv", ".vob", ".ogg", ".ogv", ".avi", ".mts", ".m2ts", ".ts", ".mov", ".qt", ".asf", ".mp4", ".m4p", ".m4v", ".mpg", ".mp2", ".mpeg", ".mpe", ".mpv", ".m2v", ".3gp", ".3g2" }; private static readonly string[] VideoExtensions = { ".webm", ".mkv", ".flv", ".vob", ".ogg", ".ogv", ".avi", ".mts", ".m2ts", ".ts", ".mov", ".qt", ".asf", ".mp4", ".m4p", ".m4v", ".mpg", ".mp2", ".mpeg", ".mpe", ".mpv", ".m2v", ".3gp", ".3g2" };
@ -252,7 +211,7 @@ namespace Kyoo.Controllers
public Task StopAsync() public Task StopAsync()
{ {
cancellation.Cancel(); _cancellation.Cancel();
return null; return null;
} }
} }

View File

@ -1,8 +1,6 @@
using Kyoo.Models; using Kyoo.Models;
using Kyoo.Models.Watch; using Kyoo.Models.Watch;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.SQLite;
using System.Linq; using System.Linq;
namespace Kyoo.Controllers namespace Kyoo.Controllers
@ -10,7 +8,6 @@ namespace Kyoo.Controllers
public class LibraryManager : ILibraryManager public class LibraryManager : ILibraryManager
{ {
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
private readonly SQLiteConnection sqlConnection;
public LibraryManager(DatabaseContext database) public LibraryManager(DatabaseContext database)
@ -63,9 +60,8 @@ namespace Kyoo.Controllers
public IEnumerable<Show> GetShows() public IEnumerable<Show> GetShows()
{ {
return (from show in _database.Shows join link in _database.CollectionLinks on show equals link.Show into gj return (from show in _database.Shows from l in _database.CollectionLinks.DefaultIfEmpty()
from l in gj.DefaultIfEmpty() where l.CollectionID == null select show).AsEnumerable().Union(
where l.CollectionID == null select l.Show).AsEnumerable().Union(
from collection in _database.Collections select collection.AsShow()).OrderBy(x => x.Title); from collection in _database.Collections select collection.AsShow()).OrderBy(x => x.Title);
} }
@ -303,43 +299,9 @@ namespace Kyoo.Controllers
#region Write Into The Database #region Write Into The Database
public long RegisterCollection(Collection collection) public long RegisterCollection(Collection collection)
{ {
// string query = "INSERT INTO collections (slug, name, overview, imgPrimary) VALUES($slug, $name, $overview, $imgPrimary);"; _database.Collections.Add(collection);
// _database.SaveChanges();
// using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) return collection.ID;
// {
// try
// {
// cmd.Parameters.AddWithValue("$slug", collection.Slug);
// cmd.Parameters.AddWithValue("$name", collection.Name);
// cmd.Parameters.AddWithValue("$overview", collection.Overview);
// cmd.Parameters.AddWithValue("$imgPrimary", collection.ImgPrimary);
// cmd.ExecuteNonQuery();
//
// cmd.CommandText = "SELECT LAST_INSERT_ROWID()";
// return (long)cmd.ExecuteScalar();
// }
// catch
// {
// Console.Error.WriteLine("SQL error while trying to create a collection. Collection probably already registered.");
// cmd.CommandText = "SELECT * FROM collections WHERE slug = $slug";
// cmd.Parameters.AddWithValue("$slug", collection.Slug);
// return (long)cmd.ExecuteScalar();
// }
// }
return -1;
}
public void RegisterInLibrary(long showID, Library library)
{
// 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("$libraryID", library.Id);
// cmd.Parameters.AddWithValue("$showID", showID);
// cmd.ExecuteNonQuery();
// }
} }
public long RegisterShow(Show show) public long RegisterShow(Show show)
@ -351,167 +313,54 @@ namespace Kyoo.Controllers
public long RegisterSeason(Season season) public long RegisterSeason(Season season)
{ {
string query = "INSERT INTO seasons (showID, seasonNumber, title, overview, year, imgPrimary, externalIDs) VALUES($showID, $seasonNumber, $title, $overview, $year, $imgPrimary, $externalIDs);"; _database.Seasons.Add(season);
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) _database.SaveChanges();
{ return season.ID;
try
{
cmd.Parameters.AddWithValue("$showID", season.ShowID);
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("$imgPrimary", season.ImgPrimary);
cmd.Parameters.AddWithValue("$externalIDs", season.ExternalIDs);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT LAST_INSERT_ROWID()";
return (long)cmd.ExecuteScalar();
}
catch
{
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);
return (long)cmd.ExecuteScalar();
}
}
} }
public long RegisterEpisode(Episode episode) public long RegisterEpisode(Episode episode)
{ {
string query = "INSERT INTO episodes (showID, seasonID, seasonNumber, episodeNumber, absoluteNumber, path, title, overview, releaseDate, runtime, imgPrimary, externalIDs) VALUES($showID, $seasonID, $seasonNumber, $episodeNumber, $absoluteNumber, $path, $title, $overview, $releaseDate, $runtime, $imgPrimary, $externalIDs);"; _database.Episodes.Add(episode);
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) _database.SaveChanges();
{ return episode.ID;
try
{
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("$path", episode.Path);
cmd.Parameters.AddWithValue("$title", episode.Title);
cmd.Parameters.AddWithValue("$overview", episode.Overview);
cmd.Parameters.AddWithValue("$releaseDate", episode.ReleaseDate);
cmd.Parameters.AddWithValue("$runtime", episode.Runtime);
cmd.Parameters.AddWithValue("$imgPrimary", episode.ImgPrimary);
cmd.Parameters.AddWithValue("$externalIDs", episode.ExternalIDs);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT LAST_INSERT_ROWID()";
return (long)cmd.ExecuteScalar();
}
catch
{
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);
return (long)cmd.ExecuteScalar();
}
}
} }
public void RegisterTrack(Track track) public long RegisterTrack(Track track)
{ {
string query = "INSERT INTO tracks (episodeID, streamType, title, language, codec, isDefault, isForced, isExternal, path) VALUES($episodeID, $streamType, $title, $language, $codec, $isDefault, $isForced, $isExternal, $path);"; _database.Tracks.Add(track);
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) _database.SaveChanges();
{ return track.ID;
cmd.Parameters.AddWithValue("$episodeID", track.EpisodeID);
cmd.Parameters.AddWithValue("$streamType", track.Type);
cmd.Parameters.AddWithValue("$title", track.Title);
cmd.Parameters.AddWithValue("$language", track.Language);
cmd.Parameters.AddWithValue("$codec", track.Codec);
cmd.Parameters.AddWithValue("$isDefault", track.IsDefault);
cmd.Parameters.AddWithValue("$isForced", track.IsForced);
cmd.Parameters.AddWithValue("$isExternal", track.IsExternal);
cmd.Parameters.AddWithValue("$path", track.Path);
cmd.ExecuteNonQuery();
}
} }
public void RegisterShowPeople(long showID, IEnumerable<People> people) public void RegisterShowLinks(Library library, Collection collection, Show show)
{ {
if (people == null) if (collection != null)
return;
string linkQuery = "INSERT INTO peopleLinks (peopleID, showID, role, type) VALUES($peopleID, $showID, $role, $type);";
foreach (People peop in people)
{ {
using (SQLiteCommand cmd = new SQLiteCommand(linkQuery, sqlConnection)) _database.LibraryLinks.Add(new LibraryLink {LibraryID = library.ID, CollectionID = collection.ID});
{ _database.CollectionLinks.Add(new CollectionLink { CollectionID = collection.ID, ShowID = show.ID});
cmd.Parameters.AddWithValue("$peopleID", GetOrCreatePeople(peop));
cmd.Parameters.AddWithValue("$showID", showID);
cmd.Parameters.AddWithValue("$role", peop.Role);
cmd.Parameters.AddWithValue("$type", peop.Type);
cmd.ExecuteNonQuery();
}
}
}
public void AddShowToCollection(long showID, long collectionID)
{
string linkQuery = "INSERT INTO collectionsLinks (collectionID, showID) VALUES($collectionID, $showID);";
using (SQLiteCommand cmd = new SQLiteCommand(linkQuery, sqlConnection))
{
cmd.Parameters.AddWithValue("$collectionID", collectionID);
cmd.Parameters.AddWithValue("$showID", showID);
cmd.ExecuteNonQuery();
} }
_database.LibraryLinks.Add(new LibraryLink {LibraryID = library.ID, ShowID = show.ID});
_database.SaveChanges();
} }
public void RemoveShow(long showID) public void RemoveShow(long showID)
{ {
string query = "DELETE FROM shows WHERE id = $showID;"; _database.Shows.Remove(new Show {ID = showID});
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$showID", showID);
cmd.ExecuteNonQuery();
}
} }
public void RemoveSeason(long showID, long seasonID) public void RemoveSeason(long seasonID)
{ {
string query = "DELETE FROM seasons WHERE id = $seasonID;"; _database.Seasons.Remove(new Season {ID = seasonID});
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$seasonID", seasonID);
cmd.ExecuteNonQuery();
}
if (GetSeasons(showID).Count() == 0)
RemoveShow(showID);
} }
public void RemoveEpisode(Episode episode) public void RemoveEpisode(long episodeID)
{ {
string query = "DELETE FROM episodes WHERE id = $episodeID;"; _database.Episodes.Remove(new Episode {ID = episodeID});
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$episodeID", episode.ID);
cmd.ExecuteNonQuery();
}
if (GetEpisodes(episode.ShowID, episode.SeasonNumber).Count() == 0)
RemoveSeason(episode.ShowID, episode.SeasonID);
} }
public void ClearSubtitles(long episodeID) public void ClearSubtitles(long episodeID)
{ {
string query = "DELETE FROM tracks WHERE episodeID = $episodeID;"; _database.Tracks.RemoveRange(_database.Tracks.Where(x => x.EpisodeID == episodeID));
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$episodeID", episodeID);
cmd.ExecuteNonQuery();
}
} }
#endregion #endregion
} }

View File

@ -31,7 +31,7 @@ namespace Kyoo.Controllers
if (library == null) if (library == null)
return NotFound(); return NotFound();
return _libraryManager.GetShowsInLibrary(library.Id).ToList(); return _libraryManager.GetShowsInLibrary(library.ID).ToList();
} }
} }
} }

View File

@ -23,7 +23,7 @@ namespace Kyoo.Controllers
if (people == null) if (people == null)
return NotFound(); return NotFound();
Collection collection = new Collection(0, people.Slug, people.Name, null, null) Collection collection = new Collection(people.Slug, people.Name, null, null)
{ {
Shows = libraryManager.GetShowsByPeople(people.ID), Shows = libraryManager.GetShowsByPeople(people.ID),
Poster = "peopleimg/" + people.Slug Poster = "peopleimg/" + people.Slug