21 Commits

Author SHA1 Message Date
68a83b052a Updater added 2022-08-28 12:59:41 +03:00
d689eee7fa 2022-08-26 10:42:15 +03:00
f6442af30c patch: listplugs, plugin version system and progress bar 2022-08-25 15:15:47 +03:00
b98f57fcf8 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-08-24 21:34:13 +03:00
77aad985fa Added a new ProgressBar type 2022-08-24 21:34:06 +03:00
Wizzy69
f8ebf76f92 Delete .idea/.idea.SethDiscordBot/.idea directory 2022-08-20 20:52:21 +03:00
6da9828e5c improved save method 2022-08-20 17:44:19 +03:00
3ba45790e7 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-08-17 20:31:55 +03:00
e440e97948 2022-08-17 20:31:52 +03:00
Wizzy69
938c73c810 Delete DiscordBotConsoleLauncher directory 2022-08-17 20:31:28 +03:00
a8520c8c96 fixed some bugs 2022-08-17 20:23:06 +03:00
debdc58646 The ability to remove a plugin has been added 2022-08-17 20:12:31 +03:00
8b36c086ef New Command added & Leveling System update 2022-08-17 14:19:46 +03:00
1f5e5d0611 patch 2022-08-17 10:09:02 +03:00
bbc1c601c9 Patching system build 2 2022-08-17 09:58:54 +03:00
5ab3195956 2022-08-16 23:08:56 +03:00
1f1983480a 2022-08-16 16:14:25 +03:00
2fcd86cf12 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-08-16 16:12:38 +03:00
2c83d00c00 2022-08-16 16:12:14 +03:00
Wizzy69
ccac0ca6d0 Update README.md 2022-07-26 15:15:13 +03:00
4c9c7410f0 2022-07-17 19:31:59 +03:00
58 changed files with 1846 additions and 301 deletions

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoGeneratedRunConfigurationManager">
<projectFile>DiscordBot/DiscordBot.csproj</projectFile>
<projectFile pubXmlPath="DiscordBot/Properties/PublishProfiles/WindowsBuild.pubxml">DiscordBot/DiscordBot.csproj</projectFile>
</component>
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="ab173b07-aba1-4bb8-94c1-ae9846bbdb0a" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/Roles/AddRole.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Roles/Internals/RoleManagement.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Roles/Roles.csproj" afterDir="false" />
<change beforePath="$PROJECT_DIR$/BUILDS/net6.0/CMD_Utils.dll" beforeDir="false" afterPath="$PROJECT_DIR$/BUILDS/net6.0/CMD_Utils.dll" afterDir="false" />
<change beforePath="$PROJECT_DIR$/BUILDS/net6.0/Music Commands.dll" beforeDir="false" afterPath="$PROJECT_DIR$/BUILDS/net6.0/Music Commands.dll" afterDir="false" />
<change beforePath="$PROJECT_DIR$/BUILDS/net6.0/PluginManager.dll" beforeDir="false" afterPath="$PROJECT_DIR$/BUILDS/net6.0/PluginManager.dll" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CMD_LevelingSystem/Level.cs" beforeDir="false" afterPath="$PROJECT_DIR$/CMD_LevelingSystem/Level.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CMD_Utils/Echo.cs" beforeDir="false" afterPath="$PROJECT_DIR$/CMD_Utils/Echo.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CMD_Utils/FlipCoin.cs" beforeDir="false" afterPath="$PROJECT_DIR$/CMD_Utils/FlipCoin.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CMD_Utils/Poll.cs" beforeDir="false" afterPath="$PROJECT_DIR$/CMD_Utils/Poll.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CMD_Utils/Random.cs" beforeDir="false" afterPath="$PROJECT_DIR$/CMD_Utils/Random.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DiscordBot/Discord/Commands/Help.cs" beforeDir="false" afterPath="$PROJECT_DIR$/DiscordBot/Discord/Commands/Help.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DiscordBot/Discord/Commands/Restart.cs" beforeDir="false" afterPath="$PROJECT_DIR$/DiscordBot/Discord/Commands/Restart.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DiscordBot/Discord/Commands/Settings.cs" beforeDir="false" afterPath="$PROJECT_DIR$/DiscordBot/Discord/Commands/Settings.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DiscordBot/Discord/Core/Boot.cs" beforeDir="false" afterPath="$PROJECT_DIR$/DiscordBot/Discord/Core/Boot.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DiscordBot/Discord/Core/CommandHandler.cs" beforeDir="false" afterPath="$PROJECT_DIR$/DiscordBot/Discord/Core/CommandHandler.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DiscordBot/DiscordBot.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/DiscordBot/DiscordBot.csproj" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DiscordBot/Program.cs" beforeDir="false" afterPath="$PROJECT_DIR$/DiscordBot/Program.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/MusicCommands/Leave.cs" beforeDir="false" afterPath="$PROJECT_DIR$/MusicCommands/Leave.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/MusicCommands/MusicPlayer.cs" beforeDir="false" afterPath="$PROJECT_DIR$/MusicCommands/MusicPlayer.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/MusicCommands/Pause.cs" beforeDir="false" afterPath="$PROJECT_DIR$/MusicCommands/Pause.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/MusicCommands/Play.cs" beforeDir="false" afterPath="$PROJECT_DIR$/MusicCommands/Play.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/MusicCommands/Skip.cs" beforeDir="false" afterPath="$PROJECT_DIR$/MusicCommands/Skip.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/MusicCommands/queue.cs" beforeDir="false" afterPath="$PROJECT_DIR$/MusicCommands/queue.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/PluginManager/Config.cs" beforeDir="false" afterPath="$PROJECT_DIR$/PluginManager/Config.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/PluginManager/Interfaces/DBCommand.cs" beforeDir="false" afterPath="$PROJECT_DIR$/PluginManager/Interfaces/DBCommand.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/PluginManager/Items/Command.cs" beforeDir="false" afterPath="$PROJECT_DIR$/PluginManager/Items/Command.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/PluginManager/Items/ConsoleCommandsHandler.cs" beforeDir="false" afterPath="$PROJECT_DIR$/PluginManager/Items/ConsoleCommandsHandler.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/SethDiscordBot.sln" beforeDir="false" afterPath="$PROJECT_DIR$/SethDiscordBot.sln" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectId" id="2CUQteUHoNWL2Ok4DVEh1GfFaXk" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"WebServerToolWindowFactoryState": "false",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.pluginManager",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RunManager">
<configuration name="DiscordBot: WindowsBuild" type="DotNetMsBuildPublish" factoryName="Publish to IIS">
<riderPublish publish_profile="WindowsBuild.pubxml" pubxml_path="$PROJECT_DIR$/DiscordBot/Properties/PublishProfiles/WindowsBuild.pubxml" uuid_high="612037599008934041" uuid_low="-9069359786678974134" />
<method v="2" />
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="ab173b07-aba1-4bb8-94c1-ae9846bbdb0a" name="Changes" comment="" />
<created>1658854902538</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1658854902538</updated>
<workItem from="1658854908500" duration="1731000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="UnityCheckinConfiguration" checkUnsavedScenes="true" />
<component name="UnityUnitTestConfiguration" currentTestLauncher="NUnit" />
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
</component>
<component name="VcsManagerConfiguration">
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
</component>
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -11,6 +11,8 @@ internal class Level : DBCommand
{ {
public string Command => "level"; public string Command => "level";
public List<string> Aliases => new() { "lvl" };
public string Description => "Display tour current level"; public string Description => "Display tour current level";
public string Usage => "level"; public string Usage => "level";

View File

@@ -1,11 +1,14 @@
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using System.Collections.Generic;
internal class Echo : DBCommand internal class Echo : DBCommand
{ {
public string Command => "echo"; public string Command => "echo";
public List<string> Aliases => null;
public string Description => "Replay with the same message"; public string Description => "Replay with the same message";
public string Usage => "echo [message]"; public string Usage => "echo [message]";

View File

@@ -1,6 +1,7 @@
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using System.Collections.Generic;
namespace CMD_Utils; namespace CMD_Utils;
@@ -8,6 +9,8 @@ internal class FlipCoin : DBCommand
{ {
public string Command => "flip"; public string Command => "flip";
public List<string> Aliases => null;
public string Description => "Flip a coin"; public string Description => "Flip a coin";
public string Usage => "flip"; public string Usage => "flip";

View File

@@ -11,6 +11,8 @@ public class Poll : DBCommand
{ {
public string Command => "poll"; public string Command => "poll";
public List<string> Aliases => null;
public string Description => "Create a poll with options"; public string Description => "Create a poll with options";
public string Usage => "poll [This-is-question] [This-is-answer-1] [This-is-answer-2] ... "; public string Usage => "poll [This-is-question] [This-is-answer-1] [This-is-answer-2] ... ";

View File

@@ -1,4 +1,5 @@
using Discord.Commands; using System.Collections.Generic;
using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
@@ -6,6 +7,8 @@ public class Random : DBCommand
{ {
public string Command => "random"; public string Command => "random";
public List<string> Aliases => new() { "rnd" };
public string Description => "random number between number1 and number2"; public string Description => "random number between number1 and number2";
public string Usage => "random [number1] [number2]"; public string Usage => "random [number1] [number2]";

View File

@@ -1,4 +1,6 @@
using Discord; using System.Collections.Generic;
using System.Linq;
using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
@@ -17,15 +19,17 @@ internal class Help : DBCommand
/// </summary> /// </summary>
public string Command => "help"; public string Command => "help";
public List<string> Aliases => null;
/// <summary> /// <summary>
/// Command Description /// Command Description
/// </summary> /// </summary>
public string Description => "This command allows you to check all loadded commands"; public string Description => "This command allows you to check all loaded commands";
/// <summary> /// <summary>
/// Command usage /// Command usage
/// </summary> /// </summary>
public string Usage => "help"; public string Usage => "help <command>";
/// <summary> /// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel" />/> /// Check if the command can be used <inheritdoca DM <see cref="IChannel" />/>
@@ -57,10 +61,10 @@ internal class Help : DBCommand
foreach (var item in args) foreach (var item in args)
{ {
var e = GenerateHelpCommand(item); var e = GenerateHelpCommand(item);
if (e != null) if (e is null)
context.Channel.SendMessageAsync(embed: e.Build());
else
context.Channel.SendMessageAsync("Unknown Command " + item); context.Channel.SendMessageAsync("Unknown Command " + item);
else
context.Channel.SendMessageAsync(embed: e.Build());
} }
return; return;
@@ -74,10 +78,12 @@ internal class Help : DBCommand
foreach (var cmd in PluginLoader.Commands!) foreach (var cmd in PluginLoader.Commands!)
{ {
if (cmd.canUseDM) DMCommands += cmd.Command + " "; if (cmd.canUseDM)
DMCommands += cmd.Command + " ";
if (cmd.requireAdmin) if (cmd.requireAdmin)
adminCommands += cmd.Command + " "; adminCommands += cmd.Command + " ";
else if (cmd.canUseServer) normalCommands += cmd.Command + " "; if (cmd.canUseServer)
normalCommands += cmd.Command + " ";
} }
embedBuilder.AddField("Admin Commands", adminCommands); embedBuilder.AddField("Admin Commands", adminCommands);
@@ -89,11 +95,14 @@ internal class Help : DBCommand
private EmbedBuilder GenerateHelpCommand(string command) private EmbedBuilder GenerateHelpCommand(string command)
{ {
var embedBuilder = new EmbedBuilder(); var embedBuilder = new EmbedBuilder();
var cmd = PluginLoader.Commands.Find(p => p.Command == command); var cmd = PluginLoader.Commands!.Find(p => p.Command == command || (p.Aliases is not null && p.Aliases.Contains(command)));
if (cmd == null) return null; if (cmd == null) return null;
embedBuilder.AddField("Usage", cmd.Usage); embedBuilder.AddField("Usage", cmd.Usage);
embedBuilder.AddField("Description", cmd.Description); embedBuilder.AddField("Description", cmd.Description);
if (cmd.Aliases is null)
return embedBuilder;
embedBuilder.AddField("Alias", cmd.Aliases.Count == 0 ? "-" : string.Join(", ", cmd.Aliases));
return embedBuilder; return embedBuilder;
} }

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
@@ -17,6 +18,8 @@ internal class Restart : DBCommand
/// </summary> /// </summary>
public string Command => "restart"; public string Command => "restart";
public List<string> Aliases => null;
/// <summary> /// <summary>
/// Command Description /// Command Description
/// </summary> /// </summary>

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
@@ -14,6 +15,8 @@ internal class Settings : DBCommand
/// </summary> /// </summary>
public string Command => "set"; public string Command => "set";
public List<string> Aliases => null;
/// <summary> /// <summary>
/// Command Description /// Command Description
/// </summary> /// </summary>

View File

@@ -60,7 +60,9 @@ internal class Boot
/// <returns>Task</returns> /// <returns>Task</returns>
public async Task Awake() public async Task Awake()
{ {
client = new DiscordSocketClient(); DiscordSocketConfig config = new DiscordSocketConfig { AlwaysDownloadUsers = true };
client = new DiscordSocketClient(config);
service = new CommandService(); service = new CommandService();
CommonTasks(); CommonTasks();

View File

@@ -47,13 +47,16 @@ internal class CommandHandler
{ {
try try
{ {
if (Message as SocketUserMessage == null) return; if (Message as SocketUserMessage == null)
return;
var message = Message as SocketUserMessage; var message = Message as SocketUserMessage;
if (message == null) return; if (message == null)
return;
if (!message.Content.StartsWith(botPrefix)) return; if (!message.Content.StartsWith(botPrefix))
return;
var argPos = 0; var argPos = 0;
@@ -63,17 +66,14 @@ internal class CommandHandler
return; return;
} }
if (message.Author.IsBot) return; if (message.Author.IsBot)
return;
var context = new SocketCommandContext(client, message); var context = new SocketCommandContext(client, message);
await commandService.ExecuteAsync( await commandService.ExecuteAsync(context, argPos, null);
context,
argPos,
null
);
var plugin = PluginLoader.Commands!.Where(p => p.Command == message.Content.Split(' ')[0].Substring(botPrefix.Length)).FirstOrDefault(); var plugin = PluginLoader.Commands!.Where(p => p.Command == message.Content.Split(' ')[0].Substring(botPrefix.Length) || (p.Aliases is not null && p.Aliases.Contains(message.Content.Split(' ')[0].Substring(botPrefix.Length)))).FirstOrDefault();
if (plugin != null) if (plugin != null)

View File

@@ -8,15 +8,15 @@
<StartupObject /> <StartupObject />
<SignAssembly>False</SignAssembly> <SignAssembly>False</SignAssembly>
<IsPublishable>True</IsPublishable> <IsPublishable>True</IsPublishable>
<AssemblyVersion>1.0.0.1</AssemblyVersion> <AssemblyVersion>1.0.0.10</AssemblyVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>none</DebugType> <DebugType>none</DebugType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType> <DebugType>none</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,16 +1,17 @@
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.Net.Http;
using System.Reflection; using System.Reflection;
using System.Runtime.Loader;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket;
using Discord;
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;
@@ -21,6 +22,7 @@ public class Program
{ {
private static bool loadPluginsOnStartup; private static bool loadPluginsOnStartup;
private static bool listPluginsAtStartup; private static bool listPluginsAtStartup;
private static ConsoleCommandsHandler consoleCommandsHandler;
/// <summary> /// <summary>
/// The main entry point for the application. /// The main entry point for the application.
@@ -29,41 +31,74 @@ public class Program
[Obsolete] [Obsolete]
public static void Main(string[] args) public static void Main(string[] args)
{ {
Console.WriteLine("Loading resources ...");
Directory.CreateDirectory("./Data/Resources"); Directory.CreateDirectory("./Data/Resources");
Directory.CreateDirectory("./Data/Plugins/Commands"); Directory.CreateDirectory("./Data/Plugins/Commands");
Directory.CreateDirectory("./Data/Plugins/Events"); Directory.CreateDirectory("./Data/Plugins/Events");
PreLoadComponents().Wait(); PreLoadComponents().Wait();
do
if (!Config.ContainsKey("token") || Config.GetValue<string>("token") == null || Config.GetValue<string>("token")?.Length != 70)
{ {
Console.WriteLine("Please insert your token"); if (!Config.ContainsKey("ServerID"))
Console.Write("Token = "); {
var token = Console.ReadLine();
if (token?.Length == 59 || token?.Length == 70)
Config.AddValueToVariables("token", token, true);
else
Console.WriteLine("Invalid token");
Console.WriteLine("Please insert your prefix (max. 1 character long):");
Console.WriteLine("For a prefix longer then one character, the first character will be saved and the others will be ignored.\n No spaces or numbers allowed");
Console.Write("Prefix = ");
var prefix = Console.ReadLine()![0];
if (prefix == ' ' || char.IsDigit(prefix)) Console.WriteLine("Please enter the server ID: ");
return; Console_Utilities.WriteColorText("You can find it in the Server Settings at &r\"Widget\"&c section");
Config.AddValueToVariables("prefix", prefix.ToString(), false); Console.WriteLine("Example: 1234567890123456789");
}
if (!Config.ContainsKey("prefix") || Config.GetValue<string>("prefix") == default) Console.WriteLine("This is not required, but is recommended. If you refuse to provide the ID, just press enter.\nThe server id is required to make easier for the bot to interact with the server.\nRemember: this bot is for one server ONLY.");
{ Console.Write("User Input > ");
Console.WriteLine("Please insert your prefix (max. 1 character long):"); ConsoleKeyInfo key = Console.ReadKey();
Console.WriteLine("For a prefix longer then one character, the first character will be saved and the others will be ignored.\n No spaces or numbers allowed"); if (key.Key == ConsoleKey.Enter)
Console.Write("Prefix = "); Config.AddValueToVariables("ServerID", "null", false);
var prefix = Console.ReadLine()![0]; else
if (prefix == ' ') return; {
Config.AddValueToVariables("prefix", prefix.ToString(), false); string SID = key.KeyChar + Console.ReadLine();
} if (SID.Length != 18)
{
Console.Clear();
Console_Utilities.WriteColorText("&rYour server ID is not 18 characters long. Please try again. \n");
continue;
}
Config.AddValueToVariables("ServerID", SID, false);
}
}
if (!Config.ContainsKey("token") || Config.GetValue<string>("token") == null || (Config.GetValue<string>("token")?.Length != 70 && Config.GetValue<string>("token")?.Length != 59))
{
Console.WriteLine("Please insert your token");
Console.Write("Token = ");
var token = Console.ReadLine();
if (token?.Length == 59 || token?.Length == 70)
Config.AddValueToVariables("token", token, true);
else
{
Console.Clear();
Console_Utilities.WriteColorText("&rThe token length is invalid !");
continue;
}
}
if (!Config.ContainsKey("prefix") || Config.GetValue<string>("prefix") == null || Config.GetValue<string>("prefix")?.Length != 1)
{
Console.WriteLine("Please insert your prefix (max. 1 character long):");
Console.WriteLine("For a prefix longer then one character, the first character will be saved and the others will be ignored.\n No spaces, numbers, '/' or '\\' allowed");
Console.Write("Prefix = ");
var prefix = Console.ReadLine()![0];
if (prefix == ' ' || char.IsDigit(prefix) || prefix == '/' || prefix == '\\')
{
Console.Clear();
Console_Utilities.WriteColorText("&rThe prefix is invalid");
continue;
}
Config.AddValueToVariables("prefix", prefix.ToString(), false);
}
break;
} while (true);
HandleInput(args).Wait(); HandleInput(args).Wait();
} }
@@ -74,27 +109,27 @@ public class Program
/// <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 void NoGUI(Boot discordbooter) private static void NoGUI(Boot discordbooter)
{ {
var consoleCommandsHandler = new ConsoleCommandsHandler(discordbooter.client);
#if DEBUG
Console.WriteLine();
ConsoleCommandsHandler.ExecuteCommad("lp").Wait();
#else
if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp"); if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp");
if (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs"); if (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs");
#endif
Config.SaveConfig(); Config.SaveConfig(SaveType.NORMAL).Wait();
while (true) while (true)
{ {
Console.ForegroundColor = ConsoleColor.White;
var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd!
#if DEBUG #if DEBUG
Console_Utilities.WriteColorText("&rSethBot (&yDEBUG&r) &c> ", false); , false
var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd!, false) && cmd.Length > 0)
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 #endif
) && cmd.Length > 0)
Console.WriteLine("Failed to run command " + cmd);
} }
} }
@@ -117,6 +152,14 @@ public class Program
Console_Utilities.WriteColorText("&rRemember to close the bot using the ShutDown command (&ysd&r) or some settings won't be saved\n"); 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;
if (Config.ContainsKey("LaunchMessage"))
{
Console_Utilities.WriteColorText(Config.GetValue<string>("LaunchMessage"));
Config.RemoveKey("LaunchMessage");
}
Console_Utilities.WriteColorText("Please note that the bot saves a backup save file every time you are using the shudown command (&ysd&c)");
Console.WriteLine($"============================ LOG ============================"); Console.WriteLine($"============================ LOG ============================");
try try
@@ -135,7 +178,6 @@ public class Program
#endif #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);
await discordbooter.Awake(); await discordbooter.Awake();
return discordbooter; return discordbooter;
@@ -153,7 +195,7 @@ public class Program
/// <param name="d">Directory path</param> /// <param name="d">Directory path</param>
private static Task ClearFolder(string d) private static Task ClearFolder(string d)
{ {
var files = Directory.GetFiles(d); var files = Directory.GetFiles(d);
var fileNumb = files.Length; var fileNumb = files.Length;
for (var i = 0; i < fileNumb; i++) for (var i = 0; i < fileNumb; i++)
{ {
@@ -170,11 +212,12 @@ public class Program
/// <param name="args">The arguments</param> /// <param name="args">The arguments</param>
private static async Task HandleInput(string[] args) private static async Task HandleInput(string[] args)
{ {
var len = args.Length; var len = args.Length;
if (len == 3 && args[0] == "/download") if (len == 3 && args[0] == "/download")
{ {
var url = args[1]; var url = args[1];
var location = args[2]; var location = args[2];
await ServerCom.DownloadFileAsync(url, location); await ServerCom.DownloadFileAsync(url, location);
@@ -182,6 +225,23 @@ public class Program
return; return;
} }
if (len > 0 && args[0] == "/test")
{
int p = 1;
bool allowed = true;
Console.CancelKeyPress += (sender, e) => allowed = false;
Console_Utilities.ProgressBar bar = new(ProgressBarType.NO_END);// { NoColor = false, Color = ConsoleColor.DarkRed };
Console.WriteLine("Press Ctrl + C to stop.");
while (p <= int.MaxValue - 1 && allowed)
{
bar.Update(100 / p);
await Task.Delay(100);
p++;
}
return;
}
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")) if (args.Contains("lp") || args.Contains("loadplugins"))
@@ -193,11 +253,43 @@ public class Program
} }
var b = await StartNoGUI();
consoleCommandsHandler = new ConsoleCommandsHandler(b.client);
if (len > 0 && args[0] == "/remplug")
{
string plugName = Functions.MergeStrings(args, 1);
Console.WriteLine("Starting to remove " + plugName);
await ConsoleCommandsHandler.ExecuteCommad("remplug " + plugName);
loadPluginsOnStartup = true;
len = 0;
}
if (len == 0 || (args[0] != "--exec" && args[0] != "--execute")) if (len == 0 || (args[0] != "--exec" && args[0] != "--execute"))
{ {
var b = await StartNoGUI();
Thread mainThread = new Thread(() => NoGUI(b)); Thread mainThread = new Thread(() =>
{
try
{
NoGUI(b);
}
catch (IOException ex)
{
if (ex.Message == "No process is on the other end of the pipe." || (uint)ex.HResult == 0x800700E9)
{
if (!Config.ContainsKey("LaunchMessage"))
Config.AddValueToVariables("LaunchMessage", "An error occured while closing the bot last time. Please consider closing the bot using the &rsd&c method !\nThere is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !", false);
Functions.WriteErrFile(ex.ToString());
}
}
});
mainThread.Start(); mainThread.Start();
return; return;
} }
@@ -238,7 +330,7 @@ public class Program
case "--reset-logs": case "--reset-logs":
await ClearFolder("./Output/Logs"); await ClearFolder("./Output/Logs");
await ClearFolder("./Output/Errors"); await ClearFolder("./Output/Errors");
Console.WriteLine("Successfully cleard logs folder"); Console.WriteLine("Successfully clear logs folder");
break; break;
case "--exit": case "--exit":
case "exit": case "exit":
@@ -254,6 +346,8 @@ public class Program
private static async Task PreLoadComponents() private static async Task PreLoadComponents()
{ {
Console_Utilities.ProgressBar main = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
main.Start();
await Config.LoadConfig(); await Config.LoadConfig();
if (Config.ContainsKey("DeleteLogsAtStartup")) if (Config.ContainsKey("DeleteLogsAtStartup"))
if (Config.GetValue<bool>("DeleteLogsAtStartup")) if (Config.GetValue<bool>("DeleteLogsAtStartup"))
@@ -264,9 +358,9 @@ public class Program
Config.PluginConfig.Load(); Config.PluginConfig.Load();
if (!Config.ContainsKey("Version")) if (!Config.ContainsKey("Version"))
Config.AddValueToVariables("Version", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), false); Config.AddValueToVariables("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(), false);
else else
Config.SetValue("Version", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()); Config.SetValue("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
foreach (var key in OnlineDefaultKeys) foreach (var key in OnlineDefaultKeys)
{ {
@@ -283,7 +377,11 @@ public class Program
} }
} }
List<string> onlineSettingsList = await ServerCom.ReadTextFromURL("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");
main.Stop();
foreach (var key in onlineSettingsList) foreach (var key in onlineSettingsList)
{ {
if (key.Length <= 3 || !key.Contains(' ')) continue; if (key.Length <= 3 || !key.Contains(' ')) continue;
@@ -295,42 +393,45 @@ public class Program
string newVersion = s[1]; string newVersion = s[1];
if (!newVersion.Equals(Config.GetValue<string>("Version"))) if (!newVersion.Equals(Config.GetValue<string>("Version")))
{ {
Console.WriteLine("A new version has been released on github page."); if (Functions.GetOperatingSystem() == PluginManager.Others.OperatingSystem.WINDOWS)
Console.WriteLine("Download the new version using the following link wrote in yellow");
Console_Utilities.WriteColorText("&y" + Config.GetValue<string>("GitURL") + "&c");
Console.WriteLine();
Console.WriteLine("Your product will work just fine on this outdated version, but an update is recommended.\n" +
"From now on, this version is no longer supported"
);
Console_Utilities.WriteColorText("&rUse at your own risk&c");
Console_Utilities.WriteColorText("&mCurrent Version: " + Config.GetValue<string>("Version") + "&c");
Console_Utilities.WriteColorText("&gNew Version: " + newVersion + "&c");
Console.WriteLine("\n\n");
await Task.Delay(1000);
int waitTime = 20; //wait time to proceed
Console.Write($"The bot will start in {waitTime} seconds");
while (waitTime > 0)
{ {
await Task.Delay(1000);
waitTime--; string url = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0.zip";
Console.SetCursorPosition("The bot will start in ".Length, Console.CursorTop); //string url2 = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}-preview/net6.0.zip";
Console.Write(" "); Process.Start("./Updater/Updater.exe", $"/update {url} ./DiscordBot.exe ./");
Console.SetCursorPosition("The bot will start in ".Length, Console.CursorTop);
Console.Write(waitTime + " seconds");
} }
else
{
string url = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0_linux.zip";
Process.Start("./Updater/Updater", $"/update {url} ./DiscordBot ./");
}
Environment.Exit(0);
} }
break;
case "UpdaterVersion":
string updaternewversion = s[1];
if (Config.UpdaterVersion != updaternewversion)
{
Console.Clear();
Console.WriteLine("Installing updater ...\nDo NOT close the bot during update !");
Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start();
await ServerCom.DownloadFileNoProgressAsync("https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.zip", "./Updater.zip");
await Functions.ExtractArchive("./Updater.zip", "./", null, UnzipProgressType.PercentageFromTotalSize);
Config.UpdaterVersion = updaternewversion;
File.Delete("Updater.zip");
await Config.SaveConfig(SaveType.NORMAL);
bar.Stop();
Console.Clear();
}
break; break;
} }
} }
Console_Utilities.Initialize();
Config.SaveConfig(); Console_Utilities.Initialize();
await Config.SaveConfig(SaveType.NORMAL);
Console.Clear();
} }
} }

View File

@@ -1,6 +1,8 @@
using Discord; using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using EVE_LevelingSystem.LevelingSystemCore; using EVE_LevelingSystem.LevelingSystemCore;
using PluginManager; using PluginManager;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Others; using PluginManager.Others;
@@ -9,8 +11,8 @@ namespace EVE_LevelingSystem
{ {
internal class Level : DBEvent internal class Level : DBEvent
{ {
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();
@@ -39,7 +41,7 @@ namespace EVE_LevelingSystem
{ {
if (arg.Author.IsBot || arg.IsTTS || arg.Content.StartsWith(Config.GetValue<string>("prefix"))) return; if (arg.Author.IsBot || arg.IsTTS || arg.Content.StartsWith(Config.GetValue<string>("prefix"))) return;
string userID = arg.Author.Id.ToString(); string userID = arg.Author.Id.ToString();
User user; User user;
if (File.Exists($"{Config.GetValue<string>("LevelingSystemPath")}/{userID}.dat")) if (File.Exists($"{Config.GetValue<string>("LevelingSystemPath")}/{userID}.dat"))
{ {
user = await Functions.ConvertFromJson<User>(Config.GetValue<string>("LevelingSystemPath")! + $"/{userID}.dat"); user = await Functions.ConvertFromJson<User>(Config.GetValue<string>("LevelingSystemPath")! + $"/{userID}.dat");

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using PluginManager; using PluginManager;
namespace EVE_LevelingSystem.LevelingSystemCore namespace EVE_LevelingSystem.LevelingSystemCore
@@ -18,7 +19,7 @@ namespace EVE_LevelingSystem.LevelingSystemCore
internal static void LevelUp(this User user) internal static void LevelUp(this User user)
{ {
user.CurrentEXP = 0; user.CurrentEXP = 0;
user.RequiredEXPToLevelUp = GetNextLevelRequiredEXP(user.CurrentLevel); user.RequiredEXPToLevelUp = GetNextLevelRequiredEXP(user.CurrentLevel);
user.CurrentLevel++; user.CurrentLevel++;
} }
@@ -26,15 +27,15 @@ namespace EVE_LevelingSystem.LevelingSystemCore
internal static bool AddEXP(this User user) internal static bool AddEXP(this User user)
{ {
if (OnWaitingList.Contains(user.user.userID.ToString())) return false; if (OnWaitingList.Contains(user.user.userID.ToString())) return false;
Random r = new Random(); Random r = new Random();
int exp = r.Next(2, 12); int exp = r.Next(Level.globalSettings.MinEXP, Level.globalSettings.MaxEXP + 1);
Int64 userXP = user.CurrentEXP; Int64 userXP = user.CurrentEXP;
Int64 reqEXP = user.RequiredEXPToLevelUp; Int64 reqEXP = user.RequiredEXPToLevelUp;
if (userXP + exp >= reqEXP) if (userXP + exp >= reqEXP)
{ {
user.LevelUp(); user.LevelUp();
user.CurrentEXP = exp - (reqEXP - userXP); user.CurrentEXP = exp - (reqEXP - userXP);
Console.WriteLine("Level up"); //Console.WriteLine("Level up");
return true; return true;
} }
@@ -49,7 +50,7 @@ namespace EVE_LevelingSystem.LevelingSystemCore
Thread.Sleep(60000 * minutesToWait); Thread.Sleep(60000 * minutesToWait);
OnWaitingList.Remove(user.user.userID.ToString()); OnWaitingList.Remove(user.user.userID.ToString());
} }
); ).Start();
return false; return false;
} }

View File

@@ -9,5 +9,7 @@ namespace EVE_LevelingSystem
public class Settings public class Settings
{ {
public int TimeToWaitBetweenMessages { get; set; } public int TimeToWaitBetweenMessages { get; set; }
public int MinEXP { get; set; }
public int MaxEXP { get; set; }
} }
} }

View File

@@ -1,4 +1,5 @@
using AngleSharp.Dom; using AngleSharp.Dom;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@@ -11,20 +12,20 @@ namespace MusicCommands
internal class AudioFile internal class AudioFile
{ {
internal string Name { get; set; } internal string Name { get; set; }
internal string Url { get; set; } internal string Url { get; set; }
internal AudioFile(string name, string url) internal AudioFile(string name, string url)
{ {
Name = name; Name = name;
Url = url; Url = url;
} }
internal async Task DownloadAudioFile() internal async Task DownloadAudioFile()
{ {
Process proc = new Process(); Process proc = new Process();
proc.StartInfo.FileName = "MusicDownloader.exe"; proc.StartInfo.FileName = "MusicDownloader";
proc.StartInfo.Arguments = $"{Url},{Name}"; proc.StartInfo.Arguments = $"{Url},{Name}";
proc.StartInfo.UseShellExecute = false; proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardOutput = true;
proc.Start(); proc.Start();

View File

@@ -1,4 +1,5 @@
using Discord.Commands; using System.Collections.Generic;
using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
@@ -8,6 +9,8 @@ internal class Leave : DBCommand
{ {
public string Command => "leave"; public string Command => "leave";
public List<string> Aliases => null;
public string Description => "Leave the voice channel"; public string Description => "Leave the voice channel";
public string Usage => "leave"; public string Usage => "leave";

View File

@@ -5,7 +5,8 @@ namespace MusicCommands;
internal class MusicPlayer internal class MusicPlayer
{ {
private Stream outputStream { get; } private Stream outputStream { get; }
internal AudioFile NowPlaying = null;
internal bool isPlaying, isPaused; internal bool isPlaying, isPaused;
@@ -14,9 +15,10 @@ internal class MusicPlayer
outputStream = outputChannel; outputStream = outputChannel;
} }
public async Task Play(Stream source, int byteSize) public async Task Play(Stream source, int byteSize, AudioFile songPlaying)
{ {
isPlaying = true; isPlaying = true;
NowPlaying = songPlaying;
while (isPlaying) while (isPlaying)
{ {
if (isPaused) if (isPaused)

View File

@@ -1,4 +1,5 @@
using Discord.Commands; using System.Collections.Generic;
using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
@@ -8,6 +9,8 @@ internal class Pause : DBCommand
{ {
public string Command => "pause"; public string Command => "pause";
public List<string> Aliases => null;
public string Description => "Pause/Unpause the music that is currently running"; public string Description => "Pause/Unpause the music that is currently running";
public string Usage => "pause"; public string Usage => "pause";

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using Discord; using Discord;
@@ -14,6 +15,8 @@ internal class Play : DBCommand
{ {
public string Command => "play"; public string Command => "play";
public List<string> Aliases => new() { "p" };
public string Description => "Play music from a file"; public string Description => "Play music from a file";
public string Usage => "play [name/url]"; public string Usage => "play [name/url]";
@@ -69,11 +72,11 @@ internal class Play : DBCommand
if (Data.MusicPlayer is not null) if (Data.MusicPlayer is not null)
{ {
await context.Channel.SendMessageAsync("Enqueued your request"); await context.Channel.SendMessageAsync("Queued your request: " + splitted.MergeStrings(1));
return; return;
} }
} }
while (false); while (false); // run only one time !
Data.voiceChannel = (context.User as IGuildUser)?.VoiceChannel; Data.voiceChannel = (context.User as IGuildUser)?.VoiceChannel;
@@ -93,15 +96,14 @@ internal class Play : DBCommand
using (var discordChanneAudioOutStream = Data.audioClient.CreatePCMStream(AudioApplication.Mixed)) using (var discordChanneAudioOutStream = Data.audioClient.CreatePCMStream(AudioApplication.Mixed))
{ {
if (Data.MusicPlayer is null) Data.MusicPlayer ??= new MusicPlayer(discordChanneAudioOutStream);
Data.MusicPlayer = new MusicPlayer(discordChanneAudioOutStream);
while (Data.Playlist.Count > 0) while (Data.Playlist.Count > 0)
{ {
var nowPlaying = Data.Playlist.GetNextSong; var nowPlaying = Data.Playlist.GetNextSong;
using (var ffmpeg = CreateStream(nowPlaying.Name)) using (var ffmpeg = CreateStream(nowPlaying.Name))
using (var ffmpegOutputBaseStream = ffmpeg.StandardOutput.BaseStream) using (var ffmpegOutputBaseStream = ffmpeg.StandardOutput.BaseStream)
{ {
await Data.MusicPlayer.Play(ffmpegOutputBaseStream, 1024); await Data.MusicPlayer.Play(ffmpegOutputBaseStream, 1024, nowPlaying);
Console.WriteLine("Finished playing from " + nowPlaying.Url); Console.WriteLine("Finished playing from " + nowPlaying.Url);
} }
} }
@@ -110,7 +112,7 @@ internal class Play : DBCommand
} }
} }
private Process CreateStream(string path) private static Process CreateStream(string path)
{ {
return Process.Start(new ProcessStartInfo { FileName = "ffmpeg", Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1", UseShellExecute = false, RedirectStandardOutput = true }); return Process.Start(new ProcessStartInfo { FileName = "ffmpeg", Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1", UseShellExecute = false, RedirectStandardOutput = true });
} }

View File

@@ -13,6 +13,8 @@ namespace MusicCommands
{ {
public string Command => "skip"; public string Command => "skip";
public List<string> Aliases => null;
public string Description => "skip the music that is currently running"; public string Description => "skip the music that is currently running";
public string Usage => "skip"; public string Usage => "skip";
@@ -25,7 +27,16 @@ namespace MusicCommands
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{ {
var loadedSong = Data.MusicPlayer.NowPlaying;
if (loadedSong is null || Data.MusicPlayer.isPlaying == false)
{
message.Channel.SendMessageAsync("There is no music playing");
return;
}
Data.MusicPlayer.isPlaying = false; Data.MusicPlayer.isPlaying = false;
message.Channel.SendMessageAsync($"You have skipped {loadedSong.Name}");
} }
} }
} }

View File

@@ -11,7 +11,8 @@ namespace MusicCommands
{ {
public class queue : DBCommand public class queue : DBCommand
{ {
public string Command => "queue"; public string Command => "queue";
public List<string> Aliases => new() { "q" };
public string Description => "check queue"; public string Description => "check queue";

View File

@@ -11,8 +11,10 @@ namespace PluginManager
{ {
internal class AppConfig internal class AppConfig
{ {
public string UpdaterVersion { get; set; }
public Dictionary<string, object>? ApplicationVariables { get; init; } public Dictionary<string, object>? ApplicationVariables { get; init; }
public List<string>? ProtectedKeyWords { get; init; } public List<string>? ProtectedKeyWords { get; init; }
public Dictionary<string, string>? PluginVersions { get; init; }
} }
public static class Config public static class Config
@@ -29,27 +31,27 @@ namespace PluginManager
private static void LoadCommands() private static void LoadCommands()
{ {
string cmd_path = "./Data/Plugins/Commands/"; string cmd_path = "./Data/Plugins/Commands/";
string[] files = Directory.GetFiles(cmd_path, $"*.{Loaders.PluginLoader.pluginCMDExtension}", SearchOption.AllDirectories); string[] files = Directory.GetFiles(cmd_path, $"*.{Loaders.PluginLoader.pluginCMDExtension}", SearchOption.AllDirectories);
foreach (var file in files) foreach (var file in files)
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase)) if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
{ {
string PluginName = new FileInfo(file).Name; string PluginName = new FileInfo(file).Name;
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginCMDExtension.Length); string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginCMDExtension.Length);
InstalledPlugins.Add(new(name, PluginType.Command)); InstalledPlugins.Add(new(name, PluginType.Command));
} }
} }
private static void LoadEvents() private static void LoadEvents()
{ {
string eve_path = "./Data/Plugins/Events/"; string eve_path = "./Data/Plugins/Events/";
string[] files = Directory.GetFiles(eve_path, $"*.{Loaders.PluginLoader.pluginEVEExtension}", SearchOption.AllDirectories); string[] files = Directory.GetFiles(eve_path, $"*.{Loaders.PluginLoader.pluginEVEExtension}", SearchOption.AllDirectories);
foreach (var file in files) foreach (var file in files)
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase)) if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase)) if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
{ {
string PluginName = new FileInfo(file).Name; string PluginName = new FileInfo(file).Name;
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginEVEExtension.Length); string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginEVEExtension.Length);
InstalledPlugins.Add(new(name, PluginType.Event)); InstalledPlugins.Add(new(name, PluginType.Event));
} }
} }
@@ -57,9 +59,8 @@ namespace PluginManager
public static bool Contains(string pluginName) public static bool Contains(string pluginName)
{ {
foreach (var tuple in InstalledPlugins) foreach (var tuple in InstalledPlugins)
{ if (tuple.Item1 == pluginName)
if (tuple.Item1 == pluginName) return true; return true;
}
return false; return false;
} }
@@ -67,9 +68,9 @@ namespace PluginManager
public static PluginType GetPluginType(string pluginName) public static PluginType GetPluginType(string pluginName)
{ {
foreach (var tuple in InstalledPlugins) foreach (var tuple in InstalledPlugins)
{ if (tuple.Item1 == pluginName)
if (tuple.Item1 == pluginName) return tuple.Item2; return tuple.Item2;
}
return PluginType.Unknown; return PluginType.Unknown;
} }
@@ -77,6 +78,21 @@ namespace PluginManager
private static AppConfig? appConfig { get; set; } private static AppConfig? appConfig { get; set; }
public static string UpdaterVersion { get => appConfig.UpdaterVersion; set => appConfig.UpdaterVersion = value; }
public static string GetPluginVersion(string pluginName) => appConfig!.PluginVersions![pluginName];
public static void SetPluginVersion(string pluginName, string newVersion)
{
if (appConfig!.PluginVersions!.ContainsKey(pluginName))
appConfig.PluginVersions[pluginName] = newVersion;
else appConfig.PluginVersions.Add(pluginName, newVersion);
// SaveConfig();
}
public static void RemovePluginVersion(string pluginName) => appConfig!.PluginVersions!.Remove(pluginName);
public static bool PluginVersionsContainsKey(string pluginName) => appConfig!.PluginVersions!.ContainsKey(pluginName);
public static void AddValueToVariables<T>(string key, T value, bool isProtected) public static void AddValueToVariables<T>(string key, T value, bool isProtected)
{ {
if (value == null) if (value == null)
@@ -88,7 +104,7 @@ namespace PluginManager
if (isProtected && key != "Version") if (isProtected && key != "Version")
appConfig.ProtectedKeyWords!.Add(key); appConfig.ProtectedKeyWords!.Add(key);
SaveConfig(); SaveConfig(SaveType.NORMAL);
} }
public static Type GetVariableType(string value) public static Type GetVariableType(string value)
@@ -156,7 +172,7 @@ namespace PluginManager
throw new Exception("Key is protected"); throw new Exception("Key is protected");
appConfig.ApplicationVariables[key] = JsonSerializer.SerializeToElement(value); appConfig.ApplicationVariables[key] = JsonSerializer.SerializeToElement(value);
SaveConfig(); SaveConfig(SaveType.NORMAL);
} }
public static void RemoveKey(string key) public static void RemoveKey(string key)
@@ -165,13 +181,24 @@ namespace PluginManager
throw new Exception("Key is protected"); throw new Exception("Key is protected");
appConfig!.ApplicationVariables!.Remove(key); appConfig!.ApplicationVariables!.Remove(key);
appConfig.ProtectedKeyWords!.Remove(key); appConfig.ProtectedKeyWords!.Remove(key);
SaveConfig(); SaveConfig(SaveType.NORMAL);
} }
public static async void SaveConfig() public static async Task SaveConfig(SaveType type)
{ {
string path = Functions.dataFolder + "config.json"; if (type == SaveType.NORMAL)
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!); {
string path = Functions.dataFolder + "config.json";
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!);
return;
}
if (type == SaveType.BACKUP)
{
string path = Functions.dataFolder + "config.json.bak";
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!);
return;
}
} }
public static async Task LoadConfig() public static async Task LoadConfig()
@@ -179,15 +206,28 @@ namespace PluginManager
string path = Functions.dataFolder + "config.json"; string path = Functions.dataFolder + "config.json";
if (File.Exists(path)) if (File.Exists(path))
{ {
appConfig = await Functions.ConvertFromJson<AppConfig>(path); try
{
appConfig = await Functions.ConvertFromJson<AppConfig>(path);
}
catch (Exception ex)
{
File.Delete(path);
Console.WriteLine("An error occured while loading the settings. Importing from backup file...");
path = Functions.dataFolder + "config.json.bak";
appConfig = await Functions.ConvertFromJson<AppConfig>(path);
Functions.WriteErrFile(ex.Message);
}
Functions.WriteLogFile($"Loaded {appConfig.ApplicationVariables!.Keys.Count} application variables.\nLoaded {appConfig.ProtectedKeyWords!.Count} readonly variables."); Functions.WriteLogFile($"Loaded {appConfig.ApplicationVariables!.Keys.Count} application variables.\nLoaded {appConfig.ProtectedKeyWords!.Count} readonly variables.");
return;
} }
else appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>(), PluginVersions = new Dictionary<string, string>(), UpdaterVersion = "-1" };
appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>() };
} }
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 ReadOnlyDictionary<string, object> GetAllVariables() => new(appConfig!.ApplicationVariables!); public static ReadOnlyDictionary<string, object> GetAllVariables() => new(appConfig!.ApplicationVariables!);
} }

View File

@@ -1,4 +1,5 @@
using Discord.Commands; using System.Collections.Generic;
using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
namespace PluginManager.Interfaces; namespace PluginManager.Interfaces;
@@ -11,6 +12,11 @@ public interface DBCommand
/// </summary> /// </summary>
string Command { get; } string Command { get; }
/// <summary>
/// Command aliases. Users may use this to execute the command
/// </summary>
List<string>? Aliases { get; }
/// <summary> /// <summary>
/// Command description /// Command description
/// </summary> /// </summary>
@@ -44,8 +50,5 @@ public interface DBCommand
/// <param name="message">The message that the user types</param> /// <param name="message">The message that the user types</param>
/// <param name="client">The discord client of the bot</param> /// <param name="client">The discord client of the bot</param>
/// <param name="isDM">true if the message was sent from DM, otherwise false. It is always false if canUseDM is false</param> /// <param name="isDM">true if the message was sent from DM, otherwise false. It is always false if canUseDM is false</param>
void Execute(SocketCommandContext context, void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM);
SocketMessage message,
DiscordSocketClient client,
bool isDM);
} }

