|
|
|
@ -8,8 +8,10 @@ using Jellyfin.Extensions;
|
|
|
|
|
using MediaBrowser.Controller.Entities.Audio;
|
|
|
|
|
using MediaBrowser.Controller.Providers;
|
|
|
|
|
using MediaBrowser.Model.Entities;
|
|
|
|
|
using MediaBrowser.Model.Plugins;
|
|
|
|
|
using MediaBrowser.Model.Providers;
|
|
|
|
|
using MediaBrowser.Providers.Music;
|
|
|
|
|
using MediaBrowser.Providers.Plugins.MusicBrainz.Configuration;
|
|
|
|
|
using MetaBrainz.MusicBrainz;
|
|
|
|
|
using MetaBrainz.MusicBrainz.Interfaces.Entities;
|
|
|
|
|
using MetaBrainz.MusicBrainz.Interfaces.Searches;
|
|
|
|
@ -23,8 +25,7 @@ namespace MediaBrowser.Providers.Plugins.MusicBrainz;
|
|
|
|
|
public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, AlbumInfo>, IHasOrder, IDisposable
|
|
|
|
|
{
|
|
|
|
|
private readonly ILogger<MusicBrainzAlbumProvider> _logger;
|
|
|
|
|
private readonly Query _musicBrainzQuery;
|
|
|
|
|
private readonly string _musicBrainzDefaultUri = "https://musicbrainz.org";
|
|
|
|
|
private Query _musicBrainzQuery;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="MusicBrainzAlbumProvider"/> class.
|
|
|
|
@ -33,29 +34,9 @@ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, Albu
|
|
|
|
|
public MusicBrainzAlbumProvider(ILogger<MusicBrainzAlbumProvider> logger)
|
|
|
|
|
{
|
|
|
|
|
_logger = logger;
|
|
|
|
|
|
|
|
|
|
MusicBrainz.Plugin.Instance!.ConfigurationChanged += (_, _) =>
|
|
|
|
|
{
|
|
|
|
|
if (Uri.TryCreate(MusicBrainz.Plugin.Instance.Configuration.Server, UriKind.Absolute, out var server))
|
|
|
|
|
{
|
|
|
|
|
Query.DefaultServer = server.Host;
|
|
|
|
|
Query.DefaultPort = server.Port;
|
|
|
|
|
Query.DefaultUrlScheme = server.Scheme;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Fallback to official server
|
|
|
|
|
_logger.LogWarning("Invalid MusicBrainz server specified, falling back to official server");
|
|
|
|
|
var defaultServer = new Uri(_musicBrainzDefaultUri);
|
|
|
|
|
Query.DefaultServer = defaultServer.Host;
|
|
|
|
|
Query.DefaultPort = defaultServer.Port;
|
|
|
|
|
Query.DefaultUrlScheme = defaultServer.Scheme;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Query.DelayBetweenRequests = MusicBrainz.Plugin.Instance.Configuration.RateLimit;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
_musicBrainzQuery = new Query();
|
|
|
|
|
ReloadConfig(null, MusicBrainz.Plugin.Instance!.Configuration);
|
|
|
|
|
MusicBrainz.Plugin.Instance!.ConfigurationChanged += ReloadConfig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
@ -64,6 +45,29 @@ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, Albu
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
public int Order => 0;
|
|
|
|
|
|
|
|
|
|
private void ReloadConfig(object? sender, BasePluginConfiguration e)
|
|
|
|
|
{
|
|
|
|
|
var configuration = (PluginConfiguration)e;
|
|
|
|
|
if (Uri.TryCreate(configuration.Server, UriKind.Absolute, out var server))
|
|
|
|
|
{
|
|
|
|
|
Query.DefaultServer = server.DnsSafeHost;
|
|
|
|
|
Query.DefaultPort = server.Port;
|
|
|
|
|
Query.DefaultUrlScheme = server.Scheme;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Fallback to official server
|
|
|
|
|
_logger.LogWarning("Invalid MusicBrainz server specified, falling back to official server");
|
|
|
|
|
var defaultServer = new Uri(configuration.Server);
|
|
|
|
|
Query.DefaultServer = defaultServer.Host;
|
|
|
|
|
Query.DefaultPort = defaultServer.Port;
|
|
|
|
|
Query.DefaultUrlScheme = defaultServer.Scheme;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Query.DelayBetweenRequests = configuration.RateLimit;
|
|
|
|
|
_musicBrainzQuery = new Query();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
@ -72,13 +76,13 @@ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, Albu
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(releaseId))
|
|
|
|
|
{
|
|
|
|
|
var releaseResult = await _musicBrainzQuery.LookupReleaseAsync(new Guid(releaseId), Include.ReleaseGroups, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
var releaseResult = await _musicBrainzQuery.LookupReleaseAsync(new Guid(releaseId), Include.Artists | Include.ReleaseGroups, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
return GetReleaseResult(releaseResult).SingleItemAsEnumerable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(releaseGroupId))
|
|
|
|
|
{
|
|
|
|
|
var releaseGroupResult = await _musicBrainzQuery.LookupReleaseGroupAsync(new Guid(releaseGroupId), Include.None, null, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
var releaseGroupResult = await _musicBrainzQuery.LookupReleaseGroupAsync(new Guid(releaseGroupId), Include.Releases, null, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
return GetReleaseGroupResult(releaseGroupResult.Releases);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -133,7 +137,9 @@ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, Albu
|
|
|
|
|
|
|
|
|
|
foreach (var result in releaseSearchResults)
|
|
|
|
|
{
|
|
|
|
|
yield return GetReleaseResult(result);
|
|
|
|
|
// Fetch full release info, otherwise artists are missing
|
|
|
|
|
var fullResult = _musicBrainzQuery.LookupRelease(result.Id, Include.Artists | Include.ReleaseGroups);
|
|
|
|
|
yield return GetReleaseResult(fullResult);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -143,21 +149,33 @@ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, Albu
|
|
|
|
|
{
|
|
|
|
|
Name = releaseSearchResult.Title,
|
|
|
|
|
ProductionYear = releaseSearchResult.Date?.Year,
|
|
|
|
|
PremiereDate = releaseSearchResult.Date?.NearestDate
|
|
|
|
|
PremiereDate = releaseSearchResult.Date?.NearestDate,
|
|
|
|
|
SearchProviderName = Name
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (releaseSearchResult.ArtistCredit?.Count > 0)
|
|
|
|
|
// Add artists and use first as album artist
|
|
|
|
|
var artists = releaseSearchResult.ArtistCredit;
|
|
|
|
|
if (artists is not null && artists.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
searchResult.AlbumArtist = new RemoteSearchResult
|
|
|
|
|
{
|
|
|
|
|
SearchProviderName = Name,
|
|
|
|
|
Name = releaseSearchResult.ArtistCredit[0].Name
|
|
|
|
|
};
|
|
|
|
|
var artistResults = new List<RemoteSearchResult>();
|
|
|
|
|
|
|
|
|
|
if (releaseSearchResult.ArtistCredit[0].Artist?.Id is not null)
|
|
|
|
|
foreach (var artist in artists)
|
|
|
|
|
{
|
|
|
|
|
searchResult.AlbumArtist.SetProviderId(MetadataProvider.MusicBrainzArtist, releaseSearchResult.ArtistCredit[0].Artist!.Id.ToString());
|
|
|
|
|
var artistResult = new RemoteSearchResult
|
|
|
|
|
{
|
|
|
|
|
Name = artist.Name
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (artist.Artist?.Id is not null)
|
|
|
|
|
{
|
|
|
|
|
artistResult.SetProviderId(MetadataProvider.MusicBrainzArtist, artist.Artist!.Id.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
artistResults.Add(artistResult);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
searchResult.AlbumArtist = artistResults[0];
|
|
|
|
|
searchResult.Artists = artistResults.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
searchResult.SetProviderId(MetadataProvider.MusicBrainzAlbum, releaseSearchResult.Id.ToString());
|
|
|
|
|