mirror of
https://github.com/jellyfin/jellyfin-plugin-kitsu.git
synced 2024-11-27 00:00:35 +00:00
Merge pull request #21 from pikami/feature/20-Episode-metadata-does-not-get-filled
This commit is contained in:
commit
7a097bdc79
@ -1,105 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.ApiClient
|
||||
{
|
||||
public class ApiListResponse
|
||||
{
|
||||
public List<Series> Data { get; set; }
|
||||
public ResponseMeta Meta { get; set; }
|
||||
}
|
||||
|
||||
public class ApiResponse
|
||||
{
|
||||
public Series Data { get; set; }
|
||||
public List<Included> Included { get; set; }
|
||||
}
|
||||
|
||||
public class Series
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public Attributes Attributes { get; set; }
|
||||
}
|
||||
|
||||
public class Attributes
|
||||
{
|
||||
public string Synopsis { get; set; }
|
||||
public Titles Titles { get; set; }
|
||||
public string AverageRating { get; set; }
|
||||
public DateTimeOffset? StartDate { get; set; }
|
||||
public PosterImage PosterImage { get; set; }
|
||||
|
||||
// Episode specific
|
||||
public int? Number { get; set; }
|
||||
public int? SeasonNumber { get; set; }
|
||||
public DateTime? AirDate { get; set; }
|
||||
public int? Length { get; set; }
|
||||
}
|
||||
|
||||
public class PosterImage
|
||||
{
|
||||
public Uri Medium { get; set; }
|
||||
public Uri Original { get; set; }
|
||||
}
|
||||
|
||||
public class Titles
|
||||
{
|
||||
[JsonPropertyName("en")] public string En { get; set; }
|
||||
|
||||
[JsonPropertyName("en_jp")] public string EnJp { get; set; }
|
||||
|
||||
[JsonPropertyName("ja_jp")] public string JaJp { get; set; }
|
||||
|
||||
[JsonPropertyName("en_us")] public string EnUs { get; set; }
|
||||
|
||||
public string GetTitle =>
|
||||
!string.IsNullOrWhiteSpace(En) ? En :
|
||||
!string.IsNullOrWhiteSpace(EnUs) ? EnUs :
|
||||
!string.IsNullOrWhiteSpace(EnJp) ? EnJp :
|
||||
JaJp;
|
||||
|
||||
public bool Equal(string title)
|
||||
{
|
||||
return
|
||||
(En?.Equals(title) ?? false) ||
|
||||
(EnUs?.Equals(title) ?? false) ||
|
||||
(EnJp?.Equals(title) ?? false) ||
|
||||
(JaJp?.Equals(title) ?? false);
|
||||
}
|
||||
}
|
||||
|
||||
public class ResponseMeta
|
||||
{
|
||||
public long? Count { get; set; }
|
||||
}
|
||||
|
||||
public class Included
|
||||
{
|
||||
public IncludedAttributes Attributes { get; set; }
|
||||
}
|
||||
|
||||
public class IncludedAttributes
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public enum ShowTypeEnum
|
||||
{
|
||||
Movie,
|
||||
Ova,
|
||||
Ona,
|
||||
Tv,
|
||||
Music,
|
||||
Special
|
||||
}
|
||||
|
||||
public enum Status
|
||||
{
|
||||
Current,
|
||||
Finished,
|
||||
Tba,
|
||||
Unreleased,
|
||||
Upcoming
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models;
|
||||
using MediaBrowser.Common.Net;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -16,7 +17,6 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.ApiClient
|
||||
|
||||
static KitsuIoApi()
|
||||
{
|
||||
|
||||
_serializerOptions = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
@ -25,7 +25,7 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.ApiClient
|
||||
_serializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
|
||||
}
|
||||
|
||||
public static async Task<ApiListResponse> Search_Series(Dictionary<string, string> filters, IHttpClientFactory httpClientFactory)
|
||||
public static async Task<ApiResponse<List<KitsuSeries>>> Search_Series(Dictionary<string, string> filters, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
var filterString = string.Join("&",filters.Select(x => $"filter[{x.Key}]={x.Value}"));
|
||||
var pageString = "page[limit]=10";
|
||||
@ -34,21 +34,21 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.ApiClient
|
||||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.api+json"));
|
||||
|
||||
var responseStream = await httpClient.GetStreamAsync($"{_apiBaseUrl}/anime?{filterString}&{pageString}");
|
||||
return await JsonSerializer.DeserializeAsync<ApiListResponse>(responseStream, _serializerOptions);
|
||||
return await JsonSerializer.DeserializeAsync<ApiResponse<List<KitsuSeries>>>(responseStream, _serializerOptions);
|
||||
}
|
||||
|
||||
public static async Task<ApiResponse> Get_Series(string seriesId, IHttpClientFactory httpClientFactory)
|
||||
public static async Task<ApiResponse<KitsuSeries>> Get_Series(string seriesId, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
var httpClient = httpClientFactory.CreateClient(NamedClient.Default);
|
||||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.api+json"));
|
||||
|
||||
var responseStream = await httpClient.GetStreamAsync($"{_apiBaseUrl}/anime/{seriesId}?include=genres");
|
||||
return await JsonSerializer.DeserializeAsync<ApiResponse>(responseStream, _serializerOptions);
|
||||
return await JsonSerializer.DeserializeAsync<ApiResponse<KitsuSeries>>(responseStream, _serializerOptions);
|
||||
}
|
||||
|
||||
public static async Task<ApiListResponse> Get_Episodes(string seriesId, IHttpClientFactory httpClientFactory)
|
||||
public static async Task<ApiResponse<List<KitsuEpisode>>> Get_Episodes(string seriesId, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
var result = new ApiListResponse();
|
||||
var result = new ApiResponse<List<KitsuEpisode>>(new List<KitsuEpisode>());
|
||||
long episodeCount = 10;
|
||||
var step = 10;
|
||||
|
||||
@ -59,7 +59,7 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.ApiClient
|
||||
{
|
||||
var queryString = $"?filter[mediaId]={seriesId}&page[limit]={step}&page[offset]={offset}";
|
||||
var responseStream = await httpClient.GetStreamAsync($"{_apiBaseUrl}/episodes{queryString}");
|
||||
var response = await JsonSerializer.DeserializeAsync<ApiListResponse>(responseStream, _serializerOptions);
|
||||
var response = await JsonSerializer.DeserializeAsync<ApiResponse<List<KitsuEpisode>>>(responseStream, _serializerOptions);
|
||||
|
||||
episodeCount = response.Meta.Count.Value;
|
||||
result.Data.AddRange(response.Data);
|
||||
@ -68,7 +68,7 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.ApiClient
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Task<ApiResponse> Get_Episode(string episodeId, IHttpClientFactory httpClientFactory)
|
||||
public static async Task<ApiResponse<KitsuEpisode>> Get_Episode(string episodeId, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
var filterString = $"/{episodeId}";
|
||||
|
||||
@ -76,7 +76,25 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.ApiClient
|
||||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.api+json"));
|
||||
|
||||
var responseStream = await httpClient.GetStreamAsync($"{_apiBaseUrl}/episodes{filterString}");
|
||||
return await JsonSerializer.DeserializeAsync<ApiResponse>(responseStream, _serializerOptions);
|
||||
return await JsonSerializer.DeserializeAsync<ApiResponse<KitsuEpisode>>(responseStream, _serializerOptions);
|
||||
}
|
||||
|
||||
public static async Task<ApiResponse<KitsuEpisode>> Get_Episode(string seriesId, int episodeNumber, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
var queryString = $"?filter[mediaId]={seriesId}&filter[number]={episodeNumber}";
|
||||
|
||||
var httpClient = httpClientFactory.CreateClient(NamedClient.Default);
|
||||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.api+json"));
|
||||
|
||||
var responseStream = await httpClient.GetStreamAsync($"{_apiBaseUrl}/episodes{queryString}");
|
||||
var response = await JsonSerializer.DeserializeAsync<ApiResponse<List<KitsuEpisode>>>(responseStream, _serializerOptions);
|
||||
|
||||
return new ApiResponse<KitsuEpisode>
|
||||
{
|
||||
Data = response.Data.FirstOrDefault(),
|
||||
Included = response.Included,
|
||||
Meta = response.Meta
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class ApiResponse<T>
|
||||
{
|
||||
public T Data { get; set; }
|
||||
public List<Included> Included { get; set; }
|
||||
public ResponseMeta Meta { get; set; }
|
||||
|
||||
public ApiResponse() { }
|
||||
|
||||
public ApiResponse(T initialData)
|
||||
{
|
||||
Data = initialData;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class Included
|
||||
{
|
||||
public IncludedAttributes Attributes { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class IncludedAttributes
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class KitsuEpisode
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public KitsuEpisodeAttributes Attributes { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class KitsuEpisodeAttributes
|
||||
{
|
||||
public string Synopsis { get; set; }
|
||||
public KitsuTitles Titles { get; set; }
|
||||
public int? Number { get; set; }
|
||||
public int? SeasonNumber { get; set; }
|
||||
public DateTime? AirDate { get; set; }
|
||||
public int? Length { get; set; }
|
||||
public KitsuImage Thumbnail { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class KitsuImage
|
||||
{
|
||||
public Uri Medium { get; set; }
|
||||
public Uri Original { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class KitsuSeries
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public KitsuSeriesAttributes Attributes { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class KitsuSeriesAttributes
|
||||
{
|
||||
public string Synopsis { get; set; }
|
||||
public KitsuTitles Titles { get; set; }
|
||||
public string AverageRating { get; set; }
|
||||
public DateTimeOffset? StartDate { get; set; }
|
||||
public KitsuImage PosterImage { get; set; }
|
||||
public KitsuImage CoverImage { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class ResponseMeta
|
||||
{
|
||||
public long? Count { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models
|
||||
{
|
||||
public class KitsuTitles
|
||||
{
|
||||
[JsonPropertyName("en")] public string En { get; set; }
|
||||
|
||||
[JsonPropertyName("en_jp")] public string EnJp { get; set; }
|
||||
|
||||
[JsonPropertyName("ja_jp")] public string JaJp { get; set; }
|
||||
|
||||
[JsonPropertyName("en_us")] public string EnUs { get; set; }
|
||||
|
||||
public IEnumerable<string> GetTitlesOrderedByPriority() => new [] { En, EnUs, EnJp, JaJp }
|
||||
.Where(title => !string.IsNullOrWhiteSpace(title));
|
||||
|
||||
public string GetTitle =>
|
||||
GetTitlesOrderedByPriority().FirstOrDefault();
|
||||
|
||||
public bool Equal(string title) =>
|
||||
GetTitlesOrderedByPriority().Contains(title);
|
||||
}
|
||||
}
|
@ -47,13 +47,16 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.Metadata
|
||||
{
|
||||
var result = new MetadataResult<Episode>();
|
||||
|
||||
var id = info.ProviderIds.GetValueOrDefault("Kitsu");
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
if (!info.SeriesProviderIds.TryGetValue("Kitsu", out var seriesId) || !info.IndexNumber.HasValue)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var episodeInfo = await KitsuIoApi.Get_Episode(id, _httpClientFactory);
|
||||
var episodeInfo = await KitsuIoApi.Get_Episode(seriesId, info.IndexNumber.Value, _httpClientFactory);
|
||||
if (episodeInfo?.Data?.Attributes == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result.HasMetadata = true;
|
||||
result.Item = new Episode
|
||||
@ -61,6 +64,9 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.Metadata
|
||||
IndexNumber = info.IndexNumber,
|
||||
ParentIndexNumber = info.ParentIndexNumber,
|
||||
Name = episodeInfo.Data.Attributes.Titles.GetTitle,
|
||||
PremiereDate = episodeInfo.Data.Attributes.AirDate,
|
||||
Overview = episodeInfo.Data.Attributes.Synopsis,
|
||||
ProviderIds = new Dictionary<string, string>() { { "Kitsu", episodeInfo.Data.Id.ToString() } }
|
||||
};
|
||||
|
||||
if (episodeInfo.Data.Attributes.Length != null)
|
||||
|
@ -13,10 +13,12 @@ using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Providers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using Jellyfin.Plugin.Kitsu.Providers.KitsuIO.ApiClient.Models;
|
||||
|
||||
namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.Metadata
|
||||
{
|
||||
public class KitsuIoSeriesProvider : IRemoteMetadataProvider<MediaBrowser.Controller.Entities.TV.Series, SeriesInfo>, IHasOrder
|
||||
public class KitsuIoSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
|
||||
{
|
||||
private readonly ILogger<KitsuIoSeriesProvider> _log;
|
||||
private readonly IApplicationPaths _paths;
|
||||
@ -58,9 +60,9 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.Metadata
|
||||
return searchResults;
|
||||
}
|
||||
|
||||
public async Task<MetadataResult<MediaBrowser.Controller.Entities.TV.Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
|
||||
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = new MetadataResult<MediaBrowser.Controller.Entities.TV.Series>();
|
||||
var result = new MetadataResult<Series>();
|
||||
|
||||
var kitsuId = info.ProviderIds.GetValueOrDefault("Kitsu");
|
||||
if (string.IsNullOrWhiteSpace(kitsuId))
|
||||
@ -75,7 +77,7 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.Metadata
|
||||
{
|
||||
var seriesInfo = await KitsuIoApi.Get_Series(kitsuId, _httpClientFactory);
|
||||
result.HasMetadata = true;
|
||||
result.Item = new MediaBrowser.Controller.Entities.TV.Series
|
||||
result.Item = new Series
|
||||
{
|
||||
Overview = seriesInfo.Data.Attributes.Synopsis,
|
||||
// KitsuIO has a max rating of 100
|
||||
@ -116,7 +118,7 @@ namespace Jellyfin.Plugin.Anime.Providers.KitsuIO.Metadata
|
||||
File.WriteAllText(path, url);
|
||||
}
|
||||
|
||||
private RemoteSearchResult MapToRemoteSearchResult(Series series)
|
||||
private RemoteSearchResult MapToRemoteSearchResult(KitsuSeries series)
|
||||
{
|
||||
var parsedSeries = new RemoteSearchResult
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user