Merge pull request #2965 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2017-10-20 12:19:03 -04:00 committed by GitHub
commit 9b383f6b1a
44 changed files with 792 additions and 769 deletions

View File

@ -43,37 +43,38 @@ namespace Emby.Dlna.ContentDirectory
options.RequestContent = GetRequestBody(request); options.RequestContent = GetRequestBody(request);
var response = await _httpClient.SendAsync(options, "POST"); using (var response = await _httpClient.SendAsync(options, "POST"))
using (var reader = new StreamReader(response.Content))
{ {
var doc = XDocument.Parse(reader.ReadToEnd(), LoadOptions.PreserveWhitespace); using (var reader = new StreamReader(response.Content))
var queryResult = new QueryResult<ChannelItemInfo>();
if (doc.Document == null)
return queryResult;
var responseElement = doc.Document.Descendants(UNamespace + "BrowseResponse").ToList();
var countElement = responseElement.Select(i => i.Element("TotalMatches")).FirstOrDefault(i => i != null);
var countValue = countElement == null ? null : countElement.Value;
int count;
if (!string.IsNullOrWhiteSpace(countValue) && int.TryParse(countValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out count))
{ {
queryResult.TotalRecordCount = count; var doc = XDocument.Parse(reader.ReadToEnd(), LoadOptions.PreserveWhitespace);
var resultElement = responseElement.Select(i => i.Element("Result")).FirstOrDefault(i => i != null); var queryResult = new QueryResult<ChannelItemInfo>();
var resultString = (string)resultElement;
if (resultElement != null) if (doc.Document == null)
return queryResult;
var responseElement = doc.Document.Descendants(UNamespace + "BrowseResponse").ToList();
var countElement = responseElement.Select(i => i.Element("TotalMatches")).FirstOrDefault(i => i != null);
var countValue = countElement == null ? null : countElement.Value;
int count;
if (!string.IsNullOrWhiteSpace(countValue) && int.TryParse(countValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out count))
{ {
var xElement = XElement.Parse(resultString); queryResult.TotalRecordCount = count;
}
}
return queryResult; var resultElement = responseElement.Select(i => i.Element("Result")).FirstOrDefault(i => i != null);
var resultString = (string)resultElement;
if (resultElement != null)
{
var xElement = XElement.Parse(resultString);
}
}
return queryResult;
}
} }
} }

View File

@ -182,7 +182,10 @@ namespace Emby.Dlna.Eventing
try try
{ {
await _httpClient.SendAsync(options, "NOTIFY").ConfigureAwait(false); using (await _httpClient.SendAsync(options, "NOTIFY").ConfigureAwait(false))
{
}
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {

View File

@ -31,14 +31,15 @@ namespace Emby.Dlna.PlayTo
bool logRequest = true, bool logRequest = true,
string header = null) string header = null)
{ {
var response = await PostSoapDataAsync(NormalizeServiceUrl(baseUrl, service.ControlUrl), "\"" + service.ServiceType + "#" + command + "\"", postData, header, logRequest) using (var response = await PostSoapDataAsync(NormalizeServiceUrl(baseUrl, service.ControlUrl), "\"" + service.ServiceType + "#" + command + "\"", postData, header, logRequest)
.ConfigureAwait(false); .ConfigureAwait(false))
using (var stream = response.Content)
{ {
using (var reader = new StreamReader(stream, Encoding.UTF8)) using (var stream = response.Content)
{ {
return XDocument.Parse(reader.ReadToEnd(), LoadOptions.PreserveWhitespace); using (var reader = new StreamReader(stream, Encoding.UTF8))
{
return XDocument.Parse(reader.ReadToEnd(), LoadOptions.PreserveWhitespace);
}
} }
} }
} }
@ -79,7 +80,10 @@ namespace Emby.Dlna.PlayTo
options.RequestHeaders["NT"] = "upnp:event"; options.RequestHeaders["NT"] = "upnp:event";
options.RequestHeaders["TIMEOUT"] = "Second-" + timeOut.ToString(_usCulture); options.RequestHeaders["TIMEOUT"] = "Second-" + timeOut.ToString(_usCulture);
await _httpClient.SendAsync(options, "SUBSCRIBE").ConfigureAwait(false); using (await _httpClient.SendAsync(options, "SUBSCRIBE").ConfigureAwait(false))
{
}
} }
public async Task<XDocument> GetDataAsync(string url) public async Task<XDocument> GetDataAsync(string url)
@ -94,11 +98,14 @@ namespace Emby.Dlna.PlayTo
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName; options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
{ {
using (var reader = new StreamReader(stream, Encoding.UTF8)) using (var stream = response.Content)
{ {
return XDocument.Parse(reader.ReadToEnd(), LoadOptions.PreserveWhitespace); using (var reader = new StreamReader(stream, Encoding.UTF8))
{
return XDocument.Parse(reader.ReadToEnd(), LoadOptions.PreserveWhitespace);
}
} }
} }
} }

View File

@ -279,39 +279,9 @@ namespace Emby.Server.Implementations.HttpClientManager
public async Task<Stream> Get(HttpRequestOptions options) public async Task<Stream> Get(HttpRequestOptions options)
{ {
var response = await GetResponse(options).ConfigureAwait(false); var response = await GetResponse(options).ConfigureAwait(false);
return response.Content; return response.Content;
} }
/// <summary>
/// Performs a GET request and returns the resulting stream
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="resourcePool">The resource pool.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
public Task<Stream> Get(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
{
return Get(new HttpRequestOptions
{
Url = url,
ResourcePool = resourcePool,
CancellationToken = cancellationToken,
BufferContent = resourcePool != null
});
}
/// <summary>
/// Gets the specified URL.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
public Task<Stream> Get(string url, CancellationToken cancellationToken)
{
return Get(url, null, cancellationToken);
}
/// <summary> /// <summary>
/// send as an asynchronous operation. /// send as an asynchronous operation.
/// </summary> /// </summary>
@ -589,26 +559,6 @@ namespace Emby.Server.Implementations.HttpClientManager
return response.Content; return response.Content;
} }
/// <summary>
/// Performs a POST request
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="postData">Params to add to the POST data.</param>
/// <param name="resourcePool">The resource pool.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>stream on success, null on failure</returns>
public Task<Stream> Post(string url, Dictionary<string, string> postData, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
{
return Post(new HttpRequestOptions
{
Url = url,
ResourcePool = resourcePool,
CancellationToken = cancellationToken,
BufferContent = resourcePool != null
}, postData);
}
/// <summary> /// <summary>
/// Downloads the contents of a given url into a temporary location /// Downloads the contents of a given url into a temporary location
/// </summary> /// </summary>
@ -891,18 +841,6 @@ namespace Emby.Server.Implementations.HttpClientManager
} }
} }
/// <summary>
/// Posts the specified URL.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="postData">The post data.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
public Task<Stream> Post(string url, Dictionary<string, string> postData, CancellationToken cancellationToken)
{
return Post(url, postData, null, cancellationToken);
}
private Task<WebResponse> GetResponseAsync(WebRequest request, TimeSpan timeout) private Task<WebResponse> GetResponseAsync(WebRequest request, TimeSpan timeout)
{ {
var taskCompletion = new TaskCompletionSource<WebResponse>(); var taskCompletion = new TaskCompletionSource<WebResponse>();

View File

@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
season.Name = seasonNumber == 0 ? season.Name = seasonNumber == 0 ?
args.LibraryOptions.SeasonZeroDisplayName : args.LibraryOptions.SeasonZeroDisplayName :
string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture)); string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage);
} }
return season; return season;

View File

@ -1463,6 +1463,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_timerProvider.AddOrUpdate(timer, false); _timerProvider.AddOrUpdate(timer, false);
await SaveRecordingMetadata(timer, recordPath, seriesPath).ConfigureAwait(false); await SaveRecordingMetadata(timer, recordPath, seriesPath).ConfigureAwait(false);
CreateRecordingFolders();
TriggerRefresh(recordPath); TriggerRefresh(recordPath);
EnforceKeepUpTo(timer, seriesPath); EnforceKeepUpTo(timer, seriesPath);
}; };

View File

