20 Commits

Author SHA1 Message Date
eef13db3aa 2022-07-17 19:30:39 +03:00
27bbe899ab 2022-07-17 19:29:58 +03:00
79002de9a5 2022-07-17 19:28:22 +03:00
17f68a8e5e Moved Console activity on another thread 2022-07-17 18:53:56 +03:00
c415fa1c0c Updated display features 2022-07-17 14:21:16 +03:00
b8ec6f42df Fixed some bugs with Command handler and configuration 2022-07-13 19:48:57 +03:00
3f67d7f3f9 updated music commands 2022-07-10 21:57:22 +03:00
2dae8a3a63 2022-07-10 15:07:15 +03:00
47aae730c7 Music Commands 2022-07-09 14:57:49 +03:00
aa808e950a 2022-07-09 10:41:39 +03:00
7dd43b7841 2022-07-09 10:41:33 +03:00
82a3744d48 2022-07-09 10:26:36 +03:00
3839e4d838 patch 2022-07-09 09:48:58 +03:00
a66ebc43d9 updated music 2022-07-09 09:48:45 +03:00
45bbda8185 2022-07-07 13:56:21 +03:00
2db6bf2729 2022-07-07 13:55:32 +03:00
3097eb7fca 2022-07-06 14:43:10 +03:00
efb6ac5192 2022-07-06 14:32:16 +03:00
27fe615447 2022-07-06 14:00:41 +03:00
c40fcdac9d 2022-07-06 13:59:59 +03:00
43 changed files with 781 additions and 552 deletions

2
.gitignore vendored
View File

@@ -362,3 +362,5 @@ MigrationBackup/
# Fody - auto-generated XML schema # Fody - auto-generated XML schema
FodyWeavers.xsd FodyWeavers.xsd
*.txt

View File

@@ -1,4 +0,0 @@
{
"rpc.enabled": true,
"discord.enabled": true
}

View File

@@ -6,12 +6,25 @@
"compilationOptions": {}, "compilationOptions": {},
"targets": { "targets": {
".NETCoreApp,Version=v6.0": { ".NETCoreApp,Version=v6.0": {
"MusicCommands/1.0.0": { "Music Commands/1.0.0": {
"dependencies": { "dependencies": {
"PluginManager": "1.0.0" "PluginManager": "1.0.0",
"YoutubeExplode": "6.2.0"
}, },
"runtime": { "runtime": {
"MusicCommands.dll": {} "Music Commands.dll": {}
}
},
"AngleSharp/0.17.0": {
"dependencies": {
"System.Buffers": "4.5.1",
"System.Text.Encoding.CodePages": "5.0.0"
},
"runtime": {
"lib/netstandard2.0/AngleSharp.dll": {
"assemblyVersion": "0.17.0.0",
"fileVersion": "0.17.0.0"
}
} }
}, },
"Discord.Net/3.7.2": { "Discord.Net/3.7.2": {
@@ -108,6 +121,7 @@
} }
} }
}, },
"Microsoft.NETCore.Platforms/5.0.0": {},
"Newtonsoft.Json/13.0.1": { "Newtonsoft.Json/13.0.1": {
"runtime": { "runtime": {
"lib/netstandard2.0/Newtonsoft.Json.dll": { "lib/netstandard2.0/Newtonsoft.Json.dll": {
@@ -116,6 +130,7 @@
} }
} }
}, },
"System.Buffers/4.5.1": {},
"System.Collections.Immutable/5.0.0": {}, "System.Collections.Immutable/5.0.0": {},
"System.Interactive.Async/5.0.0": { "System.Interactive.Async/5.0.0": {
"dependencies": { "dependencies": {
@@ -144,7 +159,23 @@
} }
} }
}, },
"System.Text.Encoding.CodePages/5.0.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "5.0.0"
}
},
"System.ValueTuple/4.5.0": {}, "System.ValueTuple/4.5.0": {},
"YoutubeExplode/6.2.0": {
"dependencies": {
"AngleSharp": "0.17.0"
},
"runtime": {
"lib/net5.0/YoutubeExplode.dll": {
"assemblyVersion": "6.2.0.0",
"fileVersion": "6.2.0.0"
}
}
},
"PluginManager/1.0.0": { "PluginManager/1.0.0": {
"dependencies": { "dependencies": {
"Discord.Net": "3.7.2" "Discord.Net": "3.7.2"
@@ -156,11 +187,18 @@
} }
}, },
"libraries": { "libraries": {
"MusicCommands/1.0.0": { "Music Commands/1.0.0": {
"type": "project", "type": "project",
"serviceable": false, "serviceable": false,
"sha512": "" "sha512": ""
}, },
"AngleSharp/0.17.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-74haoXINcj4SdMsmiNzk+9VUwIX1U9P61O6AZd5Uao8SGNnJJB8Y/r8VJRc8orn4c7Vk/oURAKSNF9XcSDxbfA==",
"path": "anglesharp/0.17.0",
"hashPath": "anglesharp.0.17.0.nupkg.sha512"
},
"Discord.Net/3.7.2": { "Discord.Net/3.7.2": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
@@ -217,6 +255,13 @@
"path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0", "path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512" "hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512"
}, },
"Microsoft.NETCore.Platforms/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==",
"path": "microsoft.netcore.platforms/5.0.0",
"hashPath": "microsoft.netcore.platforms.5.0.0.nupkg.sha512"
},
"Newtonsoft.Json/13.0.1": { "Newtonsoft.Json/13.0.1": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
@@ -224,6 +269,13 @@
"path": "newtonsoft.json/13.0.1", "path": "newtonsoft.json/13.0.1",
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512" "hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
}, },
"System.Buffers/4.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==",
"path": "system.buffers/4.5.1",
"hashPath": "system.buffers.4.5.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": { "System.Collections.Immutable/5.0.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
@@ -252,6 +304,13 @@
"path": "system.reactive/5.0.0", "path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512" "hashPath": "system.reactive.5.0.0.nupkg.sha512"
}, },
"System.Text.Encoding.CodePages/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==",
"path": "system.text.encoding.codepages/5.0.0",
"hashPath": "system.text.encoding.codepages.5.0.0.nupkg.sha512"
},
"System.ValueTuple/4.5.0": { "System.ValueTuple/4.5.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
@@ -259,6 +318,13 @@
"path": "system.valuetuple/4.5.0", "path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512" "hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
}, },
"YoutubeExplode/6.2.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-oH5kst4w1QkUwRjJco0alF57JOmFofSGlPkr4OniODB8R6MEyRWn1xFg3JS2wFYd6scZluoXRDhM3/uyUjO9/g==",
"path": "youtubeexplode/6.2.0",
"hashPath": "youtubeexplode.6.2.0.nupkg.sha512"
},
"PluginManager/1.0.0": { "PluginManager/1.0.0": {
"type": "project", "type": "project",
"serviceable": false, "serviceable": false,

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<BaseOutputPath>..\DiscordBot\bin\Debug\net6.0\Data\Plugins\Commands\LevelingSystem</BaseOutputPath> <BaseOutputPath>bin\</BaseOutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<BaseOutputPath></BaseOutputPath> <BaseOutputPath>bin\</BaseOutputPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

Binary file not shown.

View File

@@ -96,16 +96,6 @@ internal class Boot
Console.Title = "ONLINE"; Console.Title = "ONLINE";
isReady = true; isReady = true;
new Thread(() =>
{
while (true)
{
Config.SaveConfig();
Thread.Sleep(10000);
}
}
).Start();
return Task.CompletedTask; return Task.CompletedTask;
} }

View File

