HttpClient work

This commit is contained in:
Steven Hildreth 2022-01-19 18:42:47 -06:00
parent 5a5e4cae70
commit f508aebd36
7 changed files with 521 additions and 142 deletions

View file

@ -54,10 +54,19 @@ namespace Roadie.Library.Tests
[Fact]
public async Task LastFMReleaseSearch()
{
if (!Configuration.Integrations.LastFmProviderEnabled)
//if (!Configuration.Integrations.LastFmProviderEnabled)
//{
// return;
//}
Configuration.Integrations.ApiKeys = new List<ApiKey>();
Configuration.Integrations.ApiKeys.Add(new ApiKey
{
return;
}
ApiName = "LastFMApiKey",
Key = "a31dd32179375f9e332b89f8b9e38fc5",
KeySecret = "35b3684601b2ecf9c0c0c1cfda28159e"
});
var logger = new EventMessageLogger<LastFmHelper>();
logger.Messages += MessageLogger_Messages;
var lfmHelper = new LastFmHelper(Configuration, CacheManager, new EventMessageLogger<LastFmHelper>(), RoadieDbContext, HttpEncoder, _httpClientFactory);
@ -66,6 +75,7 @@ namespace Roadie.Library.Tests
var title = "Piano Man";
var sw = Stopwatch.StartNew();
// With Tags
var result = await lfmHelper.PerformReleaseSearch(artistName, title, 1).ConfigureAwait(false);
sw.Stop();
@ -75,6 +85,21 @@ namespace Roadie.Library.Tests
Assert.NotEmpty(result.Data);
var release = result.Data.FirstOrDefault();
Assert.NotNull(release);
artistName = "Rigor Mortis";
title = "The Infinite Carnage";
sw = Stopwatch.StartNew();
// Without Tags
result = await lfmHelper.PerformReleaseSearch(artistName, title, 1).ConfigureAwait(false);
sw.Stop();
Assert.NotNull(result);
Assert.NotNull(result.Data);
Assert.NotEmpty(result.Data);
release = result.Data.FirstOrDefault();
Assert.NotNull(release);
}
[Fact]

View file