@ -541,27 +541,30 @@ namespace Emby.Server.Implementations.LiveTv.Listings
try try
{ {
using (Stream responce = await Get(options, false, info).ConfigureAwait(false)) using (var httpResponse = await Get(options, false, info).ConfigureAwait(false))
{ {
var root = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.Headends>>(responce); using (Stream responce = httpResponse.Content)
if (root != null)
{ {
foreach (ScheduleDirect.Headends headend in root) var root = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.Headends>>(responce);
if (root != null)
{ {
foreach (ScheduleDirect.Lineup lineup in headend.lineups) foreach (ScheduleDirect.Headends headend in root)
{ {
lineups.Add(new NameIdPair foreach (ScheduleDirect.Lineup lineup in headend.lineups)
{ {
Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name, lineups.Add(new NameIdPair
Id = lineup.uri.Substring(18) {
}); Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name,
Id = lineup.uri.Substring(18)
});
}
} }
} }
} else
else {
{ _logger.Info("No lineups available");
_logger.Info("No lineups available"); }
} }
} }
} }
@ -671,13 +674,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings
return await Post(options, false, providerInfo).ConfigureAwait(false); return await Post(options, false, providerInfo).ConfigureAwait(false);
} }
private async Task<Stream> Get(HttpRequestOptions options, private async Task<HttpResponseInfo> Get(HttpRequestOptions options,
bool enableRetry, bool enableRetry,
ListingsProviderInfo providerInfo) ListingsProviderInfo providerInfo)
{ {
try try
{ {
return await _httpClient.Get(options).ConfigureAwait(false); return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
} }
catch (HttpException ex) catch (HttpException ex)
{ {
@ -797,11 +800,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings
try try
{ {
using (var response = await Get(options, false, null).ConfigureAwait(false)) using (var httpResponse = await Get(options, false, null).ConfigureAwait(false))
{ {
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Lineups>(response); using (var response = httpResponse.Content)
{
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Lineups>(response);
return root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase)); return root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase));
}
} }
} }
catch (HttpException ex) catch (HttpException ex)
@ -879,53 +885,56 @@ namespace Emby.Server.Implementations.LiveTv.Listings
var list = new List<ChannelInfo>(); var list = new List<ChannelInfo>();
using (var response = await Get(httpOptions, true, info).ConfigureAwait(false)) using (var httpResponse = await Get(httpOptions, true, info).ConfigureAwait(false))
{ {
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response); using (var response = httpResponse.Content)
_logger.Info("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
_logger.Info("Mapping Stations to Channel");
var allStations = root.stations ?? new List<ScheduleDirect.Station>();
foreach (ScheduleDirect.Map map in root.map)
{ {
var channelNumber = GetChannelNumber(map); var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
_logger.Info("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
_logger.Info("Mapping Stations to Channel");
var station = allStations.FirstOrDefault(item => string.Equals(item.stationID, map.stationID, StringComparison.OrdinalIgnoreCase)); var allStations = root.stations ?? new List<ScheduleDirect.Station>();
if (station == null)
foreach (ScheduleDirect.Map map in root.map)
{ {
station = new ScheduleDirect.Station var channelNumber = GetChannelNumber(map);
var station = allStations.FirstOrDefault(item => string.Equals(item.stationID, map.stationID, StringComparison.OrdinalIgnoreCase));
if (station == null)
{ {
stationID = map.stationID station = new ScheduleDirect.Station
{
stationID = map.stationID
};
}
var name = channelNumber;
var channelInfo = new ChannelInfo
{
Number = channelNumber,
Name = name
}; };
}
var name = channelNumber; if (station != null)
var channelInfo = new ChannelInfo
{
Number = channelNumber,
Name = name
};
if (station != null)
{
if (!string.IsNullOrWhiteSpace(station.name))
{ {
channelInfo.Name = station.name; if (!string.IsNullOrWhiteSpace(station.name))
{
channelInfo.Name = station.name;
}
channelInfo.Id = station.stationID;
channelInfo.CallSign = station.callsign;
if (station.logo != null)
{
channelInfo.ImageUrl = station.logo.URL;
channelInfo.HasImage = true;
}
} }
channelInfo.Id = station.stationID; list.Add(channelInfo);
channelInfo.CallSign = station.callsign;
if (station.logo != null)
{
channelInfo.ImageUrl = station.logo.URL;
channelInfo.HasImage = true;
}
} }
list.Add(channelInfo);
} }
} }

View File

@ -86,16 +86,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = false BufferContent = false
}; };
using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
{ {
var lineup = JsonSerializer.DeserializeFromStream<List<Channels>>(stream) ?? new List<Channels>(); using (var stream = response.Content)
if (info.ImportFavoritesOnly)
{ {
lineup = lineup.Where(i => i.Favorite).ToList(); var lineup = JsonSerializer.DeserializeFromStream<List<Channels>>(stream) ?? new List<Channels>();
}
return lineup.Where(i => !i.DRM).ToList(); if (info.ImportFavoritesOnly)
{
lineup = lineup.Where(i => i.Favorite).ToList();
}
return lineup.Where(i => !i.DRM).ToList();
}
} }
} }
@ -143,26 +146,29 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
try try
{ {
using (var stream = await _httpClient.Get(new HttpRequestOptions() using (var response = await _httpClient.SendAsync(new HttpRequestOptions()
{ {
Url = string.Format("{0}/discover.json", GetApiUrl(info, false)), Url = string.Format("{0}/discover.json", GetApiUrl(info, false)),
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds), TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds),
BufferContent = false BufferContent = false
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
var response = JsonSerializer.DeserializeFromStream<DiscoverResponse>(stream); using (var stream = response.Content)
if (!string.IsNullOrWhiteSpace(info.Id))
{ {
lock (_modelCache) var discoverResponse = JsonSerializer.DeserializeFromStream<DiscoverResponse>(stream);
{
_modelCache[info.Id] = response;
}
}
return response; if (!string.IsNullOrWhiteSpace(info.Id))
{
lock (_modelCache)
{
_modelCache[info.Id] = discoverResponse;
}
}
return discoverResponse;
}
} }
} }
catch (HttpException ex) catch (HttpException ex)

View File

@ -92,14 +92,17 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}, "GET").ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
Logger.Info("Opened HDHR stream from {0}", url); using (var stream = response.Content)
Logger.Info("Beginning multicastStream.CopyUntilCancelled");
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath));
using (var fileStream = FileSystem.GetFileStream(TempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None))
{ {
StreamHelper.CopyTo(response.Content, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken); Logger.Info("Opened HDHR stream from {0}", url);
Logger.Info("Beginning multicastStream.CopyUntilCancelled");
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(TempFilePath));
using (var fileStream = FileSystem.GetFileStream(TempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None))
{
StreamHelper.CopyTo(stream, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken);
}
} }
} }
} }

View File

@ -315,6 +315,11 @@ namespace Emby.Server.Implementations.Localization
public string GetLocalizedString(string phrase, string culture) public string GetLocalizedString(string phrase, string culture)
{ {
if (string.IsNullOrWhiteSpace(culture))
{
culture = _configurationManager.Configuration.UICulture;
}
var dictionary = GetLocalizationDictionary(culture); var dictionary = GetLocalizationDictionary(culture);
string value; string value;

View File

@ -88,15 +88,18 @@ namespace Emby.Server.Implementations.News
BufferContent = false BufferContent = false
}; };
using (var stream = await _httpClient.Get(requestOptions).ConfigureAwait(false)) using (var response = await _httpClient.SendAsync(requestOptions, "GET").ConfigureAwait(false))
{ {
using (var reader = XmlReader.Create(stream)) using (var stream = response.Content)
{ {
var news = ParseRssItems(reader).ToList(); using (var reader = XmlReader.Create(stream))
{
var news = ParseRssItems(reader).ToList();
_json.SerializeToFile(news, path); _json.SerializeToFile(news, path);
await CreateNotifications(news, lastUpdate, CancellationToken.None).ConfigureAwait(false); await CreateNotifications(news, lastUpdate, CancellationToken.None).ConfigureAwait(false);
}
} }
} }
} }

View File

@ -293,10 +293,13 @@ namespace Emby.Server.Implementations.Security
options.SetPostData(data); options.SetPostData(data);
using (var json = (await _httpClient.Post(options).ConfigureAwait(false)).Content) using (var response = (await _httpClient.Post(options).ConfigureAwait(false)))
{ {
reg = _jsonSerializer.DeserializeFromStream<RegRecord>(json); using (var json = response.Content)
success = true; {
reg = _jsonSerializer.DeserializeFromStream<RegRecord>(json);
success = true;
}
} }
if (reg.registered) if (reg.registered)

View File

@ -66,19 +66,22 @@ namespace Emby.Server.Implementations.Session
return SendMessage(name, new Dictionary<string, string>(), cancellationToken); return SendMessage(name, new Dictionary<string, string>(), cancellationToken);
} }
private Task SendMessage(string name, private async Task SendMessage(string name,
Dictionary<string, string> args, Dictionary<string, string> args,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var url = PostUrl + "/" + name + ToQueryString(args); var url = PostUrl + "/" + name + ToQueryString(args);
return _httpClient.Post(new HttpRequestOptions using ((await _httpClient.Post(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = false BufferContent = false
}); }).ConfigureAwait(false)))
{
}
} }
public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken)

View File

