Delete tvdb and tmdb providers

This commit is contained in:
Zoe Roux 2023-03-18 23:59:11 +09:00
parent 505ebb48bc
commit dca91feff8
22 changed files with 0 additions and 2173 deletions

View File

@ -7,18 +7,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Postgresql", "src\Kyoo
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Authentication", "src\Kyoo.Authentication\Kyoo.Authentication.csproj", "{7A841335-6523-47DB-9717-80AA7BD943FD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.TheTvdb", "src\Kyoo.TheTvdb\Kyoo.TheTvdb.csproj", "{D06BF829-23F5-40F3-A62D-627D9F4B4D6C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.TheMovieDb", "src\Kyoo.TheMovieDb\Kyoo.TheMovieDb.csproj", "{BAB270D4-E0EA-4329-BA65-512FDAB01001}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Tests", "tests\Kyoo.Tests\Kyoo.Tests.csproj", "{0C8AA7EA-E723-4532-852F-35AA4E8AFED5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Swagger", "src\Kyoo.Swagger\Kyoo.Swagger.csproj", "{7D1A7596-73F6-4D35-842E-A5AD9C620596}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{FEAE1B0E-D797-470F-9030-0EF743575ECC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Providers", "Providers", "{8D28F5EF-0CD7-4697-A2A7-24EC31A48F21}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kyoo.Host", "src\Kyoo.Host\Kyoo.Host.csproj", "{0938459E-2E2B-457F-8120-7D8CA93866A6}"
EndProject
Global
@ -47,14 +41,6 @@ Global
{6515380E-1E57-42DA-B6E3-E1C8A848818A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6515380E-1E57-42DA-B6E3-E1C8A848818A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6515380E-1E57-42DA-B6E3-E1C8A848818A}.Release|Any CPU.Build.0 = Release|Any CPU
{D06BF829-23F5-40F3-A62D-627D9F4B4D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D06BF829-23F5-40F3-A62D-627D9F4B4D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D06BF829-23F5-40F3-A62D-627D9F4B4D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D06BF829-23F5-40F3-A62D-627D9F4B4D6C}.Release|Any CPU.Build.0 = Release|Any CPU
{BAB270D4-E0EA-4329-BA65-512FDAB01001}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BAB270D4-E0EA-4329-BA65-512FDAB01001}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BAB270D4-E0EA-4329-BA65-512FDAB01001}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BAB270D4-E0EA-4329-BA65-512FDAB01001}.Release|Any CPU.Build.0 = Release|Any CPU
{0C8AA7EA-E723-4532-852F-35AA4E8AFED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0C8AA7EA-E723-4532-852F-35AA4E8AFED5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0C8AA7EA-E723-4532-852F-35AA4E8AFED5}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -78,7 +64,5 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0C8AA7EA-E723-4532-852F-35AA4E8AFED5} = {FEAE1B0E-D797-470F-9030-0EF743575ECC}
{BAB270D4-E0EA-4329-BA65-512FDAB01001} = {8D28F5EF-0CD7-4697-A2A7-24EC31A48F21}
{D06BF829-23F5-40F3-A62D-627D9F4B4D6C} = {8D28F5EF-0CD7-4697-A2A7-24EC31A48F21}
EndGlobalSection
EndGlobal

View File

@ -20,9 +20,7 @@
<ItemGroup>
<ProjectReference Include="../Kyoo.Abstractions/Kyoo.Abstractions.csproj" />
<ProjectReference Include="../Kyoo.TheMovieDb/Kyoo.TheMovieDb.csproj" />
<ProjectReference Include="../Kyoo.Core/Kyoo.Core.csproj" />
<ProjectReference Include="../Kyoo.TheTvdb/Kyoo.TheTvdb.csproj" />
<ProjectReference Include="../Kyoo.Postgresql/Kyoo.Postgresql.csproj" />
<ProjectReference Include="../Kyoo.Authentication/Kyoo.Authentication.csproj" />
<ProjectReference Include="../Kyoo.Swagger/Kyoo.Swagger.csproj" />

View File

@ -28,8 +28,6 @@ using Kyoo.Core.Models.Options;
using Kyoo.Host.Controllers;
using Kyoo.Postgresql;
using Kyoo.Swagger;
using Kyoo.TheMovieDb;
using Kyoo.TheTvdb;
using Kyoo.Utils;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
@ -77,8 +75,6 @@ namespace Kyoo.Host
typeof(CoreModule),
typeof(AuthenticationModule),
typeof(PostgresModule),
typeof(PluginTvdb),
typeof(PluginTmdb),
typeof(SwaggerModule)
);
}

View File

@ -1,98 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System.Collections.Generic;
using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using TMDbLib.Objects.Search;
namespace Kyoo.TheMovieDb
{
/// <summary>
/// A class containing extensions methods to convert from TMDB's types to Kyoo's types.
/// </summary>
public static partial class Convertors
{
/// <summary>
/// Convert a <see cref="SearchCollection"/> into a <see cref="Collection"/>.
/// </summary>
/// <param name="collection">The collection to convert.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>The converted collection as a <see cref="Collection"/>.</returns>
public static Collection ToCollection(this TMDbLib.Objects.Collections.Collection collection, Provider provider)
{
return new Collection
{
Slug = Utility.ToSlug(collection.Name),
Name = collection.Name,
Overview = collection.Overview,
Images = new Dictionary<int, string>
{
[Images.Poster] = collection.PosterPath != null
? $"https://image.tmdb.org/t/p/original{collection.PosterPath}"
: null,
[Images.Thumbnail] = collection.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{collection.BackdropPath}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/collection/{collection.Id}",
DataID = collection.Id.ToString()
}
}
};
}
/// <summary>
/// Convert a <see cref="SearchCollection"/> into a <see cref="Collection"/>.
/// </summary>
/// <param name="collection">The collection to convert.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>The converted collection as a <see cref="Collection"/>.</returns>
public static Collection ToCollection(this SearchCollection collection, Provider provider)
{
return new Collection
{
Slug = Utility.ToSlug(collection.Name),
Name = collection.Name,
Images = new Dictionary<int, string>
{
[Images.Poster] = collection.PosterPath != null
? $"https://image.tmdb.org/t/p/original{collection.PosterPath}"
: null,
[Images.Thumbnail] = collection.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{collection.BackdropPath}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/collection/{collection.Id}",
DataID = collection.Id.ToString()
}
}
};
}
}
}

View File

@ -1,65 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System.Collections.Generic;
using Kyoo.Abstractions.Models;
using TMDbLib.Objects.TvShows;
namespace Kyoo.TheMovieDb
{
/// <summary>
/// A class containing extensions methods to convert from TMDB's types to Kyoo's types.
/// </summary>
public static partial class Convertors
{
/// <summary>
/// Convert a <see cref="TvEpisode"/> into a <see cref="Episode"/>.
/// </summary>
/// <param name="episode">The episode to convert.</param>
/// <param name="showID">The ID of the show inside TheMovieDb.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>The converted episode as a <see cref="Episode"/>.</returns>
public static Episode ToEpisode(this TvEpisode episode, int showID, Provider provider)
{
return new Episode
{
SeasonNumber = episode.SeasonNumber,
EpisodeNumber = episode.EpisodeNumber,
Title = episode.Name,
Overview = episode.Overview,
ReleaseDate = episode.AirDate,
Images = new Dictionary<int, string>
{
[Images.Thumbnail] = episode.StillPath != null
? $"https://image.tmdb.org/t/p/original{episode.StillPath}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/tv/{showID}" +
$"/season/{episode.SeasonNumber}/episode/{episode.EpisodeNumber}",
DataID = episode.Id.ToString()
}
}
};
}
}
}

