Merge pull request #1462 from Bond-009/installationmanager

Improvements to InstallationManager
This commit is contained in:
dkanada 2019-08-11 03:47:10 -07:00 committed by GitHub
commit 1ad67e223f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 108 additions and 145 deletions

View file

@ -346,7 +346,7 @@ namespace Emby.Server.Implementations.Activity
}); });
} }
private void OnPluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e) private void OnPluginUpdated(object sender, GenericEventArgs<(IPlugin, PackageVersionInfo)> e)
{ {
CreateLogEntry(new ActivityLogEntry CreateLogEntry(new ActivityLogEntry
{ {

View file

@ -47,6 +47,11 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<!-- We need C# 7.3 to compare tuples-->
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup> </PropertyGroup>

View file

@ -1,4 +1,3 @@
using MediaBrowser.Common;
using MediaBrowser.Common.Updates; using MediaBrowser.Common.Updates;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using System; using System;
@ -25,13 +24,10 @@ namespace Emby.Server.Implementations.ScheduledTasks
private readonly IInstallationManager _installationManager; private readonly IInstallationManager _installationManager;
private readonly IApplicationHost _appHost; public PluginUpdateTask(ILogger logger, IInstallationManager installationManager)
public PluginUpdateTask(ILogger logger, IInstallationManager installationManager, IApplicationHost appHost)
{ {
_logger = logger; _logger = logger;
_installationManager = installationManager; _installationManager = installationManager;
_appHost = appHost;
} }
/// <summary> /// <summary>
@ -40,14 +36,11 @@ namespace Emby.Server.Implementations.ScheduledTasks
/// <returns>IEnumerable{BaseTaskTrigger}.</returns> /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{ {
return new[] { // At startup
yield return new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerStartup };
// At startup
new TaskTriggerInfo {Type = TaskTriggerInfo.TriggerStartup},
// Every so often // Every so often
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks} yield return new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks };
};
} }
/// <summary> /// <summary>
@ -72,7 +65,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
try try
{ {
await _installationManager.InstallPackage(package, true, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false); await _installationManager.InstallPackage(package, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false);
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {

View file

@ -3,6 +3,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
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; using MediaBrowser.Common;
@ -33,7 +34,7 @@ namespace Emby.Server.Implementations.Updates
/// <summary> /// <summary>
/// The current installations /// The current installations
/// </summary> /// </summary>
public List<Tuple<InstallationInfo, CancellationTokenSource>> CurrentInstallations { get; set; } private List<(InstallationInfo info, CancellationTokenSource token)> _currentInstallations { get; set; }
/// <summary> /// <summary>
/// The completed installations /// The completed installations
@ -47,49 +48,15 @@ namespace Emby.Server.Implementations.Updates
/// </summary> /// </summary>
public event EventHandler<GenericEventArgs<IPlugin>> PluginUninstalled; public event EventHandler<GenericEventArgs<IPlugin>> PluginUninstalled;
/// <summary>
/// Called when [plugin uninstalled].
/// </summary>
/// <param name="plugin">The plugin.</param>
private void OnPluginUninstalled(IPlugin plugin)
{
PluginUninstalled?.Invoke(this, new GenericEventArgs<IPlugin> { Argument = plugin });
}
/// <summary> /// <summary>
/// Occurs when [plugin updated]. /// Occurs when [plugin updated].
/// </summary> /// </summary>
public event EventHandler<GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>>> PluginUpdated; public event EventHandler<GenericEventArgs<(IPlugin, PackageVersionInfo)>> PluginUpdated;
/// <summary>
/// Called when [plugin updated].
/// </summary>
/// <param name="plugin">The plugin.</param>
/// <param name="newVersion">The new version.</param>
private void OnPluginUpdated(IPlugin plugin, PackageVersionInfo newVersion)
{
_logger.LogInformation("Plugin updated: {0} {1} {2}", newVersion.name, newVersion.versionStr ?? string.Empty, newVersion.classification);
PluginUpdated?.Invoke(this, new GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> { Argument = new Tuple<IPlugin, PackageVersionInfo>(plugin, newVersion) });
_applicationHost.NotifyPendingRestart();
}
/// <summary> /// <summary>
/// Occurs when [plugin updated]. /// Occurs when [plugin updated].
/// </summary> /// </summary>
public event EventHandler<GenericEventArgs<PackageVersionInfo>> PluginInstalled; public event EventHandler<GenericEventArgs<PackageVersionInfo>> PluginInstalled;
/// <summary>
/// Called when [plugin installed].
/// </summary>
/// <param name="package">The package.</param>
private void OnPluginInstalled(PackageVersionInfo package)
{
_logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification);
PluginInstalled?.Invoke(this, new GenericEventArgs<PackageVersionInfo> { Argument = package });
_applicationHost.NotifyPendingRestart();
}
/// <summary> /// <summary>
/// The _logger /// The _logger
@ -111,7 +78,7 @@ namespace Emby.Server.Implementations.Updates
private readonly IZipClient _zipClient; private readonly IZipClient _zipClient;
public InstallationManager( public InstallationManager(
ILoggerFactory loggerFactory, ILogger<InstallationManager> logger,
IApplicationHost appHost, IApplicationHost appHost,
IApplicationPaths appPaths, IApplicationPaths appPaths,
IHttpClient httpClient, IHttpClient httpClient,
@ -120,15 +87,15 @@ namespace Emby.Server.Implementations.Updates
IFileSystem fileSystem, IFileSystem fileSystem,
IZipClient zipClient) IZipClient zipClient)
{ {
if (loggerFactory == null) if (logger == null)
{ {
throw new ArgumentNullException(nameof(loggerFactory)); throw new ArgumentNullException(nameof(logger));
} }
CurrentInstallations = new List<Tuple<InstallationInfo, CancellationTokenSource>>(); _currentInstallations = new List<(InstallationInfo, CancellationTokenSource)>();
_completedInstallationsInternal = new ConcurrentBag<InstallationInfo>(); _completedInstallationsInternal = new ConcurrentBag<InstallationInfo>();
_logger = loggerFactory.CreateLogger(nameof(InstallationManager)); _logger = logger;
_applicationHost = appHost; _applicationHost = appHost;
_appPaths = appPaths; _appPaths = appPaths;
_httpClient = httpClient; _httpClient = httpClient;
@ -138,21 +105,12 @@ namespace Emby.Server.Implementations.Updates
_zipClient = zipClient; _zipClient = zipClient;
} }
private static Version GetPackageVersion(PackageVersionInfo version)
{
return new Version(ValueOrDefault(version.versionStr, "0.0.0.1"));
}
private static string ValueOrDefault(string str, string def)
{
return string.IsNullOrEmpty(str) ? def : str;
}
/// <summary> /// <summary>
/// Gets all available packages. /// Gets all available packages.
/// </summary> /// </summary>
/// <returns>Task{List{PackageInfo}}.</returns> /// <returns>Task{List{PackageInfo}}.</returns>
public async Task<List<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken, public async Task<List<PackageInfo>> GetAvailablePackages(
CancellationToken cancellationToken,
bool withRegistration = true, bool withRegistration = true,
string packageType = null, string packageType = null,
Version applicationVersion = null) Version applicationVersion = null)
@ -172,22 +130,14 @@ namespace Emby.Server.Implementations.Updates
{ {
Url = "https://repo.jellyfin.org/releases/plugin/manifest.json", Url = "https://repo.jellyfin.org/releases/plugin/manifest.json",
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
Progress = new SimpleProgress<double>(),
CacheLength = GetCacheLength() CacheLength = GetCacheLength()
}, "GET").ConfigureAwait(false)) }, HttpMethod.Get).ConfigureAwait(false))
using (var stream = response.Content)
{ {
using (var stream = response.Content) return FilterPackages(await _jsonSerializer.DeserializeFromStreamAsync<PackageInfo[]>(stream).ConfigureAwait(false));
{
return FilterPackages(await _jsonSerializer.DeserializeFromStreamAsync<PackageInfo[]>(stream).ConfigureAwait(false));
}
} }
} }
private PackageVersionClass GetSystemUpdateLevel()
{
return _applicationHost.SystemUpdateLevel;
}
private static TimeSpan GetCacheLength() private static TimeSpan GetCacheLength()
{ {
return TimeSpan.FromMinutes(3); return TimeSpan.FromMinutes(3);
@ -211,7 +161,7 @@ namespace Emby.Server.Implementations.Updates
} }
package.versions = versions package.versions = versions
.OrderByDescending(GetPackageVersion) .OrderByDescending(x => x.Version)
.ToArray(); .ToArray();
if (package.versions.Length == 0) if (package.versions.Length == 0)
@ -294,7 +244,7 @@ namespace Emby.Server.Implementations.Updates
return null; return null;
} }
return package.versions.FirstOrDefault(v => GetPackageVersion(v).Equals(version) && v.classification == classification); return package.versions.FirstOrDefault(v => v.Version == version && v.classification == classification);
} }
/// <summary> /// <summary>
@ -331,7 +281,7 @@ namespace Emby.Server.Implementations.Updates
} }
return package.versions return package.versions
.OrderByDescending(GetPackageVersion) .OrderByDescending(x => x.Version)
.FirstOrDefault(v => v.classification <= classification && IsPackageVersionUpToDate(v, currentServerVersion)); .FirstOrDefault(v => v.classification <= classification && IsPackageVersionUpToDate(v, currentServerVersion));
} }
@ -346,14 +296,14 @@ namespace Emby.Server.Implementations.Updates
{ {
var catalog = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false); var catalog = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
var systemUpdateLevel = GetSystemUpdateLevel(); var systemUpdateLevel = _applicationHost.SystemUpdateLevel;
// Figure out what needs to be installed // Figure out what needs to be installed
return _applicationHost.Plugins.Select(p => return _applicationHost.Plugins.Select(p =>
{ {
var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, systemUpdateLevel); var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, systemUpdateLevel);
return latestPluginInfo != null && GetPackageVersion(latestPluginInfo) > p.Version ? latestPluginInfo : null; return latestPluginInfo != null && latestPluginInfo.Version > p.Version ? latestPluginInfo : null;
}).Where(i => i != null) }).Where(i => i != null)
.Where(p => !string.IsNullOrEmpty(p.sourceUrl) && !CompletedInstallations.Any(i => string.Equals(i.AssemblyGuid, p.guid, StringComparison.OrdinalIgnoreCase))); .Where(p => !string.IsNullOrEmpty(p.sourceUrl) && !CompletedInstallations.Any(i => string.Equals(i.AssemblyGuid, p.guid, StringComparison.OrdinalIgnoreCase)));
@ -368,7 +318,7 @@ namespace Emby.Server.Implementations.Updates
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
/// <exception cref="ArgumentNullException">package</exception> /// <exception cref="ArgumentNullException">package</exception>
public async Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken) public async Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken)
{ {
if (package == null) if (package == null)
{ {
@ -391,12 +341,12 @@ namespace Emby.Server.Implementations.Updates
var innerCancellationTokenSource = new CancellationTokenSource(); var innerCancellationTokenSource = new CancellationTokenSource();
var tuple = new Tuple<InstallationInfo, CancellationTokenSource>(installationInfo, innerCancellationTokenSource); var tuple = (installationInfo, innerCancellationTokenSource);
// Add it to the in-progress list // Add it to the in-progress list
lock (CurrentInstallations) lock (_currentInstallations)
{ {
CurrentInstallations.Add(tuple); _currentInstallations.Add(tuple);
} }
var innerProgress = new ActionableProgress<double>(); var innerProgress = new ActionableProgress<double>();
@ -421,11 +371,11 @@ namespace Emby.Server.Implementations.Updates
try try
{ {
await InstallPackageInternal(package, isPlugin, innerProgress, linkedToken).ConfigureAwait(false); await InstallPackageInternal(package, innerProgress, linkedToken).ConfigureAwait(false);
lock (CurrentInstallations) lock (_currentInstallations)
{ {
CurrentInstallations.Remove(tuple); _currentInstallations.Remove(tuple);
} }
_completedInstallationsInternal.Add(installationInfo); _completedInstallationsInternal.Add(installationInfo);
@ -434,9 +384,9 @@ namespace Emby.Server.Implementations.Updates
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
lock (CurrentInstallations) lock (_currentInstallations)
{ {
CurrentInstallations.Remove(tuple); _currentInstallations.Remove(tuple);
} }
_logger.LogInformation("Package installation cancelled: {0} {1}", package.name, package.versionStr); _logger.LogInformation("Package installation cancelled: {0} {1}", package.name, package.versionStr);
@ -449,9 +399,9 @@ namespace Emby.Server.Implementations.Updates
{ {
_logger.LogError(ex, "Package installation failed"); _logger.LogError(ex, "Package installation failed");
lock (CurrentInstallations) lock (_currentInstallations)
{ {
CurrentInstallations.Remove(tuple); _currentInstallations.Remove(tuple);
} }
PackageInstallationFailed?.Invoke(this, new InstallationFailedEventArgs PackageInstallationFailed?.Invoke(this, new InstallationFailedEventArgs
@ -477,16 +427,11 @@ namespace Emby.Server.Implementations.Updates
/// <param name="progress">The progress.</param> /// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
private async Task InstallPackageInternal(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken) private async Task InstallPackageInternal(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken)
{ {
IPlugin plugin = null; // Set last update time if we were installed before
IPlugin plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
if (isPlugin)
{
// Set last update time if we were installed before
plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase)); ?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase));
}
string targetPath = plugin == null ? null : plugin.AssemblyFilePath; string targetPath = plugin == null ? null : plugin.AssemblyFilePath;
@ -494,17 +439,20 @@ namespace Emby.Server.Implementations.Updates
await PerformPackageInstallation(progress, targetPath, package, cancellationToken).ConfigureAwait(false); await PerformPackageInstallation(progress, targetPath, package, cancellationToken).ConfigureAwait(false);
// Do plugin-specific processing // Do plugin-specific processing
if (isPlugin) if (plugin == null)
{ {
if (plugin == null) _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification);
{
OnPluginInstalled(package); PluginInstalled?.Invoke(this, new GenericEventArgs<PackageVersionInfo>(package));
}
else
{
OnPluginUpdated(plugin, package);
}
} }
else
{
_logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification);
PluginUpdated?.Invoke(this, new GenericEventArgs<(IPlugin, PackageVersionInfo)>((plugin, package)));
}
_applicationHost.NotifyPendingRestart();
} }
private async Task PerformPackageInstallation(IProgress<double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken) private async Task PerformPackageInstallation(IProgress<double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken)
@ -622,11 +570,34 @@ namespace Emby.Server.Implementations.Updates
_config.SaveConfiguration(); _config.SaveConfiguration();
} }
OnPluginUninstalled(plugin); PluginUninstalled?.Invoke(this, new GenericEventArgs<IPlugin> { Argument = plugin });
_applicationHost.NotifyPendingRestart(); _applicationHost.NotifyPendingRestart();
} }
/// <inheritdoc/>
public bool CancelInstallation(Guid id)
{
lock (_currentInstallations)
{
var install = _currentInstallations.Find(x => x.Item1.Id == id);
if (install == default((InstallationInfo, CancellationTokenSource)))
{
return false;
}
install.Item2.Cancel();
_currentInstallations.Remove(install);
return true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary> /// <summary>
/// Releases unmanaged and - optionally - managed resources. /// Releases unmanaged and - optionally - managed resources.
/// </summary> /// </summary>
@ -635,21 +606,16 @@ namespace Emby.Server.Implementations.Updates
{ {
if (dispose) if (dispose)
{ {
lock (CurrentInstallations) lock (_currentInstallations)
{ {
foreach (var tuple in CurrentInstallations) foreach (var tuple in _currentInstallations)
{ {
tuple.Item2.Dispose(); tuple.Item2.Dispose();
} }
CurrentInstallations.Clear(); _currentInstallations.Clear();
} }
} }
} }
public void Dispose()
{
Dispose(true);
}
} }
} }