View File

@@ -44,8 +44,8 @@ public class Command
public class ConsoleCommand public class ConsoleCommand
{ {
public string CommandName { get; set; } public string CommandName { get; init; }
public string Description { get; set; } public string Description { get; init; }
public string Usage { get; set; } public string Usage { get; init; }
public Action<string[]> Action { get; set; } public Action<string[]> Action { get; init; }
} }

View File

@@ -1,21 +1,33 @@
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.Net.Http;
using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces;
using PluginManager.Loaders; using PluginManager.Loaders;
using PluginManager.Online; using PluginManager.Online;
using PluginManager.Online.Helpers;
using PluginManager.Online.Updates;
using PluginManager.Others; using PluginManager.Others;
namespace PluginManager.Items; 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");
private static readonly List<ConsoleCommand> commandList = new(); private static readonly List<ConsoleCommand> commandList = new();
private readonly DiscordSocketClient? client; private readonly DiscordSocketClient? client;
private static bool isDownloading = false;
private static bool pluginsLoaded = false;
public ConsoleCommandsHandler(DiscordSocketClient client) public ConsoleCommandsHandler(DiscordSocketClient client)
{ {
@@ -26,7 +38,7 @@ public class ConsoleCommandsHandler
private void InitializeBasicCommands() private void InitializeBasicCommands()
{ {
var pluginsLoaded = false;
commandList.Clear(); commandList.Clear();
AddCommand("help", "Show help", "help <command>", args => AddCommand("help", "Show help", "help <command>", args =>
@@ -70,30 +82,48 @@ public class ConsoleCommandsHandler
if (pluginsLoaded) if (pluginsLoaded)
return; return;
var loader = new PluginLoader(client!); var loader = new PluginLoader(client!);
ConsoleColor cc = Console.ForegroundColor;
loader.onCMDLoad += (name, typeName, success, exception) => loader.onCMDLoad += (name, typeName, success, exception) =>
{ {
Console.ForegroundColor = ConsoleColor.Green;
if (name == null || name.Length < 2) if (name == null || name.Length < 2)
name = typeName; name = typeName;
if (success) if (success)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[CMD] Successfully loaded command : " + name); Console.WriteLine("[CMD] Successfully loaded command : " + name);
}
else else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message); Console.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message);
Console.ForegroundColor = ConsoleColor.Red; }
Console.ForegroundColor = cc;
}; };
loader.onEVELoad += (name, typeName, success, exception) => loader.onEVELoad += (name, typeName, success, exception) =>
{ {
if (name == null || name.Length < 2) if (name == null || name.Length < 2)
name = typeName; name = typeName;
Console.ForegroundColor = ConsoleColor.Green;
if (success) if (success)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[EVENT] Successfully loaded event : " + name); Console.WriteLine("[EVENT] Successfully loaded event : " + name);
}
else else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message); Console.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message);
Console.ForegroundColor = ConsoleColor.Red; }
Console.ForegroundColor = cc;
}; };
loader.LoadPlugins(); loader.LoadPlugins();
Console.ForegroundColor = cc;
pluginsLoaded = true; pluginsLoaded = true;
} }
); );
@@ -101,8 +131,10 @@ public class ConsoleCommandsHandler
AddCommand("dwplug", "download plugin", "dwplug [name]", async args => AddCommand("dwplug", "download plugin", "dwplug [name]", async args =>
{ {
isDownloading = true;
if (args.Length == 1) if (args.Length == 1)
{ {
isDownloading = false;
Console.WriteLine("Please specify plugin name"); Console.WriteLine("Please specify plugin name");
return; return;
} }
@@ -116,10 +148,11 @@ public class ConsoleCommandsHandler
{ {
if (name == "") if (name == "")
{ {
isDownloading = false;
Console_Utilities.WriteColorText("Name is invalid"); Console_Utilities.WriteColorText("Name is invalid");
return; return;
} }
isDownloading = false;
Console_Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" + " Use &glistplugs &ccommand to display all available plugins !"); Console_Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" + " Use &glistplugs &ccommand to display all available plugins !");
return; return;
} }
@@ -154,34 +187,17 @@ public class ConsoleCommandsHandler
continue; continue;
var split = line.Split(','); var split = line.Split(',');
Console.WriteLine($"\nDownloading item: {split[1]}"); Console.WriteLine($"\nDownloading item: {split[1]}");
if (File.Exists("./" + split[1])) File.Delete("./" + 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") || split[0].EndsWith(".pak") || split[0].EndsWith(".pkg")) 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 = 0f; var bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END) { Max = 100f, Color = ConsoleColor.Green };
var isExtracting = true; bar.Start();
var bar = new Console_Utilities.ProgressBar { Max = 100f, Color = ConsoleColor.Green }; await Functions.ExtractArchive("./" + split[1], "./", null, UnzipProgressType.PercentageFromTotalSize);
bar.Stop();
IProgress<float> extractProgress = new Progress<float>(value => { proc = value; });
new Thread(new Task(() =>
{
while (isExtracting)
{
bar.Update(proc);
if (proc >= 99.9f)
isExtracting = false;
Thread.Sleep(500);
}
}
).Start
).Start();
await Functions.ExtractArchive("./" + split[1], "./", extractProgress, UnzipProgressType.PercentageFromTotalSize);
bar.Update(100f);
isExtracting = false;
await Task.Delay(1000);
bar.Update(100);
Console.WriteLine("\n"); Console.WriteLine("\n");
File.Delete("./" + split[1]); File.Delete("./" + split[1]);
} }
@@ -189,6 +205,12 @@ public class ConsoleCommandsHandler
Console.WriteLine(); Console.WriteLine();
} }
VersionString? ver = await VersionString.GetVersionOfPackageFromWeb(name);
if (ver is null) throw new Exception("Incorrect version");
Config.SetPluginVersion(name, $"{ver.PackageVersionID}.{ver.PackageMainVersion}.{ver.PackageCheckVersion}");
// Console.WriteLine();
isDownloading = false;
} }
); );
@@ -209,8 +231,8 @@ public class ConsoleCommandsHandler
{ {
if (args.Length < 4) if (args.Length < 4)
return; 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);
try try
@@ -237,14 +259,142 @@ public class ConsoleCommandsHandler
{ {
if (client is null) if (client is null)
return; return;
Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start();
await Config.SaveConfig(SaveType.NORMAL);
await Config.SaveConfig(SaveType.BACKUP);
await Task.Delay(4000);
bar.Stop();
Console.WriteLine();
await client.StopAsync(); await client.StopAsync();
await client.DisposeAsync(); await client.DisposeAsync();
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);
} }
); );
AddCommand("extern", "Load an external command", "extern [pluginName]", async (args) =>
{
if (args.Length <= 1) return;
string pName = Functions.MergeStrings(args, 1);
HttpClient client = new HttpClient();
string url = (await manager.GetPluginLinkByName(pName))[1];
Stream s = await client.GetStreamAsync(url);
MemoryStream str = new MemoryStream();
await s.CopyToAsync(str);
var asmb = Assembly.Load(str.ToArray());
var types = asmb.GetTypes();
foreach (var type in types)
{
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
{
DBEvent instance = (DBEvent)Activator.CreateInstance(type);
instance.Start(this.client);
Console.WriteLine($"Loaded external {type.FullName}!");
}
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
{
Console.WriteLine("Only events can be loaded from external sources !");
return;
}
}
});
AddCommand("remplug", "Remove a plugin", "remplug [plugName]", async args =>
{
if (args.Length <= 1) return;
isDownloading = true;
string plugName = Functions.MergeStrings(args, 1);
if (pluginsLoaded)
{
if (Functions.GetOperatingSystem() == Others.OperatingSystem.WINDOWS)
{
Process.Start("DiscordBot.exe", $"/remplug {plugName}");
await Task.Delay(100);
Environment.Exit(0);
}
else
{
Process.Start("./DiscordBot", $"/remplug {plugName}");
await Task.Delay(100);
Environment.Exit(0);
}
isDownloading = false;
return;
}
string location = "./Data/Plugins/";
location = Config.PluginConfig.GetPluginType(plugName) switch
{
PluginType.Command => location + "Commands/" + plugName + "." + PluginLoader.pluginCMDExtension,
PluginType.Event => location + "Events/" + plugName + "." + PluginLoader.pluginEVEExtension,
PluginType.Unknown => "./",
_ => throw new NotImplementedException("Plugin type incorrect")
};
if (!File.Exists(location))
{
Console.WriteLine("The plugin does not exist");
return;
}
File.Delete(location);
if (Config.PluginConfig.Contains(plugName))
{
var tuple = Config.PluginConfig.InstalledPlugins.Where(t => t.Item1 == plugName).FirstOrDefault();
Console.WriteLine("Found: " + tuple.ToString());
Config.PluginConfig.InstalledPlugins.Remove(tuple);
Config.RemovePluginVersion(plugName);
await Config.SaveConfig(SaveType.NORMAL);
}
Console.WriteLine("Removed the plugin DLL. Checking for other files ...");
var info = await manager.GetPluginLinkByName(plugName);
if (info[2] != string.Empty)
{
var lines = await ServerCom.ReadTextFromURL(info[2]);
foreach (var line in lines)
{
if (!(line.Length > 0 && line.Contains(",")))
continue;
var split = line.Split(',');
if (File.Exists("./" + split[1]))
File.Delete("./" + split[1]);
Console.WriteLine("Removed: " + split[1]);
}
if (Directory.Exists(plugName))
Directory.Delete(plugName, true);
}
isDownloading = false;
Console.WriteLine(plugName + " has been successfully deleted !");
});
AddCommand("reload", "Reload the bot with all plugins", () =>
{
if (Functions.GetOperatingSystem() == Others.OperatingSystem.WINDOWS)
{
Process.Start("DiscordBot.exe", $"lp");
HandleCommand("sd");
}
else
{
Process.Start("./DiscordBot", $"lp");
HandleCommand("sd");
}
});
//Sort the commands by name //Sort the commands by name
commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName)); commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName));
} }
@@ -268,7 +418,7 @@ public class ConsoleCommandsHandler
public static bool CommandExists(string command) public static bool CommandExists(string command)
{ {
return !(GetCommand(command) is null); return GetCommand(command) is not null;
} }
public static ConsoleCommand? GetCommand(string command) public static ConsoleCommand? GetCommand(string command)
@@ -276,8 +426,24 @@ public class ConsoleCommandsHandler
return commandList.FirstOrDefault(t => t.CommandName == command); return commandList.FirstOrDefault(t => t.CommandName == command);
} }
public static async Task ExecuteCommad(string command)
{
var args = command.Split(' ');
// Console.WriteLine(command);
foreach (var item in commandList.ToList())
if (item.CommandName == args[0])
{
item.Action.Invoke(args);
Console.WriteLine();
while (isDownloading) await Task.Delay(1000);
}
}
public bool HandleCommand(string command, bool removeCommandExecution = true) public bool HandleCommand(string command, bool removeCommandExecution = true)
{ {
Console.ForegroundColor = ConsoleColor.White;
var args = command.Split(' '); var args = command.Split(' ');
foreach (var item in commandList.ToList()) foreach (var item in commandList.ToList())
if (item.CommandName == args[0]) if (item.CommandName == args[0])
@@ -292,6 +458,7 @@ public class ConsoleCommandsHandler
Console.WriteLine(); Console.WriteLine();
item.Action(args); item.Action(args);
return true; return true;
} }

