Improved download speed and started using Spectre.Console package

This commit is contained in:
2023-09-18 23:13:44 +03:00
parent c9249dc71b
commit 58624f4037
7 changed files with 167 additions and 117 deletions

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using DiscordBot.Utilities;
using PluginManager;
@@ -7,16 +9,17 @@ using PluginManager.Interfaces;
using PluginManager.Loaders;
using PluginManager.Online;
using PluginManager.Others;
using Spectre.Console;
namespace DiscordBot.Bot.Actions;
public class Plugin : ICommandAction
{
private bool pluginsLoaded;
public string ActionName => "plugin";
public string Description => "Manages plugins. Use plugin help for more info.";
public string Usage => "plugin [help|list|load|install|refresh]";
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
private bool pluginsLoaded;
public string ActionName => "plugin";
public string Description => "Manages plugins. Use plugin help for more info.";
public string Usage => "plugin [help|list|load|install|refresh]";
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
public async Task Execute(string[] args)
{
@@ -31,10 +34,10 @@ public class Plugin : ICommandAction
return;
}
var manager = new PluginsManager();
switch ( args[0] )
switch (args[0])
{
case "refresh":
await Program.internalActionManager.Refresh();
@@ -67,8 +70,8 @@ public class Plugin : ICommandAction
pluginsLoaded = true;
break;
}
var cc = Console.ForegroundColor;
var cc = Console.ForegroundColor;
loader.onCMDLoad += (name, typeName, success, exception) =>
{
if (name == null || name.Length < 2)
@@ -87,7 +90,7 @@ public class Plugin : ICommandAction
else
Console.WriteLine("[CMD] Failed to load command : " + name + " because " +
exception!.Message
);
);
}
Console.ForegroundColor = cc;
@@ -126,7 +129,7 @@ public class Plugin : ICommandAction
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[SLASH] Failed to load command : " + name + " because " +
exception!.Message
);
);
}
Console.ForegroundColor = cc;
@@ -134,7 +137,7 @@ public class Plugin : ICommandAction
loader.LoadPlugins();
Console.ForegroundColor = cc;
pluginsLoaded = true;
pluginsLoaded = true;
break;
case "install":
@@ -150,68 +153,116 @@ public class Plugin : ICommandAction
break;
}
}
var pluginData = await manager.GetPluginLinkByName(pluginName);
if (pluginData == null || pluginData.Length == 0)
{
Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again.");
break;
}
var pluginType = pluginData[0];
var pluginLink = pluginData[1];
var pluginRequirements = pluginData[2];
Console.WriteLine("Downloading plugin...");
//download plugin progress bar for linux and windows terminals
var spinner = new ConsoleUtilities.Spinner();
spinner.Start();
IProgress<float> progress = new Progress<float>(p => { spinner.Message = $"Downloading {pluginName}... {Math.Round(p, 2)}% "; });
await ServerCom.DownloadFileAsync(pluginLink, $"./Data/{pluginType}s/{pluginName}.dll", progress);
spinner.Stop();
Console.WriteLine();
if (pluginRequirements == string.Empty)
{
Console.WriteLine("Finished installing " + pluginName + " successfully");
Console.WriteLine("Reloading plugins list...");
await Program.internalActionManager.Execute("plugin", "load");
await Program.internalActionManager.Refresh();
Console.WriteLine("Finished reloading plugins list");
break;
}
Console.WriteLine("Downloading plugin requirements...");
var requirementsURLs = await ServerCom.ReadTextFromURL(pluginRequirements);
foreach (var requirement in requirementsURLs)
{
if (requirement.Length < 2)
continue;
var reqdata = requirement.Split(',');
var url = reqdata[0];
var filename = reqdata[1];
Console.WriteLine($"Downloading {filename}... ");
progress = new Progress<float>(p => { spinner.Message = $"Downloading {filename}... {Math.Round(p, 2)}% "; });
spinner.Start();
await ServerCom.DownloadFileAsync(url, $"./{filename}", progress);
spinner.Stop();
progress.Report(1);
await Task.Delay(1000);
Console.WriteLine("Downloaded " + filename + " successfully");
}
Console.WriteLine("Finished installing " + pluginName + " successfully");
Console.WriteLine("Reloading plugins list...");
await Program.internalActionManager.Execute("plugin", "load", "-q");
await Program.internalActionManager.Refresh();
Console.WriteLine("Finished reloading plugins list");
await DownloadPlugin(manager, pluginName);
break;
}
}
}
private async Task RefreshPlugins()
{
Console.WriteLine("Reloading plugins list...");
await Program.internalActionManager.Execute("plugin", "load");
await Program.internalActionManager.Refresh();
Console.WriteLine("Finished reloading plugins list");
}
public async Task DownloadPlugin(PluginsManager manager, string pluginName)
{
var pluginData = await manager.GetPluginLinkByName(pluginName);
if (pluginData.Length == 0)
{
Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again.");
return;
}
var pluginType = pluginData[0];
var pluginLink = pluginData[1];
var pluginRequirements = pluginData[2];
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn()
})
.StartAsync(async ctx =>
{
var downloadTask = ctx.AddTask("Downloading plugin...");
IProgress<float> progress = new Progress<float>(p => { downloadTask.Value = p; });
await ServerCom.DownloadFileAsync(pluginLink, $"./Data/{pluginType}s/{pluginName}.dll", progress);
downloadTask.Increment(100);
ctx.Refresh();
});
if (pluginRequirements == string.Empty)
{
Console.WriteLine("Finished installing " + pluginName + " successfully");
await RefreshPlugins();
return;
}
List<string> requirementsUrLs = new();
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn()
})
.StartAsync(async ctx =>
{
var gatherInformationTask = ctx.AddTask("Gathering info...");
gatherInformationTask.IsIndeterminate = true;
requirementsUrLs = await ServerCom.ReadTextFromURL(pluginRequirements);
await Task.Delay(2000);
gatherInformationTask.Increment(100);
});
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn()
})
.StartAsync(async ctx =>
{
List<Tuple<ProgressTask, IProgress<float>, Task>> downloadTasks = new();
foreach (var info in requirementsUrLs)
{
if (info.Length < 2) continue;
string[] data = info.Split(',');
string url = data[0];
string fileName = data[1];
var task = ctx.AddTask($"Downloading {fileName}...");
IProgress<float> progress = new Progress<float>(p =>
{
task.Value = p;
});
var downloadTask = ServerCom.DownloadFileAsync(url, $"./{fileName}", progress);
downloadTasks.Add(new Tuple<ProgressTask, IProgress<float>, Task>(task, progress, downloadTask));
}
foreach (var task in downloadTasks)
{
await task.Item3;
}
});
await RefreshPlugins();
}
}