@ -175,13 +175,24 @@ namespace Emby.Server.Implementations.Updates
{ "systemid", _applicationHost.SystemId } { "systemid", _applicationHost.SystemId }
}; };
using (var json = await _httpClient.Post("https://www.mb3admin.com/admin/service/package/retrieveall?includeAllRuntimes=true", data, cancellationToken).ConfigureAwait(false)) var options = new HttpRequestOptions
{ {
cancellationToken.ThrowIfCancellationRequested(); Url = "https://www.mb3admin.com/admin/service/package/retrieveall?includeAllRuntimes=true",
CancellationToken = cancellationToken
};
var packages = _jsonSerializer.DeserializeFromStream<PackageInfo[]>(json); options.SetPostData(data);
return FilterPackages(packages, packageType, applicationVersion); using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false))
{
using (var json = response.Content)
{
cancellationToken.ThrowIfCancellationRequested();
var packages = _jsonSerializer.DeserializeFromStream<PackageInfo[]>(json);
return FilterPackages(packages, packageType, applicationVersion);
}
} }
} }
else else

View File

@ -262,28 +262,29 @@ namespace MediaBrowser.Api.Images
/// <returns>Task.</returns> /// <returns>Task.</returns>
private async Task DownloadImage(string url, Guid urlHash, string pointerCachePath) private async Task DownloadImage(string url, Guid urlHash, string pointerCachePath)
{ {
var result = await _httpClient.GetResponse(new HttpRequestOptions using (var result = await _httpClient.GetResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
BufferContent = false BufferContent = false
}).ConfigureAwait(false); }).ConfigureAwait(false))
var ext = result.ContentType.Split('/').Last();
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
using (var stream = result.Content)
{ {
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) var ext = result.ContentType.Split('/').Last();
{
await stream.CopyToAsync(filestream).ConfigureAwait(false);
}
}
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath)); var fullCachePath = GetFullCachePath(urlHash + "." + ext);
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
using (var stream = result.Content)
{
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await stream.CopyToAsync(filestream).ConfigureAwait(false);
}
}
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath));
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
}
} }
/// <summary> /// <summary>

View File

@ -18,24 +18,6 @@ namespace MediaBrowser.Common.Net
/// <returns>Task{HttpResponseInfo}.</returns> /// <returns>Task{HttpResponseInfo}.</returns>
Task<HttpResponseInfo> GetResponse(HttpRequestOptions options); Task<HttpResponseInfo> GetResponse(HttpRequestOptions options);
/// <summary>
/// Performs a GET request and returns the resulting stream
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="resourcePool">The resource pool.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
Task<Stream> Get(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken);
/// <summary>
/// Gets the specified URL.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
Task<Stream> Get(string url, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Gets the specified options. /// Gets the specified options.
/// </summary> /// </summary>
@ -51,35 +33,6 @@ namespace MediaBrowser.Common.Net
/// <returns>Task{HttpResponseInfo}.</returns> /// <returns>Task{HttpResponseInfo}.</returns>
Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod); Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod);
/// <summary>
/// Performs a POST request
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="postData">Params to add to the POST data.</param>
/// <param name="resourcePool">The resource pool.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>stream on success, null on failure</returns>
/// <exception cref="System.ArgumentNullException">postData</exception>
/// <exception cref="MediaBrowser.Model.Net.HttpException"></exception>
Task<Stream> Post(string url, Dictionary<string, string> postData, SemaphoreSlim resourcePool, CancellationToken cancellationToken);
/// <summary>
/// Posts the specified URL.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="postData">The post data.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
Task<Stream> Post(string url, Dictionary<string, string> postData, CancellationToken cancellationToken);
/// <summary>
/// Posts the specified options with post data
/// </summary>
/// <param name="options">The options</param>
/// <param name="postData">The post data</param>
/// <returns>Task{Stream}</returns>
Task<Stream> Post(HttpRequestOptions options, Dictionary<string, string> postData);
/// <summary> /// <summary>
/// Posts the specified options. /// Posts the specified options.
/// </summary> /// </summary>

View File

@ -40,11 +40,14 @@ namespace MediaBrowser.Common.Updates
options.CacheLength = cacheLength; options.CacheLength = cacheLength;
} }
using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
{ {
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream); using (var stream = response.Content)
{
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename); return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename);
}
} }
} }
@ -110,17 +113,20 @@ namespace MediaBrowser.Common.Updates
BufferContent = false BufferContent = false
}; };
using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
{ {
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream); using (var stream = response.Content)
{
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
obj = obj.Where(i => (i.assets ?? new List<Asset>()).Any(a => IsAsset(a, assetFilename, i.tag_name))).ToArray(); obj = obj.Where(i => (i.assets ?? new List<Asset>()).Any(a => IsAsset(a, assetFilename, i.tag_name))).ToArray();
list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Release)).OrderByDescending(GetVersion).Take(1)); list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Release)).OrderByDescending(GetVersion).Take(1));
list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Beta)).OrderByDescending(GetVersion).Take(1)); list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Beta)).OrderByDescending(GetVersion).Take(1));
list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Dev)).OrderByDescending(GetVersion).Take(1)); list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Dev)).OrderByDescending(GetVersion).Take(1));
return list; return list;
}
} }
} }

View File

@ -179,7 +179,7 @@ namespace MediaBrowser.Providers.BoxSets
RootObject mainResult = null; RootObject mainResult = null;
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -187,7 +187,10 @@ namespace MediaBrowser.Providers.BoxSets
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
mainResult = _json.DeserializeFromStream<RootObject>(json); using (var json = response.Content)
{
mainResult = _json.DeserializeFromStream<RootObject>(json);
}
} }
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@ -204,7 +207,7 @@ namespace MediaBrowser.Providers.BoxSets
url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language);
} }
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -212,7 +215,10 @@ namespace MediaBrowser.Providers.BoxSets
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
mainResult = _json.DeserializeFromStream<RootObject>(json); using (var json = response.Content)
{
mainResult = _json.DeserializeFromStream<RootObject>(json);
}
} }
} }
} }

View File

@ -153,16 +153,16 @@ namespace MediaBrowser.Providers.Manager
public async Task SaveImage(IHasMetadata item, string url, ImageType type, int? imageIndex, CancellationToken cancellationToken) public async Task SaveImage(IHasMetadata item, string url, ImageType type, int? imageIndex, CancellationToken cancellationToken)
{ {
var response = await _httpClient.GetResponse(new HttpRequestOptions using (var response = await _httpClient.GetResponse(new HttpRequestOptions
{ {
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
Url = url, Url = url,
BufferContent = false BufferContent = false
}).ConfigureAwait(false); }).ConfigureAwait(false))
{
await SaveImage(item, response.Content, response.ContentType, type, imageIndex, cancellationToken) await SaveImage(item, response.Content, response.ContentType, type, imageIndex, cancellationToken).ConfigureAwait(false);
.ConfigureAwait(false); }
} }
public Task SaveImage(IHasMetadata item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken) public Task SaveImage(IHasMetadata item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)

View File

@ -274,17 +274,20 @@ namespace MediaBrowser.Providers.Movies
try try
{ {
using (var response = await _httpClient.Get(new HttpRequestOptions using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = true BufferContent = true
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) using (var response = httpResponse.Content)
{ {
await response.CopyToAsync(fileStream).ConfigureAwait(false); using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(fileStream).ConfigureAwait(false);
}
} }
} }
} }

View File

@ -146,7 +146,7 @@ namespace MediaBrowser.Providers.Movies
return _tmdbSettings; return _tmdbSettings;
} }
using (var json = await GetMovieDbResponse(new HttpRequestOptions using (var response = await GetMovieDbResponse(new HttpRequestOptions
{ {
Url = string.Format(TmdbConfigUrl, ApiKey), Url = string.Format(TmdbConfigUrl, ApiKey),
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -154,9 +154,12 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
_tmdbSettings = _jsonSerializer.DeserializeFromStream<TmdbSettingsResult>(json); using (var json = response.Content)
{
_tmdbSettings = _jsonSerializer.DeserializeFromStream<TmdbSettingsResult>(json);
return _tmdbSettings; return _tmdbSettings;
}
} }
} }
@ -339,7 +342,7 @@ namespace MediaBrowser.Providers.Movies
try try
{ {
using (var json = await GetMovieDbResponse(new HttpRequestOptions using (var response = await GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -349,7 +352,10 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
mainResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json); using (var json = response.Content)
{
mainResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
}
} }
} }
catch (HttpException ex) catch (HttpException ex)
@ -381,7 +387,7 @@ namespace MediaBrowser.Providers.Movies
url += "&include_image_language=" + GetImageLanguagesParam(language); url += "&include_image_language=" + GetImageLanguagesParam(language);
} }
using (var json = await GetMovieDbResponse(new HttpRequestOptions using (var response = await GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -391,9 +397,12 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
var englishResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json); using (var json = response.Content)
{
var englishResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
mainResult.overview = englishResult.overview; mainResult.overview = englishResult.overview;
}
} }
} }
@ -407,7 +416,7 @@ namespace MediaBrowser.Providers.Movies
/// <summary> /// <summary>
/// Gets the movie db response. /// Gets the movie db response.
/// </summary> /// </summary>
internal async Task<Stream> GetMovieDbResponse(HttpRequestOptions options) internal async Task<HttpResponseInfo> GetMovieDbResponse(HttpRequestOptions options)
{ {
var delayTicks = (requestIntervalMs * 10000) - (DateTime.UtcNow.Ticks - _lastRequestTicks); var delayTicks = (requestIntervalMs * 10000) - (DateTime.UtcNow.Ticks - _lastRequestTicks);
var delayMs = Math.Min(delayTicks / 10000, requestIntervalMs); var delayMs = Math.Min(delayTicks / 10000, requestIntervalMs);
@ -423,7 +432,7 @@ namespace MediaBrowser.Providers.Movies
options.BufferContent = true; options.BufferContent = true;
options.UserAgent = "Emby/" + _appHost.ApplicationVersion; options.UserAgent = "Emby/" + _appHost.ApplicationVersion;
return await _httpClient.Get(options).ConfigureAwait(false); return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
} }
/// <summary> /// <summary>