View File

@@ -3,29 +3,32 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using PluginManager.Online.Updates;
using PluginManager.Others; using PluginManager.Others;
namespace PluginManager.Loaders; namespace PluginManager.Loaders;
internal class LoaderArgs : EventArgs internal class LoaderArgs : EventArgs
{ {
internal string? PluginName { get; init; } internal string? PluginName { get; init; }
internal string? TypeName { get; init; } internal string? TypeName { get; init; }
internal bool IsLoaded { get; init; } internal bool IsLoaded { get; init; }
internal Exception? Exception { get; init; } internal Exception? Exception { get; init; }
internal object? Plugin { get; init; } internal object? Plugin { get; init; }
} }
internal class Loader<T> internal class Loader<T>
{ {
internal Loader(string path, string extension) internal Loader(string path, string extension)
{ {
this.path = path; this.path = path;
this.extension = extension; this.extension = extension;
} }
private string path { get; } private string path { get; }
private string extension { get; } private string extension { get; }
@@ -49,16 +52,17 @@ internal class Loader<T>
var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories); var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories);
foreach (var file in files) foreach (var file in files)
{ {
Assembly.LoadFrom(file); Assembly.LoadFrom(file);
if (FileLoaded != null) if (FileLoaded != null)
{ {
var args = new LoaderArgs var args = new LoaderArgs
{ {
Exception = null, Exception = null,
TypeName = nameof(T), TypeName = nameof(T),
IsLoaded = false, IsLoaded = false,
PluginName = file, PluginName = new FileInfo(file).Name.Split('.')[0],
Plugin = null Plugin = null
}; };
FileLoaded.Invoke(args); FileLoaded.Invoke(args);
} }
@@ -83,13 +87,13 @@ internal class Loader<T>
if (PluginLoaded != null) if (PluginLoaded != null)
PluginLoaded.Invoke(new LoaderArgs PluginLoaded.Invoke(new LoaderArgs
{ {
Exception = null, Exception = null,
IsLoaded = true, IsLoaded = true,
PluginName = type.FullName, PluginName = type.FullName,
TypeName = nameof(T), TypeName = nameof(T),
Plugin = plugin Plugin = plugin
} }
); );
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -1,7 +1,15 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Online.Helpers;
using PluginManager.Online.Updates;
using PluginManager.Others; using PluginManager.Others;
namespace PluginManager.Loaders; namespace PluginManager.Loaders;
@@ -15,8 +23,8 @@ public class PluginLoader
private const string pluginCMDFolder = @"./Data/Plugins/Commands/"; private const string pluginCMDFolder = @"./Data/Plugins/Commands/";
private const string pluginEVEFolder = @"./Data/Plugins/Events/"; private const string pluginEVEFolder = @"./Data/Plugins/Events/";
internal const string pluginCMDExtension = "dll"; internal const string pluginCMDExtension = "dll";
internal const string pluginEVEExtension = "dll"; internal const string pluginEVEExtension = "dll";
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
/// <summary> /// <summary>
@@ -52,35 +60,79 @@ public class PluginLoader
/// <summary> /// <summary>
/// The main mathod that is called to load all events /// The main mathod that is called to load all events
/// </summary> /// </summary>
public void LoadPlugins() public async void LoadPlugins()
{ {
//Check for updates in commands
foreach (var file in Directory.GetFiles("./Data/Plugins/Commands", $"*.{pluginCMDExtension}", SearchOption.AllDirectories))
{
await Task.Run(async () =>
{
string name = new FileInfo(file).Name.Split('.')[0];
if (!Config.PluginVersionsContainsKey(name))
Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageVersionID + ".0.0");
if (await PluginUpdater.CheckForUpdates(name))
await PluginUpdater.Download(name);
});
}
//Check for updates in events
foreach (var file in Directory.GetFiles("./Data/Plugins/Events", $"*.{pluginEVEExtension}", SearchOption.AllDirectories))
{
await Task.Run(async () =>
{
string name = new FileInfo(file).Name.Split('.')[0];
if (!Config.PluginVersionsContainsKey(name))
Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageVersionID + ".0.0");
if (await PluginUpdater.CheckForUpdates(name))
await PluginUpdater.Download(name);
});
}
//Save the new config file (after the updates)
await Config.SaveConfig(SaveType.NORMAL);
//Load all plugins
Commands = new List<DBCommand>(); Commands = new List<DBCommand>();
Events = new List<DBEvent>(); Events = new List<DBEvent>();
Functions.WriteLogFile("Starting plugin loader ... Client: " + _client.CurrentUser.Username); Functions.WriteLogFile("Starting plugin loader ... Client: " + _client.CurrentUser.Username);
Console.WriteLine("Loading plugins"); Console.WriteLine("Loading plugins");
var commandsLoader = new Loader<DBCommand>(pluginCMDFolder, pluginCMDExtension); var commandsLoader = new Loader<DBCommand>(pluginCMDFolder, pluginCMDExtension);
var eventsLoader = new Loader<DBEvent>(pluginEVEFolder, pluginEVEExtension); var eventsLoader = new Loader<DBEvent>(pluginEVEFolder, pluginEVEExtension);
commandsLoader.FileLoaded += OnCommandFileLoaded; commandsLoader.FileLoaded += OnCommandFileLoaded;
commandsLoader.PluginLoaded += OnCommandLoaded; commandsLoader.PluginLoaded += OnCommandLoaded;
eventsLoader.FileLoaded += EventFileLoaded; eventsLoader.FileLoaded += EventFileLoaded;
eventsLoader.PluginLoaded += OnEventLoaded; eventsLoader.PluginLoaded += OnEventLoaded;
Commands = commandsLoader.Load(); Commands = commandsLoader.Load();
Events = eventsLoader.Load(); Events = eventsLoader.Load();
} }
private void EventFileLoaded(LoaderArgs e) private void EventFileLoaded(LoaderArgs e)
{ {
if (e.IsLoaded) Functions.WriteLogFile($"[EVENT] Event from file [{e.PluginName}] has been successfully created !"); if (!e.IsLoaded)
{
Functions.WriteLogFile($"[EVENT] Event from file [{e.PluginName}] has been successfully created !");
}
} }
private void OnCommandFileLoaded(LoaderArgs e) private void OnCommandFileLoaded(LoaderArgs e)
{ {
if (e.IsLoaded) Functions.WriteLogFile($"[CMD] Command from file [{e.PluginName}] has been successfully loaded !"); if (!e.IsLoaded)
{
Functions.WriteLogFile($"[CMD] Command from file [{e.PluginName}] has been successfully loaded !");
}
} }
private void OnEventLoaded(LoaderArgs e) private void OnEventLoaded(LoaderArgs e)

