Fix MusicBrainz Metadata fetching

This commit is contained in:
Shadowghost
2026-07-23 23:07:58 +02:00
parent 04e4505402
commit b7b2700425
2 changed files with 158 additions and 46 deletions
@@ -155,7 +155,6 @@ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, Albu
/// <inheritdoc />
public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo info, CancellationToken cancellationToken)
{
// TODO: This sets essentially nothing. As-is, it's mostly useless. Make it actually pull metadata and use it.
var query = MusicBrainz.Plugin.Instance!.MusicBrainzQuery;
var releaseId = info.GetReleaseId();
var releaseGroupId = info.GetReleaseGroupId();
@@ -169,13 +168,8 @@ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, Albu
if (string.IsNullOrWhiteSpace(releaseId) && !string.IsNullOrWhiteSpace(releaseGroupId))
{
// TODO: Actually try to match the release. Simply taking the first result is stupid.
var releaseGroup = await query.LookupReleaseGroupAsync(new Guid(releaseGroupId), Include.None, null, cancellationToken).ConfigureAwait(false);
var release = releaseGroup.Releases?.Count > 0 ? releaseGroup.Releases[0] : null;
if (release is not null)
{
releaseId = release.Id.ToString();
result.HasMetadata = true;
}
var releaseGroupLookup = await query.LookupReleaseGroupAsync(new Guid(releaseGroupId), Include.None, null, cancellationToken).ConfigureAwait(false);
releaseId = releaseGroupLookup.Releases?.Count > 0 ? releaseGroupLookup.Releases[0].Id.ToString() : null;
}
// If there is no release ID, lookup a release with the info we have
@@ -205,43 +199,117 @@ public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, Albu
{
releaseGroupId = releaseResult.ReleaseGroup.Id.ToString();
}
result.HasMetadata = true;
result.Item.ProductionYear = releaseResult.Date?.Year;
result.Item.Overview = releaseResult.Annotation;
}
}
// If we have a release ID but not a release group ID, lookup the release group
if (!string.IsNullOrWhiteSpace(releaseId) && string.IsNullOrWhiteSpace(releaseGroupId))
if (string.IsNullOrWhiteSpace(releaseId) && string.IsNullOrWhiteSpace(releaseGroupId))
{
var release = await query.LookupReleaseAsync(new Guid(releaseId), Include.ReleaseGroups, cancellationToken).ConfigureAwait(false);
releaseGroupId = release.ReleaseGroup?.Id.ToString();
result.HasMetadata = true;
return result;
}
// If we have a release ID and a release group ID
if (!string.IsNullOrWhiteSpace(releaseId) || !string.IsNullOrWhiteSpace(releaseGroupId))
// Fetch the full release (and its release group) so we can populate everything MusicBrainz returns.
IRelease? release = null;
if (!string.IsNullOrWhiteSpace(releaseId))
{
result.HasMetadata = true;
}
release = await query.LookupReleaseAsync(
new Guid(releaseId),
Include.Artists | Include.ReleaseGroups | Include.Labels | Include.Genres | Include.Tags | Include.Annotation,
cancellationToken).ConfigureAwait(false);
if (result.HasMetadata)
{
if (!string.IsNullOrEmpty(releaseId))
if (string.IsNullOrWhiteSpace(releaseGroupId) && release?.ReleaseGroup?.Id is not null)
{
result.Item.SetProviderId(MetadataProvider.MusicBrainzAlbum, releaseId);
}
if (!string.IsNullOrEmpty(releaseGroupId))
{
result.Item.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, releaseGroupId);
releaseGroupId = release.ReleaseGroup.Id.ToString();
}
}
IReleaseGroup? releaseGroup = null;
if (!string.IsNullOrWhiteSpace(releaseGroupId))
{
releaseGroup = await query.LookupReleaseGroupAsync(
new Guid(releaseGroupId),
Include.Artists | Include.Genres | Include.Tags | Include.Annotation,
null,
cancellationToken).ConfigureAwait(false);
}
result.HasMetadata = true;
if (!string.IsNullOrEmpty(releaseId))
{
result.Item.SetProviderId(MetadataProvider.MusicBrainzAlbum, releaseId);
}
if (!string.IsNullOrEmpty(releaseGroupId))
{
result.Item.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, releaseGroupId);
}
Populate(result.Item, release, releaseGroup);
return result;
}
private static void Populate(MusicAlbum item, IRelease? release, IReleaseGroup? releaseGroup)
{
// Prefer the release group (album-level) data, falling back to the specific release.
var overview = releaseGroup?.Annotation;
if (string.IsNullOrWhiteSpace(overview))
{
overview = release?.Annotation;
}
if (!string.IsNullOrWhiteSpace(overview))
{
item.Overview = overview;
}
// The release group's first release date is the original album date.
var date = releaseGroup?.FirstReleaseDate ?? release?.Date;
if (date is not null)
{
item.PremiereDate = date.NearestDate;
item.ProductionYear = date.Year;
}
var artistCredit = release?.ArtistCredit ?? releaseGroup?.ArtistCredit;
if (artistCredit is not null && artistCredit.Count > 0)
{
item.AlbumArtists = artistCredit
.Select(credit => credit.Name)
.Where(name => !string.IsNullOrWhiteSpace(name))
.ToArray();
}
var genres = releaseGroup?.Genres ?? release?.Genres;
if (genres is not null && genres.Count > 0)
{
item.Genres = genres
.OrderByDescending(genre => genre.VoteCount)
.Select(genre => genre.Name)
.Where(name => !string.IsNullOrWhiteSpace(name))
.ToArray();
}
var tags = releaseGroup?.Tags ?? release?.Tags;
if (tags is not null && tags.Count > 0)
{
item.Tags = tags
.OrderByDescending(tag => tag.VoteCount)
.Select(tag => tag.Name)
.Where(name => !string.IsNullOrWhiteSpace(name))
.ToArray();
}
if (release?.LabelInfo is not null && release.LabelInfo.Count > 0)
{
item.Studios = release.LabelInfo
.Where(labelInfo => !string.IsNullOrWhiteSpace(labelInfo.Label?.Name))
.Select(labelInfo => labelInfo.Label!.Name!)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToArray();
}
}
/// <inheritdoc />
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
@@ -101,28 +101,72 @@ public class MusicBrainzArtistProvider : IRemoteMetadataProvider<MusicArtist, Ar
var musicBrainzId = info.GetMusicBrainzArtistId();
// If we don't have an id yet, resolve one by name so we can look the artist up.
if (string.IsNullOrWhiteSpace(musicBrainzId))
{
var searchResults = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
var singleResult = searchResults.FirstOrDefault();
if (singleResult is not null)
{
musicBrainzId = singleResult.GetProviderId(MetadataProvider.MusicBrainzArtist);
result.Item.Overview = singleResult.Overview;
if (Plugin.Instance!.Configuration.ReplaceArtistName)
{
result.Item.Name = singleResult.Name;
}
}
musicBrainzId = searchResults.FirstOrDefault()?.GetProviderId(MetadataProvider.MusicBrainzArtist);
}
if (!string.IsNullOrWhiteSpace(musicBrainzId))
if (string.IsNullOrWhiteSpace(musicBrainzId))
{
result.HasMetadata = true;
result.Item.SetProviderId(MetadataProvider.MusicBrainzArtist, musicBrainzId);
return result;
}
var query = Plugin.Instance!.MusicBrainzQuery;
var artist = await query.LookupArtistAsync(new Guid(musicBrainzId), Include.Annotation | Include.Genres | Include.Tags, null, null, cancellationToken).ConfigureAwait(false);
if (artist is null)
{
return result;
}
result.HasMetadata = true;
result.Item.SetProviderId(MetadataProvider.MusicBrainzArtist, artist.Id.ToString());
if (Plugin.Instance!.Configuration.ReplaceArtistName && !string.IsNullOrWhiteSpace(artist.Name))
{
result.Item.Name = artist.Name;
}
if (!string.IsNullOrWhiteSpace(artist.Annotation))
{
result.Item.Overview = artist.Annotation;
}
if (artist.LifeSpan?.Begin is not null)
{
result.Item.PremiereDate = artist.LifeSpan.Begin.NearestDate;
result.Item.ProductionYear = artist.LifeSpan.Begin.Year;
}
if (artist.LifeSpan?.End is not null)
{
result.Item.EndDate = artist.LifeSpan.End.NearestDate;
}
var location = string.IsNullOrWhiteSpace(artist.Area?.Name) ? artist.Country : artist.Area!.Name;
if (!string.IsNullOrWhiteSpace(location))
{
result.Item.ProductionLocations = [location];
}
if (artist.Genres is not null && artist.Genres.Count > 0)
{
result.Item.Genres = artist.Genres
.OrderByDescending(genre => genre.VoteCount)
.Select(genre => genre.Name)
.Where(name => !string.IsNullOrWhiteSpace(name))
.ToArray();
}
if (artist.Tags is not null && artist.Tags.Count > 0)
{
result.Item.Tags = artist.Tags
.OrderByDescending(tag => tag.VoteCount)
.Select(tag => tag.Name)
.Where(name => !string.IsNullOrWhiteSpace(name))
.ToArray();
}
return result;