first commit
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Plugin.SRFPlay.Api;
|
||||
using Jellyfin.Plugin.SRFPlay.Services;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Providers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.SRFPlay.Providers;
|
||||
|
||||
/// <summary>
|
||||
/// Provides metadata for SRF Play series/shows.
|
||||
/// </summary>
|
||||
public class SRFSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>
|
||||
{
|
||||
private readonly ILogger<SRFSeriesProvider> _logger;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly MetadataCache _metadataCache;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SRFSeriesProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger instance.</param>
|
||||
/// <param name="loggerFactory">The logger factory.</param>
|
||||
/// <param name="httpClientFactory">The HTTP client factory.</param>
|
||||
/// <param name="metadataCache">The metadata cache.</param>
|
||||
public SRFSeriesProvider(
|
||||
ILogger<SRFSeriesProvider> logger,
|
||||
ILoggerFactory loggerFactory,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
MetadataCache metadataCache)
|
||||
{
|
||||
_logger = logger;
|
||||
_loggerFactory = loggerFactory;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_metadataCache = metadataCache;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "SRF Play";
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
var results = new List<RemoteSearchResult>();
|
||||
|
||||
try
|
||||
{
|
||||
// Check if we have a URN to search with
|
||||
if (searchInfo.ProviderIds.TryGetValue("SRF", out var urn) && !string.IsNullOrEmpty(urn))
|
||||
{
|
||||
_logger.LogDebug("Searching for series with URN: {Urn}", urn);
|
||||
|
||||
var config = Plugin.Instance?.Configuration;
|
||||
if (config == null)
|
||||
{
|
||||
return results;
|
||||
}
|
||||
|
||||
// Try cache first
|
||||
var mediaComposition = _metadataCache.GetMediaComposition(urn, config.CacheDurationMinutes);
|
||||
|
||||
// If not in cache, fetch from API
|
||||
if (mediaComposition == null)
|
||||
{
|
||||
using var apiClient = new SRFApiClient(_loggerFactory);
|
||||
mediaComposition = await apiClient.GetMediaCompositionByUrnAsync(urn, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (mediaComposition != null)
|
||||
{
|
||||
_metadataCache.SetMediaComposition(urn, mediaComposition);
|
||||
}
|
||||
}
|
||||
|
||||
if (mediaComposition?.Show != null)
|
||||
{
|
||||
var show = mediaComposition.Show;
|
||||
results.Add(new RemoteSearchResult
|
||||
{
|
||||
Name = show.Title,
|
||||
Overview = show.Description ?? show.Lead,
|
||||
ImageUrl = show.ImageUrl,
|
||||
SearchProviderName = Name,
|
||||
ProviderIds = new Dictionary<string, string>
|
||||
{
|
||||
{ "SRF", show.Urn ?? urn }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(searchInfo.Name))
|
||||
{
|
||||
_logger.LogDebug("Name-based search not yet implemented for: {Name}", searchInfo.Name);
|
||||
// TODO: Implement name-based search when SRF provides search API
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error searching for series: {Name}", searchInfo.Name);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = new MetadataResult<Series>();
|
||||
|
||||
try
|
||||
{
|
||||
// Check if we have a URN
|
||||
if (!info.ProviderIds.TryGetValue("SRF", out var urn) || string.IsNullOrEmpty(urn))
|
||||
{
|
||||
_logger.LogDebug("No SRF URN found for series: {Name}", info.Name);
|
||||
return result;
|
||||
}
|
||||
|
||||
_logger.LogDebug("Fetching metadata for series URN: {Urn}", urn);
|
||||
|
||||
var config = Plugin.Instance?.Configuration;
|
||||
if (config == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Try cache first
|
||||
var mediaComposition = _metadataCache.GetMediaComposition(urn, config.CacheDurationMinutes);
|
||||
|
||||
// If not in cache, fetch from API
|
||||
if (mediaComposition == null)
|
||||
{
|
||||
using var apiClient = new SRFApiClient(_loggerFactory);
|
||||
mediaComposition = await apiClient.GetMediaCompositionByUrnAsync(urn, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (mediaComposition != null)
|
||||
{
|
||||
_metadataCache.SetMediaComposition(urn, mediaComposition);
|
||||
}
|
||||
}
|
||||
|
||||
if (mediaComposition?.Show == null)
|
||||
{
|
||||
_logger.LogWarning("No show information found for URN: {Urn}", urn);
|
||||
return result;
|
||||
}
|
||||
|
||||
var show = mediaComposition.Show;
|
||||
|
||||
result.Item = new Series
|
||||
{
|
||||
Name = show.Title,
|
||||
Overview = show.Description ?? show.Lead,
|
||||
ProviderIds = new Dictionary<string, string>
|
||||
{
|
||||
{ "SRF", show.Urn ?? urn }
|
||||
}
|
||||
};
|
||||
|
||||
// Set additional metadata if available
|
||||
if (!string.IsNullOrEmpty(show.Vendor))
|
||||
{
|
||||
result.Item.Studios = new[] { show.Vendor };
|
||||
}
|
||||
|
||||
result.HasMetadata = true;
|
||||
_logger.LogDebug("Successfully fetched metadata for series: {Title}", show.Title);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching metadata for series: {Name}", info.Name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException("Image handling is done by SRFImageProvider");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user