Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Movie support #164

Merged
merged 9 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Jellyfin.Plugin.Tvdb/Providers/ExternalId/TvdbMovieExternalId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;

namespace Jellyfin.Plugin.Tvdb.Providers.ExternalId
{
/// <inheritdoc />
public class TvdbMovieExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => TvdbPlugin.ProviderId;

/// <inheritdoc />
public string Key => TvdbPlugin.ProviderName;

/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Movie;

/// <inheritdoc />
public string? UrlFormatString => null;

/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Movie;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;

namespace Jellyfin.Plugin.Tvdb.Providers.ExternalId
{
/// <inheritdoc />
public class TvdbMovieSlugExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => TvdbPlugin.ProviderId;

/// <inheritdoc />
public string Key => TvdbPlugin.SlugProviderId;

/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Movie;

/// <inheritdoc />
public string? UrlFormatString => TvdbUtils.TvdbBaseUrl + "movies/{0}";

/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Movie;
}
}
115 changes: 115 additions & 0 deletions Jellyfin.Plugin.Tvdb/Providers/TvdbMovieImageProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using Microsoft.Extensions.Logging;
using Tvdb.Sdk;

namespace Jellyfin.Plugin.Tvdb.Providers
{
/// <summary>
/// Tvdb movie image provider.
/// </summary>
public class TvdbMovieImageProvider : IRemoteImageProvider
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<TvdbMovieImageProvider> _logger;
private readonly TvdbClientManager _tvdbClientManager;

/// <summary>
/// Initializes a new instance of the <see cref="TvdbMovieImageProvider"/> class.
/// </summary>
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{TvdbMovieImageProvider}"/> interface.</param>
/// <param name="tvdbClientManager">Instance of <see cref="TvdbClientManager"/>.</param>
public TvdbMovieImageProvider(
IHttpClientFactory httpClientFactory,
ILogger<TvdbMovieImageProvider> logger,
TvdbClientManager tvdbClientManager)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
_tvdbClientManager = tvdbClientManager;
}

/// <inheritdoc />
public string Name => TvdbPlugin.ProviderName;

/// <inheritdoc />
public bool Supports(BaseItem item)
{
return item is Movie;
}

/// <inheritdoc />
public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
{
yield return ImageType.Primary;
yield return ImageType.Banner;
yield return ImageType.Backdrop;
yield return ImageType.Logo;
yield return ImageType.Art;
}

/// <inheritdoc />
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
{
if (!item.IsSupported())
{
return Enumerable.Empty<RemoteImageInfo>();
}

var languages = await _tvdbClientManager.GetLanguagesAsync(cancellationToken)
.ConfigureAwait(false);
var languageLookup = languages
.ToDictionary(l => l.Id, StringComparer.OrdinalIgnoreCase);

var artworkTypes = await _tvdbClientManager.GetArtworkTypeAsync(cancellationToken)
.ConfigureAwait(false);
var movieArtworkTypeLookup = artworkTypes
.Where(t => string.Equals(t.RecordType, "movie", StringComparison.OrdinalIgnoreCase))
.Where(t => t.Id.HasValue)
.ToDictionary(t => t.Id!.Value);

var movieTvdbId = item.GetTvdbId();
var movieArtworks = await GetMovieArtworks(movieTvdbId, cancellationToken)
.ConfigureAwait(false);

var remoteImages = new List<RemoteImageInfo>();
foreach (var artwork in movieArtworks)
{
var artworkType = artwork.Type is null ? null : movieArtworkTypeLookup.GetValueOrDefault(artwork.Type!.Value);
var imageType = artworkType.GetImageType();
var artworkLanguage = artwork.Language is null ? null : languageLookup.GetValueOrDefault(artwork.Language);

// only add if valid RemoteImageInfo
remoteImages.AddIfNotNull(artwork.CreateImageInfo(Name, imageType, artworkLanguage));
}

return remoteImages.OrderByLanguageDescending(item.GetPreferredMetadataLanguage());
}

private async Task<IReadOnlyList<ArtworkBaseRecord>> GetMovieArtworks(int movieTvdbId, CancellationToken cancellationToken)
{
var movieInfo = await _tvdbClientManager.GetMovieExtendedByIdAsync(movieTvdbId, cancellationToken)
.ConfigureAwait(false);
return movieInfo?.Artworks ?? Array.Empty<ArtworkBaseRecord>();
}

/// <inheritdoc />
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(new Uri(url), cancellationToken);
}
}
}
Loading