View file

@ -197,7 +197,7 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name)); throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name));
} }
await _installationManager.InstallPackage(package, true, new SimpleProgress<double>(), CancellationToken.None); await _installationManager.InstallPackage(package, new SimpleProgress<double>(), CancellationToken.None);
} }
/// <summary> /// <summary>
@ -206,13 +206,7 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
public void Delete(CancelPackageInstallation request) public void Delete(CancelPackageInstallation request)
{ {
var info = _installationManager.CurrentInstallations.FirstOrDefault(i => i.Item1.Id.Equals(request.Id)); _installationManager.CancelInstallation(new Guid(request.Id));
if (info != null)
{
info.Item2.Cancel();
}
} }
} }
} }

View file

@ -15,11 +15,6 @@ namespace MediaBrowser.Common.Updates
event EventHandler<InstallationFailedEventArgs> PackageInstallationFailed; event EventHandler<InstallationFailedEventArgs> PackageInstallationFailed;
event EventHandler<InstallationEventArgs> PackageInstallationCancelled; event EventHandler<InstallationEventArgs> PackageInstallationCancelled;
/// <summary>
/// The current installations
/// </summary>
List<Tuple<InstallationInfo, CancellationTokenSource>> CurrentInstallations { get; set; }
/// <summary> /// <summary>
/// The completed installations /// The completed installations
/// </summary> /// </summary>
@ -33,7 +28,7 @@ namespace MediaBrowser.Common.Updates
/// <summary> /// <summary>
/// Occurs when [plugin updated]. /// Occurs when [plugin updated].
/// </summary> /// </summary>
event EventHandler<GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>>> PluginUpdated; event EventHandler<GenericEventArgs<(IPlugin, PackageVersionInfo)>> PluginUpdated;
/// <summary> /// <summary>
/// Occurs when [plugin updated]. /// Occurs when [plugin updated].
@ -107,7 +102,7 @@ namespace MediaBrowser.Common.Updates
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
/// <exception cref="ArgumentNullException">package</exception> /// <exception cref="ArgumentNullException">package</exception>
Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken); Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Uninstalls a plugin /// Uninstalls a plugin
@ -115,5 +110,12 @@ namespace MediaBrowser.Common.Updates
/// <param name="plugin">The plugin.</param> /// <param name="plugin">The plugin.</param>
/// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentException"></exception>
void UninstallPlugin(IPlugin plugin); void UninstallPlugin(IPlugin plugin);
/// <summary>
/// Cancels the installation
/// </summary>
/// <param name="id">The id of the package that is being installed</param>
/// <returns>Returns true if the install was cancelled</returns>
bool CancelInstallation(Guid id);
} }
} }

