Added InternalActionOption in ICommandAction interface.

Updated ConsoleUtilities and removed obsolete functions.
This commit is contained in:
2024-05-10 14:39:39 +03:00
parent dc787ac130
commit 9476f9ec31
17 changed files with 214 additions and 429 deletions

View File

@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PluginManager.Interfaces;
using PluginManager.Others;
using PluginManager.Others.Actions;
namespace DiscordBot.Bot.Actions;
@@ -10,6 +13,8 @@ public class Clear: ICommandAction
public string ActionName => "clear";
public string Description => "Clears the console";
public string Usage => "clear";
public IEnumerable<InternalActionOption> ListOfOptions => [];
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
public Task Execute(string[] args)

View File

@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Others;
using PluginManager.Others.Actions;
namespace DiscordBot.Bot.Actions;
@@ -10,7 +12,12 @@ public class Exit: ICommandAction
{
public string ActionName => "exit";
public string Description => "Exits the bot and saves the config. Use exit help for more info.";
public string Usage => "exit [help|force (-f)]";
public string Usage => "exit <option?>";
public IEnumerable<InternalActionOption> ListOfOptions => new List<InternalActionOption>
{
new InternalActionOption("help", "Displays this message"),
new InternalActionOption("force | -f", "Exits the bot without saving the config")
};
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
public async Task Execute(string[] args)

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DiscordBot.Utilities;
@@ -19,18 +20,11 @@ internal static class PluginMethods
{
internal static async Task List(PluginsManager manager)
{
var data = await ConsoleUtilities.ExecuteWithProgressBar(manager.GetPluginsList(), "Loading plugins...");
var data = await ConsoleUtilities.ExecuteWithProgressBar(manager.GetPluginsList(), "Reading remote database");
TableData tableData = new(new List<string>
{
"Name",
"Description",
"Version",
"Is Installed"
}
);
TableData tableData = new(["Name", "Description", "Version", "Is Installed"]);
var installedPlugins = await manager.GetInstalledPlugins();
var installedPlugins = await ConsoleUtilities.ExecuteWithProgressBar(manager.GetInstalledPlugins(), "Reading local database ");
foreach (var plugin in data)
{
@@ -39,7 +33,7 @@ internal static class PluginMethods
}
tableData.HasRoundBorders = false;
tableData.PrintAsTable();
tableData.PrintTable();
}
internal static async Task RefreshPlugins(bool quiet)

View File

@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DiscordBot.Utilities;
using PluginManager.Interfaces;
using PluginManager.Others;
using PluginManager.Others.Actions;
using Spectre.Console;
namespace DiscordBot.Bot.Actions;
@@ -13,46 +16,55 @@ public class Help: ICommandAction
public string Description => "Shows the list of commands and their usage";
public string Usage => "help [command]";
public string Usage => "help <command?>";
public IEnumerable<InternalActionOption> ListOfOptions => [];
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
public async Task Execute(string[] args)
{
TableData tableData = new TableData();
if (args == null || args.Length == 0)
{
var items = new List<string[]>
{
new[]
{
"-", "-", "-"
},
new[]
{
"Command", "Usage", "Description"
},
new[]
{
"-", "-", "-"
}
};
tableData.Columns = ["Command", "Usage", "Description", "Options"];
foreach (var a in Program.internalActionManager.Actions)
items.Add(new[]
{
a.Key, a.Value.Usage, a.Value.Description
}
);
{
Markup actionName = new Markup($"[bold]{a.Key}[/]");
Markup usage = new Markup($"[italic]{a.Value.Usage}[/]");
Markup description = new Markup($"[dim]{a.Value.Description}[/]");
items.Add(new[]
if (a.Value.ListOfOptions.Any())
{
"-", "-", "-"
}
);
ConsoleUtilities.FormatAndAlignTable(items,
TableFormat.CENTER_EACH_COLUMN_BASED
);
var optionsTable = new Table();
optionsTable.AddColumn("Option");
optionsTable.AddColumn("Description");
foreach (var option in a.Value.ListOfOptions)
{
optionsTable.AddRow(option.OptionName, option.OptionDescription);
}
tableData.AddRow([actionName, usage, description, optionsTable]);
}
else
{
tableData.AddRow([actionName, usage, description]);
}
}
// render the table
tableData.HasRoundBorders = true;
tableData.DisplayLinesBetweenRows = true;
tableData.PrintTable();
return;
}
@@ -63,32 +75,10 @@ public class Help: ICommandAction
}
var action = Program.internalActionManager.Actions[args[0]];
var actionData = new List<string[]>
{
new[]
{
"-", "-", "-"
},
new[]
{
"Command", "Usage", "Description"
},
new[]
{
"-", "-", "-"
},
new[]
{
action.ActionName, action.Usage, action.Description
},
new[]
{
"-", "-", "-"
}
};
tableData.Columns = ["Command", "Usage", "Description"];
tableData.AddRow([action.ActionName, action.Usage, action.Description]);
ConsoleUtilities.FormatAndAlignTable(actionData,
TableFormat.CENTER_EACH_COLUMN_BASED
);
tableData.PrintTable();
}
}