View File

@@ -0,0 +1,91 @@
using PluginManager.Others;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
namespace PluginManager.Online.Helpers
{
public class VersionString
{
public int PackageVersionID;
public int PackageMainVersion;
public int PackageCheckVersion;
public VersionString(string version)
{
string[] data = version.Split('.');
try
{
PackageVersionID = int.Parse(data[0]);
PackageMainVersion = int.Parse(data[1]);
PackageCheckVersion = int.Parse(data[2]);
}
catch (Exception ex)
{
throw new Exception("Failed to write Version", ex);
}
}
#region operators
public static bool operator >(VersionString s1, VersionString s2)
{
if (s1.PackageVersionID > s2.PackageVersionID) return true;
if (s1.PackageVersionID == s2.PackageVersionID)
{
if (s1.PackageMainVersion > s2.PackageMainVersion) return true;
if (s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion > s2.PackageCheckVersion) return true;
}
return false;
}
public static bool operator <(VersionString s1, VersionString s2) => !(s1 > s2) && s1 != s2;
public static bool operator ==(VersionString s1, VersionString s2)
{
if (s1.PackageVersionID == s2.PackageVersionID && s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion == s2.PackageCheckVersion) return true;
return false;
}
public static bool operator !=(VersionString s1, VersionString s2) => !(s1 == s2);
public static bool operator <=(VersionString s1, VersionString s2) => (s1 < s2 || s1 == s2);
public static bool operator >=(VersionString s1, VersionString s2) => (s1 > s2 || s1 == s2);
#endregion
public override string ToString()
{
return "{PackageID: " + PackageVersionID + ", PackageVersion: " + PackageMainVersion + ", PackageCheckVersion: " + PackageCheckVersion + "}";
}
public string ToShortString()
{
if (PackageVersionID == 0 && PackageCheckVersion == 0 && PackageMainVersion == 0)
return "Unknown";
return $"{PackageVersionID}.{PackageMainVersion}.{PackageCheckVersion}";
}
public static VersionString? GetVersionOfPackage(string pakName)
{
if (!Config.PluginVersionsContainsKey(pakName))
return null;
return new VersionString(Config.GetPluginVersion(pakName));
}
public static async Task<VersionString?> GetVersionOfPackageFromWeb(string pakName)
{
string url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions";
List<string> data = await ServerCom.ReadTextFromURL(url);
string? version = (from item in data
where !item.StartsWith("#") && item.StartsWith(pakName)
select item.Split(',')[1]).FirstOrDefault();
if (version == default || version == null) return null;
return new VersionString(version);
}
}
}

