Updated documentation

This commit is contained in:
2022-05-03 21:58:44 +03:00
parent f3d0ea426e
commit f5f1827540
26 changed files with 520 additions and 180 deletions

Binary file not shown.

View File

@@ -11,19 +11,48 @@ using System.Collections.Generic;
namespace DiscordBot.Discord.Commands namespace DiscordBot.Discord.Commands
{ {
/// <summary>
/// The help command
/// </summary>
internal class Help : DBCommand internal class Help : DBCommand
{ {
/// <summary>
/// Command name
/// </summary>
public string Command => "help"; public string Command => "help";
/// <summary>
/// Command Description
/// </summary>
public string Description => "This command allows you to check all loadded commands"; public string Description => "This command allows you to check all loadded commands";
/// <summary>
/// Command usage
/// </summary>
public string Usage => "help"; public string Usage => "help";
/// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel"/>/>
/// </summary>
public bool canUseDM => true; public bool canUseDM => true;
/// <summary>
/// Check if the command can be used in a server
/// </summary>
public bool canUseServer => true; public bool canUseServer => true;
/// <summary>
/// Check if the command require administrator to be executed
/// </summary>
public bool requireAdmin => false; public bool requireAdmin => false;
/// <summary>
/// The main body of the command
/// </summary>
/// <param name="context">The command context</param>
/// <param name="message">The command message</param>
/// <param name="client">The discord bot client</param>
/// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param>
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{ {
List<string> args = Functions.GetArguments(message); List<string> args = Functions.GetArguments(message);

View File

@@ -14,26 +14,49 @@ using ds = Discord;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Others.Permissions; using PluginManager.Others.Permissions;
using PluginManager.Online;
using PluginManager.Others; using PluginManager.Others;
namespace DiscordBot.Discord.Commands namespace DiscordBot.Discord.Commands
{ {
class Restart : DBCommand internal class Restart : DBCommand
{ {
string DBCommand.Command => "restart"; /// <summary>
/// Command name
/// </summary>
public string Command => "restart";
string DBCommand.Description => "Restart the bot"; /// <summary>
/// Command Description
/// </summary>
public string Description => "Restart the bot";
string DBCommand.Usage => "restart [-option]"; /// <summary>
/// Command usage
/// </summary>
public string Usage => "restart [-p | -c | -args | -cmd] <args>";
bool DBCommand.canUseDM => false; /// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel"/>/>
/// </summary>
public bool canUseDM => false;
bool DBCommand.canUseServer => true; /// <summary>
/// Check if the command can be used in a server
/// </summary>
public bool canUseServer => true;
bool DBCommand.requireAdmin => true; /// <summary>
/// Check if the command require administrator to be executed
void DBCommand.Execute(dsc.SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) /// </summary>
public bool requireAdmin => false;
/// <summary>
/// The main body of the command
/// </summary>
/// <param name="context">The command context</param>
/// <param name="message">The command message</param>
/// <param name="client">The discord bot client</param>
/// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param>
public async void Execute(dsc.SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{ {
if (!DiscordPermissions.hasPermission(message.Author as SocketGuildUser, ds.GuildPermission.Administrator)) return; if (!DiscordPermissions.hasPermission(message.Author as SocketGuildUser, ds.GuildPermission.Administrator)) return;
var args = Functions.GetArguments(message); var args = Functions.GetArguments(message);
@@ -79,6 +102,9 @@ namespace DiscordBot.Discord.Commands
} }
Environment.Exit(0); Environment.Exit(0);
break; break;
default:
await context.Channel.SendMessageAsync("Invalid argument. Use `help restart` to see the usage.");
break;
} }

View File

@@ -17,16 +17,44 @@ namespace DiscordBot.Discord.Commands
{ {
class Settings : DBCommand class Settings : DBCommand
{ {
/// <summary>
/// Command name
/// </summary>
public string Command => "set"; public string Command => "set";
/// <summary>
/// Command Description
/// </summary>
public string Description => "This command allows you change all settings. Use \"set help\" to show details"; public string Description => "This command allows you change all settings. Use \"set help\" to show details";
/// <summary>
/// Command usage
/// </summary>
public string Usage => "set [keyword] [new Value]"; public string Usage => "set [keyword] [new Value]";
/// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel"/>/>
/// </summary>
public bool canUseDM => true; public bool canUseDM => true;
/// <summary>
/// Check if the command can be used in a server
/// </summary>
public bool canUseServer => true; public bool canUseServer => true;
/// <summary>
/// Check if the command require administrator to be executed
/// </summary>
public bool requireAdmin => true; public bool requireAdmin => true;
/// <summary>
/// The main body of the command
/// </summary>
/// <param name="context">The command context</param>
/// <param name="message">The command message</param>
/// <param name="client">The discord bot client</param>
/// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param>
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{ {
var channel = message.Channel; var channel = message.Channel;

View File

@@ -11,21 +11,53 @@ namespace PluginManager.Core
{ {
internal class Boot internal class Boot
{ {
/// <summary>
/// The bot prefix
/// </summary>
public readonly string botPrefix; public readonly string botPrefix;
/// <summary>
/// The bot token
/// </summary>
public readonly string botToken; public readonly string botToken;
private bool isReady = false;
/// <summary>
/// Checks if the bot is ready
/// </summary>
/// <value> true if the bot is ready, othwerwise false </value>
public bool isReady { get; private set; } = false;
/// <summary>
/// The bot client
/// </summary>
public DiscordSocketClient client; public DiscordSocketClient client;
/// <summary>
/// The bot command handler
/// </summary>
private CommandHandler commandServiceHandler; private CommandHandler commandServiceHandler;
/// <summary>
/// The command service
/// </summary>
private CommandService service; private CommandService service;
/// <summary>
/// The main Boot constructor
/// </summary>
/// <param name="botToken">The bot token</param>
/// <param name="botPrefix">The bot prefix</param>
public Boot(string botToken, string botPrefix) public Boot(string botToken, string botPrefix)
{ {
this.botPrefix = botPrefix; this.botPrefix = botPrefix;
this.botToken = botToken; this.botToken = botToken;
} }
/// <summary>
/// The start method for the bot. This method is used to load the bot
/// </summary>
/// <returns>Task</returns>
public async Task Awake() public async Task Awake()
{ {
client = new DiscordSocketClient(); client = new DiscordSocketClient();
@@ -39,10 +71,15 @@ namespace PluginManager.Core
commandServiceHandler = new CommandHandler(client, service, botPrefix); commandServiceHandler = new CommandHandler(client, service, botPrefix);
await commandServiceHandler.InstallCommandsAsync(); await commandServiceHandler.InstallCommandsAsync();
//wait for isReady to become true
while (!isReady) ; while (!isReady) ;
} }
/// <summary>
/// The method that stops the bot from running
/// </summary>
/// <returns></returns>
public async Task ShutDown() public async Task ShutDown()
{ {
if (client == null) return; if (client == null) return;

View File

@@ -21,6 +21,12 @@ namespace PluginManager.Core
private readonly CommandService commandService; private readonly CommandService commandService;
private readonly string botPrefix; private readonly string botPrefix;
/// <summary>
/// Command handler constructor
/// </summary>
/// <param name="client">The discord bot client</param>
/// <param name="commandService">The discord bot command service</param>
/// <param name="botPrefix">The prefix to watch for</param>
public CommandHandler(DiscordSocketClient client, CommandService commandService, string botPrefix) public CommandHandler(DiscordSocketClient client, CommandService commandService, string botPrefix)
{ {
this.client = client; this.client = client;
@@ -28,12 +34,21 @@ namespace PluginManager.Core
this.botPrefix = botPrefix; this.botPrefix = botPrefix;
} }
/// <summary>
/// The method to initialize all commands
/// </summary>
/// <returns></returns>
public async Task InstallCommandsAsync() public async Task InstallCommandsAsync()
{ {
client.MessageReceived += MessageHandler; client.MessageReceived += MessageHandler;
await commandService.AddModulesAsync(assembly: Assembly.GetEntryAssembly(), services: null); await commandService.AddModulesAsync(assembly: Assembly.GetEntryAssembly(), services: null);
} }
/// <summary>
/// The message handler for the bot
/// </summary>
/// <param name="Message">The message got from the user in discord chat</param>
/// <returns></returns>
private async Task MessageHandler(SocketMessage Message) private async Task MessageHandler(SocketMessage Message)
{ {
try try
@@ -45,6 +60,8 @@ namespace PluginManager.Core
if (message == null) return; if (message == null) return;
if (!message.Content.StartsWith(botPrefix)) return;
int argPos = 0; int argPos = 0;
if (message.HasMentionPrefix(client.CurrentUser, ref argPos)) if (message.HasMentionPrefix(client.CurrentUser, ref argPos))

View File

@@ -83,6 +83,10 @@ namespace DiscordBot
await manager.ListAvailablePlugins(); await manager.ListAvailablePlugins();
if (listLanguagAtStartup) if (listLanguagAtStartup)
await languageManager.ListAllLanguages(); await languageManager.ListAllLanguages();
IProgress<float> progress = null;
while (true) while (true)
{ {
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
@@ -131,7 +135,7 @@ namespace DiscordBot
} }
string path = "./Data/Plugins/" + info[0] + "s/" + name + ".dll"; string path = "./Data/Plugins/" + info[0] + "s/" + name + ".dll";
IProgress<float> progress = new Progress<float>(percent => progress = new Progress<float>(percent =>
{ {
Console.Title = $"Downloading {info[0]}: {name} ({MathF.Round(percent, 2)}%)"; Console.Title = $"Downloading {info[0]}: {name} ({MathF.Round(percent, 2)}%)";
}); });
@@ -145,11 +149,16 @@ namespace DiscordBot
// //
List<string> lines = await ServerCom.ReadTextFromFile(info[2]); List<string> lines = await ServerCom.ReadTextFromFile(info[2]);
int i = 1; int i = 1;
foreach (var line in lines) foreach (var line in lines)
{ {
string[] split = line.Split(','); string[] split = line.Split(',');
Console.WriteLine($"Downloading item: {split[1]}"); Console.WriteLine($"Downloading item: {split[1]}");
await ServerCom.DownloadFileAsync(split[0], "./" + split[1], i, lines.Count); progress = new Progress<float>(bytes =>
{
Console.Title = $"Downloading {MathF.Round(bytes, 2)}% ({i}/{lines.Count})";
});
await ServerCom.DownloadFileAsync(split[0], "./" + split[1], progress);
Console_Utilities.WriteColorText($"Downloaded item {split[1]}"); Console_Utilities.WriteColorText($"Downloaded item {split[1]}");
i++; i++;
} }

View File

@@ -4,9 +4,20 @@ namespace PluginManager.Interfaces
{ {
public interface DBEvent public interface DBEvent
{ {
/// <summary>
/// The name of the event
/// </summary>
string name { get; } string name { get; }
/// <summary>
/// The description of the event
/// </summary>
string description { get; } string description { get; }
/// <summary>
/// The method that is invoked when the event is loaded into memory
/// </summary>
/// <param name="client">The discord bot client</param>
void Start(DiscordSocketClient client); void Start(DiscordSocketClient client);
} }
} }

View File

@@ -13,10 +13,30 @@ namespace PluginManager.Items
{ {
internal class Command internal class Command
{ {
/// <summary>
/// The author of the command
/// </summary>
public SocketUser Author; public SocketUser Author;
/// <summary>
/// The list of arguments
/// </summary>
public List<string> Arguments { get; private set; } public List<string> Arguments { get; private set; }
/// <summary>
/// The command that is executed
/// </summary>
public string CommandName { get; private set; } public string CommandName { get; private set; }
/// <summary>
/// The prefix that is used for the command
/// </summary>
public char PrefixUsed { get; private set; } public char PrefixUsed { get; private set; }
/// <summary>
/// The Command class contructor
/// </summary>
/// <param name="message">The message that was sent</param>
public Command(SocketMessage message) public Command(SocketMessage message)
{ {
this.Author = message.Author; this.Author = message.Author;
@@ -28,6 +48,11 @@ namespace PluginManager.Items
this.PrefixUsed = data[0][0]; this.PrefixUsed = data[0][0];
} }
/// <summary>
/// The Command class contructor
/// </summary>
/// <param name="message">The message string itself</param>
/// <param name="hasPrefix">True if the message has a prefix, false if not</param>
public Command(string message, bool hasPrefix) public Command(string message, bool hasPrefix)
{ {
string[] data = message.Split(' '); string[] data = message.Split(' ');

View File

@@ -1,27 +0,0 @@
using System;
namespace PluginManager.Items
{
public class CustomProgressBar
{
private const char _block = '#';
private const char _emptyBlock = ' ';
private const char _leftMargin = '[';
private const char _rightMargin = ']';
const string _back = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
public static void WriteProgressBar(int percent)
{
Console.Write(_back);
Console.Write(_leftMargin);
var p = (int)((percent / 10f) + .5f);
for (var i = 0; i < 10; ++i)
{
if (i >= p)
Console.Write(_emptyBlock);
else
Console.Write(_block);
}
Console.Write($"{_rightMargin} " + percent + " %");
}
}
}

View File

@@ -5,13 +5,22 @@ namespace PluginManager.Items
{ {
public class Spinner public class Spinner
{ {
/// <summary>
/// True if active, false otherwise
/// </summary>
public bool isSpinning; public bool isSpinning;
/// <summary>
/// The Spinner constructor
/// </summary>
public Spinner() public Spinner()
{ {
isSpinning = false; isSpinning = false;
} }
/// <summary>
/// The method that is called to start spinning the spinner
/// </summary>
public async void Start() public async void Start()
{ {
isSpinning = true; isSpinning = true;
@@ -32,8 +41,13 @@ namespace PluginManager.Items
} }
} }
/// <summary>
/// The method that is called to stop the spinner from spinning
/// </summary>
public void Stop() public void Stop()
{ {
if (!isSpinning)
throw new Others.Exceptions.APIException("The spinner was not running", "Stop()");
isSpinning = false; isSpinning = false;
} }
} }

View File

@@ -8,10 +8,34 @@ namespace PluginManager.LanguageSystem
{ {
public class Language public class Language
{ {
/// <summary>
/// The active language
/// </summary>
public static Language? ActiveLanguage = null; public static Language? ActiveLanguage = null;
private static readonly string LanguageFileExtension = ".lng"; private static readonly string LanguageFileExtension = ".lng";
/// <summary>
/// The name of the language
/// </summary>
public string LanguageName { get; }
/// <summary>
/// The file where the language is imported from
/// </summary>
public string fileName { get; }
/// <summary>
/// The dictionary of the language
/// </summary>
public Dictionary<string, string> LanguageWords { get; }
/// <summary>
/// The Language constructor
/// </summary>
/// <param name="fileName">The file to import the language from</param>
/// <param name="words">The dictionary of the language</param>
/// <param name="LanguageName">The name of the language</param>
private Language(string fileName, Dictionary<string, string> words, string LanguageName) private Language(string fileName, Dictionary<string, string> words, string LanguageName)
{ {
this.fileName = fileName; this.fileName = fileName;
@@ -19,12 +43,11 @@ namespace PluginManager.LanguageSystem
LanguageWords = words; LanguageWords = words;
} }
public string LanguageName { get; } /// <summary>
/// Load language from file
public string fileName { get; } /// </summary>
/// <param name="LanguageFileLocation">The file path</param>
public Dictionary<string, string> LanguageWords { get; } /// <returns></returns>
public static Language? CreateLanguageFromFile(string LanguageFileLocation) public static Language? CreateLanguageFromFile(string LanguageFileLocation)
{ {
if (!LanguageFileLocation.EndsWith(LanguageFileExtension)) if (!LanguageFileLocation.EndsWith(LanguageFileExtension))
@@ -58,6 +81,12 @@ namespace PluginManager.LanguageSystem
return new Language(LanguageFileLocation, words, languageName); return new Language(LanguageFileLocation, words, languageName);
} }
/// <summary>
/// Format text by inserting parameters
/// </summary>
/// <param name="text">The raw text</param>
/// <param name="args">The arguments</param>
/// <returns></returns>
public string FormatText(string text, params string[] args) public string FormatText(string text, params string[] args)
{ {
if (ActiveLanguage == null) return text; if (ActiveLanguage == null) return text;

View File

@@ -8,25 +8,41 @@ using PluginManager.Interfaces;
namespace PluginManager.Loaders namespace PluginManager.Loaders
{ {
public class CommandsLoader internal class CommandsLoader
{ {
private readonly string CMDPath; private readonly string CMDPath;
private readonly string CMDExtension; private readonly string CMDExtension;
public delegate void onCommandLoaded(string name, bool success, DBCommand? command = null, Exception? exception = null);
public delegate void onCommandFileLoaded(string path); internal delegate void onCommandLoaded(string name, bool success, DBCommand? command = null, Exception? exception = null);
internal delegate void onCommandFileLoaded(string path);
public onCommandLoaded? OnCommandLoaded; /// <summary>
public onCommandFileLoaded? OnCommandFileLoaded; /// Event fired when a command is loaded
/// </summary>
internal onCommandLoaded? OnCommandLoaded;
public CommandsLoader(string CommandPath, string CommandExtension) /// <summary>
/// Event fired when the file is loaded
/// </summary>
internal onCommandFileLoaded? OnCommandFileLoaded;
/// <summary>
/// Command Loader contructor
/// </summary>
/// <param name="CommandPath">The path to the commands</param>
/// <param name="CommandExtension">The extension to search for in the <paramref name="CommandPath"/></param>
internal CommandsLoader(string CommandPath, string CommandExtension)
{ {
CMDPath = CommandPath; CMDPath = CommandPath;
CMDExtension = CommandExtension; CMDExtension = CommandExtension;
} }
public List<DBCommand>? LoadCommands() /// <summary>
/// The method that loads all commands
/// </summary>
/// <returns></returns>
internal List<DBCommand>? LoadCommands()
{ {
if (!Directory.Exists(CMDPath)) if (!Directory.Exists(CMDPath))
{ {

View File

@@ -8,25 +8,41 @@ using PluginManager.Interfaces;
namespace PluginManager.Loaders namespace PluginManager.Loaders
{ {
public class EventsLoader internal class EventsLoader
{ {
private readonly string EVPath; private readonly string EVPath;
private readonly string EVExtension; private readonly string EVExtension;
public delegate void onEventLoad(string name, bool success, DBEvent? ev = null, Exception? e = null); internal delegate void onEventLoad(string name, bool success, DBEvent? ev = null, Exception? e = null);
public delegate void onEventFileLoaded(string path); internal delegate void onEventFileLoaded(string path);
public onEventLoad? EventLoad; /// <summary>
public onEventFileLoaded? EventFileLoaded; /// An event that is fired whenever a <see cref="DBEvent"/> event is loaded in memory
/// </summary>
internal onEventLoad? EventLoad;
public EventsLoader(string path, string ext) /// <summary>
/// An event that is fired whenever a <see cref="DBEvent"/> event file is loaded
/// </summary>
internal onEventFileLoaded? EventFileLoaded;
/// <summary>
/// The Event Loader constructor
/// </summary>
/// <param name="path">The path to all events</param>
/// <param name="ext">The extension for events</param>
internal EventsLoader(string path, string ext)
{ {
EVPath = path; EVPath = path;
EVExtension = ext; EVExtension = ext;
} }
public List<DBEvent>? LoadEvents() /// <summary>
/// The method that loads all events
/// </summary>
/// <returns></returns>
internal List<DBEvent>? LoadEvents()
{ {
if (!Directory.Exists(EVPath)) if (!Directory.Exists(EVPath))

View File

@@ -10,6 +10,11 @@ namespace PluginManager.Loaders
public class PluginLoader public class PluginLoader
{ {
private DiscordSocketClient client; private DiscordSocketClient client;
/// <summary>
/// The Plugin Loader constructor
/// </summary>
/// <param name="discordSocketClient">The discord bot client where the plugins will pe attached to</param>
public PluginLoader(DiscordSocketClient discordSocketClient) public PluginLoader(DiscordSocketClient discordSocketClient)
{ {
this.client = discordSocketClient; this.client = discordSocketClient;
@@ -21,17 +26,33 @@ namespace PluginManager.Loaders
private const string pluginCMDExtension = ".dll"; private const string pluginCMDExtension = ".dll";
private const string pluginEVEExtension = ".dll"; private const string pluginEVEExtension = ".dll";
/// <summary>
/// A list of <see cref="DBCommand"/> commands
/// </summary>
public static List<DBCommand>? Plugins { get; set; } public static List<DBCommand>? Plugins { get; set; }
/// <summary>
/// A list of <see cref="DBEvent"/> commands
/// </summary>
public static List<DBEvent>? Events { get; set; } public static List<DBEvent>? Events { get; set; }
public delegate void CMDLoaded(string name, string typeName, bool success, Exception? e = null);
public delegate void CMDLoaded(string name, string typeName, bool success, Exception? e = null);
public delegate void EVELoaded(string name, string typeName, bool success, Exception? e = null); public delegate void EVELoaded(string name, string typeName, bool success, Exception? e = null);
/// <summary>
/// Event that is fired when a <see cref="DBCommand"/> is successfully loaded into commands list
/// </summary>
public CMDLoaded? onCMDLoad; public CMDLoaded? onCMDLoad;
/// <summary>
/// Event that is fired when a <see cref="DBEvent"/> is successfully loaded into events list
/// </summary>
public EVELoaded? onEVELoad; public EVELoaded? onEVELoad;
/// <summary>
/// The main mathod that is called to load all events
/// </summary>
public void LoadPlugins() public void LoadPlugins()
{ {

View File

@@ -1,8 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.IO; using System.IO;
@@ -13,6 +9,15 @@ namespace PluginManager.Online.Helpers
{ {
internal static class OnlineFunctions internal static class OnlineFunctions
{ {
/// <summary>
/// Downloads a <see cref="Stream"/> and saves it to another <see cref="Stream"/>.
/// </summary>
/// <param name="client">The <see cref="HttpClient"/> that is used to download the file</param>
/// <param name="url">The url to the file</param>
/// <param name="destination">The <see cref="Stream"/> to save the downloaded data</param>
/// <param name="progress">The <see cref="IProgress{T}"/> that is used to track the download progress</param>
/// <param name="cancellation">The cancellation token</param>
/// <returns></returns>
internal static async Task DownloadFileAsync(this HttpClient client, string url, Stream destination, IProgress<float> progress = null, CancellationToken cancellation = default) internal static async Task DownloadFileAsync(this HttpClient client, string url, Stream destination, IProgress<float> progress = null, CancellationToken cancellation = default)
{ {
using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)) using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
@@ -39,6 +44,12 @@ namespace PluginManager.Online.Helpers
} }
} }
/// <summary>
/// Read contents of a file as string from specified URL
/// </summary>
/// <param name="url">The URL to read from</param>
/// <param name="cancellation">The cancellation token</param>
/// <returns></returns>
internal static async Task<string> DownloadStringAsync(string url, CancellationToken cancellation = default) internal static async Task<string> DownloadStringAsync(string url, CancellationToken cancellation = default)
{ {
using (var client = new HttpClient()) using (var client = new HttpClient())

View File

@@ -11,8 +11,17 @@ namespace PluginManager.Online
public class LanguageManager public class LanguageManager
{ {
private string link; private string link;
/// <summary>
/// The Language Manager constructor
/// </summary>
/// <param name="link">The link to where all the languages for the bot are stored</param>
public LanguageManager(string link) => this.link = link; public LanguageManager(string link) => this.link = link;
/// <summary>
/// The method to list all languages
/// </summary>
/// <returns></returns>
public async Task ListAllLanguages() public async Task ListAllLanguages()
{ {
@@ -49,6 +58,11 @@ namespace PluginManager.Online
} }
/// <summary>
/// A function that gets the download link for specified language
/// </summary>
/// <param name="langName">The name of the language</param>
/// <returns></returns>
public async Task<string[]?> GetDownloadLink(string langName) public async Task<string[]?> GetDownloadLink(string langName)
{ {
try try

View File

@@ -10,13 +10,24 @@ namespace PluginManager.Online
{ {
public class PluginsManager public class PluginsManager
{ {
/// <summary>
/// The URL of the server
/// </summary>
public string PluginsLink { get; private set; } public string PluginsLink { get; private set; }
/// <summary>
/// The Plugin Manager constructor
/// </summary>
/// <param name="link">The link to the file where all plugins are stored</param>
public PluginsManager(string link) public PluginsManager(string link)
{ {
PluginsLink = link; PluginsLink = link;
} }
/// <summary>
/// The method to load all plugins
/// </summary>
/// <returns></returns>
public async Task ListAvailablePlugins() public async Task ListAvailablePlugins()
{ {
try try
@@ -77,6 +88,11 @@ namespace PluginManager.Online
} }
/// <summary>
/// The method to get plugin information by its name
/// </summary>
/// <param name="name">The plugin name</param>
/// <returns></returns>
public async Task<string[]> GetPluginLinkByName(string name) public async Task<string[]> GetPluginLinkByName(string name)
{ {
try try

View File

@@ -13,27 +13,26 @@ namespace PluginManager.Online
{ {
public class ServerCom public class ServerCom
{ {
/// <summary>
/// Read all lines from a file async
/// </summary>
/// <param name="link">The link of the file</param>
/// <returns></returns>
public static async Task<List<string>> ReadTextFromFile(string link) public static async Task<List<string>> ReadTextFromFile(string link)
{ {
string response = await OnlineFunctions.DownloadStringAsync(link); string response = await OnlineFunctions.DownloadStringAsync(link);
string[] lines = response.Split('\n'); string[] lines = response.Split('\n');
return lines.ToList(); return lines.ToList();
//[Obsolete]
#region old code for reading text from link
/*
List<string> s = new List<string>();
WebClient webClient = new WebClient();
var data = await webClient.OpenReadTaskAsync(link);
var response = await new StreamReader(data).ReadToEndAsync();
s.AddRange(from a in response.Split('\n')
where !a.StartsWith("$")
select a);
return s;*/
#endregion
} }
/// <summary>
/// Download file from url
/// </summary>
/// <param name="URL">The url to the file</param>
/// <param name="location">The location where to store the downloaded data</param>
/// <param name="progress">The <see cref="IProgress{T}"/> to track the download</param>
/// <returns></returns>
public static async Task DownloadFileAsync(string URL, string location, IProgress<float> progress) public static async Task DownloadFileAsync(string URL, string location, IProgress<float> progress)
{ {
using (var client = new System.Net.Http.HttpClient()) using (var client = new System.Net.Http.HttpClient())
@@ -46,50 +45,5 @@ namespace PluginManager.Online
} }
} }
} }
public static async Task DownloadFileAsync(string url, string location, int downloadNumber, int totalToDownload)
{
IProgress<float> progress = new Progress<float>(bytes =>
{
Console.Title = $"Downloading {MathF.Round(bytes, 2)}% ({downloadNumber}/{totalToDownload})";
});
await DownloadFileAsync(url, location, progress);
Console.Title = "ONLINE";
return;
//[Obsolete]
#region old download code
/*
WebClient client = new WebClient();
Spinner spinner = new Spinner();
Console.Write("Downloading ");
spinner.Start();
string oldTitle = Console.Title ?? "";
client.DownloadProgressChanged += (sender, e) =>
{
Console.Title = e.BytesReceived + "/" + e.TotalBytesToReceive + " (" + e.ProgressPercentage + "%) (" + downloadNumber + " / " + totalToDownload + ")";
};
client.DownloadFileCompleted += (sender, e) =>
{
spinner.Stop(); Console.WriteLine();
};
try
{
await client.DownloadFileTaskAsync(new Uri(url), location);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
Console.Title = oldTitle;
}*/
#endregion
}
} }
} }

View File

@@ -4,11 +4,38 @@ using System.Threading.Tasks;
namespace PluginManager.Others namespace PluginManager.Others
{ {
/// <summary>
/// A class that handles the sending of messages to the user.
/// </summary>
public static class ChannelManagement public static class ChannelManagement
{ {
/// <summary>
/// Get the text channel by name from server
/// </summary>
/// <param name="server">The server</param>
/// <param name="name">The channel name</param>
/// <returns><see cref="IGuildChannel"/></returns>
public static IGuildChannel GetTextChannel(this IGuild server, string name) => server.GetTextChannel(name); public static IGuildChannel GetTextChannel(this IGuild server, string name) => server.GetTextChannel(name);
/// <summary>
/// Get the voice channel by name from server
/// </summary>
/// <param name="server">The server</param>
/// <param name="name">The channel name</param>
/// <returns><see cref="IGuildChannel"/></returns>
public static IGuildChannel GetVoiceChannel(this IGuild server, string name) => server.GetVoiceChannel(name); public static IGuildChannel GetVoiceChannel(this IGuild server, string name) => server.GetVoiceChannel(name);
/// <summary>
/// Get the DM channel between <see cref="Discord.WebSocket.DiscordSocketClient"/> and <see cref="IGuildUser"/>
/// </summary>
/// <param name="user"></param>
/// <returns><see cref="IDMChannel"/></returns>
public static async Task<IDMChannel> GetDMChannel(IGuildUser user) => await user.CreateDMChannelAsync(); public static async Task<IDMChannel> GetDMChannel(IGuildUser user) => await user.CreateDMChannelAsync();
/// <summary>
/// Get the channel where the message was sent
/// </summary>
/// <param name="message">The message</param>
/// <returns><see cref="IChannel"/></returns>
public static IChannel GetChannel(IMessage message) => message.Channel; public static IChannel GetChannel(IMessage message) => message.Channel;
} }

View File

@@ -8,33 +8,6 @@ namespace PluginManager.Others
{ {
public class Console_Utilities public class Console_Utilities
{ {
const char _block = '■';
const string _back = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
const string _twirl = "-\\|/";
public static void WriteProgressBar(int percent, bool update = false)
{
if (update)
Console.Write(_back);
Console.Write("[");
var p = (int)((percent / 10f) + .5f);
for (var i = 0; i < 10; ++i)
{
if (i >= p)
Console.Write(' ');
else
Console.Write(_block);
}
Console.Write("] {0,3:##0}%", percent);
if (percent == 100)
Console.WriteLine();
}
public static void WriteProgress(int progress, bool update = false)
{
if (update)
Console.Write("\b");
Console.Write(_twirl[progress % _twirl.Length]);
}
/// <summary> /// <summary>
/// A way to create a table based on input data /// A way to create a table based on input data

View File

@@ -1,7 +1,49 @@
using System;
namespace PluginManager.Others namespace PluginManager.Others
{ {
public class Cryptography public class Cryptography
{ {
/// <summary>
/// Translate hex to string
/// </summary>
/// <param name="hexString">The encrypted string</param>
/// <returns></returns>
public static string FromHexToString(string hexString)
{
var bytes = new byte[hexString.Length / 2];
for (var i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
return System.Text.Encoding.Unicode.GetString(bytes);
}
/// <summary>
/// Translate string to hex
/// </summary>
/// <param name="str">The string to encrypt</param>
/// <returns></returns>
public static string ToHexString(string str)
{
var sb = new System.Text.StringBuilder();
var bytes = System.Text.Encoding.Unicode.GetBytes(str);
foreach (var t in bytes)
{
sb.Append(t.ToString("X2"));
}
return sb.ToString();
}
/// <summary>
/// Create MD5 hash
/// </summary>
/// <param name="text">The text to encrypt</param>
/// <returns></returns>
public static async System.Threading.Tasks.Task<string> CreateMD5(string text) public static async System.Threading.Tasks.Task<string> CreateMD5(string text)
{ {
string output = ""; string output = "";
@@ -17,6 +59,11 @@ namespace PluginManager.Others
return output; return output;
} }
/// <summary>
/// Create SHA256 hash
/// </summary>
/// <param name="text">The text to encrypt</param>
/// <returns></returns>
public static async System.Threading.Tasks.Task<string> CreateSHA256(string text) public static async System.Threading.Tasks.Task<string> CreateSHA256(string text)
{ {
string output = ""; string output = "";
@@ -31,7 +78,7 @@ namespace PluginManager.Others
return output; return output;
} }
public static System.IO.Stream GenerateStreamFromString(string s) private static System.IO.Stream GenerateStreamFromString(string s)
{ {
var stream = new System.IO.MemoryStream(); var stream = new System.IO.MemoryStream();
var writer = new System.IO.StreamWriter(stream); var writer = new System.IO.StreamWriter(stream);

View File

@@ -7,8 +7,14 @@
public enum OperatingSystem public enum OperatingSystem
{ WINDOWS, LINUX, MAC_OS, UNKNOWN } { WINDOWS, LINUX, MAC_OS, UNKNOWN }
/// <summary>
/// A list with all errors
/// </summary>
public enum Error public enum Error
{ UNKNOWN_ERROR, GUILD_NOT_FOUND, STREAM_NOT_FOUND } { UNKNOWN_ERROR, GUILD_NOT_FOUND, STREAM_NOT_FOUND }
/// <summary>
/// The output log type
/// </summary>
public enum OutputLogLevel { NONE, INFO, WARNING, ERROR, CRITICAL } public enum OutputLogLevel { NONE, INFO, WARNING, ERROR, CRITICAL }
} }

View File

@@ -5,10 +5,28 @@ namespace PluginManager.Others.Exceptions
[Serializable] [Serializable]
public class APIException : Exception public class APIException : Exception
{ {
/// <summary>
/// The function where the error occurred
/// </summary>
public string? Function { get; } = "not specified"; public string? Function { get; } = "not specified";
/// <summary>
/// The error code
/// </summary>
public Error? ErrorCode { get; } = Error.UNKNOWN_ERROR; public Error? ErrorCode { get; } = Error.UNKNOWN_ERROR;
/// <summary>
/// The possible cause that determined the error
/// </summary>
public string? PossibleCause { get; } = "not specified"; public string? PossibleCause { get; } = "not specified";
/// <summary>
/// The APIException contructor
/// </summary>
/// <param name="message">The error message</param>
/// <param name="function">The function where the message was triggered</param>
/// <param name="possible_cause">The possible cause of the error</param>
/// <param name="error">The error code</param>
public APIException(string message, string? function, string possible_cause, Error error) : base(message) public APIException(string message, string? function, string possible_cause, Error error) : base(message)
{ {
ErrorCode = error; ErrorCode = error;
@@ -16,22 +34,37 @@ namespace PluginManager.Others.Exceptions
PossibleCause = possible_cause; PossibleCause = possible_cause;
} }
/// <summary>
/// The APIException contructor
/// </summary>
/// <param name="message">The error message</param>
/// <param name="function">The function where the message was triggered</param>
/// <param name="errorCode">The error code</param>
public APIException(string message, string? function, Error? errorCode) : base(message) public APIException(string message, string? function, Error? errorCode) : base(message)
{ {
ErrorCode = errorCode; ErrorCode = errorCode;
Function = function; Function = function;
} }
/// <summary>
/// The APIException contructor
/// </summary>
/// <param name="message">The error message</param>
/// <param name="function">The function where the message was triggered</param>
public APIException(string message, string? function) : base(message) public APIException(string message, string? function) : base(message)
{ {
Function = function; Function = function;
} }
/// <summary>
/// The APIException contructor
/// </summary>
/// <param name="message">The error message</param>
public APIException(string message) : base(message) public APIException(string message) : base(message)
{ {
} }
/// <summary>
/// Method to print the error to <see cref="Console"/>
/// </summary>
public void Print() public void Print()
{ {
Console.WriteLine("Message Content: " + Message); Console.WriteLine("Message Content: " + Message);

View File

@@ -199,30 +199,6 @@ namespace PluginManager.Others
} }
public static string FromHexToString(string hexString)
{
var bytes = new byte[hexString.Length / 2];
for (var i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
return System.Text.Encoding.Unicode.GetString(bytes);
}
public static string ToHexString(string str)
{
var sb = new System.Text.StringBuilder();
var bytes = System.Text.Encoding.Unicode.GetBytes(str);
foreach (var t in bytes)
{
sb.Append(t.ToString("X2"));
}
return sb.ToString();
}
/// <summary> /// <summary>
/// Copy one Stream to another <see langword="async"/> /// Copy one Stream to another <see langword="async"/>
/// </summary> /// </summary>

View File

@@ -5,15 +5,47 @@ using System.Linq;
namespace PluginManager.Others.Permissions namespace PluginManager.Others.Permissions
{ {
/// <summary>
/// A class whith all discord permissions
/// </summary>
public static class DiscordPermissions public static class DiscordPermissions
{ {
/// <summary>
/// Checks if the role has the specified permission
/// </summary>
/// <param name="role">The role</param>
/// <param name="permission">The permission</param>
/// <returns></returns>
public static bool hasPermission(this IRole role, GuildPermission permission) => role.Permissions.Has(permission); public static bool hasPermission(this IRole role, GuildPermission permission) => role.Permissions.Has(permission);
/// <summary>
/// Check if user has the specified role
/// </summary>
/// <param name="user">The user</param>
/// <param name="role">The role</param>
/// <returns></returns>
public static bool hasRole(this SocketGuildUser user, IRole role) => user.Roles.Contains(role); public static bool hasRole(this SocketGuildUser user, IRole role) => user.Roles.Contains(role);
/// <summary>
/// Check if user has the specified permission
/// </summary>
/// <param name="user">The user</param>
/// <param name="permission">The permission</param>
/// <returns></returns>
public static bool hasPermission(this SocketGuildUser user, GuildPermission permission) public static bool hasPermission(this SocketGuildUser user, GuildPermission permission)
=> user.Roles.Where(role => role.hasPermission(permission)).Any() || user.Guild.Owner == user; => user.Roles.Where(role => role.hasPermission(permission)).Any() || user.Guild.Owner == user;
/// <summary>
/// Check if user is administrator of server
/// </summary>
/// <param name="user">The user</param>
/// <returns></returns>
public static bool isAdmin(this SocketGuildUser user) => user.hasPermission(GuildPermission.Administrator); public static bool isAdmin(this SocketGuildUser user) => user.hasPermission(GuildPermission.Administrator);
/// <summary>
/// Check if user is administrator of server
/// </summary>
/// <param name="user">The user</param>
/// <returns></returns>
public static bool isAdmin(this SocketUser user) => isAdmin((SocketGuildUser)user); public static bool isAdmin(this SocketUser user) => isAdmin((SocketGuildUser)user);
} }