diff --git a/Kyoo.Common/Controllers/IMetadataProvider.cs b/Kyoo.Common/Controllers/IMetadataProvider.cs
index 9c260030..f17e2d8d 100644
--- a/Kyoo.Common/Controllers/IMetadataProvider.cs
+++ b/Kyoo.Common/Controllers/IMetadataProvider.cs
@@ -35,7 +35,7 @@ namespace Kyoo.Controllers
/// If this metadata provider does not support .
///
/// A new containing metadata from your provider
- [ItemNotNull]
+ [ItemCanBeNull]
Task Get([NotNull] T item)
where T : class, IResource;
diff --git a/Kyoo.TheTvdb/Convertors.cs b/Kyoo.TheTvdb/Convertors.cs
new file mode 100644
index 00000000..b7edd2ea
--- /dev/null
+++ b/Kyoo.TheTvdb/Convertors.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using Kyoo.Models;
+using TvDbSharper.Dto;
+
+namespace Kyoo.TheTvdb
+{
+ ///
+ /// A set of extensions methods used to convert tvdb models to Kyoo models.
+ ///
+ public static class Convertors
+ {
+ ///
+ /// Convert the string representation of the status in the tvdb API to a Kyoo's enum.
+ ///
+ /// The string representing the status.
+ /// A kyoo value or null.
+ private static Status? GetStatus(string status)
+ {
+ return status switch
+ {
+ "Ended" => Status.Finished,
+ "Continuing" => Status.Airing,
+ _ => null
+ };
+ }
+
+ ///
+ /// Parse a TVDB date and return a or null if the string is invalid.
+ ///
+ /// The date string to parse
+ /// The parsed or null.
+ private static DateTime ParseDate(string date)
+ {
+ DateTime.TryParseExact(date, "yyyy-mm-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsed);
+ return parsed;
+ }
+
+ ///
+ /// Convert a series search to a show.
+ ///
+ /// The search result
+ /// The provider representing the tvdb inside kyoo
+ /// A show representing the given search result.
+ 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
+ {
+ DataID = result.Id.ToString(),
+ Link = $"https://www.thetvdb.com/series/{result.Slug}",
+ Second = provider
+ }
+ }
+ };
+ }
+
+ ///
+ /// Convert a tvdb series to a kyoo show.
+ ///
+ /// The series to convert
+ /// The provider representing the tvdb inside kyoo
+ /// A show representing the given series.
+ 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
+ {
+ DataID = series.Id.ToString(),
+ Link = $"https://www.thetvdb.com/series/{series.Slug}",
+ Second = provider
+ }
+ }
+ };
+ }
+
+ ///
+ /// Convert a tvdb actor to a kyoo .
+ ///
+ /// The actor to convert
+ /// The provider representing the tvdb inside kyoo
+ /// A people role representing the given actor in the role they played.
+ 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()
+ {
+ DataID = actor.Id.ToString(),
+ Link = $"https://www.thetvdb.com/people/{actor.Id}",
+ Second = provider
+ }
+ }
+ },
+ Role = actor.Role
+ };
+ }
+
+ ///
+ /// Convert a tvdb episode to a kyoo .
+ ///
+ /// The episode to convert
+ /// The provider representing the tvdb inside kyoo
+ /// A episode representing the given tvdb episode.
+ 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
+ {
+ DataID = episode.Id.ToString(),
+ Link = $"https://www.thetvdb.com/series/{episode.SeriesId}/episodes/{episode.Id}",
+ Second = provider
+ }
+ }
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kyoo.TheTvdb/PluginTVDB.cs b/Kyoo.TheTvdb/PluginTVDB.cs
index 6484b51d..ea4cab62 100644
--- a/Kyoo.TheTvdb/PluginTVDB.cs
+++ b/Kyoo.TheTvdb/PluginTVDB.cs
@@ -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
///
- public void Configure(IServiceCollection services, ICollection availableTypes)
+ public void Configure(ContainerBuilder builder)
{
- // services.AddProvider();
+ builder.RegisterProvider();
}
}
}
\ No newline at end of file
diff --git a/Kyoo.TheTvdb/ProviderTVDB.cs b/Kyoo.TheTvdb/ProviderTVDB.cs
index eeb065c9..44841326 100644
--- a/Kyoo.TheTvdb/ProviderTVDB.cs
+++ b/Kyoo.TheTvdb/ProviderTVDB.cs
@@ -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
///
public class ProviderTvdb : IMetadataProvider
{
- public Provider Provider { get; }
- public Task Get(T item) where T : class, IResource
+ ///
+ /// The internal tvdb client used to make requests.
+ ///
+ private readonly TvDbClient _client = new();
+
+ ///
+ /// The API key used to authenticate with the tvdb API.
+ ///
+ private readonly string _apiKey;
+
+ ///
+ 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> Search(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();
+ }
+
+ ///
+ public async Task Get(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 _GetShow([NotNull] Show show)
+ {
+ if (!int.TryParse(show.GetID(Provider.Slug), out int id))
+ return (await _SearchShow(show.Title)).FirstOrDefault();
+ TvDbResponse series = await _client.Series.GetAsync(id);
+ return series.Data.ToShow(Provider);
}
- public Task> GetPeople(Show show)
+ [ItemCanBeNull]
+ private async Task _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 episodes = await _client.Series.GetEpisodesAsync(id, 0, query);
+ return episodes.Data.FirstOrDefault()?.ToEpisode(Provider);
+ }
+
+ ///
+ public async Task> Search(string query)
+ where T : class, IResource
+ {
+ await _Authenticate();
+ if (typeof(T) == typeof(Show))
+ return (await _SearchShow(query) as ICollection)!;
throw new NotImplementedException();
}
+
+ [ItemNotNull]
+ private async Task> _SearchShow(string query)
+ {
+ TvDbResponse shows = await _client.Search.SearchSeriesByNameAsync(query);
+ return shows.Data.Select(x => x.ToShow(Provider)).ToArray();
+ }
+
+ ///
+ public async Task> GetPeople(Show show)
+ {
+ if (!int.TryParse(show?.GetID(Provider.Name), out int id))
+ return null;
+ await _Authenticate();
+ TvDbResponse 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 GetCollectionFromName(string name)
- // {
- // return Task.FromResult(null);
- // }
- //
- // public async Task> SearchShows(string showName, bool isMovie)
- // {
- // await Authentificate();
- //
- // if (isMovie)
- // return null; //There is no movie search API for now on TheTVDB.
- // TvDbResponse shows = await _client.Search.SearchSeriesAsync(showName, SearchParameter.Name);
- // return shows.Data.Select(x => x.ToShow(Provider)).ToArray();
- // }
- //
- // public async Task GetShowByID(Show show)
- // {
- // if (!int.TryParse(show?.GetID(Provider.Name), out int id))
- // return await Task.FromResult(null);
- // await Authentificate();
- // TvDbResponse serie = await _client.Series.GetAsync(id);
- // return serie.Data.ToShow(Provider);
- // }
- //
- // public async Task> GetPeople(Show show)
- // {
- // if (!int.TryParse(show?.GetID(Provider.Name), out int id))
- // return null;
- // await Authentificate();
- // TvDbResponse people = await _client.Series.GetActorsAsync(id);
- // return people.Data.Select(x => x.ToPeopleRole(Provider)).ToArray();
- // }
- //
- // public Task GetSeason(Show show, int seasonNumber)
- // {
- // return Task.FromResult(null);
- // }
- //
- // public async Task GetEpisode(Show show, int seasonNumber, int episodeNumber, int absoluteNumber)
- // {
- // if (!int.TryParse(show?.GetID(Provider.Name), out int id))
- // return null;
- // await Authentificate();
- // TvDbResponse 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}")
- // });
- // }
- // }
}
\ No newline at end of file