@@ -2,9 +2,15 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.Loader;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket;
using DiscordBot.Discord.Core; using DiscordBot.Discord.Core;
using PluginManager; using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Items; using PluginManager.Items;
using PluginManager.Online; using PluginManager.Online;
using PluginManager.Others; using PluginManager.Others;
@@ -43,7 +49,8 @@ public class Program
Console.Write("Prefix = "); Console.Write("Prefix = ");
var prefix = Console.ReadLine()![0]; var prefix = Console.ReadLine()![0];
if (prefix == ' ' || char.IsDigit(prefix)) return; if (prefix == ' ' || char.IsDigit(prefix))
return;
Config.AddValueToVariables("prefix", prefix.ToString(), false); Config.AddValueToVariables("prefix", prefix.ToString(), false);
} }
@@ -65,7 +72,7 @@ public class Program
/// The main loop for the discord bot /// The main loop for the discord bot
/// </summary> /// </summary>
/// <param name="discordbooter">The discord booter used to start the application</param> /// <param name="discordbooter">The discord booter used to start the application</param>
private static Task NoGUI(Boot discordbooter) private static void NoGUI(Boot discordbooter)
{ {
var consoleCommandsHandler = new ConsoleCommandsHandler(discordbooter.client); var consoleCommandsHandler = new ConsoleCommandsHandler(discordbooter.client);
if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp"); if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp");
@@ -73,13 +80,21 @@ public class Program
Config.SaveConfig(); Config.SaveConfig();
while (true) while (true)
{ {
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
#if DEBUG
Console_Utilities.WriteColorText("&rSethBot (&yDEBUG&r) &c> ", false);
var cmd = Console.ReadLine(); var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd)) if (!consoleCommandsHandler.HandleCommand(cmd!, false) && cmd.Length > 0)
Console.WriteLine("Failed to run command " + cmd); Console.WriteLine("Failed to run command " + cmd);
#else
Console_Utilities.WriteColorText("&rSethBot &c> ", false);
var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd!) && cmd.Length > 0)
Console.WriteLine("Failed to run command " + cmd);
#endif
} }
} }
@@ -92,19 +107,33 @@ public class Program
Console.Clear(); Console.Clear();
Console.ForegroundColor = ConsoleColor.DarkYellow; Console.ForegroundColor = ConsoleColor.DarkYellow;
List<string> startupMessageList = await ServerCom.ReadTextFromFile("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/StartupMessage"); List<string> startupMessageList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/StartupMessage");
foreach (var message in startupMessageList) Console.WriteLine(message); foreach (var message in startupMessageList)
Console.WriteLine(message);
Console.WriteLine($"Running on version: {Config.GetValue<string>("Version") ?? System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()}"); Console.WriteLine($"Running on version: {Config.GetValue<string>("Version") ?? System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()}");
Console.WriteLine($"Git URL: {Config.GetValue<string>("GitURL") ?? " Could not find Git URL"}"); Console.WriteLine($"Git URL: {Config.GetValue<string>("GitURL") ?? " Could not find Git URL"}");
Console_Utilities.WriteColorText("&rRemember to close the bot using the ShutDown command (&ysd&r) or some settings won't be saved\n");
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"============================ LOG ============================"); Console.WriteLine($"============================ LOG ============================");
try try
{ {
var token = Config.GetValue<string>("token"); var token = Config.GetValue<string>("token");
#if DEBUG
Console.WriteLine("Starting in DEBUG MODE");
if (!Directory.Exists("./Data/BetaTest"))
Console.WriteLine("Failed to start in debug mode because the folder ./Data/BetaTest does not exist");
else
{
token = File.ReadAllText("./Data/BetaTest/token.txt");
//Debug mode code...
}
#endif
var prefix = Config.GetValue<string>("prefix"); var prefix = Config.GetValue<string>("prefix");
var discordbooter = new Boot(token, prefix); var discordbooter = new Boot(token, prefix);
@@ -155,8 +184,11 @@ public class Program
if (len > 0 && (args.Contains("--cmd") || args.Contains("--args") || args.Contains("--nomessage"))) if (len > 0 && (args.Contains("--cmd") || args.Contains("--args") || args.Contains("--nomessage")))
{ {
if (args.Contains("lp") || args.Contains("loadplugins")) loadPluginsOnStartup = true; if (args.Contains("lp") || args.Contains("loadplugins"))
if (args.Contains("listplugs")) listPluginsAtStartup = true; loadPluginsOnStartup = true;
if (args.Contains("listplugs"))
listPluginsAtStartup = true;
len = 0; len = 0;
} }
@@ -164,7 +196,9 @@ public class Program
if (len == 0 || (args[0] != "--exec" && args[0] != "--execute")) if (len == 0 || (args[0] != "--exec" && args[0] != "--execute"))
{ {
var b = await StartNoGUI(); var b = await StartNoGUI();
await NoGUI(b);
Thread mainThread = new Thread(() => NoGUI(b));
mainThread.Start();
return; return;
} }
@@ -190,15 +224,7 @@ public class Program
case "--help": case "--help":
case "-help": case "-help":
Console.ForegroundColor = ConsoleColor.DarkYellow; Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine( Console.WriteLine("\tCommand name\t\t\t\tDescription\n" + "-- help | -help\t\t ------ \tDisplay the help message\n" + "--reset-full\t\t ------ \tReset all files (clear files)\n" + "--reset-settings\t ------ \tReset only bot settings\n" + "--reset-logs\t\t ------ \tClear up the output folder\n" + "--start\t\t ------ \tStart the bot\n" + "exit\t\t\t ------ \tClose the application");
"\tCommand name\t\t\t\tDescription\n" +
"-- help | -help\t\t ------ \tDisplay the help message\n" +
"--reset-full\t\t ------ \tReset all files (clear files)\n" +
"--reset-settings\t ------ \tReset only bot settings\n" +
"--reset-logs\t\t ------ \tClear up the output folder\n" +
"--start\t\t ------ \tStart the bot\n" +
"exit\t\t\t ------ \tClose the application"
);
break; break;
case "--reset-full": case "--reset-full":
await ClearFolder("./Data/Resources/"); await ClearFolder("./Data/Resources/");
@@ -218,10 +244,6 @@ public class Program
case "exit": case "exit":
Environment.Exit(0); Environment.Exit(0);
break; break;
case "--start":
var booter = await StartNoGUI();
await NoGUI(booter);
return;
default: default:
Console.WriteLine("Failed to execute command " + message[0]); Console.WriteLine("Failed to execute command " + message[0]);
@@ -237,7 +259,7 @@ public class Program
if (Config.GetValue<bool>("DeleteLogsAtStartup")) if (Config.GetValue<bool>("DeleteLogsAtStartup"))
foreach (var file in Directory.GetFiles("./Output/Logs/")) foreach (var file in Directory.GetFiles("./Output/Logs/"))
File.Delete(file); File.Delete(file);
List<string> OnlineDefaultKeys = await ServerCom.ReadTextFromFile("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/SetupKeys"); List<string> OnlineDefaultKeys = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/SetupKeys");
Config.PluginConfig.Load(); Config.PluginConfig.Load();
@@ -252,7 +274,8 @@ public class Program
string[] s = key.Split(' '); string[] s = key.Split(' ');
try try
{ {
Config.GetAndAddValueToVariable(s[0], s[1], s[2].Equals("true", StringComparison.CurrentCultureIgnoreCase)); if (Config.ContainsKey(s[0])) Config.SetValue(s[0], s[1]);
else Config.GetAndAddValueToVariable(s[0], s[1], s[2].Equals("true", StringComparison.CurrentCultureIgnoreCase));
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -260,7 +283,7 @@ public class Program
} }
} }
List<string> onlineSettingsList = await ServerCom.ReadTextFromFile("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData"); List<string> onlineSettingsList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData");
foreach (var key in onlineSettingsList) foreach (var key in onlineSettingsList)
{ {
if (key.Length <= 3 || !key.Contains(' ')) continue; if (key.Length <= 3 || !key.Contains(' ')) continue;
@@ -306,6 +329,7 @@ public class Program
} }
} }
Console_Utilities.Initialize();
Config.SaveConfig(); Config.SaveConfig();
} }

View File