View File

@@ -1,7 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using PluginManager.Online.Helpers;
using PluginManager.Others; using PluginManager.Others;
using OperatingSystem = PluginManager.Others.OperatingSystem; using OperatingSystem = PluginManager.Others.OperatingSystem;
namespace PluginManager.Online; namespace PluginManager.Online;
@@ -30,14 +33,14 @@ public class PluginsManager
{ {
try try
{ {
var list = await ServerCom.ReadTextFromURL(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[]>();
var op = Functions.GetOperatingSystem(); var op = Functions.GetOperatingSystem();
var len = lines.Length; var len = lines.Length;
string[] titles = { "Name", "Description", "Plugin Type", "Libraries", "Installed" }; string[] titles = { "Name", "Description", "Type", "Version", "Installed" };
data.Add(new[] { "-", "-", "-", "-", "-" }); data.Add(new[] { "-", "-", "-", "-", "-" });
data.Add(titles); data.Add(titles);
data.Add(new[] { "-", "-", "-", "-", "-" }); data.Add(new[] { "-", "-", "-", "-", "-" });
@@ -54,11 +57,7 @@ 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 VersionString.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0")).ToShortString();
display[3] = ((await ServerCom.ReadTextFromURL(content[5])).Count + 1).ToString();
else
display[3] = "1";
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
@@ -73,8 +72,7 @@ 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 VersionString.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0")).ToShortString();
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
@@ -86,7 +84,7 @@ public class PluginsManager
data.Add(new[] { "-", "-", "-", "-", "-" }); data.Add(new[] { "-", "-", "-", "-", "-" });
Console_Utilities.FormatAndAlignTable(data); Console_Utilities.FormatAndAlignTable(data, TableFormat.CENTER_EACH_COLUMN_BASED);
} }
catch (Exception exception) catch (Exception exception)
{ {
@@ -104,9 +102,9 @@ public class PluginsManager
{ {
try try
{ {
var list = await ServerCom.ReadTextFromURL(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++)
{ {
var contents = lines[i].Split(','); var contents = lines[i].Split(',');

View File

@@ -51,10 +51,10 @@ namespace PluginManager.Online
/// <returns></returns> /// <returns></returns>
public static async Task DownloadFileAsync(string URL, string location) public static async Task DownloadFileAsync(string URL, string location)
{ {
bool isDownloading = true; bool isDownloading = true;
float c_progress = 0; float c_progress = 0;
Console_Utilities.ProgressBar pbar = new Console_Utilities.ProgressBar { Max = 100f, NoColor = true }; Console_Utilities.ProgressBar pbar = new Console_Utilities.ProgressBar(ProgressBarType.NORMAL) { Max = 100f, NoColor = true };
IProgress<float> progress = new Progress<float>(percent => { c_progress = percent; }); IProgress<float> progress = new Progress<float>(percent => { c_progress = percent; });
@@ -79,5 +79,11 @@ namespace PluginManager.Online
pbar.Update(100f); pbar.Update(100f);
isDownloading = false; isDownloading = false;
} }
public static async Task DownloadFileNoProgressAsync(string URL, string location)
{
IProgress<float> progress = new Progress<float>();
await DownloadFileAsync(URL, location, progress);
}
} }
} }

View File

@@ -0,0 +1,51 @@
using PluginManager.Items;
using PluginManager.Online.Helpers;
using PluginManager.Others;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace PluginManager.Online.Updates
{
public class PluginUpdater
{
public static async Task<bool> CheckForUpdates(string pakName)
{
try
{
var webV = await VersionString.GetVersionOfPackageFromWeb(pakName);
var local = VersionString.GetVersionOfPackage(pakName);
if (local is null) return true;
if (webV is null) return false;
if (webV == local) return false;
if (webV > local) return true;
}
catch (Exception ex) { Console.WriteLine(ex.Message); }
return false;
}
public static async Task<Update> DownloadUpdateInfo(string pakName)
{
string url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions";
List<string> info = await ServerCom.ReadTextFromURL(url);
VersionString? version = await VersionString.GetVersionOfPackageFromWeb(pakName);
if (version is null) return Update.Empty;
Update update = new Update(pakName, string.Join('\n', info), version);
return update;
}
public static async Task Download(string pakName)
{
Console_Utilities.WriteColorText("An update was found for &g" + pakName + "&c. Version: &r" + (await VersionString.GetVersionOfPackageFromWeb(pakName))?.ToShortString() + "&c. Current Version: &y" + VersionString.GetVersionOfPackage(pakName)?.ToShortString());
await ConsoleCommandsHandler.ExecuteCommad("dwplug " + pakName);
}
}
}

View File

@@ -0,0 +1,36 @@
using PluginManager.Online.Helpers;
namespace PluginManager.Online.Updates
{
public class Update
{
public static Update Empty = new Update(null, null, null);
public string pakName;
public string UpdateMessage;
public VersionString newVersion;
private bool isEmpty;
public Update(string pakName, string updateMessage, VersionString newVersion)
{
this.pakName = pakName;
UpdateMessage = updateMessage;
this.newVersion = newVersion;
if (pakName is null && updateMessage is null && newVersion is null)
isEmpty = true;
}
public override string ToString()
{
if (isEmpty)
throw new System.Exception("The update is EMPTY. Can not print information about an empty update !");
return $"Package Name: {this.pakName}\n" +
$"Update Message: {UpdateMessage}\n" +
$"Version: {newVersion.ToString()}";
}
}
}

View File

@@ -1,7 +1,7 @@
using Discord; using Discord;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace PluginManager.Others namespace PluginManager.Others
{ {
@@ -32,16 +32,84 @@ namespace PluginManager.Others
/// </summary> /// </summary>
public class ProgressBar public class ProgressBar
{ {
public float Max { get; init; } public ProgressBar(ProgressBarType type)
public ConsoleColor Color { get; init; } {
public bool NoColor { get; init; } this.type = type;
}
public float Max { get; init; }
public ConsoleColor Color { get; init; }
public bool NoColor { get; init; }
public ProgressBarType type { get; set; }
public void Update(float progress, double speed = -1, string? unit = null) private int BarLength = 32;
private int position = 1;
private bool positive = true;
private bool isRunning;
public async void Start()
{
if (type != ProgressBarType.NO_END)
throw new Exception("Only NO_END progress bar can use this method");
if (isRunning)
throw new Exception("This progress bar is already running");
isRunning = true;
while (isRunning)
{
UpdateNoEnd();
await System.Threading.Tasks.Task.Delay(100);
}
}
public void Stop()
{
if (type != ProgressBarType.NO_END)
throw new Exception("Only NO_END progress bar can use this method");
if (!isRunning)
throw new Exception("Can not stop a progressbar that did not start");
isRunning = false;
}
public void Update(float progress)
{
switch (type)
{
case ProgressBarType.NORMAL:
UpdateNormal(progress);
return;
case ProgressBarType.NO_END:
if (progress <= 99.9f)
UpdateNoEnd();
return;
default:
return;
}
}
private void UpdateNoEnd()
{ {
Console.CursorLeft = 0; Console.CursorLeft = 0;
Console.Write("["); Console.Write("[");
Console.CursorLeft = 32; for (int i = 1; i <= position; i++)
Console.Write(" ");
Console.Write("<==()==>");
position += positive ? 1 : -1;
for (int i = position; i <= BarLength - 1 - (positive ? 0 : 2); i++)
Console.Write(" ");
Console.Write("]");
if (position == BarLength - 1 || position == 1)
positive = !positive;
}
private void UpdateNormal(float progress)
{
Console.CursorLeft = 0;
Console.Write("[");
Console.CursorLeft = BarLength;
Console.Write("]"); Console.Write("]");
Console.CursorLeft = 1; Console.CursorLeft = 1;
float onechunk = 30.0f / Max; float onechunk = 30.0f / Max;
@@ -51,28 +119,23 @@ namespace PluginManager.Others
for (int i = 0; i < onechunk * progress; i++) for (int i = 0; i < onechunk * progress; i++)
{ {
Console.BackgroundColor = NoColor ? ConsoleColor.Black : this.Color; Console.BackgroundColor = NoColor ? ConsoleColor.Black : this.Color;
Console.CursorLeft = position++; Console.CursorLeft = position++;
Console.Write("#"); Console.Write("#");
} }
for (int i = position; i <= 31; i++) for (int i = position; i < BarLength; i++)
{ {
Console.BackgroundColor = NoColor ? ConsoleColor.Black : ConsoleColor.DarkGray; Console.BackgroundColor = NoColor ? ConsoleColor.Black : ConsoleColor.DarkGray;
Console.CursorLeft = position++; Console.CursorLeft = position++;
Console.Write(" "); Console.Write(" ");
} }
Console.CursorLeft = 35; Console.CursorLeft = BarLength + 4;
Console.BackgroundColor = ConsoleColor.Black; Console.BackgroundColor = ConsoleColor.Black;
if (speed is -1 || unit == null) if (progress.CanAproximateTo(Max))
{ Console.Write(progress + " % ✓");
if (progress.CanAproximateTo(Max))
Console.Write(progress + " % ✓");
else
Console.Write(MathF.Round(progress, 2) + " % ");
}
else else
Console.Write(progress + $"{speed} {unit}/s "); Console.Write(MathF.Round(progress, 2) + " % ");
} }
} }
@@ -84,13 +147,13 @@ namespace PluginManager.Others
/// 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, TableFormat format = TableFormat.CENTER_EACH_COLUMN_BASED) public static void FormatAndAlignTable(List<string[]> data, TableFormat format)
{ {
if (format == TableFormat.CENTER_EACH_COLUMN_BASED) if (format == TableFormat.CENTER_EACH_COLUMN_BASED)
{ {
char tableLine = '-'; char tableLine = '-';
char tableCross = '+'; char tableCross = '+';
char tableWall = '|'; char tableWall = '|';
int[] len = new int[data[0].Length]; int[] len = new int[data[0].Length];
foreach (var line in data) foreach (var line in data)
@@ -196,8 +259,8 @@ namespace PluginManager.Others
if (format == TableFormat.DEFAULT) if (format == TableFormat.DEFAULT)
{ {
int[] widths = new int[data[0].Length]; int[] widths = new int[data[0].Length];
int space_between_columns = int.Parse(Config.GetValue<Dictionary<string, string>>("TableVariables")?["DefaultSpace"]!); int space_between_columns = int.Parse(Config.GetValue<Dictionary<string, string>>("TableVariables")?["DefaultSpace"]!);
for (int i = 0; i < data.Count; i++) for (int i = 0; i < data.Count; i++)
{ {
for (int j = 0; j < data[i].Length; j++) for (int j = 0; j < data[i].Length; j++)
@@ -230,7 +293,7 @@ namespace PluginManager.Others
public static void WriteColorText(string text, bool appendNewLineAtEnd = true) public static void WriteColorText(string text, bool appendNewLineAtEnd = true)
{ {
ConsoleColor initialForeGround = Console.ForegroundColor; ConsoleColor initialForeGround = Console.ForegroundColor;
char[] input = text.ToCharArray(); char[] input = text.ToCharArray();
for (int i = 0; i < input.Length; i++) for (int i = 0; i < input.Length; i++)
{ {
if (input[i] == Config.GetValue<char>("ColorPrefix")) if (input[i] == Config.GetValue<char>("ColorPrefix"))

View File

@@ -31,3 +31,6 @@ public enum PluginType { Command, Event, Unknown }
public enum UnzipProgressType { PercentageFromNumberOfFiles, PercentageFromTotalSize } public enum UnzipProgressType { PercentageFromNumberOfFiles, PercentageFromTotalSize }
public enum TableFormat { CENTER_EACH_COLUMN_BASED, CENTER_OVERALL_LENGTH, DEFAULT } public enum TableFormat { CENTER_EACH_COLUMN_BASED, CENTER_OVERALL_LENGTH, DEFAULT }
public enum SaveType { NORMAL, BACKUP }
public enum ProgressBarType { NORMAL, NO_END }

View File

@@ -26,17 +26,17 @@ namespace PluginManager.Others
/// <summary> /// <summary>
/// The location for all logs /// The location for all logs
/// </summary> /// </summary>
public static readonly string logFolder = @"./Output/Logs/"; public static readonly string logFolder = @"./Data/Output/Logs/";
/// <summary> /// <summary>
/// The location for all errors /// The location for all errors
/// </summary> /// </summary>
public static readonly string errFolder = @"./Output/Errors/"; public static readonly string errFolder = @"./Data/Output/Errors/";
/// <summary> /// <summary>
/// Archives folder /// Archives folder
/// </summary> /// </summary>
public static readonly string pakFolder = @"./Data/Resources/PAK/"; public static readonly string pakFolder = @"./Data/PAKS/";
/// <summary> /// <summary>
/// Beta testing folder /// Beta testing folder
@@ -50,15 +50,19 @@ 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 Stream? ReadFromPakAsync(string FileName, string archFile) public static async Task<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 !");
using ZipArchive archive = ZipFile.OpenRead(archFile); using ZipArchive archive = ZipFile.OpenRead(archFile);
ZipArchiveEntry? entry = archive.GetEntry(FileName); ZipArchiveEntry? entry = archive.GetEntry(FileName);
return entry?.Open(); if (entry is null) return Stream.Null;
MemoryStream stream = new MemoryStream();
await (entry?.Open()!).CopyToAsync(stream);
return stream;
} }
/// <summary> /// <summary>
@@ -68,7 +72,7 @@ namespace PluginManager.Others
public static void WriteLogFile(string LogMessage) public static void WriteLogFile(string LogMessage)
{ {
string logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt"; string logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
if (!Directory.Exists(logFolder)) Directory.CreateDirectory(logFolder); Directory.CreateDirectory(logFolder);
File.AppendAllText(logsPath, LogMessage + " \n"); File.AppendAllText(logsPath, LogMessage + " \n");
} }
@@ -79,7 +83,7 @@ namespace PluginManager.Others
public static void WriteErrFile(string ErrMessage) public static void WriteErrFile(string ErrMessage)
{ {
string errPath = errFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt"; string errPath = errFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
if (!Directory.Exists(errFolder)) Directory.CreateDirectory(errFolder); Directory.CreateDirectory(errFolder);
File.AppendAllText(errPath, ErrMessage + " \n"); File.AppendAllText(errPath, ErrMessage + " \n");
} }
@@ -91,8 +95,8 @@ namespace PluginManager.Others
/// <returns>A string built based on the array</returns> /// <returns>A string built based on the array</returns>
public static string MergeStrings(this string[] s, int indexToStart) public static string MergeStrings(this string[] s, int indexToStart)
{ {
string r = ""; string r = "";
int len = s.Length; int len = s.Length;
if (len <= indexToStart) return ""; if (len <= indexToStart) return "";
for (int i = indexToStart; i < len - 1; ++i) for (int i = indexToStart; i < len - 1; ++i)
{ {
@@ -142,9 +146,9 @@ namespace PluginManager.Others
if (!stream.CanRead) throw new InvalidOperationException("The stream is not readable."); if (!stream.CanRead) throw new InvalidOperationException("The stream is not readable.");
if (!destination.CanWrite) throw new ArgumentException("Destination stream is not writable", nameof(destination)); if (!destination.CanWrite) throw new ArgumentException("Destination stream is not writable", nameof(destination));
byte[] buffer = new byte[bufferSize]; byte[] buffer = new byte[bufferSize];
long totalBytesRead = 0; long totalBytesRead = 0;
int bytesRead; int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
{ {
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
@@ -164,18 +168,16 @@ namespace PluginManager.Others
/// <returns></returns> /// <returns></returns>
public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress, UnzipProgressType type) public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress, UnzipProgressType type)
{ {
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder); Directory.CreateDirectory(folder);
using (ZipArchive archive = ZipFile.OpenRead(zip)) using (ZipArchive archive = ZipFile.OpenRead(zip))
{ {
if (type == UnzipProgressType.PercentageFromNumberOfFiles) if (type == UnzipProgressType.PercentageFromNumberOfFiles)
{ {
int totalZIPFiles = archive.Entries.Count(); int totalZIPFiles = archive.Entries.Count();
int currentZIPFile = 0; int currentZIPFile = 0;
foreach (ZipArchiveEntry entry in archive.Entries) foreach (ZipArchiveEntry entry in archive.Entries)
{ {
if (entry.FullName.EndsWith("/")) if (entry.FullName.EndsWith("/")) // it is a folder
Directory.CreateDirectory(Path.Combine(folder, entry.FullName)); Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
else else
@@ -190,7 +192,8 @@ namespace PluginManager.Others
currentZIPFile++; currentZIPFile++;
await Task.Delay(10); await Task.Delay(10);
progress.Report((float)currentZIPFile / totalZIPFiles * 100); if (progress != null)
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
} }
} }
else if (type == UnzipProgressType.PercentageFromTotalSize) else if (type == UnzipProgressType.PercentageFromTotalSize)
@@ -220,7 +223,8 @@ namespace PluginManager.Others
} }
await Task.Delay(10); await Task.Delay(10);
progress.Report((float)currentSize / zipSize * 100); if (progress != null)
progress.Report((float)currentSize / zipSize * 100);
} }
} }
} }
@@ -261,9 +265,9 @@ namespace PluginManager.Others
/// <returns></returns> /// <returns></returns>
public static async Task SaveToJsonFile<T>(string file, T Data) public static async Task SaveToJsonFile<T>(string file, T Data)
{ {
var s = File.OpenWrite(file); MemoryStream str = new MemoryStream();
await JsonSerializer.SerializeAsync(s, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true }); await JsonSerializer.SerializeAsync(str, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
s.Close(); await File.WriteAllBytesAsync(file, str.ToArray());
} }
/// <summary> /// <summary>
@@ -276,8 +280,7 @@ namespace PluginManager.Others
{ {
Stream text; Stream text;
if (File.Exists(input)) if (File.Exists(input))
text = File.Open(input, FileMode.OpenOrCreate); text = new MemoryStream(await File.ReadAllBytesAsync(input));
else else
text = new MemoryStream(Encoding.ASCII.GetBytes(input)); text = new MemoryStream(Encoding.ASCII.GetBytes(input));
text.Position = 0; text.Position = 0;
@@ -335,7 +338,7 @@ namespace PluginManager.Others
using (MD5 md5 = MD5.Create()) using (MD5 md5 = MD5.Create())
{ {
byte[] inputBytes = Encoding.ASCII.GetBytes(input); byte[] inputBytes = Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes); byte[] hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes); return Convert.ToHexString(hashBytes);
} }
} }

View File

@@ -16,10 +16,6 @@ Plugin Types:
1. Commands 1. Commands
2. Events 2. Events
Project Structure
![Image](../../blob/gh-pages/Pictures/architecture2.png)
### How to create a plugin ### How to create a plugin
First of all, Create a new project (class library) in Visual Studio. First of all, Create a new project (class library) in Visual Studio.

57
Roles/AddRole.cs Normal file
View File

@@ -0,0 +1,57 @@
using System.IO.Compression;
using System.Runtime.CompilerServices;
using Discord;
using Discord.Commands;
using Discord.Rest;
using Discord.WebSocket;
using Microsoft.Win32.SafeHandles;
using PluginManager.Interfaces;
using PluginManager.Others;
using Roles.Internals;
namespace Roles
{
public class AddRole : DBCommand
{
public string Command => "addrole";
public List<string> Aliases => new() { "ar", "addr", "roleadd" };
public string Description => "Role options";
public string Usage => "addrole [user1] [user2] ... [role1] [role2] ...";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => true;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
if (message.MentionedUsers.Count == 0 || message.MentionedRoles.Count == 0)
{
await context.Channel.SendMessageAsync($"Invalid invocation\nUsage:{Usage}");
return;
}
try
{
var users = message.MentionedUsers;
var roles = message.MentionedRoles as IEnumerable<IRole>;
foreach (var user in users)
{
SocketGuildUser? usr = context.Client.GetUser(user.Username, user.Discriminator) as SocketGuildUser;
if (usr is null)
throw new Exception("User is null");
await usr.AddRolesAsync(roles);
}
}
catch (Exception ex)
{
await context.Channel.SendMessageAsync(ex.Message);
}
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using PluginManager.Others;
namespace Roles.Internals
{
internal static class RoleManagement
{
internal static async void AddRole(this SocketGuildUser user, string roleName)
{
string role = roleName;
IRole? r = user.Guild.Roles.FirstOrDefault(rl => rl.Name == role || rl.Mention == role);
if (r is null)
throw new Exception("The role does not exist");
try
{
await user.AddRoleAsync(r);
}
catch (Exception ex)
{
if (ex.Message.Contains("Permission", StringComparison.CurrentCultureIgnoreCase))
throw new Exception("Insufficient permissions");
}
}
internal static async void AddRole(this SocketGuildUser user, IRole role)
{
try
{
await user.AddRoleAsync(role);
}
catch (Exception ex)
{
if (ex.Message.Contains("Permission", StringComparison.CurrentCultureIgnoreCase))
throw new Exception("Insufficient permissions");
}
}
internal static async void AddRoles(this SocketGuildUser user, string[] roleNames)
{
foreach (string rolename in roleNames)
{
string roleName = rolename;
IRole? r = user.Guild.Roles.FirstOrDefault(rl => rl.Name == roleName || rl.Mention == roleName);
if (r is null)
throw new Exception("The role does not exist");
try
{
await user.AddRoleAsync(r);
}
catch (Exception ex)
{
if (ex.Message.Contains("Permission", StringComparison.CurrentCultureIgnoreCase))
throw new Exception("Insufficient permissions");
}
}
}
internal static async void AddRoles(this SocketGuildUser user, IEnumerable<IRole> roles)
{
try
{
await user.AddRolesAsync(roles);
}
catch (Exception ex)
{
if (ex.Message.Contains("Permission", StringComparison.CurrentCultureIgnoreCase))
throw new Exception("Insufficient permissions");
}
}
}
}

13
Roles/Roles.csproj Normal file
View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj" />
</ItemGroup>
</Project>

View File

@@ -21,6 +21,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EVE_LevelingSystem", "EVE_L
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CMD_LevelingSystem", "CMD_LevelingSystem\CMD_LevelingSystem.csproj", "{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CMD_LevelingSystem", "CMD_LevelingSystem\CMD_LevelingSystem.csproj", "{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roles", "Roles\Roles.csproj", "{954F2AA9-6624-4554-946D-0F17B84487C3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Others", "Others", "{727BBA0B-9114-4BC8-B9A8-3F461449A564}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Updater", "Updater\Updater.csproj", "{24616F7E-E2E9-45A3-8A44-AB51FCD2D525}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -51,6 +57,14 @@ Global
{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}.Release|Any CPU.ActiveCfg = Release|Any CPU {1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}.Release|Any CPU.Build.0 = Release|Any CPU {1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}.Release|Any CPU.Build.0 = Release|Any CPU
{954F2AA9-6624-4554-946D-0F17B84487C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{954F2AA9-6624-4554-946D-0F17B84487C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{954F2AA9-6624-4554-946D-0F17B84487C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{954F2AA9-6624-4554-946D-0F17B84487C3}.Release|Any CPU.Build.0 = Release|Any CPU
{24616F7E-E2E9-45A3-8A44-AB51FCD2D525}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{24616F7E-E2E9-45A3-8A44-AB51FCD2D525}.Debug|Any CPU.Build.0 = Debug|Any CPU
{24616F7E-E2E9-45A3-8A44-AB51FCD2D525}.Release|Any CPU.ActiveCfg = Release|Any CPU
{24616F7E-E2E9-45A3-8A44-AB51FCD2D525}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -62,6 +76,9 @@ Global
{B1B4976E-5112-4217-B57B-3A03C5207B6E} = {449FA364-0B72-43FF-B3A3-806E2916200E} {B1B4976E-5112-4217-B57B-3A03C5207B6E} = {449FA364-0B72-43FF-B3A3-806E2916200E}
{EEC445DC-0C4B-43EA-8694-606BA0390B77} = {A290C028-77C4-4D1D-AB43-DDFE6ABD9012} {EEC445DC-0C4B-43EA-8694-606BA0390B77} = {A290C028-77C4-4D1D-AB43-DDFE6ABD9012}
{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9} = {449FA364-0B72-43FF-B3A3-806E2916200E} {1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9} = {449FA364-0B72-43FF-B3A3-806E2916200E}
{954F2AA9-6624-4554-946D-0F17B84487C3} = {449FA364-0B72-43FF-B3A3-806E2916200E}
{727BBA0B-9114-4BC8-B9A8-3F461449A564} = {1862ABD5-7C30-4F15-A561-45AC8A9CA10E}
{24616F7E-E2E9-45A3-8A44-AB51FCD2D525} = {727BBA0B-9114-4BC8-B9A8-3F461449A564}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF} SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}

454
Updater/.gitignore vendored Normal file
View File

@@ -0,0 +1,454 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# JetBrains Rider
.idea/
*.sln.iml
##
## Visual Studio Code
##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

7
Updater/App.axaml Normal file
View File

@@ -0,0 +1,7 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Updater.App">
<Application.Styles>
<FluentTheme Mode="Dark"/>
</Application.Styles>
</Application>

24
Updater/App.axaml.cs Normal file
View File

@@ -0,0 +1,24 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace Updater
{
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow() { Width = 250, Height = 50 };
}
base.OnFrameworkInitializationCompleted();
}
}
}

12
Updater/MainWindow.axaml Normal file
View File

@@ -0,0 +1,12 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="250" d:DesignHeight="50"
x:Class="Updater.MainWindow"
Title="Updater">
<StackPanel Margin="0">
<Label Content="Updating ... "/>
<ProgressBar x:Class="Updater.MainWindow" x:Name="progressBar1" IsIndeterminate="True" />
</StackPanel>
</Window>

View File

@@ -0,0 +1,36 @@
using Avalonia.Controls;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Threading.Tasks;
namespace Updater
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Activated += (sender, e) => FormActive();
}
public async void FormActive()
{
if (Program.Command != "/update")
return;
await Task.Delay(3000);
WebClient c = new WebClient();
Directory.CreateDirectory("./Updater/Downloads");
await c.DownloadFileTaskAsync(Program.Link, "./Updater/Downloads/Update.zip");
await Task.Run(() => ZipFile.ExtractToDirectory("./Updater/Downloads/Update.zip", Program.Location, true));
Process.Start(Program.AppToOpen);
File.Delete("./Updater/Downloads/Update.zip");
Environment.Exit(0);
}
}
}

34
Updater/Program.cs Normal file
View File

@@ -0,0 +1,34 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using System;
namespace Updater
{
internal class Program
{
public static string Command, Link, AppToOpen, Location;
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args)
{
Command = args[0];
Link = args[1];
AppToOpen = args[2];
Location = string.Join(' ', args, 3, args.Length - 3);
BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
}
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.LogToTrace();
}
}

27
Updater/Updater.csproj Normal file
View File

@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<!--Avalonia doesen't support TrimMode=link currently,but we are working on that https://github.com/AvaloniaUI/Avalonia/issues/6892 -->
<TrimMode>copyused</TrimMode>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
</PropertyGroup>
<ItemGroup>
<None Remove=".gitignore" />
</ItemGroup>
<ItemGroup>
<!--This helps with theme dll-s trimming.
If you will publish your application in self-contained mode with p:PublishTrimmed=true and it will use Fluent theme Default theme will be trimmed from the output and vice versa.
https://github.com/AvaloniaUI/Avalonia/issues/5593 -->
<TrimmableAssembly Include="Avalonia.Themes.Fluent" />
<TrimmableAssembly Include="Avalonia.Themes.Default" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.18" />
<PackageReference Include="Avalonia.Desktop" Version="0.10.18" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="0.10.18" />
<PackageReference Include="XamlNameReferenceGenerator" Version="1.3.4" />
</ItemGroup>
</Project>