mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Cleaning up
This commit is contained in:
parent
8c8db5e9b6
commit
253b8561bc
@ -3,8 +3,8 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public interface ICrawler
|
||||
{
|
||||
Task StartAsync(CancellationToken cancellationToken);
|
||||
}
|
||||
public interface ICrawler
|
||||
{
|
||||
Task StartAsync(CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
@ -4,63 +4,63 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public interface ILibraryManager
|
||||
{
|
||||
//Read values
|
||||
string GetShowExternalIDs(long showID);
|
||||
Studio GetStudio(long showID);
|
||||
IEnumerable<PeopleLink> GetPeople(long showID);
|
||||
IEnumerable<Genre> GetGenreForShow(long showID);
|
||||
IEnumerable<Season> GetSeasons(long showID);
|
||||
int GetSeasonCount(string showSlug, long seasonNumber);
|
||||
IEnumerable<Show> GetShowsInCollection(long collectionID);
|
||||
IEnumerable<Show> GetShowsInLibrary(long libraryID);
|
||||
IEnumerable<Show> GetShowsByPeople(string peopleSlug);
|
||||
IEnumerable<string> GetLibrariesPath();
|
||||
public interface ILibraryManager
|
||||
{
|
||||
//Read values
|
||||
string GetShowExternalIDs(long showID);
|
||||
Studio GetStudio(long showID);
|
||||
IEnumerable<PeopleLink> GetPeople(long showID);
|
||||
IEnumerable<Genre> GetGenreForShow(long showID);
|
||||
IEnumerable<Season> GetSeasons(long showID);
|
||||
int GetSeasonCount(string showSlug, long seasonNumber);
|
||||
IEnumerable<Show> GetShowsInCollection(long collectionID);
|
||||
IEnumerable<Show> GetShowsInLibrary(long libraryID);
|
||||
IEnumerable<Show> GetShowsByPeople(string peopleSlug);
|
||||
IEnumerable<string> GetLibrariesPath();
|
||||
|
||||
//Internal read
|
||||
(Track video, IEnumerable<Track> audios, IEnumerable<Track> subtitles) GetStreams(long episodeID, string showSlug);
|
||||
Track GetSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag, bool forced);
|
||||
//Internal read
|
||||
(Track video, IEnumerable<Track> audios, IEnumerable<Track> subtitles) GetStreams(long episodeID, string showSlug);
|
||||
Track GetSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag, bool forced);
|
||||
|
||||
//Public read
|
||||
IEnumerable<Show> GetShows();
|
||||
IEnumerable<Show> GetShows(string searchQuery);
|
||||
Library GetLibrary(string librarySlug);
|
||||
IEnumerable<Library> GetLibraries();
|
||||
Show GetShowBySlug(string slug);
|
||||
Show GetShow(string path);
|
||||
Season GetSeason(string showSlug, long seasonNumber);
|
||||
IEnumerable<Episode> GetEpisodes(string showSlug);
|
||||
IEnumerable<Episode> GetEpisodes(string showSlug, long seasonNumber);
|
||||
Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber);
|
||||
WatchItem GetWatchItem(string showSlug, long seasonNumber, long episodeNumber, bool complete = true);
|
||||
People GetPeopleBySlug(string slug);
|
||||
Genre GetGenreBySlug(string slug);
|
||||
Studio GetStudioBySlug(string slug);
|
||||
Collection GetCollection(string slug);
|
||||
IEnumerable<Episode> GetAllEpisodes();
|
||||
IEnumerable<Episode> SearchEpisodes(string searchQuery);
|
||||
IEnumerable<People> SearchPeople(string searchQuery);
|
||||
IEnumerable<Genre> SearchGenres(string searchQuery);
|
||||
IEnumerable<Studio> SearchStudios(string searchQuery);
|
||||
//Public read
|
||||
IEnumerable<Show> GetShows();
|
||||
IEnumerable<Show> GetShows(string searchQuery);
|
||||
Library GetLibrary(string librarySlug);
|
||||
IEnumerable<Library> GetLibraries();
|
||||
Show GetShowBySlug(string slug);
|
||||
Show GetShow(string path);
|
||||
Season GetSeason(string showSlug, long seasonNumber);
|
||||
IEnumerable<Episode> GetEpisodes(string showSlug);
|
||||
IEnumerable<Episode> GetEpisodes(string showSlug, long seasonNumber);
|
||||
Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber);
|
||||
WatchItem GetWatchItem(string showSlug, long seasonNumber, long episodeNumber, bool complete = true);
|
||||
People GetPeopleBySlug(string slug);
|
||||
Genre GetGenreBySlug(string slug);
|
||||
Studio GetStudioBySlug(string slug);
|
||||
Collection GetCollection(string slug);
|
||||
IEnumerable<Episode> GetAllEpisodes();
|
||||
IEnumerable<Episode> SearchEpisodes(string searchQuery);
|
||||
IEnumerable<People> SearchPeople(string searchQuery);
|
||||
IEnumerable<Genre> SearchGenres(string searchQuery);
|
||||
IEnumerable<Studio> SearchStudios(string searchQuery);
|
||||
|
||||
//Check if value exists
|
||||
bool IsCollectionRegistered(string collectionSlug, out long collectionID);
|
||||
bool IsShowRegistered(string showPath, out long showID);
|
||||
bool IsSeasonRegistered(long showID, long seasonNumber, out long seasonID);
|
||||
bool IsEpisodeRegistered(string episodePath, out long episodeID);
|
||||
//Check if value exists
|
||||
bool IsCollectionRegistered(string collectionSlug, out long collectionID);
|
||||
bool IsShowRegistered(string showPath, out long showID);
|
||||
bool IsSeasonRegistered(long showID, long seasonNumber, out long seasonID);
|
||||
bool IsEpisodeRegistered(string episodePath, out long episodeID);
|
||||
|
||||
//Register values
|
||||
long RegisterCollection(Collection collection);
|
||||
long RegisterShow(Show show);
|
||||
long RegisterSeason(Season season);
|
||||
long RegisterEpisode(Episode episode);
|
||||
long RegisterTrack(Track track);
|
||||
void RegisterShowLinks(Library library, Collection collection, Show show);
|
||||
//Register values
|
||||
long RegisterCollection(Collection collection);
|
||||
long RegisterShow(Show show);
|
||||
long RegisterSeason(Season season);
|
||||
long RegisterEpisode(Episode episode);
|
||||
long RegisterTrack(Track track);
|
||||
void RegisterShowLinks(Library library, Collection collection, Show show);
|
||||
|
||||
void RemoveShow(long showID);
|
||||
void RemoveSeason(long seasonID);
|
||||
void RemoveEpisode(long episodeID);
|
||||
void ClearSubtitles(long episodeID);
|
||||
}
|
||||
void RemoveShow(long showID);
|
||||
void RemoveSeason(long seasonID);
|
||||
void RemoveEpisode(long episodeID);
|
||||
void ClearSubtitles(long episodeID);
|
||||
}
|
||||
}
|
||||
|
@ -4,22 +4,22 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public interface IMetadataProvider
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
//For the collection
|
||||
Task<Collection> GetCollectionFromName(string name);
|
||||
public interface IMetadataProvider
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
//For the collection
|
||||
Task<Collection> GetCollectionFromName(string name);
|
||||
|
||||
//For the show
|
||||
Task<Show> GetShowByID(Show show);
|
||||
Task<Show> GetShowFromName(string showName, bool isMovie);
|
||||
Task<IEnumerable<PeopleLink>> GetPeople(Show show);
|
||||
//For the show
|
||||
Task<Show> GetShowByID(Show show);
|
||||
Task<Show> GetShowFromName(string showName, bool isMovie);
|
||||
Task<IEnumerable<PeopleLink>> GetPeople(Show show);
|
||||
|
||||
//For the seasons
|
||||
Task<Season> GetSeason(Show show, long seasonNumber);
|
||||
//For the seasons
|
||||
Task<Season> GetSeason(Show show, long seasonNumber);
|
||||
|
||||
//For the episodes
|
||||
Task<Episode> GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber);
|
||||
}
|
||||
//For the episodes
|
||||
Task<Episode> GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber);
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,10 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public interface IThumbnailsManager
|
||||
{
|
||||
Task<Show> Validate(Show show);
|
||||
Task<IEnumerable<PeopleLink>> Validate(List<PeopleLink> actors);
|
||||
Task<Episode> Validate(Episode episode);
|
||||
}
|
||||
public interface IThumbnailsManager
|
||||
{
|
||||
Task<Show> Validate(Show show);
|
||||
Task<IEnumerable<PeopleLink>> Validate(List<PeopleLink> actors);
|
||||
Task<Episode> Validate(Episode episode);
|
||||
}
|
||||
}
|
||||
|
@ -4,18 +4,18 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public interface ITranscoder
|
||||
{
|
||||
// Should transcode to a mp4 container (same video/audio format if possible, no subtitles).
|
||||
Task<string> Transmux(WatchItem episode);
|
||||
public interface ITranscoder
|
||||
{
|
||||
// Should transcode to a mp4 container (same video/audio format if possible, no subtitles).
|
||||
Task<string> Transmux(WatchItem episode);
|
||||
|
||||
// Should transcode to a mp4 container with a h264 video format and a AAC audio format, no subtitles.
|
||||
Task<string> Transcode(WatchItem episode);
|
||||
// Should transcode to a mp4 container with a h264 video format and a AAC audio format, no subtitles.
|
||||
Task<string> Transcode(WatchItem episode);
|
||||
|
||||
// Get video and audio tracks infos (codec, name, language...)
|
||||
Task<Track[]> GetTrackInfo(string path);
|
||||
// Get video and audio tracks infos (codec, name, language...)
|
||||
Task<Track[]> GetTrackInfo(string path);
|
||||
|
||||
// Extract all subtitles of a video and save them in the subtitles sub-folder.
|
||||
Task<Track[]> ExtractSubtitles(string path);
|
||||
}
|
||||
// Extract all subtitles of a video and save them in the subtitles sub-folder.
|
||||
Task<Track[]> ExtractSubtitles(string path);
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Title>Kyoo.Common</Title>
|
||||
<Authors>Anonymus Raccoon</Authors>
|
||||
<Description>Base package to create plugins for Kyoo.</Description>
|
||||
<PackageProjectUrl>https://github.com/AnonymusRaccoon/Kyoo</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/AnonymusRaccoon/Kyoo</RepositoryUrl>
|
||||
<Company>SDG</Company>
|
||||
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<PackageVersion>1.0.11</PackageVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Title>Kyoo.Common</Title>
|
||||
<Authors>Anonymus Raccoon</Authors>
|
||||
<Description>Base package to create plugins for Kyoo.</Description>
|
||||
<PackageProjectUrl>https://github.com/AnonymusRaccoon/Kyoo</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/AnonymusRaccoon/Kyoo</RepositoryUrl>
|
||||
<Company>SDG</Company>
|
||||
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<PackageVersion>1.0.11</PackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -4,55 +4,55 @@ using System.Linq;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class Collection : IMergable<Collection>
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Poster { get; set; }
|
||||
public string Overview { get; set; }
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
public IEnumerable<Show> Shows;
|
||||
public class Collection : IMergable<Collection>
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Poster { get; set; }
|
||||
public string Overview { get; set; }
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
public IEnumerable<Show> Shows;
|
||||
|
||||
public Collection() { }
|
||||
public Collection() { }
|
||||
|
||||
public Collection(string slug, string name, string overview, string imgPrimary)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
Overview = overview;
|
||||
ImgPrimary = imgPrimary;
|
||||
}
|
||||
|
||||
public Show AsShow()
|
||||
{
|
||||
return new Show(Slug, Name, null, null, Overview, null, null, null, null, null, null)
|
||||
{
|
||||
IsCollection = true
|
||||
};
|
||||
}
|
||||
|
||||
public Collection Merge(Collection collection)
|
||||
{
|
||||
if (collection == null)
|
||||
return this;
|
||||
if (ID == -1)
|
||||
ID = collection.ID;
|
||||
if (Slug == null)
|
||||
Slug = collection.Slug;
|
||||
if (Name == null)
|
||||
Name = collection.Name;
|
||||
if (Poster == null)
|
||||
Poster = collection.Poster;
|
||||
if (Overview == null)
|
||||
Overview = collection.Overview;
|
||||
if (ImgPrimary == null)
|
||||
ImgPrimary = collection.ImgPrimary;
|
||||
if (Shows == null)
|
||||
Shows = collection.Shows;
|
||||
else
|
||||
Shows = Shows.Concat(collection.Shows);
|
||||
return this;
|
||||
public Collection(string slug, string name, string overview, string imgPrimary)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
Overview = overview;
|
||||
ImgPrimary = imgPrimary;
|
||||
}
|
||||
}
|
||||
|
||||
public Show AsShow()
|
||||
{
|
||||
return new Show(Slug, Name, null, null, Overview, null, null, null, null, null, null)
|
||||
{
|
||||
IsCollection = true
|
||||
};
|
||||
}
|
||||
|
||||
public Collection Merge(Collection collection)
|
||||
{
|
||||
if (collection == null)
|
||||
return this;
|
||||
if (ID == -1)
|
||||
ID = collection.ID;
|
||||
if (Slug == null)
|
||||
Slug = collection.Slug;
|
||||
if (Name == null)
|
||||
Name = collection.Name;
|
||||
if (Poster == null)
|
||||
Poster = collection.Poster;
|
||||
if (Overview == null)
|
||||
Overview = collection.Overview;
|
||||
if (ImgPrimary == null)
|
||||
ImgPrimary = collection.ImgPrimary;
|
||||
if (Shows == null)
|
||||
Shows = collection.Shows;
|
||||
else
|
||||
Shows = Shows.Concat(collection.Shows);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,112 +4,107 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class Episode : IMergable<Episode>
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
[JsonIgnore] public long ShowID { get; set; }
|
||||
[JsonIgnore] public virtual Show Show { get; set; }
|
||||
[JsonIgnore] public long SeasonID { get; set; }
|
||||
[JsonIgnore] public virtual Season Season { get; set; }
|
||||
public class Episode : IMergable<Episode>
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
[JsonIgnore] public long ShowID { get; set; }
|
||||
[JsonIgnore] public virtual Show Show { get; set; }
|
||||
[JsonIgnore] public long SeasonID { get; set; }
|
||||
[JsonIgnore] public virtual Season Season { get; set; }
|
||||
|
||||
public long SeasonNumber { get; set; }
|
||||
public long EpisodeNumber { get; set; }
|
||||
public long AbsoluteNumber { get; set; }
|
||||
[JsonIgnore] public string Path { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public long SeasonNumber { get; set; }
|
||||
public long EpisodeNumber { get; set; }
|
||||
public long AbsoluteNumber { get; set; }
|
||||
[JsonIgnore] public string Path { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
|
||||
public long Runtime { get; set; } //This runtime variable should be in minutes
|
||||
public long Runtime { get; set; } //This runtime variable should be in minutes
|
||||
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
public string ExternalIDs { get; set; }
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
public string ExternalIDs { get; set; }
|
||||
|
||||
[JsonIgnore] public virtual IEnumerable<Track> Tracks { get; set; }
|
||||
[JsonIgnore] public virtual IEnumerable<Track> Tracks { get; set; }
|
||||
|
||||
public string ShowTitle; //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 ShowTitle; //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 Episode()
|
||||
{
|
||||
SeasonNumber = -1;
|
||||
EpisodeNumber = -1;
|
||||
AbsoluteNumber = -1;
|
||||
}
|
||||
public Episode()
|
||||
{
|
||||
SeasonNumber = -1;
|
||||
EpisodeNumber = -1;
|
||||
AbsoluteNumber = -1;
|
||||
}
|
||||
|
||||
public Episode(long seasonNumber, long episodeNumber, long absoluteNumber, string title, string overview, DateTime? releaseDate, long runtime, string imgPrimary, string externalIDs)
|
||||
{
|
||||
SeasonNumber = seasonNumber;
|
||||
EpisodeNumber = episodeNumber;
|
||||
AbsoluteNumber = absoluteNumber;
|
||||
Title = title;
|
||||
Overview = overview;
|
||||
ReleaseDate = releaseDate;
|
||||
Runtime = runtime;
|
||||
ImgPrimary = imgPrimary;
|
||||
ExternalIDs = externalIDs;
|
||||
}
|
||||
public Episode(long seasonNumber, long episodeNumber, long absoluteNumber, string title, string overview, DateTime? releaseDate, long runtime, string imgPrimary, string externalIDs)
|
||||
{
|
||||
SeasonNumber = seasonNumber;
|
||||
EpisodeNumber = episodeNumber;
|
||||
AbsoluteNumber = absoluteNumber;
|
||||
Title = title;
|
||||
Overview = overview;
|
||||
ReleaseDate = releaseDate;
|
||||
Runtime = runtime;
|
||||
ImgPrimary = imgPrimary;
|
||||
ExternalIDs = 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)
|
||||
{
|
||||
ShowID = showID;
|
||||
SeasonID = seasonID;
|
||||
SeasonNumber = seasonNumber;
|
||||
EpisodeNumber = episodeNumber;
|
||||
AbsoluteNumber = absoluteNumber;
|
||||
Path = path;
|
||||
Title = title;
|
||||
Overview = overview;
|
||||
ReleaseDate = releaseDate;
|
||||
Runtime = runtime;
|
||||
ImgPrimary = imgPrimary;
|
||||
ExternalIDs = 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)
|
||||
{
|
||||
ShowID = showID;
|
||||
SeasonID = seasonID;
|
||||
SeasonNumber = seasonNumber;
|
||||
EpisodeNumber = episodeNumber;
|
||||
AbsoluteNumber = absoluteNumber;
|
||||
Path = path;
|
||||
Title = title;
|
||||
Overview = overview;
|
||||
ReleaseDate = releaseDate;
|
||||
Runtime = runtime;
|
||||
ImgPrimary = imgPrimary;
|
||||
ExternalIDs = externalIDs;
|
||||
}
|
||||
|
||||
public static string GetSlug(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
return showSlug + "-s" + seasonNumber + "e" + episodeNumber;
|
||||
}
|
||||
public static string GetSlug(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
return showSlug + "-s" + seasonNumber + "e" + episodeNumber;
|
||||
}
|
||||
|
||||
public Episode SetLink(string showSlug)
|
||||
{
|
||||
Link = GetSlug(showSlug, SeasonNumber, EpisodeNumber);
|
||||
Thumb = "thumb/" + Link;
|
||||
return this;
|
||||
}
|
||||
public Episode SetLink(string showSlug)
|
||||
{
|
||||
Link = GetSlug(showSlug, SeasonNumber, EpisodeNumber);
|
||||
Thumb = "thumb/" + Link;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Episode Merge(Episode other)
|
||||
{
|
||||
if (other == null)
|
||||
return this;
|
||||
if (ID == -1)
|
||||
ID = other.ID;
|
||||
if (ShowID == -1)
|
||||
ShowID = other.ShowID;
|
||||
if (SeasonID == -1)
|
||||
SeasonID = other.SeasonID;
|
||||
if (SeasonNumber == -1)
|
||||
SeasonNumber = other.SeasonNumber;
|
||||
if (EpisodeNumber == -1)
|
||||
EpisodeNumber = other.EpisodeNumber;
|
||||
if (AbsoluteNumber == -1)
|
||||
AbsoluteNumber = other.AbsoluteNumber;
|
||||
if (Path == null)
|
||||
Path = other.Path;
|
||||
if (Title == null)
|
||||
Title = other.Title;
|
||||
if (Overview == null)
|
||||
Overview = other.Overview;
|
||||
if (ReleaseDate == null)
|
||||
ReleaseDate = other.ReleaseDate;
|
||||
if (Runtime == -1)
|
||||
Runtime = other.Runtime;
|
||||
if (ImgPrimary == null)
|
||||
ImgPrimary = other.ImgPrimary;
|
||||
ExternalIDs += '|' + other.ExternalIDs;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
public Episode Merge(Episode other)
|
||||
{
|
||||
if (other == null)
|
||||
return this;
|
||||
if (ID == -1)
|
||||
ID = other.ID;
|
||||
if (ShowID == -1)
|
||||
ShowID = other.ShowID;
|
||||
if (SeasonID == -1)
|
||||
SeasonID = other.SeasonID;
|
||||
if (SeasonNumber == -1)
|
||||
SeasonNumber = other.SeasonNumber;
|
||||
if (EpisodeNumber == -1)
|
||||
EpisodeNumber = other.EpisodeNumber;
|
||||
if (AbsoluteNumber == -1)
|
||||
AbsoluteNumber = other.AbsoluteNumber;
|
||||
Path ??= other.Path;
|
||||
Title ??= other.Title;
|
||||
Overview ??= other.Overview;
|
||||
ReleaseDate ??= other.ReleaseDate;
|
||||
if (Runtime == -1)
|
||||
Runtime = other.Runtime;
|
||||
ImgPrimary ??= other.ImgPrimary;
|
||||
ExternalIDs += '|' + other.ExternalIDs;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,25 +3,25 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class Genre
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
// public IEnumerable<Show> Shows { get; set; }
|
||||
public class Genre
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
// public IEnumerable<Show> Shows { get; set; }
|
||||
|
||||
public Genre(string slug, string name)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
}
|
||||
public Genre(string slug, string name)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public Genre(long id, string slug, string name)
|
||||
{
|
||||
ID = id;
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
public Genre(long id, string slug, string name)
|
||||
{
|
||||
ID = id;
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,22 +2,22 @@
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class Library
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string[] Paths { get; set; }
|
||||
public string[] Providers { get; set; }
|
||||
public class Library
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string[] Paths { get; set; }
|
||||
public string[] Providers { get; set; }
|
||||
|
||||
public Library() { }
|
||||
|
||||
public Library(string slug, string name, string[] paths, string[] providers)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
Paths = paths;
|
||||
Providers = providers;
|
||||
}
|
||||
}
|
||||
public Library() { }
|
||||
|
||||
public Library(string slug, string name, string[] paths, string[] providers)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
Paths = paths;
|
||||
Providers = providers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,37 +3,34 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class People : IMergable<People>
|
||||
{
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
public string ExternalIDs { get; set; }
|
||||
|
||||
[JsonIgnore] public virtual IEnumerable<PeopleLink> Roles { get; set; }
|
||||
|
||||
public People() {}
|
||||
public class People : IMergable<People>
|
||||
{
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
public string ExternalIDs { get; set; }
|
||||
|
||||
[JsonIgnore] public virtual IEnumerable<PeopleLink> Roles { get; set; }
|
||||
|
||||
public People() {}
|
||||
|
||||
public People(string slug, string name, string imgPrimary, string externalIDs)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
ImgPrimary = imgPrimary;
|
||||
ExternalIDs = externalIDs;
|
||||
}
|
||||
public People(string slug, string name, string imgPrimary, string externalIDs)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
ImgPrimary = imgPrimary;
|
||||
ExternalIDs = externalIDs;
|
||||
}
|
||||
|
||||
public People Merge(People other)
|
||||
{
|
||||
if (other == null)
|
||||
return this;
|
||||
if (Slug == null)
|
||||
Slug = other.Slug;
|
||||
if (Name == null)
|
||||
Name = other.Name;
|
||||
if (ImgPrimary == null)
|
||||
ImgPrimary = other.ImgPrimary;
|
||||
ExternalIDs += '|' + other.ExternalIDs;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
public People Merge(People other)
|
||||
{
|
||||
if (other == null)
|
||||
return this;
|
||||
Slug ??= other.Slug;
|
||||
Name ??= other.Name;
|
||||
ImgPrimary ??= other.ImgPrimary;
|
||||
ExternalIDs += '|' + other.ExternalIDs;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,36 +2,36 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class PeopleLink
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
[JsonIgnore] public string PeopleID { get; set; }
|
||||
[JsonIgnore] public virtual People People { get; set; }
|
||||
|
||||
public string Slug => People.Slug;
|
||||
public string Name => People.Name;
|
||||
public string ExternalIDs => People.ExternalIDs;
|
||||
public class PeopleLink
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
[JsonIgnore] public string PeopleID { get; set; }
|
||||
[JsonIgnore] public virtual People People { get; set; }
|
||||
|
||||
public string Slug => People.Slug;
|
||||
public string Name => People.Name;
|
||||
public string ExternalIDs => People.ExternalIDs;
|
||||
|
||||
[JsonIgnore] public long ShowID { get; set; }
|
||||
[JsonIgnore] public virtual Show Show { get; set; }
|
||||
public string Role { get; set; }
|
||||
public string Type { get; set; }
|
||||
[JsonIgnore] public long ShowID { get; set; }
|
||||
[JsonIgnore] public virtual Show Show { get; set; }
|
||||
public string Role { get; set; }
|
||||
public string Type { get; set; }
|
||||
|
||||
public PeopleLink() {}
|
||||
|
||||
public PeopleLink(People people, Show show, string role, string type)
|
||||
{
|
||||
People = people;
|
||||
Show = show;
|
||||
Role = role;
|
||||
Type = type;
|
||||
}
|
||||
public PeopleLink() {}
|
||||
|
||||
public PeopleLink(People people, Show show, string role, string type)
|
||||
{
|
||||
People = people;
|
||||
Show = show;
|
||||
Role = role;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public PeopleLink(string slug, string name, string role, string type, string imgPrimary, string externalIDs)
|
||||
{
|
||||
People = new People(slug, name, imgPrimary, externalIDs);
|
||||
Role = role;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
public PeopleLink(string slug, string name, string role, string type, string imgPrimary, string externalIDs)
|
||||
{
|
||||
People = new People(slug, name, imgPrimary, externalIDs);
|
||||
Role = role;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,13 +2,13 @@
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class SearchResult
|
||||
{
|
||||
public string Query;
|
||||
public IEnumerable<Show> Shows;
|
||||
public IEnumerable<Episode> Episodes;
|
||||
public IEnumerable<People> People;
|
||||
public IEnumerable<Genre> Genres;
|
||||
public IEnumerable<Studio> Studios;
|
||||
}
|
||||
public class SearchResult
|
||||
{
|
||||
public string Query;
|
||||
public IEnumerable<Show> Shows;
|
||||
public IEnumerable<Episode> Episodes;
|
||||
public IEnumerable<People> People;
|
||||
public IEnumerable<Genre> Genres;
|
||||
public IEnumerable<Studio> Studios;
|
||||
}
|
||||
}
|
||||
|
@ -3,53 +3,49 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class Season : IMergable<Season>
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
[JsonIgnore] public long ShowID { get; set; }
|
||||
public class Season : IMergable<Season>
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
[JsonIgnore] public long ShowID { get; set; }
|
||||
|
||||
public long SeasonNumber { get; set; } = -1;
|
||||
public string Title { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public long? Year { get; set; }
|
||||
public long SeasonNumber { get; set; } = -1;
|
||||
public string Title { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public long? Year { get; set; }
|
||||
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
public string ExternalIDs { get; set; }
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
public string ExternalIDs { get; set; }
|
||||
|
||||
[JsonIgnore] public virtual Show Show { get; set; }
|
||||
[JsonIgnore] public virtual IEnumerable<Episode> Episodes { get; set; }
|
||||
[JsonIgnore] public virtual Show Show { get; set; }
|
||||
[JsonIgnore] public virtual IEnumerable<Episode> Episodes { get; set; }
|
||||
|
||||
public Season() { }
|
||||
public Season() { }
|
||||
|
||||
public Season(long showID, long seasonNumber, string title, string overview, long? year, string imgPrimary, string externalIDs)
|
||||
{
|
||||
ShowID = showID;
|
||||
SeasonNumber = seasonNumber;
|
||||
Title = title;
|
||||
Overview = overview;
|
||||
Year = year;
|
||||
ImgPrimary = imgPrimary;
|
||||
ExternalIDs = externalIDs;
|
||||
}
|
||||
public Season(long showID, long seasonNumber, string title, string overview, long? year, string imgPrimary, string externalIDs)
|
||||
{
|
||||
ShowID = showID;
|
||||
SeasonNumber = seasonNumber;
|
||||
Title = title;
|
||||
Overview = overview;
|
||||
Year = year;
|
||||
ImgPrimary = imgPrimary;
|
||||
ExternalIDs = externalIDs;
|
||||
}
|
||||
|
||||
public Season Merge(Season other)
|
||||
{
|
||||
if (other == null)
|
||||
return this;
|
||||
if (ShowID == -1)
|
||||
ShowID = other.ShowID;
|
||||
if (SeasonNumber == -1)
|
||||
SeasonNumber = other.SeasonNumber;
|
||||
if (Title == null)
|
||||
Title = other.Title;
|
||||
if (Overview == null)
|
||||
Overview = other.Overview;
|
||||
if (Year == null)
|
||||
Year = other.Year;
|
||||
if (ImgPrimary == null)
|
||||
ImgPrimary = other.ImgPrimary;
|
||||
ExternalIDs += '|' + other.ExternalIDs;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
public Season Merge(Season other)
|
||||
{
|
||||
if (other == null)
|
||||
return this;
|
||||
if (ShowID == -1)
|
||||
ShowID = other.ShowID;
|
||||
if (SeasonNumber == -1)
|
||||
SeasonNumber = other.SeasonNumber;
|
||||
Title ??= other.Title;
|
||||
Overview ??= other.Overview;
|
||||
Year ??= other.Year;
|
||||
ImgPrimary ??= other.ImgPrimary;
|
||||
ExternalIDs += '|' + other.ExternalIDs;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,144 +5,126 @@ using System.Linq;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class Show : IMergable<Show>
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
public class Show : IMergable<Show>
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
|
||||
public string Slug { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string[] Aliases { get; set; }
|
||||
[JsonIgnore] public string Path { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public Status? Status { get; set; }
|
||||
public string TrailerUrl { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string[] Aliases { get; set; }
|
||||
[JsonIgnore] public string Path { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public Status? Status { get; set; }
|
||||
public string TrailerUrl { get; set; }
|
||||
|
||||
public long? StartYear { get; set; }
|
||||
public long? EndYear { get; set; }
|
||||
public long? StartYear { get; set; }
|
||||
public long? EndYear { get; set; }
|
||||
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
[JsonIgnore] public string ImgThumb { get; set; }
|
||||
[JsonIgnore] public string ImgLogo { get; set; }
|
||||
[JsonIgnore] public string ImgBackdrop { get; set; }
|
||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
||||
[JsonIgnore] public string ImgThumb { get; set; }
|
||||
[JsonIgnore] public string ImgLogo { get; set; }
|
||||
[JsonIgnore] public string ImgBackdrop { get; set; }
|
||||
|
||||
public string ExternalIDs { get; set; }
|
||||
public string ExternalIDs { get; set; }
|
||||
|
||||
public bool IsMovie { get; set; }
|
||||
|
||||
public bool IsCollection;
|
||||
|
||||
[JsonIgnore] public virtual IEnumerable<Genre> Genres
|
||||
{
|
||||
get { return GenreLinks?.Select(x => x.Genre).OrderBy(x => x.Name); }
|
||||
set { GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList(); }
|
||||
}
|
||||
[JsonIgnore] public virtual List<GenreLink> GenreLinks { get; set; }
|
||||
[JsonIgnore] public virtual Studio Studio { get; set; }
|
||||
[JsonIgnore] public virtual IEnumerable<PeopleLink> People { get; set; }
|
||||
[JsonIgnore] public virtual IEnumerable<Season> Seasons { get; set; }
|
||||
[JsonIgnore] public virtual IEnumerable<Episode> Episodes { get; set; }
|
||||
public bool IsMovie { get; set; }
|
||||
|
||||
public bool IsCollection;
|
||||
|
||||
[JsonIgnore] public virtual IEnumerable<Genre> Genres
|
||||
{
|
||||
get { return GenreLinks?.Select(x => x.Genre).OrderBy(x => x.Name); }
|
||||
set { GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList(); }
|
||||
}
|
||||
[JsonIgnore] public virtual List<GenreLink> GenreLinks { get; set; }
|
||||
[JsonIgnore] public virtual Studio Studio { get; set; }
|
||||
[JsonIgnore] public virtual IEnumerable<PeopleLink> People { get; set; }
|
||||
[JsonIgnore] public virtual IEnumerable<Season> Seasons { get; set; }
|
||||
[JsonIgnore] public virtual IEnumerable<Episode> Episodes { get; set; }
|
||||
|
||||
|
||||
public string GetAliases()
|
||||
{
|
||||
return Aliases == null ? null : string.Join('|', Aliases);
|
||||
}
|
||||
public string GetAliases()
|
||||
{
|
||||
return Aliases == null ? null : string.Join('|', Aliases);
|
||||
}
|
||||
|
||||
public string GetGenres()
|
||||
{
|
||||
return Genres == null ? null : string.Join('|', Genres);
|
||||
}
|
||||
public string GetGenres()
|
||||
{
|
||||
return Genres == null ? null : string.Join('|', Genres);
|
||||
}
|
||||
|
||||
|
||||
public Show() { }
|
||||
public Show() { }
|
||||
|
||||
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)
|
||||
{
|
||||
Slug = slug;
|
||||
Title = title;
|
||||
Aliases = aliases.ToArray();
|
||||
Path = path;
|
||||
Overview = overview;
|
||||
TrailerUrl = trailerUrl;
|
||||
Genres = genres;
|
||||
Status = status;
|
||||
StartYear = startYear;
|
||||
EndYear = endYear;
|
||||
ExternalIDs = externalIDs;
|
||||
IsCollection = false;
|
||||
}
|
||||
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)
|
||||
{
|
||||
Slug = slug;
|
||||
Title = title;
|
||||
Aliases = aliases.ToArray();
|
||||
Path = path;
|
||||
Overview = overview;
|
||||
TrailerUrl = trailerUrl;
|
||||
Genres = genres;
|
||||
Status = status;
|
||||
StartYear = startYear;
|
||||
EndYear = endYear;
|
||||
ExternalIDs = externalIDs;
|
||||
IsCollection = false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Slug = slug;
|
||||
Title = title;
|
||||
Aliases = aliases.ToArray();
|
||||
Path = path;
|
||||
Overview = overview;
|
||||
TrailerUrl = trailerUrl;
|
||||
Status = status;
|
||||
StartYear = startYear;
|
||||
EndYear = endYear;
|
||||
ImgPrimary = imgPrimary;
|
||||
ImgThumb = imgThumb;
|
||||
ImgLogo = imgLogo;
|
||||
ImgBackdrop = imgBackdrop;
|
||||
ExternalIDs = externalIDs;
|
||||
IsCollection = false;
|
||||
}
|
||||
|
||||
public string GetID(string provider)
|
||||
{
|
||||
if (ExternalIDs?.Contains(provider) != true)
|
||||
return null;
|
||||
int startIndex = ExternalIDs.IndexOf(provider, StringComparison.Ordinal) + provider.Length + 1; //The + 1 is for the '='
|
||||
if (ExternalIDs.IndexOf('|', startIndex) == -1)
|
||||
return ExternalIDs.Substring(startIndex);
|
||||
return ExternalIDs.Substring(startIndex, ExternalIDs.IndexOf('|', startIndex) - startIndex);
|
||||
}
|
||||
|
||||
public Show Merge(Show other)
|
||||
{
|
||||
if (other == null)
|
||||
return this;
|
||||
if (ID == -1)
|
||||
ID = other.ID;
|
||||
if (Slug == null)
|
||||
Slug = other.Slug;
|
||||
if (Title == null)
|
||||
Title = other.Title;
|
||||
if (Aliases == null)
|
||||
Aliases = other.Aliases;
|
||||
else
|
||||
Aliases = Aliases.Concat(other.Aliases).ToArray();
|
||||
if (Genres == null)
|
||||
Genres = other.Genres;
|
||||
else
|
||||
Genres = Genres.Concat(other.Genres);
|
||||
if (Path == null)
|
||||
Path = other.Path;
|
||||
if (Overview == null)
|
||||
Overview = other.Overview;
|
||||
if (TrailerUrl == null)
|
||||
TrailerUrl = other.TrailerUrl;
|
||||
if (Status == null)
|
||||
Status = other.Status;
|
||||
if (StartYear == null)
|
||||
StartYear = other.StartYear;
|
||||
if (EndYear == null)
|
||||
EndYear = other.EndYear;
|
||||
if (ImgPrimary == null)
|
||||
ImgPrimary = other.ImgPrimary;
|
||||
if (ImgThumb == null)
|
||||
ImgThumb = other.ImgThumb;
|
||||
if (ImgLogo == null)
|
||||
ImgLogo = other.ImgLogo;
|
||||
if (ImgBackdrop == null)
|
||||
ImgBackdrop = other.ImgBackdrop;
|
||||
ExternalIDs += '|' + other.ExternalIDs;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
Slug = slug;
|
||||
Title = title;
|
||||
Aliases = aliases.ToArray();
|
||||
Path = path;
|
||||
Overview = overview;
|
||||
TrailerUrl = trailerUrl;
|
||||
Status = status;
|
||||
StartYear = startYear;
|
||||
EndYear = endYear;
|
||||
ImgPrimary = imgPrimary;
|
||||
ImgThumb = imgThumb;
|
||||
ImgLogo = imgLogo;
|
||||
ImgBackdrop = imgBackdrop;
|
||||
ExternalIDs = externalIDs;
|
||||
IsCollection = false;
|
||||
}
|
||||
|
||||
public enum Status { Finished, Airing }
|
||||
public string GetID(string provider)
|
||||
{
|
||||
if (ExternalIDs?.Contains(provider) != true)
|
||||
return null;
|
||||
int startIndex = ExternalIDs.IndexOf(provider, StringComparison.Ordinal) + provider.Length + 1; //The + 1 is for the '='
|
||||
if (ExternalIDs.IndexOf('|', startIndex) == -1)
|
||||
return ExternalIDs.Substring(startIndex);
|
||||
return ExternalIDs.Substring(startIndex, ExternalIDs.IndexOf('|', startIndex) - startIndex);
|
||||
}
|
||||
|
||||
public Show Merge(Show other)
|
||||
{
|
||||
if (other == null)
|
||||
return this;
|
||||
if (ID == -1)
|
||||
ID = other.ID;
|
||||
Slug ??= other.Slug;
|
||||
Title ??= other.Title;
|
||||
Aliases = Aliases == null ? other.Aliases : Aliases.Concat(other.Aliases).ToArray();
|
||||
Genres = Genres == null ? other.Genres : Genres.Concat(other.Genres);
|
||||
Path ??= other.Path;
|
||||
Overview ??= other.Overview;
|
||||
TrailerUrl ??= other.TrailerUrl;
|
||||
Status ??= other.Status;
|
||||
StartYear ??= other.StartYear;
|
||||
EndYear ??= other.EndYear;
|
||||
ImgPrimary ??= other.ImgPrimary;
|
||||
ImgThumb ??= other.ImgThumb;
|
||||
ImgLogo ??= other.ImgLogo;
|
||||
ImgBackdrop ??= other.ImgBackdrop;
|
||||
ExternalIDs += '|' + other.ExternalIDs;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Status { Finished, Airing }
|
||||
}
|
||||
|
@ -2,23 +2,23 @@
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class Studio
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
public class Studio
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
public Studio() { }
|
||||
public Studio() { }
|
||||
|
||||
public Studio(string slug, string name)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public static Studio Default()
|
||||
{
|
||||
return new Studio("unknow", "Unknow Studio");
|
||||
}
|
||||
}
|
||||
public Studio(string slug, string name)
|
||||
{
|
||||
Slug = slug;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public static Studio Default()
|
||||
{
|
||||
return new Studio("unknow", "Unknow Studio");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,121 +7,121 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
namespace Watch
|
||||
{
|
||||
public enum StreamType
|
||||
{
|
||||
Unknow = 0,
|
||||
Video = 1,
|
||||
Audio = 2,
|
||||
Subtitle = 3
|
||||
}
|
||||
namespace Watch
|
||||
{
|
||||
public enum StreamType
|
||||
{
|
||||
Unknow = 0,
|
||||
Video = 1,
|
||||
Audio = 2,
|
||||
Subtitle = 3
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public class Stream
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Language { get; set; }
|
||||
public string Codec { get; set; }
|
||||
[MarshalAs(UnmanagedType.I1)] public bool isDefault;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool isForced;
|
||||
[JsonIgnore] public string Path { get; set; }
|
||||
[JsonIgnore] public StreamType Type { get; set; }
|
||||
|
||||
public Stream() {}
|
||||
|
||||
public Stream(string title, string language, string codec, bool isDefault, bool isForced, string path, StreamType type)
|
||||
{
|
||||
Title = title;
|
||||
Language = language;
|
||||
Codec = codec;
|
||||
this.isDefault = isDefault;
|
||||
this.isForced = isForced;
|
||||
Path = path;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public Stream(Stream stream)
|
||||
{
|
||||
Title = stream.Title;
|
||||
Language = stream.Language;
|
||||
isDefault = stream.isDefault;
|
||||
isForced = stream.isForced;
|
||||
Codec = stream.Codec;
|
||||
Path = stream.Path;
|
||||
Type = stream.Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public class Stream
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Language { get; set; }
|
||||
public string Codec { get; set; }
|
||||
[MarshalAs(UnmanagedType.I1)] public bool isDefault;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool isForced;
|
||||
[JsonIgnore] public string Path { get; set; }
|
||||
[JsonIgnore] public StreamType Type { get; set; }
|
||||
|
||||
public Stream() {}
|
||||
|
||||
public Stream(string title, string language, string codec, bool isDefault, bool isForced, string path, StreamType type)
|
||||
{
|
||||
Title = title;
|
||||
Language = language;
|
||||
Codec = codec;
|
||||
this.isDefault = isDefault;
|
||||
this.isForced = isForced;
|
||||
Path = path;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public Stream(Stream stream)
|
||||
{
|
||||
Title = stream.Title;
|
||||
Language = stream.Language;
|
||||
isDefault = stream.isDefault;
|
||||
isForced = stream.isForced;
|
||||
Codec = stream.Codec;
|
||||
Path = stream.Path;
|
||||
Type = stream.Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Track : Stream
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
[JsonIgnore] public long EpisodeID { get; set; }
|
||||
public bool IsDefault
|
||||
{
|
||||
get => isDefault;
|
||||
set => isDefault = value;
|
||||
}
|
||||
public bool IsForced
|
||||
{
|
||||
get => isForced;
|
||||
set => isForced = value;
|
||||
}
|
||||
public string DisplayName;
|
||||
public string Link;
|
||||
public class Track : Stream
|
||||
{
|
||||
[JsonIgnore] public long ID { get; set; }
|
||||
[JsonIgnore] public long EpisodeID { get; set; }
|
||||
public bool IsDefault
|
||||
{
|
||||
get => isDefault;
|
||||
set => isDefault = value;
|
||||
}
|
||||
public bool IsForced
|
||||
{
|
||||
get => isForced;
|
||||
set => isForced = value;
|
||||
}
|
||||
public string DisplayName;
|
||||
public string Link;
|
||||
|
||||
[JsonIgnore] public bool IsExternal { get; set; }
|
||||
[JsonIgnore] public virtual Episode Episode { get; set; }
|
||||
|
||||
public Track() { }
|
||||
[JsonIgnore] public bool IsExternal { get; set; }
|
||||
[JsonIgnore] public virtual Episode Episode { get; set; }
|
||||
|
||||
public Track() { }
|
||||
|
||||
public Track(StreamType type, string title, string language, bool isDefault, bool isForced, string codec, bool isExternal, string path)
|
||||
: base(title, language, codec, isDefault, isForced, path, type)
|
||||
{
|
||||
IsExternal = isExternal;
|
||||
}
|
||||
public Track(StreamType type, string title, string language, bool isDefault, bool isForced, string codec, bool isExternal, string path)
|
||||
: base(title, language, codec, isDefault, isForced, path, type)
|
||||
{
|
||||
IsExternal = isExternal;
|
||||
}
|
||||
|
||||
public Track(Stream stream)
|
||||
: base(stream)
|
||||
{
|
||||
IsExternal = false;
|
||||
}
|
||||
public Track(Stream stream)
|
||||
: base(stream)
|
||||
{
|
||||
IsExternal = false;
|
||||
}
|
||||
|
||||
public Track SetLink(string episodeSlug)
|
||||
{
|
||||
if (Type == StreamType.Subtitle)
|
||||
{
|
||||
string language = Language;
|
||||
//Converting mkv track language to c# system language tag.
|
||||
if (language == "fre")
|
||||
language = "fra";
|
||||
public Track SetLink(string episodeSlug)
|
||||
{
|
||||
if (Type == StreamType.Subtitle)
|
||||
{
|
||||
string language = Language;
|
||||
//Converting mkv track language to c# system language tag.
|
||||
if (language == "fre")
|
||||
language = "fra";
|
||||
|
||||
DisplayName = CultureInfo.GetCultures(CultureTypes.NeutralCultures).FirstOrDefault(x => x.ThreeLetterISOLanguageName == language)?.EnglishName ?? language;
|
||||
Link = "/subtitle/" + episodeSlug + "." + Language;
|
||||
DisplayName = CultureInfo.GetCultures(CultureTypes.NeutralCultures).FirstOrDefault(x => x.ThreeLetterISOLanguageName == language)?.EnglishName ?? language;
|
||||
Link = "/subtitle/" + episodeSlug + "." + Language;
|
||||
|
||||
if (IsForced)
|
||||
{
|
||||
DisplayName += " Forced";
|
||||
Link += "-forced";
|
||||
}
|
||||
if (IsForced)
|
||||
{
|
||||
DisplayName += " Forced";
|
||||
Link += "-forced";
|
||||
}
|
||||
|
||||
if (Title != null && Title.Length > 1)
|
||||
DisplayName += " - " + Title;
|
||||
if (Title != null && Title.Length > 1)
|
||||
DisplayName += " - " + Title;
|
||||
|
||||
switch (Codec)
|
||||
{
|
||||
case "ass":
|
||||
Link += ".ass";
|
||||
break;
|
||||
case "subrip":
|
||||
Link += ".srt";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
Link = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
switch (Codec)
|
||||
{
|
||||
case "ass":
|
||||
Link += ".ass";
|
||||
break;
|
||||
case "subrip":
|
||||
Link += ".srt";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
Link = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,48 +4,48 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class WatchItem
|
||||
{
|
||||
[JsonIgnore] public readonly long EpisodeID = -1;
|
||||
public class WatchItem
|
||||
{
|
||||
[JsonIgnore] public readonly long EpisodeID = -1;
|
||||
|
||||
public string ShowTitle;
|
||||
public string ShowSlug;
|
||||
public long SeasonNumber;
|
||||
public long EpisodeNumber;
|
||||
public string Title;
|
||||
public string Link;
|
||||
public DateTime? ReleaseDate;
|
||||
[JsonIgnore] public string Path;
|
||||
public string PreviousEpisode;
|
||||
public Episode NextEpisode;
|
||||
public string ShowTitle;
|
||||
public string ShowSlug;
|
||||
public long SeasonNumber;
|
||||
public long EpisodeNumber;
|
||||
public string Title;
|
||||
public string Link;
|
||||
public DateTime? ReleaseDate;
|
||||
[JsonIgnore] public string Path;
|
||||
public string PreviousEpisode;
|
||||
public Episode NextEpisode;
|
||||
|
||||
public string Container;
|
||||
public Track Video;
|
||||
public IEnumerable<Track> Audios;
|
||||
public IEnumerable<Track> Subtitles;
|
||||
public string Container;
|
||||
public Track Video;
|
||||
public IEnumerable<Track> Audios;
|
||||
public IEnumerable<Track> Subtitles;
|
||||
|
||||
public WatchItem() { }
|
||||
public WatchItem() { }
|
||||
|
||||
public WatchItem(long episodeID, string showTitle, string showSlug, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path)
|
||||
{
|
||||
EpisodeID = episodeID;
|
||||
ShowTitle = showTitle;
|
||||
ShowSlug = showSlug;
|
||||
SeasonNumber = seasonNumber;
|
||||
EpisodeNumber = episodeNumber;
|
||||
Title = title;
|
||||
ReleaseDate = releaseDate;
|
||||
Path = path;
|
||||
public WatchItem(long episodeID, string showTitle, string showSlug, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path)
|
||||
{
|
||||
EpisodeID = episodeID;
|
||||
ShowTitle = showTitle;
|
||||
ShowSlug = showSlug;
|
||||
SeasonNumber = seasonNumber;
|
||||
EpisodeNumber = episodeNumber;
|
||||
Title = title;
|
||||
ReleaseDate = releaseDate;
|
||||
Path = path;
|
||||
|
||||
Container = Path.Substring(Path.LastIndexOf('.') + 1);
|
||||
Link = Episode.GetSlug(ShowSlug, seasonNumber, episodeNumber);
|
||||
}
|
||||
Container = Path.Substring(Path.LastIndexOf('.') + 1);
|
||||
Link = Episode.GetSlug(ShowSlug, seasonNumber, episodeNumber);
|
||||
}
|
||||
|
||||
public WatchItem(long episodeID, string showTitle, string showSlug, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path, Track[] audios, Track[] subtitles)
|
||||
: this(episodeID, showTitle, showSlug, seasonNumber, episodeNumber, title, releaseDate, path)
|
||||
{
|
||||
Audios = audios;
|
||||
Subtitles = subtitles;
|
||||
}
|
||||
}
|
||||
public WatchItem(long episodeID, string showTitle, string showSlug, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path, Track[] audios, Track[] subtitles)
|
||||
: this(episodeID, showTitle, showSlug, seasonNumber, episodeNumber, title, releaseDate, path)
|
||||
{
|
||||
Audios = audios;
|
||||
Subtitles = subtitles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,41 +3,41 @@ using Kyoo.Models;
|
||||
|
||||
namespace Kyoo
|
||||
{
|
||||
public interface IMergable<T>
|
||||
{
|
||||
public T Merge(T other);
|
||||
}
|
||||
|
||||
public interface IMergable<T>
|
||||
{
|
||||
public T Merge(T other);
|
||||
}
|
||||
|
||||
public static class Utility
|
||||
{
|
||||
public static string ToSlug(string name)
|
||||
{
|
||||
if (name == null)
|
||||
return null;
|
||||
public static string ToSlug(string name)
|
||||
{
|
||||
if (name == null)
|
||||
return null;
|
||||
|
||||
//First to lower case
|
||||
name = name.ToLowerInvariant();
|
||||
//First to lower case
|
||||
name = name.ToLowerInvariant();
|
||||
|
||||
//Remove all accents
|
||||
//var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(showTitle);
|
||||
//showTitle = Encoding.ASCII.GetString(bytes);
|
||||
//Remove all accents
|
||||
//var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(showTitle);
|
||||
//showTitle = Encoding.ASCII.GetString(bytes);
|
||||
|
||||
//Replace spaces
|
||||
name = Regex.Replace(name, @"\s", "-", RegexOptions.Compiled);
|
||||
//Replace spaces
|
||||
name = Regex.Replace(name, @"\s", "-", RegexOptions.Compiled);
|
||||
|
||||
//Remove invalid chars
|
||||
name = Regex.Replace(name, @"[^\w\s\p{Pd}]", "", RegexOptions.Compiled);
|
||||
//Remove invalid chars
|
||||
name = Regex.Replace(name, @"[^\w\s\p{Pd}]", "", RegexOptions.Compiled);
|
||||
|
||||
//Trim dashes from end
|
||||
name = name.Trim('-', '_');
|
||||
//Trim dashes from end
|
||||
name = name.Trim('-', '_');
|
||||
|
||||
//Replace double occurences of - or \_
|
||||
name = Regex.Replace(name, @"([-_]){2,}", "$1", RegexOptions.Compiled);
|
||||
//Replace double occurences of - or \_
|
||||
name = Regex.Replace(name, @"([-_]){2,}", "$1", RegexOptions.Compiled);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public static void SetImage(Show show, string imgUrl, ImageType type)
|
||||
{
|
||||
switch(type)
|
||||
|
@ -11,173 +11,173 @@ using Kyoo.Models.Watch;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public class Crawler : ICrawler
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IProviderManager _metadataProvider;
|
||||
private readonly ITranscoder _transcoder;
|
||||
private readonly IConfiguration _config;
|
||||
public class Crawler : ICrawler
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IProviderManager _metadataProvider;
|
||||
private readonly ITranscoder _transcoder;
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
public Crawler(ILibraryManager libraryManager, IProviderManager metadataProvider, ITranscoder transcoder, IConfiguration configuration)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_metadataProvider = metadataProvider;
|
||||
_transcoder = transcoder;
|
||||
_config = configuration;
|
||||
}
|
||||
public Crawler(ILibraryManager libraryManager, IProviderManager metadataProvider, ITranscoder transcoder, IConfiguration configuration)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_metadataProvider = metadataProvider;
|
||||
_transcoder = transcoder;
|
||||
_config = configuration;
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
IEnumerable<Episode> episodes = _libraryManager.GetAllEpisodes();
|
||||
IEnumerable<Library> libraries = _libraryManager.GetLibraries();
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
IEnumerable<Episode> episodes = _libraryManager.GetAllEpisodes();
|
||||
IEnumerable<Library> libraries = _libraryManager.GetLibraries();
|
||||
|
||||
foreach (Episode episode in episodes)
|
||||
{
|
||||
if (!File.Exists(episode.Path))
|
||||
_libraryManager.RemoveEpisode(episode.ID);
|
||||
}
|
||||
foreach (Episode episode in episodes)
|
||||
{
|
||||
if (!File.Exists(episode.Path))
|
||||
_libraryManager.RemoveEpisode(episode.ID);
|
||||
}
|
||||
|
||||
foreach (Library library in libraries)
|
||||
await Scan(library, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine($"Unknown exception thrown durring libraries scan.\nException: {ex.Message}");
|
||||
}
|
||||
Console.WriteLine("Scan finished!");
|
||||
}
|
||||
foreach (Library library in libraries)
|
||||
await Scan(library, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine($"Unknown exception thrown durring libraries scan.\nException: {ex.Message}");
|
||||
}
|
||||
Console.WriteLine("Scan finished!");
|
||||
}
|
||||
|
||||
private async Task Scan(Library library, CancellationToken cancellationToken)
|
||||
{
|
||||
Console.WriteLine($"Scanning library {library.Name} at {string.Concat(library.Paths)}");
|
||||
foreach (string path in library.Paths)
|
||||
{
|
||||
foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
if (!IsVideo(file) || _libraryManager.IsEpisodeRegistered(file, out long _))
|
||||
continue;
|
||||
string relativePath = file.Substring(path.Length);
|
||||
await RegisterFile(file, relativePath, library);
|
||||
}
|
||||
}
|
||||
}
|
||||
private async Task Scan(Library library, CancellationToken cancellationToken)
|
||||
{
|
||||
Console.WriteLine($"Scanning library {library.Name} at {string.Concat(library.Paths)}");
|
||||
foreach (string path in library.Paths)
|
||||
{
|
||||
foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
if (!IsVideo(file) || _libraryManager.IsEpisodeRegistered(file, out long _))
|
||||
continue;
|
||||
string relativePath = file.Substring(path.Length);
|
||||
await RegisterFile(file, relativePath, library);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RegisterFile(string path, string relativePath, Library library)
|
||||
{
|
||||
Console.WriteLine("Registering episode at: " + path);
|
||||
string patern = _config.GetValue<string>("regex");
|
||||
Regex regex = new Regex(patern, RegexOptions.IgnoreCase);
|
||||
Match match = regex.Match(relativePath);
|
||||
private async Task RegisterFile(string path, string relativePath, Library library)
|
||||
{
|
||||
Console.WriteLine("Registering episode at: " + path);
|
||||
string patern = _config.GetValue<string>("regex");
|
||||
Regex regex = new Regex(patern, RegexOptions.IgnoreCase);
|
||||
Match match = regex.Match(relativePath);
|
||||
|
||||
string showPath = Path.GetDirectoryName(path);
|
||||
string collectionName = match.Groups["Collection"]?.Value;
|
||||
string showName = match.Groups["ShowTitle"].Value;
|
||||
long seasonNumber = long.TryParse(match.Groups["Season"].Value, out long tmp) ? tmp : -1;
|
||||
long episodeNumber = long.TryParse(match.Groups["Episode"].Value, out tmp) ? tmp : -1;
|
||||
long absoluteNumber = long.TryParse(match.Groups["Absolute"].Value, out tmp) ? tmp : -1;
|
||||
string showPath = Path.GetDirectoryName(path);
|
||||
string collectionName = match.Groups["Collection"]?.Value;
|
||||
string showName = match.Groups["ShowTitle"].Value;
|
||||
long seasonNumber = long.TryParse(match.Groups["Season"].Value, out long tmp) ? tmp : -1;
|
||||
long episodeNumber = long.TryParse(match.Groups["Episode"].Value, out tmp) ? tmp : -1;
|
||||
long absoluteNumber = long.TryParse(match.Groups["Absolute"].Value, out tmp) ? tmp : -1;
|
||||
|
||||
Collection collection = await GetCollection(collectionName, library);
|
||||
bool isMovie = seasonNumber == -1 && episodeNumber == -1 && absoluteNumber == -1;
|
||||
Show show = await GetShow(showName, showPath, isMovie, library);
|
||||
if (isMovie)
|
||||
_libraryManager.RegisterShow(show);
|
||||
Collection collection = await GetCollection(collectionName, library);
|
||||
bool isMovie = seasonNumber == -1 && episodeNumber == -1 && absoluteNumber == -1;
|
||||
Show show = await GetShow(showName, showPath, isMovie, library);
|
||||
if (isMovie)
|
||||
_libraryManager.RegisterShow(show);
|
||||
else
|
||||
{
|
||||
Season season = await GetSeason(show, seasonNumber, library);
|
||||
Episode episode = await GetEpisode(show, season, episodeNumber, absoluteNumber, path, library);
|
||||
_libraryManager.RegisterEpisode(episode);
|
||||
}
|
||||
_libraryManager.RegisterShowLinks(library, collection, show);
|
||||
}
|
||||
{
|
||||
Season season = await GetSeason(show, seasonNumber, library);
|
||||
Episode episode = await GetEpisode(show, season, episodeNumber, absoluteNumber, path, library);
|
||||
_libraryManager.RegisterEpisode(episode);
|
||||
}
|
||||
_libraryManager.RegisterShowLinks(library, collection, show);
|
||||
}
|
||||
|
||||
private async Task<Collection> GetCollection(string collectionName, Library library)
|
||||
{
|
||||
if (string.IsNullOrEmpty(collectionName))
|
||||
return await Task.FromResult<Collection>(null);
|
||||
return _libraryManager.GetCollection(Utility.ToSlug(collectionName)) ?? await _metadataProvider.GetCollectionFromName(collectionName, library);
|
||||
}
|
||||
|
||||
private async Task<Show> GetShow(string showTitle, string showPath, bool isMovie, Library library)
|
||||
{
|
||||
Show show = _libraryManager.GetShow(showPath);
|
||||
if (show != null)
|
||||
return show;
|
||||
show = await _metadataProvider.GetShowFromName(showTitle, showPath, isMovie, library);
|
||||
show.People = (await _metadataProvider.GetPeople(show, library)).GroupBy(x => x.Slug).Select(x => x.First())
|
||||
.Select(x =>
|
||||
{
|
||||
People existing = _libraryManager.GetPeopleBySlug(x.Slug);
|
||||
return existing != null ? new PeopleLink(existing, show, x.Role, x.Type) : x;
|
||||
}).ToList();
|
||||
return show;
|
||||
}
|
||||
private async Task<Collection> GetCollection(string collectionName, Library library)
|
||||
{
|
||||
if (string.IsNullOrEmpty(collectionName))
|
||||
return await Task.FromResult<Collection>(null);
|
||||
return _libraryManager.GetCollection(Utility.ToSlug(collectionName)) ?? await _metadataProvider.GetCollectionFromName(collectionName, library);
|
||||
}
|
||||
|
||||
private async Task<Show> GetShow(string showTitle, string showPath, bool isMovie, Library library)
|
||||
{
|
||||
Show show = _libraryManager.GetShow(showPath);
|
||||
if (show != null)
|
||||
return show;
|
||||
show = await _metadataProvider.GetShowFromName(showTitle, showPath, isMovie, library);
|
||||
show.People = (await _metadataProvider.GetPeople(show, library)).GroupBy(x => x.Slug).Select(x => x.First())
|
||||
.Select(x =>
|
||||
{
|
||||
People existing = _libraryManager.GetPeopleBySlug(x.Slug);
|
||||
return existing != null ? new PeopleLink(existing, show, x.Role, x.Type) : x;
|
||||
}).ToList();
|
||||
return show;
|
||||
}
|
||||
|
||||
private async Task<Season> GetSeason(Show show, long seasonNumber, Library library)
|
||||
{
|
||||
if (seasonNumber == -1)
|
||||
return null;
|
||||
Season season = _libraryManager.GetSeason(show.Slug, seasonNumber);
|
||||
if (season != null)
|
||||
return await Task.FromResult(season);
|
||||
season = await _metadataProvider.GetSeason(show, seasonNumber, library);
|
||||
season.Show = show;
|
||||
return season;
|
||||
}
|
||||
|
||||
private async Task<Episode> GetEpisode(Show show, Season season, long episodeNumber, long absoluteNumber, string episodePath, Library library)
|
||||
{
|
||||
Episode episode = await _metadataProvider.GetEpisode(show, episodePath, season?.SeasonNumber ?? -1, episodeNumber, absoluteNumber, library);
|
||||
episode.Show = show;
|
||||
if (season == null)
|
||||
season = await GetSeason(show, episode.SeasonNumber, library);
|
||||
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;
|
||||
}
|
||||
private async Task<Season> GetSeason(Show show, long seasonNumber, Library library)
|
||||
{
|
||||
if (seasonNumber == -1)
|
||||
return null;
|
||||
Season season = _libraryManager.GetSeason(show.Slug, seasonNumber);
|
||||
if (season != null)
|
||||
return await Task.FromResult(season);
|
||||
season = await _metadataProvider.GetSeason(show, seasonNumber, library);
|
||||
season.Show = show;
|
||||
return season;
|
||||
}
|
||||
|
||||
private async Task<Episode> GetEpisode(Show show, Season season, long episodeNumber, long absoluteNumber, string episodePath, Library library)
|
||||
{
|
||||
Episode episode = await _metadataProvider.GetEpisode(show, episodePath, season?.SeasonNumber ?? -1, episodeNumber, absoluteNumber, library);
|
||||
episode.Show = show;
|
||||
if (season == null)
|
||||
season = await GetSeason(show, episode.SeasonNumber, library);
|
||||
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;
|
||||
}
|
||||
|
||||
private static IEnumerable<Track> GetExtractedSubtitles(Episode episode)
|
||||
{
|
||||
string path = Path.Combine(Path.GetDirectoryName(episode.Path), "Subtitles");
|
||||
List<Track> tracks = new List<Track>();
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
return tracks;
|
||||
foreach (string sub in Directory.EnumerateFiles(path, "", SearchOption.AllDirectories))
|
||||
{
|
||||
string episodeLink = Path.GetFileNameWithoutExtension(episode.Path);
|
||||
private static IEnumerable<Track> GetExtractedSubtitles(Episode episode)
|
||||
{
|
||||
string path = Path.Combine(Path.GetDirectoryName(episode.Path), "Subtitles");
|
||||
List<Track> tracks = new List<Track>();
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
return tracks;
|
||||
foreach (string sub in Directory.EnumerateFiles(path, "", SearchOption.AllDirectories))
|
||||
{
|
||||
string episodeLink = Path.GetFileNameWithoutExtension(episode.Path);
|
||||
|
||||
if (!sub.Contains(episodeLink))
|
||||
continue;
|
||||
string language = sub.Substring(Path.GetDirectoryName(sub).Length + episodeLink.Length + 2, 3);
|
||||
bool isDefault = sub.Contains("default");
|
||||
bool isForced = sub.Contains("forced");
|
||||
Track track = new Track(StreamType.Subtitle, null, language, isDefault, isForced, null, false, sub) { EpisodeID = episode.ID };
|
||||
if (!sub.Contains(episodeLink))
|
||||
continue;
|
||||
string language = sub.Substring(Path.GetDirectoryName(sub).Length + episodeLink.Length + 2, 3);
|
||||
bool isDefault = sub.Contains("default");
|
||||
bool isForced = sub.Contains("forced");
|
||||
Track track = new Track(StreamType.Subtitle, null, language, isDefault, isForced, null, false, sub) { EpisodeID = episode.ID };
|
||||
|
||||
if (Path.GetExtension(sub) == ".ass")
|
||||
track.Codec = "ass";
|
||||
else if (Path.GetExtension(sub) == ".srt")
|
||||
track.Codec = "subrip";
|
||||
else
|
||||
track.Codec = null;
|
||||
tracks.Add(track);
|
||||
}
|
||||
return tracks;
|
||||
}
|
||||
if (Path.GetExtension(sub) == ".ass")
|
||||
track.Codec = "ass";
|
||||
else if (Path.GetExtension(sub) == ".srt")
|
||||
track.Codec = "subrip";
|
||||
else
|
||||
track.Codec = null;
|
||||
tracks.Add(track);
|
||||
}
|
||||
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" };
|
||||
|
||||
private static bool IsVideo(string filePath)
|
||||
{
|
||||
return VideoExtensions.Contains(Path.GetExtension(filePath));
|
||||
}
|
||||
}
|
||||
private static bool IsVideo(string filePath)
|
||||
{
|
||||
return VideoExtensions.Contains(Path.GetExtension(filePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,9 +48,9 @@ namespace Kyoo.Controllers
|
||||
if (showID == null)
|
||||
return null;
|
||||
return (from track in _database.Tracks where track.Episode.ShowID == showID
|
||||
&& track.Episode.SeasonNumber == seasonNumber
|
||||
&& track.Episode.EpisodeNumber == episodeNumber
|
||||
&& track.Language == languageTag select track).FirstOrDefault();
|
||||
&& track.Episode.SeasonNumber == seasonNumber
|
||||
&& track.Episode.EpisodeNumber == episodeNumber
|
||||
&& track.Language == languageTag select track).FirstOrDefault();
|
||||
}
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ namespace Kyoo.Controllers
|
||||
where l.CollectionID == null select show).AsEnumerable().Union(
|
||||
from collection in _database.Collections select collection.AsShow())
|
||||
.Where(x => EF.Functions.Like(x.Title, $"%{searchQuery}%")
|
||||
|| EF.Functions.Like(x.GetAliases(), $"%{searchQuery}%"))
|
||||
|| EF.Functions.Like(x.GetAliases(), $"%{searchQuery}%"))
|
||||
.Take(20).OrderBy(x => x.Title);
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
return (from season in _database.Seasons
|
||||
where season.SeasonNumber == seasonNumber
|
||||
&& season.Show.Slug == showSlug
|
||||
&& season.Show.Slug == showSlug
|
||||
select season).FirstOrDefault();
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
return (from season in _database.Seasons
|
||||
where season.SeasonNumber == seasonNumber
|
||||
&& season.Show.Slug == showSlug
|
||||
&& season.Show.Slug == showSlug
|
||||
select season).FirstOrDefault()?.Episodes.Count() ?? 0;
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ namespace Kyoo.Controllers
|
||||
public IEnumerable<Episode> GetEpisodes(string showSlug, long seasonNumber)
|
||||
{
|
||||
return (from episode in _database.Episodes where episode.SeasonNumber == seasonNumber
|
||||
&& episode.Show.Slug == showSlug select episode)
|
||||
&& episode.Show.Slug == showSlug select episode)
|
||||
.OrderBy(x => x.EpisodeNumber)
|
||||
.Select(x => x.SetLink(showSlug));
|
||||
}
|
||||
@ -127,20 +127,20 @@ namespace Kyoo.Controllers
|
||||
public IEnumerable<Episode> GetEpisodes(long showID, long seasonNumber)
|
||||
{
|
||||
return from episode in _database.Episodes where episode.ShowID == showID
|
||||
&& episode.SeasonNumber == seasonNumber select episode.SetLink(episode.Show.Slug);
|
||||
&& episode.SeasonNumber == seasonNumber select episode.SetLink(episode.Show.Slug);
|
||||
}
|
||||
|
||||
public Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
return (from episode in _database.Episodes where episode.EpisodeNumber == episodeNumber
|
||||
&& episode.SeasonNumber == seasonNumber
|
||||
&& episode.Show.Slug == showSlug select episode.SetLink(showSlug)).FirstOrDefault();
|
||||
&& episode.Show.Slug == showSlug select episode.SetLink(showSlug)).FirstOrDefault();
|
||||
}
|
||||
|
||||
public WatchItem GetWatchItem(string showSlug, long seasonNumber, long episodeNumber, bool complete = true)
|
||||
{
|
||||
WatchItem item = (from episode in _database.Episodes where episode.SeasonNumber == seasonNumber
|
||||
&& episode.EpisodeNumber == episodeNumber && episode.Show.Slug == showSlug
|
||||
&& episode.EpisodeNumber == episodeNumber && episode.Show.Slug == showSlug
|
||||
select new WatchItem(episode.ID,
|
||||
episode.Show.Title,
|
||||
episode.Show.Slug,
|
||||
|
@ -49,16 +49,16 @@ namespace Kyoo.Controllers
|
||||
}
|
||||
|
||||
public T GetPlugin<T>(string name)
|
||||
{
|
||||
if (_plugins == null)
|
||||
return default;
|
||||
{
|
||||
if (_plugins == null)
|
||||
return default;
|
||||
return (T)(from plugin in _plugins where plugin.Name == name && plugin is T select plugin).FirstOrDefault();
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetPlugins<T>()
|
||||
{
|
||||
if (_plugins == null)
|
||||
return new List<T>();
|
||||
{
|
||||
if (_plugins == null)
|
||||
return new List<T>();
|
||||
return from plugin in _plugins where plugin is T select (T)plugin;
|
||||
}
|
||||
|
||||
@ -72,20 +72,20 @@ namespace Kyoo.Controllers
|
||||
|
||||
_plugins = pluginsPaths.Select(path =>
|
||||
{
|
||||
try
|
||||
{
|
||||
PluginDependencyLoader loader = new PluginDependencyLoader(Path.GetFullPath(path));
|
||||
Assembly ass = loader.LoadFromAssemblyPath(Path.GetFullPath(path));
|
||||
return (from type in ass.GetTypes()
|
||||
where typeof(IPlugin).IsAssignableFrom(type)
|
||||
select (IPlugin) ActivatorUtilities.CreateInstance(_provider, type)).FirstOrDefault();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine($"Error loading the plugin at {path}.\nException: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}).Where(x => x != null).ToList();
|
||||
try
|
||||
{
|
||||
PluginDependencyLoader loader = new PluginDependencyLoader(Path.GetFullPath(path));
|
||||
Assembly ass = loader.LoadFromAssemblyPath(Path.GetFullPath(path));
|
||||
return (from type in ass.GetTypes()
|
||||
where typeof(IPlugin).IsAssignableFrom(type)
|
||||
select (IPlugin) ActivatorUtilities.CreateInstance(_provider, type)).FirstOrDefault();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine($"Error loading the plugin at {path}.\nException: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}).Where(x => x != null).ToList();
|
||||
}
|
||||
}
|
||||
}
|
@ -6,96 +6,96 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public class ProviderManager : IProviderManager
|
||||
{
|
||||
private readonly IEnumerable<IMetadataProvider> _providers;
|
||||
private readonly IThumbnailsManager _thumbnailsManager;
|
||||
public class ProviderManager : IProviderManager
|
||||
{
|
||||
private readonly IEnumerable<IMetadataProvider> _providers;
|
||||
private readonly IThumbnailsManager _thumbnailsManager;
|
||||
|
||||
public ProviderManager(IThumbnailsManager thumbnailsManager, IPluginManager pluginManager)
|
||||
{
|
||||
_thumbnailsManager = thumbnailsManager;
|
||||
_providers = pluginManager.GetPlugins<IMetadataProvider>();
|
||||
}
|
||||
public ProviderManager(IThumbnailsManager thumbnailsManager, IPluginManager pluginManager)
|
||||
{
|
||||
_thumbnailsManager = thumbnailsManager;
|
||||
_providers = pluginManager.GetPlugins<IMetadataProvider>();
|
||||
}
|
||||
|
||||
public async Task<T> GetMetadata<T>(Func<IMetadataProvider, Task<T>> providerCall, Library library, string what) where T : IMergable<T>, new()
|
||||
{
|
||||
T ret = new T();
|
||||
|
||||
foreach (IMetadataProvider provider in _providers.OrderBy(provider => Array.IndexOf(library.Providers, provider.Name)))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (library.Providers.Contains(provider.Name))
|
||||
ret = ret.Merge(await providerCall(provider));
|
||||
} catch (Exception ex) {
|
||||
Console.Error.WriteLine($"The provider {provider.Name} coudln't work for {what}. Exception: {ex.Message}");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<T>> GetMetadata<T>(Func<IMetadataProvider, Task<IEnumerable<T>>> providerCall, Library library, string what)
|
||||
{
|
||||
List<T> ret = new List<T>();
|
||||
|
||||
foreach (IMetadataProvider provider in _providers.OrderBy(provider => Array.IndexOf(library.Providers, provider.Name)))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (library.Providers.Contains(provider.Name))
|
||||
ret.AddRange(await providerCall(provider));
|
||||
} catch (Exception ex) {
|
||||
Console.Error.WriteLine($"The provider {provider.Name} coudln't work for {what}. Exception: {ex.Message}");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public async Task<Collection> GetCollectionFromName(string name, Library library)
|
||||
{
|
||||
Collection collection = await GetMetadata(provider => provider.GetCollectionFromName(name), library, $"the collection {name}");
|
||||
collection.Name ??= name;
|
||||
collection.Slug ??= Utility.ToSlug(name);
|
||||
return collection;
|
||||
}
|
||||
public async Task<T> GetMetadata<T>(Func<IMetadataProvider, Task<T>> providerCall, Library library, string what) where T : IMergable<T>, new()
|
||||
{
|
||||
T ret = new T();
|
||||
|
||||
foreach (IMetadataProvider provider in _providers.OrderBy(provider => Array.IndexOf(library.Providers, provider.Name)))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (library.Providers.Contains(provider.Name))
|
||||
ret = ret.Merge(await providerCall(provider));
|
||||
} catch (Exception ex) {
|
||||
Console.Error.WriteLine($"The provider {provider.Name} coudln't work for {what}. Exception: {ex.Message}");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<T>> GetMetadata<T>(Func<IMetadataProvider, Task<IEnumerable<T>>> providerCall, Library library, string what)
|
||||
{
|
||||
List<T> ret = new List<T>();
|
||||
|
||||
foreach (IMetadataProvider provider in _providers.OrderBy(provider => Array.IndexOf(library.Providers, provider.Name)))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (library.Providers.Contains(provider.Name))
|
||||
ret.AddRange(await providerCall(provider));
|
||||
} catch (Exception ex) {
|
||||
Console.Error.WriteLine($"The provider {provider.Name} coudln't work for {what}. Exception: {ex.Message}");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public async Task<Collection> GetCollectionFromName(string name, Library library)
|
||||
{
|
||||
Collection collection = await GetMetadata(provider => provider.GetCollectionFromName(name), library, $"the collection {name}");
|
||||
collection.Name ??= name;
|
||||
collection.Slug ??= Utility.ToSlug(name);
|
||||
return collection;
|
||||
}
|
||||
|
||||
public async Task<Show> GetShowFromName(string showName, string showPath, bool isMovie, Library library)
|
||||
{
|
||||
Show show = await GetMetadata(provider => provider.GetShowFromName(showName, isMovie), library, $"the show {showName}");
|
||||
show.Path = showPath;
|
||||
show.Slug = Utility.ToSlug(showName);
|
||||
show.Title ??= showName;
|
||||
show.IsMovie = isMovie;
|
||||
await _thumbnailsManager.Validate(show);
|
||||
return show;
|
||||
}
|
||||
public async Task<Show> GetShowFromName(string showName, string showPath, bool isMovie, Library library)
|
||||
{
|
||||
Show show = await GetMetadata(provider => provider.GetShowFromName(showName, isMovie), library, $"the show {showName}");
|
||||
show.Path = showPath;
|
||||
show.Slug = Utility.ToSlug(showName);
|
||||
show.Title ??= showName;
|
||||
show.IsMovie = isMovie;
|
||||
await _thumbnailsManager.Validate(show);
|
||||
return show;
|
||||
}
|
||||
|
||||
public async Task<Season> GetSeason(Show show, long seasonNumber, Library library)
|
||||
{
|
||||
Season season = await GetMetadata(provider => provider.GetSeason(show, seasonNumber), library, $"the season {seasonNumber} of {show.Title}");
|
||||
season.ShowID = show.ID;
|
||||
season.SeasonNumber = season.SeasonNumber == -1 ? seasonNumber : season.SeasonNumber;
|
||||
season.Title ??= $"Season {season.SeasonNumber}";
|
||||
return season;
|
||||
}
|
||||
public async Task<Season> GetSeason(Show show, long seasonNumber, Library library)
|
||||
{
|
||||
Season season = await GetMetadata(provider => provider.GetSeason(show, seasonNumber), library, $"the season {seasonNumber} of {show.Title}");
|
||||
season.ShowID = show.ID;
|
||||
season.SeasonNumber = season.SeasonNumber == -1 ? seasonNumber : season.SeasonNumber;
|
||||
season.Title ??= $"Season {season.SeasonNumber}";
|
||||
return season;
|
||||
}
|
||||
|
||||
public async Task<Episode> GetEpisode(Show show, string episodePath, long seasonNumber, long episodeNumber, long absoluteNumber, Library library)
|
||||
{
|
||||
Episode episode = await GetMetadata(provider => provider.GetEpisode(show, seasonNumber, episodeNumber, absoluteNumber), library, "an episode");
|
||||
episode.ShowID = show.ID;
|
||||
episode.Path = episodePath;
|
||||
episode.SeasonNumber = episode.SeasonNumber != -1 ? episode.SeasonNumber : seasonNumber;
|
||||
episode.EpisodeNumber = episode.EpisodeNumber != -1 ? episode.EpisodeNumber : episodeNumber;
|
||||
episode.AbsoluteNumber = episode.AbsoluteNumber != -1 ? episode.AbsoluteNumber : absoluteNumber;
|
||||
await _thumbnailsManager.Validate(episode);
|
||||
return episode;
|
||||
}
|
||||
public async Task<Episode> GetEpisode(Show show, string episodePath, long seasonNumber, long episodeNumber, long absoluteNumber, Library library)
|
||||
{
|
||||
Episode episode = await GetMetadata(provider => provider.GetEpisode(show, seasonNumber, episodeNumber, absoluteNumber), library, "an episode");
|
||||
episode.ShowID = show.ID;
|
||||
episode.Path = episodePath;
|
||||
episode.SeasonNumber = episode.SeasonNumber != -1 ? episode.SeasonNumber : seasonNumber;
|
||||
episode.EpisodeNumber = episode.EpisodeNumber != -1 ? episode.EpisodeNumber : episodeNumber;
|
||||
episode.AbsoluteNumber = episode.AbsoluteNumber != -1 ? episode.AbsoluteNumber : absoluteNumber;
|
||||
await _thumbnailsManager.Validate(episode);
|
||||
return episode;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PeopleLink>> GetPeople(Show show, Library library)
|
||||
{
|
||||
IEnumerable<PeopleLink> people = await GetMetadata(provider => provider.GetPeople(show), library, "unknown data");
|
||||
people = await _thumbnailsManager.Validate(people.ToList());
|
||||
return people;
|
||||
}
|
||||
}
|
||||
public async Task<IEnumerable<PeopleLink>> GetPeople(Show show, Library library)
|
||||
{
|
||||
IEnumerable<PeopleLink> people = await GetMetadata(provider => provider.GetPeople(show), library, "unknown data");
|
||||
people = await _thumbnailsManager.Validate(people.ToList());
|
||||
return people;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace Kyoo.Controllers
|
||||
serviceScope.ServiceProvider.GetService<DatabaseContext>().Database.EnsureCreated();
|
||||
// Use the next line if the database is not SQLite (SQLite doesn't support complexe migrations).
|
||||
// serviceScope.ServiceProvider.GetService<DatabaseContext>().Database.Migrate();;
|
||||
|
||||
|
||||
IPluginManager pluginManager = serviceScope.ServiceProvider.GetService<IPluginManager>();
|
||||
pluginManager.ReloadPlugins();
|
||||
|
||||
|
@ -8,110 +8,110 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
public class ThumbnailsManager : IThumbnailsManager
|
||||
{
|
||||
private readonly IConfiguration _config;
|
||||
public class ThumbnailsManager : IThumbnailsManager
|
||||
{
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
public ThumbnailsManager(IConfiguration configuration)
|
||||
{
|
||||
_config = configuration;
|
||||
}
|
||||
public ThumbnailsManager(IConfiguration configuration)
|
||||
{
|
||||
_config = configuration;
|
||||
}
|
||||
|
||||
public async Task<Show> Validate(Show show)
|
||||
{
|
||||
if (show?.Path == null)
|
||||
return null;
|
||||
string localThumb = Path.Combine(show.Path, "poster.jpg");
|
||||
string localLogo = Path.Combine(show.Path, "logo.png");
|
||||
string localBackdrop = Path.Combine(show.Path, "backdrop.jpg");
|
||||
public async Task<Show> Validate(Show show)
|
||||
{
|
||||
if (show?.Path == null)
|
||||
return null;
|
||||
string localThumb = Path.Combine(show.Path, "poster.jpg");
|
||||
string localLogo = Path.Combine(show.Path, "logo.png");
|
||||
string localBackdrop = Path.Combine(show.Path, "backdrop.jpg");
|
||||
|
||||
|
||||
if (show.ImgPrimary != null && !File.Exists(localThumb))
|
||||
{
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(show.ImgPrimary), localThumb);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe poster of {show.Title} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
}
|
||||
if (show.ImgPrimary != null && !File.Exists(localThumb))
|
||||
{
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(show.ImgPrimary), localThumb);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe poster of {show.Title} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
}
|
||||
|
||||
if (show.ImgLogo != null && !File.Exists(localLogo))
|
||||
{
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(show.ImgLogo), localLogo);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe logo of {show.Title} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
}
|
||||
if (show.ImgLogo != null && !File.Exists(localLogo))
|
||||
{
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(show.ImgLogo), localLogo);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe logo of {show.Title} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
}
|
||||
|
||||
if (show.ImgBackdrop != null && !File.Exists(localBackdrop))
|
||||
{
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(show.ImgBackdrop), localBackdrop);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe backdrop of {show.Title} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
}
|
||||
if (show.ImgBackdrop != null && !File.Exists(localBackdrop))
|
||||
{
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(show.ImgBackdrop), localBackdrop);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe backdrop of {show.Title} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
}
|
||||
|
||||
return show;
|
||||
}
|
||||
return show;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PeopleLink>> Validate(List<PeopleLink> people)
|
||||
{
|
||||
if (people == null)
|
||||
return null;
|
||||
foreach (PeopleLink peop in people)
|
||||
{
|
||||
string root = _config.GetValue<string>("peoplePath");
|
||||
Directory.CreateDirectory(root);
|
||||
public async Task<IEnumerable<PeopleLink>> Validate(List<PeopleLink> people)
|
||||
{
|
||||
if (people == null)
|
||||
return null;
|
||||
foreach (PeopleLink peop in people)
|
||||
{
|
||||
string root = _config.GetValue<string>("peoplePath");
|
||||
Directory.CreateDirectory(root);
|
||||
|
||||
string localThumb = root + "/" + peop.People.Slug + ".jpg";
|
||||
if (peop.People.ImgPrimary == null || File.Exists(localThumb))
|
||||
continue;
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(peop.People.ImgPrimary), localThumb);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe profile picture of {peop.People.Name} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
}
|
||||
string localThumb = root + "/" + peop.People.Slug + ".jpg";
|
||||
if (peop.People.ImgPrimary == null || File.Exists(localThumb))
|
||||
continue;
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(peop.People.ImgPrimary), localThumb);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe profile picture of {peop.People.Name} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
}
|
||||
|
||||
return people;
|
||||
}
|
||||
return people;
|
||||
}
|
||||
|
||||
public async Task<Episode> Validate(Episode episode)
|
||||
{
|
||||
if (episode == null || episode.Path == null)
|
||||
return null;
|
||||
string localThumb = Path.ChangeExtension(episode.Path, "jpg");
|
||||
if (episode.ImgPrimary == null || File.Exists(localThumb))
|
||||
return episode;
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(episode.ImgPrimary), localThumb);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe thumbnail of {episode.Show.Title} s{episode.SeasonNumber}e{episode.EpisodeNumber} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
public async Task<Episode> Validate(Episode episode)
|
||||
{
|
||||
if (episode == null || episode.Path == null)
|
||||
return null;
|
||||
string localThumb = Path.ChangeExtension(episode.Path, "jpg");
|
||||
if (episode.ImgPrimary == null || File.Exists(localThumb))
|
||||
return episode;
|
||||
try
|
||||
{
|
||||
using WebClient client = new WebClient();
|
||||
await client.DownloadFileTaskAsync(new Uri(episode.ImgPrimary), localThumb);
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"\tThe thumbnail of {episode.Show.Title} s{episode.SeasonNumber}e{episode.EpisodeNumber} could not be downloaded.\n\tError: {exception.Message}. ");
|
||||
}
|
||||
|
||||
return episode;
|
||||
}
|
||||
}
|
||||
return episode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,97 +13,97 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
public class BadTranscoderException : Exception {}
|
||||
|
||||
public class Transcoder : ITranscoder
|
||||
{
|
||||
private readonly string _transmuxPath;
|
||||
private readonly string _transcodePath;
|
||||
public class Transcoder : ITranscoder
|
||||
{
|
||||
private readonly string _transmuxPath;
|
||||
private readonly string _transcodePath;
|
||||
|
||||
public Transcoder(IConfiguration config)
|
||||
{
|
||||
_transmuxPath = config.GetValue<string>("transmuxTempPath");
|
||||
_transcodePath = config.GetValue<string>("transcodeTempPath");
|
||||
public Transcoder(IConfiguration config)
|
||||
{
|
||||
_transmuxPath = config.GetValue<string>("transmuxTempPath");
|
||||
_transcodePath = config.GetValue<string>("transcodeTempPath");
|
||||
|
||||
if (TranscoderAPI.init() != Marshal.SizeOf<Models.Watch.Stream>())
|
||||
throw new BadTranscoderException();
|
||||
}
|
||||
if (TranscoderAPI.init() != Marshal.SizeOf<Models.Watch.Stream>())
|
||||
throw new BadTranscoderException();
|
||||
}
|
||||
|
||||
public async Task<Track[]> GetTrackInfo(string path)
|
||||
{
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
TranscoderAPI.GetTrackInfo(path, out Track[] tracks);
|
||||
return tracks;
|
||||
});
|
||||
}
|
||||
public async Task<Track[]> GetTrackInfo(string path)
|
||||
{
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
TranscoderAPI.GetTrackInfo(path, out Track[] tracks);
|
||||
return tracks;
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<Track[]> ExtractSubtitles(string path)
|
||||
{
|
||||
string output = Path.Combine(Path.GetDirectoryName(path), "Subtitles");
|
||||
Directory.CreateDirectory(output);
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
TranscoderAPI.ExtractSubtitles(path, output, out Track[] tracks);
|
||||
return tracks;
|
||||
});
|
||||
}
|
||||
public async Task<Track[]> ExtractSubtitles(string path)
|
||||
{
|
||||
string output = Path.Combine(Path.GetDirectoryName(path), "Subtitles");
|
||||
Directory.CreateDirectory(output);
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
TranscoderAPI.ExtractSubtitles(path, output, out Track[] tracks);
|
||||
return tracks;
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<string> Transmux(WatchItem episode)
|
||||
{
|
||||
string folder = Path.Combine(_transmuxPath, episode.Link);
|
||||
string manifest = Path.Combine(folder, episode.Link + ".m3u8");
|
||||
float playableDuration = 0;
|
||||
bool transmuxFailed = false;
|
||||
public async Task<string> Transmux(WatchItem episode)
|
||||
{
|
||||
string folder = Path.Combine(_transmuxPath, episode.Link);
|
||||
string manifest = Path.Combine(folder, episode.Link + ".m3u8");
|
||||
float playableDuration = 0;
|
||||
bool transmuxFailed = false;
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(folder);
|
||||
Debug.WriteLine("&Transmuxing " + episode.Link + " at " + episode.Path + ", outputPath: " + folder);
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(folder);
|
||||
Debug.WriteLine("&Transmuxing " + episode.Link + " at " + episode.Path + ", outputPath: " + folder);
|
||||
|
||||
if (File.Exists(manifest))
|
||||
return manifest;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
Console.Error.WriteLine($"Access to the path {manifest} is denied. Please change your transmux path in the config.");
|
||||
return null;
|
||||
}
|
||||
Task.Run(() =>
|
||||
{
|
||||
transmuxFailed = TranscoderAPI.transmux(episode.Path, manifest.Replace('\\', '/'), out playableDuration) != 0;
|
||||
});
|
||||
while (playableDuration < 10 || (!File.Exists(manifest) && !transmuxFailed))
|
||||
await Task.Delay(10);
|
||||
return transmuxFailed ? null : manifest;
|
||||
}
|
||||
if (File.Exists(manifest))
|
||||
return manifest;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
Console.Error.WriteLine($"Access to the path {manifest} is denied. Please change your transmux path in the config.");
|
||||
return null;
|
||||
}
|
||||
Task.Run(() =>
|
||||
{
|
||||
transmuxFailed = TranscoderAPI.transmux(episode.Path, manifest.Replace('\\', '/'), out playableDuration) != 0;
|
||||
});
|
||||
while (playableDuration < 10 || (!File.Exists(manifest) && !transmuxFailed))
|
||||
await Task.Delay(10);
|
||||
return transmuxFailed ? null : manifest;
|
||||
}
|
||||
|
||||
public async Task<string> Transcode(WatchItem episode)
|
||||
{
|
||||
string folder = Path.Combine(_transcodePath, episode.Link);
|
||||
string manifest = Path.Combine(folder, episode.Link + ".m3u8");
|
||||
float playableDuration = 0;
|
||||
bool transmuxFailed = false;
|
||||
public async Task<string> Transcode(WatchItem episode)
|
||||
{
|
||||
string folder = Path.Combine(_transcodePath, episode.Link);
|
||||
string manifest = Path.Combine(folder, episode.Link + ".m3u8");
|
||||
float playableDuration = 0;
|
||||
bool transmuxFailed = false;
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(folder);
|
||||
Debug.WriteLine("&Transcoding " + episode.Link + " at " + episode.Path + ", outputPath: " + folder);
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(folder);
|
||||
Debug.WriteLine("&Transcoding " + episode.Link + " at " + episode.Path + ", outputPath: " + folder);
|
||||
|
||||
if (File.Exists(manifest))
|
||||
return manifest;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
Console.Error.WriteLine($"Access to the path {manifest} is denied. Please change your transmux path in the config.");
|
||||
return null;
|
||||
}
|
||||
if (File.Exists(manifest))
|
||||
return manifest;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
Console.Error.WriteLine($"Access to the path {manifest} is denied. Please change your transmux path in the config.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
transmuxFailed = TranscoderAPI.transcode(episode.Path, manifest.Replace('\\', '/'), out playableDuration) != 0;
|
||||
});
|
||||
while (playableDuration < 10 || (!File.Exists(manifest) && !transmuxFailed))
|
||||
await Task.Delay(10);
|
||||
return transmuxFailed ? null : manifest;
|
||||
}
|
||||
}
|
||||
Task.Run(() =>
|
||||
{
|
||||
transmuxFailed = TranscoderAPI.transcode(episode.Path, manifest.Replace('\\', '/'), out playableDuration) != 0;
|
||||
});
|
||||
while (playableDuration < 10 || (!File.Exists(manifest) && !transmuxFailed))
|
||||
await Task.Delay(10);
|
||||
return transmuxFailed ? null : manifest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,88 +8,88 @@ using Kyoo.Models.Watch;
|
||||
|
||||
namespace Kyoo.Controllers.TranscoderLink
|
||||
{
|
||||
public static class TranscoderAPI
|
||||
{
|
||||
private const string TranscoderPath = "libtranscoder.so";
|
||||
public static class TranscoderAPI
|
||||
{
|
||||
private const string TranscoderPath = "libtranscoder.so";
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int init();
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int init();
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int transmux(string path, string out_path, out float playableDuration);
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int transcode(string path, string out_path, out float playableDuration);
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int transmux(string path, string out_path, out float playableDuration);
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int transcode(string path, string out_path, out float playableDuration);
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr get_track_info(string path, out int array_length, out int track_count);
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr extract_subtitles(string path, string out_path, out int array_length, out int track_count);
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr get_track_info(string path, out int array_length, out int track_count);
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr extract_subtitles(string path, string out_path, out int array_length, out int track_count);
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void free_streams(IntPtr stream_ptr);
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void free(IntPtr ptr);
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void free_streams(IntPtr stream_ptr);
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void free(IntPtr ptr);
|
||||
|
||||
|
||||
public static void GetTrackInfo(string path, out Track[] tracks)
|
||||
{
|
||||
int size = Marshal.SizeOf<Stream>();
|
||||
IntPtr ptr = get_track_info(path, out int arrayLength, out int trackCount);
|
||||
IntPtr streamsPtr = ptr;
|
||||
public static void GetTrackInfo(string path, out Track[] tracks)
|
||||
{
|
||||
int size = Marshal.SizeOf<Stream>();
|
||||
IntPtr ptr = get_track_info(path, out int arrayLength, out int trackCount);
|
||||
IntPtr streamsPtr = ptr;
|
||||
|
||||
if (trackCount > 0 && ptr != IntPtr.Zero)
|
||||
{
|
||||
tracks = new Track[trackCount];
|
||||
if (trackCount > 0 && ptr != IntPtr.Zero)
|
||||
{
|
||||
tracks = new Track[trackCount];
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < arrayLength; i++)
|
||||
{
|
||||
Stream stream = Marshal.PtrToStructure<Stream>(streamsPtr);
|
||||
if (stream.Type != StreamType.Unknow)
|
||||
{
|
||||
tracks[j] = new Track(stream);
|
||||
j++;
|
||||
}
|
||||
streamsPtr += size;
|
||||
}
|
||||
}
|
||||
else
|
||||
tracks = new Track[0];
|
||||
int j = 0;
|
||||
for (int i = 0; i < arrayLength; i++)
|
||||
{
|
||||
Stream stream = Marshal.PtrToStructure<Stream>(streamsPtr);
|
||||
if (stream.Type != StreamType.Unknow)
|
||||
{
|
||||
tracks[j] = new Track(stream);
|
||||
j++;
|
||||
}
|
||||
streamsPtr += size;
|
||||
}
|
||||
}
|
||||
else
|
||||
tracks = new Track[0];
|
||||
|
||||
free(ptr);
|
||||
Console.WriteLine($"\t{tracks.Length} tracks got at: {path}");
|
||||
}
|
||||
free(ptr);
|
||||
Console.WriteLine($"\t{tracks.Length} tracks got at: {path}");
|
||||
}
|
||||
|
||||
public static void ExtractSubtitles(string path, string outPath, out Track[] tracks)
|
||||
{
|
||||
int size = Marshal.SizeOf<Stream>();
|
||||
IntPtr ptr = extract_subtitles(path, outPath, out int arrayLength, out int trackCount);
|
||||
IntPtr streamsPtr = ptr;
|
||||
public static void ExtractSubtitles(string path, string outPath, out Track[] tracks)
|
||||
{
|
||||
int size = Marshal.SizeOf<Stream>();
|
||||
IntPtr ptr = extract_subtitles(path, outPath, out int arrayLength, out int trackCount);
|
||||
IntPtr streamsPtr = ptr;
|
||||
|
||||
if (trackCount > 0 && ptr != IntPtr.Zero)
|
||||
{
|
||||
tracks = new Track[trackCount];
|
||||
if (trackCount > 0 && ptr != IntPtr.Zero)
|
||||
{
|
||||
tracks = new Track[trackCount];
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < arrayLength; i++)
|
||||
{
|
||||
Stream stream = Marshal.PtrToStructure<Stream>(streamsPtr);
|
||||
if (stream.Type != StreamType.Unknow)
|
||||
{
|
||||
tracks[j] = new Track(stream);
|
||||
j++;
|
||||
}
|
||||
streamsPtr += size;
|
||||
}
|
||||
}
|
||||
else
|
||||
tracks = new Track[0];
|
||||
int j = 0;
|
||||
for (int i = 0; i < arrayLength; i++)
|
||||
{
|
||||
Stream stream = Marshal.PtrToStructure<Stream>(streamsPtr);
|
||||
if (stream.Type != StreamType.Unknow)
|
||||
{
|
||||
tracks[j] = new Track(stream);
|
||||
j++;
|
||||
}
|
||||
streamsPtr += size;
|
||||
}
|
||||
}
|
||||
else
|
||||
tracks = new Track[0];
|
||||
|
||||
free(ptr);
|
||||
Console.WriteLine($"\t{tracks.Count(x => x.Type == StreamType.Subtitle)} subtitles got at: {path}");
|
||||
}
|
||||
}
|
||||
free(ptr);
|
||||
Console.WriteLine($"\t{tracks.Count(x => x.Type == StreamType.Subtitle)} subtitles got at: {path}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,65 +7,65 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace Kyoo
|
||||
{
|
||||
public class DatabaseContext : DbContext
|
||||
{
|
||||
public DatabaseContext(DbContextOptions options) : base(options) { }
|
||||
public class DatabaseContext : DbContext
|
||||
{
|
||||
public DatabaseContext(DbContextOptions options) : base(options) { }
|
||||
|
||||
public DbSet<Library> Libraries { get; set; }
|
||||
public DbSet<Collection> Collections { get; set; }
|
||||
public DbSet<Show> Shows { get; set; }
|
||||
public DbSet<Season> Seasons { get; set; }
|
||||
public DbSet<Episode> Episodes { get; set; }
|
||||
public DbSet<Track> Tracks { get; set; }
|
||||
public DbSet<Genre> Genres { get; set; }
|
||||
public DbSet<People> Peoples { get; set; }
|
||||
public DbSet<Studio> Studios { get; set; }
|
||||
|
||||
public DbSet<LibraryLink> LibraryLinks { get; set; }
|
||||
public DbSet<CollectionLink> CollectionLinks { get; set; }
|
||||
public DbSet<PeopleLink> PeopleLinks { get; set; }
|
||||
|
||||
// This is used because EF doesn't support Many-To-Many relationships so for now we need to override the getter/setters to store this.
|
||||
public DbSet<GenreLink> GenreLinks { get; set; }
|
||||
|
||||
|
||||
private ValueConverter<string[], string> stringArrayConverter = new ValueConverter<string[], string>(
|
||||
arr => string.Join("|", arr),
|
||||
str => str.Split("|", StringSplitOptions.None));
|
||||
public DbSet<Library> Libraries { get; set; }
|
||||
public DbSet<Collection> Collections { get; set; }
|
||||
public DbSet<Show> Shows { get; set; }
|
||||
public DbSet<Season> Seasons { get; set; }
|
||||
public DbSet<Episode> Episodes { get; set; }
|
||||
public DbSet<Track> Tracks { get; set; }
|
||||
public DbSet<Genre> Genres { get; set; }
|
||||
public DbSet<People> Peoples { get; set; }
|
||||
public DbSet<Studio> Studios { get; set; }
|
||||
|
||||
public DbSet<LibraryLink> LibraryLinks { get; set; }
|
||||
public DbSet<CollectionLink> CollectionLinks { get; set; }
|
||||
public DbSet<PeopleLink> PeopleLinks { get; set; }
|
||||
|
||||
// This is used because EF doesn't support Many-To-Many relationships so for now we need to override the getter/setters to store this.
|
||||
public DbSet<GenreLink> GenreLinks { get; set; }
|
||||
|
||||
|
||||
private ValueConverter<string[], string> stringArrayConverter = new ValueConverter<string[], string>(
|
||||
arr => string.Join("|", arr),
|
||||
str => str.Split("|", StringSplitOptions.None));
|
||||
|
||||
private ValueComparer<string[]> stringArrayComparer = new ValueComparer<string[]>(
|
||||
(l1, l2) => l1.SequenceEqual(l2),
|
||||
arr => arr.Aggregate(0, (i, s) => s.GetHashCode()));
|
||||
private ValueComparer<string[]> stringArrayComparer = new ValueComparer<string[]>(
|
||||
(l1, l2) => l1.SequenceEqual(l2),
|
||||
arr => arr.Aggregate(0, (i, s) => s.GetHashCode()));
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<Library>().Property(e => e.Paths).HasConversion(stringArrayConverter).Metadata.SetValueComparer(stringArrayComparer);
|
||||
modelBuilder.Entity<Library>().Property(e => e.Providers).HasConversion(stringArrayConverter).Metadata.SetValueComparer(stringArrayComparer);
|
||||
modelBuilder.Entity<Show>().Property(e => e.Aliases).HasConversion(stringArrayConverter).Metadata.SetValueComparer(stringArrayComparer);
|
||||
modelBuilder.Entity<Library>().Property(e => e.Paths).HasConversion(stringArrayConverter).Metadata.SetValueComparer(stringArrayComparer);
|
||||
modelBuilder.Entity<Library>().Property(e => e.Providers).HasConversion(stringArrayConverter).Metadata.SetValueComparer(stringArrayComparer);
|
||||
modelBuilder.Entity<Show>().Property(e => e.Aliases).HasConversion(stringArrayConverter).Metadata.SetValueComparer(stringArrayComparer);
|
||||
|
||||
modelBuilder.Entity<Track>()
|
||||
.Property(t => t.IsDefault)
|
||||
.ValueGeneratedNever();
|
||||
|
||||
modelBuilder.Entity<Track>()
|
||||
.Property(t => t.IsForced)
|
||||
.ValueGeneratedNever();
|
||||
|
||||
modelBuilder.Entity<People>()
|
||||
.HasKey(x => x.Slug);
|
||||
modelBuilder.Entity<Track>()
|
||||
.Property(t => t.IsDefault)
|
||||
.ValueGeneratedNever();
|
||||
|
||||
modelBuilder.Entity<Track>()
|
||||
.Property(t => t.IsForced)
|
||||
.ValueGeneratedNever();
|
||||
|
||||
modelBuilder.Entity<People>()
|
||||
.HasKey(x => x.Slug);
|
||||
|
||||
modelBuilder.Entity<GenreLink>()
|
||||
.HasKey(x => new {x.ShowID, x.GenreID});
|
||||
|
||||
modelBuilder.Entity<Show>()
|
||||
.Ignore(x => x.Genres);
|
||||
|
||||
// modelBuilder.Entity<Genre>()
|
||||
// .Ignore(x => x.Shows);
|
||||
}
|
||||
}
|
||||
modelBuilder.Entity<GenreLink>()
|
||||
.HasKey(x => new {x.ShowID, x.GenreID});
|
||||
|
||||
modelBuilder.Entity<Show>()
|
||||
.Ignore(x => x.Genres);
|
||||
|
||||
// modelBuilder.Entity<Genre>()
|
||||
// .Ignore(x => x.Shows);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class DbSetExtension
|
||||
|
@ -4,17 +4,17 @@ using Kyoo.Controllers;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class AdminController : ControllerBase
|
||||
{
|
||||
[HttpGet("scan")]
|
||||
public IActionResult ScanLibrary([FromServices] ICrawler crawler)
|
||||
{
|
||||
// The crawler is destroyed before the completion of this task.
|
||||
// TODO implement an hosted service that can queue tasks from the controller.
|
||||
crawler.StartAsync(new CancellationToken());
|
||||
return Ok("Scanning");
|
||||
}
|
||||
}
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class AdminController : ControllerBase
|
||||
{
|
||||
[HttpGet("scan")]
|
||||
public IActionResult ScanLibrary([FromServices] ICrawler crawler)
|
||||
{
|
||||
// The crawler is destroyed before the completion of this task.
|
||||
// TODO implement an hosted service that can queue tasks from the controller.
|
||||
crawler.StartAsync(new CancellationToken());
|
||||
return Ok("Scanning");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,12 @@ using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
public class AuthentificationAPI : Controller
|
||||
{
|
||||
// [Authorize, HttpGet("/connect/authorize")]
|
||||
// public async Task<IActionResult> Authorize(CancellationToken token)
|
||||
// {
|
||||
// //HttpContext.GetOpenIdConnectResponse()
|
||||
// }
|
||||
}
|
||||
public class AuthentificationAPI : Controller
|
||||
{
|
||||
// [Authorize, HttpGet("/connect/authorize")]
|
||||
// public async Task<IActionResult> Authorize(CancellationToken token)
|
||||
// {
|
||||
// //HttpContext.GetOpenIdConnectResponse()
|
||||
// }
|
||||
}
|
||||
}
|
@ -5,26 +5,26 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class CollectionController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class CollectionController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public CollectionController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
public CollectionController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet("{collectionSlug}")]
|
||||
public ActionResult<Collection> GetShows(string collectionSlug)
|
||||
{
|
||||
Collection collection = _libraryManager.GetCollection(collectionSlug);
|
||||
[HttpGet("{collectionSlug}")]
|
||||
public ActionResult<Collection> GetShows(string collectionSlug)
|
||||
{
|
||||
Collection collection = _libraryManager.GetCollection(collectionSlug);
|
||||
|
||||
if (collection == null)
|
||||
return NotFound();
|
||||
if (collection == null)
|
||||
return NotFound();
|
||||
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,38 +6,38 @@ using Kyoo.Controllers;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class EpisodesController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class EpisodesController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public EpisodesController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
public EpisodesController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet("{showSlug}/season/{seasonNumber}")]
|
||||
public ActionResult<IEnumerable<Episode>> GetEpisodesForSeason(string showSlug, long seasonNumber)
|
||||
{
|
||||
IEnumerable<Episode> episodes = _libraryManager.GetEpisodes(showSlug, seasonNumber);
|
||||
[HttpGet("{showSlug}/season/{seasonNumber}")]
|
||||
public ActionResult<IEnumerable<Episode>> GetEpisodesForSeason(string showSlug, long seasonNumber)
|
||||
{
|
||||
IEnumerable<Episode> episodes = _libraryManager.GetEpisodes(showSlug, seasonNumber);
|
||||
|
||||
if(episodes == null)
|
||||
return NotFound();
|
||||
if(episodes == null)
|
||||
return NotFound();
|
||||
|
||||
return episodes.ToList();
|
||||
}
|
||||
return episodes.ToList();
|
||||
}
|
||||
|
||||
[HttpGet("{showSlug}/season/{seasonNumber}/episode/{episodeNumber}")]
|
||||
[JsonDetailed]
|
||||
public ActionResult<Episode> GetEpisode(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber);
|
||||
[HttpGet("{showSlug}/season/{seasonNumber}/episode/{episodeNumber}")]
|
||||
[JsonDetailed]
|
||||
public ActionResult<Episode> GetEpisode(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber);
|
||||
|
||||
if (episode == null)
|
||||
return NotFound();
|
||||
if (episode == null)
|
||||
return NotFound();
|
||||
|
||||
return episode;
|
||||
}
|
||||
}
|
||||
return episode;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,32 +6,32 @@ using System.Linq;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("api/libraries")]
|
||||
[ApiController]
|
||||
public class LibrariesController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
[Route("api/libraries")]
|
||||
[ApiController]
|
||||
public class LibrariesController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public LibrariesController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
public LibrariesController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IEnumerable<Library> GetLibraries()
|
||||
{
|
||||
return _libraryManager.GetLibraries();
|
||||
}
|
||||
[HttpGet]
|
||||
public IEnumerable<Library> GetLibraries()
|
||||
{
|
||||
return _libraryManager.GetLibraries();
|
||||
}
|
||||
|
||||
[HttpGet("{librarySlug}")]
|
||||
public ActionResult<IEnumerable<Show>> GetShows(string librarySlug)
|
||||
{
|
||||
Library library = _libraryManager.GetLibrary(librarySlug);
|
||||
[HttpGet("{librarySlug}")]
|
||||
public ActionResult<IEnumerable<Show>> GetShows(string librarySlug)
|
||||
{
|
||||
Library library = _libraryManager.GetLibrary(librarySlug);
|
||||
|
||||
if (library == null)
|
||||
return NotFound();
|
||||
if (library == null)
|
||||
return NotFound();
|
||||
|
||||
return _libraryManager.GetShowsInLibrary(library.ID).ToList();
|
||||
}
|
||||
}
|
||||
return _libraryManager.GetShowsInLibrary(library.ID).ToList();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,30 +4,30 @@ using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class PeopleController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class PeopleController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public PeopleController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
public PeopleController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet("{peopleSlug}")]
|
||||
public ActionResult<Collection> GetPeople(string peopleSlug)
|
||||
{
|
||||
People people = _libraryManager.GetPeopleBySlug(peopleSlug);
|
||||
[HttpGet("{peopleSlug}")]
|
||||
public ActionResult<Collection> GetPeople(string peopleSlug)
|
||||
{
|
||||
People people = _libraryManager.GetPeopleBySlug(peopleSlug);
|
||||
|
||||
if (people == null)
|
||||
return NotFound();
|
||||
Collection collection = new Collection(people.Slug, people.Name, null, null)
|
||||
{
|
||||
Shows = _libraryManager.GetShowsByPeople(people.Slug),
|
||||
Poster = "peopleimg/" + people.Slug
|
||||
};
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
if (people == null)
|
||||
return NotFound();
|
||||
Collection collection = new Collection(people.Slug, people.Name, null, null)
|
||||
{
|
||||
Shows = _libraryManager.GetShowsByPeople(people.Slug),
|
||||
Poster = "peopleimg/" + people.Slug
|
||||
};
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,30 +4,30 @@ using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class SearchController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class SearchController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public SearchController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
public SearchController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet("{query}")]
|
||||
public ActionResult<SearchResult> Search(string query)
|
||||
{
|
||||
SearchResult result = new SearchResult
|
||||
{
|
||||
Query = query,
|
||||
Shows = _libraryManager.GetShows(query),
|
||||
Episodes = _libraryManager.SearchEpisodes(query),
|
||||
People = _libraryManager.SearchPeople(query),
|
||||
Genres = _libraryManager.SearchGenres(query),
|
||||
Studios = _libraryManager.SearchStudios(query)
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
[HttpGet("{query}")]
|
||||
public ActionResult<SearchResult> Search(string query)
|
||||
{
|
||||
SearchResult result = new SearchResult
|
||||
{
|
||||
Query = query,
|
||||
Shows = _libraryManager.GetShows(query),
|
||||
Episodes = _libraryManager.SearchEpisodes(query),
|
||||
People = _libraryManager.SearchPeople(query),
|
||||
Genres = _libraryManager.SearchGenres(query),
|
||||
Studios = _libraryManager.SearchStudios(query)
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,34 +5,34 @@ using Kyoo.Controllers;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("api/shows")]
|
||||
[Route("api/show")]
|
||||
[ApiController]
|
||||
public class ShowsController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
[Route("api/shows")]
|
||||
[Route("api/show")]
|
||||
[ApiController]
|
||||
public class ShowsController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public ShowsController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
public ShowsController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IEnumerable<Show> GetShows()
|
||||
{
|
||||
return _libraryManager.GetShows();
|
||||
}
|
||||
[HttpGet]
|
||||
public IEnumerable<Show> GetShows()
|
||||
{
|
||||
return _libraryManager.GetShows();
|
||||
}
|
||||
|
||||
[HttpGet("{slug}")]
|
||||
[JsonDetailed]
|
||||
public ActionResult<Show> GetShow(string slug)
|
||||
{
|
||||
Show show = _libraryManager.GetShowBySlug(slug);
|
||||
[HttpGet("{slug}")]
|
||||
[JsonDetailed]
|
||||
public ActionResult<Show> GetShow(string slug)
|
||||
{
|
||||
Show show = _libraryManager.GetShowBySlug(slug);
|
||||
|
||||
if (show == null)
|
||||
return NotFound();
|
||||
if (show == null)
|
||||
return NotFound();
|
||||
|
||||
return show;
|
||||
}
|
||||
}
|
||||
return show;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,171 +7,171 @@ using Kyoo.Controllers;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("[controller]")]
|
||||
[ApiController]
|
||||
public class SubtitleController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ITranscoder _transcoder;
|
||||
[Route("[controller]")]
|
||||
[ApiController]
|
||||
public class SubtitleController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ITranscoder _transcoder;
|
||||
|
||||
public SubtitleController(ILibraryManager libraryManager, ITranscoder transcoder)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_transcoder = transcoder;
|
||||
}
|
||||
public SubtitleController(ILibraryManager libraryManager, ITranscoder transcoder)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_transcoder = transcoder;
|
||||
}
|
||||
|
||||
[HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}.{identifier}.{extension?}")]
|
||||
public IActionResult GetSubtitle(string showSlug, int seasonNumber, int episodeNumber, string identifier, string extension)
|
||||
{
|
||||
string languageTag = identifier.Substring(0, 3);
|
||||
bool forced = identifier.Length > 3 && identifier.Substring(4) == "forced";
|
||||
[HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}.{identifier}.{extension?}")]
|
||||
public IActionResult GetSubtitle(string showSlug, int seasonNumber, int episodeNumber, string identifier, string extension)
|
||||
{
|
||||
string languageTag = identifier.Substring(0, 3);
|
||||
bool forced = identifier.Length > 3 && identifier.Substring(4) == "forced";
|
||||
|
||||
Track subtitle = _libraryManager.GetSubtitle(showSlug, seasonNumber, episodeNumber, languageTag, forced);
|
||||
Track subtitle = _libraryManager.GetSubtitle(showSlug, seasonNumber, episodeNumber, languageTag, forced);
|
||||
|
||||
if (subtitle == null)
|
||||
return NotFound();
|
||||
if (subtitle == null)
|
||||
return NotFound();
|
||||
|
||||
|
||||
if (subtitle.Codec == "subrip" && extension == "vtt") //The request wants a WebVTT from a Subrip subtitle, convert it on the fly and send it.
|
||||
{
|
||||
return new ConvertSubripToVtt(subtitle.Path);
|
||||
}
|
||||
if (subtitle.Codec == "subrip" && extension == "vtt") //The request wants a WebVTT from a Subrip subtitle, convert it on the fly and send it.
|
||||
{
|
||||
return new ConvertSubripToVtt(subtitle.Path);
|
||||
}
|
||||
|
||||
string mime;
|
||||
if (subtitle.Codec == "ass")
|
||||
mime = "text/x-ssa";
|
||||
else
|
||||
mime = "application/x-subrip";
|
||||
string mime;
|
||||
if (subtitle.Codec == "ass")
|
||||
mime = "text/x-ssa";
|
||||
else
|
||||
mime = "application/x-subrip";
|
||||
|
||||
//Should use appropriate mime type here
|
||||
return PhysicalFile(subtitle.Path, mime);
|
||||
}
|
||||
//Should use appropriate mime type here
|
||||
return PhysicalFile(subtitle.Path, mime);
|
||||
}
|
||||
|
||||
[HttpGet("extract/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public async Task<string> ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber);
|
||||
_libraryManager.ClearSubtitles(episode.ID);
|
||||
[HttpGet("extract/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public async Task<string> ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber);
|
||||
_libraryManager.ClearSubtitles(episode.ID);
|
||||
|
||||
Track[] tracks = await _transcoder.ExtractSubtitles(episode.Path);
|
||||
foreach (Track track in tracks)
|
||||
{
|
||||
track.EpisodeID = episode.ID;
|
||||
_libraryManager.RegisterTrack(track);
|
||||
}
|
||||
Track[] tracks = await _transcoder.ExtractSubtitles(episode.Path);
|
||||
foreach (Track track in tracks)
|
||||
{
|
||||
track.EpisodeID = episode.ID;
|
||||
_libraryManager.RegisterTrack(track);
|
||||
}
|
||||
|
||||
return "Done. " + tracks.Length + " track(s) extracted.";
|
||||
}
|
||||
return "Done. " + tracks.Length + " track(s) extracted.";
|
||||
}
|
||||
|
||||
[HttpGet("extract/{showSlug}")]
|
||||
public async Task<string> ExtractSubtitle(string showSlug)
|
||||
{
|
||||
IEnumerable<Episode> episodes = _libraryManager.GetEpisodes(showSlug);
|
||||
foreach (Episode episode in episodes)
|
||||
{
|
||||
_libraryManager.ClearSubtitles(episode.ID);
|
||||
[HttpGet("extract/{showSlug}")]
|
||||
public async Task<string> ExtractSubtitle(string showSlug)
|
||||
{
|
||||
IEnumerable<Episode> episodes = _libraryManager.GetEpisodes(showSlug);
|
||||
foreach (Episode episode in episodes)
|
||||
{
|
||||
_libraryManager.ClearSubtitles(episode.ID);
|
||||
|
||||
Track[] tracks = await _transcoder.ExtractSubtitles(episode.Path);
|
||||
foreach (Track track in tracks)
|
||||
{
|
||||
track.EpisodeID = episode.ID;
|
||||
_libraryManager.RegisterTrack(track);
|
||||
}
|
||||
}
|
||||
Track[] tracks = await _transcoder.ExtractSubtitles(episode.Path);
|
||||
foreach (Track track in tracks)
|
||||
{
|
||||
track.EpisodeID = episode.ID;
|
||||
_libraryManager.RegisterTrack(track);
|
||||
}
|
||||
}
|
||||
|
||||
return "Done.";
|
||||
}
|
||||
}
|
||||
return "Done.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ConvertSubripToVtt : IActionResult
|
||||
{
|
||||
private readonly string _path;
|
||||
public class ConvertSubripToVtt : IActionResult
|
||||
{
|
||||
private readonly string _path;
|
||||
|
||||
public ConvertSubripToVtt(string subtitlePath)
|
||||
{
|
||||
_path = subtitlePath;
|
||||
}
|
||||
public ConvertSubripToVtt(string subtitlePath)
|
||||
{
|
||||
_path = subtitlePath;
|
||||
}
|
||||
|
||||
public async Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
string line;
|
||||
List<string> lines = new List<string>();
|
||||
public async Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
string line;
|
||||
List<string> lines = new List<string>();
|
||||
|
||||
context.HttpContext.Response.StatusCode = 200;
|
||||
context.HttpContext.Response.Headers.Add("Content-Type", "text/vtt");
|
||||
context.HttpContext.Response.StatusCode = 200;
|
||||
context.HttpContext.Response.Headers.Add("Content-Type", "text/vtt");
|
||||
|
||||
await using (StreamWriter writer = new StreamWriter(context.HttpContext.Response.Body))
|
||||
{
|
||||
await writer.WriteLineAsync("WEBVTT");
|
||||
await writer.WriteLineAsync("");
|
||||
await writer.WriteLineAsync("");
|
||||
await using (StreamWriter writer = new StreamWriter(context.HttpContext.Response.Body))
|
||||
{
|
||||
await writer.WriteLineAsync("WEBVTT");
|
||||
await writer.WriteLineAsync("");
|
||||
await writer.WriteLineAsync("");
|
||||
|
||||
using (StreamReader reader = new StreamReader(_path))
|
||||
{
|
||||
while ((line = await reader.ReadLineAsync()) != null)
|
||||
{
|
||||
if (line == "")
|
||||
{
|
||||
lines.Add("");
|
||||
List<string> processedBlock = ConvertBlock(lines);
|
||||
for (int i = 0; i < processedBlock.Count; i++)
|
||||
await writer.WriteLineAsync(processedBlock[i]);
|
||||
lines.Clear();
|
||||
}
|
||||
else
|
||||
lines.Add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
using (StreamReader reader = new StreamReader(_path))
|
||||
{
|
||||
while ((line = await reader.ReadLineAsync()) != null)
|
||||
{
|
||||
if (line == "")
|
||||
{
|
||||
lines.Add("");
|
||||
List<string> processedBlock = ConvertBlock(lines);
|
||||
for (int i = 0; i < processedBlock.Count; i++)
|
||||
await writer.WriteLineAsync(processedBlock[i]);
|
||||
lines.Clear();
|
||||
}
|
||||
else
|
||||
lines.Add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await context.HttpContext.Response.Body.FlushAsync();
|
||||
}
|
||||
await context.HttpContext.Response.Body.FlushAsync();
|
||||
}
|
||||
|
||||
private static List<string> ConvertBlock(List<string> lines)
|
||||
{
|
||||
lines[1] = lines[1].Replace(',', '.');
|
||||
if (lines[2].Length > 5)
|
||||
{
|
||||
switch (lines[2].Substring(0, 6))
|
||||
{
|
||||
case "{\\an1}":
|
||||
lines[1] += " line:93% position:15%";
|
||||
break;
|
||||
case "{\\an2}":
|
||||
lines[1] += " line:93%";
|
||||
break;
|
||||
case "{\\an3}":
|
||||
lines[1] += " line:93% position:85%";
|
||||
break;
|
||||
case "{\\an4}":
|
||||
lines[1] += " line:50% position:15%";
|
||||
break;
|
||||
case "{\\an5}":
|
||||
lines[1] += " line:50%";
|
||||
break;
|
||||
case "{\\an6}":
|
||||
lines[1] += " line:50% position:85%";
|
||||
break;
|
||||
case "{\\an7}":
|
||||
lines[1] += " line:7% position:15%";
|
||||
break;
|
||||
case "{\\an8}":
|
||||
lines[1] += " line:7%";
|
||||
break;
|
||||
case "{\\an9}":
|
||||
lines[1] += " line:7% position:85%";
|
||||
break;
|
||||
default:
|
||||
lines[1] += " line:93%";
|
||||
break;
|
||||
}
|
||||
}
|
||||
private static List<string> ConvertBlock(List<string> lines)
|
||||
{
|
||||
lines[1] = lines[1].Replace(',', '.');
|
||||
if (lines[2].Length > 5)
|
||||
{
|
||||
switch (lines[2].Substring(0, 6))
|
||||
{
|
||||
case "{\\an1}":
|
||||
lines[1] += " line:93% position:15%";
|
||||
break;
|
||||
case "{\\an2}":
|
||||
lines[1] += " line:93%";
|
||||
break;
|
||||
case "{\\an3}":
|
||||
lines[1] += " line:93% position:85%";
|
||||
break;
|
||||
case "{\\an4}":
|
||||
lines[1] += " line:50% position:15%";
|
||||
break;
|
||||
case "{\\an5}":
|
||||
lines[1] += " line:50%";
|
||||
break;
|
||||
case "{\\an6}":
|
||||
lines[1] += " line:50% position:85%";
|
||||
break;
|
||||
case "{\\an7}":
|
||||
lines[1] += " line:7% position:15%";
|
||||
break;
|
||||
case "{\\an8}":
|
||||
lines[1] += " line:7%";
|
||||
break;
|
||||
case "{\\an9}":
|
||||
lines[1] += " line:7% position:85%";
|
||||
break;
|
||||
default:
|
||||
lines[1] += " line:93%";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lines[2].StartsWith("{\\an"))
|
||||
lines[2] = lines[2].Substring(6);
|
||||
if (lines[2].StartsWith("{\\an"))
|
||||
lines[2] = lines[2].Substring(6);
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,82 +5,82 @@ using Kyoo.Controllers;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
public class ThumbnailController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly string _peoplePath;
|
||||
public class ThumbnailController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly string _peoplePath;
|
||||
|
||||
|
||||
public ThumbnailController(ILibraryManager libraryManager, IConfiguration config)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_peoplePath = config.GetValue<string>("peoplePath");
|
||||
}
|
||||
public ThumbnailController(ILibraryManager libraryManager, IConfiguration config)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_peoplePath = config.GetValue<string>("peoplePath");
|
||||
}
|
||||
|
||||
[HttpGet("poster/{showSlug}")]
|
||||
public IActionResult GetShowThumb(string showSlug)
|
||||
{
|
||||
string path = _libraryManager.GetShowBySlug(showSlug)?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
[HttpGet("poster/{showSlug}")]
|
||||
public IActionResult GetShowThumb(string showSlug)
|
||||
{
|
||||
string path = _libraryManager.GetShowBySlug(showSlug)?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
|
||||
string thumb = Path.Combine(path, "poster.jpg");
|
||||
string thumb = Path.Combine(path, "poster.jpg");
|
||||
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(thumb, "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(thumb, "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("logo/{showSlug}")]
|
||||
public IActionResult GetShowLogo(string showSlug)
|
||||
{
|
||||
string path = _libraryManager.GetShowBySlug(showSlug)?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
[HttpGet("logo/{showSlug}")]
|
||||
public IActionResult GetShowLogo(string showSlug)
|
||||
{
|
||||
string path = _libraryManager.GetShowBySlug(showSlug)?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
|
||||
string thumb = Path.Combine(path, "logo.png");
|
||||
string thumb = Path.Combine(path, "logo.png");
|
||||
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(thumb, "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(thumb, "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("backdrop/{showSlug}")]
|
||||
public IActionResult GetShowBackdrop(string showSlug)
|
||||
{
|
||||
string path = _libraryManager.GetShowBySlug(showSlug)?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
[HttpGet("backdrop/{showSlug}")]
|
||||
public IActionResult GetShowBackdrop(string showSlug)
|
||||
{
|
||||
string path = _libraryManager.GetShowBySlug(showSlug)?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
|
||||
string thumb = Path.Combine(path, "backdrop.jpg");
|
||||
string thumb = Path.Combine(path, "backdrop.jpg");
|
||||
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(thumb, "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(thumb, "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("peopleimg/{peopleSlug}")]
|
||||
public IActionResult GetPeopleIcon(string peopleSlug)
|
||||
{
|
||||
string thumbPath = Path.Combine(_peoplePath, peopleSlug + ".jpg");
|
||||
if (!System.IO.File.Exists(thumbPath))
|
||||
return NotFound();
|
||||
[HttpGet("peopleimg/{peopleSlug}")]
|
||||
public IActionResult GetPeopleIcon(string peopleSlug)
|
||||
{
|
||||
string thumbPath = Path.Combine(_peoplePath, peopleSlug + ".jpg");
|
||||
if (!System.IO.File.Exists(thumbPath))
|
||||
return NotFound();
|
||||
|
||||
return new PhysicalFileResult(thumbPath, "image/jpg");
|
||||
}
|
||||
return new PhysicalFileResult(thumbPath, "image/jpg");
|
||||
}
|
||||
|
||||
[HttpGet("thumb/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public IActionResult GetEpisodeThumb(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
string path = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber)?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
[HttpGet("thumb/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public IActionResult GetEpisodeThumb(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
string path = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber)?.Path;
|
||||
if (path == null)
|
||||
return NotFound();
|
||||
|
||||
string thumb = Path.ChangeExtension(path, "jpg");
|
||||
string thumb = Path.ChangeExtension(path, "jpg");
|
||||
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(thumb, "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
if (System.IO.File.Exists(thumb))
|
||||
return new PhysicalFileResult(thumb, "image/jpg");
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,64 +7,64 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("[controller]")]
|
||||
[ApiController]
|
||||
public class VideoController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ITranscoder _transcoder;
|
||||
private readonly string _transmuxPath;
|
||||
[Route("[controller]")]
|
||||
[ApiController]
|
||||
public class VideoController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ITranscoder _transcoder;
|
||||
private readonly string _transmuxPath;
|
||||
|
||||
public VideoController(ILibraryManager libraryManager, ITranscoder transcoder, IConfiguration config)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_transcoder = transcoder;
|
||||
_transmuxPath = config.GetValue<string>("transmuxTempPath");
|
||||
}
|
||||
public VideoController(ILibraryManager libraryManager, ITranscoder transcoder, IConfiguration config)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_transcoder = transcoder;
|
||||
_transmuxPath = config.GetValue<string>("transmuxTempPath");
|
||||
}
|
||||
|
||||
[HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public IActionResult Index(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem episode = _libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
[HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public IActionResult Index(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem episode = _libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
|
||||
if (episode != null && System.IO.File.Exists(episode.Path))
|
||||
return PhysicalFile(episode.Path, "video/x-matroska", true);
|
||||
return NotFound();
|
||||
}
|
||||
if (episode != null && System.IO.File.Exists(episode.Path))
|
||||
return PhysicalFile(episode.Path, "video/x-matroska", true);
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("transmux/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public async Task<IActionResult> Transmux(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem episode = _libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
[HttpGet("transmux/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public async Task<IActionResult> Transmux(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem episode = _libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
|
||||
if (episode == null || !System.IO.File.Exists(episode.Path))
|
||||
return NotFound();
|
||||
string path = await _transcoder.Transmux(episode);
|
||||
if (path != null)
|
||||
return PhysicalFile(path, "application/x-mpegURL ", true);
|
||||
return StatusCode(500);
|
||||
}
|
||||
if (episode == null || !System.IO.File.Exists(episode.Path))
|
||||
return NotFound();
|
||||
string path = await _transcoder.Transmux(episode);
|
||||
if (path != null)
|
||||
return PhysicalFile(path, "application/x-mpegURL ", true);
|
||||
return StatusCode(500);
|
||||
}
|
||||
|
||||
[HttpGet("transmux/{episodeLink}/segment/{chunk}")]
|
||||
public IActionResult GetTransmuxedChunk(string episodeLink, string chunk)
|
||||
{
|
||||
string path = Path.Combine(_transmuxPath, episodeLink);
|
||||
path = Path.Combine(path, "segments" + Path.DirectorySeparatorChar + chunk);
|
||||
[HttpGet("transmux/{episodeLink}/segment/{chunk}")]
|
||||
public IActionResult GetTransmuxedChunk(string episodeLink, string chunk)
|
||||
{
|
||||
string path = Path.Combine(_transmuxPath, episodeLink);
|
||||
path = Path.Combine(path, "segments" + Path.DirectorySeparatorChar + chunk);
|
||||
|
||||
return PhysicalFile(path, "video/MP2T");
|
||||
}
|
||||
return PhysicalFile(path, "video/MP2T");
|
||||
}
|
||||
|
||||
[HttpGet("transcode/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public async Task<IActionResult> Transcode(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem episode = _libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
[HttpGet("transcode/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public async Task<IActionResult> Transcode(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem episode = _libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
|
||||
if (episode == null || !System.IO.File.Exists(episode.Path))
|
||||
return NotFound();
|
||||
string path = await _transcoder.Transcode(episode);
|
||||
if (path != null)
|
||||
return PhysicalFile(path, "application/x-mpegURL ", true);
|
||||
return StatusCode(500);
|
||||
}
|
||||
}
|
||||
if (episode == null || !System.IO.File.Exists(episode.Path))
|
||||
return NotFound();
|
||||
string path = await _transcoder.Transcode(episode);
|
||||
if (path != null)
|
||||
return PhysicalFile(path, "application/x-mpegURL ", true);
|
||||
return StatusCode(500);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,26 +4,26 @@ using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class WatchController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class WatchController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public WatchController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
public WatchController(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public ActionResult<WatchItem> Index(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem item = _libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
[HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public ActionResult<WatchItem> Index(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem item = _libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
|
||||
if(item == null)
|
||||
return NotFound();
|
||||
if(item == null)
|
||||
return NotFound();
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,18 +7,18 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Kyoo
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
Console.WriteLine($"Running as: {Environment.UserName}");
|
||||
await CreateWebHostBuilder(args).Build().RunAsync();
|
||||
}
|
||||
public class Program
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
Console.WriteLine($"Running as: {Environment.UserName}");
|
||||
await CreateWebHostBuilder(args).Build().RunAsync();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseKestrel((config) => { config.AddServerHeader = false; })
|
||||
.UseUrls("http://*:5000")
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseKestrel((config) => { config.AddServerHeader = false; })
|
||||
.UseUrls("http://*:5000")
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
||||
|
148
Kyoo/Startup.cs
148
Kyoo/Startup.cs
@ -12,91 +12,91 @@ using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Kyoo
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// In production, the Angular files will be served from this directory
|
||||
services.AddSpaStaticFiles(configuration =>
|
||||
{
|
||||
configuration.RootPath = "ClientApp/dist";
|
||||
});
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// In production, the Angular files will be served from this directory
|
||||
services.AddSpaStaticFiles(configuration =>
|
||||
{
|
||||
configuration.RootPath = "ClientApp/dist";
|
||||
});
|
||||
|
||||
services.AddControllers().AddNewtonsoftJson();
|
||||
services.AddHttpClient();
|
||||
services.AddControllers().AddNewtonsoftJson();
|
||||
services.AddHttpClient();
|
||||
|
||||
services.AddDbContext<DatabaseContext>(options => options.UseLazyLoadingProxies()
|
||||
.UseSqlite(Configuration.GetConnectionString("Database")));
|
||||
services.AddDbContext<DatabaseContext>(options => options.UseLazyLoadingProxies()
|
||||
.UseSqlite(Configuration.GetConnectionString("Database")));
|
||||
|
||||
// services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
// .AddEntityFrameworkStores()
|
||||
// services.AddIdentityServer();
|
||||
// services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
// .AddEntityFrameworkStores()
|
||||
// services.AddIdentityServer();
|
||||
|
||||
services.AddScoped<ILibraryManager, LibraryManager>();
|
||||
services.AddScoped<ICrawler, Crawler>();
|
||||
services.AddSingleton<ITranscoder, Transcoder>();
|
||||
services.AddSingleton<IThumbnailsManager, ThumbnailsManager>();
|
||||
services.AddSingleton<IProviderManager, ProviderManager>();
|
||||
services.AddSingleton<IPluginManager, PluginManager>();
|
||||
|
||||
services.AddHostedService<StartupCode>();
|
||||
}
|
||||
services.AddScoped<ILibraryManager, LibraryManager>();
|
||||
services.AddScoped<ICrawler, Crawler>();
|
||||
services.AddSingleton<ITranscoder, Transcoder>();
|
||||
services.AddSingleton<IThumbnailsManager, ThumbnailsManager>();
|
||||
services.AddSingleton<IProviderManager, ProviderManager>();
|
||||
services.AddSingleton<IPluginManager, PluginManager>();
|
||||
|
||||
services.AddHostedService<StartupCode>();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Error");
|
||||
app.UseHsts();
|
||||
}
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Error");
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.Use((ctx, next) =>
|
||||
{
|
||||
ctx.Response.Headers.Remove("X-Powered-By");
|
||||
ctx.Response.Headers.Remove("Server");
|
||||
ctx.Response.Headers.Add("Feature-Policy", "autoplay 'self'; fullscreen");
|
||||
ctx.Response.Headers.Add("Content-Security-Policy", "default-src 'self' data: blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; style-src 'self' 'unsafe-inline'");
|
||||
ctx.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
|
||||
ctx.Response.Headers.Add("Referrer-Policy", "no-referrer");
|
||||
ctx.Response.Headers.Add("Access-Control-Allow-Origin", "null");
|
||||
ctx.Response.Headers.Add("X-Content-Type-Options", "nosniff");
|
||||
return next();
|
||||
});
|
||||
app.Use((ctx, next) =>
|
||||
{
|
||||
ctx.Response.Headers.Remove("X-Powered-By");
|
||||
ctx.Response.Headers.Remove("Server");
|
||||
ctx.Response.Headers.Add("Feature-Policy", "autoplay 'self'; fullscreen");
|
||||
ctx.Response.Headers.Add("Content-Security-Policy", "default-src 'self' data: blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; style-src 'self' 'unsafe-inline'");
|
||||
ctx.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
|
||||
ctx.Response.Headers.Add("Referrer-Policy", "no-referrer");
|
||||
ctx.Response.Headers.Add("Access-Control-Allow-Origin", "null");
|
||||
ctx.Response.Headers.Add("X-Content-Type-Options", "nosniff");
|
||||
return next();
|
||||
});
|
||||
|
||||
//app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
if (!env.IsDevelopment())
|
||||
app.UseSpaStaticFiles();
|
||||
//app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
if (!env.IsDevelopment())
|
||||
app.UseSpaStaticFiles();
|
||||
|
||||
app.UseRouting();
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllerRoute("API Route", "api/{controller=Home}/{action=Index}/{id?}");
|
||||
});
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllerRoute("API Route", "api/{controller=Home}/{action=Index}/{id?}");
|
||||
});
|
||||
|
||||
app.UseSpa(spa =>
|
||||
{
|
||||
spa.Options.SourcePath = "ClientApp";
|
||||
app.UseSpa(spa =>
|
||||
{
|
||||
spa.Options.SourcePath = "ClientApp";
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
spa.UseAngularCliServer(npmScript: "start");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
spa.UseAngularCliServer(npmScript: "start");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user