aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordkanada <dkanada@users.noreply.github.com>2021-02-25 17:17:34 +0900
committerJoshua M. Boniface <joshua@boniface.me>2021-02-26 21:01:50 -0500
commiteb0621a3549b6ca8532376396217d19b680b325e (patch)
tree92df47e48f69cc012aaedac7e283d1275165a863
parent621c0b9d154580a90da5463521088e8e1c4e74f1 (diff)
Merge pull request #5217 from jellyfin/auto-manifest
handle plugin manifests automatically (cherry picked from commit c54ca489f1fc3cbf12c4b7714389fe80f4038f84) Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
-rw-r--r--Emby.Server.Implementations/Plugins/PluginManager.cs93
-rw-r--r--Emby.Server.Implementations/Updates/InstallationManager.cs22
-rw-r--r--MediaBrowser.Common/Plugins/IPluginManager.cs10
-rw-r--r--MediaBrowser.Model/Updates/InstallationInfo.cs7
4 files changed, 99 insertions, 33 deletions
diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs
index 51e9ba1ef..56cfbfc97 100644
--- a/Emby.Server.Implementations/Plugins/PluginManager.cs
+++ b/Emby.Server.Implementations/Plugins/PluginManager.cs
@@ -1,8 +1,10 @@
#nullable enable
+
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Text.Json;
@@ -11,9 +13,11 @@ using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Json;
using MediaBrowser.Common.Json.Converters;
+using MediaBrowser.Common.Net;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Plugins;
+using MediaBrowser.Model.Updates;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@@ -33,6 +37,21 @@ namespace Emby.Server.Implementations.Plugins
private readonly IList<LocalPlugin> _plugins;
private readonly Version _minimumVersion;
+ private IHttpClientFactory? _httpClientFactory;
+
+ private IHttpClientFactory HttpClientFactory
+ {
+ get
+ {
+ if (_httpClientFactory == null)
+ {
+ _httpClientFactory = _appHost.Resolve<IHttpClientFactory>();
+ }
+
+ return _httpClientFactory;
+ }
+ }
+
/// <summary>
/// Initializes a new instance of the <see cref="PluginManager"/> class.
/// </summary>
@@ -332,32 +351,74 @@ namespace Emby.Server.Implementations.Plugins
ChangePluginState(plugin, PluginStatus.Malfunctioned);
}
- /// <summary>
- /// Saves the manifest back to disk.
- /// </summary>
- /// <param name="manifest">The <see cref="PluginManifest"/> to save.</param>
- /// <param name="path">The path where to save the manifest.</param>
- /// <returns>True if successful.</returns>
+ /// <inheritdoc/>
public bool SaveManifest(PluginManifest manifest, string path)
{
- if (manifest == null)
- {
- return false;
- }
-
try
{
var data = JsonSerializer.Serialize(manifest, _jsonOptions);
File.WriteAllText(Path.Combine(path, "meta.json"), data);
return true;
}
-#pragma warning disable CA1031 // Do not catch general exception types
- catch (Exception e)
-#pragma warning restore CA1031 // Do not catch general exception types
+ catch (ArgumentException e)
+ {
+ _logger.LogWarning(e, "Unable to save plugin manifest due to invalid value. {Path}", path);
+ return false;
+ }
+ }
+
+ /// <inheritdoc/>
+ public async Task<bool> GenerateManifest(PackageInfo packageInfo, Version version, string path)
+ {
+ if (packageInfo == null)
{
- _logger.LogWarning(e, "Unable to save plugin manifest. {Path}", path);
return false;
}
+
+ var versionInfo = packageInfo.Versions.First(v => v.Version == version.ToString());
+ var imagePath = string.Empty;
+
+ if (!string.IsNullOrEmpty(packageInfo.ImageUrl))
+ {
+ var url = new Uri(packageInfo.ImageUrl);
+ imagePath = Path.Join(path, url.Segments[^1]);
+
+ await using var fileStream = File.OpenWrite(imagePath);
+
+ try
+ {
+ await using var downloadStream = await HttpClientFactory
+ .CreateClient(NamedClient.Default)
+ .GetStreamAsync(url)
+ .ConfigureAwait(false);
+
+ await downloadStream.CopyToAsync(fileStream).ConfigureAwait(false);
+ }
+ catch (HttpRequestException ex)
+ {
+ _logger.LogError(ex, "Failed to download image to path {Path} on disk.", imagePath);
+ imagePath = string.Empty;
+ }
+ }
+
+ var manifest = new PluginManifest
+ {
+ Category = packageInfo.Category,
+ Changelog = versionInfo.Changelog ?? string.Empty,
+ Description = packageInfo.Description,
+ Id = new Guid(packageInfo.Id),
+ Name = packageInfo.Name,
+ Overview = packageInfo.Overview,
+ Owner = packageInfo.Owner,
+ TargetAbi = versionInfo.TargetAbi ?? string.Empty,
+ Timestamp = string.IsNullOrEmpty(versionInfo.Timestamp) ? DateTime.MinValue : DateTime.Parse(versionInfo.Timestamp),
+ Version = versionInfo.Version,
+ Status = PluginStatus.Active,
+ AutoUpdate = true,
+ ImagePath = imagePath
+ };
+
+ return SaveManifest(manifest, path);
}
/// <summary>
@@ -410,7 +471,7 @@ namespace Emby.Server.Implementations.Plugins
if (plugin == null)
{
// Create a dummy record for the providers.
- // TODO: remove this code, if all provided have been released as separate plugins.
+ // TODO: remove this code once all provided have been released as separate plugins.
plugin = new LocalPlugin(
instance.AssemblyFilePath,
true,
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index abcb4313f..7af52ea65 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -192,17 +192,12 @@ namespace Emby.Server.Implementations.Updates
var version = package.Versions[i];
var plugin = _pluginManager.GetPlugin(packageGuid, version.VersionNumber);
- // Update the manifests, if anything changes.
if (plugin != null)
{
- if (!string.Equals(plugin.Manifest.TargetAbi, version.TargetAbi, StringComparison.Ordinal))
- {
- plugin.Manifest.TargetAbi = version.TargetAbi ?? string.Empty;
- _pluginManager.SaveManifest(plugin.Manifest, plugin.Path);
- }
+ await _pluginManager.GenerateManifest(package, version.VersionNumber, plugin.Path);
}
- // Remove versions with a target abi that is greater then the current application version.
+ // Remove versions with a target ABI greater then the current application version.
if (Version.TryParse(version.TargetAbi, out var targetAbi) && _applicationHost.ApplicationVersion < targetAbi)
{
package.Versions.RemoveAt(i);
@@ -294,7 +289,8 @@ namespace Emby.Server.Implementations.Updates
Name = package.Name,
Version = v.VersionNumber,
SourceUrl = v.SourceUrl,
- Checksum = v.Checksum
+ Checksum = v.Checksum,
+ PackageInfo = package
};
}
}
@@ -571,24 +567,16 @@ namespace Emby.Server.Implementations.Updates
stream.Position = 0;
_zipClient.ExtractAllFromZip(stream, targetDir, true);
+ await _pluginManager.GenerateManifest(package.PackageInfo, package.Version, targetDir);
_pluginManager.ImportPluginFrom(targetDir);
}
private async Task<bool> InstallPackageInternal(InstallationInfo package, CancellationToken cancellationToken)
{
- // Set last update time if we were installed before
LocalPlugin? plugin = _pluginManager.Plugins.FirstOrDefault(p => p.Id.Equals(package.Id) && p.Version.Equals(package.Version))
?? _pluginManager.Plugins.FirstOrDefault(p => p.Name.Equals(package.Name, StringComparison.OrdinalIgnoreCase) && p.Version.Equals(package.Version));
- if (plugin != null)
- {
- plugin.Manifest.Timestamp = DateTime.UtcNow;
- _pluginManager.SaveManifest(plugin.Manifest, plugin.Path);
- }
- // Do the install
await PerformPackageInstallation(package, cancellationToken).ConfigureAwait(false);
-
- // Do plugin-specific processing
_logger.LogInformation(plugin == null ? "New plugin installed: {PluginName} {PluginVersion}" : "Plugin updated: {PluginName} {PluginVersion}", package.Name, package.Version);
return plugin != null;
diff --git a/MediaBrowser.Common/Plugins/IPluginManager.cs b/MediaBrowser.Common/Plugins/IPluginManager.cs
index 3da34d8bb..fc2fcb517 100644
--- a/MediaBrowser.Common/Plugins/IPluginManager.cs
+++ b/MediaBrowser.Common/Plugins/IPluginManager.cs
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
+using MediaBrowser.Model.Updates;
using Microsoft.Extensions.DependencyInjection;
namespace MediaBrowser.Common.Plugins
@@ -45,6 +46,15 @@ namespace MediaBrowser.Common.Plugins
bool SaveManifest(PluginManifest manifest, string path);
/// <summary>
+ /// Generates a manifest from repository data.
+ /// </summary>
+ /// <param name="packageInfo">The <see cref="PackageInfo"/> used to generate a manifest.</param>
+ /// <param name="version">Version to be installed.</param>
+ /// <param name="path">The path where to save the manifest.</param>
+ /// <returns>True if successful.</returns>
+ Task<bool> GenerateManifest(PackageInfo packageInfo, Version version, string path);
+
+ /// <summary>
/// Imports plugin details from a folder.
/// </summary>
/// <param name="folder">Folder of the plugin.</param>
diff --git a/MediaBrowser.Model/Updates/InstallationInfo.cs b/MediaBrowser.Model/Updates/InstallationInfo.cs
index eebe1a903..cc600de9d 100644
--- a/MediaBrowser.Model/Updates/InstallationInfo.cs
+++ b/MediaBrowser.Model/Updates/InstallationInfo.cs
@@ -1,4 +1,5 @@
#nullable disable
+
using System;
using System.Text.Json.Serialization;
@@ -45,5 +46,11 @@ namespace MediaBrowser.Model.Updates
/// </summary>
/// <value>The checksum.</value>
public string Checksum { get; set; }
+
+ /// <summary>
+ /// Gets or sets package information for the installation.
+ /// </summary>
+ /// <value>The package information.</value>
+ public PackageInfo PackageInfo { get; set; }
}
}