@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<BaseOutputPath>..\DiscordBot\bin\Debug\net6.0\Data\Plugins\Events\LevelingSystem</BaseOutputPath> <BaseOutputPath></BaseOutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -11,15 +11,18 @@ namespace EVE_LevelingSystem
{ {
public string name => "Leveling System Event Handler"; public string name => "Leveling System Event Handler";
public string description => "The Leveling System Event Handler"; public string description => "The Leveling System Event Handler";
internal static Settings globalSettings = new(); internal static Settings globalSettings = new();
public async void Start(DiscordSocketClient client) public async void Start(DiscordSocketClient client)
{ {
Directory.CreateDirectory("./Data/Resources/LevelingSystem"); Directory.CreateDirectory("./Data/Resources/LevelingSystem");
if (!Config.ContainsKey("LevelingSystemPath"))
Config.AddValueToVariables("LevelingSystemPath", "./Data/Resources/LevelingSystem", true); Config.AddValueToVariables("LevelingSystemPath", "./Data/Resources/LevelingSystem", true);
if (!Config.ContainsKey("LevelingSystemSettingsFile"))
Config.AddValueToVariables("LevelingSystemSettingsFile", "./Data/Resources/LevelingSystemSettings.txt", true); Config.AddValueToVariables("LevelingSystemSettingsFile", "./Data/Resources/LevelingSystemSettings.txt", true);
//PluginManager.Config.AddValueToVariables
if (!File.Exists(Config.GetValue<string>("LevelingSystemSettingsFile"))) if (!File.Exists(Config.GetValue<string>("LevelingSystemSettingsFile")))
{ {
globalSettings = new Settings { TimeToWaitBetweenMessages = 5 }; globalSettings = new Settings { TimeToWaitBetweenMessages = 5 };

View File

@@ -0,0 +1,34 @@
using AngleSharp.Dom;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MusicCommands
{
internal class AudioFile
{
internal string Name { get; set; }
internal string Url { get; set; }
internal AudioFile(string name, string url)
{
Name = name;
Url = url;
}
internal async Task DownloadAudioFile()
{
Process proc = new Process();
proc.StartInfo.FileName = "MusicDownloader.exe";
proc.StartInfo.Arguments = $"{Url},{Name}";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
await proc.WaitForExitAsync();
}
}
}

View File

@@ -8,5 +8,6 @@ internal static class Data
internal static IAudioClient audioClient = null; internal static IAudioClient audioClient = null;
internal static IVoiceChannel voiceChannel = null; internal static IVoiceChannel voiceChannel = null;
internal static MusicPlayer CurrentlyRunning = null; internal static MusicPlayer MusicPlayer = null;
internal static MusicPlaylist Playlist = new();
} }

View File

@@ -22,10 +22,20 @@ internal class Leave : DBCommand
{ {
if (Data.audioClient is not null && Data.voiceChannel is not null) if (Data.audioClient is not null && Data.voiceChannel is not null)
{ {
Data.CurrentlyRunning.Stop();
Data.CurrentlyRunning = null;
await Data.audioClient.StopAsync(); await Data.audioClient.StopAsync();
await Data.voiceChannel.DisconnectAsync(); await Data.voiceChannel.DisconnectAsync();
} }
if (Data.Playlist is not null)
{
Data.Playlist.ClearQueue();
Data.Playlist = new();
}
if (Data.MusicPlayer is not null)
{
Data.MusicPlayer.Stop();
Data.MusicPlayer = null;
}
} }
} }

View File

@@ -3,7 +3,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Nullable>warnings</Nullable> <Nullable>warnings</Nullable>
<BaseOutputPath>..\DiscordBot\bin\Debug\net6.0\Data\Plugins\Commands\MusicCommands</BaseOutputPath> <BaseOutputPath>bin\</BaseOutputPath>
<AssemblyName>Music Commands</AssemblyName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -17,4 +18,8 @@
<ProjectReference Include="..\PluginManager\PluginManager.csproj" /> <ProjectReference Include="..\PluginManager\PluginManager.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="YoutubeExplode" Version="6.2.0" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,118 +1,51 @@
using System; using System.IO;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using PluginManager.Others;
namespace MusicCommands; namespace MusicCommands;
internal class MusicPlayer internal class MusicPlayer
{ {
public MusicPlayer(Stream input, Stream output) private Stream outputStream { get; }
internal bool isPlaying, isPaused;
public MusicPlayer(Stream outputChannel)
{ {
inputStream = input; outputStream = outputChannel;
outputStream = output;
} }
public MusicPlayer(Stream output) public async Task Play(Stream source, int byteSize)
{ {
inputStream = null; isPlaying = true;
outputStream = output; while (isPlaying)
{
if (isPaused)
continue;
var bits = new byte[byteSize];
var read = await source.ReadAsync(bits, 0, byteSize);
if (read == 0)
break;
try
{
await outputStream.WriteAsync(bits, 0, read);
}
catch
{
break;
}
} }
public Stream inputStream { get; } // from FFMPEG
public Stream outputStream { get; } // to Voice Channel
public bool Paused { get; set; } await source.FlushAsync();
private bool _stop { get; set; } await source.DisposeAsync();
source.Close();
await outputStream.FlushAsync();
isPlaying = false;
}
public void Stop() public void Stop()
{ {
_stop = true; isPlaying = false;
}
public async Task StartSendAudioFromLink(string URL)
{
/* using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(URL))
using (var content = response.Content)
{
await (await content.ReadAsStreamAsync()).CopyToAsync(outputStream);
}*/
Stream ms = new MemoryStream();
var bsize = 512;
new Thread(async delegate(object o)
{
var response = await new HttpClient().GetAsync(URL);
using (var stream = await response.Content.ReadAsStreamAsync())
{
var buffer = new byte[bsize];
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
var pos = ms.Position;
ms.Position = ms.Length;
ms.Write(buffer, 0, read);
ms.Position = pos;
}
}
}
).Start();
Console.Write("Reading data: ");
while (ms.Length < bsize * 10)
{
await Task.Delay(1000);
Console.Title = "Reading data: " + ms.Length + " bytes read of " + bsize * 10;
Console.Write(".");
}
Console.WriteLine("\nDone");
ms.Position = 0;
_stop = false;
Paused = false;
while (!_stop)
{
if (Paused) continue;
var buffer = new byte[bsize];
var read = await ms.ReadAsync(buffer, 0, buffer.Length);
if (read > 0)
await outputStream.WriteAsync(buffer, 0, read);
else
break;
}
}
public async Task StartSendAudio()
{
Paused = false;
_stop = false;
while (!_stop)
{
if (Paused) continue;
var bsize = 512;
var buffer = new byte[bsize];
var bcount = await inputStream.ReadAsync(buffer, 0, bsize);
if (bcount <= 0)
{
Stop();
Data.CurrentlyRunning = null;
break;
}
try
{
await outputStream.WriteAsync(buffer, 0, bcount);
}
catch (Exception ex)
{
await outputStream.FlushAsync();
Functions.WriteLogFile(ex.ToString());
}
}
} }
} }

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MusicCommands
{
internal class MusicPlaylist
{
internal MusicPlaylist()
{
Console.WriteLine("Initialized playlist.");
}
public Queue<AudioFile> QueueList = new();
public void Enqueue(AudioFile query) => QueueList.Enqueue(query);
public void ClearQueue() => QueueList.Clear();
public int Count => QueueList.Count;
public AudioFile GetNextSong => QueueList.Dequeue();
public AudioFile WhatIsNext => QueueList.Peek();
}
}

View File

@@ -8,7 +8,7 @@ internal class Pause : DBCommand
{ {
public string Command => "pause"; public string Command => "pause";
public string Description => "Pause the music"; public string Description => "Pause/Unpause the music that is currently running";
public string Usage => "pause"; public string Usage => "pause";
@@ -20,6 +20,6 @@ internal class Pause : DBCommand
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{ {
Data.CurrentlyRunning.Paused = true; Data.MusicPlayer.isPaused = !Data.MusicPlayer.isPaused;
} }
} }

View File

@@ -12,11 +12,11 @@ namespace MusicCommands;
internal class Play : DBCommand internal class Play : DBCommand
{ {
public string Command => "fplay"; public string Command => "play";
public string Description => "Play music from a file"; public string Description => "Play music from a file";
public string Usage => "fplay [name]"; public string Usage => "play [name/url]";
public bool canUseDM => false; public bool canUseDM => false;
@@ -26,32 +26,87 @@ internal class Play : DBCommand
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 path = "./Music"; Directory.CreateDirectory("Music");
var FileName = Functions.GetArguments(message).ToArray().MergeStrings(0); var path = "./Music/";
path += "/" + FileName + ".ogg"; string[] splitted = message.Content.Split(' ');
if (!File.Exists(path)) if (splitted.Length < 2)
return;
do
{ {
Console.WriteLine("Unknown path " + path); if (splitted.Length == 2 && splitted[1].Contains("youtube.com") || splitted[1].Contains("youtu.be"))
{
var url = splitted[1];
path += $"{Functions.CreateMD5(url)}";
if (File.Exists(path))
{
Data.Playlist.Enqueue(new AudioFile(path, null));
}
else
{
var file = new AudioFile(path, url);
await file.DownloadAudioFile();
Data.Playlist.Enqueue(file);
}
}
else
{
var searchString = splitted.MergeStrings(1);
path += $"{Functions.CreateMD5(searchString)}";
if (File.Exists(path))
{
Data.Playlist.Enqueue(new AudioFile(path, null));
}
else
{
await context.Channel.SendMessageAsync("Searching for " + searchString);
var file = new AudioFile(path, searchString);
await file.DownloadAudioFile();
Data.Playlist.Enqueue(file);
if (Data.MusicPlayer is null)
await context.Channel.SendMessageAsync("Playing: " + searchString);
}
}
if (Data.MusicPlayer is not null)
{
await context.Channel.SendMessageAsync("Enqueued your request");
return; return;
} }
}
while (false);
Data.voiceChannel = (context.User as IGuildUser)?.VoiceChannel; Data.voiceChannel = (context.User as IGuildUser)?.VoiceChannel;
if (Data.voiceChannel == null) if (Data.voiceChannel == null)
{ {
await context.Channel.SendMessageAsync("User must be in a voice channel, or a voice channel must be passed as an argument."); await context.Channel.SendMessageAsync("User must be in a voice channel, or a voice channel must be passed as an argument.");
return; return;
} }
Data.audioClient = await Data.voiceChannel.ConnectAsync(); if (Data.audioClient is null)
using (var ffmpeg = CreateStream(path))
using (var output = ffmpeg.StandardOutput.BaseStream)
using (var discord = Data.audioClient.CreatePCMStream(AudioApplication.Mixed))
{ {
if (Data.CurrentlyRunning != null) Data.CurrentlyRunning.Stop(); Data.audioClient = await Data.voiceChannel.ConnectAsync(true);
Data.CurrentlyRunning = new MusicPlayer(output, discord); Data.MusicPlayer = null;
await Data.CurrentlyRunning.StartSendAudio(); }
using (var discordChanneAudioOutStream = Data.audioClient.CreatePCMStream(AudioApplication.Mixed))
{
if (Data.MusicPlayer is null)
Data.MusicPlayer = new MusicPlayer(discordChanneAudioOutStream);
while (Data.Playlist.Count > 0)
{
var nowPlaying = Data.Playlist.GetNextSong;
using (var ffmpeg = CreateStream(nowPlaying.Name))
using (var ffmpegOutputBaseStream = ffmpeg.StandardOutput.BaseStream)
{
await Data.MusicPlayer.Play(ffmpegOutputBaseStream, 1024);
Console.WriteLine("Finished playing from " + nowPlaying.Url);
}
}
Data.MusicPlayer = null;
} }
} }

31
MusicCommands/Skip.cs Normal file
View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace MusicCommands
{
public class Skip : DBCommand
{
public string Command => "skip";
public string Description => "skip the music that is currently running";
public string Usage => "skip";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false;
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
Data.MusicPlayer.isPlaying = false;
}
}
}

