Implementing the tvdb provider

This commit is contained in:
Zoe Roux 2021-07-14 01:50:05 +02:00
parent ecb4101924
commit 2d45d6422d
4 changed files with 245 additions and 180 deletions

View File

@ -35,7 +35,7 @@ namespace Kyoo.Controllers
/// If this metadata provider does not support <typeparamref name="T"/>.
/// </exception>
/// <returns>A new <typeparamref name="T"/> containing metadata from your provider</returns>
[ItemNotNull]
[ItemCanBeNull]
Task<T> Get<T>([NotNull] T item)
where T : class, IResource;

157
Kyoo.TheTvdb/Convertors.cs Normal file
View File

@ -0,0 +1,157 @@
using System;
using System.Globalization;
using System.Linq;
using Kyoo.Models;
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,
_ => null
};
}
/// <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)
{
DateTime.TryParseExact(date, "yyyy-mm-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsed);
return parsed;
}
/// <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()
{
Slug = result.Slug,
Title = result.SeriesName,
Aliases = result.Aliases,
Overview = result.Overview,
Status = GetStatus(result.Status),
StartAir = ParseDate(result.FirstAired),
Poster = result.Poster != null ? $"https://www.thetvdb.com{result.Poster}" : null,
ExternalIDs = new[]
{
new MetadataID<Show>
{
DataID = result.Id.ToString(),
Link = $"https://www.thetvdb.com/series/{result.Slug}",
Second = 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()
{
Slug = series.Slug,
Title = series.SeriesName,
Aliases = series.Aliases,
Overview = series.Overview,
Status = GetStatus(series.Status),
StartAir = ParseDate(series.FirstAired),
Poster = series.Poster != null ? $"https://www.thetvdb.com/banners/{series.Poster}" : null,
Backdrop = series.FanArt != null ? $"https://www.thetvdb.com/banners/{series.FanArt}" : null,
Genres = series.Genre.Select(y => new Genre(y)).ToList(),
ExternalIDs = new[]
{
new MetadataID<Show>
{
DataID = series.Id.ToString(),
Link = $"https://www.thetvdb.com/series/{series.Slug}",
Second = provider
}
}
};
}
/// <summary>
/// Convert a tvdb actor to a kyoo <see cref="PeopleRole"/>.
/// </summary>
/// <param name="actor">The actor to convert</param>
/// <param name="provider">The provider representing the tvdb inside kyoo</param>
/// <returns>A people role representing the given actor in the role they played.</returns>
public static PeopleRole ToPeopleRole(this Actor actor, Provider provider)
{
return new()
{
People = new People
{
Slug = Utility.ToSlug(actor.Name),
Name = actor.Name,
Poster = actor.Image != null ? $"https://www.thetvdb.com/banners/{actor.Image}" : null,
ExternalIDs = new []
{
new MetadataID<People>()
{
DataID = actor.Id.ToString(),
Link = $"https://www.thetvdb.com/people/{actor.Id}",
Second = provider
}
}
},
Role = actor.Role
};
}
/// <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()
{
SeasonNumber = episode.AiredSeason,
EpisodeNumber = episode.AiredEpisodeNumber,
AbsoluteNumber = episode.AbsoluteNumber,
Title = episode.EpisodeName,
Overview = episode.Overview,
Thumb = episode.Filename != null ? $"https://www.thetvdb.com/banners/{episode.Filename}" : null,
ExternalIDs = new[]
{
new MetadataID<Episode>
{
DataID = episode.Id.ToString(),
Link = $"https://www.thetvdb.com/series/{episode.SeriesId}/episodes/{episode.Id}",
Second = provider
}
}
};
}
}
}

View File

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using Autofac;
using Kyoo.Controllers;
using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.TheTvdb
{
@ -33,9 +33,9 @@ namespace Kyoo.TheTvdb
/// <inheritdoc />
public void Configure(IServiceCollection services, ICollection<Type> availableTypes)
public void Configure(ContainerBuilder builder)
{
// services.AddProvider<ProviderTvdb>();
builder.RegisterProvider<ProviderTvdb>();
}
}
}