View File

@ -1,120 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System.Collections.Generic;
using System.Linq;
using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using TMDbLib.Objects.Movies;
using TMDbLib.Objects.Search;
namespace Kyoo.TheMovieDb
{
/// <summary>
/// A class containing extensions methods to convert from TMDB's types to Kyoo's types.
/// </summary>
public static partial class Convertors
{
/// <summary>
/// Convert a <see cref="Movie"/> into a <see cref="Show"/>.
/// </summary>
/// <param name="movie">The movie to convert.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>The converted movie as a <see cref="Show"/>.</returns>
public static Show ToShow(this Movie movie, Provider provider)
{
return new Show
{
Slug = Utility.ToSlug(movie.Title),
Title = movie.Title,
Aliases = movie.AlternativeTitles.Titles.Select(x => x.Title).ToArray(),
Overview = movie.Overview,
Status = movie.Status == "Released" ? Status.Finished : Status.Planned,
StartAir = movie.ReleaseDate,
EndAir = movie.ReleaseDate,
Images = new Dictionary<int, string>
{
[Images.Poster] = movie.PosterPath != null
? $"https://image.tmdb.org/t/p/original{movie.PosterPath}"
: null,
[Images.Thumbnail] = movie.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{movie.BackdropPath}"
: null,
[Images.Trailer] = movie.Videos?.Results
.Where(x => x.Type is "Trailer" or "Teaser" && x.Site == "YouTube")
.Select(x => "https://www.youtube.com/watch?v=" + x.Key).FirstOrDefault(),
},
Genres = movie.Genres.Select(x => new Genre(x.Name)).ToArray(),
Studio = !string.IsNullOrEmpty(movie.ProductionCompanies.FirstOrDefault()?.Name)
? new Studio(movie.ProductionCompanies.First().Name)
: null,
IsMovie = true,
People = movie.Credits.Cast
.Select(x => x.ToPeople(provider))
.Concat(movie.Credits.Crew.Select(x => x.ToPeople(provider)))
.ToArray(),
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/movie/{movie.Id}",
DataID = movie.Id.ToString()
}
}
};
}
/// <summary>
/// Convert a <see cref="SearchMovie"/> into a <see cref="Show"/>.
/// </summary>
/// <param name="movie">The movie to convert.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>The converted movie as a <see cref="Show"/>.</returns>
public static Show ToShow(this SearchMovie movie, Provider provider)
{
return new Show
{
Slug = Utility.ToSlug(movie.Title),
Title = movie.Title,
Overview = movie.Overview,
StartAir = movie.ReleaseDate,
EndAir = movie.ReleaseDate,
Images = new Dictionary<int, string>
{
[Images.Poster] = movie.PosterPath != null
? $"https://image.tmdb.org/t/p/original{movie.PosterPath}"
: null,
[Images.Thumbnail] = movie.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{movie.BackdropPath}"
: null,
},
IsMovie = true,
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/movie/{movie.Id}",
DataID = movie.Id.ToString()
}
}
};
}
}
}

View File

@ -1,201 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System.Collections.Generic;
using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using TMDbLib.Objects.General;
using TMDbLib.Objects.People;
using TMDbLib.Objects.Search;
using Images = Kyoo.Abstractions.Models.Images;
using MovieCast = TMDbLib.Objects.Movies.Cast;
using TvCast = TMDbLib.Objects.TvShows.Cast;
namespace Kyoo.TheMovieDb
{
/// <summary>
/// A class containing extensions methods to convert from TMDB's types to Kyoo's types.
/// </summary>
public static partial class Convertors
{
/// <summary>
/// Convert a <see cref="MovieCast"/> to a <see cref="Abstractions.Models.PeopleRole"/>.
/// </summary>
/// <param name="cast">An internal TheMovieDB cast.</param>
/// <param name="provider">The provider that represent TheMovieDB inside Kyoo.</param>
/// <returns>A <see cref="Abstractions.Models.PeopleRole"/> representing the movie cast.</returns>
public static PeopleRole ToPeople(this MovieCast cast, Provider provider)
{
return new PeopleRole
{
People = new People
{
Slug = Utility.ToSlug(cast.Name),
Name = cast.Name,
Images = new Dictionary<int, string>
{
[Images.Poster] = cast.ProfilePath != null
? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
DataID = cast.Id.ToString(),
Link = $"https://www.themoviedb.org/person/{cast.Id}"
}
}
},
Type = "Actor",
Role = cast.Character
};
}
/// <summary>
/// Convert a <see cref="TvCast"/> to a <see cref="PeopleRole"/>.
/// </summary>
/// <param name="cast">An internal TheMovieDB cast.</param>
/// <param name="provider">The provider that represent TheMovieDB inside Kyoo.</param>
/// <returns>A <see cref="PeopleRole"/> representing the movie cast.</returns>
public static PeopleRole ToPeople(this TvCast cast, Provider provider)
{
return new PeopleRole
{
People = new People
{
Slug = Utility.ToSlug(cast.Name),
Name = cast.Name,
Images = new Dictionary<int, string>
{
[Images.Poster] = cast.ProfilePath != null
? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
DataID = cast.Id.ToString(),
Link = $"https://www.themoviedb.org/person/{cast.Id}"
}
}
},
Type = "Actor",
Role = cast.Character
};
}
/// <summary>
/// Convert a <see cref="Crew"/> to a <see cref="PeopleRole"/>.
/// </summary>
/// <param name="crew">An internal TheMovieDB crew member.</param>
/// <param name="provider">The provider that represent TheMovieDB inside Kyoo.</param>
/// <returns>A <see cref="PeopleRole"/> representing the movie crew.</returns>
public static PeopleRole ToPeople(this Crew crew, Provider provider)
{
return new PeopleRole
{
People = new People
{
Slug = Utility.ToSlug(crew.Name),
Name = crew.Name,
Images = new Dictionary<int, string>
{
[Images.Poster] = crew.ProfilePath != null
? $"https://image.tmdb.org/t/p/original{crew.ProfilePath}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
DataID = crew.Id.ToString(),
Link = $"https://www.themoviedb.org/person/{crew.Id}"
}
}
},
Type = crew.Department,
Role = crew.Job
};
}
/// <summary>
/// Convert a <see cref="Person"/> to a <see cref="People"/>.
/// </summary>
/// <param name="person">An internal TheMovieDB person.</param>
/// <param name="provider">The provider that represent TheMovieDB inside Kyoo.</param>
/// <returns>A <see cref="People"/> representing the person.</returns>
public static People ToPeople(this Person person, Provider provider)
{
return new People
{
Slug = Utility.ToSlug(person.Name),
Name = person.Name,
Images = new Dictionary<int, string>
{
[Images.Poster] = person.ProfilePath != null
? $"https://image.tmdb.org/t/p/original{person.ProfilePath}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
DataID = person.Id.ToString(),
Link = $"https://www.themoviedb.org/person/{person.Id}"
}
}
};
}
/// <summary>
/// Convert a <see cref="SearchPerson"/> to a <see cref="People"/>.
/// </summary>
/// <param name="person">An internal TheMovieDB person.</param>
/// <param name="provider">The provider that represent TheMovieDB inside Kyoo.</param>
/// <returns>A <see cref="People"/> representing the person.</returns>
public static People ToPeople(this SearchPerson person, Provider provider)
{
return new People
{
Slug = Utility.ToSlug(person.Name),
Name = person.Name,
Images = new Dictionary<int, string>
{
[Images.Poster] = person.ProfilePath != null
? $"https://image.tmdb.org/t/p/original{person.ProfilePath}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
DataID = person.Id.ToString(),
Link = $"https://www.themoviedb.org/person/{person.Id}"
}
}
};
}
}
}