View File

@@ -1,25 +0,0 @@
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace MusicCommands;
internal class Unpause : DBCommand
{
public string Command => "unpause";
public string Description => "Unpause the music";
public string Usage => "unpause";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false;
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
Data.CurrentlyRunning.Paused = false;
}
}

View File

@@ -1,49 +0,0 @@
using Discord;
using Discord.Audio;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace MusicCommands;
internal class lplay : DBCommand
{
public string Command => "lplay";
public string Description => "Play music from a link";
public string Usage => "lplay [url]";
public bool canUseDM => false;
public bool canUseServer => false;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
var URL = message.Content.Split(' ')[1];
if (!URL.EndsWith(".mp3") && !URL.EndsWith(".wav") && !URL.EndsWith(".flac") && !URL.EndsWith(".ogg"))
{
await message.Channel.SendMessageAsync("Invalid URL");
return;
}
Data.voiceChannel = (context.User as IGuildUser)?.VoiceChannel;
if (Data.voiceChannel == null)
{
await context.Channel.SendMessageAsync("User must be in a voice channel, or a voice channel must be passed as an argument.");
return;
}
Data.audioClient = await Data.voiceChannel.ConnectAsync();
using (var discord = Data.audioClient.CreatePCMStream(AudioApplication.Mixed))
{
await message.Channel.SendMessageAsync("Loading...");
Data.CurrentlyRunning = new MusicPlayer(discord);
await Data.CurrentlyRunning.StartSendAudioFromLink(URL);
}
}
}

31
MusicCommands/queue.cs Normal file
View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager.Interfaces;
namespace MusicCommands
{
public class queue : DBCommand
{
public string Command => "queue";
public string Description => "check queue";
public string Usage => "queue";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
await context.Channel.SendMessageAsync($"You have {Data.Playlist.Count} items in queue");
}
}
}

View File

