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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordBot.Utilities; using DiscordBot.Utilities;
using PluginManager; using PluginManager;
@@ -7,16 +9,17 @@ using PluginManager.Interfaces;
using PluginManager.Loaders; using PluginManager.Loaders;
using PluginManager.Online; using PluginManager.Online;
using PluginManager.Others; using PluginManager.Others;
using Spectre.Console;
namespace DiscordBot.Bot.Actions; namespace DiscordBot.Bot.Actions;
public class Plugin : ICommandAction public class Plugin : ICommandAction
{ {
private bool pluginsLoaded; private bool pluginsLoaded;
public string ActionName => "plugin"; public string ActionName => "plugin";
public string Description => "Manages plugins. Use plugin help for more info."; public string Description => "Manages plugins. Use plugin help for more info.";
public string Usage => "plugin [help|list|load|install|refresh]"; public string Usage => "plugin [help|list|load|install|refresh]";
public InternalActionRunType RunType => InternalActionRunType.ON_CALL; public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
public async Task Execute(string[] args) public async Task Execute(string[] args)
{ {
@@ -31,10 +34,10 @@ public class Plugin : ICommandAction
return; return;
} }
var manager = new PluginsManager(); var manager = new PluginsManager();
switch ( args[0] ) switch (args[0])
{ {
case "refresh": case "refresh":
await Program.internalActionManager.Refresh(); await Program.internalActionManager.Refresh();
@@ -67,8 +70,8 @@ public class Plugin : ICommandAction
pluginsLoaded = true; pluginsLoaded = true;
break; break;
} }
var cc = Console.ForegroundColor; var cc = Console.ForegroundColor;
loader.onCMDLoad += (name, typeName, success, exception) => loader.onCMDLoad += (name, typeName, success, exception) =>
{ {
if (name == null || name.Length < 2) if (name == null || name.Length < 2)
@@ -87,7 +90,7 @@ public class Plugin : ICommandAction
else else
Console.WriteLine("[CMD] Failed to load command : " + name + " because " + Console.WriteLine("[CMD] Failed to load command : " + name + " because " +
exception!.Message exception!.Message
); );
} }
Console.ForegroundColor = cc; Console.ForegroundColor = cc;
@@ -126,7 +129,7 @@ public class Plugin : ICommandAction
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[SLASH] Failed to load command : " + name + " because " + Console.WriteLine("[SLASH] Failed to load command : " + name + " because " +
exception!.Message exception!.Message
); );
} }
Console.ForegroundColor = cc; Console.ForegroundColor = cc;
@@ -134,7 +137,7 @@ public class Plugin : ICommandAction
loader.LoadPlugins(); loader.LoadPlugins();
Console.ForegroundColor = cc; Console.ForegroundColor = cc;
pluginsLoaded = true; pluginsLoaded = true;
break; break;
case "install": case "install":
@@ -150,68 +153,116 @@ public class Plugin : ICommandAction
break; 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]; await DownloadPlugin(manager, pluginName);
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");
break; 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> <ItemGroup>
<PackageReference Include="Discord.Net" Version="3.11.0"/> <PackageReference Include="Discord.Net" Version="3.11.0"/>
<PackageReference Include="pythonnet" Version="3.0.1" /> <PackageReference Include="pythonnet" Version="3.0.1" />
<PackageReference Include="Spectre.Console" Version="0.47.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj"/> <ProjectReference Include="..\PluginManager\PluginManager.csproj"/>

View File

@@ -8,6 +8,18 @@ public class Entry
{ {
public static void Main(string[] args) 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; var currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += LoadFromSameFolder; currentDomain.AssemblyResolve += LoadFromSameFolder;

View File

@@ -1,8 +1,6 @@
using System; using System;
using System.IO;
using System.Threading.Tasks;
using PluginManager; using PluginManager;
using PluginManager.Online; using Spectre.Console;
namespace DiscordBot; namespace DiscordBot;
@@ -10,36 +8,21 @@ public static class Installer
{ {
public static void GenerateStartupConfig() public static void GenerateStartupConfig()
{ {
Console.WriteLine("Welcome to the SethBot installer !"); AnsiConsole.WriteLine("Welcome to the [bold]SethBot[/] installer !");
Console.WriteLine("First, we need to configure the bot. Don't worry, it will be quick !"); AnsiConsole.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)"); var token = AnsiConsole.Ask<string>("Please enter the bot token :");
var prefix = AnsiConsole.Ask<string>("Please enter the bot prefix :");
if (!Config.AppSettings.ContainsKey("token")) var serverId = AnsiConsole.Ask<string>("Please enter the Server ID :");
{
Console.WriteLine("Please enter the bot token :"); Config.AppSettings.Add("token", token);
var token = Console.ReadLine(); Config.AppSettings.Add("prefix", prefix);
Config.AppSettings.Add("token", token); Config.AppSettings.Add("ServerID", serverId);
}
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);
Config.AppSettings.SaveToFile(); 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;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordBot.Utilities; using DiscordBot.Utilities;
using PluginManager.Bot; using PluginManager.Bot;
using PluginManager.Online;
using PluginManager.Online.Helpers;
using PluginManager.Others; using PluginManager.Others;
using PluginManager.Others.Actions; using PluginManager.Others.Actions;
using static PluginManager.Config; using static PluginManager.Config;
@@ -32,7 +29,7 @@ public class Program
!AppSettings.ContainsKey("prefix") || AppSettings["prefix"] == null || !AppSettings.ContainsKey("prefix") || AppSettings["prefix"] == null ||
AppSettings["prefix"]?.Length != 1 || AppSettings["prefix"]?.Length != 1 ||
args.Length == 1 && args[0] == "/reset") args.Length == 1 && args[0] == "/reset")
Installer.GenerateStartupConfig(); Installer.GenerateStartupConfig();
HandleInput().Wait(); HandleInput().Wait();
} }
@@ -137,6 +134,7 @@ public class Program
Console.WriteLine($"[{type.ToString()}] {message}"); Console.WriteLine($"[{type.ToString()}] {message}");
Console.ResetColor(); Console.ResetColor();
}; };
AppSettings["Version"] = Assembly.GetExecutingAssembly().GetName().Version.ToString(); AppSettings["Version"] = Assembly.GetExecutingAssembly().GetName().Version.ToString();
} }
} }

View File

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