Skip to content

Commit

Permalink
Add album image provider
Browse files Browse the repository at this point in the history
  • Loading branch information
heyhippari committed Mar 19, 2021
1 parent 8090317 commit 7f5ed3e
Show file tree
Hide file tree
Showing 9 changed files with 311 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Plugin.Template", "Jellyfin.Plugin.Template\Jellyfin.Plugin.Template.csproj", "{D921B930-CF91-406F-ACBC-08914DCD0D34}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Plugin.ITunes", "Jellyfin.Plugin.ITunes\Jellyfin.Plugin.ITunes.csproj", "{D921B930-CF91-406F-ACBC-08914DCD0D34}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using MediaBrowser.Model.Plugins;

namespace Jellyfin.Plugin.Template.Configuration
namespace Jellyfin.Plugin.ITunes.Configuration
{
public enum SomeOptions
{
Expand Down
79 changes: 79 additions & 0 deletions Jellyfin.Plugin.ITunes/Dtos/AlbumResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System.Text.Json.Serialization;

namespace Jellyfin.Plugin.ITunes.Dtos
{
public partial class ITunesAlbumDto
{
[JsonPropertyName("resultCount")]
public long ResultCount { get; set; }

[JsonPropertyName("results")]
public Result[] Results { get; set; }
}

public partial class Result
{
[JsonPropertyName("wrapperType")]
public string WrapperType { get; set; }

[JsonPropertyName("collectionType")]
public string CollectionType { get; set; }

[JsonPropertyName("artistId")]
public long ArtistId { get; set; }

[JsonPropertyName("collectionId")]
public long CollectionId { get; set; }

[JsonPropertyName("artistName")]
public string ArtistName { get; set; }

[JsonPropertyName("collectionName")]
public string CollectionName { get; set; }

[JsonPropertyName("collectionCensoredName")]
public string CollectionCensoredName { get; set; }

[JsonPropertyName("artistViewUrl")]
public string ArtistViewUrl { get; set; }

[JsonPropertyName("collectionViewUrl")]
public string CollectionViewUrl { get; set; }

[JsonPropertyName("artworkUrl60")]
public string ArtworkUrl60 { get; set; }

[JsonPropertyName("artworkUrl100")]
public string ArtworkUrl100 { get; set; }

[JsonPropertyName("collectionPrice")]
public double CollectionPrice { get; set; }

[JsonPropertyName("collectionExplicitness")]
public string CollectionExplicitness { get; set; }

[JsonPropertyName("trackCount")]
public long TrackCount { get; set; }

[JsonPropertyName("copyright")]
public string Copyright { get; set; }

[JsonPropertyName("country")]
public string Country { get; set; }

[JsonPropertyName("currency")]
public string Currency { get; set; }

[JsonPropertyName("releaseDate")]
public string ReleaseDate { get; set; }

[JsonPropertyName("primaryGenreName")]
public string PrimaryGenreName { get; set; }

[JsonPropertyName("contentAdvisoryRating")]
public string ContentAdvisoryRating { get; set; }

[JsonPropertyName("amgArtistId")]
public long? AmgArtistId { get; set; }
}
}
32 changes: 32 additions & 0 deletions Jellyfin.Plugin.ITunes/Jellyfin.Plugin.ITunes.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>Jellyfin.Plugin.ITunes</RootNamespace>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
</PropertyGroup>

<ItemGroup>
<None Remove="Configuration\configPage.html" />
<EmbeddedResource Include="Configuration\configPage.html" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Jellyfin.Controller" Version="10.*-*" />
<PackageReference Include="Jellyfin.Model" Version="10.*-*" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>

<PropertyGroup>
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
using System;
using System.Collections.Generic;
using Jellyfin.Plugin.Template.Configuration;
using Jellyfin.Plugin.ITunes.Configuration;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Plugins;
using MediaBrowser.Model.Serialization;

namespace Jellyfin.Plugin.Template
namespace Jellyfin.Plugin.ITunes
{
public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
{
public override string Name => "Template";
public override string Name => "iTunes";

public override Guid Id => Guid.Parse("eb5d7894-8eef-4b36-aa6f-5d124e828ce1");
public override Guid Id => Guid.Parse("a9f62a44-fea5-46c3-ac26-55abba29c7c8");

public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer) : base(applicationPaths, xmlSerializer)
{
Expand Down
126 changes: 126 additions & 0 deletions Jellyfin.Plugin.ITunes/Providers/ItunesAlbumProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using Microsoft.Extensions.Logging;
using Jellyfin.Plugin.ITunes.Dtos;

namespace Jellyfin.Plugin.ITunes.Providers
{
public class ITunesAlbumProvider : IRemoteImageProvider, IHasOrder
{
private readonly IHttpClientFactory _httpClientFactory;

/// <summary>
/// Initializes a new instance of the <see cref="ITunesAlbumProvider"/> class.
/// </summary>
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{CoverArtArchiveImageProvider}"/> interface.</param>
public ITunesAlbumProvider(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}

/// <inheritdoc />
public string Name => "iTunes";

/// <inheritdoc />
public int Order => 1; // After embedded provider

/// <inheritdoc />
public bool Supports(BaseItem item)
=> item is MusicAlbum;

/// <inheritdoc />
public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
{
return new List<ImageType>
{
ImageType.Primary
};
}

/// <inheritdoc />
public async Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
return await httpClient.GetAsync(new Uri(url), cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
{
var album = (MusicAlbum)item;
var list = new List<RemoteImageInfo>();

if (!string.IsNullOrEmpty(album.Name))
{
var searchQuery = album.Name;

if (album.AlbumArtists.Count > 0) {
string[] terms = {
album.AlbumArtists[0],
album.Name
};
searchQuery = String.Join(' ', terms);
}

var encodedName = Uri.EscapeUriString(searchQuery);

list.AddRange(await GetImagesInternal($"https://itunes.apple.com/search?term={encodedName}&media=music&entity=album", cancellationToken)
.ConfigureAwait(false));
}

return list;
}

private async Task<IEnumerable<RemoteImageInfo>> GetImagesInternal(string url, CancellationToken cancellationToken)
{
List<RemoteImageInfo> list = new List<RemoteImageInfo>();

var iTunesAlbumDto = await _httpClientFactory
.CreateClient(NamedClient.Default)
.GetFromJsonAsync<ITunesAlbumDto>(new Uri(url))
.ConfigureAwait(false);;

if (iTunesAlbumDto != null)
{
foreach (Result result in iTunesAlbumDto.Results)
{
// The max artwork size is 3000x3000. Some might return less, but we can't predict that.
var image1400 = result.ArtworkUrl100.Replace("100x100bb","3000x3000bb");

list.Add(
new RemoteImageInfo
{
ProviderName = Name,
Url = image1400,
Type = ImageType.Primary,
ThumbnailUrl = result.ArtworkUrl100,
RatingType = RatingType.Score,
}
);
}
}
else
{
return Array.Empty<RemoteImageInfo>();
}

return list;
}
}
}
20 changes: 0 additions & 20 deletions Jellyfin.Plugin.Template/Jellyfin.Plugin.Template.csproj

This file was deleted.

68 changes: 68 additions & 0 deletions jellyfin.ruleset
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Rules for Jellyfin.Server" Description="Code analysis rules for Jellyfin.Server.csproj" ToolsVersion="14.0">
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<!-- disable warning SA1202: 'public' members must come before 'private' members -->
<Rule Id="SA1202" Action="Info" />
<!-- disable warning SA1204: Static members must appear before non-static members -->
<Rule Id="SA1204" Action="Info" />
<!-- disable warning SA1404: Code analysis suppression should have justification -->
<Rule Id="SA1404" Action="Info" />

<!-- disable warning SA1009: Closing parenthesis should be followed by a space. -->
<Rule Id="SA1009" Action="None" />
<!-- disable warning SA1101: Prefix local calls with 'this.' -->
<Rule Id="SA1101" Action="None" />
<!-- disable warning SA1108: Block statements should not contain embedded comments -->
<Rule Id="SA1108" Action="None" />
<!-- disable warning SA1128:: Put constructor initializers on their own line -->
<Rule Id="SA1128" Action="None" />
<!-- disable warning SA1130: Use lambda syntax -->
<Rule Id="SA1130" Action="None" />
<!-- disable warning SA1200: 'using' directive must appear within a namespace declaration -->
<Rule Id="SA1200" Action="None" />
<!-- disable warning SA1309: Fields must not begin with an underscore -->
<Rule Id="SA1309" Action="None" />
<!-- disable warning SA1413: Use trailing comma in multi-line initializers -->
<Rule Id="SA1413" Action="None" />
<!-- disable warning SA1512: Single-line comments must not be followed by blank line -->
<Rule Id="SA1512" Action="None" />
<!-- disable warning SA1515: Single-line comment should be preceded by blank line -->
<Rule Id="SA1515" Action="None" />
<!-- disable warning SA1600: Elements should be documented -->
<Rule Id="SA1600" Action="None" />
<!-- disable warning SA1633: The file header is missing or not located at the top of the file -->
<Rule Id="SA1633" Action="None" />
</Rules>

<Rules AnalyzerId="Microsoft.CodeAnalysis.FxCopAnalyzers" RuleNamespace="Microsoft.Design">
<!-- disable warning CA1031: Do not catch general exception types -->
<Rule Id="CA1031" Action="Info" />
<!-- disable warning CA1032: Implement standard exception constructors -->
<Rule Id="CA1032" Action="Info" />
<!-- disable warning CA1062: Validate arguments of public methods -->
<Rule Id="CA1062" Action="Info" />
<!-- disable warning CA1716: Identifiers should not match keywords -->
<Rule Id="CA1716" Action="Info" />
<!-- disable warning CA1720: Identifiers should not contain type names -->
<Rule Id="CA1720" Action="Info" />
<!-- disable warning CA1812: internal class that is apparently never instantiated.
If so, remove the code from the assembly.
If this class is intended to contain only static members, make it static -->
<Rule Id="CA1812" Action="Info" />
<!-- disable warning CA1822: Member does not access instance data and can be marked as static -->
<Rule Id="CA1822" Action="Info" />
<!-- disable warning CA2000: Dispose objects before losing scope -->
<Rule Id="CA2000" Action="Info" />

<!-- disable warning CA1054: Change the type of parameter url from string to System.Uri -->
<Rule Id="CA1054" Action="None" />
<!-- disable warning CA1055: URI return values should not be strings -->
<Rule Id="CA1055" Action="None" />
<!-- disable warning CA1056: URI properties should not be strings -->
<Rule Id="CA1056" Action="None" />
<!-- disable warning CA1303: Do not pass literals as localized parameters -->
<Rule Id="CA1303" Action="None" />
<!-- disable warning CA1308: Normalize strings to uppercase -->
<Rule Id="CA1308" Action="None" />
</Rules>
</RuleSet>

0 comments on commit 7f5ed3e

Please sign in to comment.