View File

@@ -35,6 +35,7 @@
<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.11.0"/>
<PackageReference Include="pythonnet" Version="3.0.1" />
<PackageReference Include="Spectre.Console" Version="0.47.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj"/>

View File

@@ -8,6 +8,18 @@ public class Entry
{
public static void Main(string[] args)
{
#if DEBUG
if (args.Length == 1 && args[0] == "/purge_plugins")
{
foreach (var plugin in Directory.GetFiles("./Data/Plugins", "*.dll", SearchOption.AllDirectories))
{
File.Delete(plugin);
}
}
#endif
var currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += LoadFromSameFolder;

View File

@@ -1,8 +1,6 @@
using System;
using System.IO;
using System.Threading.Tasks;
using PluginManager;
using PluginManager.Online;
using Spectre.Console;
namespace DiscordBot;
@@ -10,36 +8,21 @@ public static class Installer
{
public static void GenerateStartupConfig()
{
Console.WriteLine("Welcome to the SethBot installer !");
Console.WriteLine("First, we need to configure the bot. Don't worry, it will be quick !");
Console.WriteLine("The following information will be stored in the config.json file in the ./Data/Resources folder. You can change it later from there.");
Console.WriteLine("The bot token is required to run the bot. You can get it from the Discord Developer Portal. (https://discord.com/developers/applications)");
if (!Config.AppSettings.ContainsKey("token"))
{
Console.WriteLine("Please enter the bot token :");
var token = Console.ReadLine();
Config.AppSettings.Add("token", token);
}
if (!Config.AppSettings.ContainsKey("prefix"))
{
Console.WriteLine("Please enter the bot prefix :");
var prefix = Console.ReadLine();
Config.AppSettings.Add("prefix", prefix);
}
if (!Config.AppSettings.ContainsKey("ServerID"))
{
Console.WriteLine("Please enter the Server ID :");
var serverId = Console.ReadLine();
Config.AppSettings.Add("ServerID", serverId);
}
Config.Logger.Log("Config Saved", "Installer", isInternal: true);
AnsiConsole.WriteLine("Welcome to the [bold]SethBot[/] installer !");
AnsiConsole.WriteLine("First, we need to configure the bot. Don't worry, it will be quick !");
var token = AnsiConsole.Ask<string>("Please enter the bot token :");
var prefix = AnsiConsole.Ask<string>("Please enter the bot prefix :");
var serverId = AnsiConsole.Ask<string>("Please enter the Server ID :");
Config.AppSettings.Add("token", token);
Config.AppSettings.Add("prefix", prefix);
Config.AppSettings.Add("ServerID", serverId);
Config.AppSettings.SaveToFile();
Console.WriteLine("Config saved !");
AnsiConsole.MarkupLine("[bold]Config saved ![/]");
Config.Logger.Log("Config Saved", "Installer", isInternal: true);
}
}

View File

@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using DiscordBot.Utilities;
using PluginManager.Bot;
using PluginManager.Online;
using PluginManager.Online.Helpers;
using PluginManager.Others;
using PluginManager.Others.Actions;
using static PluginManager.Config;
@@ -32,7 +29,7 @@ public class Program
!AppSettings.ContainsKey("prefix") || AppSettings["prefix"] == null ||
AppSettings["prefix"]?.Length != 1 ||
args.Length == 1 && args[0] == "/reset")
Installer.GenerateStartupConfig();
Installer.GenerateStartupConfig();
HandleInput().Wait();
}
@@ -137,6 +134,7 @@ public class Program
Console.WriteLine($"[{type.ToString()}] {message}");
Console.ResetColor();
};
AppSettings["Version"] = Assembly.GetExecutingAssembly().GetName().Version.ToString();
}
}

View File

@@ -35,21 +35,25 @@ internal static class OnlineFunctions
if (progress == null || !contentLength.HasValue)
{
await download.CopyToAsync(destination, cancellation);
if(!contentLength.HasValue)
progress?.Report(100f);
return;
}
// Convert absolute progress (bytes downloaded) into relative progress (0% - 100%)
var relativeProgress = new Progress<long>(totalBytes =>
{
progress?.Report((float)totalBytes / contentLength.Value *
100);
downloadedBytes?.Report(totalBytes);
}
);
// total ... 100%
// downloaded ... x%
// x = downloaded * 100 / total => x = downloaded / total * 100
var relativeProgress = new Progress<long>(totalBytesDownloaded =>
{
progress?.Report(totalBytesDownloaded / (float)contentLength.Value * 100);
downloadedBytes?.Report(totalBytesDownloaded);
}
);
// Use extension method to report progress while downloading
await download.CopyToOtherStreamAsync(destination, bufferSize, relativeProgress, cancellation);
progress.Report(100);
progress.Report(100f);
}
}
}

View File

@@ -48,4 +48,5 @@ public static class ServerCom
{
await DownloadFileAsync(URl, location, progress, null);
}
}