Solving a bug with images and adding unit tests.

This commit is contained in:
Zoe Roux
2019-10-19 17:30:47 +02:00
parent 0829a7aba0
commit 8b0dca8fbf
18 changed files with 385 additions and 146 deletions
+133 -120
View File
@@ -26,7 +26,7 @@ namespace Kyoo.InternalAPI
this.libraryManager = libraryManager;
this.metadataProvider = metadataProvider;
this.transcoder = transcoder;
config = configuration;
this.config = configuration;
cancellation = new CancellationTokenSource();
}
@@ -39,7 +39,7 @@ namespace Kyoo.InternalAPI
private Task StartAsync(bool watch, CancellationToken cancellationToken)
{
Debug.WriteLine("&Crawler started");
string[] paths = config.GetSection("libraryPaths").Get<string[]>();
IEnumerable<string> paths = libraryManager.GetLibrariesPath();
foreach (string path in paths)
{
@@ -65,71 +65,72 @@ namespace Kyoo.InternalAPI
return;
if (IsVideo(file))
await TryRegisterEpisode(file);
await ExtractEpisodeData(file, folderPath);
}
}
public void Watch(string folderPath, CancellationToken cancellationToken)
{
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 TryRegisterEpisode(string path)
{
if (!libraryManager.IsEpisodeRegistered(path))
//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))
{
string relativePath = episodePath.Substring(libraryPath.Length);
string patern = config.GetValue<string>("regex");
Regex regex = new Regex(patern, RegexOptions.IgnoreCase);
Match match = regex.Match(path);
Match match = regex.Match(relativePath);
string showPath = Path.GetDirectoryName(path);
string showPath = Path.GetDirectoryName(episodePath);
string collectionName = match.Groups["Collection"]?.Value;
string showName = match.Groups["ShowTitle"].Value;
bool seasonSuccess = long.TryParse(match.Groups["Season"].Value, out long seasonNumber);
@@ -143,81 +144,93 @@ namespace Kyoo.InternalAPI
episodeNumber = -1;
regex = new Regex(config.GetValue<string>("absoluteRegex"));
match = regex.Match(path);
match = regex.Match(relativePath);
showName = match.Groups["ShowTitle"].Value;
bool absoluteSucess = long.TryParse(match.Groups["AbsoluteNumber"].Value, out absoluteNumber);
if (!absoluteSucess)
{
Debug.WriteLine("&Couldn't find basic data for the episode (regexs didn't match) at " + path);
Debug.WriteLine("&Couldn't find basic data for the episode (regexs didn't match) at " + episodePath);
return;
}
}
string showProviderIDs;
if (!libraryManager.IsShowRegistered(showPath, out long showID))
{
Show show = await metadataProvider.GetShowFromName(showName, showPath);
showProviderIDs = show.ExternalIDs;
showID = libraryManager.RegisterShow(show);
Show show = await RegisterOrGetShow(collectionName, showName, showPath, libraryPath);
await RegisterEpisode(show, seasonNumber, episodeNumber, absoluteNumber, episodePath);
}
}
if (collectionName != null)
private async Task<Show> RegisterOrGetShow(string collectionName, string showTitle, string showPath, string libraryPath)
{
string showProviderIDs;
if (!libraryManager.IsShowRegistered(showPath, out long showID))
{
Show show = await metadataProvider.GetShowFromName(showTitle, showPath);
showProviderIDs = show.ExternalIDs;
showID = libraryManager.RegisterShow(show);
libraryManager.RegisterInLibrary(showID, libraryPath);
if (collectionName != null)
{
if (!libraryManager.IsCollectionRegistered(Slugifier.ToSlug(collectionName), out long collectionID))
{
if (!libraryManager.IsCollectionRegistered(Slugifier.ToSlug(collectionName), out long collectionID))
Collection collection = await metadataProvider.GetCollectionFromName(collectionName);
collectionID = libraryManager.RegisterCollection(collection);
}
libraryManager.AddShowToCollection(showID, collectionID);
}
List<People> actors = await metadataProvider.GetPeople(show.ExternalIDs);
libraryManager.RegisterShowPeople(showID, actors);
}
else
showProviderIDs = libraryManager.GetShowExternalIDs(showID);
return new Show { id = showID, ExternalIDs = showProviderIDs, Title = showTitle };
}
private async Task RegisterEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber, string episodePath)
{
long seasonID = -1;
if (seasonNumber != -1)
{
if (!libraryManager.IsSeasonRegistered(show.id, seasonNumber, out seasonID))
{
Season season = await metadataProvider.GetSeason(show.Title, seasonNumber);
season.ShowID = show.id;
seasonID = libraryManager.RegisterSeason(season);
}
}
Episode episode = await metadataProvider.GetEpisode(show.ExternalIDs, seasonNumber, episodeNumber, absoluteNumber, episodePath);
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.ShowID = show.id;
seasonID = libraryManager.RegisterSeason(season);
}
}
episode.SeasonID = seasonID;
episode.id = libraryManager.RegisterEpisode(episode);
if (episode.Path.EndsWith(".mkv"))
{
if (!FindExtractedSubtitles(episode))
{
Track[] tracks = transcoder.ExtractSubtitles(episode.Path);
if (tracks != null)
{
foreach (Track track in tracks)
{
Collection collection = await metadataProvider.GetCollectionFromName(collectionName);
collectionID = libraryManager.RegisterCollection(collection);
}
libraryManager.AddShowToCollection(showID, collectionID);
}
List<People> actors = await metadataProvider.GetPeople(show.ExternalIDs);
libraryManager.RegisterShowPeople(showID, actors);
}
else
showProviderIDs = libraryManager.GetShowExternalIDs(showID);
long seasonID = -1;
if (seasonNumber != -1)
{
if (!libraryManager.IsSeasonRegistered(showID, seasonNumber, out seasonID))
{
Season season = await metadataProvider.GetSeason(showName, seasonNumber);
season.ShowID = showID;
seasonID = libraryManager.RegisterSeason(season);
}
}
Episode episode = await metadataProvider.GetEpisode(showProviderIDs, seasonNumber, episodeNumber, absoluteNumber, path);
episode.ShowID = showID;
if (seasonID == -1)
{
if (!libraryManager.IsSeasonRegistered(showID, episode.seasonNumber, out seasonID))
{
Season season = await metadataProvider.GetSeason(showName, episode.seasonNumber);
season.ShowID = showID;
seasonID = libraryManager.RegisterSeason(season);
}
}
episode.SeasonID = seasonID;
long episodeID = libraryManager.RegisterEpisode(episode);
episode.id = episodeID;
if (episode.Path.EndsWith(".mkv"))
{
if (!FindExtractedSubtitles(episode))
{
Track[] tracks = transcoder.ExtractSubtitles(episode.Path);
if (tracks != null)
{
foreach (Track track in tracks)
{
track.episodeID = episode.id;
libraryManager.RegisterTrack(track);
}
track.episodeID = episode.id;
libraryManager.RegisterTrack(track);
}
}
}
@@ -16,6 +16,8 @@ namespace Kyoo.InternalAPI
List<Season> GetSeasons(long showID);
int GetSeasonCount(string showSlug, long seasonNumber);
IEnumerable<Show> GetShowsInCollection(long collectionID);
IEnumerable<Show> GetShowsByPeople(long peopleID);
IEnumerable<string> GetLibrariesPath();
//Internal HTML read
(List<Track> audios, List<Track> subtitles) GetStreams(long episodeID, string showSlug);
@@ -55,6 +57,7 @@ namespace Kyoo.InternalAPI
void RegisterShowPeople(long showID, List<People> actors);
void AddShowToCollection(long showID, long collectionID);
void RegisterInLibrary(long showID, string libraryPath);
void ClearSubtitles(long episodeID);
}
@@ -88,12 +88,13 @@ namespace Kyoo.InternalAPI
CREATE TABLE libraries(
id INTEGER PRIMARY KEY UNIQUE,
slug TEXT UNIQUE,
name TEXT
name TEXT,
path TEXT
);
CREATE TABLE librariesLinks(
librarieID INTEGER,
libraryID INTEGER,
showID INTEGER,
FOREIGN KEY(librarieID) REFERENCES libraries(id),
FOREIGN KEY(libraryID) REFERENCES libraries(id),
FOREIGN KEY(showID) REFERENCES shows(id)
);
@@ -190,6 +191,23 @@ namespace Kyoo.InternalAPI
}
}
public IEnumerable<string> GetLibrariesPath()
{
string query = "SELECT path FROM libraries;";
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
SQLiteDataReader reader = cmd.ExecuteReader();
List<string> libraries = new List<string>();
while (reader.Read())
libraries.Add(reader["path"] as string);
return libraries;
}
}
public string GetShowExternalIDs(long showID)
{
string query = string.Format("SELECT * FROM shows WHERE id = {0};", showID);
@@ -561,6 +579,22 @@ namespace Kyoo.InternalAPI
return shows;
}
}
public IEnumerable<Show> GetShowsByPeople(long peopleID)
{
string query = "SELECT * FROM shows JOIN peopleLinks l ON l.showID = shows.id WHERE l.peopleID = $id;";
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$id", peopleID);
SQLiteDataReader reader = cmd.ExecuteReader();
List<Show> shows = new List<Show>();
while (reader.Read())
shows.Add(Show.FromReader(reader));
return shows;
}
}
#endregion
#region Check if items exists
@@ -726,6 +760,18 @@ namespace Kyoo.InternalAPI
}
}
public void RegisterInLibrary(long showID, string libraryPath)
{
string query = "INSERT INTO librariesLinks (libraryID, showID) SELECT id, $showID FROM libraries WHERE libraries.path = $libraryPath;";
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$libraryPath", libraryPath);
cmd.Parameters.AddWithValue("$showID", showID);
cmd.ExecuteNonQuery();
}
}
public long RegisterShow(Show show)
{
string query = "INSERT INTO shows (slug, title, aliases, path, overview, trailerUrl, startYear, endYear, imgPrimary, imgThumb, imgLogo, imgBackdrop, externalIDs) VALUES($slug, $title, $aliases, $path, $overview, $trailerUrl, $startYear, $endYear, $imgPrimary, $imgThumb, $imgLogo, $imgBackdrop, $externalIDs);";
@@ -120,7 +120,7 @@ namespace Kyoo.InternalAPI
}
Show show = Merge(datas);
return thumbnailsManager.Validate(show);
return await thumbnailsManager.Validate(show);
}
public async Task<Season> GetSeason(string showName, long seasonNumber)
@@ -151,13 +151,13 @@ namespace Kyoo.InternalAPI
Episode episode = Merge(datas);
episode.Path = episodePath;
return thumbnailsManager.Validate(episode);
return await thumbnailsManager.Validate(episode);
}
public async Task<List<People>> GetPeople(string id)
{
List<People> actors = await providers[0].GetPeople(id);
return thumbnailsManager.Validate(actors);
return await thumbnailsManager.Validate(actors);
}
}
}
@@ -1,12 +1,13 @@
using Kyoo.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Kyoo.InternalAPI.ThumbnailsManager
{
public interface IThumbnailsManager
{
Show Validate(Show show);
List<People> Validate(List<People> actors);
Episode Validate(Episode episode);
Task<Show> Validate(Show show);
Task<List<People>> Validate(List<People> actors);
Task<Episode> Validate(Episode episode);
}
}
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace Kyoo.InternalAPI.ThumbnailsManager
{
@@ -17,7 +18,7 @@ namespace Kyoo.InternalAPI.ThumbnailsManager
config = configuration;
}
public Show Validate(Show show)
public async Task<Show> Validate(Show show)
{
string localThumb = Path.Combine(show.Path, "poster.jpg");
string localLogo = Path.Combine(show.Path, "logo.png");
@@ -30,7 +31,7 @@ namespace Kyoo.InternalAPI.ThumbnailsManager
{
using (WebClient client = new WebClient())
{
client.DownloadFileAsync(new Uri(show.ImgPrimary), localThumb);
await client.DownloadFileTaskAsync(new Uri(show.ImgPrimary), localThumb);
}
}
}
@@ -41,7 +42,7 @@ namespace Kyoo.InternalAPI.ThumbnailsManager
{
using (WebClient client = new WebClient())
{
client.DownloadFileAsync(new Uri(show.ImgLogo), localLogo);
await client.DownloadFileTaskAsync(new Uri(show.ImgLogo), localLogo);
}
}
}
@@ -52,7 +53,7 @@ namespace Kyoo.InternalAPI.ThumbnailsManager
{
using (WebClient client = new WebClient())
{
client.DownloadFileAsync(new Uri(show.ImgBackdrop), localBackdrop);
await client.DownloadFileTaskAsync(new Uri(show.ImgBackdrop), localBackdrop);
}
}
}
@@ -60,7 +61,7 @@ namespace Kyoo.InternalAPI.ThumbnailsManager
return show;
}
public List<People> Validate(List<People> people)
public async Task<List<People>> Validate(List<People> people)
{
for (int i = 0; i < people?.Count; i++)
{
@@ -73,7 +74,7 @@ namespace Kyoo.InternalAPI.ThumbnailsManager
using (WebClient client = new WebClient())
{
Debug.WriteLine("&" + localThumb);
client.DownloadFileAsync(new Uri(people[i].imgPrimary), localThumb);
await client.DownloadFileTaskAsync(new Uri(people[i].imgPrimary), localThumb);
}
}
}
@@ -81,7 +82,7 @@ namespace Kyoo.InternalAPI.ThumbnailsManager
return people;
}
public Episode Validate(Episode episode)
public async Task<Episode> Validate(Episode episode)
{
//string localThumb = Path.ChangeExtension(episode.Path, "jpg");
string localThumb = episode.Path.Replace(Path.GetExtension(episode.Path), "-thumb.jpg");
@@ -89,7 +90,7 @@ namespace Kyoo.InternalAPI.ThumbnailsManager
{
using (WebClient client = new WebClient())
{
client.DownloadFileAsync(new Uri(episode.ImgPrimary), localThumb);
await client.DownloadFileTaskAsync(new Uri(episode.ImgPrimary), localThumb);
}
}