View File

@ -154,7 +154,7 @@ namespace MediaBrowser.Providers.Movies
var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, type); var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, type);
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url3, Url = url3,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -162,38 +162,41 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
var searchResults = _json.DeserializeFromStream<TmdbMovieSearchResults>(json); using (var json = response.Content)
{
var searchResults = _json.DeserializeFromStream<TmdbMovieSearchResults>(json);
var results = searchResults.results ?? new List<TmdbMovieSearchResult>(); var results = searchResults.results ?? new List<TmdbMovieSearchResult>();
return results return results
.Select(i => .Select(i =>
{
var remoteResult = new RemoteSearchResult
{ {
SearchProviderName = MovieDbProvider.Current.Name, var remoteResult = new RemoteSearchResult
Name = i.title ?? i.name ?? i.original_title, {
ImageUrl = string.IsNullOrWhiteSpace(i.poster_path) ? null : baseImageUrl + i.poster_path SearchProviderName = MovieDbProvider.Current.Name,
}; Name = i.title ?? i.name ?? i.original_title,
ImageUrl = string.IsNullOrWhiteSpace(i.poster_path) ? null : baseImageUrl + i.poster_path
};
if (!string.IsNullOrWhiteSpace(i.release_date)) if (!string.IsNullOrWhiteSpace(i.release_date))
{ {
DateTime r; DateTime r;
// These dates are always in this exact format // These dates are always in this exact format
if (DateTime.TryParseExact(i.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r)) if (DateTime.TryParseExact(i.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
{ {
remoteResult.PremiereDate = r.ToUniversalTime(); remoteResult.PremiereDate = r.ToUniversalTime();
remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year; remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
}
} }
}
remoteResult.SetProviderId(MetadataProviders.Tmdb, i.id.ToString(EnUs)); remoteResult.SetProviderId(MetadataProviders.Tmdb, i.id.ToString(EnUs));
return remoteResult; return remoteResult;
}) })
.ToList(); .ToList();
}
} }
} }
@ -206,7 +209,7 @@ namespace MediaBrowser.Providers.Movies
var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, "tv"); var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, "tv");
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url3, Url = url3,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -214,38 +217,41 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
var searchResults = _json.DeserializeFromStream<TmdbTvSearchResults>(json); using (var json = response.Content)
{
var searchResults = _json.DeserializeFromStream<TmdbTvSearchResults>(json);
var results = searchResults.results ?? new List<TvResult>(); var results = searchResults.results ?? new List<TvResult>();
return results return results
.Select(i => .Select(i =>
{
var remoteResult = new RemoteSearchResult
{ {
SearchProviderName = MovieDbProvider.Current.Name, var remoteResult = new RemoteSearchResult
Name = i.name ?? i.original_name, {
ImageUrl = string.IsNullOrWhiteSpace(i.poster_path) ? null : baseImageUrl + i.poster_path SearchProviderName = MovieDbProvider.Current.Name,
}; Name = i.name ?? i.original_name,
ImageUrl = string.IsNullOrWhiteSpace(i.poster_path) ? null : baseImageUrl + i.poster_path
};
if (!string.IsNullOrWhiteSpace(i.first_air_date)) if (!string.IsNullOrWhiteSpace(i.first_air_date))
{ {
DateTime r; DateTime r;
// These dates are always in this exact format // These dates are always in this exact format
if (DateTime.TryParseExact(i.first_air_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r)) if (DateTime.TryParseExact(i.first_air_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
{ {
remoteResult.PremiereDate = r.ToUniversalTime(); remoteResult.PremiereDate = r.ToUniversalTime();
remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year; remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
}
} }
}
remoteResult.SetProviderId(MetadataProviders.Tmdb, i.id.ToString(EnUs)); remoteResult.SetProviderId(MetadataProviders.Tmdb, i.id.ToString(EnUs));
return remoteResult; return remoteResult;
}) })
.ToList(); .ToList();
}
} }
} }

View File

@ -161,16 +161,19 @@ namespace MediaBrowser.Providers.Music
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
using (var response = await _httpClient.Get(new HttpRequestOptions using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken CancellationToken = cancellationToken
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) using (var response = httpResponse.Content)
{ {
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false); using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
}
} }
} }
} }

View File

@ -147,19 +147,22 @@ namespace MediaBrowser.Providers.Music
var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId); var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
using (var response = await _httpClient.Get(new HttpRequestOptions using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = true BufferContent = true
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); using (var response = httpResponse.Content)
using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{ {
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
}
} }
} }
} }

View File