View File

@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Input;
using DiscordBot.Bot.Actions.Extra;
using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Loaders;
using PluginManager.Online;
using PluginManager.Others;
using Spectre.Console;
using PluginManager.Others.Actions;
namespace DiscordBot.Bot.Actions;
@@ -17,7 +14,18 @@ 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 string Usage => "plugin <option!>";
public IEnumerable<InternalActionOption> ListOfOptions => new List<InternalActionOption>
{
new InternalActionOption("help", "Displays this message"),
new InternalActionOption("list", "Lists all plugins"),
new InternalActionOption("load", "Loads all plugins"),
new InternalActionOption("install", "Installs a plugin"),
new InternalActionOption("refresh", "Refreshes the plugin list"),
new InternalActionOption("uninstall", "Uninstalls a plugin")
};
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
public async Task Execute(string[] args)

View File

@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DiscordBot.Bot.Actions.Extra;
using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Others;
using PluginManager.Others.Actions;
namespace DiscordBot.Bot.Actions;
@@ -11,7 +13,14 @@ public class SettingsConfig: ICommandAction
{
public string ActionName => "config";
public string Description => "Change the settings of the bot";
public string Usage => "config [options] <setting?> <value?>";
public string Usage => "config <options!>";
public IEnumerable<InternalActionOption> ListOfOptions => new List<InternalActionOption>
{
new InternalActionOption("help", "Displays this message"),
new InternalActionOption("set", "Set a setting"),
new InternalActionOption("remove", "Remove a setting"),
new InternalActionOption("add", "Add a setting")
};
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
public Task Execute(string[] args)
{

View File

@@ -7,6 +7,16 @@ namespace DiscordBot;
public static class Entry
{
private static readonly string logo = @"
_____ _ _ _____ _ _ ____ _
/ ____| | | | | | __ \(_) | | | _ \ | |
| (___ ___| |_| |__ | | | |_ ___ ___ ___ _ __ __| | | |_) | ___ | |_
\___ \ / _ \ __| '_ \ | | | | / __|/ __/ _ \| '__/ _` | | _ < / _ \| __|
____) | __/ |_| | | | | |__| | \__ \ (_| (_) | | | (_| | | |_) | (_) | |_
|_____/ \___|\__|_| |_| |_____/|_|___/\___\___/|_| \__,_| |____/ \___/ \__|
";
public static void Main(string[] args)
{
#if DEBUG
@@ -20,6 +30,10 @@ public static class Entry
#endif
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine(logo);
Console.ResetColor();
var currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += LoadFromSameFolder;

View File

@@ -54,22 +54,19 @@ public class Program
/// <summary>
/// Start the bot without user interface
/// </summary>
/// <returns>Returns the boot loader for the Discord Bot</returns>
/// <returns>Returns the bootloader for the Discord Bot</returns>
private static async Task StartNoGui()
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($"Running on version: {AppSettings["Version"]}");
Console.WriteLine("Git SethBot: https://github.com/andreitdr/SethDiscordBot");
Console.WriteLine("Git Plugins: https://github.com/andreitdr/SethPlugins");
AnsiConsole.MarkupLine($"[yellow]Running on version: {AppSettings["Version"]}[/]");
AnsiConsole.MarkupLine("[yellow]Git SethBot: https://github.com/andreitdr/SethDiscordBot [/]");
AnsiConsole.MarkupLine("[yellow]Git Plugins: https://github.com/andreitdr/SethPlugins [/]");
ConsoleUtilities.WriteColorText("&rRemember to close the bot using the ShutDown command (&yexit&r) or some settings won't be saved");
AnsiConsole.MarkupLine("[yellow]Remember to close the bot using the shutdown command ([/][red]exit[/][yellow]) or some settings won't be saved[/]");
AnsiConsole.MarkupLine($"[yellow]Running on [/][magenta]{(OperatingSystem.IsWindows() ? "Windows" : "Linux")}[/]");
ConsoleUtilities.WriteColorText($"Running on &m{(OperatingSystem.IsWindows() ? "Windows" : "Linux")}");
Console.WriteLine("============================ LOG ============================");
AnsiConsole.MarkupLine("[yellow]===== Seth Discord Bot =====[/]");
Console.ForegroundColor = ConsoleColor.White;
try
{
var token = AppSettings["token"];

View File

@@ -7,347 +7,25 @@ using Spectre.Console;
namespace DiscordBot.Utilities;
public class TableData
{
public List<string> Columns;
public List<string[]> Rows;
public bool IsEmpty => Rows.Count == 0;
public bool HasRoundBorders { get; set; } = true;
public TableData(List<string> columns)
{
Columns = columns;
Rows = new List<string[]>();
}
public TableData(string[] columns)
{
Columns = columns.ToList();
Rows = new List<string[]>();
}
public void AddRow(string[] row)
{
Rows.Add(row);
}
}
public static class ConsoleUtilities
{
public static async Task<T> ExecuteWithProgressBar<T>(Task<T> function, string message)
{
T result = default;
await AnsiConsole.Progress()
.Columns(
new ProgressColumn[]
{
new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn()
}
)
.StartAsync(
async ctx =>
{
var task = ctx.AddTask(message);
task.IsIndeterminate = true;
result = await function;
task.Increment(100);
}
);
return result;
}
public static async Task ExecuteWithProgressBar(Task function, string message)
{
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn()
}
)
.StartAsync(async ctx =>
{
var task = ctx.AddTask(message);
task.IsIndeterminate = true;
await function;
task.Increment(100);
}
);
}
private static readonly Dictionary<char, ConsoleColor> Colors = new()
{
{
'g', ConsoleColor.Green
},
{
'b', ConsoleColor.Blue
},
{
'r', ConsoleColor.Red
},
{
'm', ConsoleColor.Magenta
},
{
'y', ConsoleColor.Yellow
}
};
private static readonly char ColorPrefix = '&';
private static bool CanAproximateTo(this float f, float y)
{
return MathF.Abs(f - y) < 0.000001;
}
public static void PrintAsTable(this TableData tableData)
{
var table = new Table();
table.Border(tableData.HasRoundBorders ? TableBorder.Rounded : TableBorder.Square);
table.AddColumns(tableData.Columns.ToArray());
foreach (var row in tableData.Rows)
table.AddRow(row);
AnsiConsole.Write(table);
}
/// <summary>
/// A way to create a table based on input data
/// </summary>
/// <param name="data">The List of arrays of string that represent the rows.</param>
public static void FormatAndAlignTable(List<string[]> data, TableFormat format)
{
if (format == TableFormat.SPECTRE_CONSOLE)
{
var table = new Table();
table.Border(TableBorder.Rounded);
table.AddColumns(data[0]);
data.RemoveAt(0);
foreach (var row in data)
table.AddRow(row);
AnsiConsole.Write(table);
return;
}
if (format == TableFormat.CENTER_EACH_COLUMN_BASED)
{
var tableLine = '-';
var tableCross = '+';
var tableWall = '|';
var len = new int[data[0].Length];
foreach (var line in data)
for (var i = 0; i < line.Length; i++)
if (line[i].Length > len[i])
len[i] = line[i].Length;
foreach (var row in data)
{
if (row[0][0] == tableLine)
Console.Write(tableCross);
else
Console.Write(tableWall);
for (var l = 0; l < row.Length; l++)
.AutoClear(true)
.Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn())
.StartAsync(
async ctx =>
{
if (row[l][0] == tableLine)
{
for (var i = 0; i < len[l] + 4; ++i)
Console.Write(tableLine);
}
else if (row[l].Length == len[l])
{
Console.Write(" ");
Console.Write(row[l]);
Console.Write(" ");
}
else
{
var lenHalf = row[l].Length / 2;
for (var i = 0; i < (len[l] + 4) / 2 - lenHalf; ++i)
Console.Write(" ");
Console.Write(row[l]);
for (var i = (len[l] + 4) / 2 + lenHalf + 1; i < len[l] + 4; ++i)
Console.Write(" ");
if (row[l].Length % 2 == 0)
Console.Write(" ");
}
Console.Write(row[l][0] == tableLine ? tableCross : tableWall);
}
Console.WriteLine(); //end line
}
return;
}
if (format == TableFormat.CENTER_OVERALL_LENGTH)
{
var maxLen = 0;
foreach (var row in data)
foreach (var s in row)
if (s.Length > maxLen)
maxLen = s.Length;
var div = (maxLen + 4) / 2;
foreach (var row in data)
{
Console.Write("\t");
if (row[0] == "-")
Console.Write("+");
else
Console.Write("|");
foreach (var s in row)
{
if (s == "-")
{
for (var i = 0; i < maxLen + 4; ++i)
Console.Write("-");
}
else if (s.Length == maxLen)
{
Console.Write(" ");
Console.Write(s);
Console.Write(" ");
}
else
{
var lenHalf = s.Length / 2;
for (var i = 0; i < div - lenHalf; ++i)
Console.Write(" ");
Console.Write(s);
for (var i = div + lenHalf + 1; i < maxLen + 4; ++i)
Console.Write(" ");
if (s.Length % 2 == 0)
Console.Write(" ");
}
if (s == "-")
Console.Write("+");
else
Console.Write("|");
}
Console.WriteLine(); //end line
}
return;
}
if (format == TableFormat.DEFAULT)
{
var widths = new int[data[0].Length];
var space_between_columns = 3;
for (var i = 0; i < data.Count; i++)
for (var j = 0; j < data[i].Length; j++)
if (data[i][j].Length > widths[j])
widths[j] = data[i][j].Length;
for (var i = 0; i < data.Count; i++)
{
for (var j = 0; j < data[i].Length; j++)
{
if (data[i][j] == "-")
data[i][j] = " ";
Console.Write(data[i][j]);
for (var k = 0; k < widths[j] - data[i][j].Length + 1 + space_between_columns; k++)
Console.Write(" ");
}
Console.WriteLine();
}
return;
}
throw new Exception("Unknown type of table");
}
public static void WriteColorText(string text, bool appendNewLineAtEnd = true)
{
var initialForeGround = Console.ForegroundColor;
var input = text.ToCharArray();
for (var i = 0; i < input.Length; i++)
if (input[i] == ColorPrefix)
{
if (i + 1 < input.Length)
{
if (Colors.ContainsKey(input[i + 1]))
{
Console.ForegroundColor = Colors[input[i + 1]];
i++;
}
else if (input[i + 1] == 'c')
{
Console.ForegroundColor = initialForeGround;
i++;
}
}
}
else
{
Console.Write(input[i]);
}
Console.ForegroundColor = initialForeGround;
if (appendNewLineAtEnd)
Console.WriteLine();
}
public class Spinner
{
private readonly string[] Sequence;
private bool isRunning;
public string Message;
private int position;
private Thread thread;
public Spinner()
{
Sequence = new[]
{
"|", "/", "-", "\\"
};
position = 0;
}
public void Start()
{
Console.CursorVisible = false;
isRunning = true;
thread = new Thread(() =>
{
while (isRunning)
{
Console.SetCursorPosition(0, Console.CursorTop);
Console.Write(" " + Sequence[position] + " " + Message + " ");
position++;
if (position >= Sequence.Length)
position = 0;
Thread.Sleep(100);
}
var task = ctx.AddTask(message);
task.IsIndeterminate = true;
result = await function;
task.Increment(100);
}
);
thread.Start();
}
public void Stop()
{
isRunning = false;
Console.CursorVisible = true;
}
return result;
}
}
}

View File

@@ -1,9 +0,0 @@
namespace DiscordBot.Utilities;
public enum TableFormat
{
SPECTRE_CONSOLE,
CENTER_EACH_COLUMN_BASED,
CENTER_OVERALL_LENGTH,
DEFAULT
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using PluginManager.Others;
using Spectre.Console;
using Spectre.Console.Rendering;
namespace DiscordBot.Utilities
{
public class TableData
{
public List<string> Columns;
public List<OneOf<string, IRenderable>[]> Rows;
public TableData()
{
Columns = new List<string>();
Rows = new List<OneOf<string, IRenderable>[]>();
}
public TableData(List<string> columns)
{
Columns = columns;
Rows = new List<OneOf<string, IRenderable>[]>();
}
public bool IsEmpty => Rows.Count == 0;
public bool HasRoundBorders { get; set; } = true;
public bool DisplayLinesBetweenRows { get; set; } = false;
public void AddRow(OneOf<string, IRenderable>[] row)
{
Rows.Add(row);
}
public void PrintTable()
{
var table = new Table();
table.Border(this.HasRoundBorders ? TableBorder.Rounded : TableBorder.Square);
table.AddColumns(this.Columns.ToArray());
table.ShowRowSeparators = DisplayLinesBetweenRows;
foreach (var row in this.Rows)
{
table.AddRow(row.Select(element => element.Match(
(data) => new Markup(data),
(data) => data
)));
}
AnsiConsole.Write(table);
}
}
}