Implement basic metadata and image providers for episodes

This commit is contained in:
DarkFighterLuke
2024-03-09 16:57:11 +01:00
parent bb8d31b122
commit ebf7725ca6
9 changed files with 506 additions and 0 deletions
@@ -0,0 +1,71 @@
using Newtonsoft.Json;
namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
{
/// <summary>
/// A class representing TubeArchivist API channel data.
/// </summary>
public class Channel
{
/// <summary>
/// Initializes a new instance of the <see cref="Channel"/> class.
/// </summary>
/// <param name="bannerUrl">URL of the channel banner image.</param>
/// <param name="description">Channel description.</param>
/// <param name="id">Channel YouTube id.</param>
/// <param name="name">Channel name.</param>
/// <param name="thumbUrl">URL of the channel thumb image.</param>
/// <param name="tvartUrl">URL of the channel tvart image.</param>
public Channel(
string bannerUrl,
string description,
string id,
string name,
string thumbUrl,
string tvartUrl)
{
this.BannerUrl = bannerUrl;
this.Description = description;
this.Id = id;
this.Name = name;
this.ThumbUrl = thumbUrl;
this.TvartUrl = tvartUrl;
}
/// <summary>
/// Gets or sets the URL of the channel banner image.
/// </summary>
[JsonProperty(PropertyName = "channel_banner_url")]
public string BannerUrl { get; set; }
/// <summary>
/// Gets or sets the channel description.
/// </summary>
[JsonProperty(PropertyName = "channel_description")]
public string Description { get; set; }
/// <summary>
/// Gets or sets the channel YouTube id.
/// </summary>
[JsonProperty(PropertyName = "channel_id")]
public string Id { get; set; }
/// <summary>
/// Gets or sets the channel name.
/// </summary>
[JsonProperty(PropertyName = "channel_name")]
public string Name { get; set; }
/// <summary>
/// Gets or sets the URL of the channel thumb image.
/// </summary>
[JsonProperty(PropertyName = "channel_thumb_url")]
public string ThumbUrl { get; set; }
/// <summary>
/// Gets or sets the URL of the channel tvart image.
/// </summary>
[JsonProperty(PropertyName = "channel_tvart_url")]
public string TvartUrl { get; set; }
}
}
@@ -0,0 +1,14 @@
namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
{
/// <summary>
/// Class representing the base common structure of TubeArchivist API responses.
/// </summary>
/// <typeparam name="T">The contained data type.</typeparam>
public class ResponseContainer<T>
{
/// <summary>
/// Gets or sets the contained data object.
/// </summary>
public T? Data { get; set; }
}
}
@@ -0,0 +1,124 @@
using System;
using System.Data;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
{
/// <summary>
/// Class to interact with TubeArchivist API.
/// </summary>
public class TubeArchivistApi
{
private HttpClient client;
private static TubeArchivistApi _taApiInstance = null!;
/// <summary>
/// Initializes a new instance of the <see cref="TubeArchivistApi"/> class.
/// </summary>
/// <param name="httpClient">HTTP client to make requests to TubeArchivist API.</param>
private TubeArchivistApi(HttpClient httpClient)
{
client = httpClient;
}
/// <summary>
/// Gets the instance of the <see cref="TubeArchivistApi"/> class.
/// </summary>
/// <returns>The TubeArchivistApi instance.</returns>
public static TubeArchivistApi GetInstance()
{
if (_taApiInstance == null)
{
if (Plugin.Instance != null)
{
_taApiInstance = new TubeArchivistApi(Plugin.Instance.HttpClient);
}
else
{
throw new DataException("Uninitialized plugin!");
}
}
return _taApiInstance;
}
/// <summary>
/// Retrieves the given channel information from TubeArchivist.
/// </summary>
/// <param name="channelId">YouTube channel id.</param>
/// <returns>A task.</returns>
public async Task<Channel?> GetChannel(string channelId)
{
ResponseContainer<Channel>? channel = null;
Console.WriteLine(Plugin.Instance?.Configuration.TubeArchivistUrl);
Console.WriteLine(Plugin.Instance?.Configuration.TubeArchivistApiKey);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", Plugin.Instance?.Configuration.TubeArchivistApiKey);
var channelsEndpoint = "/api/channel/";
var url = new Uri(Plugin.Instance?.Configuration.TubeArchivistUrl + channelsEndpoint + channelId);
var response = await client.GetAsync(url).ConfigureAwait(true);
Console.WriteLine(response.StatusCode);
while (response.StatusCode == HttpStatusCode.Moved)
{
Console.WriteLine("Received redirect to: " + response.Headers.Location);
response = await client.GetAsync(response.Headers.Location).ConfigureAwait(true);
}
Console.WriteLine(url + ": " + response.StatusCode);
if (response.IsSuccessStatusCode)
{
string rawData = await response.Content.ReadAsStringAsync().ConfigureAwait(true);
channel = JsonConvert.DeserializeObject<ResponseContainer<Channel>>(rawData);
Console.WriteLine("Channel null? " + channel == null);
Console.WriteLine("Channel: " + channel?.Data?.Name);
if (channel != null && channel.Data != null)
{
Console.WriteLine(JsonConvert.SerializeObject(channel));
}
}
return channel?.Data;
}
/// <summary>
/// Retrieves the given video information from TubeArchivist.
/// </summary>
/// <param name="videoId">YouTube video id.</param>
/// <returns>A task.</returns>
public async Task<Video?> GetVideo(string videoId)
{
ResponseContainer<Video>? video = null;
Console.WriteLine(Plugin.Instance?.Configuration.TubeArchivistUrl);
Console.WriteLine(Plugin.Instance?.Configuration.TubeArchivistApiKey);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", Plugin.Instance?.Configuration.TubeArchivistApiKey);
var videosEndpoint = "/api/video/";
var url = new Uri(Plugin.Instance?.Configuration.TubeArchivistUrl + videosEndpoint + videoId);
var response = await client.GetAsync(url).ConfigureAwait(true);
Console.WriteLine(response.StatusCode);
while (response.StatusCode == HttpStatusCode.Moved)
{
Console.WriteLine("Received redirect to: " + response.Headers.Location);
response = await client.GetAsync(response.Headers.Location).ConfigureAwait(true);
}
Console.WriteLine(url + ": " + response.StatusCode);
if (response.IsSuccessStatusCode)
{
string rawData = await response.Content.ReadAsStringAsync().ConfigureAwait(true);
video = JsonConvert.DeserializeObject<ResponseContainer<Video>>(rawData);
}
return video?.Data;
}
}
}
@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using Newtonsoft.Json;
namespace Jellyfin.Plugin.TubeArchivistMetadata.TubeArchivist
{
/// <summary>
/// A class representing TubeArchivist API video data.
/// </summary>
public class Video
{
/// <summary>
/// Initializes a new instance of the <see cref="Video"/> class.
/// </summary>
/// <param name="channel">Channel the video belongs to.</param>
/// <param name="title">Video title.</param>
/// <param name="description">Video description.</param>
/// <param name="published">Video published date.</param>
/// <param name="vidThumbUrl">Video thuumb image URL.</param>
/// <param name="youtubeId">Video YouTube id.</param>
public Video(
Channel channel,
string title,
string description,
DateTime published,
string vidThumbUrl,
string youtubeId)
{
this.Channel = channel;
this.Title = title;
this.Description = description;
this.Published = published;
this.VidThumbUrl = vidThumbUrl;
this.YoutubeId = youtubeId;
}
/// <summary>
/// Gets or sets the channel info.
/// </summary>
[JsonProperty(PropertyName = "channel")]
public Channel Channel { get; set; }
/// <summary>
/// Gets or sets video title.
/// </summary>
[JsonProperty(PropertyName = "title")]
public string Title { get; set; }
/// <summary>
/// Gets or sets video description.
/// </summary>
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
/// <summary>
/// Gets or sets video published date.
/// </summary>
[JsonProperty(PropertyName = "published")]
public DateTime Published { get; set; }
/// <summary>
/// Gets or sets video thumb image URL.
/// </summary>
[JsonProperty(PropertyName = "vid_thumb_url")]
public string VidThumbUrl { get; set; }
/// <summary>
/// Gets or sets video YouTube id.
/// </summary>
[JsonProperty(PropertyName = "youtube_id")]
public string YoutubeId { get; set; }
/// <summary>
/// Converts the TubeArchivist API video to a Jellyfin <see cref="RemoteSearchResult"/> object.
/// </summary>
/// <returns>The video equivalent Jellyfin <see cref="RemoteSearchResult"/> object.</returns>
public RemoteSearchResult ToSearchResult()
{
return new RemoteSearchResult
{
Name = Title,
SearchProviderName = Constants.ProviderName,
ProductionYear = Published.Year,
ImageUrl = VidThumbUrl,
ProviderIds = new Dictionary<string, string>() { { Constants.ProviderName, YoutubeId } }
};
}
/// <summary>
/// Converts the TubeArchivist API video to a Jellyfin <see cref="Episode"/> object.
/// </summary>
/// <returns>The video equivalent Jellyfin <see cref="Episode"/> object.</returns>
public Episode ToEpisode()
{
return new Episode
{
Name = Title,
SeasonName = Published.Year.ToString(CultureInfo.CurrentCulture),
SeriesName = Channel.Name,
ProviderIds = new Dictionary<string, string>()
{
{
Constants.ProviderName, YoutubeId
}
},
ImageInfos = new[]
{
new ItemImageInfo
{
Path = VidThumbUrl,
Type = ImageType.Primary
}
}
};
}
}
}