Compare commits
21 Commits
v1.0.6-pre
...
v1.0.0.11
| Author | SHA1 | Date | |
|---|---|---|---|
| 68a83b052a | |||
| d689eee7fa | |||
| f6442af30c | |||
| b98f57fcf8 | |||
| 77aad985fa | |||
|
|
f8ebf76f92 | ||
| 6da9828e5c | |||
| 3ba45790e7 | |||
| e440e97948 | |||
|
|
938c73c810 | ||
| a8520c8c96 | |||
| debdc58646 | |||
| 8b36c086ef | |||
| 1f5e5d0611 | |||
| bbc1c601c9 | |||
| 5ab3195956 | |||
| 1f1983480a | |||
| 2fcd86cf12 | |||
| 2c83d00c00 | |||
|
|
ccac0ca6d0 | ||
| 4c9c7410f0 |
6
.idea/.idea.SethDiscordBot/.idea/projectSettingsUpdater.xml
generated
Normal file
6
.idea/.idea.SethDiscordBot/.idea/projectSettingsUpdater.xml
generated
Normal 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>
|
||||
107
.idea/.idea.SethDiscordBot/.idea/workspace.xml
generated
Normal file
107
.idea/.idea.SethDiscordBot/.idea/workspace.xml
generated
Normal 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.
Binary file not shown.
Binary file not shown.
BIN
BUILDS/net6.0/Plugins/Commands/Roles.dll
Normal file
BIN
BUILDS/net6.0/Plugins/Commands/Roles.dll
Normal file
Binary file not shown.
Binary file not shown.
@@ -11,6 +11,8 @@ internal class Level : DBCommand
|
||||
{
|
||||
public string Command => "level";
|
||||
|
||||
public List<string> Aliases => new() { "lvl" };
|
||||
|
||||
public string Description => "Display tour current level";
|
||||
|
||||
public string Usage => "level";
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using PluginManager.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal class Echo : DBCommand
|
||||
{
|
||||
public string Command => "echo";
|
||||
|
||||
public List<string> Aliases => null;
|
||||
|
||||
public string Description => "Replay with the same message";
|
||||
|
||||
public string Usage => "echo [message]";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using PluginManager.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CMD_Utils;
|
||||
|
||||
@@ -8,6 +9,8 @@ internal class FlipCoin : DBCommand
|
||||
{
|
||||
public string Command => "flip";
|
||||
|
||||
public List<string> Aliases => null;
|
||||
|
||||
public string Description => "Flip a coin";
|
||||
|
||||
public string Usage => "flip";
|
||||
|
||||
@@ -11,6 +11,8 @@ public class Poll : DBCommand
|
||||
{
|
||||
public string Command => "poll";
|
||||
|
||||
public List<string> Aliases => null;
|
||||
|
||||
public string Description => "Create a poll with options";
|
||||
|
||||
public string Usage => "poll [This-is-question] [This-is-answer-1] [This-is-answer-2] ... ";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Discord.Commands;
|
||||
using System.Collections.Generic;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using PluginManager.Interfaces;
|
||||
|
||||
@@ -6,6 +7,8 @@ public class Random : DBCommand
|
||||
{
|
||||
public string Command => "random";
|
||||
|
||||
public List<string> Aliases => new() { "rnd" };
|
||||
|
||||
public string Description => "random number between number1 and number2";
|
||||
|
||||
public string Usage => "random [number1] [number2]";
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Discord;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using PluginManager.Interfaces;
|
||||
@@ -17,15 +19,17 @@ internal class Help : DBCommand
|
||||
/// </summary>
|
||||
public string Command => "help";
|
||||
|
||||
public List<string> Aliases => null;
|
||||
|
||||
/// <summary>
|
||||
/// Command Description
|
||||
/// </summary>
|
||||
public string Description => "This command allows you to check all loadded commands";
|
||||
public string Description => "This command allows you to check all loaded commands";
|
||||
|
||||
/// <summary>
|
||||
/// Command usage
|
||||
/// </summary>
|
||||
public string Usage => "help";
|
||||
public string Usage => "help <command>";
|
||||
|
||||
/// <summary>
|
||||
/// 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)
|
||||
{
|
||||
var e = GenerateHelpCommand(item);
|
||||
if (e != null)
|
||||
context.Channel.SendMessageAsync(embed: e.Build());
|
||||
else
|
||||
if (e is null)
|
||||
context.Channel.SendMessageAsync("Unknown Command " + item);
|
||||
else
|
||||
context.Channel.SendMessageAsync(embed: e.Build());
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -74,10 +78,12 @@ internal class Help : DBCommand
|
||||
|
||||
foreach (var cmd in PluginLoader.Commands!)
|
||||
{
|
||||
if (cmd.canUseDM) DMCommands += cmd.Command + " ";
|
||||
if (cmd.canUseDM)
|
||||
DMCommands += cmd.Command + " ";
|
||||
if (cmd.requireAdmin)
|
||||
adminCommands += cmd.Command + " ";
|
||||
else if (cmd.canUseServer) normalCommands += cmd.Command + " ";
|
||||
adminCommands += cmd.Command + " ";
|
||||
if (cmd.canUseServer)
|
||||
normalCommands += cmd.Command + " ";
|
||||
}
|
||||
|
||||
embedBuilder.AddField("Admin Commands", adminCommands);
|
||||
@@ -89,11 +95,14 @@ internal class Help : DBCommand
|
||||
private EmbedBuilder GenerateHelpCommand(string command)
|
||||
{
|
||||
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;
|
||||
|
||||
embedBuilder.AddField("Usage", cmd.Usage);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Discord.WebSocket;
|
||||
using PluginManager.Interfaces;
|
||||
@@ -17,6 +18,8 @@ internal class Restart : DBCommand
|
||||
/// </summary>
|
||||
public string Command => "restart";
|
||||
|
||||
public List<string> Aliases => null;
|
||||
|
||||
/// <summary>
|
||||
/// Command Description
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
@@ -14,6 +15,8 @@ internal class Settings : DBCommand
|
||||
/// </summary>
|
||||
public string Command => "set";
|
||||
|
||||
public List<string> Aliases => null;
|
||||
|
||||
/// <summary>
|
||||
/// Command Description
|
||||
/// </summary>
|
||||
|
||||
@@ -60,7 +60,9 @@ internal class Boot
|
||||
/// <returns>Task</returns>
|
||||
public async Task Awake()
|
||||
{
|
||||
client = new DiscordSocketClient();
|
||||
DiscordSocketConfig config = new DiscordSocketConfig { AlwaysDownloadUsers = true };
|
||||
|
||||
client = new DiscordSocketClient(config);
|
||||
service = new CommandService();
|
||||
|
||||
CommonTasks();
|
||||
|
||||
@@ -47,13 +47,16 @@ internal class CommandHandler
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Message as SocketUserMessage == null) return;
|
||||
if (Message as SocketUserMessage == null)
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
@@ -63,17 +66,14 @@ internal class CommandHandler
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.Author.IsBot) return;
|
||||
if (message.Author.IsBot)
|
||||
return;
|
||||
|
||||
var context = new SocketCommandContext(client, message);
|
||||
|
||||
await commandService.ExecuteAsync(
|
||||
context,
|
||||
argPos,
|
||||
null
|
||||
);
|
||||
await commandService.ExecuteAsync(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)
|
||||
|
||||
@@ -8,15 +8,15 @@
|
||||
<StartupObject />
|
||||
<SignAssembly>False</SignAssembly>
|
||||
<IsPublishable>True</IsPublishable>
|
||||
<AssemblyVersion>1.0.0.1</AssemblyVersion>
|
||||
<AssemblyVersion>1.0.0.10</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebugType>none</DebugType>
|
||||
<DebugType>none</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<DebugType>none</DebugType>
|
||||
<DebugType>none</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.WebSocket;
|
||||
|
||||
using Discord;
|
||||
|
||||
using DiscordBot.Discord.Core;
|
||||
|
||||
using PluginManager;
|
||||
using PluginManager.Interfaces;
|
||||
using PluginManager.Items;
|
||||
using PluginManager.Online;
|
||||
using PluginManager.Others;
|
||||
@@ -21,6 +22,7 @@ public class Program
|
||||
{
|
||||
private static bool loadPluginsOnStartup;
|
||||
private static bool listPluginsAtStartup;
|
||||
private static ConsoleCommandsHandler consoleCommandsHandler;
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
@@ -29,41 +31,74 @@ public class Program
|
||||
[Obsolete]
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Loading resources ...");
|
||||
|
||||
Directory.CreateDirectory("./Data/Resources");
|
||||
Directory.CreateDirectory("./Data/Plugins/Commands");
|
||||
Directory.CreateDirectory("./Data/Plugins/Events");
|
||||
PreLoadComponents().Wait();
|
||||
|
||||
if (!Config.ContainsKey("token") || Config.GetValue<string>("token") == null || Config.GetValue<string>("token")?.Length != 70)
|
||||
do
|
||||
{
|
||||
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.WriteLine("Invalid token");
|
||||
if (!Config.ContainsKey("ServerID"))
|
||||
{
|
||||
|
||||
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))
|
||||
return;
|
||||
Config.AddValueToVariables("prefix", prefix.ToString(), false);
|
||||
}
|
||||
Console.WriteLine("Please enter the server ID: ");
|
||||
Console_Utilities.WriteColorText("You can find it in the Server Settings at &r\"Widget\"&c section");
|
||||
Console.WriteLine("Example: 1234567890123456789");
|
||||
|
||||
if (!Config.ContainsKey("prefix") || Config.GetValue<string>("prefix") == default)
|
||||
{
|
||||
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 == ' ') return;
|
||||
Config.AddValueToVariables("prefix", prefix.ToString(), false);
|
||||
}
|
||||
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 > ");
|
||||
ConsoleKeyInfo key = Console.ReadKey();
|
||||
if (key.Key == ConsoleKey.Enter)
|
||||
Config.AddValueToVariables("ServerID", "null", false);
|
||||
else
|
||||
{
|
||||
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();
|
||||
}
|
||||
@@ -74,27 +109,27 @@ public class Program
|
||||
/// <param name="discordbooter">The discord booter used to start the application</param>
|
||||
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 (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs");
|
||||
|
||||
Config.SaveConfig();
|
||||
#endif
|
||||
Config.SaveConfig(SaveType.NORMAL).Wait();
|
||||
|
||||
while (true)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
|
||||
var cmd = Console.ReadLine();
|
||||
if (!consoleCommandsHandler.HandleCommand(cmd!
|
||||
#if DEBUG
|
||||
Console_Utilities.WriteColorText("&rSethBot (&yDEBUG&r) &c> ", 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);
|
||||
, false
|
||||
#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.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 ============================");
|
||||
|
||||
try
|
||||
@@ -135,7 +178,6 @@ public class Program
|
||||
#endif
|
||||
|
||||
var prefix = Config.GetValue<string>("prefix");
|
||||
|
||||
var discordbooter = new Boot(token, prefix);
|
||||
await discordbooter.Awake();
|
||||
return discordbooter;
|
||||
@@ -153,7 +195,7 @@ public class Program
|
||||
/// <param name="d">Directory path</param>
|
||||
private static Task ClearFolder(string d)
|
||||
{
|
||||
var files = Directory.GetFiles(d);
|
||||
var files = Directory.GetFiles(d);
|
||||
var fileNumb = files.Length;
|
||||
for (var i = 0; i < fileNumb; i++)
|
||||
{
|
||||
@@ -170,11 +212,12 @@ public class Program
|
||||
/// <param name="args">The arguments</param>
|
||||
private static async Task HandleInput(string[] args)
|
||||
{
|
||||
|
||||
var len = args.Length;
|
||||
|
||||
if (len == 3 && args[0] == "/download")
|
||||
{
|
||||
var url = args[1];
|
||||
var url = args[1];
|
||||
var location = args[2];
|
||||
|
||||
await ServerCom.DownloadFileAsync(url, location);
|
||||
@@ -182,6 +225,23 @@ public class Program
|
||||
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 (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"))
|
||||
{
|
||||
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();
|
||||
return;
|
||||
}
|
||||
@@ -238,7 +330,7 @@ public class Program
|
||||
case "--reset-logs":
|
||||
await ClearFolder("./Output/Logs");
|
||||
await ClearFolder("./Output/Errors");
|
||||
Console.WriteLine("Successfully cleard logs folder");
|
||||
Console.WriteLine("Successfully clear logs folder");
|
||||
break;
|
||||
case "--exit":
|
||||
case "exit":
|
||||
@@ -254,6 +346,8 @@ public class Program
|
||||
|
||||
private static async Task PreLoadComponents()
|
||||
{
|
||||
Console_Utilities.ProgressBar main = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
|
||||
main.Start();
|
||||
await Config.LoadConfig();
|
||||
if (Config.ContainsKey("DeleteLogsAtStartup"))
|
||||
if (Config.GetValue<bool>("DeleteLogsAtStartup"))
|
||||
@@ -264,9 +358,9 @@ public class Program
|
||||
Config.PluginConfig.Load();
|
||||
|
||||
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
|
||||
Config.SetValue("Version", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
||||
Config.SetValue("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
||||
|
||||
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");
|
||||
main.Stop();
|
||||
foreach (var key in onlineSettingsList)
|
||||
{
|
||||
if (key.Length <= 3 || !key.Contains(' ')) continue;
|
||||
@@ -295,42 +393,45 @@ public class Program
|
||||
string newVersion = s[1];
|
||||
if (!newVersion.Equals(Config.GetValue<string>("Version")))
|
||||
{
|
||||
Console.WriteLine("A new version has been released on github page.");
|
||||
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)
|
||||
if (Functions.GetOperatingSystem() == PluginManager.Others.OperatingSystem.WINDOWS)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
waitTime--;
|
||||
Console.SetCursorPosition("The bot will start in ".Length, Console.CursorTop);
|
||||
Console.Write(" ");
|
||||
Console.SetCursorPosition("The bot will start in ".Length, Console.CursorTop);
|
||||
Console.Write(waitTime + " seconds");
|
||||
|
||||
string url = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0.zip";
|
||||
//string url2 = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}-preview/net6.0.zip";
|
||||
Process.Start("./Updater/Updater.exe", $"/update {url} ./DiscordBot.exe ./");
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Console_Utilities.Initialize();
|
||||
|
||||
Config.SaveConfig();
|
||||
Console_Utilities.Initialize();
|
||||
await Config.SaveConfig(SaveType.NORMAL);
|
||||
Console.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
|
||||
using EVE_LevelingSystem.LevelingSystemCore;
|
||||
|
||||
using PluginManager;
|
||||
using PluginManager.Interfaces;
|
||||
using PluginManager.Others;
|
||||
@@ -9,8 +11,8 @@ namespace EVE_LevelingSystem
|
||||
{
|
||||
internal class Level : DBEvent
|
||||
{
|
||||
public string name => "Leveling System Event Handler";
|
||||
public string description => "The Leveling System Event Handler";
|
||||
public string name => "Leveling System Event Handler";
|
||||
public string description => "The Leveling System Event Handler";
|
||||
|
||||
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;
|
||||
string userID = arg.Author.Id.ToString();
|
||||
User user;
|
||||
User user;
|
||||
if (File.Exists($"{Config.GetValue<string>("LevelingSystemPath")}/{userID}.dat"))
|
||||
{
|
||||
user = await Functions.ConvertFromJson<User>(Config.GetValue<string>("LevelingSystemPath")! + $"/{userID}.dat");
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PluginManager;
|
||||
|
||||
namespace EVE_LevelingSystem.LevelingSystemCore
|
||||
@@ -18,7 +19,7 @@ namespace EVE_LevelingSystem.LevelingSystemCore
|
||||
|
||||
internal static void LevelUp(this User user)
|
||||
{
|
||||
user.CurrentEXP = 0;
|
||||
user.CurrentEXP = 0;
|
||||
user.RequiredEXPToLevelUp = GetNextLevelRequiredEXP(user.CurrentLevel);
|
||||
user.CurrentLevel++;
|
||||
}
|
||||
@@ -26,15 +27,15 @@ namespace EVE_LevelingSystem.LevelingSystemCore
|
||||
internal static bool AddEXP(this User user)
|
||||
{
|
||||
if (OnWaitingList.Contains(user.user.userID.ToString())) return false;
|
||||
Random r = new Random();
|
||||
int exp = r.Next(2, 12);
|
||||
Int64 userXP = user.CurrentEXP;
|
||||
Int64 reqEXP = user.RequiredEXPToLevelUp;
|
||||
Random r = new Random();
|
||||
int exp = r.Next(Level.globalSettings.MinEXP, Level.globalSettings.MaxEXP + 1);
|
||||
Int64 userXP = user.CurrentEXP;
|
||||
Int64 reqEXP = user.RequiredEXPToLevelUp;
|
||||
if (userXP + exp >= reqEXP)
|
||||
{
|
||||
user.LevelUp();
|
||||
user.CurrentEXP = exp - (reqEXP - userXP);
|
||||
Console.WriteLine("Level up");
|
||||
//Console.WriteLine("Level up");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -49,7 +50,7 @@ namespace EVE_LevelingSystem.LevelingSystemCore
|
||||
Thread.Sleep(60000 * minutesToWait);
|
||||
OnWaitingList.Remove(user.user.userID.ToString());
|
||||
}
|
||||
);
|
||||
).Start();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -9,5 +9,7 @@ namespace EVE_LevelingSystem
|
||||
public class Settings
|
||||
{
|
||||
public int TimeToWaitBetweenMessages { get; set; }
|
||||
public int MinEXP { get; set; }
|
||||
public int MaxEXP { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AngleSharp.Dom;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -11,20 +12,20 @@ namespace MusicCommands
|
||||
internal class AudioFile
|
||||
{
|
||||
internal string Name { get; set; }
|
||||
internal string Url { get; set; }
|
||||
internal string Url { get; set; }
|
||||
|
||||
internal AudioFile(string name, string url)
|
||||
{
|
||||
Name = name;
|
||||
Url = url;
|
||||
Url = url;
|
||||
}
|
||||
|
||||
internal async Task DownloadAudioFile()
|
||||
{
|
||||
Process proc = new Process();
|
||||
proc.StartInfo.FileName = "MusicDownloader.exe";
|
||||
proc.StartInfo.Arguments = $"{Url},{Name}";
|
||||
proc.StartInfo.UseShellExecute = false;
|
||||
proc.StartInfo.FileName = "MusicDownloader";
|
||||
proc.StartInfo.Arguments = $"{Url},{Name}";
|
||||
proc.StartInfo.UseShellExecute = false;
|
||||
proc.StartInfo.RedirectStandardOutput = true;
|
||||
|
||||
proc.Start();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Discord.Commands;
|
||||
using System.Collections.Generic;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using PluginManager.Interfaces;
|
||||
|
||||
@@ -8,6 +9,8 @@ internal class Leave : DBCommand
|
||||
{
|
||||
public string Command => "leave";
|
||||
|
||||
public List<string> Aliases => null;
|
||||
|
||||
public string Description => "Leave the voice channel";
|
||||
|
||||
public string Usage => "leave";
|
||||
|
||||
@@ -5,7 +5,8 @@ namespace MusicCommands;
|
||||
|
||||
internal class MusicPlayer
|
||||
{
|
||||
private Stream outputStream { get; }
|
||||
private Stream outputStream { get; }
|
||||
internal AudioFile NowPlaying = null;
|
||||
|
||||
internal bool isPlaying, isPaused;
|
||||
|
||||
@@ -14,9 +15,10 @@ internal class MusicPlayer
|
||||
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)
|
||||
{
|
||||
if (isPaused)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Discord.Commands;
|
||||
using System.Collections.Generic;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using PluginManager.Interfaces;
|
||||
|
||||
@@ -8,6 +9,8 @@ internal class Pause : DBCommand
|
||||
{
|
||||
public string Command => "pause";
|
||||
|
||||
public List<string> Aliases => null;
|
||||
|
||||
public string Description => "Pause/Unpause the music that is currently running";
|
||||
|
||||
public string Usage => "pause";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Discord;
|
||||
@@ -14,6 +15,8 @@ internal class Play : DBCommand
|
||||
{
|
||||
public string Command => "play";
|
||||
|
||||
public List<string> Aliases => new() { "p" };
|
||||
|
||||
public string Description => "Play music from a file";
|
||||
|
||||
public string Usage => "play [name/url]";
|
||||
@@ -69,11 +72,11 @@ internal class Play : DBCommand
|
||||
|
||||
if (Data.MusicPlayer is not null)
|
||||
{
|
||||
await context.Channel.SendMessageAsync("Enqueued your request");
|
||||
await context.Channel.SendMessageAsync("Queued your request: " + splitted.MergeStrings(1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (false);
|
||||
while (false); // run only one time !
|
||||
|
||||
|
||||
Data.voiceChannel = (context.User as IGuildUser)?.VoiceChannel;
|
||||
@@ -93,15 +96,14 @@ internal class Play : DBCommand
|
||||
|
||||
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)
|
||||
{
|
||||
var nowPlaying = Data.Playlist.GetNextSong;
|
||||
using (var ffmpeg = CreateStream(nowPlaying.Name))
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ namespace MusicCommands
|
||||
{
|
||||
public string Command => "skip";
|
||||
|
||||
public List<string> Aliases => null;
|
||||
|
||||
public string Description => "skip the music that is currently running";
|
||||
|
||||
public string Usage => "skip";
|
||||
@@ -25,7 +27,16 @@ namespace MusicCommands
|
||||
|
||||
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;
|
||||
message.Channel.SendMessageAsync($"You have skipped {loadedSong.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ namespace MusicCommands
|
||||
{
|
||||
public class queue : DBCommand
|
||||
{
|
||||
public string Command => "queue";
|
||||
public string Command => "queue";
|
||||
public List<string> Aliases => new() { "q" };
|
||||
|
||||
public string Description => "check queue";
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@ namespace PluginManager
|
||||
{
|
||||
internal class AppConfig
|
||||
{
|
||||
public string UpdaterVersion { get; set; }
|
||||
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
|
||||
@@ -29,27 +31,27 @@ namespace PluginManager
|
||||
|
||||
private static void LoadCommands()
|
||||
{
|
||||
string cmd_path = "./Data/Plugins/Commands/";
|
||||
string[] files = Directory.GetFiles(cmd_path, $"*.{Loaders.PluginLoader.pluginCMDExtension}", SearchOption.AllDirectories);
|
||||
string cmd_path = "./Data/Plugins/Commands/";
|
||||
string[] files = Directory.GetFiles(cmd_path, $"*.{Loaders.PluginLoader.pluginCMDExtension}", SearchOption.AllDirectories);
|
||||
foreach (var file in files)
|
||||
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadEvents()
|
||||
{
|
||||
string eve_path = "./Data/Plugins/Events/";
|
||||
string[] files = Directory.GetFiles(eve_path, $"*.{Loaders.PluginLoader.pluginEVEExtension}", SearchOption.AllDirectories);
|
||||
string eve_path = "./Data/Plugins/Events/";
|
||||
string[] files = Directory.GetFiles(eve_path, $"*.{Loaders.PluginLoader.pluginEVEExtension}", SearchOption.AllDirectories);
|
||||
foreach (var file in files)
|
||||
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
|
||||
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -57,9 +59,8 @@ namespace PluginManager
|
||||
public static bool Contains(string pluginName)
|
||||
{
|
||||
foreach (var tuple in InstalledPlugins)
|
||||
{
|
||||
if (tuple.Item1 == pluginName) return true;
|
||||
}
|
||||
if (tuple.Item1 == pluginName)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -67,9 +68,9 @@ namespace PluginManager
|
||||
public static PluginType GetPluginType(string pluginName)
|
||||
{
|
||||
foreach (var tuple in InstalledPlugins)
|
||||
{
|
||||
if (tuple.Item1 == pluginName) return tuple.Item2;
|
||||
}
|
||||
if (tuple.Item1 == pluginName)
|
||||
return tuple.Item2;
|
||||
|
||||
|
||||
return PluginType.Unknown;
|
||||
}
|
||||
@@ -77,6 +78,21 @@ namespace PluginManager
|
||||
|
||||
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)
|
||||
{
|
||||
if (value == null)
|
||||
@@ -88,7 +104,7 @@ namespace PluginManager
|
||||
if (isProtected && key != "Version")
|
||||
appConfig.ProtectedKeyWords!.Add(key);
|
||||
|
||||
SaveConfig();
|
||||
SaveConfig(SaveType.NORMAL);
|
||||
}
|
||||
|
||||
public static Type GetVariableType(string value)
|
||||
@@ -156,7 +172,7 @@ namespace PluginManager
|
||||
throw new Exception("Key is protected");
|
||||
|
||||
appConfig.ApplicationVariables[key] = JsonSerializer.SerializeToElement(value);
|
||||
SaveConfig();
|
||||
SaveConfig(SaveType.NORMAL);
|
||||
}
|
||||
|
||||
public static void RemoveKey(string key)
|
||||
@@ -165,13 +181,24 @@ namespace PluginManager
|
||||
throw new Exception("Key is protected");
|
||||
appConfig!.ApplicationVariables!.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";
|
||||
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!);
|
||||
if (type == SaveType.NORMAL)
|
||||
{
|
||||
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()
|
||||
@@ -179,15 +206,28 @@ namespace PluginManager
|
||||
string path = Functions.dataFolder + "config.json";
|
||||
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.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>() };
|
||||
appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>(), PluginVersions = new Dictionary<string, string>(), UpdaterVersion = "-1" };
|
||||
}
|
||||
|
||||
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!);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Discord.Commands;
|
||||
using System.Collections.Generic;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace PluginManager.Interfaces;
|
||||
@@ -11,6 +12,11 @@ public interface DBCommand
|
||||
/// </summary>
|
||||
string Command { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Command aliases. Users may use this to execute the command
|
||||
/// </summary>
|
||||
List<string>? Aliases { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Command description
|
||||
/// </summary>
|
||||
@@ -44,8 +50,5 @@ public interface DBCommand
|
||||
/// <param name="message">The message that the user types</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>
|
||||
void Execute(SocketCommandContext context,
|
||||
SocketMessage message,
|
||||
DiscordSocketClient client,
|
||||
bool isDM);
|
||||
void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM);
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ public class Command
|
||||
|
||||
public class ConsoleCommand
|
||||
{
|
||||
public string CommandName { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Usage { get; set; }
|
||||
public Action<string[]> Action { get; set; }
|
||||
public string CommandName { get; init; }
|
||||
public string Description { get; init; }
|
||||
public string Usage { get; init; }
|
||||
public Action<string[]> Action { get; init; }
|
||||
}
|
||||
@@ -1,21 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Discord.WebSocket;
|
||||
|
||||
using PluginManager.Interfaces;
|
||||
using PluginManager.Loaders;
|
||||
using PluginManager.Online;
|
||||
using PluginManager.Online.Helpers;
|
||||
using PluginManager.Online.Updates;
|
||||
using PluginManager.Others;
|
||||
|
||||
namespace PluginManager.Items;
|
||||
|
||||
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 readonly DiscordSocketClient? client;
|
||||
private readonly DiscordSocketClient? client;
|
||||
|
||||
|
||||
private static bool isDownloading = false;
|
||||
private static bool pluginsLoaded = false;
|
||||
|
||||
public ConsoleCommandsHandler(DiscordSocketClient client)
|
||||
{
|
||||
@@ -26,7 +38,7 @@ public class ConsoleCommandsHandler
|
||||
|
||||
private void InitializeBasicCommands()
|
||||
{
|
||||
var pluginsLoaded = false;
|
||||
|
||||
commandList.Clear();
|
||||
|
||||
AddCommand("help", "Show help", "help <command>", args =>
|
||||
@@ -70,30 +82,48 @@ public class ConsoleCommandsHandler
|
||||
if (pluginsLoaded)
|
||||
return;
|
||||
var loader = new PluginLoader(client!);
|
||||
ConsoleColor cc = Console.ForegroundColor;
|
||||
loader.onCMDLoad += (name, typeName, success, exception) =>
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
|
||||
if (name == null || name.Length < 2)
|
||||
name = typeName;
|
||||
if (success)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine("[CMD] Successfully loaded command : " + name);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
|
||||
Console.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message);
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
}
|
||||
Console.ForegroundColor = cc;
|
||||
};
|
||||
loader.onEVELoad += (name, typeName, success, exception) =>
|
||||
{
|
||||
if (name == null || name.Length < 2)
|
||||
name = typeName;
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
|
||||
if (success)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine("[EVENT] Successfully loaded event : " + name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message);
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
}
|
||||
Console.ForegroundColor = cc;
|
||||
};
|
||||
|
||||
loader.LoadPlugins();
|
||||
Console.ForegroundColor = cc;
|
||||
pluginsLoaded = true;
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
@@ -101,8 +131,10 @@ public class ConsoleCommandsHandler
|
||||
|
||||
AddCommand("dwplug", "download plugin", "dwplug [name]", async args =>
|
||||
{
|
||||
isDownloading = true;
|
||||
if (args.Length == 1)
|
||||
{
|
||||
isDownloading = false;
|
||||
Console.WriteLine("Please specify plugin name");
|
||||
return;
|
||||
}
|
||||
@@ -116,10 +148,11 @@ public class ConsoleCommandsHandler
|
||||
{
|
||||
if (name == "")
|
||||
{
|
||||
isDownloading = false;
|
||||
Console_Utilities.WriteColorText("Name is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
isDownloading = false;
|
||||
Console_Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" + " Use &glistplugs &ccommand to display all available plugins !");
|
||||
return;
|
||||
}
|
||||
@@ -154,34 +187,17 @@ public class ConsoleCommandsHandler
|
||||
continue;
|
||||
var split = line.Split(',');
|
||||
Console.WriteLine($"\nDownloading item: {split[1]}");
|
||||
if (File.Exists("./" + split[1])) File.Delete("./" + split[1]);
|
||||
await ServerCom.DownloadFileAsync(split[0], "./" + split[1]);
|
||||
Console.WriteLine();
|
||||
|
||||
if (split[0].EndsWith(".zip") || split[0].EndsWith(".pak") || split[0].EndsWith(".pkg"))
|
||||
{
|
||||
Console.WriteLine($"Extracting {split[1]}");
|
||||
var proc = 0f;
|
||||
var isExtracting = true;
|
||||
var bar = new Console_Utilities.ProgressBar { Max = 100f, Color = ConsoleColor.Green };
|
||||
|
||||
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($"Extracting {split[1]} ...");
|
||||
var bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END) { Max = 100f, Color = ConsoleColor.Green };
|
||||
bar.Start();
|
||||
await Functions.ExtractArchive("./" + split[1], "./", null, UnzipProgressType.PercentageFromTotalSize);
|
||||
bar.Stop();
|
||||
Console.WriteLine("\n");
|
||||
File.Delete("./" + split[1]);
|
||||
}
|
||||
@@ -189,6 +205,12 @@ public class ConsoleCommandsHandler
|
||||
|
||||
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)
|
||||
return;
|
||||
var key = args[1];
|
||||
var value = args[2];
|
||||
var key = args[1];
|
||||
var value = args[2];
|
||||
var isReadOnly = args[3].Equals("true", StringComparison.CurrentCultureIgnoreCase);
|
||||
|
||||
try
|
||||
@@ -237,14 +259,142 @@ public class ConsoleCommandsHandler
|
||||
{
|
||||
if (client is null)
|
||||
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.DisposeAsync();
|
||||
Config.SaveConfig();
|
||||
Console.WriteLine("Bot is closing in 2 seconds ! Please wait to save data !");
|
||||
await Task.Delay(2000);
|
||||
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
|
||||
commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName));
|
||||
}
|
||||
@@ -268,7 +418,7 @@ public class ConsoleCommandsHandler
|
||||
|
||||
public static bool CommandExists(string command)
|
||||
{
|
||||
return !(GetCommand(command) is null);
|
||||
return GetCommand(command) is not null;
|
||||
}
|
||||
|
||||
public static ConsoleCommand? GetCommand(string command)
|
||||
@@ -276,8 +426,24 @@ public class ConsoleCommandsHandler
|
||||
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)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
var args = command.Split(' ');
|
||||
foreach (var item in commandList.ToList())
|
||||
if (item.CommandName == args[0])
|
||||
@@ -292,6 +458,7 @@ public class ConsoleCommandsHandler
|
||||
|
||||
Console.WriteLine();
|
||||
item.Action(args);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,29 +3,32 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PluginManager.Online.Updates;
|
||||
using PluginManager.Others;
|
||||
|
||||
namespace PluginManager.Loaders;
|
||||
|
||||
internal class LoaderArgs : EventArgs
|
||||
{
|
||||
internal string? PluginName { get; init; }
|
||||
internal string? TypeName { get; init; }
|
||||
internal bool IsLoaded { get; init; }
|
||||
internal Exception? Exception { get; init; }
|
||||
internal object? Plugin { get; init; }
|
||||
internal string? PluginName { get; init; }
|
||||
internal string? TypeName { get; init; }
|
||||
internal bool IsLoaded { get; init; }
|
||||
internal Exception? Exception { get; init; }
|
||||
internal object? Plugin { get; init; }
|
||||
}
|
||||
|
||||
internal class Loader<T>
|
||||
{
|
||||
internal Loader(string path, string extension)
|
||||
{
|
||||
this.path = path;
|
||||
this.path = path;
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
|
||||
private string path { get; }
|
||||
private string path { get; }
|
||||
private string extension { get; }
|
||||
|
||||
|
||||
@@ -49,16 +52,17 @@ internal class Loader<T>
|
||||
var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories);
|
||||
foreach (var file in files)
|
||||
{
|
||||
|
||||
Assembly.LoadFrom(file);
|
||||
if (FileLoaded != null)
|
||||
{
|
||||
var args = new LoaderArgs
|
||||
{
|
||||
Exception = null,
|
||||
TypeName = nameof(T),
|
||||
IsLoaded = false,
|
||||
PluginName = file,
|
||||
Plugin = null
|
||||
Exception = null,
|
||||
TypeName = nameof(T),
|
||||
IsLoaded = false,
|
||||
PluginName = new FileInfo(file).Name.Split('.')[0],
|
||||
Plugin = null
|
||||
};
|
||||
FileLoaded.Invoke(args);
|
||||
}
|
||||
@@ -83,13 +87,13 @@ internal class Loader<T>
|
||||
|
||||
if (PluginLoaded != null)
|
||||
PluginLoaded.Invoke(new LoaderArgs
|
||||
{
|
||||
Exception = null,
|
||||
IsLoaded = true,
|
||||
PluginName = type.FullName,
|
||||
TypeName = nameof(T),
|
||||
Plugin = plugin
|
||||
}
|
||||
{
|
||||
Exception = null,
|
||||
IsLoaded = true,
|
||||
PluginName = type.FullName,
|
||||
TypeName = nameof(T),
|
||||
Plugin = plugin
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Discord.WebSocket;
|
||||
|
||||
using PluginManager.Interfaces;
|
||||
using PluginManager.Online.Helpers;
|
||||
using PluginManager.Online.Updates;
|
||||
using PluginManager.Others;
|
||||
|
||||
namespace PluginManager.Loaders;
|
||||
@@ -15,8 +23,8 @@ public class PluginLoader
|
||||
private const string pluginCMDFolder = @"./Data/Plugins/Commands/";
|
||||
private const string pluginEVEFolder = @"./Data/Plugins/Events/";
|
||||
|
||||
internal const string pluginCMDExtension = "dll";
|
||||
internal const string pluginEVEExtension = "dll";
|
||||
internal const string pluginCMDExtension = "dll";
|
||||
internal const string pluginEVEExtension = "dll";
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
/// <summary>
|
||||
@@ -52,35 +60,79 @@ public class PluginLoader
|
||||
/// <summary>
|
||||
/// The main mathod that is called to load all events
|
||||
/// </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>();
|
||||
Events = new List<DBEvent>();
|
||||
Events = new List<DBEvent>();
|
||||
|
||||
Functions.WriteLogFile("Starting plugin loader ... Client: " + _client.CurrentUser.Username);
|
||||
Console.WriteLine("Loading plugins");
|
||||
|
||||
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;
|
||||
|
||||
eventsLoader.FileLoaded += EventFileLoaded;
|
||||
eventsLoader.FileLoaded += EventFileLoaded;
|
||||
eventsLoader.PluginLoaded += OnEventLoaded;
|
||||
|
||||
Commands = commandsLoader.Load();
|
||||
Events = eventsLoader.Load();
|
||||
Events = eventsLoader.Load();
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
||||
91
PluginManager/Online/Helpers/VersionString.cs
Normal file
91
PluginManager/Online/Helpers/VersionString.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PluginManager.Online.Helpers;
|
||||
using PluginManager.Others;
|
||||
|
||||
using OperatingSystem = PluginManager.Others.OperatingSystem;
|
||||
|
||||
namespace PluginManager.Online;
|
||||
@@ -30,14 +33,14 @@ public class PluginsManager
|
||||
{
|
||||
try
|
||||
{
|
||||
var list = await ServerCom.ReadTextFromURL(PluginsLink);
|
||||
var list = await ServerCom.ReadTextFromURL(PluginsLink);
|
||||
var lines = list.ToArray();
|
||||
|
||||
var data = new List<string[]>();
|
||||
var op = Functions.GetOperatingSystem();
|
||||
var op = Functions.GetOperatingSystem();
|
||||
|
||||
var len = lines.Length;
|
||||
string[] titles = { "Name", "Description", "Plugin Type", "Libraries", "Installed" };
|
||||
var len = lines.Length;
|
||||
string[] titles = { "Name", "Description", "Type", "Version", "Installed" };
|
||||
data.Add(new[] { "-", "-", "-", "-", "-" });
|
||||
data.Add(titles);
|
||||
data.Add(new[] { "-", "-", "-", "-", "-" });
|
||||
@@ -54,11 +57,7 @@ public class PluginsManager
|
||||
display[0] = content[0];
|
||||
display[1] = content[1];
|
||||
display[2] = content[2];
|
||||
if (content.Length == 6 && (content[5] != null || content[5].Length > 2))
|
||||
display[3] = ((await ServerCom.ReadTextFromURL(content[5])).Count + 1).ToString();
|
||||
|
||||
else
|
||||
display[3] = "1";
|
||||
display[3] = (await VersionString.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0")).ToShortString();
|
||||
if (Config.PluginConfig.Contains(content[0]) || Config.PluginConfig.Contains(content[0]))
|
||||
display[4] = "✓";
|
||||
else
|
||||
@@ -73,8 +72,7 @@ public class PluginsManager
|
||||
display[0] = content[0];
|
||||
display[1] = content[1];
|
||||
display[2] = content[2];
|
||||
if (content.Length == 6 && (content[5] != null || content[5].Length > 2))
|
||||
display[3] = ((await ServerCom.ReadTextFromURL(content[5])).Count + 1).ToString();
|
||||
display[3] = (await VersionString.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0")).ToShortString();
|
||||
if (Config.PluginConfig.Contains(content[0]) || Config.PluginConfig.Contains(content[0]))
|
||||
display[4] = "✓";
|
||||
else
|
||||
@@ -86,7 +84,7 @@ public class PluginsManager
|
||||
|
||||
data.Add(new[] { "-", "-", "-", "-", "-" });
|
||||
|
||||
Console_Utilities.FormatAndAlignTable(data);
|
||||
Console_Utilities.FormatAndAlignTable(data, TableFormat.CENTER_EACH_COLUMN_BASED);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@@ -104,9 +102,9 @@ public class PluginsManager
|
||||
{
|
||||
try
|
||||
{
|
||||
var list = await ServerCom.ReadTextFromURL(PluginsLink);
|
||||
var list = await ServerCom.ReadTextFromURL(PluginsLink);
|
||||
var lines = list.ToArray();
|
||||
var len = lines.Length;
|
||||
var len = lines.Length;
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var contents = lines[i].Split(',');
|
||||
|
||||
@@ -51,10 +51,10 @@ namespace PluginManager.Online
|
||||
/// <returns></returns>
|
||||
public static async Task DownloadFileAsync(string URL, string location)
|
||||
{
|
||||
bool isDownloading = true;
|
||||
float c_progress = 0;
|
||||
bool isDownloading = true;
|
||||
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; });
|
||||
|
||||
@@ -79,5 +79,11 @@ namespace PluginManager.Online
|
||||
pbar.Update(100f);
|
||||
isDownloading = false;
|
||||
}
|
||||
public static async Task DownloadFileNoProgressAsync(string URL, string location)
|
||||
{
|
||||
IProgress<float> progress = new Progress<float>();
|
||||
await DownloadFileAsync(URL, location, progress);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
51
PluginManager/Online/Updates/PluginUpdater.cs
Normal file
51
PluginManager/Online/Updates/PluginUpdater.cs
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
36
PluginManager/Online/Updates/Update.cs
Normal file
36
PluginManager/Online/Updates/Update.cs
Normal 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()}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Discord;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PluginManager.Others
|
||||
{
|
||||
@@ -32,16 +32,84 @@ namespace PluginManager.Others
|
||||
/// </summary>
|
||||
public class ProgressBar
|
||||
{
|
||||
public float Max { get; init; }
|
||||
public ConsoleColor Color { get; init; }
|
||||
public bool NoColor { get; init; }
|
||||
public ProgressBar(ProgressBarType type)
|
||||
{
|
||||
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.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.CursorLeft = 1;
|
||||
float onechunk = 30.0f / Max;
|
||||
@@ -51,28 +119,23 @@ namespace PluginManager.Others
|
||||
for (int i = 0; i < onechunk * progress; i++)
|
||||
{
|
||||
Console.BackgroundColor = NoColor ? ConsoleColor.Black : this.Color;
|
||||
Console.CursorLeft = position++;
|
||||
Console.CursorLeft = position++;
|
||||
Console.Write("#");
|
||||
}
|
||||
|
||||
for (int i = position; i <= 31; i++)
|
||||
for (int i = position; i < BarLength; i++)
|
||||
{
|
||||
Console.BackgroundColor = NoColor ? ConsoleColor.Black : ConsoleColor.DarkGray;
|
||||
Console.CursorLeft = position++;
|
||||
Console.CursorLeft = position++;
|
||||
Console.Write(" ");
|
||||
}
|
||||
|
||||
Console.CursorLeft = 35;
|
||||
Console.CursorLeft = BarLength + 4;
|
||||
Console.BackgroundColor = ConsoleColor.Black;
|
||||
if (speed is -1 || unit == null)
|
||||
{
|
||||
if (progress.CanAproximateTo(Max))
|
||||
Console.Write(progress + " % ✓");
|
||||
else
|
||||
Console.Write(MathF.Round(progress, 2) + " % ");
|
||||
}
|
||||
if (progress.CanAproximateTo(Max))
|
||||
Console.Write(progress + " % ✓");
|
||||
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
|
||||
/// </summary>
|
||||
/// <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)
|
||||
{
|
||||
char tableLine = '-';
|
||||
char tableLine = '-';
|
||||
char tableCross = '+';
|
||||
char tableWall = '|';
|
||||
char tableWall = '|';
|
||||
|
||||
int[] len = new int[data[0].Length];
|
||||
foreach (var line in data)
|
||||
@@ -196,8 +259,8 @@ namespace PluginManager.Others
|
||||
|
||||
if (format == TableFormat.DEFAULT)
|
||||
{
|
||||
int[] widths = new int[data[0].Length];
|
||||
int space_between_columns = int.Parse(Config.GetValue<Dictionary<string, string>>("TableVariables")?["DefaultSpace"]!);
|
||||
int[] widths = new int[data[0].Length];
|
||||
int space_between_columns = int.Parse(Config.GetValue<Dictionary<string, string>>("TableVariables")?["DefaultSpace"]!);
|
||||
for (int i = 0; i < data.Count; i++)
|
||||
{
|
||||
for (int j = 0; j < data[i].Length; j++)
|
||||
@@ -230,7 +293,7 @@ namespace PluginManager.Others
|
||||
public static void WriteColorText(string text, bool appendNewLineAtEnd = true)
|
||||
{
|
||||
ConsoleColor initialForeGround = Console.ForegroundColor;
|
||||
char[] input = text.ToCharArray();
|
||||
char[] input = text.ToCharArray();
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
if (input[i] == Config.GetValue<char>("ColorPrefix"))
|
||||
|
||||
@@ -31,3 +31,6 @@ public enum PluginType { Command, Event, Unknown }
|
||||
public enum UnzipProgressType { PercentageFromNumberOfFiles, PercentageFromTotalSize }
|
||||
|
||||
public enum TableFormat { CENTER_EACH_COLUMN_BASED, CENTER_OVERALL_LENGTH, DEFAULT }
|
||||
|
||||
public enum SaveType { NORMAL, BACKUP }
|
||||
public enum ProgressBarType { NORMAL, NO_END }
|
||||
@@ -26,17 +26,17 @@ namespace PluginManager.Others
|
||||
/// <summary>
|
||||
/// The location for all logs
|
||||
/// </summary>
|
||||
public static readonly string logFolder = @"./Output/Logs/";
|
||||
public static readonly string logFolder = @"./Data/Output/Logs/";
|
||||
|
||||
/// <summary>
|
||||
/// The location for all errors
|
||||
/// </summary>
|
||||
public static readonly string errFolder = @"./Output/Errors/";
|
||||
public static readonly string errFolder = @"./Data/Output/Errors/";
|
||||
|
||||
/// <summary>
|
||||
/// Archives folder
|
||||
/// </summary>
|
||||
public static readonly string pakFolder = @"./Data/Resources/PAK/";
|
||||
public static readonly string pakFolder = @"./Data/PAKS/";
|
||||
|
||||
/// <summary>
|
||||
/// 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="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>
|
||||
public static Stream? ReadFromPakAsync(string FileName, string archFile)
|
||||
public static async Task<Stream?> ReadFromPakAsync(string FileName, string archFile)
|
||||
{
|
||||
archFile = pakFolder + archFile;
|
||||
Directory.CreateDirectory(pakFolder);
|
||||
if (!File.Exists(archFile)) throw new FileNotFoundException("Failed to load file !");
|
||||
|
||||
using ZipArchive archive = ZipFile.OpenRead(archFile);
|
||||
ZipArchiveEntry? entry = archive.GetEntry(FileName);
|
||||
return entry?.Open();
|
||||
ZipArchiveEntry? entry = archive.GetEntry(FileName);
|
||||
if (entry is null) return Stream.Null;
|
||||
MemoryStream stream = new MemoryStream();
|
||||
await (entry?.Open()!).CopyToAsync(stream);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,7 +72,7 @@ namespace PluginManager.Others
|
||||
public static void WriteLogFile(string LogMessage)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -79,7 +83,7 @@ namespace PluginManager.Others
|
||||
public static void WriteErrFile(string ErrMessage)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -91,8 +95,8 @@ namespace PluginManager.Others
|
||||
/// <returns>A string built based on the array</returns>
|
||||
public static string MergeStrings(this string[] s, int indexToStart)
|
||||
{
|
||||
string r = "";
|
||||
int len = s.Length;
|
||||
string r = "";
|
||||
int len = s.Length;
|
||||
if (len <= indexToStart) return "";
|
||||
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 (!destination.CanWrite) throw new ArgumentException("Destination stream is not writable", nameof(destination));
|
||||
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
long totalBytesRead = 0;
|
||||
int bytesRead;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
long totalBytesRead = 0;
|
||||
int bytesRead;
|
||||
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
|
||||
{
|
||||
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
|
||||
@@ -164,18 +168,16 @@ namespace PluginManager.Others
|
||||
/// <returns></returns>
|
||||
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))
|
||||
{
|
||||
if (type == UnzipProgressType.PercentageFromNumberOfFiles)
|
||||
{
|
||||
int totalZIPFiles = archive.Entries.Count();
|
||||
int totalZIPFiles = archive.Entries.Count();
|
||||
int currentZIPFile = 0;
|
||||
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));
|
||||
|
||||
else
|
||||
@@ -190,7 +192,8 @@ namespace PluginManager.Others
|
||||
|
||||
currentZIPFile++;
|
||||
await Task.Delay(10);
|
||||
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
|
||||
if (progress != null)
|
||||
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
|
||||
}
|
||||
}
|
||||
else if (type == UnzipProgressType.PercentageFromTotalSize)
|
||||
@@ -220,7 +223,8 @@ namespace PluginManager.Others
|
||||
}
|
||||
|
||||
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>
|
||||
public static async Task SaveToJsonFile<T>(string file, T Data)
|
||||
{
|
||||
var s = File.OpenWrite(file);
|
||||
await JsonSerializer.SerializeAsync(s, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
|
||||
s.Close();
|
||||
MemoryStream str = new MemoryStream();
|
||||
await JsonSerializer.SerializeAsync(str, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
|
||||
await File.WriteAllBytesAsync(file, str.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -276,8 +280,7 @@ namespace PluginManager.Others
|
||||
{
|
||||
Stream text;
|
||||
if (File.Exists(input))
|
||||
text = File.Open(input, FileMode.OpenOrCreate);
|
||||
|
||||
text = new MemoryStream(await File.ReadAllBytesAsync(input));
|
||||
else
|
||||
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
|
||||
text.Position = 0;
|
||||
@@ -335,7 +338,7 @@ namespace PluginManager.Others
|
||||
using (MD5 md5 = MD5.Create())
|
||||
{
|
||||
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
|
||||
byte[] hashBytes = md5.ComputeHash(inputBytes);
|
||||
byte[] hashBytes = md5.ComputeHash(inputBytes);
|
||||
return Convert.ToHexString(hashBytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,6 @@ Plugin Types:
|
||||
1. Commands
|
||||
2. Events
|
||||
|
||||
Project Structure
|
||||
|
||||

|
||||
|
||||
### How to create a plugin
|
||||
|
||||
First of all, Create a new project (class library) in Visual Studio.
|
||||
|
||||
57
Roles/AddRole.cs
Normal file
57
Roles/AddRole.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
Roles/Internals/RoleManagement.cs
Normal file
79
Roles/Internals/RoleManagement.cs
Normal 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
13
Roles/Roles.csproj
Normal 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>
|
||||
@@ -21,6 +21,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EVE_LevelingSystem", "EVE_L
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CMD_LevelingSystem", "CMD_LevelingSystem\CMD_LevelingSystem.csproj", "{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}"
|
||||
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
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
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}.Release|Any CPU.ActiveCfg = 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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -62,6 +76,9 @@ Global
|
||||
{B1B4976E-5112-4217-B57B-3A03C5207B6E} = {449FA364-0B72-43FF-B3A3-806E2916200E}
|
||||
{EEC445DC-0C4B-43EA-8694-606BA0390B77} = {A290C028-77C4-4D1D-AB43-DDFE6ABD9012}
|
||||
{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
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}
|
||||
|
||||
454
Updater/.gitignore
vendored
Normal file
454
Updater/.gitignore
vendored
Normal 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
7
Updater/App.axaml
Normal 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
24
Updater/App.axaml.cs
Normal 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
12
Updater/MainWindow.axaml
Normal 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>
|
||||
36
Updater/MainWindow.axaml.cs
Normal file
36
Updater/MainWindow.axaml.cs
Normal 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
34
Updater/Program.cs
Normal 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
27
Updater/Updater.csproj
Normal 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>
|
||||
Reference in New Issue
Block a user