View File

@ -1,63 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System.Collections.Generic;
using Kyoo.Abstractions.Models;
using TMDbLib.Objects.TvShows;
namespace Kyoo.TheMovieDb
{
/// <summary>
/// A class containing extensions methods to convert from TMDB's types to Kyoo's types.
/// </summary>
public static partial class Convertors
{
/// <summary>
/// Convert a <see cref="TvSeason"/> into a <see cref="Season"/>.
/// </summary>
/// <param name="season">The season to convert.</param>
/// <param name="showID">The ID of the show inside TheMovieDb.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>The converted season as a <see cref="Season"/>.</returns>
public static Season ToSeason(this TvSeason season, int showID, Provider provider)
{
return new Season
{
SeasonNumber = season.SeasonNumber,
Title = season.Name,
Overview = season.Overview,
StartDate = season.AirDate,
Images = new Dictionary<int, string>
{
[Images.Poster] = season.PosterPath != null
? $"https://image.tmdb.org/t/p/original{season.PosterPath}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/tv/{showID}/season/{season.SeasonNumber}",
DataID = season.Id?.ToString()
}
}
};
}
}
}

View File

@ -1,117 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System.Collections.Generic;
using System.Linq;
using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using TMDbLib.Objects.Search;
using TMDbLib.Objects.TvShows;
namespace Kyoo.TheMovieDb
{
/// <summary>
/// A class containing extensions methods to convert from TMDB's types to Kyoo's types.
/// </summary>
public static partial class Convertors
{
/// <summary>
/// Convert a <see cref="TvShow"/> to a <see cref="Show"/>.
/// </summary>
/// <param name="tv">The show to convert.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>A converted <see cref="TvShow"/> as a <see cref="Show"/>.</returns>
public static Show ToShow(this TvShow tv, Provider provider)
{
return new Show
{
Slug = Utility.ToSlug(tv.Name),
Title = tv.Name,
Aliases = tv.AlternativeTitles.Results.Select(x => x.Title).ToArray(),
Overview = tv.Overview,
Status = tv.Status == "Ended" ? Status.Finished : Status.Planned,
StartAir = tv.FirstAirDate,
EndAir = tv.LastAirDate,
Images = new Dictionary<int, string>
{
[Images.Poster] = tv.PosterPath != null
? $"https://image.tmdb.org/t/p/original{tv.PosterPath}"
: null,
[Images.Thumbnail] = tv.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{tv.BackdropPath}"
: null,
[Images.Trailer] = tv.Videos?.Results
.Where(x => x.Type is "Trailer" or "Teaser" && x.Site == "YouTube")
.Select(x => "https://www.youtube.com/watch?v=" + x.Key).FirstOrDefault()
},
Genres = tv.Genres.Select(x => new Genre(x.Name)).ToArray(),
Studio = !string.IsNullOrEmpty(tv.ProductionCompanies.FirstOrDefault()?.Name)
? new Studio(tv.ProductionCompanies.First().Name)
: null,
People = tv.Credits.Cast
.Select(x => x.ToPeople(provider))
.Concat(tv.Credits.Crew.Select(x => x.ToPeople(provider)))
.ToArray(),
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/tv/{tv.Id}",
DataID = tv.Id.ToString()
}
}
};
}
/// <summary>
/// Convert a <see cref="SearchTv"/> to a <see cref="Show"/>.
/// </summary>
/// <param name="tv">The show to convert.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>A converted <see cref="SearchTv"/> as a <see cref="Show"/>.</returns>
public static Show ToShow(this SearchTv tv, Provider provider)
{
return new Show
{
Slug = Utility.ToSlug(tv.Name),
Title = tv.Name,
Overview = tv.Overview,
StartAir = tv.FirstAirDate,
Images = new Dictionary<int, string>
{
[Images.Poster] = tv.PosterPath != null
? $"https://image.tmdb.org/t/p/original{tv.PosterPath}"
: null,
[Images.Thumbnail] = tv.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{tv.BackdropPath}"
: null,
},
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/tv/{tv.Id}",
DataID = tv.Id.ToString()
}
}
};
}
}
}

View File

@ -1,79 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using TMDbLib.Objects.Companies;
using TMDbLib.Objects.Search;
namespace Kyoo.TheMovieDb
{
/// <summary>
/// A class containing extensions methods to convert from TMDB's types to Kyoo's types.
/// </summary>
public static partial class Convertors
{
/// <summary>
/// Convert a <see cref="Company"/> into a <see cref="Studio"/>.
/// </summary>
/// <param name="company">The company to convert.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>The converted company as a <see cref="Studio"/>.</returns>
public static Studio ToStudio(this Company company, Provider provider)
{
return new Studio
{
Slug = Utility.ToSlug(company.Name),
Name = company.Name,
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/company/{company.Id}",
DataID = company.Id.ToString()
}
}
};
}
/// <summary>
/// Convert a <see cref="SearchCompany"/> into a <see cref="Studio"/>.
/// </summary>
/// <param name="company">The company to convert.</param>
/// <param name="provider">The provider representing TheMovieDb.</param>
/// <returns>The converted company as a <see cref="Studio"/>.</returns>
public static Studio ToStudio(this SearchCompany company, Provider provider)
{
return new Studio
{
Slug = Utility.ToSlug(company.Name),
Name = company.Name,
ExternalIDs = new[]
{
new MetadataID
{
Provider = provider,
Link = $"https://www.themoviedb.org/company/{company.Id}",
DataID = company.Id.ToString()
}
}
};
}
}
}

View File

@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Kyoo.TheMovieDb</AssemblyName>
<RootNamespace>Kyoo.TheMovieDb</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
<PackageReference Include="TMDbLib" Version="1.8.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Kyoo.Abstractions/Kyoo.Abstractions.csproj" />
</ItemGroup>
</Project>

View File

@ -1,75 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using Autofac;
using Kyoo.Abstractions;
using Kyoo.Abstractions.Controllers;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Kyoo.TheMovieDb
{
/// <summary>
/// A plugin that add a <see cref="IMetadataProvider"/> for TheMovieDB.
/// </summary>
public class PluginTmdb : IPlugin
{
/// <summary>
/// The configuration used to check if the api key is present or not.
/// </summary>
private readonly IConfiguration _configuration;
/// <summary>
/// Create a new <see cref="PluginTmdb"/>.
/// </summary>
/// <param name="configuration">The configuration used to check if the api key is present or not.</param>
/// <param name="logger">The logger used to warn when the api key is not present.</param>
public PluginTmdb(IConfiguration configuration, ILogger<PluginTmdb> logger)
{
_configuration = configuration;
if (!Enabled)
{
logger.LogWarning("No API key configured for TheMovieDB provider. " +
"To enable TheMovieDB, specify one in the setting themoviedb:APIKEY");
}
}
/// <inheritdoc />
public string Slug => "the-moviedb";
/// <inheritdoc />
public string Name => "TheMovieDb";
/// <inheritdoc />
public string Description => "A metadata provider for TheMovieDB.";
/// <inheritdoc />
public bool Enabled => !string.IsNullOrEmpty(_configuration.GetValue<string>("THEMOVIEDB_APIKEY"));
/// <inheritdoc />
public Dictionary<string, Type> Configuration => new();
/// <inheritdoc />
public void Configure(ContainerBuilder builder)
{
builder.RegisterProvider<TheMovieDbProvider>();
}
}
}

View File