View file

@ -30,23 +30,25 @@ namespace MediaBrowser.Model.Updates
/// The _version /// The _version
/// </summary> /// </summary>
private Version _version; private Version _version;
/// <summary> /// <summary>
/// Gets or sets the version. /// Gets or sets the version.
/// Had to make this an interpreted property since Protobuf can't handle Version /// Had to make this an interpreted property since Protobuf can't handle Version
/// </summary> /// </summary>
/// <value>The version.</value> /// <value>The version.</value>
[IgnoreDataMember] [IgnoreDataMember]
public Version version => _version ?? (_version = new Version(ValueOrDefault(versionStr, "0.0.0.1"))); public Version Version
/// <summary>
/// Values the or default.
/// </summary>
/// <param name="str">The STR.</param>
/// <param name="def">The def.</param>
/// <returns>System.String.</returns>
private static string ValueOrDefault(string str, string def)
{ {
return string.IsNullOrEmpty(str) ? def : str; get
{
if (_version == null)
{
var ver = versionStr;
_version = new Version(string.IsNullOrEmpty(ver) ? "0.0.0.1" : ver);
}
return _version;
}
} }
/// <summary> /// <summary>

View file

@ -3,6 +3,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; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -347,7 +348,7 @@ namespace MediaBrowser.Providers.Omdb
CancellationToken = cancellationToken, CancellationToken = cancellationToken,
BufferContent = true, BufferContent = true,
EnableDefaultUserAgent = true EnableDefaultUserAgent = true
}, "GET"); }, HttpMethod.Get);
} }
internal string GetDataFilePath(string imdbId) internal string GetDataFilePath(string imdbId)