View File

@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Kyoo.Controllers;
using Kyoo.Models;
using TvDbSharper;
@ -15,189 +15,97 @@ namespace Kyoo.TheTvdb
/// </summary>
public class ProviderTvdb : IMetadataProvider
{
public Provider Provider { get; }
public Task<T> Get<T>(T item) where T : class, IResource
/// <summary>
/// The internal tvdb client used to make requests.
/// </summary>
private readonly TvDbClient _client = new();
/// <summary>
/// The API key used to authenticate with the tvdb API.
/// </summary>
private readonly string _apiKey;
/// <inheritdoc />
public Provider Provider => new()
{
throw new NotImplementedException();
Slug = "the-tvdb",
Name = "TheTVDB",
LogoExtension = "png",
Logo = "https://www.thetvdb.com/images/logo.png"
};
public ProviderTvdb(string apiKey)
{
_apiKey = apiKey;
}
public Task<ICollection<T>> Search<T>(string query) where T : class, IResource
private Task _Authenticate()
{
throw new NotImplementedException();
if (_client.Authentication.Token == null)
return _client.Authentication.AuthenticateAsync(_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,
_ => throw new NotSupportedException()
};
}
[ItemCanBeNull]
private async Task<Show> _GetShow([NotNull] Show show)
{
if (!int.TryParse(show.GetID(Provider.Slug), out int id))
return (await _SearchShow(show.Title)).FirstOrDefault();
TvDbResponse<Series> series = await _client.Series.GetAsync(id);
return series.Data.ToShow(Provider);
}
public Task<ICollection<PeopleRole>> GetPeople(Show show)
[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>)!;
throw new NotImplementedException();
}
[ItemNotNull]
private async Task<ICollection<Show>> _SearchShow(string query)
{
TvDbResponse<SeriesSearchResult[]> shows = await _client.Search.SearchSeriesByNameAsync(query);
return shows.Data.Select(x => x.ToShow(Provider)).ToArray();
}
/// <inheritdoc />
public async Task<ICollection<PeopleRole>> GetPeople(Show show)
{
if (!int.TryParse(show?.GetID(Provider.Name), out int id))
return null;
await _Authenticate();
TvDbResponse<Actor[]> people = await _client.Series.GetActorsAsync(id);
return people.Data.Select(x => x.ToPeopleRole(Provider)).ToArray();
}
}
// public class Old
// {
// private static readonly ProviderID _provider = new()
// {
// Slug = "the-tvdb",
// Name = "TheTVDB",
// LogoExtension = "png",
// Logo = "https://www.thetvdb.com/images/logo.png"
// };
// public ProviderID Provider => _provider;
//
//
// private readonly TvDbClient _client = new();
//
// private Task Authentificate()
// {
// if (_client.Authentication.Token == null)
// return _client.Authentication.AuthenticateAsync(APIKey);
// return _client.Authentication.RefreshTokenAsync();
// }
//
// public Task<Collection> GetCollectionFromName(string name)
// {
// return Task.FromResult<Collection>(null);
// }
//
// public async Task<ICollection<Show>> SearchShows(string showName, bool isMovie)
// {
// await Authentificate();
//
// if (isMovie)
// return null; //There is no movie search API for now on TheTVDB.
// TvDbResponse<SeriesSearchResult[]> shows = await _client.Search.SearchSeriesAsync(showName, SearchParameter.Name);
// return shows.Data.Select(x => x.ToShow(Provider)).ToArray();
// }
//
// public async Task<Show> GetShowByID(Show show)
// {
// if (!int.TryParse(show?.GetID(Provider.Name), out int id))
// return await Task.FromResult<Show>(null);
// await Authentificate();
// TvDbResponse<Series> serie = await _client.Series.GetAsync(id);
// return serie.Data.ToShow(Provider);
// }
//
// public async Task<ICollection<PeopleRole>> GetPeople(Show show)
// {
// if (!int.TryParse(show?.GetID(Provider.Name), out int id))
// return null;
// await Authentificate();
// TvDbResponse<Actor[]> people = await _client.Series.GetActorsAsync(id);
// return people.Data.Select(x => x.ToPeopleRole(Provider)).ToArray();
// }
//
// public Task<Season> GetSeason(Show show, int seasonNumber)
// {
// return Task.FromResult<Season>(null);
// }
//
// public async Task<Episode> GetEpisode(Show show, int seasonNumber, int episodeNumber, int absoluteNumber)
// {
// if (!int.TryParse(show?.GetID(Provider.Name), out int id))
// return null;
// await Authentificate();
// TvDbResponse<EpisodeRecord[]> episodes = absoluteNumber != -1
// ? await _client.Series.GetEpisodesAsync(id, 0, new EpisodeQuery {AbsoluteNumber = absoluteNumber})
// : await _client.Series.GetEpisodesAsync(id, 0, new EpisodeQuery {AiredSeason = seasonNumber, AiredEpisode = episodeNumber});
// EpisodeRecord x = episodes.Data[0];
//
// if (absoluteNumber == -1)
// absoluteNumber = x.AbsoluteNumber ?? -1;
// else
// {
// seasonNumber = x.AiredSeason ?? -1;
// episodeNumber = x.AiredEpisodeNumber ?? -1;
// }
//
// return new Episode(seasonNumber,
// episodeNumber,
// absoluteNumber,
// x.EpisodeName,
// x.Overview,
// DateTime.ParseExact(x.FirstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture),
// -1,
// x.Filename != null ? "https://www.thetvdb.com/banners/" + x.Filename : null,
// new []
// {
// new MetadataID(Provider, x.Id.ToString(), $"https://www.thetvdb.com/series/{id}/episodes/{x.Id}")
// });
// }
// }
// public static class Convertors
// {
// private static int? GetYear(string firstAired)
// {
// if (firstAired?.Length >= 4 && int.TryParse(firstAired.Substring(0, 4), out int year))
// return year;
// return null;
// }
//
// private static Status? GetStatus(string status)
// {
// return status switch
// {
// "Ended" => Status.Finished,
// "Continuing" => Status.Airing,
// _ => null
// };
// }
//
// public static Show ToShow(this SeriesSearchResult x, ProviderID provider)
// {
// Show ret = new(x.Slug,
// x.SeriesName,
// x.Aliases,
// null,
// x.Overview,
// null,
// null,
// GetStatus(x.Status),
// GetYear(x.FirstAired),
// null,
// new[]
// {
// new MetadataID(provider, x.Id.ToString(), $"https://www.thetvdb.com/series/{x.Slug}")
// });
// if (x.Poster != null)
// Utility.SetImage(ret, $"https://www.thetvdb.com{x.Poster}", ImageType.Poster);
// return ret;
// }
//
// public static Show ToShow(this Series x, ProviderID provider)
// {
// return new(x.Slug,
// x.SeriesName,
// x.Aliases,
// null,
// x.Overview,
// null,
// x.Genre.Select(y => new Genre(Utility.ToSlug(y), y)),
// GetStatus(x.Status),
// GetYear(x.FirstAired),
// null,
// new[]
// {
// new MetadataID(provider, x.Id.ToString(),$"https://www.thetvdb.com/series/{x.Slug}")
// })
// {
// Poster = x.Poster != null ? $"https://www.thetvdb.com/banners/{x.Poster}" : null,
// Backdrop = x.FanArt != null ? $"https://www.thetvdb.com/banners/{x.FanArt}" : null
// };
// }
//
// public static PeopleRole ToPeopleRole(this Actor x, ProviderID provider)
// {
// return new (Utility.ToSlug(x.Name),
// x.Name,
// x.Role,
// null,
// x.Image != null ? $"https://www.thetvdb.com/banners/{x.Image}" : null,
// new[]
// {
// new MetadataID(provider, x.Id.ToString(), $"https://www.thetvdb.com/people/{x.Id}")
// });
// }
// }
}