@ -1,297 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using TMDbLib.Client;
using TMDbLib.Objects.Movies;
using TMDbLib.Objects.Search;
using TMDbLib.Objects.TvShows;
namespace Kyoo.TheMovieDb
{
/// <summary>
/// A metadata provider for TheMovieDb.
/// </summary>
public class TheMovieDbProvider : IMetadataProvider
{
/// <summary>
/// The API key used to authenticate with TheMovieDb API.
/// </summary>
private readonly string _apiKey;
/// <summary>
/// The logger to use in ase of issue.
/// </summary>
private readonly ILogger<TheMovieDbProvider> _logger;
/// <inheritdoc />
public Provider Provider => new()
{
Slug = "the-moviedb",
Name = "TheMovieDB",
Images = new Dictionary<int, string>
{
[Images.Logo] = "https://www.themoviedb.org/assets/2/v4/logos/v2/" +
"blue_short-8e7b30f73a4020692ccca9c88bafe5dcb6f8a62a4c6bc55cd9ba82bb2cd95f6c.svg"
}
};
/// <summary>
/// Create a new <see cref="TheMovieDbProvider"/> using the given api key.
/// </summary>
/// <param name="config">The api key.</param>
/// <param name="logger">The logger to use in case of issue.</param>
public TheMovieDbProvider(IConfiguration config, ILogger<TheMovieDbProvider> logger)
{
_apiKey = config.GetValue<string>("THEMOVIEDB_APIKEY");
_logger = logger;
}
/// <inheritdoc />
public Task<T> Get<T>(T item)
where T : class, IResource
{
return item switch
{
Collection collection => _GetCollection(collection) as Task<T>,
Show show => _GetShow(show) as Task<T>,
Season season => _GetSeason(season) as Task<T>,
Episode episode => _GetEpisode(episode) as Task<T>,
People person => _GetPerson(person) as Task<T>,
Studio studio => _GetStudio(studio) as Task<T>,
_ => null
};
}
/// <summary>
/// Get a collection using it's id, if the id is not present in the collection, fallback to a name search.
/// </summary>
/// <param name="collection">The collection to search for.</param>
/// <returns>A collection containing metadata from TheMovieDb.</returns>
private async Task<Collection> _GetCollection(Collection collection)
{
if (!collection.TryGetID(Provider.Slug, out int id))
{
Collection found = (await _SearchCollections(collection.Name ?? collection.Slug)).FirstOrDefault();
if (found?.TryGetID(Provider.Slug, out id) != true)
return found;
}
TMDbClient client = new(_apiKey);
return (await client.GetCollectionAsync(id)).ToCollection(Provider);
}
/// <summary>
/// Get a show using it's id, if the id is not present in the show, fallback to a title search.
/// </summary>
/// <param name="show">The show to search for.</param>
/// <returns>A show containing metadata from TheMovieDb.</returns>
private async Task<Show> _GetShow(Show show)
{
if (!show.TryGetID(Provider.Slug, out int id))
{
Show found = (await _SearchShows(show.Title ?? show.Slug, show.StartAir?.Year))
.FirstOrDefault(x => x.IsMovie == show.IsMovie);
if (found?.TryGetID(Provider.Slug, out id) != true)
return found;
}
TMDbClient client = new(_apiKey);
if (show.IsMovie)
{
return (await client
.GetMovieAsync(id, MovieMethods.AlternativeTitles | MovieMethods.Videos | MovieMethods.Credits))
?.ToShow(Provider);
}
return (await client
.GetTvShowAsync(id, TvShowMethods.AlternativeTitles | TvShowMethods.Videos | TvShowMethods.Credits))
?.ToShow(Provider);
}
/// <summary>
/// Get a season using it's show and it's season number.
/// </summary>
/// <param name="season">The season to retrieve metadata for.</param>
/// <returns>A season containing metadata from TheMovieDb.</returns>
private async Task<Season> _GetSeason(Season season)
{
if (season.Show == null)
{
_logger.LogWarning("Metadata for a season was requested but it's show is not loaded. " +
"This is unsupported");
return null;
}
if (!season.Show.TryGetID(Provider.Slug, out int id))
return null;
TMDbClient client = new(_apiKey);
return (await client.GetTvSeasonAsync(id, season.SeasonNumber))
.ToSeason(id, Provider);
}
/// <summary>
/// Get an episode using it's show, it's season number and it's episode number.
/// Absolute numbering is not supported.
/// </summary>
/// <param name="episode">The episode to retrieve metadata for.</param>
/// <returns>An episode containing metadata from TheMovieDb.</returns>
private async Task<Episode> _GetEpisode(Episode episode)
{
if (episode.Show == null)
{
_logger.LogWarning("Metadata for an episode was requested but it's show is not loaded. " +
"This is unsupported");
return null;
}
if (!episode.Show.TryGetID(Provider.Slug, out int id)
|| episode.SeasonNumber == null || episode.EpisodeNumber == null)
return null;
TMDbClient client = new(_apiKey);
return (await client.GetTvEpisodeAsync(id, episode.SeasonNumber.Value, episode.EpisodeNumber.Value))
?.ToEpisode(id, Provider);
}
/// <summary>
/// Get a person using it's id, if the id is not present in the person, fallback to a name search.
/// </summary>
/// <param name="person">The person to search for.</param>
/// <returns>A person containing metadata from TheMovieDb.</returns>
private async Task<People> _GetPerson(People person)
{
if (!person.TryGetID(Provider.Slug, out int id))
{
People found = (await _SearchPeople(person.Name ?? person.Slug)).FirstOrDefault();
if (found?.TryGetID(Provider.Slug, out id) != true)
return found;
}
TMDbClient client = new(_apiKey);
return (await client.GetPersonAsync(id)).ToPeople(Provider);
}
/// <summary>
/// Get a studio using it's id, if the id is not present in the studio, fallback to a name search.
/// </summary>
/// <param name="studio">The studio to search for.</param>
/// <returns>A studio containing metadata from TheMovieDb.</returns>
private async Task<Studio> _GetStudio(Studio studio)
{
if (!studio.TryGetID(Provider.Slug, out int id))
{
Studio found = (await _SearchStudios(studio.Name ?? studio.Slug)).FirstOrDefault();
if (found?.TryGetID(Provider.Slug, out id) != true)
return found;
}
TMDbClient client = new(_apiKey);
return (await client.GetCompanyAsync(id)).ToStudio(Provider);
}
/// <inheritdoc />
public async Task<ICollection<T>> Search<T>(string query)
where T : class, IResource
{
if (typeof(T) == typeof(Collection))
return (await _SearchCollections(query) as ICollection<T>)!;
if (typeof(T) == typeof(Show))
return (await _SearchShows(query) as ICollection<T>)!;
if (typeof(T) == typeof(People))
return (await _SearchPeople(query) as ICollection<T>)!;
if (typeof(T) == typeof(Studio))
return (await _SearchStudios(query) as ICollection<T>)!;
return ArraySegment<T>.Empty;
}
/// <summary>
/// Search for a collection using it's name as a query.
/// </summary>
/// <param name="query">The query to search for</param>
/// <returns>A list of collections containing metadata from TheMovieDb</returns>
private async Task<ICollection<Collection>> _SearchCollections(string query)
{
TMDbClient client = new(_apiKey);
return (await client.SearchCollectionAsync(query))
.Results
.Select(x => x.ToCollection(Provider))
.ToArray();
}
/// <summary>
/// Search for a show using it's name as a query.
/// </summary>
/// <param name="query">The query to search for</param>
/// <param name="year">The year in witch the show has aired.</param>
/// <returns>A list of shows containing metadata from TheMovieDb</returns>
private async Task<ICollection<Show>> _SearchShows(string query, int? year = null)
{
TMDbClient client = new(_apiKey);
return (await client.SearchMultiAsync(query, year: year ?? 0))
.Results
.Select(x =>
{
return x switch
{
SearchTv tv => tv.ToShow(Provider),
SearchMovie movie => movie.ToShow(Provider),
_ => null
};
})
.Where(x => x != null)
.ToArray();
}
/// <summary>
/// Search for people using there name as a query.
/// </summary>
/// <param name="query">The query to search for</param>
/// <returns>A list of people containing metadata from TheMovieDb</returns>
private async Task<ICollection<People>> _SearchPeople(string query)
{
TMDbClient client = new(_apiKey);
return (await client.SearchPersonAsync(query))
.Results
.Select(x => x.ToPeople(Provider))
.ToArray();
}
/// <summary>
/// Search for studios using there name as a query.
/// </summary>
/// <param name="query">The query to search for</param>
/// <returns>A list of studios containing metadata from TheMovieDb</returns>
private async Task<ICollection<Studio>> _SearchStudios(string query)
{
TMDbClient client = new(_apiKey);
return (await client.SearchCompanyAsync(query))
.Results
.Select(x => x.ToStudio(Provider))
.ToArray();
}
}
}