@ -251,17 +251,20 @@ namespace MediaBrowser.Providers.Music
try try
{ {
using (var response = await _httpClient.Get(new HttpRequestOptions using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = true BufferContent = true
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
using (var saveFileStream = _fileSystem.GetFileStream(jsonPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) using (var response = httpResponse.Content)
{ {
await response.CopyToAsync(saveFileStream).ConfigureAwait(false); using (var saveFileStream = _fileSystem.GetFileStream(jsonPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(saveFileStream).ConfigureAwait(false);
}
} }
} }
} }

View File

@ -83,9 +83,12 @@ namespace MediaBrowser.Providers.Music
if (!string.IsNullOrWhiteSpace(url)) if (!string.IsNullOrWhiteSpace(url))
{ {
using (var stream = await GetMusicBrainzResponse(url, isNameSearch, forceMusicBrainzProper, cancellationToken).ConfigureAwait(false)) using (var response = await GetMusicBrainzResponse(url, isNameSearch, forceMusicBrainzProper, cancellationToken).ConfigureAwait(false))
{ {
return GetResultsFromResponse(stream); using (var stream = response.Content)
{
return GetResultsFromResponse(stream);
}
} }
} }
@ -226,19 +229,22 @@ namespace MediaBrowser.Providers.Music
WebUtility.UrlEncode(albumName), WebUtility.UrlEncode(albumName),
artistId); artistId);
using (var stream = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false)) using (var response = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
{ {
using (var oReader = new StreamReader(stream, Encoding.UTF8)) using (var stream = response.Content)
{ {
var settings = _xmlSettings.Create(false); using (var oReader = new StreamReader(stream, Encoding.UTF8))
settings.CheckCharacters = false;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var reader = XmlReader.Create(oReader, settings))
{ {
return ReleaseResult.Parse(reader).FirstOrDefault(); var settings = _xmlSettings.Create(false);
settings.CheckCharacters = false;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var reader = XmlReader.Create(oReader, settings))
{
return ReleaseResult.Parse(reader).FirstOrDefault();
}
} }
} }
} }
@ -250,19 +256,22 @@ namespace MediaBrowser.Providers.Music
WebUtility.UrlEncode(albumName), WebUtility.UrlEncode(albumName),
WebUtility.UrlEncode(artistName)); WebUtility.UrlEncode(artistName));
using (var stream = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false)) using (var response = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
{ {
using (var oReader = new StreamReader(stream, Encoding.UTF8)) using (var stream = response.Content)
{ {
var settings = _xmlSettings.Create(false); using (var oReader = new StreamReader(stream, Encoding.UTF8))
settings.CheckCharacters = false;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var reader = XmlReader.Create(oReader, settings))
{ {
return ReleaseResult.Parse(reader).FirstOrDefault(); var settings = _xmlSettings.Create(false);
settings.CheckCharacters = false;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var reader = XmlReader.Create(oReader, settings))
{
return ReleaseResult.Parse(reader).FirstOrDefault();
}
} }
} }
} }
@ -431,23 +440,26 @@ namespace MediaBrowser.Providers.Music
{ {
var url = string.Format("/ws/2/release?release-group={0}", releaseGroupId); var url = string.Format("/ws/2/release?release-group={0}", releaseGroupId);
using (var stream = await GetMusicBrainzResponse(url, true, true, cancellationToken).ConfigureAwait(false)) using (var response = await GetMusicBrainzResponse(url, true, true, cancellationToken).ConfigureAwait(false))
{ {
using (var oReader = new StreamReader(stream, Encoding.UTF8)) using (var stream = response.Content)
{ {
var settings = _xmlSettings.Create(false); using (var oReader = new StreamReader(stream, Encoding.UTF8))
settings.CheckCharacters = false;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var reader = XmlReader.Create(oReader, settings))
{ {
var result = ReleaseResult.Parse(reader).FirstOrDefault(); var settings = _xmlSettings.Create(false);
if (result != null) settings.CheckCharacters = false;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var reader = XmlReader.Create(oReader, settings))
{ {
return result.ReleaseId; var result = ReleaseResult.Parse(reader).FirstOrDefault();
if (result != null)
{
return result.ReleaseId;
}
} }
} }
} }
@ -466,53 +478,56 @@ namespace MediaBrowser.Providers.Music
{ {
var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId); var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
using (var stream = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false)) using (var response = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
{ {
using (var oReader = new StreamReader(stream, Encoding.UTF8)) using (var stream = response.Content)
{ {
var settings = _xmlSettings.Create(false); using (var oReader = new StreamReader(stream, Encoding.UTF8))
settings.CheckCharacters = false;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var reader = XmlReader.Create(oReader, settings))
{ {
reader.MoveToContent(); var settings = _xmlSettings.Create(false);
reader.Read();
// Loop through each element settings.CheckCharacters = false;
while (!reader.EOF && reader.ReadState == ReadState.Interactive) settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var reader = XmlReader.Create(oReader, settings))
{ {
if (reader.NodeType == XmlNodeType.Element) reader.MoveToContent();
reader.Read();
// Loop through each element
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{ {
switch (reader.Name) if (reader.NodeType == XmlNodeType.Element)
{ {
case "release-group-list": switch (reader.Name)
{ {
if (reader.IsEmptyElement) case "release-group-list":
{ {
reader.Read(); if (reader.IsEmptyElement)
continue; {
reader.Read();
continue;
}
using (var subReader = reader.ReadSubtree())
{
return GetFirstReleaseGroupId(subReader);
}
} }
using (var subReader = reader.ReadSubtree()) default:
{ {
return GetFirstReleaseGroupId(subReader); reader.Skip();
break;
} }
} }
default: }
{ else
reader.Skip(); {
break; reader.Read();
}
} }
} }
else return null;
{
reader.Read();
}
} }
return null;
} }
} }
} }
@ -598,11 +613,14 @@ namespace MediaBrowser.Providers.Music
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion
}; };
using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false))
{ {
var results = _json.DeserializeFromStream<List<MbzUrl>>(stream); using (var stream = response.Content)
{
var results = _json.DeserializeFromStream<List<MbzUrl>>(stream);
list = results; list = results;
}
} }
_lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks; _lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks;
} }
@ -626,7 +644,7 @@ namespace MediaBrowser.Providers.Music
return list; return list;
} }
internal Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken) internal Task<HttpResponseInfo> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
{ {
return GetMusicBrainzResponse(url, isSearch, false, cancellationToken); return GetMusicBrainzResponse(url, isSearch, false, cancellationToken);
} }
@ -634,7 +652,7 @@ namespace MediaBrowser.Providers.Music
/// <summary> /// <summary>
/// Gets the music brainz response. /// Gets the music brainz response.
/// </summary> /// </summary>
internal async Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, bool forceMusicBrainzProper, CancellationToken cancellationToken) internal async Task<HttpResponseInfo> GetMusicBrainzResponse(string url, bool isSearch, bool forceMusicBrainzProper, CancellationToken cancellationToken)
{ {
var urlInfo = await GetMbzUrl(forceMusicBrainzProper).ConfigureAwait(false); var urlInfo = await GetMbzUrl(forceMusicBrainzProper).ConfigureAwait(false);
var throttleMs = urlInfo.throttleMs; var throttleMs = urlInfo.throttleMs;
@ -656,7 +674,7 @@ namespace MediaBrowser.Providers.Music
BufferContent = throttleMs > 0 BufferContent = throttleMs > 0
}; };
return await _httpClient.Get(options).ConfigureAwait(false); return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
} }
public int Order public int Order

View File

@ -35,10 +35,12 @@ namespace MediaBrowser.Providers.Music
{ {
var url = string.Format("/ws/2/artist/?query=arid:{0}", musicBrainzId); var url = string.Format("/ws/2/artist/?query=arid:{0}", musicBrainzId);
using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken) using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
.ConfigureAwait(false))
{ {
return GetResultsFromResponse(stream); using (var stream = response.Content)
{
return GetResultsFromResponse(stream);
}
} }
} }
else else
@ -48,13 +50,16 @@ namespace MediaBrowser.Providers.Music
var url = String.Format("/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch)); var url = String.Format("/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch));
using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false)) using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
{ {
var results = GetResultsFromResponse(stream); using (var stream = response.Content)
if (results.Count > 0)
{ {
return results; var results = GetResultsFromResponse(stream);
if (results.Count > 0)
{
return results;
}
} }
} }
@ -63,9 +68,12 @@ namespace MediaBrowser.Providers.Music
// Try again using the search with accent characters url // Try again using the search with accent characters url
url = String.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); url = String.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false)) using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
{ {
return GetResultsFromResponse(stream); using (var stream = response.Content)
{
return GetResultsFromResponse(stream);
}
} }
} }
} }

View File

@ -126,65 +126,68 @@ namespace MediaBrowser.Providers.Omdb
var url = OmdbProvider.GetOmdbUrl(urlQuery, cancellationToken); var url = OmdbProvider.GetOmdbUrl(urlQuery, cancellationToken);
using (var stream = await OmdbProvider.GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false)) using (var response = await OmdbProvider.GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{ {
var resultList = new List<SearchResult>(); using (var stream = response.Content)
if (isSearch)
{ {
var searchResultList = _jsonSerializer.DeserializeFromStream<SearchResultList>(stream); var resultList = new List<SearchResult>();
if (searchResultList != null && searchResultList.Search != null)
if (isSearch)
{ {
resultList.AddRange(searchResultList.Search); var searchResultList = _jsonSerializer.DeserializeFromStream<SearchResultList>(stream);
if (searchResultList != null && searchResultList.Search != null)
{
resultList.AddRange(searchResultList.Search);
}
} }
else
{
var result = _jsonSerializer.DeserializeFromStream<SearchResult>(stream);
if (string.Equals(result.Response, "true", StringComparison.OrdinalIgnoreCase))
{
resultList.Add(result);
}
}
return resultList.Select(result =>
{
var item = new RemoteSearchResult
{
IndexNumber = searchInfo.IndexNumber,
Name = result.Title,
ParentIndexNumber = searchInfo.ParentIndexNumber,
SearchProviderName = Name
};
if (episodeSearchInfo != null && episodeSearchInfo.IndexNumberEnd.HasValue)
{
item.IndexNumberEnd = episodeSearchInfo.IndexNumberEnd.Value;
}
item.SetProviderId(MetadataProviders.Imdb, result.imdbID);
int parsedYear;
if (result.Year.Length > 0
&& int.TryParse(result.Year.Substring(0, Math.Min(result.Year.Length, 4)), NumberStyles.Any, CultureInfo.InvariantCulture, out parsedYear))
{
item.ProductionYear = parsedYear;
}
DateTime released;
if (!string.IsNullOrEmpty(result.Released)
&& DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out released))
{
item.PremiereDate = released;
}
if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase))
{
item.ImageUrl = result.Poster;
}
return item;
});
} }
else
{
var result = _jsonSerializer.DeserializeFromStream<SearchResult>(stream);
if (string.Equals(result.Response, "true", StringComparison.OrdinalIgnoreCase))
{
resultList.Add(result);
}
}
return resultList.Select(result =>
{
var item = new RemoteSearchResult
{
IndexNumber = searchInfo.IndexNumber,
Name = result.Title,
ParentIndexNumber = searchInfo.ParentIndexNumber,
SearchProviderName = Name
};
if (episodeSearchInfo != null && episodeSearchInfo.IndexNumberEnd.HasValue)
{
item.IndexNumberEnd = episodeSearchInfo.IndexNumberEnd.Value;
}
item.SetProviderId(MetadataProviders.Imdb, result.imdbID);
int parsedYear;
if (result.Year.Length > 0
&& int.TryParse(result.Year.Substring(0, Math.Min(result.Year.Length, 4)), NumberStyles.Any, CultureInfo.InvariantCulture, out parsedYear))
{
item.ProductionYear = parsedYear;
}
DateTime released;
if (!string.IsNullOrEmpty(result.Released)
&& DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out released))
{
item.PremiereDate = released;
}
if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase))
{
item.ImageUrl = result.Poster;
}
return item;
});
} }
} }

View File

