mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-08 18:54:22 -04:00
Solving a bug with images and adding unit tests.
This commit is contained in:
parent
0829a7aba0
commit
8b0dca8fbf
14
Kyoo.sln
14
Kyoo.sln
@ -10,6 +10,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kyoo", "Kyoo\Kyoo.csproj",
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Kyoo.Transcoder", "Kyoo.Transcoder\Kyoo.Transcoder.vcxproj", "{E5EFA4B2-F09D-4C4F-83DD-A436CD60BB77}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unit Tests", "Unit Tests\Unit Tests.csproj", "{CC8144B5-8868-4EA7-B171-4E47746ED003}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -42,6 +44,18 @@ Global
|
||||
{E5EFA4B2-F09D-4C4F-83DD-A436CD60BB77}.Release|x64.Build.0 = Release|x64
|
||||
{E5EFA4B2-F09D-4C4F-83DD-A436CD60BB77}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E5EFA4B2-F09D-4C4F-83DD-A436CD60BB77}.Release|x86.Build.0 = Release|Win32
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CC8144B5-8868-4EA7-B171-4E47746ED003}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -10,13 +10,15 @@ import { PlayerComponent } from "./player/player.component";
|
||||
import { StreamResolverService } from "./services/stream-resolver.service";
|
||||
import { CollectionComponent } from "./collection/collection.component";
|
||||
import { CollectionResolverService } from "./services/collection-resolver.service";
|
||||
import { PeopleResolverService } from "./services/people-resolver.service";
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: "browse", component: BrowseComponent, pathMatch: "full", resolve: { shows: LibraryResolverService } },
|
||||
{ path: "browse/:library-slug", component: BrowseComponent, resolve: { shows: LibraryResolverService } },
|
||||
{ path: "show/:show-slug", component: ShowDetailsComponent, resolve: { show: ShowResolverService } },
|
||||
{ path: "collection/:collection-slug", component: CollectionComponent, resolve: { collection: CollectionResolverService } },
|
||||
{ path: "collection/:collection-slug", component: CollectionComponent, resolve: { collection: CollectionResolverService } },
|
||||
{ path: "people/:people-slug", component: CollectionComponent, resolve: { collection: PeopleResolverService } },
|
||||
{ path: "watch/:item", component: PlayerComponent, resolve: { item: StreamResolverService } },
|
||||
{ path: "**", component: NotFoundComponent }
|
||||
];
|
||||
|
34
Kyoo/ClientApp/src/app/services/people-resolver.service.ts
Normal file
34
Kyoo/ClientApp/src/app/services/people-resolver.service.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
|
||||
import { EMPTY, Observable } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { Collection } from "../../models/collection";
|
||||
import { People } from "../../models/people";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PeopleResolverService implements Resolve<Collection>
|
||||
{
|
||||
constructor(private http: HttpClient, private snackBar: MatSnackBar) { }
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot): Collection | Observable<Collection> | Promise<Collection>
|
||||
{
|
||||
let people: string = route.paramMap.get("people-slug");
|
||||
return this.http.get<Collection>("api/people/" + people).pipe(catchError((error: HttpErrorResponse) =>
|
||||
{
|
||||
console.log(error.status + " - " + error.message);
|
||||
if (error.status == 404)
|
||||
{
|
||||
this.snackBar.open("People \"" + people + "\" not found.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||
}
|
||||
else
|
||||
{
|
||||
this.snackBar.open("An unknow error occured.", null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
|
||||
}
|
||||
return EMPTY;
|
||||
}));
|
||||
}
|
||||
}
|
36
Kyoo/Controllers/PeopleController.cs
Normal file
36
Kyoo/Controllers/PeopleController.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using Kyoo.InternalAPI;
|
||||
using Kyoo.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class PeopleController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager libraryManager;
|
||||
|
||||
public PeopleController(ILibraryManager libraryManager)
|
||||
{
|
||||
this.libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet("{people-slug}")]
|
||||
public ActionResult<Collection> GetPeople(string slug)
|
||||
{
|
||||
People people = libraryManager.GetPeopleBySlug(slug);
|
||||
|
||||
//This always return not found
|
||||
if (people == null)
|
||||
return NotFound();
|
||||
|
||||
Debug.WriteLine("&People: " + people.Name);
|
||||
Collection collection = new Collection(0, people.slug, people.Name, null, null)
|
||||
{
|
||||
Shows = libraryManager.GetShowsByPeople(people.id)
|
||||
};
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.9" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.10" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
<PackageReference Include="System.Data.SQLite" Version="1.0.111" />
|
||||
</ItemGroup>
|
||||
|
@ -7,19 +7,22 @@ namespace Kyoo.Models
|
||||
[JsonIgnore] public readonly long id;
|
||||
public string Slug;
|
||||
public string Name;
|
||||
public string Path;
|
||||
|
||||
public Library(long id, string slug, string name)
|
||||
public Library(long id, string slug, string name, string path)
|
||||
{
|
||||
this.id = id;
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
Path = path;
|
||||
}
|
||||
|
||||
public static Library FromReader(System.Data.SQLite.SQLiteDataReader reader)
|
||||
{
|
||||
return new Library((long)reader["id"],
|
||||
reader["slug"] as string,
|
||||
reader["name"] as string);
|
||||
reader["name"] as string,
|
||||
reader["path"] as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ namespace Kyoo.Models
|
||||
{
|
||||
public class Show
|
||||
{
|
||||
[JsonIgnore] public readonly long id = -1;
|
||||
[JsonIgnore] public long id = -1;
|
||||
|
||||
public string Slug;
|
||||
public string Title;
|
||||
|
Binary file not shown.
@ -13,9 +13,6 @@
|
||||
"peoplePath": "D:\\\\Videos\\People",
|
||||
"plugins": "C:\\Projects\\Kyoo\\Debug",
|
||||
"providerPlugins": "C://Projects/Plugins/Providers",
|
||||
"libraryPaths": [
|
||||
"\\\\sdg\\video\\Anime"
|
||||
],
|
||||
"regex": ".*\\\\(?<Collection>.+?)?\\\\.*\\\\(?<ShowTitle>.+?) S(?<Season>\\d+)E(?<Episode>\\d+)",
|
||||
"regex": "^(\\\\(?<Collection>.+?))?\\\\.*\\\\(?<ShowTitle>.+?) S(?<Season>\\d+)E(?<Episode>\\d+)",
|
||||
"absoluteRegex": ".*\\\\(?<ShowTitle>.+?) (?<AbsoluteNumber>\\d+)"
|
||||
}
|
||||
|
42
Unit Tests/Kyoo-InternalAPI/Thumbnails-Tests.cs
Normal file
42
Unit Tests/Kyoo-InternalAPI/Thumbnails-Tests.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using Kyoo;
|
||||
using Kyoo.InternalAPI;
|
||||
using Kyoo.InternalAPI.ThumbnailsManager;
|
||||
using Kyoo.Models;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using NUnit.Framework;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace UnitTests.Kyoo_InternalAPI
|
||||
{
|
||||
public class Tests
|
||||
{
|
||||
private IConfiguration config;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
config = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DownloadShowImages()
|
||||
{
|
||||
LibraryManager library = new LibraryManager(config);
|
||||
ThumbnailsManager manager = new ThumbnailsManager(config);
|
||||
Show show = library.GetShowBySlug(library.QueryShows(null).FirstOrDefault().Slug);
|
||||
Debug.WriteLine("&Show: " + show.Path);
|
||||
string posterPath = Path.Combine(show.Path, "poster.jpg");
|
||||
File.Delete(posterPath);
|
||||
|
||||
await manager.Validate(show);
|
||||
long posterLength = new FileInfo(posterPath).Length;
|
||||
Assert.IsTrue(posterLength > 0, "Poster size is zero for the tested show (" + posterPath + ")");
|
||||
}
|
||||
}
|
||||
}
|
29
Unit Tests/Unit Tests.csproj
Normal file
29
Unit Tests/Unit Tests.csproj
Normal file
@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<RootNamespace>UnitTests</RootNamespace>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<AssemblyName>UnitTests</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.0.0" />
|
||||
<PackageReference Include="nunit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Kyoo\Kyoo.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
18
Unit Tests/appsettings.json
Normal file
18
Unit Tests/appsettings.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"server.urls": "http://0.0.0.0:5000",
|
||||
"https_port": 44300,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
|
||||
"databasePath": "C://Projects/database.db",
|
||||
"tempPath": "C:\\\\Projects\\temp",
|
||||
"peoplePath": "D:\\\\Videos\\People",
|
||||
"plugins": "C:\\Projects\\Kyoo\\Debug",
|
||||
"providerPlugins": "C://Projects/Plugins/Providers",
|
||||
"regex": "^(\\\\(?<Collection>.+?))?\\\\.*\\\\(?<ShowTitle>.+?) S(?<Season>\\d+)E(?<Episode>\\d+)",
|
||||
"absoluteRegex": ".*\\\\(?<ShowTitle>.+?) (?<AbsoluteNumber>\\d+)"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user