View File

@ -1,192 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Kyoo.Abstractions.Models;
using Kyoo.Utils;
using TvDbSharper.Dto;
namespace Kyoo.TheTvdb
{
/// <summary>
/// A set of extensions methods used to convert tvdb models to Kyoo models.
/// </summary>
public static class Convertors
{
/// <summary>
/// Convert the string representation of the status in the tvdb API to a Kyoo's <see cref="Status"/> enum.
/// </summary>
/// <param name="status">The string representing the status.</param>
/// <returns>A kyoo <see cref="Status"/> value or null.</returns>
private static Status _GetStatus(string status)
{
return status switch
{
"Ended" => Status.Finished,
"Continuing" => Status.Airing,
_ => Status.Unknown
};
}
/// <summary>
/// Parse a TVDB date and return a <see cref="DateTime"/> or null if the string is invalid.
/// </summary>
/// <param name="date">The date string to parse</param>
/// <returns>The parsed <see cref="DateTime"/> or null.</returns>
private static DateTime? _ParseDate(string date)
{
return DateTime.TryParseExact(date, "yyyy-MM-dd", CultureInfo.InvariantCulture,
DateTimeStyles.None, out DateTime parsed)
? parsed
: null;
}
/// <summary>
/// Convert a series search to a show.
/// </summary>
/// <param name="result">The search result</param>
/// <param name="provider">The provider representing the tvdb inside kyoo</param>
/// <returns>A show representing the given search result.</returns>
public static Show ToShow(this SeriesSearchResult result, Provider provider)
{
return new Show
{
Slug = result.Slug,
Title = result.SeriesName,
Aliases = result.Aliases,
Overview = result.Overview,
Status = _GetStatus(result.Status),
StartAir = _ParseDate(result.FirstAired),
Images = new Dictionary<int, string>
{
[Images.Poster] = !string.IsNullOrEmpty(result.Poster)
? $"https://www.thetvdb.com{result.Poster}"
: null,
},
ExternalIDs = new[]
{
new MetadataID
{
DataID = result.Id.ToString(),
Link = $"https://www.thetvdb.com/series/{result.Slug}",
Provider = provider
}
}
};
}
/// <summary>
/// Convert a tvdb series to a kyoo show.
/// </summary>
/// <param name="series">The series to convert</param>
/// <param name="provider">The provider representing the tvdb inside kyoo</param>
/// <returns>A show representing the given series.</returns>
public static Show ToShow(this Series series, Provider provider)
{
return new Show
{
Slug = series.Slug,
Title = series.SeriesName,
Aliases = series.Aliases,
Overview = series.Overview,
Status = _GetStatus(series.Status),
StartAir = _ParseDate(series.FirstAired),
Images = new Dictionary<int, string>
{
[Images.Poster] = !string.IsNullOrEmpty(series.Poster)
? $"https://www.thetvdb.com/banners/{series.Poster}"
: null,
[Images.Thumbnail] = !string.IsNullOrEmpty(series.FanArt)
? $"https://www.thetvdb.com/banners/{series.FanArt}"
: null
},
Genres = series.Genre.Select(y => new Genre(y)).ToList(),
ExternalIDs = new[]
{
new MetadataID
{
DataID = series.Id.ToString(),
Link = $"https://www.thetvdb.com/series/{series.Slug}",
Provider = provider
}
}
};
}
/// <summary>
/// Convert a tvdb actor to a kyoo <see cref="PeopleRole"/>.
/// </summary>
/// <param name="actor">The actor to convert</param>
/// <returns>A people role representing the given actor in the role they played.</returns>
public static PeopleRole ToPeopleRole(this Actor actor)
{
return new PeopleRole
{
People = new People
{
Slug = Utility.ToSlug(actor.Name),
Name = actor.Name,
Images = new Dictionary<int, string>
{
[Images.Poster] = !string.IsNullOrEmpty(actor.Image)
? $"https://www.thetvdb.com/banners/{actor.Image}"
: null
}
},
Role = actor.Role,
Type = "Actor"
};
}
/// <summary>
/// Convert a tvdb episode to a kyoo <see cref="Episode"/>.
/// </summary>
/// <param name="episode">The episode to convert</param>
/// <param name="provider">The provider representing the tvdb inside kyoo</param>
/// <returns>A episode representing the given tvdb episode.</returns>
public static Episode ToEpisode(this EpisodeRecord episode, Provider provider)
{
return new Episode
{
SeasonNumber = episode.AiredSeason,
EpisodeNumber = episode.AiredEpisodeNumber,
AbsoluteNumber = episode.AbsoluteNumber,
Title = episode.EpisodeName,
Overview = episode.Overview,
Images = new Dictionary<int, string>
{
[Images.Thumbnail] = !string.IsNullOrEmpty(episode.Filename)
? $"https://www.thetvdb.com/banners/{episode.Filename}"
: null
},
ExternalIDs = new[]
{
new MetadataID
{
DataID = episode.Id.ToString(),
Link = $"https://www.thetvdb.com/series/{episode.SeriesId}/episodes/{episode.Id}",
Provider = provider
}
}
};
}
}
}

View File

@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Kyoo.TheTvdb</AssemblyName>
<RootNamespace>Kyoo.TheTvdb</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
<PackageReference Include="TvDbSharper" Version="3.2.2" />
<ProjectReference Include="../Kyoo.Abstractions/Kyoo.Abstractions.csproj" />
</ItemGroup>
</Project>

View File

@ -1,81 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using Autofac;
using Kyoo.Abstractions;
using Kyoo.Abstractions.Controllers;
using Kyoo.TheTvdb.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using TvDbSharper;
namespace Kyoo.TheTvdb
{
/// <summary>
/// A plugin that add a <see cref="IMetadataProvider"/> for The TVDB.
/// </summary>
public class PluginTvdb : IPlugin
{
/// <inheritdoc />
public string Slug => "the-tvdb";
/// <inheritdoc />
public string Name => "TVDB";
/// <inheritdoc />
public string Description => "A metadata provider for The TVDB.";
/// <inheritdoc />
public bool Enabled => !string.IsNullOrEmpty(_configuration.GetValue<string>("tvdb:apikey"));
/// <inheritdoc />
public Dictionary<string, Type> Configuration => new()
{
{ TvdbOption.Path, typeof(TvdbOption) }
};
/// <summary>
/// The configuration used to check if the api key is present or not.
/// </summary>
private readonly IConfiguration _configuration;
/// <summary>
/// Create a new <see cref="PluginTvdb"/>.
/// </summary>
/// <param name="configuration">The configuration used to check if the api key is present or not.</param>
/// <param name="logger">The logger used to warn when the api key is not present.</param>
public PluginTvdb(IConfiguration configuration, ILogger<PluginTvdb> logger)
{
_configuration = configuration;
if (!Enabled)
{
logger.LogWarning("No API key configured for TVDB provider. " +
"To enable TVDB, specify one in the setting TVDB:APIKEY ");
}
}
/// <inheritdoc />
public void Configure(ContainerBuilder builder)
{
builder.RegisterType<TvDbClient>().As<ITvDbClient>();
builder.RegisterProvider<ProviderTvdb>();
}
}
}