@ -301,11 +301,14 @@ namespace MediaBrowser.Providers.Omdb
var url = GetOmdbUrl(string.Format("i={0}&plot=short&tomatoes=true&r=json", imdbParam), cancellationToken); var url = GetOmdbUrl(string.Format("i={0}&plot=short&tomatoes=true&r=json", imdbParam), cancellationToken);
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false)) using (var response = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{ {
var rootObject = _jsonSerializer.DeserializeFromStream<RootObject>(stream); using (var stream = response.Content)
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); {
_jsonSerializer.SerializeToFile(rootObject, path); var rootObject = _jsonSerializer.DeserializeFromStream<RootObject>(stream);
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(rootObject, path);
}
} }
return path; return path;
@ -335,25 +338,28 @@ namespace MediaBrowser.Providers.Omdb
var url = GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), cancellationToken); var url = GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), cancellationToken);
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false)) using (var response = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{ {
var rootObject = _jsonSerializer.DeserializeFromStream<SeasonRootObject>(stream); using (var stream = response.Content)
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); {
_jsonSerializer.SerializeToFile(rootObject, path); var rootObject = _jsonSerializer.DeserializeFromStream<SeasonRootObject>(stream);
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(rootObject, path);
}
} }
return path; return path;
} }
public static Task<Stream> GetOmdbResponse(IHttpClient httpClient, string url, CancellationToken cancellationToken) public static Task<HttpResponseInfo> GetOmdbResponse(IHttpClient httpClient, string url, CancellationToken cancellationToken)
{ {
return httpClient.Get(new HttpRequestOptions return httpClient.SendAsync(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = true, BufferContent = true,
EnableDefaultUserAgent = true EnableDefaultUserAgent = true
}); }, "GET");
} }
internal string GetDataFilePath(string imdbId) internal string GetDataFilePath(string imdbId)

View File

@ -91,7 +91,7 @@ namespace MediaBrowser.Providers.People
var url = string.Format(@"https://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), MovieDbProvider.ApiKey); var url = string.Format(@"https://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), MovieDbProvider.ApiKey);
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -99,10 +99,13 @@ namespace MediaBrowser.Providers.People
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
var result = _jsonSerializer.DeserializeFromStream<PersonSearchResults>(json) ?? using (var json = response.Content)
new PersonSearchResults(); {
var result = _jsonSerializer.DeserializeFromStream<PersonSearchResults>(json) ??
new PersonSearchResults();
return result.Results.Select(i => GetSearchResult(i, tmdbImageUrl)); return result.Results.Select(i => GetSearchResult(i, tmdbImageUrl));
}
} }
} }
@ -223,7 +226,7 @@ namespace MediaBrowser.Providers.People
var url = string.Format(@"https://api.themoviedb.org/3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids", MovieDbProvider.ApiKey, id); var url = string.Format(@"https://api.themoviedb.org/3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids", MovieDbProvider.ApiKey, id);
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -231,11 +234,14 @@ namespace MediaBrowser.Providers.People
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath)); using (var json = response.Content)
using (var fs = _fileSystem.GetFileStream(dataFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{ {
await json.CopyToAsync(fs).ConfigureAwait(false); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
using (var fs = _fileSystem.GetFileStream(dataFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await json.CopyToAsync(fs).ConfigureAwait(false);
}
} }
} }
} }

View File

@ -316,17 +316,20 @@ namespace MediaBrowser.Providers.TV
try try
{ {
using (var response = await _httpClient.Get(new HttpRequestOptions using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = true BufferContent = true
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) using (var response = httpResponse.Content)
{ {
await response.CopyToAsync(fileStream).ConfigureAwait(false); using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(fileStream).ConfigureAwait(false);
}
} }
} }
} }

View File

@ -125,7 +125,7 @@ namespace MediaBrowser.Providers.TV
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -133,7 +133,10 @@ namespace MediaBrowser.Providers.TV
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
return _jsonSerializer.DeserializeFromStream<RootObject>(json); using (var json = response.Content)
{
return _jsonSerializer.DeserializeFromStream<RootObject>(json);
}
} }
} }

View File

@ -214,7 +214,7 @@ namespace MediaBrowser.Providers.TV
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -222,7 +222,10 @@ namespace MediaBrowser.Providers.TV
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
return _jsonSerializer.DeserializeFromStream<RootObject>(json); using (var json = response.Content)
{
return _jsonSerializer.DeserializeFromStream<RootObject>(json);
}
} }
} }

View File

@ -352,7 +352,7 @@ namespace MediaBrowser.Providers.TV
RootObject mainResult; RootObject mainResult;
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -360,11 +360,14 @@ namespace MediaBrowser.Providers.TV
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
mainResult = _jsonSerializer.DeserializeFromStream<RootObject>(json); using (var json = response.Content)
if (!string.IsNullOrEmpty(language))
{ {
mainResult.ResultLanguage = language; mainResult = _jsonSerializer.DeserializeFromStream<RootObject>(json);
if (!string.IsNullOrEmpty(language))
{
mainResult.ResultLanguage = language;
}
} }
} }
@ -386,7 +389,7 @@ namespace MediaBrowser.Providers.TV
url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language);
} }
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -394,10 +397,13 @@ namespace MediaBrowser.Providers.TV
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
var englishResult = _jsonSerializer.DeserializeFromStream<RootObject>(json); using (var json = response.Content)
{
var englishResult = _jsonSerializer.DeserializeFromStream<RootObject>(json);
mainResult.overview = englishResult.overview; mainResult.overview = englishResult.overview;
mainResult.ResultLanguage = "en"; mainResult.ResultLanguage = "en";
}
} }
} }
@ -449,7 +455,7 @@ namespace MediaBrowser.Providers.TV
MovieDbProvider.ApiKey, MovieDbProvider.ApiKey,
externalSource); externalSource);
using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions using (var response = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
@ -457,27 +463,30 @@ namespace MediaBrowser.Providers.TV
}).ConfigureAwait(false)) }).ConfigureAwait(false))
{ {
var result = _jsonSerializer.DeserializeFromStream<MovieDbSearch.ExternalIdLookupResult>(json); using (var json = response.Content)
if (result != null && result.tv_results != null)
{ {
var tv = result.tv_results.FirstOrDefault(); var result = _jsonSerializer.DeserializeFromStream<MovieDbSearch.ExternalIdLookupResult>(json);
if (tv != null) if (result != null && result.tv_results != null)
{ {
var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); var tv = result.tv_results.FirstOrDefault();
var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original";
var remoteResult = new RemoteSearchResult if (tv != null)
{ {
Name = tv.name, var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
SearchProviderName = Name, var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original";
ImageUrl = string.IsNullOrWhiteSpace(tv.poster_path) ? null : tmdbImageUrl + tv.poster_path
};
remoteResult.SetProviderId(MetadataProviders.Tmdb, tv.id.ToString(_usCulture)); var remoteResult = new RemoteSearchResult
{
Name = tv.name,
SearchProviderName = Name,
ImageUrl = string.IsNullOrWhiteSpace(tv.poster_path) ? null : tmdbImageUrl + tv.poster_path
};
return remoteResult; remoteResult.SetProviderId(MetadataProviders.Tmdb, tv.id.ToString(_usCulture));
return remoteResult;
}
} }
} }
} }

View File

