mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 18:08:53 -07:00
Merge pull request #4030 from crobibero/http-client-migrate
Remove IHttpClient
This commit is contained in:
commit
6152d40303
@ -1,8 +1,8 @@
|
|||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Dlna.Service;
|
using Emby.Dlna.Service;
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@ -18,8 +18,8 @@ namespace Emby.Dlna.ConnectionManager
|
|||||||
IDlnaManager dlna,
|
IDlnaManager dlna,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
ILogger<ConnectionManagerService> logger,
|
ILogger<ConnectionManagerService> logger,
|
||||||
IHttpClient httpClient)
|
IHttpClientFactory httpClientFactory)
|
||||||
: base(logger, httpClient)
|
: base(logger, httpClientFactory)
|
||||||
{
|
{
|
||||||
_dlna = dlna;
|
_dlna = dlna;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Dlna.Service;
|
using Emby.Dlna.Service;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
@ -41,7 +41,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
ILogger<ContentDirectoryService> logger,
|
ILogger<ContentDirectoryService> logger,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClient,
|
||||||
ILocalizationManager localization,
|
ILocalizationManager localization,
|
||||||
IMediaSourceManager mediaSourceManager,
|
IMediaSourceManager mediaSourceManager,
|
||||||
IUserViewManager userViewManager,
|
IUserViewManager userViewManager,
|
||||||
|
@ -80,6 +80,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Net.Mime;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
@ -20,13 +21,13 @@ namespace Emby.Dlna.Eventing
|
|||||||
new ConcurrentDictionary<string, EventSubscription>(StringComparer.OrdinalIgnoreCase);
|
new ConcurrentDictionary<string, EventSubscription>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
|
|
||||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
public DlnaEventManager(ILogger logger, IHttpClient httpClient)
|
public DlnaEventManager(ILogger logger, IHttpClientFactory httpClientFactory)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,24 +168,17 @@ namespace Emby.Dlna.Eventing
|
|||||||
|
|
||||||
builder.Append("</e:propertyset>");
|
builder.Append("</e:propertyset>");
|
||||||
|
|
||||||
var options = new HttpRequestOptions
|
using var options = new HttpRequestMessage(new HttpMethod("NOTIFY"), subscription.CallbackUrl);
|
||||||
{
|
options.Content = new StringContent(builder.ToString(), Encoding.UTF8, MediaTypeNames.Text.Xml);
|
||||||
RequestContent = builder.ToString(),
|
options.Headers.TryAddWithoutValidation("NT", subscription.NotificationType);
|
||||||
RequestContentType = "text/xml",
|
options.Headers.TryAddWithoutValidation("NTS", "upnp:propchange");
|
||||||
Url = subscription.CallbackUrl,
|
options.Headers.TryAddWithoutValidation("SID", subscription.Id);
|
||||||
BufferContent = false
|
options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(_usCulture));
|
||||||
};
|
|
||||||
|
|
||||||
options.RequestHeaders.Add("NT", subscription.NotificationType);
|
|
||||||
options.RequestHeaders.Add("NTS", "upnp:propchange");
|
|
||||||
options.RequestHeaders.Add("SID", subscription.Id);
|
|
||||||
options.RequestHeaders.Add("SEQ", subscription.TriggerCount.ToString(_usCulture));
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false))
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
{
|
.SendAsync(options, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -36,7 +37,7 @@ namespace Emby.Dlna.Main
|
|||||||
private readonly ILogger<DlnaEntryPoint> _logger;
|
private readonly ILogger<DlnaEntryPoint> _logger;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IDlnaManager _dlnaManager;
|
private readonly IDlnaManager _dlnaManager;
|
||||||
@ -61,7 +62,7 @@ namespace Emby.Dlna.Main
|
|||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
IServerApplicationHost appHost,
|
IServerApplicationHost appHost,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
IDlnaManager dlnaManager,
|
IDlnaManager dlnaManager,
|
||||||
@ -79,7 +80,7 @@ namespace Emby.Dlna.Main
|
|||||||
_config = config;
|
_config = config;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_dlnaManager = dlnaManager;
|
_dlnaManager = dlnaManager;
|
||||||
@ -101,7 +102,7 @@ namespace Emby.Dlna.Main
|
|||||||
config,
|
config,
|
||||||
userManager,
|
userManager,
|
||||||
loggerFactory.CreateLogger<ContentDirectory.ContentDirectoryService>(),
|
loggerFactory.CreateLogger<ContentDirectory.ContentDirectoryService>(),
|
||||||
httpClient,
|
httpClientFactory,
|
||||||
localizationManager,
|
localizationManager,
|
||||||
mediaSourceManager,
|
mediaSourceManager,
|
||||||
userViewManager,
|
userViewManager,
|
||||||
@ -112,11 +113,11 @@ namespace Emby.Dlna.Main
|
|||||||
dlnaManager,
|
dlnaManager,
|
||||||
config,
|
config,
|
||||||
loggerFactory.CreateLogger<ConnectionManager.ConnectionManagerService>(),
|
loggerFactory.CreateLogger<ConnectionManager.ConnectionManagerService>(),
|
||||||
httpClient);
|
httpClientFactory);
|
||||||
|
|
||||||
MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrarService(
|
MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrarService(
|
||||||
loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrarService>(),
|
loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrarService>(),
|
||||||
httpClient,
|
httpClientFactory,
|
||||||
config);
|
config);
|
||||||
Current = this;
|
Current = this;
|
||||||
}
|
}
|
||||||
@ -364,7 +365,7 @@ namespace Emby.Dlna.Main
|
|||||||
_appHost,
|
_appHost,
|
||||||
_imageProcessor,
|
_imageProcessor,
|
||||||
_deviceDiscovery,
|
_deviceDiscovery,
|
||||||
_httpClient,
|
_httpClientFactory,
|
||||||
_config,
|
_config,
|
||||||
_userDataManager,
|
_userDataManager,
|
||||||
_localization,
|
_localization,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Dlna.Service;
|
using Emby.Dlna.Service;
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
@ -14,9 +14,9 @@ namespace Emby.Dlna.MediaReceiverRegistrar
|
|||||||
|
|
||||||
public MediaReceiverRegistrarService(
|
public MediaReceiverRegistrarService(
|
||||||
ILogger<MediaReceiverRegistrarService> logger,
|
ILogger<MediaReceiverRegistrarService> logger,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
IServerConfigurationManager config)
|
IServerConfigurationManager config)
|
||||||
: base(logger, httpClient)
|
: base(logger, httpClientFactory)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -21,7 +22,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
{
|
{
|
||||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
@ -34,10 +35,10 @@ namespace Emby.Dlna.PlayTo
|
|||||||
private int _connectFailureCount;
|
private int _connectFailureCount;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger)
|
public Device(DeviceInfo deviceProperties, IHttpClientFactory httpClientFactory, ILogger logger)
|
||||||
{
|
{
|
||||||
Properties = deviceProperties;
|
Properties = deviceProperties;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +237,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
_logger.LogDebug("Setting mute");
|
_logger.LogDebug("Setting mute");
|
||||||
var value = mute ? 1 : 0;
|
var value = mute ? 1 : 0;
|
||||||
|
|
||||||
await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
|
await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
IsMuted = mute;
|
IsMuted = mute;
|
||||||
@ -271,7 +272,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
// Remote control will perform better
|
// Remote control will perform better
|
||||||
Volume = value;
|
Volume = value;
|
||||||
|
|
||||||
await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
|
await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +293,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
throw new InvalidOperationException("Unable to find service");
|
throw new InvalidOperationException("Unable to find service");
|
||||||
}
|
}
|
||||||
|
|
||||||
await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME"))
|
await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME"))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
RestartTimer(true);
|
RestartTimer(true);
|
||||||
@ -326,7 +327,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
}
|
}
|
||||||
|
|
||||||
var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
|
var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
|
||||||
await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header)
|
await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await Task.Delay(50).ConfigureAwait(false);
|
await Task.Delay(50).ConfigureAwait(false);
|
||||||
@ -368,7 +369,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
throw new InvalidOperationException("Unable to find service");
|
throw new InvalidOperationException("Unable to find service");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SsdpHttpClient(_httpClient).SendCommandAsync(
|
return new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
|
||||||
Properties.BaseUrl,
|
Properties.BaseUrl,
|
||||||
service,
|
service,
|
||||||
command.Name,
|
command.Name,
|
||||||
@ -397,7 +398,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
|
|
||||||
var service = GetAvTransportService();
|
var service = GetAvTransportService();
|
||||||
|
|
||||||
await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
|
await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
RestartTimer(true);
|
RestartTimer(true);
|
||||||
@ -415,7 +416,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
|
|
||||||
var service = GetAvTransportService();
|
var service = GetAvTransportService();
|
||||||
|
|
||||||
await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
|
await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
TransportState = TransportState.Paused;
|
TransportState = TransportState.Paused;
|
||||||
@ -542,7 +543,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
|
||||||
Properties.BaseUrl,
|
Properties.BaseUrl,
|
||||||
service,
|
service,
|
||||||
command.Name,
|
command.Name,
|
||||||
@ -592,7 +593,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
|
||||||
Properties.BaseUrl,
|
Properties.BaseUrl,
|
||||||
service,
|
service,
|
||||||
command.Name,
|
command.Name,
|
||||||
@ -625,7 +626,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
|
||||||
Properties.BaseUrl,
|
Properties.BaseUrl,
|
||||||
service,
|
service,
|
||||||
command.Name,
|
command.Name,
|
||||||
@ -667,7 +668,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
|
|
||||||
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
|
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
|
||||||
Properties.BaseUrl,
|
Properties.BaseUrl,
|
||||||
service,
|
service,
|
||||||
command.Name,
|
command.Name,
|
||||||
@ -734,7 +735,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
|
|
||||||
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
|
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
|
||||||
Properties.BaseUrl,
|
Properties.BaseUrl,
|
||||||
service,
|
service,
|
||||||
command.Name,
|
command.Name,
|
||||||
@ -912,7 +913,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
|
|
||||||
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
|
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
|
||||||
|
|
||||||
var httpClient = new SsdpHttpClient(_httpClient);
|
var httpClient = new SsdpHttpClient(_httpClientFactory);
|
||||||
|
|
||||||
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
|
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -940,7 +941,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
|
|
||||||
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
|
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
|
||||||
|
|
||||||
var httpClient = new SsdpHttpClient(_httpClient);
|
var httpClient = new SsdpHttpClient(_httpClientFactory);
|
||||||
_logger.LogDebug("Dlna Device.GetRenderingProtocolAsync");
|
_logger.LogDebug("Dlna Device.GetRenderingProtocolAsync");
|
||||||
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
|
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -969,9 +970,9 @@ namespace Emby.Dlna.PlayTo
|
|||||||
return baseUrl + url;
|
return baseUrl + url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
|
public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClientFactory httpClientFactory, ILogger logger, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var ssdpHttpClient = new SsdpHttpClient(httpClient);
|
var ssdpHttpClient = new SsdpHttpClient(httpClientFactory);
|
||||||
|
|
||||||
var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false);
|
var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -1079,7 +1080,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Device(deviceProperties, httpClient, logger);
|
return new Device(deviceProperties, httpClientFactory, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DeviceIcon CreateIcon(XElement element)
|
private static DeviceIcon CreateIcon(XElement element)
|
||||||
|
@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Data.Events;
|
using Jellyfin.Data.Events;
|
||||||
@ -33,7 +34,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
private readonly IDlnaManager _dlnaManager;
|
private readonly IDlnaManager _dlnaManager;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly IImageProcessor _imageProcessor;
|
private readonly IImageProcessor _imageProcessor;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
@ -46,7 +47,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
private SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
|
private SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
|
||||||
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
|
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder)
|
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClientFactory httpClientFactory, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
@ -56,7 +57,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_imageProcessor = imageProcessor;
|
_imageProcessor = imageProcessor;
|
||||||
_deviceDiscovery = deviceDiscovery;
|
_deviceDiscovery = deviceDiscovery;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_config = config;
|
_config = config;
|
||||||
_userDataManager = userDataManager;
|
_userDataManager = userDataManager;
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
@ -174,7 +175,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
|
|
||||||
if (controller == null)
|
if (controller == null)
|
||||||
{
|
{
|
||||||
var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _logger, cancellationToken).ConfigureAwait(false);
|
var device = await Device.CreateuPnpDeviceAsync(uri, _httpClientFactory, _logger, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
string deviceName = device.Properties.Name;
|
string deviceName = device.Properties.Name;
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ using System;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Net.Mime;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -20,11 +22,11 @@ namespace Emby.Dlna.PlayTo
|
|||||||
|
|
||||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
|
|
||||||
public SsdpHttpClient(IHttpClient httpClient)
|
public SsdpHttpClient(IHttpClientFactory httpClientFactory)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<XDocument> SendCommandAsync(
|
public async Task<XDocument> SendCommandAsync(
|
||||||
@ -36,20 +38,18 @@ namespace Emby.Dlna.PlayTo
|
|||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var url = NormalizeServiceUrl(baseUrl, service.ControlUrl);
|
var url = NormalizeServiceUrl(baseUrl, service.ControlUrl);
|
||||||
using (var response = await PostSoapDataAsync(
|
using var response = await PostSoapDataAsync(
|
||||||
url,
|
url,
|
||||||
$"\"{service.ServiceType}#{command}\"",
|
$"\"{service.ServiceType}#{command}\"",
|
||||||
postData,
|
postData,
|
||||||
header,
|
header,
|
||||||
cancellationToken)
|
cancellationToken)
|
||||||
.ConfigureAwait(false))
|
.ConfigureAwait(false);
|
||||||
using (var stream = response.Content)
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
using var reader = new StreamReader(stream, Encoding.UTF8);
|
||||||
{
|
return XDocument.Parse(
|
||||||
return XDocument.Parse(
|
await reader.ReadToEndAsync().ConfigureAwait(false),
|
||||||
await reader.ReadToEndAsync().ConfigureAwait(false),
|
LoadOptions.PreserveWhitespace);
|
||||||
LoadOptions.PreserveWhitespace);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string NormalizeServiceUrl(string baseUrl, string serviceUrl)
|
private static string NormalizeServiceUrl(string baseUrl, string serviceUrl)
|
||||||
@ -76,49 +76,32 @@ namespace Emby.Dlna.PlayTo
|
|||||||
int eventport,
|
int eventport,
|
||||||
int timeOut = 3600)
|
int timeOut = 3600)
|
||||||
{
|
{
|
||||||
var options = new HttpRequestOptions
|
using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url);
|
||||||
{
|
options.Headers.UserAgent.ParseAdd(USERAGENT);
|
||||||
Url = url,
|
options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(_usCulture));
|
||||||
UserAgent = USERAGENT,
|
options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(_usCulture) + ">");
|
||||||
LogErrorResponseBody = true,
|
options.Headers.TryAddWithoutValidation("NT", "upnp:event");
|
||||||
BufferContent = false,
|
options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(_usCulture));
|
||||||
};
|
|
||||||
|
|
||||||
options.RequestHeaders["HOST"] = ip + ":" + port.ToString(_usCulture);
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport.ToString(_usCulture) + ">";
|
.SendAsync(options, HttpCompletionOption.ResponseHeadersRead)
|
||||||
options.RequestHeaders["NT"] = "upnp:event";
|
.ConfigureAwait(false);
|
||||||
options.RequestHeaders["TIMEOUT"] = "Second-" + timeOut.ToString(_usCulture);
|
|
||||||
|
|
||||||
using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<XDocument> GetDataAsync(string url, CancellationToken cancellationToken)
|
public async Task<XDocument> GetDataAsync(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var options = new HttpRequestOptions
|
using var options = new HttpRequestMessage(HttpMethod.Get, url);
|
||||||
{
|
options.Headers.UserAgent.ParseAdd(USERAGENT);
|
||||||
Url = url,
|
options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
|
||||||
UserAgent = USERAGENT,
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||||
LogErrorResponseBody = true,
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
BufferContent = false,
|
using var reader = new StreamReader(stream, Encoding.UTF8);
|
||||||
|
return XDocument.Parse(
|
||||||
CancellationToken = cancellationToken
|
await reader.ReadToEndAsync().ConfigureAwait(false),
|
||||||
};
|
LoadOptions.PreserveWhitespace);
|
||||||
|
|
||||||
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
|
|
||||||
|
|
||||||
using (var response = await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false))
|
|
||||||
using (var stream = response.Content)
|
|
||||||
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
|
||||||
{
|
|
||||||
return XDocument.Parse(
|
|
||||||
await reader.ReadToEndAsync().ConfigureAwait(false),
|
|
||||||
LoadOptions.PreserveWhitespace);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<HttpResponseInfo> PostSoapDataAsync(
|
private Task<HttpResponseMessage> PostSoapDataAsync(
|
||||||
string url,
|
string url,
|
||||||
string soapAction,
|
string soapAction,
|
||||||
string postData,
|
string postData,
|
||||||
@ -130,29 +113,20 @@ namespace Emby.Dlna.PlayTo
|
|||||||
soapAction = $"\"{soapAction}\"";
|
soapAction = $"\"{soapAction}\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = new HttpRequestOptions
|
using var options = new HttpRequestMessage(HttpMethod.Post, url);
|
||||||
{
|
options.Headers.UserAgent.ParseAdd(USERAGENT);
|
||||||
Url = url,
|
options.Headers.TryAddWithoutValidation("SOAPACTION", soapAction);
|
||||||
UserAgent = USERAGENT,
|
options.Headers.TryAddWithoutValidation("Pragma", "no-cache");
|
||||||
LogErrorResponseBody = true,
|
options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
|
||||||
BufferContent = false,
|
|
||||||
|
|
||||||
CancellationToken = cancellationToken
|
|
||||||
};
|
|
||||||
|
|
||||||
options.RequestHeaders["SOAPAction"] = soapAction;
|
|
||||||
options.RequestHeaders["Pragma"] = "no-cache";
|
|
||||||
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(header))
|
if (!string.IsNullOrEmpty(header))
|
||||||
{
|
{
|
||||||
options.RequestHeaders["contentFeatures.dlna.org"] = header;
|
options.Headers.TryAddWithoutValidation("contentFeatures.dlna.org", header);
|
||||||
}
|
}
|
||||||
|
|
||||||
options.RequestContentType = "text/xml";
|
options.Content = new StringContent(postData, Encoding.UTF8, MediaTypeNames.Text.Xml);
|
||||||
options.RequestContent = postData;
|
|
||||||
|
|
||||||
return _httpClient.Post(options);
|
return _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,21 @@
|
|||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System.Net.Http;
|
||||||
using Emby.Dlna.Eventing;
|
using Emby.Dlna.Eventing;
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Emby.Dlna.Service
|
namespace Emby.Dlna.Service
|
||||||
{
|
{
|
||||||
public class BaseService : IDlnaEventManager
|
public class BaseService : IDlnaEventManager
|
||||||
{
|
{
|
||||||
protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient)
|
protected BaseService(ILogger<BaseService> logger, IHttpClientFactory httpClientFactory)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
HttpClient = httpClient;
|
EventManager = new DlnaEventManager(logger, httpClientFactory);
|
||||||
|
|
||||||
EventManager = new DlnaEventManager(logger, HttpClient);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IDlnaEventManager EventManager { get; }
|
protected IDlnaEventManager EventManager { get; }
|
||||||
|
|
||||||
protected IHttpClient HttpClient { get; }
|
|
||||||
|
|
||||||
protected ILogger Logger { get; }
|
protected ILogger Logger { get; }
|
||||||
|
|
||||||
public EventSubscriptionResponse CancelEventSubscription(string subscriptionId)
|
public EventSubscriptionResponse CancelEventSubscription(string subscriptionId)
|
||||||
|
@ -49,6 +49,7 @@ using Jellyfin.Api.Helpers;
|
|||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Events;
|
using MediaBrowser.Common.Events;
|
||||||
|
using MediaBrowser.Common.Json;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Common.Plugins;
|
using MediaBrowser.Common.Plugins;
|
||||||
using MediaBrowser.Common.Updates;
|
using MediaBrowser.Common.Updates;
|
||||||
@ -122,8 +123,8 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
private IMediaEncoder _mediaEncoder;
|
private IMediaEncoder _mediaEncoder;
|
||||||
private ISessionManager _sessionManager;
|
private ISessionManager _sessionManager;
|
||||||
|
private IHttpClientFactory _httpClientFactory;
|
||||||
private IWebSocketManager _webSocketManager;
|
private IWebSocketManager _webSocketManager;
|
||||||
private IHttpClient _httpClient;
|
|
||||||
|
|
||||||
private string[] _urlPrefixes;
|
private string[] _urlPrefixes;
|
||||||
|
|
||||||
@ -526,8 +527,6 @@ namespace Emby.Server.Implementations
|
|||||||
ServiceCollection.AddSingleton(_fileSystemManager);
|
ServiceCollection.AddSingleton(_fileSystemManager);
|
||||||
ServiceCollection.AddSingleton<TvdbClientManager>();
|
ServiceCollection.AddSingleton<TvdbClientManager>();
|
||||||
|
|
||||||
ServiceCollection.AddSingleton<IHttpClient, HttpClientManager.HttpClientManager>();
|
|
||||||
|
|
||||||
ServiceCollection.AddSingleton(_networkManager);
|
ServiceCollection.AddSingleton(_networkManager);
|
||||||
|
|
||||||
ServiceCollection.AddSingleton<IIsoManager, IsoManager>();
|
ServiceCollection.AddSingleton<IIsoManager, IsoManager>();
|
||||||
@ -654,8 +653,8 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
_mediaEncoder = Resolve<IMediaEncoder>();
|
_mediaEncoder = Resolve<IMediaEncoder>();
|
||||||
_sessionManager = Resolve<ISessionManager>();
|
_sessionManager = Resolve<ISessionManager>();
|
||||||
|
_httpClientFactory = Resolve<IHttpClientFactory>();
|
||||||
_webSocketManager = Resolve<IWebSocketManager>();
|
_webSocketManager = Resolve<IWebSocketManager>();
|
||||||
_httpClient = Resolve<IHttpClient>();
|
|
||||||
|
|
||||||
((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
|
((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
|
||||||
|
|
||||||
@ -1300,25 +1299,17 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var response = await _httpClient.SendAsync(
|
using var request = new HttpRequestMessage(HttpMethod.Post, apiUrl);
|
||||||
new HttpRequestOptions
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
{
|
.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||||
Url = apiUrl,
|
|
||||||
LogErrorResponseBody = false,
|
|
||||||
BufferContent = false,
|
|
||||||
CancellationToken = cancellationToken
|
|
||||||
}, HttpMethod.Post).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
using (var reader = new StreamReader(response.Content))
|
|
||||||
{
|
|
||||||
var result = await reader.ReadToEndAsync().ConfigureAwait(false);
|
|
||||||
var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
_validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid);
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
Logger.LogDebug("Ping test result to {0}. Success: {1}", apiUrl, valid);
|
var result = await System.Text.Json.JsonSerializer.DeserializeAsync<string>(stream, JsonDefaults.GetOptions(), cancellationToken).ConfigureAwait(false);
|
||||||
return valid;
|
var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
|
||||||
}
|
_validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid);
|
||||||
|
Logger.LogDebug("Ping test result to {0}. Success: {1}", apiUrl, valid);
|
||||||
|
return valid;
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
@ -1,335 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Common;
|
|
||||||
using MediaBrowser.Common.Configuration;
|
|
||||||
using MediaBrowser.Common.Extensions;
|
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Net.Http.Headers;
|
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.HttpClientManager
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class HttpClientManager.
|
|
||||||
/// </summary>
|
|
||||||
public class HttpClientManager : IHttpClient
|
|
||||||
{
|
|
||||||
private readonly ILogger<HttpClientManager> _logger;
|
|
||||||
private readonly IApplicationPaths _appPaths;
|
|
||||||
private readonly IFileSystem _fileSystem;
|
|
||||||
private readonly IApplicationHost _appHost;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Holds a dictionary of http clients by host. Use GetHttpClient(host) to retrieve or create a client for web requests.
|
|
||||||
/// DON'T dispose it after use.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The HTTP clients.</value>
|
|
||||||
private readonly ConcurrentDictionary<string, HttpClient> _httpClients = new ConcurrentDictionary<string, HttpClient>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="HttpClientManager" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public HttpClientManager(
|
|
||||||
IApplicationPaths appPaths,
|
|
||||||
ILogger<HttpClientManager> logger,
|
|
||||||
IFileSystem fileSystem,
|
|
||||||
IApplicationHost appHost)
|
|
||||||
{
|
|
||||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
||||||
_fileSystem = fileSystem;
|
|
||||||
_appPaths = appPaths ?? throw new ArgumentNullException(nameof(appPaths));
|
|
||||||
_appHost = appHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the correct http client for the given url.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="url">The url.</param>
|
|
||||||
/// <returns>HttpClient.</returns>
|
|
||||||
private HttpClient GetHttpClient(string url)
|
|
||||||
{
|
|
||||||
var key = GetHostFromUrl(url);
|
|
||||||
|
|
||||||
if (!_httpClients.TryGetValue(key, out var client))
|
|
||||||
{
|
|
||||||
client = new HttpClient()
|
|
||||||
{
|
|
||||||
BaseAddress = new Uri(url)
|
|
||||||
};
|
|
||||||
|
|
||||||
_httpClients.TryAdd(key, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpRequestMessage GetRequestMessage(HttpRequestOptions options, HttpMethod method)
|
|
||||||
{
|
|
||||||
string url = options.Url;
|
|
||||||
var uriAddress = new Uri(url);
|
|
||||||
string userInfo = uriAddress.UserInfo;
|
|
||||||
if (!string.IsNullOrWhiteSpace(userInfo))
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Found userInfo in url: {0} ... url: {1}", userInfo, url);
|
|
||||||
url = url.Replace(userInfo + '@', string.Empty, StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
var request = new HttpRequestMessage(method, url);
|
|
||||||
|
|
||||||
foreach (var header in options.RequestHeaders)
|
|
||||||
{
|
|
||||||
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.EnableDefaultUserAgent
|
|
||||||
&& !request.Headers.TryGetValues(HeaderNames.UserAgent, out _))
|
|
||||||
{
|
|
||||||
request.Headers.Add(HeaderNames.UserAgent, _appHost.ApplicationUserAgent);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (options.DecompressionMethod)
|
|
||||||
{
|
|
||||||
case CompressionMethods.Deflate | CompressionMethods.Gzip:
|
|
||||||
request.Headers.Add(HeaderNames.AcceptEncoding, new[] { "gzip", "deflate" });
|
|
||||||
break;
|
|
||||||
case CompressionMethods.Deflate:
|
|
||||||
request.Headers.Add(HeaderNames.AcceptEncoding, "deflate");
|
|
||||||
break;
|
|
||||||
case CompressionMethods.Gzip:
|
|
||||||
request.Headers.Add(HeaderNames.AcceptEncoding, "gzip");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.EnableKeepAlive)
|
|
||||||
{
|
|
||||||
request.Headers.Add(HeaderNames.Connection, "Keep-Alive");
|
|
||||||
}
|
|
||||||
|
|
||||||
// request.Headers.Add(HeaderNames.CacheControl, "no-cache");
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (!string.IsNullOrWhiteSpace(userInfo))
|
|
||||||
{
|
|
||||||
var parts = userInfo.Split(':');
|
|
||||||
if (parts.Length == 2)
|
|
||||||
{
|
|
||||||
request.Headers.Add(HeaderNames., GetCredential(url, parts[0], parts[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the response internal.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
|
||||||
public Task<HttpResponseInfo> GetResponse(HttpRequestOptions options)
|
|
||||||
=> SendAsync(options, HttpMethod.Get);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs a GET request and returns the resulting stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <returns>Task{Stream}.</returns>
|
|
||||||
public async Task<Stream> Get(HttpRequestOptions options)
|
|
||||||
{
|
|
||||||
var response = await GetResponse(options).ConfigureAwait(false);
|
|
||||||
return response.Content;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// send as an asynchronous operation.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <param name="httpMethod">The HTTP method.</param>
|
|
||||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
|
||||||
public Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod)
|
|
||||||
=> SendAsync(options, new HttpMethod(httpMethod));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// send as an asynchronous operation.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <param name="httpMethod">The HTTP method.</param>
|
|
||||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
|
||||||
public async Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, HttpMethod httpMethod)
|
|
||||||
{
|
|
||||||
if (options.CacheMode == CacheMode.None)
|
|
||||||
{
|
|
||||||
return await SendAsyncInternal(options, httpMethod).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = options.Url;
|
|
||||||
var urlHash = url.ToUpperInvariant().GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
|
||||||
|
|
||||||
var responseCachePath = Path.Combine(_appPaths.CachePath, "httpclient", urlHash);
|
|
||||||
|
|
||||||
var response = GetCachedResponse(responseCachePath, options.CacheLength, url);
|
|
||||||
if (response != null)
|
|
||||||
{
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
response = await SendAsyncInternal(options, httpMethod).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (response.StatusCode == HttpStatusCode.OK)
|
|
||||||
{
|
|
||||||
await CacheResponse(response, responseCachePath).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpResponseInfo GetCachedResponse(string responseCachePath, TimeSpan cacheLength, string url)
|
|
||||||
{
|
|
||||||
if (File.Exists(responseCachePath)
|
|
||||||
&& _fileSystem.GetLastWriteTimeUtc(responseCachePath).Add(cacheLength) > DateTime.UtcNow)
|
|
||||||
{
|
|
||||||
var stream = new FileStream(responseCachePath, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true);
|
|
||||||
|
|
||||||
return new HttpResponseInfo
|
|
||||||
{
|
|
||||||
ResponseUrl = url,
|
|
||||||
Content = stream,
|
|
||||||
StatusCode = HttpStatusCode.OK,
|
|
||||||
ContentLength = stream.Length
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task CacheResponse(HttpResponseInfo response, string responseCachePath)
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(responseCachePath));
|
|
||||||
|
|
||||||
using (var fileStream = new FileStream(
|
|
||||||
responseCachePath,
|
|
||||||
FileMode.Create,
|
|
||||||
FileAccess.Write,
|
|
||||||
FileShare.None,
|
|
||||||
IODefaults.FileStreamBufferSize,
|
|
||||||
true))
|
|
||||||
{
|
|
||||||
await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.Content.Position = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<HttpResponseInfo> SendAsyncInternal(HttpRequestOptions options, HttpMethod httpMethod)
|
|
||||||
{
|
|
||||||
ValidateParams(options);
|
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var client = GetHttpClient(options.Url);
|
|
||||||
|
|
||||||
var httpWebRequest = GetRequestMessage(options, httpMethod);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(options.RequestContent)
|
|
||||||
|| httpMethod == HttpMethod.Post)
|
|
||||||
{
|
|
||||||
if (options.RequestContent != null)
|
|
||||||
{
|
|
||||||
httpWebRequest.Content = new StringContent(
|
|
||||||
options.RequestContent,
|
|
||||||
null,
|
|
||||||
options.RequestContentType);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
httpWebRequest.Content = new ByteArrayContent(Array.Empty<byte>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var response = await client.SendAsync(
|
|
||||||
httpWebRequest,
|
|
||||||
options.BufferContent || options.CacheMode == CacheMode.Unconditional ? HttpCompletionOption.ResponseContentRead : HttpCompletionOption.ResponseHeadersRead,
|
|
||||||
options.CancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
await EnsureSuccessStatusCode(response, options).ConfigureAwait(false);
|
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
|
||||||
return new HttpResponseInfo(response.Headers, response.Content.Headers)
|
|
||||||
{
|
|
||||||
Content = stream,
|
|
||||||
StatusCode = response.StatusCode,
|
|
||||||
ContentType = response.Content.Headers.ContentType?.MediaType,
|
|
||||||
ContentLength = response.Content.Headers.ContentLength,
|
|
||||||
ResponseUrl = response.Content.Headers.ContentLocation?.ToString()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<HttpResponseInfo> Post(HttpRequestOptions options)
|
|
||||||
=> SendAsync(options, HttpMethod.Post);
|
|
||||||
|
|
||||||
private void ValidateParams(HttpRequestOptions options)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(options.Url))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(options));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the host from URL.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="url">The URL.</param>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
private static string GetHostFromUrl(string url)
|
|
||||||
{
|
|
||||||
var index = url.IndexOf("://", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
url = url.Substring(index + 3);
|
|
||||||
var host = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(host))
|
|
||||||
{
|
|
||||||
return host;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task EnsureSuccessStatusCode(HttpResponseMessage response, HttpRequestOptions options)
|
|
||||||
{
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.LogErrorResponseBody)
|
|
||||||
{
|
|
||||||
string msg = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
_logger.LogError("HTTP request failed with message: {Message}", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HttpException(response.ReasonPhrase)
|
|
||||||
{
|
|
||||||
StatusCode = response.StatusCode
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,13 +16,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
public class DirectRecorder : IRecorder
|
public class DirectRecorder : IRecorder
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IStreamHelper _streamHelper;
|
private readonly IStreamHelper _streamHelper;
|
||||||
|
|
||||||
public DirectRecorder(ILogger logger, IHttpClient httpClient, IStreamHelper streamHelper)
|
public DirectRecorder(ILogger logger, IHttpClientFactory httpClientFactory, IStreamHelper streamHelper)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_streamHelper = streamHelper;
|
_streamHelper = streamHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,42 +63,28 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
private async Task RecordFromMediaSource(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
private async Task RecordFromMediaSource(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var httpRequestOptions = new HttpRequestOptions
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
{
|
.GetAsync(mediaSource.Path, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||||
Url = mediaSource.Path,
|
|
||||||
BufferContent = false,
|
|
||||||
|
|
||||||
// Some remote urls will expect a user agent to be supplied
|
_logger.LogInformation("Opened recording stream from tuner provider");
|
||||||
UserAgent = "Emby/3.0",
|
|
||||||
|
|
||||||
// Shouldn't matter but may cause issues
|
Directory.CreateDirectory(Path.GetDirectoryName(targetFile));
|
||||||
DecompressionMethod = CompressionMethods.None,
|
|
||||||
CancellationToken = cancellationToken
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false))
|
await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||||
{
|
|
||||||
_logger.LogInformation("Opened recording stream from tuner provider");
|
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(targetFile));
|
onStarted();
|
||||||
|
|
||||||
using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read))
|
_logger.LogInformation("Copying recording stream to file {0}", targetFile);
|
||||||
{
|
|
||||||
onStarted();
|
|
||||||
|
|
||||||
_logger.LogInformation("Copying recording stream to file {0}", targetFile);
|
// The media source if infinite so we need to handle stopping ourselves
|
||||||
|
var durationToken = new CancellationTokenSource(duration);
|
||||||
|
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||||
|
|
||||||
// The media source if infinite so we need to handle stopping ourselves
|
await _streamHelper.CopyUntilCancelled(
|
||||||
using var durationToken = new CancellationTokenSource(duration);
|
await response.Content.ReadAsStreamAsync().ConfigureAwait(false),
|
||||||
using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
|
output,
|
||||||
|
IODefaults.CopyToBufferSize,
|
||||||
await _streamHelper.CopyUntilCancelled(
|
cancellationToken).ConfigureAwait(false);
|
||||||
response.Content,
|
|
||||||
output,
|
|
||||||
IODefaults.CopyToBufferSize,
|
|
||||||
cancellationTokenSource.Token).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("Recording completed to file {0}", targetFile);
|
_logger.LogInformation("Recording completed to file {0}", targetFile);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using System.Diagnostics;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -48,7 +49,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly ILogger<EmbyTV> _logger;
|
private readonly ILogger<EmbyTV> _logger;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
|
|
||||||
@ -81,7 +82,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
IMediaSourceManager mediaSourceManager,
|
IMediaSourceManager mediaSourceManager,
|
||||||
ILogger<EmbyTV> logger,
|
ILogger<EmbyTV> logger,
|
||||||
IJsonSerializer jsonSerializer,
|
IJsonSerializer jsonSerializer,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
ILiveTvManager liveTvManager,
|
ILiveTvManager liveTvManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
@ -94,7 +95,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_config = config;
|
_config = config;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
@ -1637,7 +1638,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer);
|
return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DirectRecorder(_logger, _httpClient, _streamHelper);
|
return new DirectRecorder(_logger, _httpClientFactory, _streamHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSuccessfulRecording(TimerInfo timer, string path)
|
private void OnSuccessfulRecording(TimerInfo timer, string path)
|
||||||
|
@ -8,6 +8,8 @@ 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.Mime;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
@ -28,19 +30,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
private readonly ILogger<SchedulesDirect> _logger;
|
private readonly ILogger<SchedulesDirect> _logger;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly SemaphoreSlim _tokenSemaphore = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim _tokenSemaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly IApplicationHost _appHost;
|
private readonly IApplicationHost _appHost;
|
||||||
|
|
||||||
public SchedulesDirect(
|
public SchedulesDirect(
|
||||||
ILogger<SchedulesDirect> logger,
|
ILogger<SchedulesDirect> logger,
|
||||||
IJsonSerializer jsonSerializer,
|
IJsonSerializer jsonSerializer,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
IApplicationHost appHost)
|
IApplicationHost appHost)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,95 +104,78 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
var requestString = _jsonSerializer.SerializeToString(requestList);
|
var requestString = _jsonSerializer.SerializeToString(requestList);
|
||||||
_logger.LogDebug("Request string for schedules is: {RequestString}", requestString);
|
_logger.LogDebug("Request string for schedules is: {RequestString}", requestString);
|
||||||
|
|
||||||
var httpOptions = new HttpRequestOptions()
|
using var options = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/schedules");
|
||||||
|
options.Content = new StringContent(requestString, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||||
|
options.Headers.TryAddWithoutValidation("token", token);
|
||||||
|
using var response = await Send(options, true, info, cancellationToken).ConfigureAwait(false);
|
||||||
|
await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
|
var dailySchedules = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Day>>(responseStream).ConfigureAwait(false);
|
||||||
|
_logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId);
|
||||||
|
|
||||||
|
using var programRequestOptions = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/programs");
|
||||||
|
programRequestOptions.Headers.TryAddWithoutValidation("token", token);
|
||||||
|
|
||||||
|
var programsID = dailySchedules.SelectMany(d => d.programs.Select(s => s.programID)).Distinct();
|
||||||
|
programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programsID) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||||
|
|
||||||
|
using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false);
|
||||||
|
await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
|
var programDetails = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ProgramDetails>>(innerResponseStream).ConfigureAwait(false);
|
||||||
|
var programDict = programDetails.ToDictionary(p => p.programID, y => y);
|
||||||
|
|
||||||
|
var programIdsWithImages =
|
||||||
|
programDetails.Where(p => p.hasImageArtwork).Select(p => p.programID)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var images = await GetImageForPrograms(info, programIdsWithImages, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var programsInfo = new List<ProgramInfo>();
|
||||||
|
foreach (ScheduleDirect.Program schedule in dailySchedules.SelectMany(d => d.programs))
|
||||||
{
|
{
|
||||||
Url = ApiUrl + "/schedules",
|
// _logger.LogDebug("Proccesing Schedule for statio ID " + stationID +
|
||||||
UserAgent = UserAgent,
|
// " which corresponds to channel " + channelNumber + " and program id " +
|
||||||
CancellationToken = cancellationToken,
|
// schedule.programID + " which says it has images? " +
|
||||||
LogErrorResponseBody = true,
|
// programDict[schedule.programID].hasImageArtwork);
|
||||||
RequestContent = requestString
|
|
||||||
};
|
|
||||||
|
|
||||||
httpOptions.RequestHeaders["token"] = token;
|
if (images != null)
|
||||||
|
|
||||||
using (var response = await Post(httpOptions, true, info).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
var dailySchedules = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Day>>(response.Content).ConfigureAwait(false);
|
|
||||||
_logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId);
|
|
||||||
|
|
||||||
httpOptions = new HttpRequestOptions()
|
|
||||||
{
|
{
|
||||||
Url = ApiUrl + "/programs",
|
var imageIndex = images.FindIndex(i => i.programID == schedule.programID.Substring(0, 10));
|
||||||
UserAgent = UserAgent,
|
if (imageIndex > -1)
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
LogErrorResponseBody = true
|
|
||||||
};
|
|
||||||
|
|
||||||
httpOptions.RequestHeaders["token"] = token;
|
|
||||||
|
|
||||||
var programsID = dailySchedules.SelectMany(d => d.programs.Select(s => s.programID)).Distinct();
|
|
||||||
httpOptions.RequestContent = "[\"" + string.Join("\", \"", programsID) + "\"]";
|
|
||||||
|
|
||||||
using (var innerResponse = await Post(httpOptions, true, info).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
var programDetails = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ProgramDetails>>(innerResponse.Content).ConfigureAwait(false);
|
|
||||||
var programDict = programDetails.ToDictionary(p => p.programID, y => y);
|
|
||||||
|
|
||||||
var programIdsWithImages =
|
|
||||||
programDetails.Where(p => p.hasImageArtwork).Select(p => p.programID)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var images = await GetImageForPrograms(info, programIdsWithImages, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var programsInfo = new List<ProgramInfo>();
|
|
||||||
foreach (ScheduleDirect.Program schedule in dailySchedules.SelectMany(d => d.programs))
|
|
||||||
{
|
{
|
||||||
// _logger.LogDebug("Proccesing Schedule for statio ID " + stationID +
|
var programEntry = programDict[schedule.programID];
|
||||||
// " which corresponds to channel " + channelNumber + " and program id " +
|
|
||||||
// schedule.programID + " which says it has images? " +
|
|
||||||
// programDict[schedule.programID].hasImageArtwork);
|
|
||||||
|
|
||||||
if (images != null)
|
var allImages = images[imageIndex].data ?? new List<ScheduleDirect.ImageData>();
|
||||||
|
var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase));
|
||||||
|
var imagesWithoutText = allImages.Where(i => string.Equals(i.text, "no", StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
const double DesiredAspect = 2.0 / 3;
|
||||||
|
|
||||||
|
programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, true, DesiredAspect) ??
|
||||||
|
GetProgramImage(ApiUrl, allImages, true, DesiredAspect);
|
||||||
|
|
||||||
|
const double WideAspect = 16.0 / 9;
|
||||||
|
|
||||||
|
programEntry.thumbImage = GetProgramImage(ApiUrl, imagesWithText, true, WideAspect);
|
||||||
|
|
||||||
|
// Don't supply the same image twice
|
||||||
|
if (string.Equals(programEntry.primaryImage, programEntry.thumbImage, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
var imageIndex = images.FindIndex(i => i.programID == schedule.programID.Substring(0, 10));
|
programEntry.thumbImage = null;
|
||||||
if (imageIndex > -1)
|
|
||||||
{
|
|
||||||
var programEntry = programDict[schedule.programID];
|
|
||||||
|
|
||||||
var allImages = images[imageIndex].data ?? new List<ScheduleDirect.ImageData>();
|
|
||||||
var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase));
|
|
||||||
var imagesWithoutText = allImages.Where(i => string.Equals(i.text, "no", StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
const double DesiredAspect = 2.0 / 3;
|
|
||||||
|
|
||||||
programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, true, DesiredAspect) ??
|
|
||||||
GetProgramImage(ApiUrl, allImages, true, DesiredAspect);
|
|
||||||
|
|
||||||
const double WideAspect = 16.0 / 9;
|
|
||||||
|
|
||||||
programEntry.thumbImage = GetProgramImage(ApiUrl, imagesWithText, true, WideAspect);
|
|
||||||
|
|
||||||
// Don't supply the same image twice
|
|
||||||
if (string.Equals(programEntry.primaryImage, programEntry.thumbImage, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
programEntry.thumbImage = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect);
|
|
||||||
|
|
||||||
// programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
|
|
||||||
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
|
|
||||||
// GetProgramImage(ApiUrl, data, "Banner-LO", false) ??
|
|
||||||
// GetProgramImage(ApiUrl, data, "Banner-LOT", false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
programsInfo.Add(GetProgram(channelId, schedule, programDict[schedule.programID]));
|
programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect);
|
||||||
}
|
|
||||||
|
|
||||||
return programsInfo;
|
// programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
|
||||||
|
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
|
||||||
|
// GetProgramImage(ApiUrl, data, "Banner-LO", false) ??
|
||||||
|
// GetProgramImage(ApiUrl, data, "Banner-LOT", false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
programsInfo.Add(GetProgram(channelId, schedule, programDict[schedule.programID]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return programsInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetSizeOrder(ScheduleDirect.ImageData image)
|
private static int GetSizeOrder(ScheduleDirect.ImageData image)
|
||||||
@ -483,22 +468,15 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
imageIdString = imageIdString.TrimEnd(',') + "]";
|
imageIdString = imageIdString.TrimEnd(',') + "]";
|
||||||
|
|
||||||
var httpOptions = new HttpRequestOptions()
|
using var message = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/metadata/programs");
|
||||||
{
|
message.Content = new StringContent(imageIdString, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||||
Url = ApiUrl + "/metadata/programs",
|
|
||||||
UserAgent = UserAgent,
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
RequestContent = imageIdString,
|
|
||||||
LogErrorResponseBody = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var innerResponse2 = await Post(httpOptions, true, info).ConfigureAwait(false))
|
using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false);
|
||||||
{
|
await using var response = await innerResponse2.Content.ReadAsStreamAsync();
|
||||||
return await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ShowImages>>(
|
return await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ShowImages>>(
|
||||||
innerResponse2.Content).ConfigureAwait(false);
|
response).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -519,41 +497,33 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
return lineups;
|
return lineups;
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = new HttpRequestOptions()
|
using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/headends?country=" + country + "&postalcode=" + location);
|
||||||
{
|
options.Headers.TryAddWithoutValidation("token", token);
|
||||||
Url = ApiUrl + "/headends?country=" + country + "&postalcode=" + location,
|
|
||||||
UserAgent = UserAgent,
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
LogErrorResponseBody = true
|
|
||||||
};
|
|
||||||
|
|
||||||
options.RequestHeaders["token"] = token;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var httpResponse = await Get(options, false, info).ConfigureAwait(false))
|
using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false);
|
||||||
using (Stream responce = httpResponse.Content)
|
await using var response = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
{
|
|
||||||
var root = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Headends>>(responce).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (root != null)
|
var root = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Headends>>(response).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (root != null)
|
||||||
|
{
|
||||||
|
foreach (ScheduleDirect.Headends headend in root)
|
||||||
{
|
{
|
||||||
foreach (ScheduleDirect.Headends headend in root)
|
foreach (ScheduleDirect.Lineup lineup in headend.lineups)
|
||||||
{
|
{
|
||||||
foreach (ScheduleDirect.Lineup lineup in headend.lineups)
|
lineups.Add(new NameIdPair
|
||||||
{
|
{
|
||||||
lineups.Add(new NameIdPair
|
Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name,
|
||||||
{
|
Id = lineup.uri.Substring(18)
|
||||||
Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name,
|
});
|
||||||
Id = lineup.uri.Substring(18)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
_logger.LogInformation("No lineups available");
|
{
|
||||||
}
|
_logger.LogInformation("No lineups available");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -634,17 +604,16 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<HttpResponseInfo> Post(
|
private async Task<HttpResponseMessage> Send(
|
||||||
HttpRequestOptions options,
|
HttpRequestMessage options,
|
||||||
bool enableRetry,
|
bool enableRetry,
|
||||||
ListingsProviderInfo providerInfo)
|
ListingsProviderInfo providerInfo,
|
||||||
|
CancellationToken cancellationToken,
|
||||||
|
HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead)
|
||||||
{
|
{
|
||||||
// Schedules direct requires that the client support compression and will return a 400 response without it
|
|
||||||
options.DecompressionMethod = CompressionMethods.Deflate;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await _httpClient.Post(options).ConfigureAwait(false);
|
return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, completionOption, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
@ -661,39 +630,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
options.RequestHeaders["token"] = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false);
|
options.Headers.TryAddWithoutValidation("token", await GetToken(providerInfo, cancellationToken).ConfigureAwait(false));
|
||||||
return await Post(options, false, providerInfo).ConfigureAwait(false);
|
return await Send(options, false, providerInfo, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<HttpResponseInfo> Get(
|
|
||||||
HttpRequestOptions options,
|
|
||||||
bool enableRetry,
|
|
||||||
ListingsProviderInfo providerInfo)
|
|
||||||
{
|
|
||||||
// Schedules direct requires that the client support compression and will return a 400 response without it
|
|
||||||
options.DecompressionMethod = CompressionMethods.Deflate;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (HttpException ex)
|
|
||||||
{
|
|
||||||
_tokens.Clear();
|
|
||||||
|
|
||||||
if (!ex.StatusCode.HasValue || (int)ex.StatusCode.Value >= 500)
|
|
||||||
{
|
|
||||||
enableRetry = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!enableRetry)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
options.RequestHeaders["token"] = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false);
|
|
||||||
return await Get(options, false, providerInfo).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> GetTokenInternal(
|
private async Task<string> GetTokenInternal(
|
||||||
@ -701,28 +639,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
string password,
|
string password,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var httpOptions = new HttpRequestOptions()
|
using var options = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/token");
|
||||||
{
|
options.Content = new StringContent("{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}", Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||||
Url = ApiUrl + "/token",
|
|
||||||
UserAgent = UserAgent,
|
|
||||||
RequestContent = "{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}",
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
LogErrorResponseBody = true
|
|
||||||
};
|
|
||||||
// _logger.LogInformation("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " +
|
|
||||||
// httpOptions.RequestContent);
|
|
||||||
|
|
||||||
using (var response = await Post(httpOptions, false, null).ConfigureAwait(false))
|
using var response = await Send(options, false, null, cancellationToken).ConfigureAwait(false);
|
||||||
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
|
var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Token>(stream).ConfigureAwait(false);
|
||||||
|
if (root.message == "OK")
|
||||||
{
|
{
|
||||||
var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Token>(response.Content).ConfigureAwait(false);
|
_logger.LogInformation("Authenticated with Schedules Direct token: " + root.token);
|
||||||
if (root.message == "OK")
|
return root.token;
|
||||||
{
|
|
||||||
_logger.LogInformation("Authenticated with Schedules Direct token: " + root.token);
|
|
||||||
return root.token;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception("Could not authenticate with Schedules Direct Error: " + root.message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new Exception("Could not authenticate with Schedules Direct Error: " + root.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken)
|
private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken)
|
||||||
@ -741,20 +670,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
_logger.LogInformation("Adding new LineUp ");
|
_logger.LogInformation("Adding new LineUp ");
|
||||||
|
|
||||||
var httpOptions = new HttpRequestOptions()
|
using var options = new HttpRequestMessage(HttpMethod.Put, ApiUrl + "/lineups/" + info.ListingsId);
|
||||||
{
|
options.Headers.TryAddWithoutValidation("token", token);
|
||||||
Url = ApiUrl + "/lineups/" + info.ListingsId,
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||||
UserAgent = UserAgent,
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
LogErrorResponseBody = true,
|
|
||||||
BufferContent = false
|
|
||||||
};
|
|
||||||
|
|
||||||
httpOptions.RequestHeaders["token"] = token;
|
|
||||||
|
|
||||||
using (await _httpClient.SendAsync(httpOptions, HttpMethod.Put).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken)
|
private async Task<bool> HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken)
|
||||||
@ -773,25 +691,17 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
_logger.LogInformation("Headends on account ");
|
_logger.LogInformation("Headends on account ");
|
||||||
|
|
||||||
var options = new HttpRequestOptions()
|
using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/lineups");
|
||||||
{
|
options.Headers.TryAddWithoutValidation("token", token);
|
||||||
Url = ApiUrl + "/lineups",
|
|
||||||
UserAgent = UserAgent,
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
LogErrorResponseBody = true
|
|
||||||
};
|
|
||||||
|
|
||||||
options.RequestHeaders["token"] = token;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var httpResponse = await Get(options, false, null).ConfigureAwait(false))
|
using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false);
|
||||||
using (var response = httpResponse.Content)
|
await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
{
|
using var response = httpResponse.Content;
|
||||||
var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Lineups>(response).ConfigureAwait(false);
|
var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Lineups>(stream).ConfigureAwait(false);
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@ -856,55 +766,43 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
throw new Exception("token required");
|
throw new Exception("token required");
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpOptions = new HttpRequestOptions()
|
using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/lineups/" + listingsId);
|
||||||
{
|
options.Headers.TryAddWithoutValidation("token", token);
|
||||||
Url = ApiUrl + "/lineups/" + listingsId,
|
|
||||||
UserAgent = UserAgent,
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
LogErrorResponseBody = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
httpOptions.RequestHeaders["token"] = token;
|
|
||||||
|
|
||||||
var list = new List<ChannelInfo>();
|
var list = new List<ChannelInfo>();
|
||||||
|
|
||||||
using (var httpResponse = await Get(httpOptions, true, info).ConfigureAwait(false))
|
using var httpResponse = await Send(options, true, info, cancellationToken).ConfigureAwait(false);
|
||||||
using (var response = httpResponse.Content)
|
await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
|
var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Channel>(stream).ConfigureAwait(false);
|
||||||
|
_logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.map.Count);
|
||||||
|
_logger.LogInformation("Mapping Stations to Channel");
|
||||||
|
|
||||||
|
var allStations = root.stations ?? Enumerable.Empty<ScheduleDirect.Station>();
|
||||||
|
|
||||||
|
foreach (ScheduleDirect.Map map in root.map)
|
||||||
{
|
{
|
||||||
var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Channel>(response).ConfigureAwait(false);
|
var channelNumber = GetChannelNumber(map);
|
||||||
_logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.map.Count);
|
|
||||||
_logger.LogInformation("Mapping Stations to Channel");
|
|
||||||
|
|
||||||
var allStations = root.stations ?? Enumerable.Empty<ScheduleDirect.Station>();
|
var station = allStations.FirstOrDefault(item => string.Equals(item.stationID, map.stationID, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (station == null)
|
||||||
foreach (ScheduleDirect.Map map in root.map)
|
|
||||||
{
|
{
|
||||||
var channelNumber = GetChannelNumber(map);
|
station = new ScheduleDirect.Station { stationID = map.stationID };
|
||||||
|
|
||||||
var station = allStations.FirstOrDefault(item => string.Equals(item.stationID, map.stationID, StringComparison.OrdinalIgnoreCase));
|
|
||||||
if (station == null)
|
|
||||||
{
|
|
||||||
station = new ScheduleDirect.Station
|
|
||||||
{
|
|
||||||
stationID = map.stationID
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var channelInfo = new ChannelInfo
|
|
||||||
{
|
|
||||||
Id = station.stationID,
|
|
||||||
CallSign = station.callsign,
|
|
||||||
Number = channelNumber,
|
|
||||||
Name = string.IsNullOrWhiteSpace(station.name) ? channelNumber : station.name
|
|
||||||
};
|
|
||||||
|
|
||||||
if (station.logo != null)
|
|
||||||
{
|
|
||||||
channelInfo.ImageUrl = station.logo.URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add(channelInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var channelInfo = new ChannelInfo
|
||||||
|
{
|
||||||
|
Id = station.stationID,
|
||||||
|
CallSign = station.callsign,
|
||||||
|
Number = channelNumber,
|
||||||
|
Name = string.IsNullOrWhiteSpace(station.name) ? channelNumber : station.name
|
||||||
|
};
|
||||||
|
|
||||||
|
if (station.logo != null)
|
||||||
|
{
|
||||||
|
channelInfo.ImageUrl = station.logo.URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add(channelInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
@ -25,20 +25,20 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
public class XmlTvListingsProvider : IListingsProvider
|
public class XmlTvListingsProvider : IListingsProvider
|
||||||
{
|
{
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly ILogger<XmlTvListingsProvider> _logger;
|
private readonly ILogger<XmlTvListingsProvider> _logger;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IZipClient _zipClient;
|
private readonly IZipClient _zipClient;
|
||||||
|
|
||||||
public XmlTvListingsProvider(
|
public XmlTvListingsProvider(
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
ILogger<XmlTvListingsProvider> logger,
|
ILogger<XmlTvListingsProvider> logger,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IZipClient zipClient)
|
IZipClient zipClient)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_zipClient = zipClient;
|
_zipClient = zipClient;
|
||||||
@ -78,28 +78,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(cacheFile));
|
Directory.CreateDirectory(Path.GetDirectoryName(cacheFile));
|
||||||
|
|
||||||
using (var res = await _httpClient.SendAsync(
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false);
|
||||||
new HttpRequestOptions
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
{
|
await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew))
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
Url = path,
|
|
||||||
DecompressionMethod = CompressionMethods.Gzip,
|
|
||||||
},
|
|
||||||
HttpMethod.Get).ConfigureAwait(false))
|
|
||||||
using (var stream = res.Content)
|
|
||||||
using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew))
|
|
||||||
{
|
{
|
||||||
if (res.ContentHeaders.ContentEncoding.Contains("gzip"))
|
await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
|
||||||
{
|
|
||||||
using (var gzStream = new GZipStream(stream, CompressionMode.Decompress))
|
|
||||||
{
|
|
||||||
await gzStream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return UnzipIfNeeded(path, cacheFile);
|
return UnzipIfNeeded(path, cacheFile);
|
||||||
|
@ -31,7 +31,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||||||
{
|
{
|
||||||
public class HdHomerunHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost
|
public class HdHomerunHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost
|
||||||
{
|
{
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly ISocketFactory _socketFactory;
|
private readonly ISocketFactory _socketFactory;
|
||||||
private readonly INetworkManager _networkManager;
|
private readonly INetworkManager _networkManager;
|
||||||
@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
ILogger<HdHomerunHost> logger,
|
ILogger<HdHomerunHost> logger,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
IServerApplicationHost appHost,
|
IServerApplicationHost appHost,
|
||||||
ISocketFactory socketFactory,
|
ISocketFactory socketFactory,
|
||||||
INetworkManager networkManager,
|
INetworkManager networkManager,
|
||||||
@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||||||
IMemoryCache memoryCache)
|
IMemoryCache memoryCache)
|
||||||
: base(config, logger, fileSystem, memoryCache)
|
: base(config, logger, fileSystem, memoryCache)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_socketFactory = socketFactory;
|
_socketFactory = socketFactory;
|
||||||
_networkManager = networkManager;
|
_networkManager = networkManager;
|
||||||
@ -71,15 +71,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||||||
{
|
{
|
||||||
var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
|
var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var options = new HttpRequestOptions
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||||
{
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
Url = model.LineupURL,
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
BufferContent = false
|
|
||||||
};
|
|
||||||
|
|
||||||
using var response = await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false);
|
|
||||||
await using var stream = response.Content;
|
|
||||||
var lineup = await JsonSerializer.DeserializeAsync<List<Channels>>(stream, cancellationToken: cancellationToken)
|
var lineup = await JsonSerializer.DeserializeAsync<List<Channels>>(stream, cancellationToken: cancellationToken)
|
||||||
.ConfigureAwait(false) ?? new List<Channels>();
|
.ConfigureAwait(false) ?? new List<Channels>();
|
||||||
|
|
||||||
@ -133,14 +126,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var response = await _httpClient.SendAsync(
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
new HttpRequestOptions
|
.GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken)
|
||||||
{
|
.ConfigureAwait(false);
|
||||||
Url = string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)),
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
BufferContent = false
|
|
||||||
}, HttpMethod.Get).ConfigureAwait(false);
|
|
||||||
await using var stream = response.Content;
|
|
||||||
var discoverResponse = await JsonSerializer.DeserializeAsync<DiscoverResponse>(stream, cancellationToken: cancellationToken)
|
var discoverResponse = await JsonSerializer.DeserializeAsync<DiscoverResponse>(stream, cancellationToken: cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
@ -183,48 +172,41 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||||||
{
|
{
|
||||||
var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
|
var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
using (var response = await _httpClient.SendAsync(
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
new HttpRequestOptions()
|
.GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken)
|
||||||
{
|
.ConfigureAwait(false);
|
||||||
Url = string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)),
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
CancellationToken = cancellationToken,
|
using var sr = new StreamReader(stream, System.Text.Encoding.UTF8);
|
||||||
BufferContent = false
|
var tuners = new List<LiveTvTunerInfo>();
|
||||||
},
|
while (!sr.EndOfStream)
|
||||||
HttpMethod.Get).ConfigureAwait(false))
|
|
||||||
using (var stream = response.Content)
|
|
||||||
using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8))
|
|
||||||
{
|
{
|
||||||
var tuners = new List<LiveTvTunerInfo>();
|
string line = StripXML(sr.ReadLine());
|
||||||
while (!sr.EndOfStream)
|
if (line.Contains("Channel", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
string line = StripXML(sr.ReadLine());
|
LiveTvTunerStatus status;
|
||||||
if (line.Contains("Channel", StringComparison.Ordinal))
|
var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase);
|
||||||
|
var name = line.Substring(0, index - 1);
|
||||||
|
var currentChannel = line.Substring(index + 7);
|
||||||
|
if (currentChannel != "none")
|
||||||
{
|
{
|
||||||
LiveTvTunerStatus status;
|
status = LiveTvTunerStatus.LiveTv;
|
||||||
var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase);
|
}
|
||||||
var name = line.Substring(0, index - 1);
|
else
|
||||||
var currentChannel = line.Substring(index + 7);
|
{
|
||||||
if (currentChannel != "none")
|
status = LiveTvTunerStatus.Available;
|
||||||
{
|
|
||||||
status = LiveTvTunerStatus.LiveTv;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
status = LiveTvTunerStatus.Available;
|
|
||||||
}
|
|
||||||
|
|
||||||
tuners.Add(new LiveTvTunerInfo
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber,
|
|
||||||
ProgramName = currentChannel,
|
|
||||||
Status = status
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return tuners;
|
tuners.Add(new LiveTvTunerInfo
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber,
|
||||||
|
ProgramName = currentChannel,
|
||||||
|
Status = status
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return tuners;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string StripXML(string source)
|
private static string StripXML(string source)
|
||||||
@ -634,7 +616,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||||||
info,
|
info,
|
||||||
streamId,
|
streamId,
|
||||||
FileSystem,
|
FileSystem,
|
||||||
_httpClient,
|
_httpClientFactory,
|
||||||
Logger,
|
Logger,
|
||||||
Config,
|
Config,
|
||||||
_appHost,
|
_appHost,
|
||||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
@ -26,7 +27,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
{
|
{
|
||||||
public class M3UTunerHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost
|
public class M3UTunerHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost
|
||||||
{
|
{
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly INetworkManager _networkManager;
|
private readonly INetworkManager _networkManager;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
@ -37,14 +38,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
IMediaSourceManager mediaSourceManager,
|
IMediaSourceManager mediaSourceManager,
|
||||||
ILogger<M3UTunerHost> logger,
|
ILogger<M3UTunerHost> logger,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
IServerApplicationHost appHost,
|
IServerApplicationHost appHost,
|
||||||
INetworkManager networkManager,
|
INetworkManager networkManager,
|
||||||
IStreamHelper streamHelper,
|
IStreamHelper streamHelper,
|
||||||
IMemoryCache memoryCache)
|
IMemoryCache memoryCache)
|
||||||
: base(config, logger, fileSystem, memoryCache)
|
: base(config, logger, fileSystem, memoryCache)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_networkManager = networkManager;
|
_networkManager = networkManager;
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
@ -64,7 +65,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
{
|
{
|
||||||
var channelIdPrefix = GetFullChannelIdPrefix(info);
|
var channelIdPrefix = GetFullChannelIdPrefix(info);
|
||||||
|
|
||||||
return await new M3uParser(Logger, _httpClient, _appHost).Parse(info.Url, channelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false);
|
return await new M3uParser(Logger, _httpClientFactory, _appHost).Parse(info.Url, channelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken)
|
public Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken)
|
||||||
@ -116,7 +117,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
|
|
||||||
if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
|
if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config, _appHost, _streamHelper);
|
return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +126,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
|
|
||||||
public async Task Validate(TunerHostInfo info)
|
public async Task Validate(TunerHostInfo info)
|
||||||
{
|
{
|
||||||
using (var stream = await new M3uParser(Logger, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false))
|
using (var stream = await new M3uParser(Logger, _httpClientFactory, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -19,13 +20,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
public class M3uParser
|
public class M3uParser
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
|
|
||||||
public M3uParser(ILogger logger, IHttpClient httpClient, IServerApplicationHost appHost)
|
public M3uParser(ILogger logger, IHttpClientFactory httpClientFactory, IServerApplicationHost appHost)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,13 +52,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
{
|
{
|
||||||
if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return _httpClient.Get(new HttpRequestOptions
|
return _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
{
|
.GetStreamAsync(url);
|
||||||
Url = url,
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
// Some data providers will require a user agent
|
|
||||||
UserAgent = _appHost.ApplicationUserAgent
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult((Stream)File.OpenRead(url));
|
return Task.FromResult((Stream)File.OpenRead(url));
|
||||||
|
@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
{
|
{
|
||||||
public class SharedHttpStream : LiveStream, IDirectStreamProvider
|
public class SharedHttpStream : LiveStream, IDirectStreamProvider
|
||||||
{
|
{
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
|
|
||||||
public SharedHttpStream(
|
public SharedHttpStream(
|
||||||
@ -29,14 +29,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
TunerHostInfo tunerHostInfo,
|
TunerHostInfo tunerHostInfo,
|
||||||
string originalStreamId,
|
string originalStreamId,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IConfigurationManager configurationManager,
|
IConfigurationManager configurationManager,
|
||||||
IServerApplicationHost appHost,
|
IServerApplicationHost appHost,
|
||||||
IStreamHelper streamHelper)
|
IStreamHelper streamHelper)
|
||||||
: base(mediaSource, tunerHostInfo, fileSystem, logger, configurationManager, streamHelper)
|
: base(mediaSource, tunerHostInfo, fileSystem, logger, configurationManager, streamHelper)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
OriginalStreamId = originalStreamId;
|
OriginalStreamId = originalStreamId;
|
||||||
EnableStreamSharing = true;
|
EnableStreamSharing = true;
|
||||||
@ -55,25 +55,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
var typeName = GetType().Name;
|
var typeName = GetType().Name;
|
||||||
Logger.LogInformation("Opening " + typeName + " Live stream from {0}", url);
|
Logger.LogInformation("Opening " + typeName + " Live stream from {0}", url);
|
||||||
|
|
||||||
var httpRequestOptions = new HttpRequestOptions
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
{
|
.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None)
|
||||||
Url = url,
|
.ConfigureAwait(false);
|
||||||
CancellationToken = CancellationToken.None,
|
|
||||||
BufferContent = false,
|
|
||||||
DecompressionMethod = CompressionMethods.None
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var header in mediaSource.RequiredHttpHeaders)
|
|
||||||
{
|
|
||||||
httpRequestOptions.RequestHeaders[header.Key] = header.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var extension = "ts";
|
var extension = "ts";
|
||||||
var requiresRemux = false;
|
var requiresRemux = false;
|
||||||
|
|
||||||
var contentType = response.ContentType ?? string.Empty;
|
var contentType = response.Content.Headers.ContentType.ToString();
|
||||||
if (contentType.IndexOf("matroska", StringComparison.OrdinalIgnoreCase) != -1)
|
if (contentType.IndexOf("matroska", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
{
|
{
|
||||||
requiresRemux = true;
|
requiresRemux = true;
|
||||||
@ -132,24 +121,22 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task StartStreaming(HttpResponseInfo response, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
|
private Task StartStreaming(HttpResponseMessage response, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return Task.Run(async () =>
|
return Task.Run(async () =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath);
|
Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath);
|
||||||
using (response)
|
using var message = response;
|
||||||
using (var stream = response.Content)
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
using (var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||||
{
|
await StreamHelper.CopyToAsync(
|
||||||
await StreamHelper.CopyToAsync(
|
stream,
|
||||||
stream,
|
fileStream,
|
||||||
fileStream,
|
IODefaults.CopyToBufferSize,
|
||||||
IODefaults.CopyToBufferSize,
|
() => Resolve(openTaskCompletionSource),
|
||||||
() => Resolve(openTaskCompletionSource),
|
cancellationToken).ConfigureAwait(false);
|
||||||
cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException ex)
|
catch (OperationCanceledException ex)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger<InstallationManager> _logger;
|
private readonly ILogger<InstallationManager> _logger;
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
@ -63,7 +63,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
ILogger<InstallationManager> logger,
|
ILogger<InstallationManager> logger,
|
||||||
IApplicationHost appHost,
|
IApplicationHost appHost,
|
||||||
IApplicationPaths appPaths,
|
IApplicationPaths appPaths,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
IJsonSerializer jsonSerializer,
|
IJsonSerializer jsonSerializer,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
_applicationHost = appHost;
|
_applicationHost = appHost;
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
_config = config;
|
_config = config;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
@ -116,26 +116,18 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var response = await _httpClient.SendAsync(
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
new HttpRequestOptions
|
.GetAsync(manifest, cancellationToken).ConfigureAwait(false);
|
||||||
{
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
Url = manifest,
|
|
||||||
CancellationToken = cancellationToken,
|
try
|
||||||
CacheMode = CacheMode.Unconditional,
|
|
||||||
CacheLength = TimeSpan.FromMinutes(3)
|
|
||||||
},
|
|
||||||
HttpMethod.Get).ConfigureAwait(false))
|
|
||||||
using (Stream stream = response.Content)
|
|
||||||
{
|
{
|
||||||
try
|
return await _jsonSerializer.DeserializeFromStreamAsync<IReadOnlyList<PackageInfo>>(stream).ConfigureAwait(false);
|
||||||
{
|
}
|
||||||
return await _jsonSerializer.DeserializeFromStreamAsync<IReadOnlyList<PackageInfo>>(stream).ConfigureAwait(false);
|
catch (SerializationException ex)
|
||||||
}
|
{
|
||||||
catch (SerializationException ex)
|
_logger.LogError(ex, "Failed to deserialize the plugin manifest retrieved from {Manifest}", manifest);
|
||||||
{
|
return Array.Empty<PackageInfo>();
|
||||||
_logger.LogError(ex, "Failed to deserialize the plugin manifest retrieved from {Manifest}", manifest);
|
|
||||||
return Array.Empty<PackageInfo>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (UriFormatException ex)
|
catch (UriFormatException ex)
|
||||||
@ -360,42 +352,34 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
// Always override the passed-in target (which is a file) and figure it out again
|
// Always override the passed-in target (which is a file) and figure it out again
|
||||||
string targetDir = Path.Combine(_appPaths.PluginsPath, package.Name);
|
string targetDir = Path.Combine(_appPaths.PluginsPath, package.Name);
|
||||||
|
|
||||||
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
|
.GetAsync(package.SourceUrl, cancellationToken).ConfigureAwait(false);
|
||||||
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
// CA5351: Do Not Use Broken Cryptographic Algorithms
|
// CA5351: Do Not Use Broken Cryptographic Algorithms
|
||||||
#pragma warning disable CA5351
|
#pragma warning disable CA5351
|
||||||
using (var res = await _httpClient.SendAsync(
|
using var md5 = MD5.Create();
|
||||||
new HttpRequestOptions
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
{
|
|
||||||
Url = package.SourceUrl,
|
var hash = Hex.Encode(md5.ComputeHash(stream));
|
||||||
CancellationToken = cancellationToken,
|
if (!string.Equals(package.Checksum, hash, StringComparison.OrdinalIgnoreCase))
|
||||||
// We need it to be buffered for setting the position
|
|
||||||
BufferContent = true
|
|
||||||
},
|
|
||||||
HttpMethod.Get).ConfigureAwait(false))
|
|
||||||
using (var stream = res.Content)
|
|
||||||
using (var md5 = MD5.Create())
|
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
_logger.LogError(
|
||||||
|
"The checksums didn't match while installing {Package}, expected: {Expected}, got: {Received}",
|
||||||
var hash = Hex.Encode(md5.ComputeHash(stream));
|
package.Name,
|
||||||
if (!string.Equals(package.Checksum, hash, StringComparison.OrdinalIgnoreCase))
|
package.Checksum,
|
||||||
{
|
hash);
|
||||||
_logger.LogError(
|
throw new InvalidDataException("The checksum of the received data doesn't match.");
|
||||||
"The checksums didn't match while installing {Package}, expected: {Expected}, got: {Received}",
|
|
||||||
package.Name,
|
|
||||||
package.Checksum,
|
|
||||||
hash);
|
|
||||||
throw new InvalidDataException("The checksum of the received data doesn't match.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Directory.Exists(targetDir))
|
|
||||||
{
|
|
||||||
Directory.Delete(targetDir, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.Position = 0;
|
|
||||||
_zipClient.ExtractAllFromZip(stream, targetDir, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Directory.Exists(targetDir))
|
||||||
|
{
|
||||||
|
Directory.Delete(targetDir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.Position = 0;
|
||||||
|
_zipClient.ExtractAllFromZip(stream, targetDir, true);
|
||||||
|
|
||||||
#pragma warning restore CA5351
|
#pragma warning restore CA5351
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ using Jellyfin.Api.Models.LiveTvDtos;
|
|||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
@ -1069,7 +1070,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public async Task<ActionResult> GetSchedulesDirectCountries()
|
public async Task<ActionResult> GetSchedulesDirectCountries()
|
||||||
{
|
{
|
||||||
var client = _httpClientFactory.CreateClient();
|
var client = _httpClientFactory.CreateClient(NamedClient.Default);
|
||||||
// https://json.schedulesdirect.org/20141201/available/countries
|
// https://json.schedulesdirect.org/20141201/available/countries
|
||||||
// Can't dispose the response as it's required up the call chain.
|
// Can't dispose the response as it's required up the call chain.
|
||||||
var response = await client.GetAsync("https://json.schedulesdirect.org/20141201/available/countries")
|
var response = await client.GetAsync("https://json.schedulesdirect.org/20141201/available/countries")
|
||||||
|
@ -9,6 +9,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -244,7 +245,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
/// <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 httpClient = _httpClientFactory.CreateClient();
|
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
|
||||||
using var response = await httpClient.GetAsync(url).ConfigureAwait(false);
|
using var response = await httpClient.GetAsync(url).ConfigureAwait(false);
|
||||||
var ext = response.Content.Headers.ContentType.MediaType.Split('/').Last();
|
var ext = response.Content.Headers.ContentType.MediaType.Split('/').Last();
|
||||||
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
|
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
|
||||||
|
@ -11,6 +11,7 @@ using Jellyfin.Api.Extensions;
|
|||||||
using Jellyfin.Api.Helpers;
|
using Jellyfin.Api.Helpers;
|
||||||
using Jellyfin.Api.Models.StreamingDtos;
|
using Jellyfin.Api.Models.StreamingDtos;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Devices;
|
using MediaBrowser.Controller.Devices;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
@ -473,7 +474,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
{
|
{
|
||||||
StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager);
|
StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager);
|
||||||
|
|
||||||
var httpClient = _httpClientFactory.CreateClient();
|
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
|
||||||
return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, HttpContext).ConfigureAwait(false);
|
return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, HttpContext).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Api.Models.StreamingDtos;
|
using Jellyfin.Api.Models.StreamingDtos;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Devices;
|
using MediaBrowser.Controller.Devices;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
@ -138,7 +139,7 @@ namespace Jellyfin.Api.Helpers
|
|||||||
{
|
{
|
||||||
StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager);
|
StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager);
|
||||||
|
|
||||||
var httpClient = _httpClientFactory.CreateClient();
|
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
|
||||||
return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, _httpContextAccessor.HttpContext).ConfigureAwait(false);
|
return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, _httpContextAccessor.HttpContext).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
#pragma warning disable CS1591
|
|
||||||
#pragma warning disable SA1602
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Net
|
|
||||||
{
|
|
||||||
public enum CacheMode
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Unconditional = 1
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#pragma warning disable CS1591
|
|
||||||
#pragma warning disable SA1602
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Net
|
|
||||||
{
|
|
||||||
[Flags]
|
|
||||||
public enum CompressionMethods
|
|
||||||
{
|
|
||||||
None = 0b00000001,
|
|
||||||
Deflate = 0b00000010,
|
|
||||||
Gzip = 0b00000100
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
#pragma warning disable CS1591
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using Microsoft.Net.Http.Headers;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Net
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class HttpRequestOptions.
|
|
||||||
/// </summary>
|
|
||||||
public class HttpRequestOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="HttpRequestOptions"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public HttpRequestOptions()
|
|
||||||
{
|
|
||||||
RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
CacheMode = CacheMode.None;
|
|
||||||
DecompressionMethod = CompressionMethods.Deflate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the URL.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The URL.</value>
|
|
||||||
public string Url { get; set; }
|
|
||||||
|
|
||||||
public CompressionMethods DecompressionMethod { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the accept header.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The accept header.</value>
|
|
||||||
public string AcceptHeader
|
|
||||||
{
|
|
||||||
get => GetHeaderValue(HeaderNames.Accept);
|
|
||||||
set => RequestHeaders[HeaderNames.Accept] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the cancellation token.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The cancellation token.</value>
|
|
||||||
public CancellationToken CancellationToken { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user agent.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user agent.</value>
|
|
||||||
public string UserAgent
|
|
||||||
{
|
|
||||||
get => GetHeaderValue(HeaderNames.UserAgent);
|
|
||||||
set => RequestHeaders[HeaderNames.UserAgent] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the referrer.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The referrer.</value>
|
|
||||||
public string Referer
|
|
||||||
{
|
|
||||||
get => GetHeaderValue(HeaderNames.Referer);
|
|
||||||
set => RequestHeaders[HeaderNames.Referer] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the host.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The host.</value>
|
|
||||||
public string Host
|
|
||||||
{
|
|
||||||
get => GetHeaderValue(HeaderNames.Host);
|
|
||||||
set => RequestHeaders[HeaderNames.Host] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<string, string> RequestHeaders { get; private set; }
|
|
||||||
|
|
||||||
public string RequestContentType { get; set; }
|
|
||||||
|
|
||||||
public string RequestContent { get; set; }
|
|
||||||
|
|
||||||
public bool BufferContent { get; set; }
|
|
||||||
|
|
||||||
public bool LogErrorResponseBody { get; set; }
|
|
||||||
|
|
||||||
public bool EnableKeepAlive { get; set; }
|
|
||||||
|
|
||||||
public CacheMode CacheMode { get; set; }
|
|
||||||
|
|
||||||
public TimeSpan CacheLength { get; set; }
|
|
||||||
|
|
||||||
public bool EnableDefaultUserAgent { get; set; }
|
|
||||||
|
|
||||||
private string GetHeaderValue(string name)
|
|
||||||
{
|
|
||||||
RequestHeaders.TryGetValue(name, out var value);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Net
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class HttpResponseInfo.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class HttpResponseInfo : IDisposable
|
|
||||||
{
|
|
||||||
#pragma warning disable CS1591
|
|
||||||
public HttpResponseInfo()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpResponseInfo(HttpResponseHeaders headers, HttpContentHeaders contentHeader)
|
|
||||||
{
|
|
||||||
Headers = headers;
|
|
||||||
ContentHeaders = contentHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning restore CS1591
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the type of the content.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The type of the content.</value>
|
|
||||||
public string ContentType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the response URL.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The response URL.</value>
|
|
||||||
public string ResponseUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the content.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The content.</value>
|
|
||||||
public Stream Content { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the status code.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The status code.</value>
|
|
||||||
public HttpStatusCode StatusCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the temp file path.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The temp file path.</value>
|
|
||||||
public string TempFilePath { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the length of the content.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The length of the content.</value>
|
|
||||||
public long? ContentLength { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the headers.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The headers.</value>
|
|
||||||
public HttpResponseHeaders Headers { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the content headers.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The content headers.</value>
|
|
||||||
public HttpContentHeaders ContentHeaders { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// backwards compatibility
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Net
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interface IHttpClient.
|
|
||||||
/// </summary>
|
|
||||||
public interface IHttpClient
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the response.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
|
||||||
Task<HttpResponseInfo> GetResponse(HttpRequestOptions options);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the specified options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <returns>Task{Stream}.</returns>
|
|
||||||
Task<Stream> Get(HttpRequestOptions options);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Warning: Deprecated function,
|
|
||||||
/// use 'Task{HttpResponseInfo} SendAsync(HttpRequestOptions options, HttpMethod httpMethod);' instead
|
|
||||||
/// Sends the asynchronous.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <param name="httpMethod">The HTTP method.</param>
|
|
||||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
|
||||||
[Obsolete("Use 'Task{HttpResponseInfo} SendAsync(HttpRequestOptions options, HttpMethod httpMethod);' instead")]
|
|
||||||
Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends the asynchronous.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <param name="httpMethod">The HTTP method.</param>
|
|
||||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
|
||||||
Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, HttpMethod httpMethod);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Posts the specified options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
|
||||||
Task<HttpResponseInfo> Post(HttpRequestOptions options);
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BDInfo" Version="0.7.6.1" />
|
<PackageReference Include="BDInfo" Version="0.7.6.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.1" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.1" />
|
||||||
<PackageReference Include="UTF.Unknown" Version="2.3.0" />
|
<PackageReference Include="UTF.Unknown" Version="2.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -6,6 +6,7 @@ using System.Diagnostics;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -31,7 +32,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IMediaEncoder _mediaEncoder;
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -46,7 +47,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
IApplicationPaths appPaths,
|
IApplicationPaths appPaths,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IMediaEncoder mediaEncoder,
|
IMediaEncoder mediaEncoder,
|
||||||
IHttpClient httpClient,
|
IHttpClientFactory httpClientFactory,
|
||||||
IMediaSourceManager mediaSourceManager)
|
IMediaSourceManager mediaSourceManager)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
@ -54,7 +55,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_mediaEncoder = mediaEncoder;
|
_mediaEncoder = mediaEncoder;
|
||||||
_httpClient = httpClient;
|
_httpClientFactory = httpClientFactory;
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,24 +751,20 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<Stream> GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken)
|
private async Task<Stream> GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
switch (protocol)
|
switch (protocol)
|
||||||
{
|
{
|
||||||
case MediaProtocol.Http:
|
case MediaProtocol.Http:
|
||||||
var opts = new HttpRequestOptions()
|
{
|
||||||
{
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
||||||
Url = path,
|
.GetAsync(path, cancellationToken)
|
||||||
CancellationToken = cancellationToken,
|
.ConfigureAwait(false);
|
||||||
|
return await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
// Needed for seeking
|
}
|
||||||
BufferContent = true
|
|
||||||
};
|
|
||||||
|
|
||||||
return _httpClient.Get(opts);
|
|
||||||
|
|
||||||
case MediaProtocol.File:
|
case MediaProtocol.File:
|
||||||
return Task.FromResult<Stream>(File.OpenRead(path));
|
return File.OpenRead(path);
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(protocol));
|
throw new ArgumentOutOfRangeException(nameof(protocol));
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ namespace MediaBrowser.Providers.Manager
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async Task SaveImage(BaseItem item, string url, ImageType type, int? imageIndex, CancellationToken cancellationToken)
|
public async Task SaveImage(BaseItem item, string url, ImageType type, int? imageIndex, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var httpClient = _httpClientFactory.CreateClient();
|
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
|
||||||
using var response = await httpClient.GetAsync(url, cancellationToken).ConfigureAwait(false);
|
using var response = await httpClient.GetAsync(url, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var contentType = response.Content.Headers.ContentType.MediaType;
|
var contentType = response.Content.Headers.ContentType.MediaType;
|
||||||
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
@ -96,7 +97,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var httpClient = _httpClientFactory.CreateClient();
|
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
|
||||||
return httpClient.GetAsync(url, cancellationToken);
|
return httpClient.GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -173,7 +174,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
|
|||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||||
|
|
||||||
using var response = await _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
|
||||||
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
|
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
|
||||||
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
|
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
|
||||||
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
@ -137,7 +138,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var httpClient = _httpClientFactory.CreateClient();
|
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
|
||||||
return httpClient.GetAsync(url, cancellationToken);
|
return httpClient.GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -154,7 +155,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
|
|||||||
|
|
||||||
var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
|
var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
|
||||||
|
|
||||||
using var response = await _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
|
||||||
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||||
|
@ -14,6 +14,7 @@ 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;
|
||||||
@ -765,7 +766,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 _httpClientFactory.CreateClient().SendAsync(options).ConfigureAwait(false);
|
response = await _httpClientFactory.CreateClient(NamedClient.Default).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)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Globalization;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
@ -82,7 +83,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name => "The Open Movie Database";
|
public string Name => "The Open Movie Database";
|
||||||
|
@ -9,6 +9,7 @@ using System.Net.Http;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
@ -129,7 +130,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||||||
|
|
||||||
var url = OmdbProvider.GetOmdbUrl(urlQuery);
|
var url = OmdbProvider.GetOmdbUrl(urlQuery);
|
||||||
|
|
||||||
using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
|
using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
|
||||||
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
var resultList = new List<SearchResult>();
|
var resultList = new List<SearchResult>();
|
||||||
|
|
||||||
@ -274,7 +275,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SearchResult
|
class SearchResult
|
||||||
|
@ -10,6 +10,7 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -296,7 +297,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||||||
"i={0}&plot=short&tomatoes=true&r=json",
|
"i={0}&plot=short&tomatoes=true&r=json",
|
||||||
imdbParam));
|
imdbParam));
|
||||||
|
|
||||||
using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
|
using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
|
||||||
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(stream).ConfigureAwait(false);
|
var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(stream).ConfigureAwait(false);
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||||
@ -334,7 +335,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||||||
imdbParam,
|
imdbParam,
|
||||||
seasonId));
|
seasonId));
|
||||||
|
|
||||||
using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
|
using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
|
||||||
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||||
var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<SeasonRootObject>(stream).ConfigureAwait(false);
|
var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<SeasonRootObject>(stream).ConfigureAwait(false);
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||||
|
@ -6,6 +6,7 @@ using System.Net.Http;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -116,7 +117,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -244,7 +245,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Order => 0;
|
public int Order => 0;
|
||||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
@ -106,7 +107,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -148,7 +149,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
@ -146,7 +147,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ using System.Text;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -410,7 +411,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -155,7 +156,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using System.Net.Http.Headers;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
@ -271,7 +272,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -204,7 +205,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
@ -383,7 +384,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
|||||||
internal Task<HttpResponseMessage> GetMovieDbResponse(HttpRequestMessage message)
|
internal Task<HttpResponseMessage> GetMovieDbResponse(HttpRequestMessage message)
|
||||||
{
|
{
|
||||||
message.Headers.UserAgent.ParseAdd(_appHost.ApplicationUserAgent);
|
message.Headers.UserAgent.ParseAdd(_appHost.ApplicationUserAgent);
|
||||||
return _httpClientFactory.CreateClient().SendAsync(message);
|
return _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -392,7 +393,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -131,7 +132,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -267,7 +268,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using System.Net.Http;
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
@ -138,7 +139,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
|||||||
|
|
||||||
protected Task<HttpResponseMessage> GetResponse(string url, CancellationToken cancellationToken)
|
protected Task<HttpResponseMessage> GetResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -38,7 +39,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
|
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
|
||||||
|
@ -9,6 +9,7 @@ using System.Net.Http;
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
@ -124,7 +125,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<SeasonResult> GetSeasonInfo(string seriesTmdbId, int season, string preferredMetadataLanguage,
|
private async Task<SeasonResult> GetSeasonInfo(string seriesTmdbId, int season, string preferredMetadataLanguage,
|
||||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -182,7 +183,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ using System.Net.Http.Headers;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
@ -551,7 +552,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
@ -36,7 +37,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Trailers
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
@ -122,7 +123,7 @@ namespace MediaBrowser.Providers.Studios
|
|||||||
|
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var httpClient = _httpClientFactory.CreateClient();
|
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
|
||||||
return httpClient.GetAsync(url, cancellationToken);
|
return httpClient.GetAsync(url, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +141,7 @@ namespace MediaBrowser.Providers.Studios
|
|||||||
|
|
||||||
if (!fileInfo.Exists || (DateTime.UtcNow - fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays > 1)
|
if (!fileInfo.Exists || (DateTime.UtcNow - fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays > 1)
|
||||||
{
|
{
|
||||||
var httpClient = _httpClientFactory.CreateClient();
|
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(file));
|
Directory.CreateDirectory(Path.GetDirectoryName(file));
|
||||||
await using var response = await httpClient.GetStreamAsync(url).ConfigureAwait(false);
|
await using var response = await httpClient.GetStreamAsync(url).ConfigureAwait(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user