View File

@ -1,165 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.TheTvdb.Models;
using Microsoft.Extensions.Options;
using TvDbSharper;
using TvDbSharper.Dto;
namespace Kyoo.TheTvdb
{
/// <summary>
/// A metadata provider for The TVDB.
/// </summary>
public class ProviderTvdb : IMetadataProvider
{
/// <summary>
/// The internal tvdb client used to make requests.
/// </summary>
private readonly ITvDbClient _client;
/// <summary>
/// The API key used to authenticate with the tvdb API.
/// </summary>
private readonly IOptions<TvdbOption> _apiKey;
/// <inheritdoc />
public Provider Provider => new()
{
Slug = "the-tvdb",
Name = "TheTVDB",
Images = new Dictionary<int, string>
{
[Images.Logo] = "https://www.thetvdb.com/images/logo.png"
}
};
/// <summary>
/// Create a new <see cref="ProviderTvdb"/> using a tvdb client and an api key.
/// </summary>
/// <param name="client">The tvdb client to use</param>
/// <param name="apiKey">The api key</param>
public ProviderTvdb(ITvDbClient client, IOptions<TvdbOption> apiKey)
{
_client = client;
_apiKey = apiKey;
}
/// <summary>
/// Authenticate and refresh the token of the tvdb client.
/// </summary>
private Task _Authenticate()
{
if (_client.Authentication.Token == null)
return _client.Authentication.AuthenticateAsync(_apiKey.Value.ApiKey);
return _client.Authentication.RefreshTokenAsync();
}
/// <inheritdoc />
public async Task<T> Get<T>(T item)
where T : class, IResource
{
await _Authenticate();
return item switch
{
Show show => await _GetShow(show) as T,
Episode episode => await _GetEpisode(episode) as T,
_ => null
};
}
/// <summary>
/// Retrieve metadata about a show.
/// </summary>
/// <param name="show">The base show to retrieve metadata for.</param>
/// <returns>A new show filled with metadata from the tvdb.</returns>
[ItemCanBeNull]
private async Task<Show> _GetShow([NotNull] Show show)
{
if (show.IsMovie)
return null;
if (!int.TryParse(show.GetID(Provider.Slug), out int id))
{
Show found = (await _SearchShow(show.Title)).FirstOrDefault();
if (found == null)
return null;
return await Get(found);
}
TvDbResponse<Series> series = await _client.Series.GetAsync(id);
Show ret = series.Data.ToShow(Provider);
TvDbResponse<Actor[]> people = await _client.Series.GetActorsAsync(id);
ret.People = people.Data.Select(x => x.ToPeopleRole()).ToArray();
return ret;
}
/// <summary>
/// Retrieve metadata about an episode.
/// </summary>
/// <param name="episode">The base episode to retrieve metadata for.</param>
/// <returns>A new episode filled with metadata from the tvdb.</returns>
[ItemCanBeNull]
private async Task<Episode> _GetEpisode([NotNull] Episode episode)
{
if (!int.TryParse(episode.Show?.GetID(Provider.Slug), out int id))
return null;
EpisodeQuery query = episode.AbsoluteNumber != null
? new EpisodeQuery { AbsoluteNumber = episode.AbsoluteNumber }
: new EpisodeQuery { AiredSeason = episode.SeasonNumber, AiredEpisode = episode.EpisodeNumber };
TvDbResponse<EpisodeRecord[]> episodes = await _client.Series.GetEpisodesAsync(id, 0, query);
return episodes.Data.FirstOrDefault()?.ToEpisode(Provider);
}
/// <inheritdoc />
public async Task<ICollection<T>> Search<T>(string query)
where T : class, IResource
{
await _Authenticate();
if (typeof(T) == typeof(Show))
return (await _SearchShow(query) as ICollection<T>)!;
return ArraySegment<T>.Empty;
}
/// <summary>
/// Search for shows in the tvdb.
/// </summary>
/// <param name="query">The query to ask the tvdb about.</param>
/// <returns>A list of shows that could be found on the tvdb.</returns>
[ItemNotNull]
private async Task<ICollection<Show>> _SearchShow(string query)
{
try
{
TvDbResponse<SeriesSearchResult[]> shows = await _client.Search.SearchSeriesByNameAsync(query);
return shows.Data.Select(x => x.ToShow(Provider)).ToArray();
}
catch (TvDbServerException)
{
return ArraySegment<Show>.Empty;
}
}
}
}

View File

@ -1,36 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
namespace Kyoo.TheTvdb.Models
{
/// <summary>
/// The option containing the api key for the tvdb.
/// </summary>
public class TvdbOption
{
/// <summary>
/// The path to get this option from the root configuration.
/// </summary>
public const string Path = "tvdb";
/// <summary>
/// The api key of the tvdb.
/// </summary>
public string ApiKey { get; set; }
}
}

View File

