Skip to content

Commit

Permalink
[Neo CLI New Feature] Allow custom plugins (#3295)
Browse files Browse the repository at this point in the history
* allow custom plugins

* use command instead.

---------

Co-authored-by: Shargon <[email protected]>
Co-authored-by: NGD Admin <[email protected]>
  • Loading branch information
3 people authored Jun 14, 2024
1 parent a6dff23 commit e0ba897
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 16 deletions.
23 changes: 14 additions & 9 deletions src/Neo.CLI/CLI/MainService.Plugins.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,17 @@ partial class MainService
/// Process "install" command
/// </summary>
/// <param name="pluginName">Plugin name</param>
/// <param name="downloadUrl">Custom plugins download url, this is optional.</param>
[ConsoleCommand("install", Category = "Plugin Commands")]
private void OnInstallCommand(string pluginName)
private void OnInstallCommand(string pluginName, string? downloadUrl = null)
{
if (PluginExists(pluginName))
{
ConsoleHelper.Warning($"Plugin already exist.");
return;
}

var result = InstallPluginAsync(pluginName).GetAwaiter().GetResult();
var result = InstallPluginAsync(pluginName, downloadUrl).GetAwaiter().GetResult();
if (result)
{
var asmName = Assembly.GetExecutingAssembly().GetName().Name;
Expand Down Expand Up @@ -74,16 +75,17 @@ private void OnReinstallCommand(string pluginName)
/// </summary>
/// <param name="pluginName">name of the plugin</param>
/// <param name="pluginVersion"></param>
/// <param name="customDownloadUrl">Custom plugin download url.</param>
/// <param name="prerelease"></param>
/// <returns>Downloaded content</returns>
private static async Task<Stream> DownloadPluginAsync(string pluginName, Version pluginVersion, bool prerelease = false)
private static async Task<Stream> DownloadPluginAsync(string pluginName, Version pluginVersion, string? customDownloadUrl = null, bool prerelease = false)
{
using var httpClient = new HttpClient();

var asmName = Assembly.GetExecutingAssembly().GetName();
httpClient.DefaultRequestHeaders.UserAgent.Add(new(asmName.Name!, asmName.Version!.ToString(3)));

var json = await httpClient.GetFromJsonAsync<JsonArray>(Settings.Default.Plugins.DownloadUrl) ?? throw new HttpRequestException($"Failed: {Settings.Default.Plugins.DownloadUrl}");
var url = customDownloadUrl == null ? Settings.Default.Plugins.DownloadUrl : new Uri(customDownloadUrl);
var json = await httpClient.GetFromJsonAsync<JsonArray>(url) ?? throw new HttpRequestException($"Failed: {url}");
var jsonRelease = json.AsArray()
.SingleOrDefault(s =>
s != null &&
Expand All @@ -110,10 +112,12 @@ private static async Task<Stream> DownloadPluginAsync(string pluginName, Version
/// Install plugin from stream
/// </summary>
/// <param name="pluginName">Name of the plugin</param>
/// <param name="downloadUrl">Custom plugins download url.</param>
/// <param name="installed">Dependency set</param>
/// <param name="overWrite">Install by force for `update`</param>
private async Task<bool> InstallPluginAsync(
string pluginName,
string? downloadUrl = null,
HashSet<string>? installed = null,
bool overWrite = false)
{
Expand All @@ -124,14 +128,14 @@ private async Task<bool> InstallPluginAsync(
try
{

using var stream = await DownloadPluginAsync(pluginName, Settings.Default.Plugins.Version, Settings.Default.Plugins.Prerelease);
using var stream = await DownloadPluginAsync(pluginName, Settings.Default.Plugins.Version, downloadUrl, Settings.Default.Plugins.Prerelease);

using var zip = new ZipArchive(stream, ZipArchiveMode.Read);
var entry = zip.Entries.FirstOrDefault(p => p.Name == "config.json");
if (entry is not null)
{
await using var es = entry.Open();
await InstallDependenciesAsync(es, installed);
await InstallDependenciesAsync(es, installed, downloadUrl);
}
zip.ExtractToDirectory("./", true);
return true;
Expand All @@ -148,7 +152,8 @@ private async Task<bool> InstallPluginAsync(
/// </summary>
/// <param name="config">plugin config path in temp</param>
/// <param name="installed">Dependency set</param>
private async Task InstallDependenciesAsync(Stream config, HashSet<string> installed)
/// <param name="downloadUrl">Custom plugin download url.</param>
private async Task InstallDependenciesAsync(Stream config, HashSet<string> installed, string? downloadUrl = null)
{
var dependency = new ConfigurationBuilder()
.AddJsonStream(config)
Expand All @@ -162,7 +167,7 @@ private async Task InstallDependenciesAsync(Stream config, HashSet<string> insta
foreach (var plugin in dependencies.Where(p => p is not null && !PluginExists(p)))
{
ConsoleHelper.Info($"Installing dependency: {plugin}");
await InstallPluginAsync(plugin!, installed);
await InstallPluginAsync(plugin!, downloadUrl, installed);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/Neo.CLI/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Neo.Network.P2P;
using Neo.Persistence;
using System;
using System.Linq;
using System.Reflection;
using System.Threading;

Expand Down
4 changes: 2 additions & 2 deletions src/Neo.CLI/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"Active": false
},
"Storage": {
"Engine": "LevelDBStore", // Candidates [MemoryStore, LevelDBStore, RocksDBStore]
"Path": "Data_LevelDB_{0}" // {0} is a placeholder for the network id
"Engine": "LevelDBStore",
"Path": "Data_LevelDB_{0}"
},
"P2P": {
"Port": 10333,
Expand Down
10 changes: 5 additions & 5 deletions src/Neo.CLI/config.json.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# README for Application and Protocol Configuration JSON File

This README provides an explanation for each field in the JSON configuration file for a NEO node.
This README provides an explanation for each field in the JSON configuration file for a Neo node.

## ApplicationConfiguration

Expand Down Expand Up @@ -31,15 +31,15 @@ This README provides an explanation for each field in the JSON configuration fil
- **NeoNameService**: Script hash of the Neo Name Service contract. MainNet is `0x50ac1c37690cc2cfc594472833cf57505d5f46de`, TestNet is `0x50ac1c37690cc2cfc594472833cf57505d5f46de`.

### Plugins
- **DownloadUrl**: URL to download plugins, typically from the NEO project's GitHub releases. Default is `https://api.github.com/repos/neo-project/neo/releases`.
- **DownloadUrl**: URL to download plugins, typically from the Neo project's GitHub releases. Default is `https://api.github.com/repos/neo-project/neo/releases`.

## ProtocolConfiguration

### Network
- **Network**: Network ID for the NEO network. MainNet is `860833102`, TestNet is `894710606`
- **Network**: Network ID for the Neo network. MainNet is `860833102`, TestNet is `894710606`

### AddressVersion
- **AddressVersion**: Version byte used in NEO address generation. Default is `53`.
- **AddressVersion**: Version byte used in Neo address generation. Default is `53`.

### MillisecondsPerBlock
- **MillisecondsPerBlock**: Time interval between blocks in milliseconds. Default is `15000` (15 seconds).
Expand Down Expand Up @@ -82,4 +82,4 @@ This README provides an explanation for each field in the JSON configuration fil
- `seed4t5.neo.org:20333`
- `seed5t5.neo.org:20333`

This configuration file is essential for setting up and running a NEO node, ensuring proper logging, storage, network connectivity, and consensus protocol parameters.
This configuration file is essential for setting up and running a Neo node, ensuring proper logging, storage, network connectivity, and consensus protocol parameters.

0 comments on commit e0ba897

Please sign in to comment.