Adding collection support, only need to make the component for the visual interface.

This commit is contained in:
Zoe Roux
2019-10-07 00:13:26 +02:00
parent 725c6c4b88
commit 5940ccfc9d
15 changed files with 170 additions and 134 deletions
+18 -6
View File
@@ -1,4 +1,5 @@
using Kyoo.Models;
using Kyoo.InternalAPI.Utility;
using Kyoo.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System.Collections.Generic;
@@ -15,17 +16,17 @@ namespace Kyoo.InternalAPI
{
private readonly CancellationTokenSource cancellation;
private readonly IConfiguration config;
private readonly ILibraryManager libraryManager;
private readonly IMetadataProvider metadataProvider;
private readonly ITranscoder transcoder;
private readonly IConfiguration config;
public Crawler(IConfiguration configuration, ILibraryManager libraryManager, IMetadataProvider metadataProvider, ITranscoder transcoder)
public Crawler(ILibraryManager libraryManager, IMetadataProvider metadataProvider, ITranscoder transcoder, IConfiguration configuration)
{
config = configuration;
this.libraryManager = libraryManager;
this.metadataProvider = metadataProvider;
this.transcoder = transcoder;
config = configuration;
cancellation = new CancellationTokenSource();
}
@@ -129,12 +130,13 @@ namespace Kyoo.InternalAPI
Match match = regex.Match(path);
string showPath = Path.GetDirectoryName(path);
string collectionName = match.Groups["Collection"]?.Value;
string showName = match.Groups["ShowTitle"].Value;
bool seasonSuccess = long.TryParse(match.Groups["Season"].Value, out long seasonNumber);
bool episodeSucess = long.TryParse(match.Groups["Episode"].Value, out long episodeNumber);
long absoluteNumber = -1;
if(!seasonSuccess || !episodeSucess)
if (!seasonSuccess || !episodeSucess)
{
//Considering that the episode is using absolute path.
seasonNumber = -1;
@@ -160,6 +162,16 @@ namespace Kyoo.InternalAPI
showProviderIDs = show.ExternalIDs;
showID = libraryManager.RegisterShow(show);
if (collectionName != null)
{
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);
}
@@ -180,7 +192,7 @@ namespace Kyoo.InternalAPI
Episode episode = await metadataProvider.GetEpisode(showProviderIDs, seasonNumber, episodeNumber, absoluteNumber, path);
episode.ShowID = showID;
if(seasonID == -1)
if (seasonID == -1)
{
if (!libraryManager.IsSeasonRegistered(showID, episode.seasonNumber, out seasonID))
{
@@ -35,6 +35,8 @@ namespace Kyoo.InternalAPI
Collection GetCollection(string slug);
//Check if value exists
bool IsCollectionRegistered(string collectionSlug);
bool IsCollectionRegistered(string collectionSlug, out long collectionID);
bool IsShowRegistered(string showPath);
bool IsShowRegistered(string showPath, out long showID);
bool IsSeasonRegistered(long showID, long seasonNumber);
@@ -52,6 +54,7 @@ namespace Kyoo.InternalAPI
long GetOrCreateStudio(Studio studio);
void RegisterShowPeople(long showID, List<People> actors);
void AddShowToCollection(long showID, long collectionID);
void ClearSubtitles(long episodeID);
}
@@ -102,6 +102,8 @@ namespace Kyoo.InternalAPI
slug TEXT UNIQUE,
name TEXT,
overview TEXT,
starYear INTEGER,
endYear INTEGER,
imgPrimary TEXT
);
CREATE TABLE collectionsLinks(
@@ -253,19 +255,17 @@ namespace Kyoo.InternalAPI
public IEnumerable<Show> QueryShows(string selection)
{
string query = "SELECT * FROM shows ORDER BY title;";
List<Show> shows = new List<Show>();
SQLiteDataReader reader;
string query = "SELECT slug, title, startYear, endYear, '0' FROM shows LEFT JOIN collectionsLinks l ON l.showID = shows.id WHERE l.showID IS NULL UNION SELECT slug, name, startYear, endYear, '1' FROM collections ORDER BY title;";
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
SQLiteDataReader reader = cmd.ExecuteReader();
List<Show> shows = new List<Show>();
reader = cmd.ExecuteReader();
while (reader.Read())
shows.Add(Show.FromReader(reader));
return shows;
shows.Add(Show.FromQueryReader(reader));
}
return shows;
}
public Show GetShowBySlug(string slug)
@@ -564,6 +564,31 @@ namespace Kyoo.InternalAPI
#endregion
#region Check if items exists
public bool IsCollectionRegistered(string collectionSlug)
{
string query = "SELECT (id) FROM collections WHERE slug = $slug;";
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$slug", collectionSlug);
return cmd.ExecuteScalar() != null;
}
}
public bool IsCollectionRegistered(string collectionSlug, out long collectionID)
{
string query = "SELECT (id) FROM collections WHERE slug = $slug;";
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$slug", collectionSlug);
collectionID = cmd.ExecuteScalar() as long? ?? -1;
return collectionID != -1;
}
}
public bool IsShowRegistered(string showPath)
{
string query = "SELECT (id) FROM shows WHERE path = $path;";
@@ -831,6 +856,18 @@ namespace Kyoo.InternalAPI
}
}
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();
}
}
public void ClearSubtitles(long episodeID)
{
string query = "DELETE FROM tracks WHERE episodeID = $episodeID;";
@@ -6,6 +6,9 @@ namespace Kyoo.InternalAPI
{
public interface IMetadataProvider
{
//For the collection
Task<Collection> GetCollectionFromName(string name);
//For the show
Task<Show> GetShowByID(string id);
Task<Show> GetShowFromName(string showName, string showPath);
@@ -1,10 +1,8 @@
using Kyoo.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
@@ -1,6 +1,8 @@
using Kyoo.InternalAPI.MetadataProvider.TheTvDB;
using Kyoo.InternalAPI.Utility;
using Kyoo.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -16,74 +18,13 @@ namespace Kyoo.InternalAPI.MetadataProvider
[MetaProvider]
public class ProviderTheTvDB : HelperTvDB, IMetadataProvider
{
private struct SearchTbDB
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
public async Task<Collection> GetCollectionFromName(string name)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{
public string seriesName;
public string overview;
public string slug;
public string network;
public string status;
public int id;
public string firstAired;
public string banner;
public string[] aliases;
return new Collection(-1, Slugifier.ToSlug(name), name, null, null);
}
private struct DataTvDb
{
public string seriesName;
public string overview;
public string slug;
public string network;
public string status;
public int id;
public string seriesId;
public string imdbId;
public string zap2itId;
public string firstAired;
public string banner;
public string[] aliases;
public string[] genre;
public string added;
public string airsDayOfWeek;
public string airsTime;
public string lastUpdated;
public string runtime;
public string networkId;
public string rating;
public float siteRating;
public int siteRatingCount;
}
private struct RatingInfo
{
public float average;
public int count;
}
private struct ImageTvDb
{
public string fileName;
public int id;
public string keyType;
public int languageId;
public RatingInfo ratingsInfo;
public string resolution;
public string subKey;
public string thumbnail;
}
private struct ErrorsTvDB
{
public string[] invalidFilters;
public string invalidLanguage;
public string[] invalidQueryParams;
}
public async Task<Show> GetShowFromName(string showName, string showPath)
{
string token = await Authentificate();
@@ -109,21 +50,21 @@ namespace Kyoo.InternalAPI.MetadataProvider
stream.Close();
response.Close();
var model = new { data = new SearchTbDB[0] };
SearchTbDB data = JsonConvert.DeserializeAnonymousType(content, model).data[0];
dynamic obj = JsonConvert.DeserializeObject(content);
dynamic data = obj.data[0];
Show show = new Show(-1,
ToSlug(showName),
data.seriesName,
data.aliases,
(string)data.seriesName,
((JArray)data.aliases).ToObject<IEnumerable<string>>(),
showPath,
data.overview,
(string)data.overview,
null, //trailer
null, //genres (no info with this request)
GetStatus(data.status),
GetYear(data.firstAired),
GetStatus((string)data.status),
GetYear((string)data.firstAired),
null, //endYear
string.Format("{0}={1}|", Provider, data.id));
string.Format("{0}={1}|", Provider, (string)data.id));
return (await GetShowByID(GetID(show.ExternalIDs))).Set(show.Slug, show.Path) ?? show;
}
}
@@ -168,19 +109,19 @@ namespace Kyoo.InternalAPI.MetadataProvider
stream.Close();
response.Close();
var model = new { data = new DataTvDb(), errors = new ErrorsTvDB() };
DataTvDb data = JsonConvert.DeserializeAnonymousType(content, model).data;
dynamic model = JsonConvert.DeserializeObject(content);
dynamic data = model.data;
Show show = new Show(-1,
null, //Slug
data.seriesName,
data.aliases,
(string)data.seriesName,
((JArray)data.aliases).ToObject<IEnumerable<string>>(),
null, //Path
data.overview,
(string)data.overview,
null, //Trailer
GetGenres(data.genre),
GetStatus(data.status),
GetYear(data.firstAired),
GetGenres(((JArray)data.genre).ToObject<string[]>()),
GetStatus((string)data.status),
GetYear((string)data.firstAired),
null, //endYear
string.Format("TvDB={0}|", id));
await GetImages(show);
@@ -237,10 +178,9 @@ namespace Kyoo.InternalAPI.MetadataProvider
stream.Close();
response.Close();
var model = new { data = new ImageTvDb[0], error = new ErrorsTvDB() };
dynamic model = JsonConvert.DeserializeObject(content);
//Should implement language selection here
ImageTvDb data = JsonConvert.DeserializeAnonymousType(content, model).data.OrderByDescending(x => x.ratingsInfo.average).ThenByDescending(x => x.ratingsInfo.count).FirstOrDefault();
IEnumerable<ImageTvDb> datas = JsonConvert.DeserializeAnonymousType(content, model).data.OrderByDescending(x => x.ratingsInfo.average).ThenByDescending(x => x.ratingsInfo.count);
dynamic data = ((IEnumerable<dynamic>)model.data).OrderByDescending(x => x.ratingsInfo.average).ThenByDescending(x => x.ratingsInfo.count).FirstOrDefault();
SetImage(show, "https://www.thetvdb.com/banners/" + data.fileName, type.Key);
}
}
@@ -1,14 +1,13 @@
using Kyoo.Models;
using Kyoo.InternalAPI.Utility;
using Kyoo.Models;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Kyoo.InternalAPI.MetadataProvider
{
public abstract class ProviderHelper
{
public abstract string Provider { get; }
public string GetID(string externalIDs)
{
if (externalIDs?.Contains(Provider) == true)
@@ -22,29 +21,7 @@ namespace Kyoo.InternalAPI.MetadataProvider
public string ToSlug(string showTitle)
{
if (showTitle == null)
return null;
//First to lower case
showTitle = showTitle.ToLowerInvariant();
//Remove all accents
//var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(showTitle);
//showTitle = Encoding.ASCII.GetString(bytes);
//Replace spaces
showTitle = Regex.Replace(showTitle, @"\s", "-", RegexOptions.Compiled);
//Remove invalid chars
showTitle = Regex.Replace(showTitle, @"[^\w\s\p{Pd}]", "", RegexOptions.Compiled);
//Trim dashes from end
showTitle = showTitle.Trim('-', '_');
//Replace double occurences of - or \_
showTitle = Regex.Replace(showTitle, @"([-_]){2,}", "$1", RegexOptions.Compiled);
return showTitle;
return Slugifier.ToSlug(showTitle);
}
public enum ImageType { Poster, Background, Thumbnail, Logo }
@@ -79,6 +79,11 @@ namespace Kyoo.InternalAPI
//For all the following methods, it should use all providers and merge the data.
public Task<Collection> GetCollectionFromName(string name)
{
return providers[0].GetCollectionFromName(name);
}
public Task<Show> GetImages(Show show)
{
return providers[0].GetImages(show);
+34
View File
@@ -0,0 +1,34 @@
using System.Text.RegularExpressions;
namespace Kyoo.InternalAPI.Utility
{
public class Slugifier
{
public static string ToSlug(string showTitle)
{
if (showTitle == null)
return null;
//First to lower case
showTitle = showTitle.ToLowerInvariant();
//Remove all accents
//var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(showTitle);
//showTitle = Encoding.ASCII.GetString(bytes);
//Replace spaces
showTitle = Regex.Replace(showTitle, @"\s", "-", RegexOptions.Compiled);
//Remove invalid chars
showTitle = Regex.Replace(showTitle, @"[^\w\s\p{Pd}]", "", RegexOptions.Compiled);
//Trim dashes from end
showTitle = showTitle.Trim('-', '_');
//Replace double occurences of - or \_
showTitle = Regex.Replace(showTitle, @"([-_]){2,}", "$1", RegexOptions.Compiled);
return showTitle;
}
}
}