@ -142,16 +142,20 @@ namespace MediaBrowser.Providers.TV
if (string.IsNullOrEmpty(lastUpdateTime)) if (string.IsNullOrEmpty(lastUpdateTime))
{ {
// First get tvdb server time // First get tvdb server time
using (var stream = await _httpClient.Get(new HttpRequestOptions using (var response = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = ServerTimeUrl, Url = ServerTimeUrl,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
EnableHttpCompression = true, EnableHttpCompression = true,
BufferContent = false BufferContent = false
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
newUpdateTime = GetUpdateTime(stream); // First get tvdb server time
using (var stream = response.Content)
{
newUpdateTime = GetUpdateTime(stream);
}
} }
existingDirectories.AddRange(missingSeries); existingDirectories.AddRange(missingSeries);
@ -238,23 +242,26 @@ namespace MediaBrowser.Providers.TV
private async Task<Tuple<IEnumerable<string>, string>> GetSeriesIdsToUpdate(IEnumerable<string> existingSeriesIds, string lastUpdateTime, CancellationToken cancellationToken) private async Task<Tuple<IEnumerable<string>, string>> GetSeriesIdsToUpdate(IEnumerable<string> existingSeriesIds, string lastUpdateTime, CancellationToken cancellationToken)
{ {
// First get last time // First get last time
using (var stream = await _httpClient.Get(new HttpRequestOptions using (var response = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = string.Format(UpdatesUrl, lastUpdateTime), Url = string.Format(UpdatesUrl, lastUpdateTime),
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
EnableHttpCompression = true, EnableHttpCompression = true,
BufferContent = false BufferContent = false
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
var data = GetUpdatedSeriesIdList(stream); using (var stream = response.Content)
{
var data = GetUpdatedSeriesIdList(stream);
var existingDictionary = existingSeriesIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); var existingDictionary = existingSeriesIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
var seriesList = data.Item1 var seriesList = data.Item1
.Where(i => !string.IsNullOrWhiteSpace(i) && existingDictionary.ContainsKey(i)); .Where(i => !string.IsNullOrWhiteSpace(i) && existingDictionary.ContainsKey(i));
return new Tuple<IEnumerable<string>, string>(seriesList, data.Item2); return new Tuple<IEnumerable<string>, string>(seriesList, data.Item2);
}
} }
} }

View File

@ -216,24 +216,27 @@ namespace MediaBrowser.Providers.TV
var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, NormalizeLanguage(preferredMetadataLanguage)); var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, NormalizeLanguage(preferredMetadataLanguage));
using (var zipStream = await _httpClient.Get(new HttpRequestOptions using (var response = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = false BufferContent = false
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
// Delete existing files using (var zipStream = response.Content)
DeleteXmlFiles(seriesDataPath);
// Copy to memory stream because we need a seekable stream
using (var ms = _memoryStreamProvider.CreateNew())
{ {
await zipStream.CopyToAsync(ms).ConfigureAwait(false); // Delete existing files
DeleteXmlFiles(seriesDataPath);
ms.Position = 0; // Copy to memory stream because we need a seekable stream
_zipClient.ExtractAllFromZip(ms, seriesDataPath, true); using (var ms = _memoryStreamProvider.CreateNew())
{
await zipStream.CopyToAsync(ms).ConfigureAwait(false);
ms.Position = 0;
_zipClient.ExtractAllFromZip(ms, seriesDataPath, true);
}
} }
} }
@ -260,15 +263,18 @@ namespace MediaBrowser.Providers.TV
{ {
var url = string.Format(GetSeriesByImdbId, id, NormalizeLanguage(language)); var url = string.Format(GetSeriesByImdbId, id, NormalizeLanguage(language));
using (var result = await _httpClient.Get(new HttpRequestOptions using (var response = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = false BufferContent = false
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
return FindSeriesId(result); using (var result = response.Content)
{
return FindSeriesId(result);
}
} }
} }
@ -514,64 +520,67 @@ namespace MediaBrowser.Providers.TV
var comparableName = GetComparableName(name); var comparableName = GetComparableName(name);
using (var stream = await _httpClient.Get(new HttpRequestOptions using (var response = await _httpClient.SendAsync(new HttpRequestOptions
{ {
Url = url, Url = url,
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = false BufferContent = false
}).ConfigureAwait(false)) }, "GET").ConfigureAwait(false))
{ {
var settings = _xmlSettings.Create(false); using (var stream = response.Content)
settings.CheckCharacters = false;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
{ {
// Use XmlReader for best performance var settings = _xmlSettings.Create(false);
using (var reader = XmlReader.Create(streamReader, settings))
settings.CheckCharacters = false;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreComments = true;
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
{ {
reader.MoveToContent(); // Use XmlReader for best performance
reader.Read(); using (var reader = XmlReader.Create(streamReader, settings))
// Loop through each element
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{ {
cancellationToken.ThrowIfCancellationRequested(); reader.MoveToContent();
reader.Read();
if (reader.NodeType == XmlNodeType.Element) // Loop through each element
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{ {
switch (reader.Name) cancellationToken.ThrowIfCancellationRequested();
if (reader.NodeType == XmlNodeType.Element)
{ {
case "Series": switch (reader.Name)
{ {
if (reader.IsEmptyElement) case "Series":
{ {
reader.Read(); if (reader.IsEmptyElement)
continue;
}
using (var subtree = reader.ReadSubtree())
{
var searchResult = GetSeriesSearchResultFromSubTree(subtree, comparableName);
if (searchResult != null)
{ {
searchResult.SearchProviderName = Name; reader.Read();
searchResults.Add(searchResult); continue;
} }
using (var subtree = reader.ReadSubtree())
{
var searchResult = GetSeriesSearchResultFromSubTree(subtree, comparableName);
if (searchResult != null)
{
searchResult.SearchProviderName = Name;
searchResults.Add(searchResult);
}
}
break;
} }
break;
}
default: default:
reader.Skip(); reader.Skip();
break; break;
}
}
else
{
reader.Read();
} }
}
else
{
reader.Read();
} }
} }
} }

View File

@ -33,6 +33,7 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using System.Net.Sockets; using System.Net.Sockets;
using System.Net; using System.Net;
using System.Threading.Tasks;
namespace Mono.Nat namespace Mono.Nat
{ {

View File

@ -67,7 +67,6 @@
<Compile Include="Upnp\Messages\Responses\CreatePortMappingResponseMessage.cs" /> <Compile Include="Upnp\Messages\Responses\CreatePortMappingResponseMessage.cs" />
<Compile Include="Upnp\Messages\UpnpMessage.cs" /> <Compile Include="Upnp\Messages\UpnpMessage.cs" />
<Compile Include="Upnp\Searchers\UpnpSearcher.cs" /> <Compile Include="Upnp\Searchers\UpnpSearcher.cs" />
<Compile Include="Upnp\Upnp.cs" />
<Compile Include="Upnp\UpnpNatDevice.cs" /> <Compile Include="Upnp\UpnpNatDevice.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -208,14 +208,14 @@ namespace Mono.Nat
} }
} }
public static void Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint, NatProtocol protocol) public static async Task Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint, NatProtocol protocol)
{ {
switch (protocol) switch (protocol)
{ {
case NatProtocol.Upnp: case NatProtocol.Upnp:
var searcher = new UpnpSearcher(Logger, HttpClient); var searcher = new UpnpSearcher(Logger, HttpClient);
searcher.DeviceFound += Searcher_DeviceFound; searcher.DeviceFound += Searcher_DeviceFound;
searcher.Handle(localAddress, deviceInfo, endpoint); await searcher.Handle(localAddress, deviceInfo, endpoint).ConfigureAwait(false);
break; break;
default: default:
throw new ArgumentException("Unexpected protocol: " + protocol); throw new ArgumentException("Unexpected protocol: " + protocol);

View File

@ -42,13 +42,13 @@ namespace Mono.Nat
{ {
internal class PmpSearcher : ISearcher internal class PmpSearcher : ISearcher
{ {
static PmpSearcher instance = new PmpSearcher(); static PmpSearcher instance = new PmpSearcher();
public static PmpSearcher Instance public static PmpSearcher Instance
{ {
get { return instance; } get { return instance; }
} }
private int timeout; private int timeout;
private DateTime nextSearch; private DateTime nextSearch;
@ -143,21 +143,21 @@ namespace Mono.Nat
} }
public async void Search() public async void Search()
{ {
foreach (UdpClient s in sockets) foreach (UdpClient s in sockets)
{ {
try try
{ {
await Search(s).ConfigureAwait(false); await Search(s).ConfigureAwait(false);
} }
catch catch
{ {
// Ignore any search errors // Ignore any search errors
} }
} }
} }
async Task Search (UdpClient client) async Task Search(UdpClient client)
{ {
// Sort out the time for the next search first. The spec says the // Sort out the time for the next search first. The spec says the
// timeout should double after each attempt. Once it reaches 64 seconds // timeout should double after each attempt. Once it reaches 64 seconds
@ -175,10 +175,10 @@ namespace Mono.Nat
// The nat-pmp search message. Must be sent to GatewayIP:53531 // The nat-pmp search message. Must be sent to GatewayIP:53531
byte[] buffer = new byte[] { PmpConstants.Version, PmpConstants.OperationCode }; byte[] buffer = new byte[] { PmpConstants.Version, PmpConstants.OperationCode };
foreach (IPEndPoint gatewayEndpoint in gatewayLists[client]) foreach (IPEndPoint gatewayEndpoint in gatewayLists[client])
{ {
await client.SendAsync(buffer, buffer.Length, gatewayEndpoint).ConfigureAwait(false); await client.SendAsync(buffer, buffer.Length, gatewayEndpoint).ConfigureAwait(false);
} }
} }
bool IsSearchAddress(IPAddress address) bool IsSearchAddress(IPAddress address)

View File

@ -39,6 +39,7 @@ using System.Net.NetworkInformation;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using System.Threading.Tasks;
namespace Mono.Nat namespace Mono.Nat
{ {
@ -61,7 +62,7 @@ namespace Mono.Nat
{ {
} }
public void Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint) public async Task Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint)
{ {
// No matter what, this method should never throw an exception. If something goes wrong // No matter what, this method should never throw an exception. If something goes wrong
// we should still be in a position to handle the next reply correctly. // we should still be in a position to handle the next reply correctly.
@ -82,6 +83,8 @@ namespace Mono.Nat
UpnpNatDevice d = new UpnpNatDevice(localAddress, deviceInfo, endpoint, string.Empty, _logger, _httpClient); UpnpNatDevice d = new UpnpNatDevice(localAddress, deviceInfo, endpoint, string.Empty, _logger, _httpClient);
NatUtility.Log("Fetching service list: {0}", d.HostEndPoint); NatUtility.Log("Fetching service list: {0}", d.HostEndPoint);
await d.GetServicesList().ConfigureAwait(false);
OnDeviceFound(new DeviceEventArgs(d)); OnDeviceFound(new DeviceEventArgs(d));
} }
catch (Exception ex) catch (Exception ex)

View File

@ -1,95 +0,0 @@
//
// Authors:
// Alan McGovern alan.mcgovern@gmail.com
// Ben Motmans <ben.motmans@gmail.com>
// Nicholas Terry <nick.i.terry@gmail.com>
//
// Copyright (C) 2006 Alan McGovern
// Copyright (C) 2007 Ben Motmans
// Copyright (C) 2014 Nicholas Terry
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging;
namespace Mono.Nat.Upnp
{
internal class Upnp
{
protected readonly ILogger Logger;
protected readonly IHttpClient HttpClient;
public Upnp(ILogger logger, IHttpClient httpClient)
{
Logger = logger;
HttpClient = httpClient;
}
public virtual Task<UpnpNatDevice> Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
{
// Convert it to a string for easy parsing
string dataString = null;
string urn;
dataString = Encoding.UTF8.GetString(response);
if (NatUtility.Verbose)
NatUtility.Log("UPnP Response: {0}", dataString);
/* For UPnP Port Mapping we need ot find either WANPPPConnection or WANIPConnection.
Any other device type is no good to us for this purpose. See the IGP overview paper
page 5 for an overview of device types and their hierarchy.
http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf */
/* TODO: Currently we are assuming version 1 of the protocol. We should figure out which
version it is and apply the correct URN. */
/* Some routers don't correctly implement the version ID on the URN, so we only search for the type
prefix. */
string log = "UPnP Response: Router advertised a '{0}' service";
StringComparison c = StringComparison.OrdinalIgnoreCase;
if (dataString.IndexOf("urn:schemas-upnp-org:service:WANIPConnection:", c) != -1)
{
urn = "urn:schemas-upnp-org:service:WANIPConnection:1";
NatUtility.Log(log, "urn:schemas-upnp-org:service:WANIPConnection:1");
}
else if (dataString.IndexOf("urn:schemas-upnp-org:service:WANPPPConnection:", c) != -1)
{
urn = "urn:schemas-upnp-org:service:WANPPPConnection:1";
NatUtility.Log(log, "urn:schemas-upnp-org:service:WANPPPConnection:");
}
else
throw new NotSupportedException("Received non-supported device type");
// We have an internet gateway device now
var device = new UpnpNatDevice(localAddress, dataString, urn, Logger, HttpClient);
return Task.FromResult(device);
}
}
}

View File

@ -90,52 +90,101 @@ namespace Mono.Nat.Upnp
} }
} }
internal UpnpNatDevice(IPAddress localAddress, string deviceDetails, string serviceType, ILogger logger, IHttpClient httpClient) public async Task GetServicesList()
{ {
_logger = logger; // Create a HTTPWebRequest to download the list of services the device offers
_httpClient = httpClient; var message = new GetServicesMessage(this.serviceDescriptionUrl, this.hostEndPoint, _logger);
this.LastSeen = DateTime.Now;
this.localAddress = localAddress;
// Split the string at the "location" section so i can extract the ipaddress and service description url using (var response = await _httpClient.SendAsync(message.Encode(), message.Method).ConfigureAwait(false))
string locationDetails = deviceDetails.Substring(deviceDetails.IndexOf("Location", StringComparison.OrdinalIgnoreCase) + 9).Split('\r')[0];
this.serviceType = serviceType;
// Make sure we have no excess whitespace
locationDetails = locationDetails.Trim();
// FIXME: Is this reliable enough. What if we get a hostname as opposed to a proper http address
// Are we going to get addresses with the "http://" attached?
if (locationDetails.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
{ {
NatUtility.Log("Found device at: {0}", locationDetails); OnServicesReceived(response);
// This bit strings out the "http://" from the string
locationDetails = locationDetails.Substring(7);
// We then split off the end of the string to get something like: 192.168.0.3:241 in our string
string hostAddressAndPort = locationDetails.Remove(locationDetails.IndexOf('/'));
// From this we parse out the IP address and Port
if (hostAddressAndPort.IndexOf(':') > 0)
{
this.hostEndPoint = new IPEndPoint(IPAddress.Parse(hostAddressAndPort.Remove(hostAddressAndPort.IndexOf(':'))),
Convert.ToUInt16(hostAddressAndPort.Substring(hostAddressAndPort.IndexOf(':') + 1), System.Globalization.CultureInfo.InvariantCulture));
}
else
{
// there is no port specified, use default port (80)
this.hostEndPoint = new IPEndPoint(IPAddress.Parse(hostAddressAndPort), 80);
}
NatUtility.Log("Parsed device as: {0}", this.hostEndPoint.ToString());
// The service description URL is the remainder of the "locationDetails" string. The bit that was originally after the ip
// and port information
this.serviceDescriptionUrl = locationDetails.Substring(locationDetails.IndexOf('/'));
} }
else }
private void OnServicesReceived(HttpResponseInfo response)
{
int abortCount = 0;
int bytesRead = 0;
byte[] buffer = new byte[10240];
StringBuilder servicesXml = new StringBuilder();
XmlDocument xmldoc = new XmlDocument();
using (var s = response.Content)
{ {
logger.Warn("Couldn't decode address: " + deviceDetails); if (response.StatusCode != HttpStatusCode.OK)
{
NatUtility.Log("{0}: Couldn't get services list: {1}", HostEndPoint, response.StatusCode);
return; // FIXME: This the best thing to do??
}
while (true)
{
bytesRead = s.Read(buffer, 0, buffer.Length);
servicesXml.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead));
try
{
xmldoc.LoadXml(servicesXml.ToString());
break;
}
catch (XmlException)
{
// If we can't receive the entire XML within 500ms, then drop the connection
// Unfortunately not all routers supply a valid ContentLength (mine doesn't)
// so this hack is needed to keep testing our recieved data until it gets successfully
// parsed by the xmldoc. Without this, the code will never pick up my router.
if (abortCount++ > 50)
{
return;
}
NatUtility.Log("{0}: Couldn't parse services list", HostEndPoint);
System.Threading.Thread.Sleep(10);
}
}
NatUtility.Log("{0}: Parsed services list", HostEndPoint);
XmlNamespaceManager ns = new XmlNamespaceManager(xmldoc.NameTable);
ns.AddNamespace("ns", "urn:schemas-upnp-org:device-1-0");
XmlNodeList nodes = xmldoc.SelectNodes("//*/ns:serviceList", ns);
foreach (XmlNode node in nodes)
{
//Go through each service there
foreach (XmlNode service in node.ChildNodes)
{
//If the service is a WANIPConnection, then we have what we want
string type = service["serviceType"].InnerText;
NatUtility.Log("{0}: Found service: {1}", HostEndPoint, type);
StringComparison c = StringComparison.OrdinalIgnoreCase;
// TODO: Add support for version 2 of UPnP.
if (type.Equals("urn:schemas-upnp-org:service:WANPPPConnection:1", c) ||
type.Equals("urn:schemas-upnp-org:service:WANIPConnection:1", c))
{
this.controlUrl = service["controlURL"].InnerText;
NatUtility.Log("{0}: Found upnp service at: {1}", HostEndPoint, controlUrl);
try
{
Uri u = new Uri(controlUrl);
if (u.IsAbsoluteUri)
{
EndPoint old = hostEndPoint;
this.hostEndPoint = new IPEndPoint(IPAddress.Parse(u.Host), u.Port);
NatUtility.Log("{0}: Absolute URI detected. Host address is now: {1}", old, HostEndPoint);
this.controlUrl = controlUrl.Substring(u.GetLeftPart(UriPartial.Authority).Length);
NatUtility.Log("{0}: New control url: {1}", HostEndPoint, controlUrl);
}
}
catch
{
NatUtility.Log("{0}: Assuming control Uri is relative: {1}", HostEndPoint, controlUrl);
}
NatUtility.Log("{0}: Handshake Complete", HostEndPoint);
return;
}
}
}
//If we get here, it means that we didn't get WANIPConnection service, which means no uPnP forwarding
//So we don't invoke the callback, so this device is never added to our lists
} }
} }
@ -171,10 +220,13 @@ namespace Mono.Nat.Upnp
get { return serviceType; } get { return serviceType; }
} }
public override Task CreatePortMap(Mapping mapping) public override async Task CreatePortMap(Mapping mapping)
{ {
CreatePortMappingMessage message = new CreatePortMappingMessage(mapping, localAddress, this); CreatePortMappingMessage message = new CreatePortMappingMessage(mapping, localAddress, this);
return _httpClient.SendAsync(message.Encode(), message.Method); using (await _httpClient.SendAsync(message.Encode(), message.Method).ConfigureAwait(false))
{
}
} }
public override bool Equals(object obj) public override bool Equals(object obj)

View File

@ -1,3 +1,3 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("3.2.33.13")] [assembly: AssemblyVersion("3.2.33.14")]