@ -1,210 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Exceptions;
using Kyoo.Core.Controllers;
using Kyoo.Core.Models.Options;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
namespace Kyoo.Tests.Identifier
{
public class Identifier
{
private readonly Mock<ILibraryManager> _manager;
private readonly IIdentifier _identifier;
public Identifier()
{
Mock<IOptionsMonitor<MediaOptions>> options = new();
options.Setup(x => x.CurrentValue).Returns(new MediaOptions
{
Regex = new[]
{
"^\\/?(?<Collection>.+)?\\/(?<Show>.+?)(?: \\((?<StartYear>\\d+)\\))?\\/\\k<Show>(?: \\(\\d+\\))? S(?<Season>\\d+)E(?<Episode>\\d+)\\..*$",
"^\\/?(?<Collection>.+)?\\/(?<Show>.+?)(?: \\((?<StartYear>\\d+)\\))?\\/\\k<Show>(?: \\(\\d+\\))? (?<Absolute>\\d+)\\..*$",
"^\\/?(?<Collection>.+)?\\/(?<Show>.+?)(?: \\((?<StartYear>\\d+)\\))?\\/\\k<Show>(?: \\(\\d+\\))?\\..*$"
},
SubtitleRegex = new[]
{
"^(?<Episode>.+)\\.(?<Language>\\w{1,3})\\.(?<Default>default\\.)?(?<Forced>forced\\.)?.*$"
}
});
_manager = new Mock<ILibraryManager>();
_identifier = new RegexIdentifier(options.Object, _manager.Object);
}
[Fact]
public async Task EpisodeIdentification()
{
_manager.Setup(x => x.GetAll<Library>(null, default, default)).ReturnsAsync(new[]
{
new Library {Paths = new [] {"/kyoo/Library/"}}
});
(Collection collection, Show show, Season season, Episode episode) = await _identifier.Identify(
"/kyoo/Library/Collection/Show (2000)/Show S01E01.extension");
Assert.Equal("Collection", collection.Name);
Assert.Equal("collection", collection.Slug);
Assert.Equal("Show", show.Title);
Assert.Equal("show", show.Slug);
Assert.Equal(2000, show.StartAir!.Value.Year);
Assert.Equal(1, season.SeasonNumber);
Assert.Equal(1, episode.SeasonNumber);
Assert.Equal(1, episode.EpisodeNumber);
Assert.Null(episode.AbsoluteNumber);
}
[Fact]
public async Task EpisodeIdentificationWithoutLibraryTrailingSlash()
{
_manager.Setup(x => x.GetAll<Library>(null, default, default)).ReturnsAsync(new[]
{
new Library {Paths = new [] {"/kyoo/Library"}}
});
(Collection collection, Show show, Season season, Episode episode) = await _identifier.Identify(
"/kyoo/Library/Collection/Show (2000)/Show S01E01.extension");
Assert.Equal("Collection", collection.Name);
Assert.Equal("collection", collection.Slug);
Assert.Equal("Show", show.Title);
Assert.Equal("show", show.Slug);
Assert.Equal(2000, show.StartAir!.Value.Year);
Assert.Equal(1, season.SeasonNumber);
Assert.Equal(1, episode.SeasonNumber);
Assert.Equal(1, episode.EpisodeNumber);
Assert.Null(episode.AbsoluteNumber);
}
[Fact]
public async Task EpisodeIdentificationMultiplePaths()
{
_manager.Setup(x => x.GetAll<Library>(null, default, default)).ReturnsAsync(new[]
{
new Library {Paths = new [] {"/kyoo", "/kyoo/Library/"}}
});
(Collection collection, Show show, Season season, Episode episode) = await _identifier.Identify(
"/kyoo/Library/Collection/Show (2000)/Show S01E01.extension");
Assert.Equal("Collection", collection.Name);
Assert.Equal("collection", collection.Slug);
Assert.Equal("Show", show.Title);
Assert.Equal("show", show.Slug);
Assert.Equal(2000, show.StartAir!.Value.Year);
Assert.Equal(1, season.SeasonNumber);
Assert.Equal(1, episode.SeasonNumber);
Assert.Equal(1, episode.EpisodeNumber);
Assert.Null(episode.AbsoluteNumber);
}
[Fact]
public async Task AbsoluteEpisodeIdentification()
{
_manager.Setup(x => x.GetAll<Library>(null, default, default)).ReturnsAsync(new[]
{
new Library {Paths = new [] {"/kyoo", "/kyoo/Library/"}}
});
(Collection collection, Show show, Season season, Episode episode) = await _identifier.Identify(
"/kyoo/Library/Collection/Show (2000)/Show 100.extension");
Assert.Equal("Collection", collection.Name);
Assert.Equal("collection", collection.Slug);
Assert.Equal("Show", show.Title);
Assert.Equal("show", show.Slug);
Assert.Equal(2000, show.StartAir!.Value.Year);
Assert.Null(season);
Assert.Null(episode.SeasonNumber);
Assert.Null(episode.EpisodeNumber);
Assert.Equal(100, episode.AbsoluteNumber);
}
[Fact]
public async Task MovieEpisodeIdentification()
{
_manager.Setup(x => x.GetAll<Library>(null, default, default)).ReturnsAsync(new[]
{
new Library {Paths = new [] {"/kyoo", "/kyoo/Library/"}}
});
(Collection collection, Show show, Season season, Episode episode) = await _identifier.Identify(
"/kyoo/Library/Collection/Show (2000)/Show.extension");
Assert.Equal("Collection", collection.Name);
Assert.Equal("collection", collection.Slug);
Assert.Equal("Show", show.Title);
Assert.Equal("show", show.Slug);
Assert.Equal(2000, show.StartAir!.Value.Year);
Assert.Null(season);
Assert.True(show.IsMovie);
Assert.Null(episode.SeasonNumber);
Assert.Null(episode.EpisodeNumber);
Assert.Null(episode.AbsoluteNumber);
}
[Fact]
public async Task InvalidEpisodeIdentification()
{
_manager.Setup(x => x.GetAll<Library>(null, default, default)).ReturnsAsync(new[]
{
new Library {Paths = new [] {"/kyoo", "/kyoo/Library/"}}
});
await Assert.ThrowsAsync<IdentificationFailedException>(() => _identifier.Identify("/invalid/path"));
}
[Fact]
public async Task SubtitleIdentification()
{
_manager.Setup(x => x.GetAll<Library>(null, default, default)).ReturnsAsync(new[]
{
new Library {Paths = new [] {"/kyoo", "/kyoo/Library/"}}
});
Track track = await _identifier.IdentifyTrack("/kyoo/Library/Collection/Show (2000)/Show.eng.default.str");
Assert.True(track.IsExternal);
Assert.Equal("eng", track.Language);
Assert.Equal("subrip", track.Codec);
Assert.True(track.IsDefault);
Assert.False(track.IsForced);
Assert.StartsWith("/kyoo/Library/Collection/Show (2000)/Show", track.Episode.Path);
}
[Fact]
public async Task SubtitleIdentificationUnknownCodec()
{
_manager.Setup(x => x.GetAll<Library>(null, default, default)).ReturnsAsync(new[]
{
new Library {Paths = new [] {"/kyoo", "/kyoo/Library/"}}
});
Track track = await _identifier.IdentifyTrack("/kyoo/Library/Collection/Show (2000)/Show.eng.default.extension");
Assert.True(track.IsExternal);
Assert.Equal("eng", track.Language);
Assert.Equal("extension", track.Codec);
Assert.True(track.IsDefault);
Assert.False(track.IsForced);
Assert.StartsWith("/kyoo/Library/Collection/Show (2000)/Show", track.Episode.Path);
}
[Fact]
public async Task InvalidSubtitleIdentification()
{
_manager.Setup(x => x.GetAll<Library>(null, default, default)).ReturnsAsync(new[]
{
new Library {Paths = new [] {"/kyoo", "/kyoo/Library/"}}
});
await Assert.ThrowsAsync<IdentificationFailedException>(() => _identifier.IdentifyTrack("/invalid/path"));
}
}
}

View File

