From 8f57f3537260642315d48192e66abd977017d857 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Thu, 23 Jul 2026 21:21:28 +0200 Subject: [PATCH] Implement AudioDb artist search --- .../Plugins/AudioDb/AudioDbArtistProvider.cs | 86 ++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs index d8cb6b4b24..b4aae6ac8b 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; @@ -52,8 +53,89 @@ namespace MediaBrowser.Providers.Plugins.AudioDb public int Order => 1; /// - public Task> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken) - => Task.FromResult(Enumerable.Empty()); + public async Task> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken) + { + // Prefer a known TheAudioDB artist id. + var audioDbId = searchInfo.GetProviderId(MetadataProvider.AudioDbArtist); + if (!string.IsNullOrWhiteSpace(audioDbId)) + { + var artists = await FetchArtists(BaseUrl + "/artist.php?i=" + audioDbId, cancellationToken).ConfigureAwait(false); + return artists.Select(ToRemoteSearchResult); + } + + // Fall back to the MusicBrainz artist id, reusing the on-disk cache also used by GetMetadata. + var musicBrainzId = searchInfo.GetMusicBrainzArtistId(); + if (!string.IsNullOrWhiteSpace(musicBrainzId)) + { + await EnsureArtistInfo(musicBrainzId, cancellationToken).ConfigureAwait(false); + + var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId); + + FileStream jsonStream = AsyncFile.OpenRead(path); + await using (jsonStream.ConfigureAwait(false)) + { + var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + + if (obj is not null && obj.artists is not null) + { + return obj.artists.Select(ToRemoteSearchResult); + } + } + + return Enumerable.Empty(); + } + + // Finally, search by name. + if (!string.IsNullOrWhiteSpace(searchInfo.Name)) + { + var artists = await FetchArtists(BaseUrl + "/search.php?s=" + Uri.EscapeDataString(searchInfo.Name), cancellationToken).ConfigureAwait(false); + return artists.Select(ToRemoteSearchResult); + } + + return Enumerable.Empty(); + } + + private async Task> FetchArtists(string url, CancellationToken cancellationToken) + { + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + + var jsonStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + await using (jsonStream.ConfigureAwait(false)) + { + var obj = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + + return obj?.artists ?? []; + } + } + + private RemoteSearchResult ToRemoteSearchResult(Artist artist) + { + var result = new RemoteSearchResult + { + Name = artist.strArtist, + ImageUrl = artist.strArtistThumb, + SearchProviderName = Name, + Overview = (artist.strBiographyEN ?? string.Empty).StripHtml() + }; + + if (!string.IsNullOrEmpty(artist.idArtist)) + { + result.SetProviderId(MetadataProvider.AudioDbArtist, artist.idArtist); + } + + if (!string.IsNullOrEmpty(artist.strMusicBrainzID)) + { + result.SetProviderId(MetadataProvider.MusicBrainzArtist, artist.strMusicBrainzID); + } + + if (int.TryParse(artist.intFormedYear, NumberStyles.Integer, CultureInfo.InvariantCulture, out var formedYear)) + { + result.ProductionYear = formedYear; + } + + return result; + } /// public async Task> GetMetadata(ArtistInfo info, CancellationToken cancellationToken)