@ -1,128 +1,437 @@
using System.Collections.Generic;
using System.Xml.Serialization;
namespace Roadie.Library.SearchEngines.MetaData.LastFm
namespace Roadie.Library.SearchEngines.MetaData.LastFm
{
/// <remarks />
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public class lfm
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.SerializableAttribute()]
public partial class lfm
{
/// <remarks />
public lfmAlbum album { get; set; }
private lfmAlbum albumField;
/// <remarks />
[XmlAttribute]
public string status { get; set; }
private string statusField;
/// <remarks/>
public lfmAlbum album
{
get
{
return this.albumField;
}
set
{
this.albumField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string status
{
get
{
return this.statusField;
}
set
{
this.statusField = value;
}
}
}
/// <remarks />
[XmlType(AnonymousType = true)]
public class lfmAlbum
/// <remarks/>
[System.SerializableAttribute()]
public partial class lfmAlbum
{
/// <remarks />
public string artist { get; set; }
private string nameField;
/// <remarks />
[XmlElement("image")]
public List<lfmAlbumImage> image { get; set; }
private string artistField;
/// <remarks />
public ushort listeners { get; set; }
private string mbidField;
/// <remarks />
public string mbid { get; set; }
private string urlField;
/// <remarks />
public string name { get; set; }
private lfmAlbumImage[] imageField;
/// <remarks />
public uint playcount { get; set; }
private uint? listenersField;
/// <remarks />
[XmlArrayItem("tag", IsNullable = false)]
public List<lfmAlbumTag> tags { get; set; }
private uint? playcountField;
/// <remarks />
[XmlArrayItem("track", IsNullable = false)]
public List<lfmAlbumTrack> tracks { get; set; }
private lfmAlbumTrack[] tracksField;
/// <remarks />
public string url { get; set; }
private lfmAlbumTag[] tagsField;
/// <remarks/>
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
/// <remarks/>
public string artist
{
get
{
return this.artistField;
}
set
{
this.artistField = value;
}
}
/// <remarks/>
public string mbid
{
get
{
return this.mbidField;
}
set
{
this.mbidField = value;
}
}
/// <remarks/>
public string url
{
get
{
return this.urlField;
}
set
{
this.urlField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("image")]
public lfmAlbumImage[] image
{
get
{
return this.imageField;
}
set
{
this.imageField = value;
}
}
/// <remarks/>
public uint? listeners
{
get
{
return this.listenersField;
}
set
{
this.listenersField = value;
}
}
/// <remarks/>
public uint? playcount
{
get
{
return this.playcountField;
}
set
{
this.playcountField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("track", IsNullable = false)]
public lfmAlbumTrack[] tracks
{
get
{
return this.tracksField;
}
set
{
this.tracksField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("tag", IsNullable = false)]
public lfmAlbumTag[] tags
{
get
{
return this.tagsField;
}
set
{
this.tagsField = value;
}
}
}
/// <remarks />
[XmlType(AnonymousType = true)]
public class lfmAlbumImage
/// <remarks/>
[System.SerializableAttribute()]
public partial class lfmAlbumImage
{
/// <remarks />
[XmlAttribute]
public string size { get; set; }
private string sizeField;
/// <remarks />
[XmlText]
public string Value { get; set; }
private string valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string size
{
get
{
return this.sizeField;
}
set
{
this.sizeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
/// <remarks />
[XmlType(AnonymousType = true)]
public class lfmAlbumTag
/// <remarks/>
[System.SerializableAttribute()]
public partial class lfmAlbumTrack
{
/// <remarks />
public string name { get; set; }
private string nameField;
/// <remarks />
public string url { get; set; }
private string urlField;
private ushort durationField;
private lfmAlbumTrackStreamable streamableField;
private lfmAlbumTrackArtist artistField;
private byte rankField;
/// <remarks/>
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
/// <remarks/>
public string url
{
get
{
return this.urlField;
}
set
{
this.urlField = value;
}
}
/// <remarks/>
public ushort duration
{
get
{
return this.durationField;
}
set
{
this.durationField = value;
}
}
/// <remarks/>
public lfmAlbumTrackStreamable streamable
{
get
{
return this.streamableField;
}
set
{
this.streamableField = value;
}
}
/// <remarks/>
public lfmAlbumTrackArtist artist
{
get
{
return this.artistField;
}
set
{
this.artistField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte rank
{
get
{
return this.rankField;
}
set
{
this.rankField = value;
}
}
}
/// <remarks />
[XmlType(AnonymousType = true)]
public class lfmAlbumTrack
/// <remarks/>
[System.SerializableAttribute()]
public partial class lfmAlbumTrackStreamable
{
/// <remarks />
public lfmAlbumTrackArtist artist { get; set; }
private byte fulltrackField;
/// <remarks />
public ushort duration { get; set; }
private byte valueField;
/// <remarks />
public string name { get; set; }
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte fulltrack
{
get
{
return this.fulltrackField;
}
set
{
this.fulltrackField = value;
}
}
/// <remarks />
[XmlAttribute]
public byte rank { get; set; }
/// <remarks />
public lfmAlbumTrackStreamable streamable { get; set; }
/// <remarks />
public string url { get; set; }
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public byte Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
/// <remarks />
[XmlType(AnonymousType = true)]
public class lfmAlbumTrackArtist
/// <remarks/>
[System.SerializableAttribute()]
public partial class lfmAlbumTrackArtist
{
/// <remarks />
public string mbid { get; set; }
private string nameField;
/// <remarks />
public string name { get; set; }
private string mbidField;
/// <remarks />
public string url { get; set; }
private string urlField;
/// <remarks/>
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
/// <remarks/>
public string mbid
{
get
{
return this.mbidField;
}
set
{
this.mbidField = value;
}
}
/// <remarks/>
public string url
{
get
{
return this.urlField;
}
set
{
this.urlField = value;
}
}
}
/// <remarks />
[XmlType(AnonymousType = true)]
public class lfmAlbumTrackStreamable
/// <remarks/>
[System.SerializableAttribute()]
public partial class lfmAlbumTag
{
/// <remarks />
[XmlAttribute]
public byte fulltrack { get; set; }
private string nameField;
/// <remarks />
[XmlText]
public byte Value { get; set; }
private string urlField;
/// <remarks/>
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
/// <remarks/>
public string url
{
get
{
return this.urlField;
}
set
{
this.urlField = value;
}
}
}
}
}

View file

@ -14,12 +14,14 @@ using Roadie.Library.SearchEngines.MetaData.LastFm;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;
using static System.Net.Mime.MediaTypeNames;
@ -92,10 +94,9 @@ namespace Roadie.Library.MetaData.LastFm
{"token", token}
};
string responseXML = null;
var client = _httpClientFactory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, BuildUrl("auth.getSession", parameters));
request.Headers.Add("User-Agent", WebHelper.UserAgent);
var response = await client.SendAsync(request).ConfigureAwait(false);
var response = await HttpClient.SendAsync(request).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
responseXML = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
@ -136,10 +137,9 @@ namespace Roadie.Library.MetaData.LastFm
parameters.Add("api_sig", signature);
ServicePointManager.Expect100Continue = false;
var client = _httpClientFactory.CreateClient();
XPathNavigator xp = null;
var parametersJson = new StringContent(CacheManager.CacheSerializer.Serialize(parameters), System.Text.Encoding.UTF8, Application.Json);
using (var httpResponseMessage = await client.PostAsync(url, parametersJson).ConfigureAwait(false))
using (var httpResponseMessage = await HttpClient.PostAsync(url, parametersJson).ConfigureAwait(false))
{
if (httpResponseMessage.IsSuccessStatusCode)
{
@ -170,7 +170,7 @@ namespace Roadie.Library.MetaData.LastFm
{
Logger.LogTrace("LastFmHelper:PerformArtistSearch:{0}", query);
var auth = new LastAuth(ApiKey.Key, ApiKey.KeySecret);
var albumApi = new ArtistApi(auth, _httpClientFactory.CreateClient());
var albumApi = new ArtistApi(auth, HttpClient);
var response = await albumApi.GetInfoAsync(query).ConfigureAwait(false);
if (!response.Success)
{
@ -184,8 +184,15 @@ namespace Roadie.Library.MetaData.LastFm
MusicBrainzId = lastFmArtist.Mbid,
Bio = lastFmArtist.Bio != null ? lastFmArtist.Bio.Content : null
};
if (lastFmArtist.Tags != null) result.Tags = lastFmArtist.Tags.Select(x => x.Name).ToList();
// No longer fetching/consuming images LastFm says is violation of ToS ; https://getsatisfaction.com/lastfm/topics/api-announcement-dac8oefw5vrxq
if (lastFmArtist.Tags != null)
{
result.Tags = lastFmArtist.Tags.Select(x => x.Name).ToList();
}
if(lastFmArtist.MainImage != null)
{
result.ImageUrls = new string[1] { lastFmArtist.MainImage.Largest?.AbsoluteUri };
}
if (lastFmArtist.Url != null)
{
result.Urls = new[] { lastFmArtist.Url.ToString() };
@ -211,50 +218,54 @@ namespace Roadie.Library.MetaData.LastFm
var cacheKey = $"uri:lastfm:releasesearch:{ artistName.ToAlphanumericName() }:{ query.ToAlphanumericName() }";
var data = await CacheManager.GetAsync<ReleaseSearchResult>(cacheKey, async () =>
{
Rootobject response = null;
var client = _httpClientFactory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, $"http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key={ ApiKey.Key }&artist={ artistName }&album={ query }&format=json");
request.Headers.Add("User-Agent", WebHelper.UserAgent);
var sendResponse = await client.SendAsync(request).ConfigureAwait(false);
if (sendResponse.IsSuccessStatusCode)
var auth = new LastAuth(ApiKey.Key, ApiKey.KeySecret);
var releaseApi =new IF.Lastfm.Core.Api.AlbumApi(auth, HttpClient);
var sendResponse = await releaseApi.GetInfoAsync(artistName, query).ConfigureAwait(false);
if (!sendResponse.Success)
{
try
{
var r = await sendResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
response = CacheManager.CacheSerializer.Deserialize<Rootobject>(r);
}
catch (Exception ex)
{
Logger.LogError(ex);
}
return null;
}
var response = sendResponse.Content;
ReleaseSearchResult result = null;
if (response != null && response.album != null)
if (response != null)
{
var lastFmAlbum = response.album;
var lastFmAlbum = response;
result = new ReleaseSearchResult
{
ReleaseTitle = lastFmAlbum.name,
MusicBrainzId = lastFmAlbum.mbid
ReleaseTitle = lastFmAlbum.Name,
MusicBrainzId = lastFmAlbum.Mbid
};
// No longer fetching/consuming images LastFm says is violation of ToS ; https://getsatisfaction.com/lastfm/topics/api-announcement-dac8oefw5vrxq
if (!string.IsNullOrWhiteSpace(lastFmAlbum.tags))
if(lastFmAlbum.Images != null)
{
result.Tags = lastFmAlbum.GetTags(CacheManager.CacheSerializer)?.Select(x => x.name).ToList();
result.ImageUrls = new string[1] { lastFmAlbum.Images.Largest.AbsoluteUri };
}
if (lastFmAlbum.tracks != null)
if (lastFmAlbum.TopTags?.Any() == true)
{
result.Tags = FilterTags(lastFmAlbum.TopTags.Select(x => x.Name));
}
else
{
var tagResult = await releaseApi.GetTopTagsAsync(artistName, query).ConfigureAwait(false);
if(tagResult != null)
{
result.Tags = FilterTags(tagResult.Select(x => x.Name).Distinct().Take(25).ToArray());
}
}
if (lastFmAlbum.Tracks != null)
{
var tracks = new List<TrackSearchResult>();
foreach (var lastFmTrack in lastFmAlbum.tracks.track)
foreach (var lastFmTrack in lastFmAlbum.Tracks)
{
tracks.Add(new TrackSearchResult
{
TrackNumber = SafeParser.ToNumber<short?>(lastFmTrack.TrackNumber),
Title = lastFmTrack.name,
Duration = SafeParser.ToNumber<int?>(lastFmTrack.duration),
Urls = string.IsNullOrEmpty(lastFmTrack.url) ? new[] { lastFmTrack.url } : null
TrackNumber = SafeParser.ToNumber<short?>(lastFmTrack.Rank),
Title = lastFmTrack.Name,
Duration = SafeParser.ToNumber<int?>(lastFmTrack.Duration),
Urls = lastFmTrack.Url != null ? new[] { lastFmTrack.Url.AbsoluteUri } : null
});
}
result.ReleaseMedia = new List<ReleaseMediaSearchResult>
@ -276,6 +287,31 @@ namespace Roadie.Library.MetaData.LastFm
};
}
private static IEnumerable<string> _tagsToIgnore = new List<string>
{
"albums I listened to",
"albums i own on vinyl",
"albums I own",
"everything",
"favorite album",
"me in concert",
"my favorites",
"our wedding dance",
"records i own",
"reminds me of my childhood",
"vinyls i own"
};
private List<string> FilterTags(IEnumerable<string> tags)
{
if(tags.Any() == false)
{
return null;
}
var result = tags.Where(x => !string.IsNullOrWhiteSpace(x) && x.Length > 1).ToList();
return result.Except(_tagsToIgnore).ToList();
}
public async Task<OperationResult<bool>> Scrobble(User roadieUser, ScrobbleInfo scrobble)
{
var result = false;
@ -315,10 +351,9 @@ namespace Roadie.Library.MetaData.LastFm
parameters.Add("api_sig", signature);
ServicePointManager.Expect100Continue = false;
var client = _httpClientFactory.CreateClient();
XPathNavigator xp = null;
var parametersJson = new StringContent(CacheManager.CacheSerializer.Serialize(parameters), System.Text.Encoding.UTF8, Application.Json);
using (var httpResponseMessage = await client.PostAsync(url, parametersJson).ConfigureAwait(false))
using (var httpResponseMessage = await HttpClient.PostAsync(url, parametersJson).ConfigureAwait(false))
{
if (httpResponseMessage.IsSuccessStatusCode)
{

View file

@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using Roadie.Library.Caching;
using Roadie.Library.Configuration;
using System;
using System.Net;
using System.Net.Http;
@ -8,10 +9,12 @@ namespace Roadie.Library.MetaData
{
public abstract class MetaDataProviderBase
{
private Lazy<HttpClient> _httpClient;
private readonly IHttpClientFactory _httpClientFactory;
protected readonly ICacheManager _cacheManager;
protected readonly IRoadieSettings _configuration;
protected readonly ILogger _logger;
protected readonly IHttpClientFactory _httpClientFactory;
protected IApiKey _apiKey = null;
@ -25,6 +28,8 @@ namespace Roadie.Library.MetaData
protected ILogger Logger => _logger;
protected HttpClient HttpClient => _httpClient.Value;
public MetaDataProviderBase(
IRoadieSettings configuration,
ICacheManager cacheManager,
@ -36,6 +41,8 @@ namespace Roadie.Library.MetaData
_logger = logger;
_httpClientFactory = httpClientFactory;
_httpClient = new Lazy<HttpClient>(() => _httpClientFactory.CreateClient());
ServicePointManager.ServerCertificateValidationCallback += delegate
{
return true; // **** Always accept

View file

@ -61,7 +61,7 @@ namespace Roadie.Library.MetaData.MusicBrainz
}
// Now get The Release Details
release = await MusicBrainzRequestHelper.GetAsync<Release>(_httpClientFactory, MusicBrainzRequestHelper.CreateLookupUrl("release", ReleaseResult.MusicBrainzId, "recordings")).ConfigureAwait(false);
release = await MusicBrainzRequestHelper.GetAsync<Release>(HttpClient, MusicBrainzRequestHelper.CreateLookupUrl("release", ReleaseResult.MusicBrainzId, "recordings")).ConfigureAwait(false);
if (release == null) return null;
CacheManager.Add(ReleaseCacheKey, release);
}
@ -300,7 +300,7 @@ namespace Roadie.Library.MetaData.MusicBrainz
};
}
private Task<CoverArtArchivesResult> CoverArtForMusicBrainzReleaseByIdAsync(string musicBrainzId) => MusicBrainzRequestHelper.GetAsync<CoverArtArchivesResult>(_httpClientFactory, MusicBrainzRequestHelper.CreateCoverArtReleaseUrl(musicBrainzId));
private Task<CoverArtArchivesResult> CoverArtForMusicBrainzReleaseByIdAsync(string musicBrainzId) => MusicBrainzRequestHelper.GetAsync<CoverArtArchivesResult>(HttpClient, MusicBrainzRequestHelper.CreateCoverArtReleaseUrl(musicBrainzId));
private async Task<IEnumerable<Release>> ReleasesForArtistAsync(string artist, string artistMusicBrainzId = null)
{

View file

@ -16,7 +16,10 @@ namespace Roadie.Library.MetaData.MusicBrainz
private ILogger<MusicBrainzProvider> Logger { get; }
private IHttpClientFactory HttpClientFactory { get; }
private Lazy<HttpClient> _httpClient;
private readonly IHttpClientFactory _httpClientFactory;
private HttpClient HttpClient => _httpClient.Value;
public MusicBrainzRepository(
IRoadieSettings configuration,
@ -31,7 +34,8 @@ namespace Roadie.Library.MetaData.MusicBrainz
Directory.CreateDirectory(directory);
}
FileName = Path.Combine(directory, "MusicBrainzRespository.db");
HttpClientFactory = httpClientFactory;
_httpClientFactory = httpClientFactory;
_httpClient = new Lazy<HttpClient>(() => _httpClientFactory.CreateClient());
}
/// <summary>
@ -54,14 +58,14 @@ namespace Roadie.Library.MetaData.MusicBrainz
if (artist == null)
{
// Perform a query to get the MbId for the Name
var artistResult = await MusicBrainzRequestHelper.GetAsync<ArtistResult>(HttpClientFactory, MusicBrainzRequestHelper.CreateSearchTemplate("artist", name, resultsCount ?? 1, 0)).ConfigureAwait(false);
var artistResult = await MusicBrainzRequestHelper.GetAsync<ArtistResult>(HttpClient, MusicBrainzRequestHelper.CreateSearchTemplate("artist", name, resultsCount ?? 1, 0)).ConfigureAwait(false);
if (artistResult == null || artistResult.artists == null || !artistResult.artists.Any() || artistResult.count < 1)
{
return null;
}
var mbId = artistResult.artists.First().id;
// Now perform a detail request to get the details by the MbId
result = await MusicBrainzRequestHelper.GetAsync<Artist>(HttpClientFactory, MusicBrainzRequestHelper.CreateLookupUrl("artist", mbId, "aliases+tags+genres+url-rels")).ConfigureAwait(false);
result = await MusicBrainzRequestHelper.GetAsync<Artist>(HttpClient, MusicBrainzRequestHelper.CreateLookupUrl("artist", mbId, "aliases+tags+genres+url-rels")).ConfigureAwait(false);
if (result != null)
{
col.Insert(new RepositoryArtist
@ -119,7 +123,7 @@ namespace Roadie.Library.MetaData.MusicBrainz
var pageSize = 50;
var page = 0;
var url = MusicBrainzRequestHelper.CreateArtistBrowseTemplate(artistMbId, pageSize, 0);
var mbReleaseBrowseResult = await MusicBrainzRequestHelper.GetAsync<ReleaseBrowseResult>(HttpClientFactory, url).ConfigureAwait(false);
var mbReleaseBrowseResult = await MusicBrainzRequestHelper.GetAsync<ReleaseBrowseResult>(HttpClient, url).ConfigureAwait(false);
var totalReleases = mbReleaseBrowseResult != null ? mbReleaseBrowseResult.releasecount : 0;
var totalPages = Math.Ceiling((decimal)totalReleases / pageSize);
var fetchResult = new List<Release>();
@ -130,7 +134,7 @@ namespace Roadie.Library.MetaData.MusicBrainz
fetchResult.AddRange(mbReleaseBrowseResult.releases.Where(x => !string.IsNullOrEmpty(x.date)));
}
page++;
mbReleaseBrowseResult = await MusicBrainzRequestHelper.GetAsync<ReleaseBrowseResult>(HttpClientFactory, MusicBrainzRequestHelper.CreateArtistBrowseTemplate(artistMbId, pageSize, pageSize * page)).ConfigureAwait(false);
mbReleaseBrowseResult = await MusicBrainzRequestHelper.GetAsync<ReleaseBrowseResult>(HttpClient, MusicBrainzRequestHelper.CreateArtistBrowseTemplate(artistMbId, pageSize, pageSize * page)).ConfigureAwait(false);
} while (page < totalPages);
var releasesToInsert = fetchResult.GroupBy(x => x.title).Select(x => x.OrderBy(x => x.date).First()).OrderBy(x => x.date).ThenBy(x => x.title);
col.InsertBulk(releasesToInsert.Where(x => x != null).Select(x => new RepositoryRelease

View file

@ -40,7 +40,7 @@ namespace Roadie.Library.MetaData.MusicBrainz
return string.Format("{0}{1}", WebServiceUrl, string.Format(SearchTemplate, entity, query, limit, offset));
}
internal static async Task<T> GetAsync<T>(IHttpClientFactory httpClientFactory, string url, bool withoutMetadata = true)
internal static async Task<T> GetAsync<T>(HttpClient client, string url, bool withoutMetadata = true)
{
var tryCount = 0;
var result = default(T);
@ -49,7 +49,6 @@ namespace Roadie.Library.MetaData.MusicBrainz
{
try
{
var client = httpClientFactory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Add("User-Agent", WebHelper.UserAgent);
var response = await client.SendAsync(request).ConfigureAwait(false);