@@ -4,22 +4,22 @@ using System.IO;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading; using System.Threading;
using Newtonsoft.Json.Linq;
namespace PluginManager namespace PluginManager
{ {
internal class AppConfig internal class AppConfig
{ {
public Dictionary<string, object>? ApplicationVariables { get; set; } public Dictionary<string, object>? ApplicationVariables { get; init; }
public List<string>? ProtectedKeyWords { get; set; } public List<string>? ProtectedKeyWords { get; init; }
} }
public static class Config public static class Config
{ {
public static class PluginConfig public static class PluginConfig
{ {
public static List<Tuple<string, PluginType>> InstalledPlugins = new(); public static readonly List<Tuple<string, PluginType>> InstalledPlugins = new();
public static void Load() public static void Load()
{ {
@@ -77,20 +77,43 @@ namespace PluginManager
private static AppConfig? appConfig { get; set; } private static AppConfig? appConfig { get; set; }
public static bool AddValueToVariables<T>(string key, T value, bool isProtected) public static void AddValueToVariables<T>(string key, T value, bool isProtected)
{ {
if (appConfig!.ApplicationVariables!.ContainsKey(key)) return false; if (value == null)
if (value == null) return false; throw new Exception("The value cannot be null");
if (appConfig!.ApplicationVariables!.ContainsKey(key))
throw new Exception($"The key ({key}) already exists in the variables. Value {GetValue<T>(key)}");
appConfig.ApplicationVariables.Add(key, value); appConfig.ApplicationVariables.Add(key, value);
if (isProtected && key != "Version") appConfig.ProtectedKeyWords!.Add(key); if (isProtected && key != "Version")
appConfig.ProtectedKeyWords!.Add(key);
SaveConfig(); SaveConfig();
return true; }
public static Type GetVariableType(string value)
{
if (int.TryParse(value, out var intValue))
return typeof(int);
if (bool.TryParse(value, out var boolValue))
return typeof(bool);
if (float.TryParse(value, out var floatValue))
return typeof(float);
if (double.TryParse(value, out var doubleValue))
return typeof(double);
if (uint.TryParse(value, out var uintValue))
return typeof(uint);
if (long.TryParse(value, out var longValue))
return typeof(long);
if (byte.TryParse(value, out var byteValue))
return typeof(byte);
return typeof(string);
} }
public static void GetAndAddValueToVariable(string key, string value, bool isReadOnly) public static void GetAndAddValueToVariable(string key, string value, bool isReadOnly)
{ {
if (Config.ContainsKey(key)) return; if (Config.ContainsKey(key))
return;
if (int.TryParse(value, out var intValue)) if (int.TryParse(value, out var intValue))
Config.AddValueToVariables(key, intValue, isReadOnly); Config.AddValueToVariables(key, intValue, isReadOnly);
else if (bool.TryParse(value, out var boolValue)) else if (bool.TryParse(value, out var boolValue))
@@ -123,24 +146,26 @@ namespace PluginManager
} }
} }
public static bool SetValue<T>(string key, T value) public static void SetValue<T>(string key, T value)
{ {
if (!appConfig!.ApplicationVariables!.ContainsKey(key)) return false; if (value == null)
if (appConfig.ProtectedKeyWords!.Contains(key)) return false; throw new Exception("Value is null");
if (value == null) return false; if (!appConfig!.ApplicationVariables!.ContainsKey(key))
throw new Exception("Key does not exist in the config file");
if (appConfig.ProtectedKeyWords!.Contains(key))
throw new Exception("Key is protected");
appConfig.ApplicationVariables[key] = JsonSerializer.SerializeToElement(value); appConfig.ApplicationVariables[key] = JsonSerializer.SerializeToElement(value);
SaveConfig(); SaveConfig();
return true;
} }
public static bool RemoveKey(string key) public static void RemoveKey(string key)
{ {
if (key == "Version" || key == "token" || key == "prefix") return false; if (key == "Version" || key == "token" || key == "prefix")
throw new Exception("Key is protected");
appConfig!.ApplicationVariables!.Remove(key); appConfig!.ApplicationVariables!.Remove(key);
appConfig.ProtectedKeyWords!.Remove(key); appConfig.ProtectedKeyWords!.Remove(key);
SaveConfig(); SaveConfig();
return true;
} }
public static async void SaveConfig() public static async void SaveConfig()
@@ -164,6 +189,6 @@ namespace PluginManager
public static bool ContainsValue<T>(T value) => appConfig!.ApplicationVariables!.ContainsValue(value!); public static bool ContainsValue<T>(T value) => appConfig!.ApplicationVariables!.ContainsValue(value!);
public static bool ContainsKey(string key) => appConfig!.ApplicationVariables!.ContainsKey(key); public static bool ContainsKey(string key) => appConfig!.ApplicationVariables!.ContainsKey(key);
public static Dictionary<string, object> GetAllVariables() => new(appConfig!.ApplicationVariables!); public static ReadOnlyDictionary<string, object> GetAllVariables() => new(appConfig!.ApplicationVariables!);
} }
} }

View File

@@ -1,11 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Others; using PluginManager.Others;
namespace PluginManager.Items; namespace PluginManager.Items;
internal class Command public class Command
{ {
/// <summary> /// <summary>
/// The author of the command /// The author of the command
@@ -20,10 +21,7 @@ internal class Command
{ {
Author = message.Author; Author = message.Author;
var data = message.Content.Split(' '); var data = message.Content.Split(' ');
if (data.Length > 1) Arguments = data.Length > 1 ? new List<string>(data.MergeStrings(1).Split(' ')) : new List<string>();
Arguments = new List<string>(data.MergeStrings(1).Split(' '));
else
Arguments = new List<string>();
CommandName = data[0].Substring(1); CommandName = data[0].Substring(1);
PrefixUsed = data[0][0]; PrefixUsed = data[0][0];
} }

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
@@ -15,14 +14,14 @@ namespace PluginManager.Items;
public class ConsoleCommandsHandler public class ConsoleCommandsHandler
{ {
private static readonly PluginsManager manager = new("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Plugins.txt"); private static readonly PluginsManager manager = new("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Plugins.txt");
public static List<ConsoleCommand> commandList = new(); private static readonly List<ConsoleCommand> commandList = new();
private readonly DiscordSocketClient? client; private readonly DiscordSocketClient? client;
public ConsoleCommandsHandler(DiscordSocketClient client) public ConsoleCommandsHandler(DiscordSocketClient client)
{ {
this.client = client; this.client = client;
InitializeBasicCommands(); InitializeBasicCommands();
Console.WriteLine("Initialized console command handler !"); //Console.WriteLine("Initialized console command handler !");
} }
private void InitializeBasicCommands() private void InitializeBasicCommands()
@@ -43,14 +42,12 @@ public class ConsoleCommandsHandler
foreach (var command in commandList) foreach (var command in commandList)
{ {
var pa = from p in command.Action.Method.GetParameters() var pa = from p in command.Action.Method.GetParameters() where p.Name != null select p.ParameterType.FullName;
where p.Name != null
select p.ParameterType.FullName;
items.Add(new[] { command.CommandName, command.Description, command.Usage }); items.Add(new[] { command.CommandName, command.Description, command.Usage });
} }
items.Add(new[] { "-", "-", "-" }); items.Add(new[] { "-", "-", "-" });
Console_Utilities.FormatAndAlignTable(items); Console_Utilities.FormatAndAlignTable(items, TableFormat.DEFAULT);
} }
else else
{ {
@@ -70,12 +67,14 @@ public class ConsoleCommandsHandler
AddCommand("lp", "Load plugins", () => AddCommand("lp", "Load plugins", () =>
{ {
if (pluginsLoaded) return; if (pluginsLoaded)
return;
var loader = new PluginLoader(client!); var loader = new PluginLoader(client!);
loader.onCMDLoad += (name, typeName, success, exception) => loader.onCMDLoad += (name, typeName, success, exception) =>
{ {
Console.ForegroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Green;
if (name == null || name.Length < 2) name = typeName; if (name == null || name.Length < 2)
name = typeName;
if (success) if (success)
Console.WriteLine("[CMD] Successfully loaded command : " + name); Console.WriteLine("[CMD] Successfully loaded command : " + name);
else else
@@ -84,7 +83,8 @@ public class ConsoleCommandsHandler
}; };
loader.onEVELoad += (name, typeName, success, exception) => loader.onEVELoad += (name, typeName, success, exception) =>
{ {
if (name == null || name.Length < 2) name = typeName; if (name == null || name.Length < 2)
name = typeName;
Console.ForegroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Green;
if (success) if (success)
Console.WriteLine("[EVENT] Successfully loaded event : " + name); Console.WriteLine("[EVENT] Successfully loaded event : " + name);
@@ -97,7 +97,7 @@ public class ConsoleCommandsHandler
} }
); );
AddCommand("listplugs", "list available plugins", async () => { await manager.ListAvailablePlugins(); }); AddCommand("listplugs", "list available plugins", () => { manager.ListAvailablePlugins().Wait(); });
AddCommand("dwplug", "download plugin", "dwplug [name]", async args => AddCommand("dwplug", "download plugin", "dwplug [name]", async args =>
{ {
@@ -120,22 +120,22 @@ public class ConsoleCommandsHandler
return; return;
} }
Console_Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" + Console_Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" + " Use &glistplugs &ccommand to display all available plugins !");
" Use &glistplugs &ccommand to display all available plugins !"
);
return; return;
} }
string path; string path;
if (info[0] == "Command" || info[0] == "Event") if (info[0] == "Command" || info[0] == "Event")
path = "./Data/Plugins/" + info[0] + "s/" + name + ".dll"; path = "./Data/Plugins/" + info[0] + "s/" + name + "." + (info[0] == "Command" ? PluginLoader.pluginCMDExtension : PluginLoader.pluginEVEExtension);
else else
path = $"./{info[1].Split('/')[info[1].Split('/').Length - 1]}"; path = $"./{info[1].Split('/')[info[1].Split('/').Length - 1]}";
//Console.WriteLine("Downloading: " + path + " [" + info[1] + "]");
await ServerCom.DownloadFileAsync(info[1], path); await ServerCom.DownloadFileAsync(info[1], path);
if (info[0] == "Command" || info[0] == "Event") if (info[0] == "Command" || info[0] == "Event")
if (info[0] == "Event") if (info[0] == "Event")
Config.PluginConfig.InstalledPlugins.Add(new(name, PluginType.Event)); Config.PluginConfig.InstalledPlugins.Add(new(name, PluginType.Event));
else if (info[0] == "Command") Config.PluginConfig.InstalledPlugins.Add(new(name, PluginType.Command)); else if (info[0] == "Command")
Config.PluginConfig.InstalledPlugins.Add(new(name, PluginType.Command));
Console.WriteLine("\n"); Console.WriteLine("\n");
@@ -146,37 +146,39 @@ public class ConsoleCommandsHandler
{ {
Console.WriteLine($"Downloading requirements for plugin : {name}"); Console.WriteLine($"Downloading requirements for plugin : {name}");
var lines = await ServerCom.ReadTextFromFile(info[2]); var lines = await ServerCom.ReadTextFromURL(info[2]);
foreach (var line in lines) foreach (var line in lines)
{ {
if (!(line.Length > 0 && line.Contains(","))) continue; if (!(line.Length > 0 && line.Contains(",")))
continue;
var split = line.Split(','); var split = line.Split(',');
Console.WriteLine($"\nDownloading item: {split[1]}"); Console.WriteLine($"\nDownloading item: {split[1]}");
await ServerCom.DownloadFileAsync(split[0], "./" + split[1]); await ServerCom.DownloadFileAsync(split[0], "./" + split[1]);
Console.WriteLine(); Console.WriteLine();
if (split[0].EndsWith(".zip")) if (split[0].EndsWith(".zip") || split[0].EndsWith(".pak") || split[0].EndsWith(".pkg"))
{ {
Console.WriteLine($"Extracting {split[1]}"); Console.WriteLine($"Extracting {split[1]}");
var proc = 0d; var proc = 0f;
var isExtracting = true; var isExtracting = true;
var bar = new Console_Utilities.ProgressBar { Max = 100, Color = ConsoleColor.Green }; var bar = new Console_Utilities.ProgressBar { Max = 100f, Color = ConsoleColor.Green };
IProgress<float> extractProgress = new Progress<float>(value => { proc = value; }); IProgress<float> extractProgress = new Progress<float>(value => { proc = value; });
new Thread(new Task(() => new Thread(new Task(() =>
{ {
while (isExtracting) while (isExtracting)
{ {
bar.Update((int)proc); bar.Update(proc);
if (proc >= 99.9f) break; if (proc >= 99.9f)
isExtracting = false;
Thread.Sleep(500); Thread.Sleep(500);
} }
} }
).Start ).Start
).Start(); ).Start();
await Functions.ExtractArchive("./" + split[1], "./", extractProgress); await Functions.ExtractArchive("./" + split[1], "./", extractProgress, UnzipProgressType.PercentageFromTotalSize);
bar.Update(100); bar.Update(100f);
isExtracting = false; isExtracting = false;
await Task.Delay(1000); await Task.Delay(1000);
bar.Update(100); bar.Update(100);
@@ -191,19 +193,22 @@ public class ConsoleCommandsHandler
); );
AddCommand("value", "read value from VariableStack", "value [key]",args => AddCommand("value", "read value from VariableStack", "value [key]", args =>
{ {
if (args.Length != 2) return; if (args.Length != 2)
if (!Config.ContainsKey(args[1])) return; return;
if (!Config.ContainsKey(args[1]))
return;
var data = Config.GetValue<string>(args[1]); var data = Config.GetValue<string>(args[1]);
Console.WriteLine($"{args[1]} => {data}"); Console.WriteLine($"{args[1]} => {data}");
} }
); );
AddCommand("add", "add variable to the system variables","add [key] [value] [isReadOnly=true/false]", args => AddCommand("add", "add variable to the system variables", "add [key] [value] [isReadOnly=true/false]", args =>
{ {
if (args.Length < 4) return; if (args.Length < 4)
return;
var key = args[1]; var key = args[1];
var value = args[2]; var value = args[2];
var isReadOnly = args[3].Equals("true", StringComparison.CurrentCultureIgnoreCase); var isReadOnly = args[3].Equals("true", StringComparison.CurrentCultureIgnoreCase);
@@ -222,30 +227,21 @@ public class ConsoleCommandsHandler
AddCommand("remv", "remove variable from system variables", "remv [key]", args => AddCommand("remv", "remove variable from system variables", "remv [key]", args =>
{ {
if (args.Length < 2) return; if (args.Length < 2)
return;
Config.RemoveKey(args[1]); Config.RemoveKey(args[1]);
} }
); );
AddCommand("vars", "Display all variables", () =>
{
var d = Config.GetAllVariables();
var data = new List<string[]>();
data.Add(new[] { "-", "-" });
data.Add(new[] { "Key", "Value" });
data.Add(new[] { "-", "-" });
foreach (var kvp in d) data.Add(new[] { kvp.Key, kvp.Value.ToString()! });
data.Add(new[] { "-", "-" });
Console_Utilities.FormatAndAlignTable(data);
}
);
AddCommand("sd", "Shuts down the discord bot", async () => AddCommand("sd", "Shuts down the discord bot", async () =>
{ {
if (client is null) return; if (client is null)
return;
await client.StopAsync(); await client.StopAsync();
await client.DisposeAsync(); await client.DisposeAsync();
Config.SaveConfig(); Config.SaveConfig();
Console.WriteLine("Bot is closing in 2 seconds ! Please wait to save data !");
await Task.Delay(2000);
Environment.Exit(0); Environment.Exit(0);
} }
); );
@@ -255,13 +251,7 @@ public class ConsoleCommandsHandler
public static void AddCommand(string command, string description, string usage, Action<string[]> action) public static void AddCommand(string command, string description, string usage, Action<string[]> action)
{ {
commandList.Add(new ConsoleCommand commandList.Add(new ConsoleCommand { CommandName = command, Description = description, Action = action, Usage = usage });
{
CommandName = command,
Description = description,
Action = action,
Usage = usage
});
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
Console_Utilities.WriteColorText($"Command &r{command} &cadded to the list of commands"); Console_Utilities.WriteColorText($"Command &r{command} &cadded to the list of commands");
} }
@@ -295,7 +285,8 @@ public class ConsoleCommandsHandler
if (removeCommandExecution) if (removeCommandExecution)
{ {
Console.SetCursorPosition(0, Console.CursorTop - 1); Console.SetCursorPosition(0, Console.CursorTop - 1);
for (int i = 0; i < command.Length; i++) Console.Write(" "); for (int i = 0; i < command.Length + 30; i++)
Console.Write(" ");
Console.SetCursorPosition(0, Console.CursorTop); Console.SetCursorPosition(0, Console.CursorTop);
} }

View File

@@ -85,10 +85,21 @@ public class PluginLoader
private void OnEventLoaded(LoaderArgs e) private void OnEventLoaded(LoaderArgs e)
{ {
if (e.IsLoaded) ((DBEvent)e.Plugin!).Start(_client); try
{
if (e.IsLoaded)
((DBEvent)e.Plugin!).Start(_client);
onEVELoad?.Invoke(((DBEvent)e.Plugin!).name, e.TypeName!, e.IsLoaded, e.Exception); onEVELoad?.Invoke(((DBEvent)e.Plugin!).name, e.TypeName!, e.IsLoaded, e.Exception);
} }
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.WriteLine("Plugin: " + e.PluginName);
Console.WriteLine("Type: " + e.TypeName);
Console.WriteLine("IsLoaded: " + e.IsLoaded);
}
}
private void OnCommandLoaded(LoaderArgs e) private void OnCommandLoaded(LoaderArgs e)
{ {

View File

@@ -18,21 +18,19 @@ namespace PluginManager.Online.Helpers
/// <param name="progress">The <see cref="IProgress{T}"/> that is used to track the download progress</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> /// <param name="cancellation">The cancellation token</param>
/// <returns></returns> /// <returns></returns>
internal static async Task DownloadFileAsync(this HttpClient client, string url, Stream destination, internal static async Task DownloadFileAsync(this HttpClient client, string url, Stream destination, IProgress<float>? progress = null, IProgress<long>? downloadedBytes = null, int bufferSize = 81920, CancellationToken cancellation = default)
IProgress<float>? progress = null, IProgress<long>? downloadedBytes = null, CancellationToken cancellation = default)
{ {
using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)) using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellation))
{ {
var contentLength = response.Content.Headers.ContentLength; var contentLength = response.Content.Headers.ContentLength;
using (var download = await response.Content.ReadAsStreamAsync()) using (var download = await response.Content.ReadAsStreamAsync(cancellation))
{ {
// Ignore progress reporting when no progress reporter was // Ignore progress reporting when no progress reporter was
// passed or when the content length is unknown // passed or when the content length is unknown
if (progress == null || !contentLength.HasValue) if (progress == null || !contentLength.HasValue)
{ {
await download.CopyToAsync(destination); await download.CopyToAsync(destination, cancellation);
return; return;
} }
@@ -41,9 +39,11 @@ namespace PluginManager.Online.Helpers
{ {
progress.Report((float)totalBytes / contentLength.Value * 100); progress.Report((float)totalBytes / contentLength.Value * 100);
downloadedBytes?.Report(totalBytes); downloadedBytes?.Report(totalBytes);
}); }
);
// Use extension method to report progress while downloading // Use extension method to report progress while downloading
await download.CopyToOtherStreamAsync(destination, 81920, relativeProgress, cancellation); await download.CopyToOtherStreamAsync(destination, bufferSize, relativeProgress, cancellation);
progress.Report(1); progress.Report(1);
} }
} }
@@ -57,10 +57,8 @@ namespace PluginManager.Online.Helpers
/// <returns></returns> /// <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();
{ return await client.GetStringAsync(url, cancellation);
return await client.GetStringAsync(url);
}
} }

View File

@@ -30,7 +30,7 @@ public class PluginsManager
{ {
try try
{ {
var list = await ServerCom.ReadTextFromFile(PluginsLink); var list = await ServerCom.ReadTextFromURL(PluginsLink);
var lines = list.ToArray(); var lines = list.ToArray();
var data = new List<string[]>(); var data = new List<string[]>();
@@ -43,7 +43,8 @@ public class PluginsManager
data.Add(new[] { "-", "-", "-", "-", "-" }); data.Add(new[] { "-", "-", "-", "-", "-" });
for (var i = 0; i < len; i++) for (var i = 0; i < len; i++)
{ {
if (lines[i].Length <= 2) continue; if (lines[i].Length <= 2)
continue;
var content = lines[i].Split(','); var content = lines[i].Split(',');
var display = new string[titles.Length]; var display = new string[titles.Length];
if (op == OperatingSystem.WINDOWS) if (op == OperatingSystem.WINDOWS)
@@ -54,7 +55,7 @@ public class PluginsManager
display[1] = content[1]; display[1] = content[1];
display[2] = content[2]; display[2] = content[2];
if (content.Length == 6 && (content[5] != null || content[5].Length > 2)) if (content.Length == 6 && (content[5] != null || content[5].Length > 2))
display[3] = ((await ServerCom.ReadTextFromFile(content[5])).Count + 1).ToString(); display[3] = ((await ServerCom.ReadTextFromURL(content[5])).Count + 1).ToString();
else else
display[3] = "1"; display[3] = "1";
@@ -72,7 +73,8 @@ public class PluginsManager
display[0] = content[0]; display[0] = content[0];
display[1] = content[1]; display[1] = content[1];
display[2] = content[2]; display[2] = content[2];
if (content.Length == 6 && (content[5] != null || content[5].Length > 2)) display[3] = ((await ServerCom.ReadTextFromFile(content[5])).Count + 1).ToString(); if (content.Length == 6 && (content[5] != null || content[5].Length > 2))
display[3] = ((await ServerCom.ReadTextFromURL(content[5])).Count + 1).ToString();
if (Config.PluginConfig.Contains(content[0]) || Config.PluginConfig.Contains(content[0])) if (Config.PluginConfig.Contains(content[0]) || Config.PluginConfig.Contains(content[0]))
display[4] = "✓"; display[4] = "✓";
else else
@@ -88,7 +90,7 @@ public class PluginsManager
} }
catch (Exception exception) catch (Exception exception)
{ {
Console.WriteLine("Failed to execute command: listlang\nReason: " + exception.Message); Console.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
Functions.WriteErrFile(exception.ToString()); Functions.WriteErrFile(exception.ToString());
} }
} }
@@ -102,7 +104,7 @@ public class PluginsManager
{ {
try try
{ {
var list = await ServerCom.ReadTextFromFile(PluginsLink); var list = await ServerCom.ReadTextFromURL(PluginsLink);
var lines = list.ToArray(); var lines = list.ToArray();
var len = lines.Length; var len = lines.Length;
for (var i = 0; i < len; i++) for (var i = 0; i < len; i++)
@@ -110,8 +112,10 @@ public class PluginsManager
var contents = lines[i].Split(','); var contents = lines[i].Split(',');
if (contents[0] == name) if (contents[0] == name)
{ {
if (contents.Length == 6) return new[] { contents[2], contents[3], contents[5] }; if (contents.Length == 6)
if (contents.Length == 5) return new[] { contents[2], contents[3], string.Empty }; return new[] { contents[2], contents[3], contents[5] };
if (contents.Length == 5)
return new[] { contents[2], contents[3], string.Empty };
throw new Exception("Failed to download plugin. Invalid Argument Length"); throw new Exception("Failed to download plugin. Invalid Argument Length");
} }
} }

View File

@@ -9,15 +9,14 @@ using PluginManager.Others;
namespace PluginManager.Online namespace PluginManager.Online
{ {
public class ServerCom public static class ServerCom
{ {
/// <summary> /// <summary>
/// Read all lines from a file async /// Read all lines from a file async
/// </summary> /// </summary>
/// <param name="link">The link of the file</param> /// <param name="link">The link of the file</param>
/// <returns></returns> /// <returns></returns>
public static async Task<List<string>> ReadTextFromFile(string link) public static async Task<List<string>> ReadTextFromURL(string link)
{ {
string response = await OnlineFunctions.DownloadStringAsync(link); string response = await OnlineFunctions.DownloadStringAsync(link);
string[] lines = response.Split('\n'); string[] lines = response.Split('\n');
@@ -53,14 +52,11 @@ namespace PluginManager.Online
public static async Task DownloadFileAsync(string URL, string location) public static async Task DownloadFileAsync(string URL, string location)
{ {
bool isDownloading = true; bool isDownloading = true;
int c_progress = 0; float c_progress = 0;
Console_Utilities.ProgressBar pbar = new Console_Utilities.ProgressBar { Max = 100, NoColor = true }; Console_Utilities.ProgressBar pbar = new Console_Utilities.ProgressBar { Max = 100f, NoColor = true };
IProgress<float> progress = new Progress<float>(percent => IProgress<float> progress = new Progress<float>(percent => { c_progress = percent; });
{
c_progress = (int)percent;
});
Task updateProgressBarTask = new Task(() => Task updateProgressBarTask = new Task(() =>
@@ -68,7 +64,8 @@ namespace PluginManager.Online
while (isDownloading) while (isDownloading)
{ {
pbar.Update(c_progress); pbar.Update(c_progress);
if (c_progress == 100) break; if (c_progress == 100f)
break;
Thread.Sleep(500); Thread.Sleep(500);
} }
} }
@@ -78,8 +75,8 @@ namespace PluginManager.Online
await DownloadFileAsync(URL, location, progress); await DownloadFileAsync(URL, location, progress);
c_progress = 100; c_progress = pbar.Max;
pbar.Update(100); pbar.Update(100f);
isDownloading = false; isDownloading = false;
} }
} }

View File

@@ -1,21 +1,43 @@
using System; using Discord;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace PluginManager.Others namespace PluginManager.Others
{ {
public class Console_Utilities public static class Console_Utilities
{ {
public static void Initialize()
{
if (!Config.ContainsKey("TableVariables"))
Config.AddValueToVariables("TableVariables", new Dictionary<string, string> { { "DefaultSpace", "3" } }, false);
if (!Config.ContainsKey("ColorDataBase"))
Config.AddValueToVariables("ColorDataBase", new Dictionary<char, ConsoleColor>()
{
{ 'g', ConsoleColor.Green },
{ 'b', ConsoleColor.Blue },
{ 'r', ConsoleColor.Red },
{ 'm', ConsoleColor.Magenta },
{ 'y', ConsoleColor.Yellow },
}, false
);
if (!Config.ContainsKey("ColorPrefix"))
Config.AddValueToVariables("ColorPrefix", '&', false);
}
/// <summary> /// <summary>
/// Progress bar object /// Progress bar object
/// </summary> /// </summary>
public class ProgressBar public class ProgressBar
{ {
public int Max { get; init; } public float Max { get; init; }
public ConsoleColor Color { get; init; } public ConsoleColor Color { get; init; }
public bool NoColor { get; init; } public bool NoColor { get; init; }
public void Update(int progress, double speed = -1, string? unit = null) public void Update(float progress, double speed = -1, string? unit = null)
{ {
Console.CursorLeft = 0; Console.CursorLeft = 0;
Console.Write("["); Console.Write("[");
@@ -28,44 +50,43 @@ namespace PluginManager.Others
for (int i = 0; i < onechunk * progress; i++) for (int i = 0; i < onechunk * progress; i++)
{ {
if (NoColor) Console.BackgroundColor = NoColor ? ConsoleColor.Black : this.Color;
Console.BackgroundColor = ConsoleColor.Black; //this.Color
else
Console.BackgroundColor = this.Color;
Console.CursorLeft = position++; Console.CursorLeft = position++;
Console.Write("#"); Console.Write("#");
} }
for (int i = position; i <= 31; i++) for (int i = position; i <= 31; i++)
{ {
if (NoColor) Console.BackgroundColor = NoColor ? ConsoleColor.Black : ConsoleColor.DarkGray;
Console.BackgroundColor = ConsoleColor.Black; // background of empty bar
else
Console.BackgroundColor = ConsoleColor.DarkGray;
Console.CursorLeft = position++; Console.CursorLeft = position++;
Console.Write(" "); Console.Write(" ");
} }
Console.CursorLeft = 35; Console.CursorLeft = 35;
Console.BackgroundColor = ConsoleColor.Black; Console.BackgroundColor = ConsoleColor.Black;
if (speed == -1 || unit == null) if (speed is -1 || unit == null)
{ {
if (progress == Max) if (progress.CanAproximateTo(Max))
Console.Write(progress.ToString() + " % ✓"); Console.Write(progress + " % ✓");
else Console.Write(progress.ToString() + " % "); else
Console.Write(MathF.Round(progress, 2) + " % ");
} }
else else
Console.Write(progress.ToString() + $"{speed} {unit}/s "); Console.Write(progress + $"{speed} {unit}/s ");
}
}
}
} private static bool CanAproximateTo(this float f, float y) => (MathF.Abs(f - y) < 0.000001);
/// <summary> /// <summary>
/// A way to create a table based on input data /// A way to create a table based on input data
/// </summary> /// </summary>
/// <param name="data">The List of arrays of strings that represent the rows.</param> /// <param name="data">The List of arrays of strings that represent the rows.</param>
public static void FormatAndAlignTable(List<string[]> data) public static void FormatAndAlignTable(List<string[]> data, TableFormat format = TableFormat.CENTER_EACH_COLUMN_BASED)
{
if (format == TableFormat.CENTER_EACH_COLUMN_BASED)
{ {
char tableLine = '-'; char tableLine = '-';
char tableCross = '+'; char tableCross = '+';
@@ -73,17 +94,17 @@ namespace PluginManager.Others
int[] len = new int[data[0].Length]; int[] len = new int[data[0].Length];
foreach (var line in data) foreach (var line in data)
{
for (int i = 0; i < line.Length; i++) for (int i = 0; i < line.Length; i++)
if (line[i].Length > len[i]) if (line[i].Length > len[i])
len[i] = line[i].Length; len[i] = line[i].Length;
}
foreach (string[] row in data) foreach (string[] row in data)
{ {
if (row[0][0] == tableLine) Console.Write(tableCross); if (row[0][0] == tableLine)
else Console.Write(tableWall); Console.Write(tableCross);
else
Console.Write(tableWall);
for (int l = 0; l < row.Length; l++) for (int l = 0; l < row.Length; l++)
{ {
if (row[l][0] == tableLine) if (row[l][0] == tableLine)
@@ -99,7 +120,6 @@ namespace PluginManager.Others
} }
else else
{ {
int lenHalf = row[l].Length / 2; int lenHalf = row[l].Length / 2;
for (int i = 0; i < ((len[l] + 4) / 2 - lenHalf); ++i) for (int i = 0; i < ((len[l] + 4) / 2 - lenHalf); ++i)
Console.Write(" "); Console.Write(" ");
@@ -110,47 +130,132 @@ namespace PluginManager.Others
Console.Write(" "); Console.Write(" ");
} }
if (row[l][0] == tableLine) Console.Write(tableCross); Console.Write(row[l][0] == tableLine ? tableCross : tableWall);
else Console.Write(tableWall);
} }
Console.WriteLine(); //end line Console.WriteLine(); //end line
}
} }
public static void WriteColorText(string text, bool appendNewLine = true) return;
}
if (format == TableFormat.CENTER_OVERALL_LENGTH)
{ {
int maxLen = 0;
foreach (string[] row in data)
foreach (string s in row)
if (s.Length > maxLen)
maxLen = s.Length;
string[] words = text.Split(' '); int div = (maxLen + 4) / 2;
ConsoleColor fg = Console.ForegroundColor;
Dictionary<string, ConsoleColor> colors = new Dictionary<string, ConsoleColor>() foreach (string[] row in data)
{ {
{ "&g", ConsoleColor.Green }, Console.Write("\t");
{ "&b", ConsoleColor.Blue }, if (row[0] == "-")
{ "&r", ConsoleColor.Red }, Console.Write("+");
{ "&m", ConsoleColor.Magenta }, else
{ "&y", ConsoleColor.Yellow }, Console.Write("|");
{ "&c", fg }
}; foreach (string s in row)
foreach (string word in words)
{ {
if (word.Length >= 2) if (s == "-")
{ {
string prefix = word.Substring(0, 2); for (int i = 0; i < maxLen + 4; ++i)
if (colors.ContainsKey(prefix)) Console.Write("-");
Console.ForegroundColor = colors[prefix]; }
else if (s.Length == maxLen)
{
Console.Write(" ");
Console.Write(s);
Console.Write(" ");
}
else
{
int lenHalf = s.Length / 2;
for (int i = 0; i < div - lenHalf; ++i)
Console.Write(" ");
Console.Write(s);
for (int i = div + lenHalf + 1; i < maxLen + 4; ++i)
Console.Write(" ");
if (s.Length % 2 == 0)
Console.Write(" ");
} }
string m = word; if (s == "-")
foreach (var key in colors.Keys) { m = m.Replace(key, ""); } Console.Write("+");
else
Console.Write(m + " "); Console.Write("|");
}
if (appendNewLine)
Console.Write('\n');
Console.ForegroundColor = fg;
} }
Console.WriteLine(); //end line
}
return;
}
if (format == TableFormat.DEFAULT)
{
int[] widths = new int[data[0].Length];
int space_between_columns = int.Parse(Config.GetValue<Dictionary<string, string>>("TableVariables")?["DefaultSpace"]!);
for (int i = 0; i < data.Count; i++)
{
for (int j = 0; j < data[i].Length; j++)
{
if (data[i][j].Length > widths[j])
widths[j] = data[i][j].Length;
}
}
for (int i = 0; i < data.Count; i++)
{
for (int j = 0; j < data[i].Length; j++)
{
if (data[i][j] == "-")
data[i][j] = " ";
Console.Write(data[i][j]);
for (int 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)
{
ConsoleColor initialForeGround = Console.ForegroundColor;
char[] input = text.ToCharArray();
for (int i = 0; i < input.Length; i++)
{
if (input[i] == Config.GetValue<char>("ColorPrefix"))
{
if (i + 1 < input.Length)
{
if (Config.GetValue<Dictionary<char, ConsoleColor>>("ColorDataBase")!.ContainsKey(input[i + 1]))
{
Console.ForegroundColor = Config.GetValue<Dictionary<char, ConsoleColor>>("ColorDataBase")![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();
}
} }
} }

View File

@@ -27,3 +27,7 @@ public enum OutputLogLevel { NONE, INFO, WARNING, ERROR, CRITICAL }
/// Plugin Type /// Plugin Type
/// </summary> /// </summary>
public enum PluginType { Command, Event, Unknown } public enum PluginType { Command, Event, Unknown }
public enum UnzipProgressType { PercentageFromNumberOfFiles, PercentageFromTotalSize }
public enum TableFormat { CENTER_EACH_COLUMN_BASED, CENTER_OVERALL_LENGTH, DEFAULT }

View File

@@ -4,6 +4,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Cryptography;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Items; using PluginManager.Items;
using System.Threading; using System.Threading;
@@ -37,6 +38,11 @@ namespace PluginManager.Others
/// </summary> /// </summary>
public static readonly string pakFolder = @"./Data/Resources/PAK/"; public static readonly string pakFolder = @"./Data/Resources/PAK/";
/// <summary>
/// Beta testing folder
/// </summary>
public static readonly string betaFolder = @"./Data/BetaTest/";
/// <summary> /// <summary>
/// Read data from a file that is inside an archive (ZIP format) /// Read data from a file that is inside an archive (ZIP format)
@@ -44,31 +50,15 @@ namespace PluginManager.Others
/// <param name="FileName">The file name that is inside the archive or its full path</param> /// <param name="FileName">The file name that is inside the archive or its full path</param>
/// <param name="archFile">The archive location from the PAKs folder</param> /// <param name="archFile">The archive location from the PAKs folder</param>
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns> /// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
public static async Task<Stream?> ReadFromPakAsync(string FileName, string archFile) public static Stream? ReadFromPakAsync(string FileName, string archFile)
{ {
archFile = pakFolder + archFile; archFile = pakFolder + archFile;
Directory.CreateDirectory(pakFolder); Directory.CreateDirectory(pakFolder);
if (!File.Exists(archFile)) throw new FileNotFoundException("Failed to load file !"); if (!File.Exists(archFile)) throw new FileNotFoundException("Failed to load file !");
Stream? textValue = null; using ZipArchive archive = ZipFile.OpenRead(archFile);
var fs = new FileStream(archFile, FileMode.Open); ZipArchiveEntry? entry = archive.GetEntry(FileName);
var zip = new ZipArchive(fs, ZipArchiveMode.Read); return entry?.Open();
foreach (var entry in zip.Entries)
{
if (entry.Name == FileName || entry.FullName == FileName)
{
Stream s = entry.Open();
StreamReader reader = new StreamReader(s);
textValue = reader.BaseStream;
textValue.Position = 0;
reader.Close();
s.Close();
fs.Close();
break;
}
}
return textValue;
} }
/// <summary> /// <summary>
@@ -77,7 +67,7 @@ namespace PluginManager.Others
/// <param name="LogMessage">The message to be wrote</param> /// <param name="LogMessage">The message to be wrote</param>
public static void WriteLogFile(string LogMessage) public static void WriteLogFile(string LogMessage)
{ {
string logsPath = logFolder + "Log.txt"; string logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
if (!Directory.Exists(logFolder)) Directory.CreateDirectory(logFolder); if (!Directory.Exists(logFolder)) Directory.CreateDirectory(logFolder);
File.AppendAllText(logsPath, LogMessage + " \n"); File.AppendAllText(logsPath, LogMessage + " \n");
} }
@@ -88,7 +78,7 @@ namespace PluginManager.Others
/// <param name="ErrMessage">The message to be wrote</param> /// <param name="ErrMessage">The message to be wrote</param>
public static void WriteErrFile(string ErrMessage) public static void WriteErrFile(string ErrMessage)
{ {
string errPath = errFolder + "Error.txt"; string errPath = errFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
if (!Directory.Exists(errFolder)) Directory.CreateDirectory(errFolder); if (!Directory.Exists(errFolder)) Directory.CreateDirectory(errFolder);
File.AppendAllText(errPath, ErrMessage + " \n"); File.AppendAllText(errPath, ErrMessage + " \n");
} }
@@ -169,13 +159,17 @@ namespace PluginManager.Others
/// </summary> /// </summary>
/// <param name="zip">The zip location</param> /// <param name="zip">The zip location</param>
/// <param name="folder">The target location</param> /// <param name="folder">The target location</param>
/// <param name="progress">The progress that is updated as a file is processed</param>
/// <param name="type">The type of progress</param>
/// <returns></returns> /// <returns></returns>
public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress) public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress, UnzipProgressType type)
{ {
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder); if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
using (ZipArchive archive = ZipFile.OpenRead(zip)) using (ZipArchive archive = ZipFile.OpenRead(zip))
{
if (type == UnzipProgressType.PercentageFromNumberOfFiles)
{ {
int totalZIPFiles = archive.Entries.Count(); int totalZIPFiles = archive.Entries.Count();
int currentZIPFile = 0; int currentZIPFile = 0;
@@ -189,8 +183,9 @@ namespace PluginManager.Others
{ {
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true); entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
} }
catch catch (Exception ex)
{ {
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
} }
currentZIPFile++; currentZIPFile++;
@@ -198,6 +193,37 @@ namespace PluginManager.Others
progress.Report((float)currentZIPFile / totalZIPFiles * 100); progress.Report((float)currentZIPFile / totalZIPFiles * 100);
} }
} }
else if (type == UnzipProgressType.PercentageFromTotalSize)
{
ulong zipSize = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
zipSize += (ulong)entry.CompressedLength;
ulong currentSize = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith("/"))
{
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
continue;
}
try
{
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
currentSize += (ulong)entry.CompressedLength;
}
catch (Exception ex)
{
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
}
await Task.Delay(10);
progress.Report((float)currentSize / zipSize * 100);
}
}
}
} }
@@ -303,5 +329,15 @@ namespace PluginManager.Others
var data = jsonObject.RootElement.TryGetProperty(codeName, out element); var data = jsonObject.RootElement.TryGetProperty(codeName, out element);
return data; return data;
} }
public static string CreateMD5(string input)
{
using (MD5 md5 = MD5.Create())
{
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes);
}
}
} }
} }

View File

@@ -5,7 +5,6 @@ This project is based on:
- [.NET 6 (C#)](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) - [.NET 6 (C#)](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
- [Discord.Net](https://github.com/discord-net/Discord.Net) - [Discord.Net](https://github.com/discord-net/Discord.Net)
- [Avalonia UI](https://avaloniaui.net/) for `DiscordBotUI` extension
## Plugins ## Plugins

70
TODO
View File

@@ -1,70 +0,0 @@
Discord Bot:
✔ Create bootloader
✔ Create commands handler
✔ Create bot launcher
✔ Enable startup commands
✔ Enable console input
☐ Create self update feature
Plugin Manager:
Define plugin interface:
✔ DBCommand
✔ DBPlugin
Functions.cs:
✔ Read from file
✔ Read from archive (PAK)
✔ Write Logs & Errors
✔ Manipulate settings (files) and strings
✔ Stream copy async
Console Utilities:
✔ Progress bar
✔ Create table
✔ Write to console with colors
Discord Permissions:
✔ Check if user has permission
✔ Check if user is owner
Discord Plugins:
✔ Create loader for commands
✔ Create loader for events
☐ Improve memory efficiency
☐ Improve performance
☐ Improve stability
Language System:
✔ Create language system
✔ Load language files
Server Communication:
✔ Plugin Download system
✔ Language Download system
☐ Move to a new server
☐ Create plugin versioning system
☐ Create plugin update system
Plugins:
Events:
✔ Leveling system
Utilities:
✔ Random number generator
✔ Flip a coin
✔ Poll
Commands:
✔ Leveling system
☐ Music Commands @started
// Windows only version
// Download as a patch but replaces old DiscordBot executable with a new one
// Adds new dll to support windows forms
// Must act the same as the old version
☐ Create version of discord bot with windows form
☐ Download system and patch will result in a windows only based version of bot
☐ Possibility to reverse patch to get back to original version

View File

@@ -1 +0,0 @@
0