@ -1,143 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.Core.Controllers;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
using Xunit.Abstractions;
namespace Kyoo.Tests.Identifier
{
public class ProviderTests
{
private readonly ILoggerFactory _factory;
public ProviderTests(ITestOutputHelper output)
{
_factory = LoggerFactory.Create(x =>
{
x.ClearProviders();
x.AddXunit(output);
});
}
[Fact]
public async Task NoProviderGetTest()
{
AProviderComposite provider = new ProviderComposite(Array.Empty<IMetadataProvider>(),
_factory.CreateLogger<ProviderComposite>());
Show show = new()
{
ID = 4,
Genres = new[] { new Genre("genre") }
};
Show ret = await provider.Get(show);
KAssert.DeepEqual(show, ret);
}
[Fact]
public async Task NoProviderSearchTest()
{
AProviderComposite provider = new ProviderComposite(Array.Empty<IMetadataProvider>(),
_factory.CreateLogger<ProviderComposite>());
ICollection<Show> ret = await provider.Search<Show>("show");
Assert.Empty(ret);
}
[Fact]
public async Task OneProviderGetTest()
{
Show show = new()
{
ID = 4,
Genres = new[] { new Genre("genre") }
};
Mock<IMetadataProvider> mock = new();
mock.Setup(x => x.Get(show)).ReturnsAsync(new Show
{
Title = "title",
Genres = new[] { new Genre("ToMerge") }
});
AProviderComposite provider = new ProviderComposite(new[]
{
mock.Object
},
_factory.CreateLogger<ProviderComposite>());
Show ret = await provider.Get(show);
Assert.Equal(4, ret.ID);
Assert.Equal("title", ret.Title);
Assert.Equal(2, ret.Genres.Count);
Assert.Contains("genre", ret.Genres.Select(x => x.Slug));
Assert.Contains("tomerge", ret.Genres.Select(x => x.Slug));
}
[Fact]
public async Task FailingProviderGetTest()
{
Show show = new()
{
ID = 4,
Genres = new[] { new Genre("genre") }
};
Mock<IMetadataProvider> mock = new();
mock.Setup(x => x.Provider).Returns(new Provider("mock", string.Empty));
mock.Setup(x => x.Get(show)).ReturnsAsync(new Show
{
Title = "title",
Genres = new[] { new Genre("ToMerge") }
});
Mock<IMetadataProvider> mockTwo = new();
mockTwo.Setup(x => x.Provider).Returns(new Provider("mockTwo", string.Empty));
mockTwo.Setup(x => x.Get(show)).ReturnsAsync(new Show
{
Title = "title2",
Status = Status.Finished,
Genres = new[] { new Genre("ToMerge") }
});
Mock<IMetadataProvider> mockFailing = new();
mockFailing.Setup(x => x.Provider).Returns(new Provider("mockFail", string.Empty));
mockFailing.Setup(x => x.Get(show)).Throws<ArgumentException>();
AProviderComposite provider = new ProviderComposite(new[]
{
mock.Object,
mockTwo.Object,
mockFailing.Object
},
_factory.CreateLogger<ProviderComposite>());
Show ret = await provider.Get(show);
Assert.Equal(4, ret.ID);
Assert.Equal("title", ret.Title);
Assert.Equal(Status.Finished, ret.Status);
Assert.Equal(2, ret.Genres.Count);
Assert.Contains("genre", ret.Genres.Select(x => x.Slug));
Assert.Contains("tomerge", ret.Genres.Select(x => x.Slug));
}
}
}

View File

@ -1,177 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Linq;
using Kyoo.Abstractions.Models;
using Kyoo.TheTvdb;
using TvDbSharper.Dto;
using Xunit;
namespace Kyoo.Tests.Identifier.Tvdb
{
public class ConvertorTests
{
[Fact]
public void SeriesSearchToShow()
{
SeriesSearchResult result = new()
{
Slug = "slug",
SeriesName = "name",
Aliases = new[] { "Aliases" },
Overview = "overview",
Status = "Ended",
FirstAired = "2021-07-23",
Poster = "/poster",
Id = 5
};
Provider provider = TestSample.Get<Provider>();
Show show = result.ToShow(provider);
Assert.Equal("slug", show.Slug);
Assert.Equal("name", show.Title);
Assert.Single(show.Aliases);
Assert.Equal("Aliases", show.Aliases[0]);
Assert.Equal("overview", show.Overview);
Assert.Equal(new DateTime(2021, 7, 23), show.StartAir);
Assert.Equal("https://www.thetvdb.com/poster", show.Images[Images.Poster]);
Assert.Single(show.ExternalIDs);
Assert.Equal("5", show.ExternalIDs.First().DataID);
Assert.Equal(provider, show.ExternalIDs.First().Provider);
Assert.Equal("https://www.thetvdb.com/series/slug", show.ExternalIDs.First().Link);
Assert.Equal(Status.Finished, show.Status);
}
[Fact]
public void SeriesSearchToShowInvalidDate()
{
SeriesSearchResult result = new()
{
Slug = "slug",
SeriesName = "name",
Aliases = new[] { "Aliases" },
Overview = "overview",
Status = "ad",
FirstAired = "2e021-07-23",
Poster = "/poster",
Id = 5
};
Provider provider = TestSample.Get<Provider>();
Show show = result.ToShow(provider);
Assert.Equal("slug", show.Slug);
Assert.Equal("name", show.Title);
Assert.Single(show.Aliases);
Assert.Equal("Aliases", show.Aliases[0]);
Assert.Equal("overview", show.Overview);
Assert.Null(show.StartAir);
Assert.Equal("https://www.thetvdb.com/poster", show.Images[Images.Poster]);
Assert.Single(show.ExternalIDs);
Assert.Equal("5", show.ExternalIDs.First().DataID);
Assert.Equal(provider, show.ExternalIDs.First().Provider);
Assert.Equal("https://www.thetvdb.com/series/slug", show.ExternalIDs.First().Link);
Assert.Equal(Status.Unknown, show.Status);
}
[Fact]
public void SeriesToShow()
{
Series result = new()
{
Slug = "slug",
SeriesName = "name",
Aliases = new[] { "Aliases" },
Overview = "overview",
Status = "Continuing",
FirstAired = "2021-07-23",
Poster = "poster",
FanArt = "fanart",
Id = 5,
Genre = new[]
{
"Action",
"Test With Sp??acial characters"
}
};
Provider provider = TestSample.Get<Provider>();
Show show = result.ToShow(provider);
Assert.Equal("slug", show.Slug);
Assert.Equal("name", show.Title);
Assert.Single(show.Aliases);
Assert.Equal("Aliases", show.Aliases[0]);
Assert.Equal("overview", show.Overview);
Assert.Equal(new DateTime(2021, 7, 23), show.StartAir);
Assert.Equal("https://www.thetvdb.com/banners/poster", show.Images[Images.Poster]);
Assert.Equal("https://www.thetvdb.com/banners/fanart", show.Images[Images.Thumbnail]);
Assert.Single(show.ExternalIDs);
Assert.Equal("5", show.ExternalIDs.First().DataID);
Assert.Equal(provider, show.ExternalIDs.First().Provider);
Assert.Equal("https://www.thetvdb.com/series/slug", show.ExternalIDs.First().Link);
Assert.Equal(Status.Airing, show.Status);
Assert.Equal(2, show.Genres.Count);
Assert.Equal("action", show.Genres.ToArray()[0].Slug);
Assert.Equal("Action", show.Genres.ToArray()[0].Name);
Assert.Equal("Test With Sp??acial characters", show.Genres.ToArray()[1].Name);
Assert.Equal("test-with-spacial-characters", show.Genres.ToArray()[1].Slug);
}
[Fact]
public void ActorToPeople()
{
Actor actor = new()
{
Id = 5,
Image = "image",
Name = "Name",
Role = "role"
};
PeopleRole people = actor.ToPeopleRole();
Assert.Equal("name", people.Slug);
Assert.Equal("Name", people.People.Name);
Assert.Equal("role", people.Role);
Assert.Equal("https://www.thetvdb.com/banners/image", people.People.Images[Images.Poster]);
}
[Fact]
public void EpisodeRecordToEpisode()
{
EpisodeRecord record = new()
{
Id = 5,
AiredSeason = 2,
AiredEpisodeNumber = 3,
AbsoluteNumber = 23,
EpisodeName = "title",
Overview = "overview",
Filename = "thumb"
};
Provider provider = TestSample.Get<Provider>();
Episode episode = record.ToEpisode(provider);
Assert.Equal("title", episode.Title);
Assert.Equal(2, episode.SeasonNumber);
Assert.Equal(3, episode.EpisodeNumber);
Assert.Equal(23, episode.AbsoluteNumber);
Assert.Equal("overview", episode.Overview);
Assert.Equal("https://www.thetvdb.com/banners/thumb", episode.Images[Images.Thumbnail]);
}
}
}

View File

@ -31,6 +31,5 @@
<ItemGroup>
<ProjectReference Include="../../src/Kyoo.Abstractions/Kyoo.Abstractions.csproj" />
<ProjectReference Include="..\..\src\Kyoo.Host\Kyoo.Host.csproj" />
<ProjectReference Include="../../src/Kyoo.TheTvdb/Kyoo.TheTvdb.csproj" />
</ItemGroup>
</Project>