@ -8,12 +8,12 @@ using System.IO;
using System.Linq ;
using System.Linq ;
using System.Net ;
using System.Net ;
using System.Net.Http ;
using System.Net.Http ;
using System.Net.Http.Headers ;
using System.Text ;
using System.Text ;
using System.Threading ;
using System.Threading ;
using System.Threading.Tasks ;
using System.Threading.Tasks ;
using System.Xml ;
using System.Xml ;
using MediaBrowser.Common ;
using MediaBrowser.Common ;
using MediaBrowser.Common.Net ;
using MediaBrowser.Controller.Entities.Audio ;
using MediaBrowser.Controller.Entities.Audio ;
using MediaBrowser.Controller.Providers ;
using MediaBrowser.Controller.Providers ;
using MediaBrowser.Model.Entities ;
using MediaBrowser.Model.Entities ;
@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Music
internal static MusicBrainzAlbumProvider Current ;
internal static MusicBrainzAlbumProvider Current ;
private readonly IHttpClient _httpClient ;
private readonly IHttpClient Factory _httpClient Factory ;
private readonly IApplicationHost _appHost ;
private readonly IApplicationHost _appHost ;
private readonly ILogger < MusicBrainzAlbumProvider > _logger ;
private readonly ILogger < MusicBrainzAlbumProvider > _logger ;
@ -51,11 +51,11 @@ namespace MediaBrowser.Providers.Music
private Stopwatch _stopWatchMusicBrainz = new Stopwatch ( ) ;
private Stopwatch _stopWatchMusicBrainz = new Stopwatch ( ) ;
public MusicBrainzAlbumProvider (
public MusicBrainzAlbumProvider (
IHttpClient httpClient ,
IHttpClient Factory httpClient Factory ,
IApplicationHost appHost ,
IApplicationHost appHost ,
ILogger < MusicBrainzAlbumProvider > logger )
ILogger < MusicBrainzAlbumProvider > logger )
{
{
_httpClient = httpClient ;
_httpClient Factory = httpClient Factory ;
_appHost = appHost ;
_appHost = appHost ;
_logger = logger ;
_logger = logger ;
@ -123,12 +123,10 @@ namespace MediaBrowser.Providers.Music
if ( ! string . IsNullOrWhiteSpace ( url ) )
if ( ! string . IsNullOrWhiteSpace ( url ) )
{
{
using ( var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) )
using var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) ;
using ( var stream = response . Content )
await using var stream = await response . Content . ReadAsStreamAsync ( ) . ConfigureAwait ( false ) ;
{
return GetResultsFromResponse ( stream ) ;
return GetResultsFromResponse ( stream ) ;
}
}
}
return Enumerable . Empty < RemoteSearchResult > ( ) ;
return Enumerable . Empty < RemoteSearchResult > ( ) ;
}
}
@ -282,11 +280,10 @@ namespace MediaBrowser.Providers.Music
WebUtility . UrlEncode ( albumName ) ,
WebUtility . UrlEncode ( albumName ) ,
artistId ) ;
artistId ) ;
using ( var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) )
using var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) ;
using ( var stream = response . Content )
await using var stream = await response . Content . ReadAsStreamAsync ( ) . ConfigureAwait ( false ) ;
using ( var oReader = new StreamReader ( stream , Encoding . UTF8 ) )
using var oReader = new StreamReader ( stream , Encoding . UTF8 ) ;
{
var settings = new XmlReaderSettings
var settings = new XmlReaderSettings ( )
{
{
ValidationType = ValidationType . None ,
ValidationType = ValidationType . None ,
CheckCharacters = false ,
CheckCharacters = false ,
@ -294,12 +291,9 @@ namespace MediaBrowser.Providers.Music
IgnoreComments = true
IgnoreComments = true
} ;
} ;
using ( var reader = XmlReader . Create ( oReader , settings ) )
using var reader = XmlReader . Create ( oReader , settings ) ;
{
return ReleaseResult . Parse ( reader ) . FirstOrDefault ( ) ;
return ReleaseResult . Parse ( reader ) . FirstOrDefault ( ) ;
}
}
}
}
private async Task < ReleaseResult > GetReleaseResultByArtistName ( string albumName , string artistName , CancellationToken cancellationToken )
private async Task < ReleaseResult > GetReleaseResultByArtistName ( string albumName , string artistName , CancellationToken cancellationToken )
{
{
@ -309,10 +303,9 @@ namespace MediaBrowser.Providers.Music
WebUtility . UrlEncode ( albumName ) ,
WebUtility . UrlEncode ( albumName ) ,
WebUtility . UrlEncode ( artistName ) ) ;
WebUtility . UrlEncode ( artistName ) ) ;
using ( var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) )
using var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) ;
using ( var stream = response . Content )
await using var stream = await response . Content . ReadAsStreamAsync ( ) . ConfigureAwait ( false ) ;
using ( var oReader = new StreamReader ( stream , Encoding . UTF8 ) )
using var oReader = new StreamReader ( stream , Encoding . UTF8 ) ;
{
var settings = new XmlReaderSettings ( )
var settings = new XmlReaderSettings ( )
{
{
ValidationType = ValidationType . None ,
ValidationType = ValidationType . None ,
@ -321,12 +314,9 @@ namespace MediaBrowser.Providers.Music
IgnoreComments = true
IgnoreComments = true
} ;
} ;
using ( var reader = XmlReader . Create ( oReader , settings ) )
using var reader = XmlReader . Create ( oReader , settings ) ;
{
return ReleaseResult . Parse ( reader ) . FirstOrDefault ( ) ;
return ReleaseResult . Parse ( reader ) . FirstOrDefault ( ) ;
}
}
}
}
private class ReleaseResult
private class ReleaseResult
{
{
@ -624,11 +614,10 @@ namespace MediaBrowser.Providers.Music
{
{
var url = "/ws/2/release?release-group=" + releaseGroupId . ToString ( CultureInfo . InvariantCulture ) ;
var url = "/ws/2/release?release-group=" + releaseGroupId . ToString ( CultureInfo . InvariantCulture ) ;
using ( var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) )
using var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) ;
using ( var stream = response . Content )
await using var stream = await response . Content . ReadAsStreamAsync ( ) . ConfigureAwait ( false ) ;
using ( var oReader = new StreamReader ( stream , Encoding . UTF8 ) )
using var oReader = new StreamReader ( stream , Encoding . UTF8 ) ;
{
var settings = new XmlReaderSettings
var settings = new XmlReaderSettings ( )
{
{
ValidationType = ValidationType . None ,
ValidationType = ValidationType . None ,
CheckCharacters = false ,
CheckCharacters = false ,
@ -636,18 +625,10 @@ namespace MediaBrowser.Providers.Music
IgnoreComments = true
IgnoreComments = true
} ;
} ;
using ( var reader = XmlReader . Create ( oReader , settings ) )
using var reader = XmlReader . Create ( oReader , settings ) ;
{
var result = ReleaseResult . Parse ( reader ) . FirstOrDefault ( ) ;
var result = ReleaseResult . Parse ( reader ) . FirstOrDefault ( ) ;
if ( result ! = null )
return result ? . ReleaseId ;
{
return result . ReleaseId ;
}
}
}
return null ;
}
}
/// <summary>
/// <summary>
@ -660,11 +641,10 @@ namespace MediaBrowser.Providers.Music
{
{
var url = "/ws/2/release-group/?query=reid:" + releaseEntryId . ToString ( CultureInfo . InvariantCulture ) ;
var url = "/ws/2/release-group/?query=reid:" + releaseEntryId . ToString ( CultureInfo . InvariantCulture ) ;
using ( var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) )
using var response = await GetMusicBrainzResponse ( url , cancellationToken ) . ConfigureAwait ( false ) ;
using ( var stream = response . Content )
await using var stream = await response . Content . ReadAsStreamAsync ( ) . ConfigureAwait ( false ) ;
using ( var oReader = new StreamReader ( stream , Encoding . UTF8 ) )
using var oReader = new StreamReader ( stream , Encoding . UTF8 ) ;
{
var settings = new XmlReaderSettings
var settings = new XmlReaderSettings ( )
{
{
ValidationType = ValidationType . None ,
ValidationType = ValidationType . None ,
CheckCharacters = false ,
CheckCharacters = false ,
@ -714,7 +694,6 @@ namespace MediaBrowser.Providers.Music
return null ;
return null ;
}
}
}
}
}
private string GetFirstReleaseGroupId ( XmlReader reader )
private string GetFirstReleaseGroupId ( XmlReader reader )
{
{
@ -755,23 +734,19 @@ namespace MediaBrowser.Providers.Music
/// A number of retries shall be made in order to try and satisfy the request before
/// A number of retries shall be made in order to try and satisfy the request before
/// giving up and returning null.
/// giving up and returning null.
/// </summary>
/// </summary>
internal async Task < HttpResponseInfo > GetMusicBrainzResponse ( string url , CancellationToken cancellationToken )
internal async Task < HttpResponseMessage > GetMusicBrainzResponse ( string url , CancellationToken cancellationToken )
{
var options = new HttpRequestOptions
{
{
Url = _musicBrainzBaseUrl . TrimEnd ( '/' ) + url ,
using var options = new HttpRequestMessage ( HttpMethod . Get , _musicBrainzBaseUrl . TrimEnd ( '/' ) + url ) ;
CancellationToken = cancellationToken ,
// MusicBrainz request a contact email address is supplied, as comment, in user agent field:
// MusicBrainz request a contact email address is supplied, as comment, in user agent field:
// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting#User-Agent
// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting#User-Agent
UserAgent = string . Format (
options . Headers . UserAgent . Add ( new ProductInfoHeaderValue ( string . Format (
CultureInfo . InvariantCulture ,
CultureInfo . InvariantCulture ,
"{0} ( {1} )" ,
"{0} ( {1} )" ,
_appHost . ApplicationUserAgent ,
_appHost . ApplicationUserAgent ,
_appHost . ApplicationUserAgentAddress ) ,
_appHost . ApplicationUserAgentAddress ) ) ) ;
BufferContent = false
} ;
HttpResponse Info response ;
HttpResponseMessage response ;
var attempts = 0 u ;
var attempts = 0 u ;
do
do
@ -790,7 +765,7 @@ namespace MediaBrowser.Providers.Music
_logger . LogDebug ( "GetMusicBrainzResponse: Time since previous request: {0} ms" , _stopWatchMusicBrainz . ElapsedMilliseconds ) ;
_logger . LogDebug ( "GetMusicBrainzResponse: Time since previous request: {0} ms" , _stopWatchMusicBrainz . ElapsedMilliseconds ) ;
_stopWatchMusicBrainz . Restart ( ) ;
_stopWatchMusicBrainz . Restart ( ) ;
response = await _httpClient . SendAsync ( options , HttpMethod . Get ) . ConfigureAwait ( false ) ;
response = await _httpClient Factory. CreateClient ( ) . SendAsync ( options ) . ConfigureAwait ( false ) ;
// We retry a finite number of times, and only whilst MB is indicating 503 (throttling)
// We retry a finite number of times, and only whilst MB is indicating 503 (throttling)
}
}
@ -799,14 +774,14 @@ namespace MediaBrowser.Providers.Music
// Log error if unable to query MB database due to throttling
// Log error if unable to query MB database due to throttling
if ( attempts = = MusicBrainzQueryAttempts & & response . StatusCode = = HttpStatusCode . ServiceUnavailable )
if ( attempts = = MusicBrainzQueryAttempts & & response . StatusCode = = HttpStatusCode . ServiceUnavailable )
{
{
_logger . LogError ( "GetMusicBrainzResponse: 503 Service Unavailable (throttled) response received {0} times whilst requesting {1}" , attempts , options . Url ) ;
_logger . LogError ( "GetMusicBrainzResponse: 503 Service Unavailable (throttled) response received {0} times whilst requesting {1}" , attempts , options . RequestUri ) ;
}
}
return response ;
return response ;
}
}
/// <inheritdoc />
/// <inheritdoc />
public Task < HttpResponse Info > GetImageResponse ( string url , CancellationToken cancellationToken )
public Task < HttpResponse Message > GetImageResponse ( string url , CancellationToken cancellationToken )
{
{
throw new NotImplementedException ( ) ;
throw new NotImplementedException ( ) ;
}
}