13 Commits

54 changed files with 1365 additions and 478 deletions

View File

@@ -1,13 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/projectSettingsUpdater.xml
/contentModel.xml
/.idea.SethDiscordBot.iml
/modules.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AvaloniaProject">
<option name="projectPerEditor">
<map>
<entry key="Updater/MainWindow.axaml" value="Updater/Updater.csproj" />
</map>
</option>
</component>
</project>

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

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

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoGeneratedRunConfigurationManager">
<projectFile pubXmlPath="DiscordBot/Properties/PublishProfiles/LinuxProfile.pubxml">DiscordBot/DiscordBot.csproj</projectFile>
<projectFile pubXmlPath="DiscordBot/Properties/PublishProfiles/WindowsBuild.pubxml">DiscordBot/DiscordBot.csproj</projectFile>
<projectFile>Updater/Updater.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 beforePath="$PROJECT_DIR$/.idea/.idea.SethDiscordBot/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.SethDiscordBot/.idea/workspace.xml" 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$/DiscordBot/DiscordBot.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/DiscordBot/DiscordBot.csproj" 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">{
&quot;keyToString&quot;: {
&quot;ASKED_SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
<component name="RunManager" selected="Publish to IIS.DiscordBot: WindowsBuild">
<configuration name="DiscordBot: LinuxProfile" type="DotNetMsBuildPublish" factoryName="Publish to IIS">
<riderPublish publish_profile="LinuxProfile.pubxml" pubxml_path="$PROJECT_DIR$/DiscordBot/Properties/PublishProfiles/LinuxProfile.pubxml" uuid_high="612037599008934041" uuid_low="-9069359786678974134" />
<method v="2" />
</configuration>
<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>
<configuration name="Updater" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="USE_MONO" value="0" />
<option name="RUNTIME_ARGUMENTS" value="" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/Updater/Updater.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value="" />
<method v="2">
<option name="Build" />
</method>
</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" />
<workItem from="1662205818938" duration="46000" />
<workItem from="1662205887643" duration="139000" />
</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.

View File

@@ -1,6 +1,7 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager; using PluginManager;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Others; using PluginManager.Others;
@@ -17,21 +18,17 @@ internal class Level : DBCommand
public string Usage => "level"; public string Usage => "level";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false; public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public async void ExecuteServer(SocketCommandContext context)
{ {
if (!File.Exists(Config.GetValue<string>("LevelingSystemPath") + $"/{message.Author.Id}.dat")) if (!File.Exists(Config.GetValue<string>("LevelingSystemPath") + $"/{context.Message.Author.Id}.dat"))
{ {
await context.Channel.SendMessageAsync("You are now unranked !"); await context.Channel.SendMessageAsync("You are now unranked !");
return; return;
} }
var user = await Functions.ConvertFromJson<User>(Config.GetValue<string>("LevelingSystemPath") + $"/{message.Author.Id}.dat"); var user = await Functions.ConvertFromJson<User>(Config.GetValue<string>("LevelingSystemPath") + $"/{context.Message.Author.Id}.dat");
if (user == null) if (user == null)
{ {
await context.Channel.SendMessageAsync("You are now unranked !"); await context.Channel.SendMessageAsync("You are now unranked !");
@@ -39,7 +36,7 @@ internal class Level : DBCommand
} }
var builder = new EmbedBuilder(); var builder = new EmbedBuilder();
var r = new Random(); var r = new Random();
builder.WithColor(r.Next(256), r.Next(256), r.Next(256)); builder.WithColor(r.Next(256), r.Next(256), r.Next(256));
builder.AddField("Current Level", user.CurrentLevel, true) builder.AddField("Current Level", user.CurrentLevel, true)
.AddField("Current EXP", user.CurrentEXP, true) .AddField("Current EXP", user.CurrentEXP, true)

View File

@@ -1,26 +0,0 @@
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]";
public bool canUseDM => true;
public bool canUseServer => true;
public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{
var m = message.Content.Substring(6);
await message.Channel.SendMessageAsync(m);
}
}

View File

@@ -1,6 +1,8 @@
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
namespace CMD_Utils; namespace CMD_Utils;
@@ -15,19 +17,16 @@ internal class FlipCoin : DBCommand
public string Usage => "flip"; public string Usage => "flip";
public bool canUseDM => true;
public bool canUseServer => true;
public bool requireAdmin => false; public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public async void ExecuteDM(SocketCommandContext context) => ExecuteServer(context);
public async void ExecuteServer(SocketCommandContext context)
{ {
var random = new System.Random(); var random = new System.Random();
var r = random.Next(1, 3); var r = random.Next(1, 3);
if (r == 1) if (r == 1)
await message.Channel.SendMessageAsync("Heads"); await context.Message.Channel.SendMessageAsync("Heads");
else else
await message.Channel.SendMessageAsync("Tails"); await context.Message.Channel.SendMessageAsync("Tails");
} }
} }

View File

@@ -1,7 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Others; using PluginManager.Others;
@@ -17,17 +19,12 @@ public class Poll : DBCommand
public string Usage => "poll [This-is-question] [This-is-answer-1] [This-is-answer-2] ... "; public string Usage => "poll [This-is-question] [This-is-answer-1] [This-is-answer-2] ... ";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => true; public bool requireAdmin => true;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public async void ExecuteServer(SocketCommandContext context)
{ {
if (isDM) return; var question = context.Message.Content.Split(' ')[1].Replace('-', ' ');
var question = message.Content.Split(' ')[1].Replace('-', ' '); var answers = Functions.MergeStrings(context.Message.Content.Split(' '), 2).Split(' ');
var answers = Functions.MergeStrings(message.Content.Split(' '), 2).Split(' ');
var embedBuilder = new EmbedBuilder(); var embedBuilder = new EmbedBuilder();
embedBuilder.Title = question; embedBuilder.Title = question;
var len = answers.Length; var len = answers.Length;

View File

@@ -1,6 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
public class Random : DBCommand public class Random : DBCommand
@@ -12,31 +14,30 @@ public class Random : DBCommand
public string Description => "random number between number1 and number2"; public string Description => "random number between number1 and number2";
public string Usage => "random [number1] [number2]"; public string Usage => "random [number1] [number2]";
public bool canUseDM => true;
public bool canUseServer => true;
public bool requireAdmin => false; public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public async void ExecuteDM(SocketCommandContext context) => ExecuteServer(context);
public async void ExecuteServer(SocketCommandContext context)
{ {
try try
{ {
var msg = message.Content; var msg = context.Message.Content;
var a = int.Parse(msg.Split(' ')[1]); var a = int.Parse(msg.Split(' ')[1]);
var b = int.Parse(msg.Split(' ')[2]); var b = int.Parse(msg.Split(' ')[2]);
if (a > b) if (a > b)
{ {
var temp = a; var temp = a;
a = b; a = b;
b = temp; b = temp;
} }
await message.Channel.SendMessageAsync("Your random generated number is " + new System.Random().Next(a, b)); await context.Message.Channel.SendMessageAsync("Your random generated number is " + new System.Random().Next(a, b));
} }
catch catch
{ {
await message.Channel.SendMessageAsync("Invalid numbers or no numbers:\nUsage: " + Usage); await context.Message.Channel.SendMessageAsync("Invalid numbers or no numbers:\nUsage: " + Usage);
} }
} }
} }

View File

@@ -1,8 +1,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Loaders; using PluginManager.Loaders;
using PluginManager.Others; using PluginManager.Others;
@@ -31,16 +33,6 @@ internal class Help : DBCommand
/// </summary> /// </summary>
public string Usage => "help <command>"; public string Usage => "help <command>";
/// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel" />/>
/// </summary>
public bool canUseDM => true;
/// <summary>
/// Check if the command can be used in a server
/// </summary>
public bool canUseServer => true;
/// <summary> /// <summary>
/// Check if the command require administrator to be executed /// Check if the command require administrator to be executed
/// </summary> /// </summary>
@@ -53,9 +45,9 @@ internal class Help : DBCommand
/// <param name="message">The command message</param> /// <param name="message">The command message</param>
/// <param name="client">The discord bot client</param> /// <param name="client">The discord bot client</param>
/// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param> /// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param>
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public void ExecuteServer(SocketCommandContext context)
{ {
var args = Functions.GetArguments(message); var args = Functions.GetArguments(context.Message);
if (args.Count != 0) if (args.Count != 0)
{ {
foreach (var item in args) foreach (var item in args)
@@ -72,30 +64,26 @@ internal class Help : DBCommand
var embedBuilder = new EmbedBuilder(); var embedBuilder = new EmbedBuilder();
var adminCommands = ""; var adminCommands = "";
var normalCommands = ""; var normalCommands = "";
var DMCommands = "";
foreach (var cmd in PluginLoader.Commands!) foreach (var cmd in PluginLoader.Commands!)
{ {
if (cmd.canUseDM)
DMCommands += cmd.Command + " ";
if (cmd.requireAdmin) if (cmd.requireAdmin)
adminCommands += cmd.Command + " "; adminCommands += cmd.Command + " ";
if (cmd.canUseServer) else
normalCommands += cmd.Command + " "; normalCommands += cmd.Command + " ";
} }
embedBuilder.AddField("Admin Commands", adminCommands); embedBuilder.AddField("Admin Commands", adminCommands);
embedBuilder.AddField("Normal Commands", normalCommands); embedBuilder.AddField("Normal Commands", normalCommands);
embedBuilder.AddField("DM Commands", DMCommands);
context.Channel.SendMessageAsync(embed: embedBuilder.Build()); context.Channel.SendMessageAsync(embed: embedBuilder.Build());
} }
private EmbedBuilder GenerateHelpCommand(string command) private EmbedBuilder GenerateHelpCommand(string command)
{ {
var embedBuilder = new EmbedBuilder(); var embedBuilder = new EmbedBuilder();
var cmd = PluginLoader.Commands!.Find(p => p.Command == command || (p.Aliases is not null && p.Aliases.Contains(command))); var cmd = PluginLoader.Commands!.Find(p => p.Command == command || (p.Aliases is not null && p.Aliases.Contains(command)));
if (cmd == null) return null; if (cmd == null) return null;
embedBuilder.AddField("Usage", cmd.Usage); embedBuilder.AddField("Usage", cmd.Usage);

View File

@@ -30,33 +30,19 @@ internal class Restart : DBCommand
/// </summary> /// </summary>
public string Usage => "restart [-p | -c | -args | -cmd] <args>"; public string Usage => "restart [-p | -c | -args | -cmd] <args>";
/// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel" />/>
/// </summary>
public bool canUseDM => false;
/// <summary>
/// Check if the command can be used in a server
/// </summary>
public bool canUseServer => true;
/// <summary> /// <summary>
/// Check if the command require administrator to be executed /// Check if the command require administrator to be executed
/// </summary> /// </summary>
public bool requireAdmin => false; public bool requireAdmin => true;
/// <summary> /// <summary>
/// The main body of the command /// The main body of the command
/// </summary> /// </summary>
/// <param name="context">The command context</param> /// <param name="context">The command context</param>
/// <param name="message">The command message</param> public async void ExecuteServer(DiscordLibCommands.SocketCommandContext context)
/// <param name="client">The discord bot client</param>
/// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param>
public async void Execute(DiscordLibCommands.SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{ {
if (!(message.Author as SocketGuildUser).hasPermission(DiscordLib.GuildPermission.Administrator)) return; var args = Functions.GetArguments(context.Message);
var args = Functions.GetArguments(message); var OS = Functions.GetOperatingSystem();
var OS = Functions.GetOperatingSystem();
if (args.Count == 0) if (args.Count == 0)
{ {
switch (OS) switch (OS)

View File

@@ -1,8 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager; using PluginManager;
using PluginManager.Interfaces; using PluginManager.Interfaces;
@@ -27,16 +29,6 @@ internal class Settings : DBCommand
/// </summary> /// </summary>
public string Usage => "set [keyword] [new Value]"; public string Usage => "set [keyword] [new Value]";
/// <summary>
/// Check if the command can be used <inheritdoca DM <see cref="IChannel" />/>
/// </summary>
public bool canUseDM => true;
/// <summary>
/// Check if the command can be used in a server
/// </summary>
public bool canUseServer => true;
/// <summary> /// <summary>
/// Check if the command require administrator to be executed /// Check if the command require administrator to be executed
/// </summary> /// </summary>
@@ -46,16 +38,13 @@ internal class Settings : DBCommand
/// The main body of the command /// The main body of the command
/// </summary> /// </summary>
/// <param name="context">The command context</param> /// <param name="context">The command context</param>
/// <param name="message">The command message</param> public async void Execute(SocketCommandContext context)
/// <param name="client">The discord bot client</param>
/// <param name="isDM">True if the message was sent from a DM channel, false otherwise</param>
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
{ {
var channel = message.Channel; var channel = context.Message.Channel;
try try
{ {
var content = message.Content; var content = context.Message.Content;
var data = content.Split(' '); var data = content.Split(' ');
var keyword = data[1]; var keyword = data[1];
if (keyword.ToLower() == "help") if (keyword.ToLower() == "help")
{ {

View File

@@ -1,10 +1,13 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager; using PluginManager;
using static PluginManager.Others.Functions; using static PluginManager.Others.Functions;
namespace DiscordBot.Discord.Core; namespace DiscordBot.Discord.Core;
@@ -44,7 +47,7 @@ internal class Boot
public Boot(string botToken, string botPrefix) public Boot(string botToken, string botPrefix)
{ {
this.botPrefix = botPrefix; this.botPrefix = botPrefix;
this.botToken = botToken; this.botToken = botToken;
} }
@@ -62,7 +65,7 @@ internal class Boot
{ {
DiscordSocketConfig config = new DiscordSocketConfig { AlwaysDownloadUsers = true }; DiscordSocketConfig config = new DiscordSocketConfig { AlwaysDownloadUsers = true };
client = new DiscordSocketClient(config); client = new DiscordSocketClient(config);
service = new CommandService(); service = new CommandService();
CommonTasks(); CommonTasks();
@@ -81,9 +84,9 @@ internal class Boot
{ {
if (client == null) return; if (client == null) return;
client.LoggedOut += Client_LoggedOut; client.LoggedOut += Client_LoggedOut;
client.Log += Log; client.Log += Log;
client.LoggedIn += LoggedIn; client.LoggedIn += LoggedIn;
client.Ready += Ready; client.Ready += Ready;
} }
private Task Client_LoggedOut() private Task Client_LoggedOut()
@@ -96,7 +99,7 @@ internal class Boot
private Task Ready() private Task Ready()
{ {
Console.Title = "ONLINE"; Console.Title = "ONLINE";
isReady = true; isReady = true;
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -138,4 +141,5 @@ internal class Boot
return Task.CompletedTask; return Task.CompletedTask;
} }
} }

View File

@@ -1,8 +1,10 @@
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Loaders; using PluginManager.Loaders;
using PluginManager.Others; using PluginManager.Others;
using PluginManager.Others.Permissions; using PluginManager.Others.Permissions;
@@ -11,9 +13,9 @@ namespace DiscordBot.Discord.Core;
internal class CommandHandler internal class CommandHandler
{ {
private readonly string botPrefix; private readonly string botPrefix;
private readonly DiscordSocketClient client; private readonly DiscordSocketClient client;
private readonly CommandService commandService; private readonly CommandService commandService;
/// <summary> /// <summary>
/// Command handler constructor /// Command handler constructor
@@ -23,9 +25,9 @@ internal class CommandHandler
/// <param name="botPrefix">The prefix to watch for</param> /// <param name="botPrefix">The prefix to watch for</param>
public CommandHandler(DiscordSocketClient client, CommandService commandService, string botPrefix) public CommandHandler(DiscordSocketClient client, CommandService commandService, string botPrefix)
{ {
this.client = client; this.client = client;
this.commandService = commandService; this.commandService = commandService;
this.botPrefix = botPrefix; this.botPrefix = botPrefix;
} }
/// <summary> /// <summary>
@@ -75,57 +77,19 @@ internal class CommandHandler
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(); 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 is null) throw new System.Exception("Failed to run command. !");
if (plugin != null) if (plugin.requireAdmin && !context.Message.Author.isAdmin())
{ return;
if (message.Channel == await message.Author.CreateDMChannelAsync())
{
if (plugin.canUseDM)
{
if (plugin.requireAdmin)
{
if (message.Author.isAdmin())
{
plugin.Execute(context, message, client, true);
Functions.WriteLogFile($"[{message.Author.Id}] Executed command (DM) : " + plugin.Command);
return;
}
await message.Channel.SendMessageAsync("This command is for administrators only !"); if (context.Channel is SocketDMChannel)
return; plugin.ExecuteDM(context);
} else plugin.ExecuteServer(context);
plugin.Execute(context, message, client, true);
Functions.WriteLogFile($"[{message.Author.Id}] Executed command (DM) : " + plugin.Command);
return;
}
await message.Channel.SendMessageAsync("This command is not for DMs");
return;
}
if (plugin.canUseServer)
{
if (plugin.requireAdmin)
{
if (message.Author.isAdmin())
{
plugin.Execute(context, message, client, false);
Functions.WriteLogFile($"[{message.Author.Id}] Executed command : " + plugin.Command);
return;
}
await message.Channel.SendMessageAsync("This command is for administrators only !");
return;
}
plugin.Execute(context, message, client, false);
Functions.WriteLogFile($"[{message.Author.Id}] Executed command : " + plugin.Command);
}
}
} }
catch catch (System.Exception ex)
{ {
ex.WriteErrFile();
} }
} }
} }

View File

@@ -8,7 +8,7 @@
<StartupObject /> <StartupObject />
<SignAssembly>False</SignAssembly> <SignAssembly>False</SignAssembly>
<IsPublishable>True</IsPublishable> <IsPublishable>True</IsPublishable>
<AssemblyVersion>1.0.0.2</AssemblyVersion> <AssemblyVersion>1.0.0.11</AssemblyVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -1,11 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using DiscordBot.Discord.Core; using DiscordBot.Discord.Core;
using PluginManager; using PluginManager;
@@ -19,6 +22,7 @@ public class Program
{ {
private static bool loadPluginsOnStartup; private static bool loadPluginsOnStartup;
private static bool listPluginsAtStartup; private static bool listPluginsAtStartup;
private static ConsoleCommandsHandler consoleCommandsHandler;
/// <summary> /// <summary>
/// The main entry point for the application. /// The main entry point for the application.
@@ -27,17 +31,18 @@ public class Program
[Obsolete] [Obsolete]
public static void Main(string[] args) public static void Main(string[] args)
{ {
Console.WriteLine("Loading resources ...");
Directory.CreateDirectory("./Data/Resources"); Directory.CreateDirectory("./Data/Resources");
Directory.CreateDirectory("./Data/Plugins/Commands"); Directory.CreateDirectory("./Data/Plugins/Commands");
Directory.CreateDirectory("./Data/Plugins/Events"); Directory.CreateDirectory("./Data/Plugins/Events");
PreLoadComponents().Wait(); PreLoadComponents().Wait();
do
if (!Config.ContainsKey("ServerID"))
{ {
do if (!Config.ContainsKey("ServerID"))
{ {
Console.Clear();
Console.WriteLine("Please enter the server ID: "); Console.WriteLine("Please enter the server ID: ");
Console_Utilities.WriteColorText("You can find it in the Server Settings at &r\"Widget\"&c section"); Console_Utilities.WriteColorText("You can find it in the Server Settings at &r\"Widget\"&c section");
Console.WriteLine("Example: 1234567890123456789"); Console.WriteLine("Example: 1234567890123456789");
@@ -52,49 +57,48 @@ public class Program
string SID = key.KeyChar + Console.ReadLine(); string SID = key.KeyChar + Console.ReadLine();
if (SID.Length != 18) if (SID.Length != 18)
{ {
Console.WriteLine("Your server ID is not 18 characters long. Please try again."); Console.Clear();
Console_Utilities.WriteColorText("&rYour server ID is not 18 characters long. Please try again. \n");
continue; continue;
} }
Config.AddValueToVariables("ServerID", SID, false); Config.AddValueToVariables("ServerID", SID, false);
} }
break; }
} while (true);
} 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("token") || Config.GetValue<string>("token") == null || Config.GetValue<string>("token")?.Length != 70) if (!Config.ContainsKey("prefix") || Config.GetValue<string>("prefix") == null || Config.GetValue<string>("prefix")?.Length != 1)
{ {
Console.WriteLine("Please insert your token"); Console.WriteLine("Please insert your prefix (max. 1 character long):");
Console.Write("Token = "); 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");
var token = Console.ReadLine(); Console.Write("Prefix = ");
if (token?.Length == 59 || token?.Length == 70) var prefix = Console.ReadLine()![0];
Config.AddValueToVariables("token", token, true);
else
Console.WriteLine("Invalid token");
Console.WriteLine("Please insert your prefix (max. 1 character long):"); if (prefix == ' ' || char.IsDigit(prefix) || prefix == '/' || prefix == '\\')
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 = "); Console.Clear();
var prefix = Console.ReadLine()![0]; Console_Utilities.WriteColorText("&rThe prefix is invalid");
continue;
if (prefix == ' ' || char.IsDigit(prefix)) }
return; Config.AddValueToVariables("prefix", prefix.ToString(), false);
Config.AddValueToVariables("prefix", prefix.ToString(), false); }
}
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);
}
break;
} while (true);
HandleInput(args).Wait(); HandleInput(args).Wait();
} }
@@ -105,23 +109,25 @@ public class Program
/// <param name="discordbooter">The discord booter used to start the application</param> /// <param name="discordbooter">The discord booter used to start the application</param>
private static void NoGUI(Boot discordbooter) private static void NoGUI(Boot discordbooter)
{ {
var consoleCommandsHandler = new ConsoleCommandsHandler(discordbooter.client);
#if DEBUG #if DEBUG
Console.WriteLine(); Console.WriteLine();
consoleCommandsHandler.HandleCommand("lp"); ConsoleCommandsHandler.ExecuteCommad("lp").Wait();
#else #else
if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp"); if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp");
if (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs"); if (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs");
#endif #endif
Config.SaveConfig(); Config.SaveConfig(SaveType.NORMAL).Wait();
while (true) while (true)
{ {
//Console_Utilities.WriteColorText("&rSethBot (&yDEBUG&r) &c> ", false);
var cmd = Console.ReadLine(); var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd!, if (!consoleCommandsHandler.HandleCommand(cmd!
#if DEBUG #if DEBUG
false , false
#endif #endif
) && cmd.Length > 0) ) && cmd.Length > 0)
Console.WriteLine("Failed to run command " + cmd); Console.WriteLine("Failed to run command " + cmd);
} }
@@ -146,6 +152,14 @@ public class Program
Console_Utilities.WriteColorText("&rRemember to close the bot using the ShutDown command (&ysd&r) or some settings won't be saved\n"); Console_Utilities.WriteColorText("&rRemember to close the bot using the ShutDown command (&ysd&r) or some settings won't be saved\n");
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
if (Config.ContainsKey("LaunchMessage"))
{
Console_Utilities.WriteColorText(Config.GetValue<string>("LaunchMessage"));
Config.RemoveKey("LaunchMessage");
}
Console_Utilities.WriteColorText("Please note that the bot saves a backup save file every time you are using the shudown command (&ysd&c)");
Console.WriteLine($"============================ LOG ============================"); Console.WriteLine($"============================ LOG ============================");
try try
@@ -164,7 +178,6 @@ public class Program
#endif #endif
var prefix = Config.GetValue<string>("prefix"); var prefix = Config.GetValue<string>("prefix");
var discordbooter = new Boot(token, prefix); var discordbooter = new Boot(token, prefix);
await discordbooter.Awake(); await discordbooter.Awake();
return discordbooter; return discordbooter;
@@ -199,6 +212,7 @@ public class Program
/// <param name="args">The arguments</param> /// <param name="args">The arguments</param>
private static async Task HandleInput(string[] args) private static async Task HandleInput(string[] args)
{ {
var len = args.Length; var len = args.Length;
if (len == 3 && args[0] == "/download") if (len == 3 && args[0] == "/download")
@@ -211,6 +225,23 @@ public class Program
return; return;
} }
if (len > 0 && args[0] == "/test")
{
int p = 1;
bool allowed = true;
Console.CancelKeyPress += (sender, e) => allowed = false;
Console_Utilities.ProgressBar bar = new(ProgressBarType.NO_END);// { NoColor = false, Color = ConsoleColor.DarkRed };
Console.WriteLine("Press Ctrl + C to stop.");
while (p <= int.MaxValue - 1 && allowed)
{
bar.Update(100 / p);
await Task.Delay(100);
p++;
}
return;
}
if (len > 0 && (args.Contains("--cmd") || args.Contains("--args") || args.Contains("--nomessage"))) if (len > 0 && (args.Contains("--cmd") || args.Contains("--args") || args.Contains("--nomessage")))
{ {
if (args.Contains("lp") || args.Contains("loadplugins")) if (args.Contains("lp") || args.Contains("loadplugins"))
@@ -222,11 +253,43 @@ public class Program
} }
var b = await StartNoGUI();
consoleCommandsHandler = new ConsoleCommandsHandler(b.client);
if (len > 0 && args[0] == "/remplug")
{
string plugName = Functions.MergeStrings(args, 1);
Console.WriteLine("Starting to remove " + plugName);
await ConsoleCommandsHandler.ExecuteCommad("remplug " + plugName);
loadPluginsOnStartup = true;
len = 0;
}
if (len == 0 || (args[0] != "--exec" && args[0] != "--execute")) if (len == 0 || (args[0] != "--exec" && args[0] != "--execute"))
{ {
var b = await StartNoGUI();
Thread mainThread = new Thread(() => NoGUI(b)); Thread mainThread = new Thread(() =>
{
try
{
NoGUI(b);
}
catch (IOException ex)
{
if (ex.Message == "No process is on the other end of the pipe." || (uint)ex.HResult == 0x800700E9)
{
if (!Config.ContainsKey("LaunchMessage"))
Config.AddValueToVariables("LaunchMessage", "An error occured while closing the bot last time. Please consider closing the bot using the &rsd&c method !\nThere is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !", false);
Functions.WriteErrFile(ex.ToString());
}
}
});
mainThread.Start(); mainThread.Start();
return; return;
} }
@@ -283,6 +346,8 @@ public class Program
private static async Task PreLoadComponents() private static async Task PreLoadComponents()
{ {
Console_Utilities.ProgressBar main = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
main.Start();
await Config.LoadConfig(); await Config.LoadConfig();
if (Config.ContainsKey("DeleteLogsAtStartup")) if (Config.ContainsKey("DeleteLogsAtStartup"))
if (Config.GetValue<bool>("DeleteLogsAtStartup")) if (Config.GetValue<bool>("DeleteLogsAtStartup"))
@@ -312,7 +377,11 @@ public class Program
} }
} }
List<string> onlineSettingsList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData"); List<string> onlineSettingsList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData");
main.Stop();
foreach (var key in onlineSettingsList) foreach (var key in onlineSettingsList)
{ {
if (key.Length <= 3 || !key.Contains(' ')) continue; if (key.Length <= 3 || !key.Contains(' ')) continue;
@@ -324,42 +393,45 @@ public class Program
string newVersion = s[1]; string newVersion = s[1];
if (!newVersion.Equals(Config.GetValue<string>("Version"))) if (!newVersion.Equals(Config.GetValue<string>("Version")))
{ {
Console.WriteLine("A new version has been released on github page."); if (Functions.GetOperatingSystem() == PluginManager.Others.OperatingSystem.WINDOWS)
Console.WriteLine("Download the new version using the following link wrote in yellow");
Console_Utilities.WriteColorText("&y" + Config.GetValue<string>("GitURL") + "&c");
Console.WriteLine();
Console.WriteLine("Your product will work just fine on this outdated version, but an update is recommended.\n" +
"From now on, this version is no longer supported"
);
Console_Utilities.WriteColorText("&rUse at your own risk&c");
Console_Utilities.WriteColorText("&mCurrent Version: " + Config.GetValue<string>("Version") + "&c");
Console_Utilities.WriteColorText("&gNew Version: " + newVersion + "&c");
Console.WriteLine("\n\n");
await Task.Delay(1000);
int waitTime = 10; //wait time to proceed
Console.Write($"The bot will start in {waitTime} seconds");
while (waitTime > 0)
{ {
await Task.Delay(1000);
waitTime--; string url = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0.zip";
Console.SetCursorPosition("The bot will start in ".Length, Console.CursorTop); //string url2 = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}-preview/net6.0.zip";
Console.Write(" "); Process.Start("./Updater/Updater.exe", $"/update {url} ./DiscordBot.exe ./");
Console.SetCursorPosition("The bot will start in ".Length, Console.CursorTop);
Console.Write(waitTime + " seconds");
} }
else
{
string url = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0_linux.zip";
Process.Start("./Updater/Updater", $"/update {url} ./DiscordBot ./");
}
Environment.Exit(0);
} }
break;
case "UpdaterVersion":
string updaternewversion = s[1];
if (Config.UpdaterVersion != updaternewversion)
{
Console.Clear();
Console.WriteLine("Installing updater ...\nDo NOT close the bot during update !");
Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start();
await ServerCom.DownloadFileNoProgressAsync("https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.zip", "./Updater.zip");
await Functions.ExtractArchive("./Updater.zip", "./", null, UnzipProgressType.PercentageFromTotalSize);
Config.UpdaterVersion = updaternewversion;
File.Delete("Updater.zip");
await Config.SaveConfig(SaveType.NORMAL);
bar.Stop();
Console.Clear();
}
break; break;
} }
} }
Console_Utilities.Initialize();
Config.SaveConfig(); Console_Utilities.Initialize();
await Config.SaveConfig(SaveType.NORMAL);
Console.Clear();
} }
} }

View File

@@ -1,21 +0,0 @@
using PluginManager.Online.Updates;
try
{
bool requireUpdate = await PluginUpdater.CheckForUpdates("DiscordBotConsoleLauncher");
if (requireUpdate)
{
var update = await PluginUpdater.DownloadUpdateInfo("DiscordBotConsoleLauncher");
if (update == Update.Empty)
return;
Console.WriteLine("Found an update: ");
Console.WriteLine(update.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine("An exception was thrown. ");
Console.WriteLine(ex.Message);
Environment.Exit(-2);
}

View File

@@ -0,0 +1,24 @@
using Discord.Commands;
using PluginManager.Interfaces;
namespace FreeGamesModule
{
public class Free : DBCommand
{
public string Command => "free";
public List<string>? Aliases => null;
public string Description => "Check out any free game";
public string Usage => "free";
public bool requireAdmin => false;
public void ExecuteServer(SocketCommandContext context)
{
}
}
}

View File

@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>

View File

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

View File

@@ -1,6 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
namespace MusicCommands; namespace MusicCommands;
@@ -15,13 +17,9 @@ internal class Leave : DBCommand
public string Usage => "leave"; public string Usage => "leave";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false; public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public async void ExecuteServer(SocketCommandContext context)
{ {
if (Data.audioClient is not null && Data.voiceChannel is not null) if (Data.audioClient is not null && Data.voiceChannel is not null)
{ {

View File

@@ -1,6 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
namespace MusicCommands; namespace MusicCommands;
@@ -15,13 +17,9 @@ internal class Pause : DBCommand
public string Usage => "pause"; public string Usage => "pause";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false; public bool requireAdmin => false;
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public void ExecuteServer(SocketCommandContext context)
{ {
Data.MusicPlayer.isPaused = !Data.MusicPlayer.isPaused; Data.MusicPlayer.isPaused = !Data.MusicPlayer.isPaused;
} }

View File

@@ -2,10 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using Discord; using Discord;
using Discord.Audio; using Discord.Audio;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Others; using PluginManager.Others;
@@ -21,17 +23,13 @@ internal class Play : DBCommand
public string Usage => "play [name/url]"; public string Usage => "play [name/url]";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false; public bool requireAdmin => false;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public async void ExecuteServer(SocketCommandContext context)
{ {
Directory.CreateDirectory("Music"); Directory.CreateDirectory("Music");
var path = "./Music/"; var path = "./Music/";
string[] splitted = message.Content.Split(' '); string[] splitted = context.Message.Content.Split(' ');
if (splitted.Length < 2) if (splitted.Length < 2)
return; return;
do do

View File

@@ -3,8 +3,10 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
namespace MusicCommands namespace MusicCommands
@@ -19,24 +21,20 @@ namespace MusicCommands
public string Usage => "skip"; public string Usage => "skip";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => false; public bool requireAdmin => false;
public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public async void ExecuteServer(SocketCommandContext context)
{ {
var loadedSong = Data.MusicPlayer.NowPlaying; var loadedSong = Data.MusicPlayer.NowPlaying;
if (loadedSong is null || Data.MusicPlayer.isPlaying == false) if (loadedSong is null || Data.MusicPlayer.isPlaying == false)
{ {
message.Channel.SendMessageAsync("There is no music playing"); await context.Message.Channel.SendMessageAsync("There is no music playing");
return; return;
} }
Data.MusicPlayer.isPlaying = false; Data.MusicPlayer.isPlaying = false;
message.Channel.SendMessageAsync($"You have skipped {loadedSong.Name}"); await context.Message.Channel.SendMessageAsync($"You have skipped {loadedSong.Name}");
} }
} }
} }

View File

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

View File

@@ -11,10 +11,10 @@ namespace PluginManager
{ {
internal class AppConfig internal class AppConfig
{ {
public string UpdaterVersion { get; set; }
public Dictionary<string, object>? ApplicationVariables { get; init; } public Dictionary<string, object>? ApplicationVariables { get; init; }
public List<string>? ProtectedKeyWords { get; init; } public List<string>? ProtectedKeyWords { get; init; }
public Dictionary<string, string>? PluginVersions { get; init; }
public Dictionary<string, string> PluginVersions { get; init; }
} }
public static class Config public static class Config
@@ -59,9 +59,8 @@ namespace PluginManager
public static bool Contains(string pluginName) public static bool Contains(string pluginName)
{ {
foreach (var tuple in InstalledPlugins) foreach (var tuple in InstalledPlugins)
{ if (tuple.Item1 == pluginName)
if (tuple.Item1 == pluginName) return true; return true;
}
return false; return false;
} }
@@ -79,18 +78,20 @@ namespace PluginManager
private static AppConfig? appConfig { get; set; } private static AppConfig? appConfig { get; set; }
public static string GetPluginVersion(string pluginName) => appConfig.PluginVersions[pluginName]; 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) public static void SetPluginVersion(string pluginName, string newVersion)
{ {
if (appConfig.PluginVersions.ContainsKey(pluginName)) if (appConfig!.PluginVersions!.ContainsKey(pluginName))
appConfig.PluginVersions[pluginName] = newVersion; appConfig.PluginVersions[pluginName] = newVersion;
else appConfig.PluginVersions.Add(pluginName, newVersion); else appConfig.PluginVersions.Add(pluginName, newVersion);
// SaveConfig(); // SaveConfig();
} }
public static void RemovePluginVersion(string pluginName) => appConfig.PluginVersions.Remove(pluginName); public static void RemovePluginVersion(string pluginName) => appConfig!.PluginVersions!.Remove(pluginName);
public static bool PluginVersionsContainsKey(string pluginName) => appConfig.PluginVersions.ContainsKey(pluginName); public static bool PluginVersionsContainsKey(string pluginName) => appConfig!.PluginVersions!.ContainsKey(pluginName);
public static void AddValueToVariables<T>(string key, T value, bool isProtected) public static void AddValueToVariables<T>(string key, T value, bool isProtected)
{ {
@@ -103,7 +104,7 @@ namespace PluginManager
if (isProtected && key != "Version") if (isProtected && key != "Version")
appConfig.ProtectedKeyWords!.Add(key); appConfig.ProtectedKeyWords!.Add(key);
SaveConfig(); SaveConfig(SaveType.NORMAL);
} }
public static Type GetVariableType(string value) public static Type GetVariableType(string value)
@@ -171,7 +172,7 @@ namespace PluginManager
throw new Exception("Key is protected"); throw new Exception("Key is protected");
appConfig.ApplicationVariables[key] = JsonSerializer.SerializeToElement(value); appConfig.ApplicationVariables[key] = JsonSerializer.SerializeToElement(value);
SaveConfig(); SaveConfig(SaveType.NORMAL);
} }
public static void RemoveKey(string key) public static void RemoveKey(string key)
@@ -180,13 +181,24 @@ namespace PluginManager
throw new Exception("Key is protected"); throw new Exception("Key is protected");
appConfig!.ApplicationVariables!.Remove(key); appConfig!.ApplicationVariables!.Remove(key);
appConfig.ProtectedKeyWords!.Remove(key); appConfig.ProtectedKeyWords!.Remove(key);
SaveConfig(); SaveConfig(SaveType.NORMAL);
} }
public static async void SaveConfig() public static async Task SaveConfig(SaveType type)
{ {
string path = Functions.dataFolder + "config.json"; if (type == SaveType.NORMAL)
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!); {
string path = Functions.dataFolder + "config.json";
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!);
return;
}
if (type == SaveType.BACKUP)
{
string path = Functions.dataFolder + "config.json.bak";
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!);
return;
}
} }
public static async Task LoadConfig() public static async Task LoadConfig()
@@ -194,11 +206,24 @@ namespace PluginManager
string path = Functions.dataFolder + "config.json"; string path = Functions.dataFolder + "config.json";
if (File.Exists(path)) if (File.Exists(path))
{ {
appConfig = await Functions.ConvertFromJson<AppConfig>(path); try
{
appConfig = await Functions.ConvertFromJson<AppConfig>(path);
}
catch (Exception ex)
{
File.Delete(path);
Console.WriteLine("An error occured while loading the settings. Importing from backup file...");
path = Functions.dataFolder + "config.json.bak";
appConfig = await Functions.ConvertFromJson<AppConfig>(path);
Functions.WriteErrFile(ex.Message);
}
Functions.WriteLogFile($"Loaded {appConfig.ApplicationVariables!.Keys.Count} application variables.\nLoaded {appConfig.ProtectedKeyWords!.Count} readonly variables."); Functions.WriteLogFile($"Loaded {appConfig.ApplicationVariables!.Keys.Count} application variables.\nLoaded {appConfig.ProtectedKeyWords!.Count} readonly variables.");
return;
} }
else appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>(), PluginVersions = new Dictionary<string, string>(), UpdaterVersion = "-1" };
appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>(), PluginVersions = new Dictionary<string, string>() };
} }
public static bool ContainsValue<T>(T value) => appConfig!.ApplicationVariables!.ContainsValue(value!); public static bool ContainsValue<T>(T value) => appConfig!.ApplicationVariables!.ContainsValue(value!);

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
@@ -28,27 +29,20 @@ public interface DBCommand
/// </summary> /// </summary>
string Usage { get; } string Usage { get; }
/// <summary>
/// true if the command can be used in a DM channel, otherwise false
/// </summary>
bool canUseDM { get; }
/// <summary>
/// true if the command can be used in a server, otherwise false
/// </summary>
bool canUseServer { get; }
/// <summary> /// <summary>
/// true if the command requre admin, otherwise false /// true if the command requre admin, otherwise false
/// </summary> /// </summary>
bool requireAdmin { get; } bool requireAdmin { get; }
/// <summary> /// <summary>
/// The main body of the command. This is what is executed when user calls the command /// The main body of the command. This is what is executed when user calls the command in Server
/// </summary> /// </summary>
/// <param name="context">The disocrd Context</param> /// <param name="context">The disocrd Context</param>
/// <param name="message">The message that the user types</param> void ExecuteServer(SocketCommandContext context) { }
/// <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> /// <summary>
void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM); /// The main body of the command. This is what is executed when user calls the command in DM
/// </summary>
/// <param name="context">The disocrd Context</param>
void ExecuteDM(SocketCommandContext context) { }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
@@ -81,30 +82,48 @@ public class ConsoleCommandsHandler
if (pluginsLoaded) if (pluginsLoaded)
return; return;
var loader = new PluginLoader(client!); var loader = new PluginLoader(client!);
ConsoleColor cc = Console.ForegroundColor;
loader.onCMDLoad += (name, typeName, success, exception) => loader.onCMDLoad += (name, typeName, success, exception) =>
{ {
Console.ForegroundColor = ConsoleColor.Green;
if (name == null || name.Length < 2) if (name == null || name.Length < 2)
name = typeName; name = typeName;
if (success) if (success)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[CMD] Successfully loaded command : " + name); Console.WriteLine("[CMD] Successfully loaded command : " + name);
}
else else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message); Console.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message);
Console.ForegroundColor = ConsoleColor.Red; }
Console.ForegroundColor = cc;
}; };
loader.onEVELoad += (name, typeName, success, exception) => loader.onEVELoad += (name, typeName, success, exception) =>
{ {
if (name == null || name.Length < 2) if (name == null || name.Length < 2)
name = typeName; name = typeName;
Console.ForegroundColor = ConsoleColor.Green;
if (success) if (success)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[EVENT] Successfully loaded event : " + name); Console.WriteLine("[EVENT] Successfully loaded event : " + name);
}
else else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message); Console.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message);
Console.ForegroundColor = ConsoleColor.Red; }
Console.ForegroundColor = cc;
}; };
loader.LoadPlugins(); loader.LoadPlugins();
Console.ForegroundColor = cc;
pluginsLoaded = true; pluginsLoaded = true;
} }
); );
@@ -168,34 +187,17 @@ public class ConsoleCommandsHandler
continue; continue;
var split = line.Split(','); var split = line.Split(',');
Console.WriteLine($"\nDownloading item: {split[1]}"); Console.WriteLine($"\nDownloading item: {split[1]}");
if (File.Exists("./" + split[1])) File.Delete("./" + split[1]);
await ServerCom.DownloadFileAsync(split[0], "./" + split[1]); await ServerCom.DownloadFileAsync(split[0], "./" + split[1]);
Console.WriteLine(); Console.WriteLine();
if (split[0].EndsWith(".zip") || split[0].EndsWith(".pak") || split[0].EndsWith(".pkg")) if (split[0].EndsWith(".zip") || split[0].EndsWith(".pak") || split[0].EndsWith(".pkg"))
{ {
Console.WriteLine($"Extracting {split[1]}"); Console.WriteLine($"Extracting {split[1]} ...");
var proc = 0f; var bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END) { Max = 100f, Color = ConsoleColor.Green };
var isExtracting = true; bar.Start();
var bar = new Console_Utilities.ProgressBar { Max = 100f, Color = ConsoleColor.Green }; await Functions.ExtractArchive("./" + split[1], "./", null, UnzipProgressType.PercentageFromTotalSize);
bar.Stop();
IProgress<float> extractProgress = new Progress<float>(value => { proc = value; });
new Thread(new Task(() =>
{
while (isExtracting)
{
bar.Update(proc);
if (proc >= 99.9f)
isExtracting = false;
Thread.Sleep(500);
}
}
).Start
).Start();
await Functions.ExtractArchive("./" + split[1], "./", extractProgress, UnzipProgressType.PercentageFromTotalSize);
bar.Update(100f);
isExtracting = false;
await Task.Delay(1000);
bar.Update(100);
Console.WriteLine("\n"); Console.WriteLine("\n");
File.Delete("./" + split[1]); File.Delete("./" + split[1]);
} }
@@ -205,7 +207,7 @@ public class ConsoleCommandsHandler
} }
VersionString? ver = await VersionString.GetVersionOfPackageFromWeb(name); VersionString? ver = await VersionString.GetVersionOfPackageFromWeb(name);
if (ver is null) throw new Exception("Incorrect version"); if (ver is null) throw new Exception("Incorrect version");
Config.SetPluginVersion(name, $"{ver.PackageID}.{ver.PackageMainVersion}.{ver.PackageCheckVersion}"); Config.SetPluginVersion(name, $"{ver.PackageVersionID}.{ver.PackageMainVersion}.{ver.PackageCheckVersion}");
// Console.WriteLine(); // Console.WriteLine();
isDownloading = false; isDownloading = false;
@@ -253,16 +255,22 @@ public class ConsoleCommandsHandler
} }
); );
AddCommand("sd", "Shuts down the discord bot", () => AddCommand("sd", "Shuts down the discord bot", async () =>
{ {
if (client is null) if (client is null)
return; return;
client.StopAsync(); Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
client.DisposeAsync();
Config.SaveConfig(); bar.Start();
Console.WriteLine("Bot is closing in 2 seconds ! Please wait to save data !"); await Config.SaveConfig(SaveType.NORMAL);
Thread.Sleep(2000); await Config.SaveConfig(SaveType.BACKUP);
await Task.Delay(4000);
bar.Stop();
Console.WriteLine();
await client.StopAsync();
await client.DisposeAsync();
Environment.Exit(0); Environment.Exit(0);
} }
); );
@@ -294,6 +302,99 @@ public class ConsoleCommandsHandler
} }
}); });
AddCommand("remplug", "Remove a plugin", "remplug [plugName]", async args =>
{
if (args.Length <= 1) return;
isDownloading = true;
string plugName = Functions.MergeStrings(args, 1);
if (pluginsLoaded)
{
if (Functions.GetOperatingSystem() == Others.OperatingSystem.WINDOWS)
{
Process.Start("DiscordBot.exe", $"/remplug {plugName}");
await Task.Delay(100);
Environment.Exit(0);
}
else
{
Process.Start("./DiscordBot", $"/remplug {plugName}");
await Task.Delay(100);
Environment.Exit(0);
}
isDownloading = false;
return;
}
string location = "./Data/Plugins/";
location = Config.PluginConfig.GetPluginType(plugName) switch
{
PluginType.Command => location + "Commands/" + plugName + "." + PluginLoader.pluginCMDExtension,
PluginType.Event => location + "Events/" + plugName + "." + PluginLoader.pluginEVEExtension,
PluginType.Unknown => "./",
_ => throw new NotImplementedException("Plugin type incorrect")
};
if (!File.Exists(location))
{
Console.WriteLine("The plugin does not exist");
return;
}
File.Delete(location);
if (Config.PluginConfig.Contains(plugName))
{
var tuple = Config.PluginConfig.InstalledPlugins.Where(t => t.Item1 == plugName).FirstOrDefault();
Console.WriteLine("Found: " + tuple.ToString());
Config.PluginConfig.InstalledPlugins.Remove(tuple);
Config.RemovePluginVersion(plugName);
await Config.SaveConfig(SaveType.NORMAL);
}
Console.WriteLine("Removed the plugin DLL. Checking for other files ...");
var info = await manager.GetPluginLinkByName(plugName);
if (info[2] != string.Empty)
{
var lines = await ServerCom.ReadTextFromURL(info[2]);
foreach (var line in lines)
{
if (!(line.Length > 0 && line.Contains(",")))
continue;
var split = line.Split(',');
if (File.Exists("./" + split[1]))
File.Delete("./" + split[1]);
Console.WriteLine("Removed: " + split[1]);
}
if (Directory.Exists(plugName))
Directory.Delete(plugName, true);
}
isDownloading = false;
Console.WriteLine(plugName + " has been successfully deleted !");
});
AddCommand("reload", "Reload the bot with all plugins", () =>
{
if (Functions.GetOperatingSystem() == Others.OperatingSystem.WINDOWS)
{
Process.Start("DiscordBot.exe", $"lp");
HandleCommand("sd");
}
else
{
Process.Start("./DiscordBot", $"lp");
HandleCommand("sd");
}
});
//Sort the commands by name //Sort the commands by name
commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName)); commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName));
} }
@@ -325,9 +426,10 @@ public class ConsoleCommandsHandler
return commandList.FirstOrDefault(t => t.CommandName == command); return commandList.FirstOrDefault(t => t.CommandName == command);
} }
internal static async Task ExecuteCommad(string command) public static async Task ExecuteCommad(string command)
{ {
var args = command.Split(' '); var args = command.Split(' ');
// Console.WriteLine(command);
foreach (var item in commandList.ToList()) foreach (var item in commandList.ToList())
if (item.CommandName == args[0]) if (item.CommandName == args[0])
{ {

View File

@@ -69,7 +69,7 @@ public class PluginLoader
{ {
string name = new FileInfo(file).Name.Split('.')[0]; string name = new FileInfo(file).Name.Split('.')[0];
if (!Config.PluginVersionsContainsKey(name)) if (!Config.PluginVersionsContainsKey(name))
Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageID + ".0.0"); Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageVersionID + ".0.0");
if (await PluginUpdater.CheckForUpdates(name)) if (await PluginUpdater.CheckForUpdates(name))
await PluginUpdater.Download(name); await PluginUpdater.Download(name);
@@ -84,7 +84,7 @@ public class PluginLoader
{ {
string name = new FileInfo(file).Name.Split('.')[0]; string name = new FileInfo(file).Name.Split('.')[0];
if (!Config.PluginVersionsContainsKey(name)) if (!Config.PluginVersionsContainsKey(name))
Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageID + ".0.0"); Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageVersionID + ".0.0");
if (await PluginUpdater.CheckForUpdates(name)) if (await PluginUpdater.CheckForUpdates(name))
await PluginUpdater.Download(name); await PluginUpdater.Download(name);
@@ -94,7 +94,7 @@ public class PluginLoader
//Save the new config file (after the updates) //Save the new config file (after the updates)
Config.SaveConfig(); await Config.SaveConfig(SaveType.NORMAL);
//Load all plugins //Load all plugins

View File

@@ -9,7 +9,7 @@ namespace PluginManager.Online.Helpers
{ {
public class VersionString public class VersionString
{ {
public int PackageID; public int PackageVersionID;
public int PackageMainVersion; public int PackageMainVersion;
public int PackageCheckVersion; public int PackageCheckVersion;
@@ -18,7 +18,7 @@ namespace PluginManager.Online.Helpers
string[] data = version.Split('.'); string[] data = version.Split('.');
try try
{ {
PackageID = int.Parse(data[0]); PackageVersionID = int.Parse(data[0]);
PackageMainVersion = int.Parse(data[1]); PackageMainVersion = int.Parse(data[1]);
PackageCheckVersion = int.Parse(data[2]); PackageCheckVersion = int.Parse(data[2]);
} }
@@ -28,20 +28,25 @@ namespace PluginManager.Online.Helpers
} }
} }
#region operators
public static bool operator >(VersionString s1, VersionString s2) public static bool operator >(VersionString s1, VersionString s2)
{ {
if (s1.PackageID != s2.PackageID) throw new Exception("Can not compare two different paks"); if (s1.PackageVersionID > s2.PackageVersionID) return true;
if (s1.PackageMainVersion > s2.PackageMainVersion) return true; if (s1.PackageVersionID == s2.PackageVersionID)
if (s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion > s2.PackageCheckVersion) return true; {
if (s1.PackageMainVersion > s2.PackageMainVersion) return true;
if (s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion > s2.PackageCheckVersion) return true;
}
return false; return false;
} }
public static bool operator <(VersionString s1, VersionString s2) => !(s1 > s2) && s1 != s2; public static bool operator <(VersionString s1, VersionString s2) => !(s1 > s2) && s1 != s2;
public static bool operator ==(VersionString s1, VersionString s2) public static bool operator ==(VersionString s1, VersionString s2)
{ {
if (s1.PackageID == s2.PackageID && s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion == s2.PackageCheckVersion) return true; if (s1.PackageVersionID == s2.PackageVersionID && s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion == s2.PackageCheckVersion) return true;
return false; return false;
} }
@@ -50,14 +55,18 @@ namespace PluginManager.Online.Helpers
public static bool operator <=(VersionString s1, VersionString s2) => (s1 < 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); public static bool operator >=(VersionString s1, VersionString s2) => (s1 > s2 || s1 == s2);
#endregion
public override string ToString() public override string ToString()
{ {
return "{PackageID: " + PackageID + ", PackageVersion: " + PackageMainVersion + ", PackageCheckVersion: " + PackageCheckVersion + "}"; return "{PackageID: " + PackageVersionID + ", PackageVersion: " + PackageMainVersion + ", PackageCheckVersion: " + PackageCheckVersion + "}";
} }
public string ToShortString() public string ToShortString()
{ {
return $"{PackageID}.{PackageMainVersion}.{PackageCheckVersion}"; if (PackageVersionID == 0 && PackageCheckVersion == 0 && PackageMainVersion == 0)
return "Unknown";
return $"{PackageVersionID}.{PackageMainVersion}.{PackageCheckVersion}";
} }
public static VersionString? GetVersionOfPackage(string pakName) public static VersionString? GetVersionOfPackage(string pakName)

View File

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

View File

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

View File

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

View File

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

View File

@@ -26,17 +26,17 @@ namespace PluginManager.Others
/// <summary> /// <summary>
/// The location for all logs /// The location for all logs
/// </summary> /// </summary>
public static readonly string logFolder = @"./Output/Logs/"; public static readonly string logFolder = @"./Data/Output/Logs/";
/// <summary> /// <summary>
/// The location for all errors /// The location for all errors
/// </summary> /// </summary>
public static readonly string errFolder = @"./Output/Errors/"; public static readonly string errFolder = @"./Data/Output/Errors/";
/// <summary> /// <summary>
/// Archives folder /// Archives folder
/// </summary> /// </summary>
public static readonly string pakFolder = @"./Data/Resources/PAK/"; public static readonly string pakFolder = @"./Data/PAKS/";
/// <summary> /// <summary>
/// Beta testing folder /// Beta testing folder
@@ -50,7 +50,7 @@ namespace PluginManager.Others
/// <param name="FileName">The file name that is inside the archive or its full path</param> /// <param name="FileName">The file name that is inside the archive or its full path</param>
/// <param name="archFile">The archive location from the PAKs folder</param> /// <param name="archFile">The archive location from the PAKs folder</param>
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns> /// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
public static Stream? ReadFromPakAsync(string FileName, string archFile) public static async Task<Stream?> ReadFromPakAsync(string FileName, string archFile)
{ {
archFile = pakFolder + archFile; archFile = pakFolder + archFile;
Directory.CreateDirectory(pakFolder); Directory.CreateDirectory(pakFolder);
@@ -58,7 +58,11 @@ namespace PluginManager.Others
using ZipArchive archive = ZipFile.OpenRead(archFile); using ZipArchive archive = ZipFile.OpenRead(archFile);
ZipArchiveEntry? entry = archive.GetEntry(FileName); ZipArchiveEntry? entry = archive.GetEntry(FileName);
return entry?.Open(); if (entry is null) return Stream.Null;
MemoryStream stream = new MemoryStream();
await (entry?.Open()!).CopyToAsync(stream);
return stream;
} }
/// <summary> /// <summary>
@@ -83,6 +87,11 @@ namespace PluginManager.Others
File.AppendAllText(errPath, ErrMessage + " \n"); File.AppendAllText(errPath, ErrMessage + " \n");
} }
public static void WriteErrFile(this Exception ex)
{
WriteErrFile(ex.ToString());
}
/// <summary> /// <summary>
/// Merge one array of strings into one string /// Merge one array of strings into one string
/// </summary> /// </summary>
@@ -164,9 +173,7 @@ namespace PluginManager.Others
/// <returns></returns> /// <returns></returns>
public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress, UnzipProgressType type) public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress, UnzipProgressType type)
{ {
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder); Directory.CreateDirectory(folder);
using (ZipArchive archive = ZipFile.OpenRead(zip)) using (ZipArchive archive = ZipFile.OpenRead(zip))
{ {
if (type == UnzipProgressType.PercentageFromNumberOfFiles) if (type == UnzipProgressType.PercentageFromNumberOfFiles)
@@ -190,7 +197,8 @@ namespace PluginManager.Others
currentZIPFile++; currentZIPFile++;
await Task.Delay(10); await Task.Delay(10);
progress.Report((float)currentZIPFile / totalZIPFiles * 100); if (progress != null)
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
} }
} }
else if (type == UnzipProgressType.PercentageFromTotalSize) else if (type == UnzipProgressType.PercentageFromTotalSize)
@@ -220,7 +228,8 @@ namespace PluginManager.Others
} }
await Task.Delay(10); await Task.Delay(10);
progress.Report((float)currentSize / zipSize * 100); if (progress != null)
progress.Report((float)currentSize / zipSize * 100);
} }
} }
} }
@@ -261,10 +270,9 @@ namespace PluginManager.Others
/// <returns></returns> /// <returns></returns>
public static async Task SaveToJsonFile<T>(string file, T Data) public static async Task SaveToJsonFile<T>(string file, T Data)
{ {
File.Delete(file); MemoryStream str = new MemoryStream();
var s = File.Open(file, FileMode.OpenOrCreate); await JsonSerializer.SerializeAsync(str, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
await JsonSerializer.SerializeAsync(s, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true }); await File.WriteAllBytesAsync(file, str.ToArray());
s.Close();
} }
/// <summary> /// <summary>
@@ -277,8 +285,7 @@ namespace PluginManager.Others
{ {
Stream text; Stream text;
if (File.Exists(input)) if (File.Exists(input))
text = File.OpenRead(input); text = new MemoryStream(await File.ReadAllBytesAsync(input));
else else
text = new MemoryStream(Encoding.ASCII.GetBytes(input)); text = new MemoryStream(Encoding.ASCII.GetBytes(input));
text.Position = 0; text.Position = 0;

View File

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

View File

@@ -1,12 +1,16 @@
using System.IO.Compression; using System.IO.Compression;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.Rest; using Discord.Rest;
using Discord.WebSocket; using Discord.WebSocket;
using Microsoft.Win32.SafeHandles; using Microsoft.Win32.SafeHandles;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Others; using PluginManager.Others;
using Roles.Internals; using Roles.Internals;
namespace Roles namespace Roles
@@ -21,15 +25,11 @@ namespace Roles
public string Usage => "addrole [user1] [user2] ... [role1] [role2] ..."; public string Usage => "addrole [user1] [user2] ... [role1] [role2] ...";
public bool canUseDM => false;
public bool canUseServer => true;
public bool requireAdmin => true; public bool requireAdmin => true;
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) public async void ExecuteServer(SocketCommandContext context)
{ {
if (message.MentionedUsers.Count == 0 || message.MentionedRoles.Count == 0) if (context.Message.MentionedUsers.Count == 0 || context.Message.MentionedRoles.Count == 0)
{ {
await context.Channel.SendMessageAsync($"Invalid invocation\nUsage:{Usage}"); await context.Channel.SendMessageAsync($"Invalid invocation\nUsage:{Usage}");
return; return;
@@ -37,15 +37,20 @@ namespace Roles
try try
{ {
var users = message.MentionedUsers; var users = context.Message.MentionedUsers;
var roles = message.MentionedRoles as IEnumerable<IRole>; var roles = context.Message.MentionedRoles;
foreach (var user in users) foreach (var user in users)
{ {
SocketGuildUser? usr = context.Client.GetUser(user.Username, user.Discriminator) as SocketGuildUser; foreach (var role in roles)
if (usr is null) {
throw new Exception("User is null"); try
await usr.AddRolesAsync(roles); {
await ((SocketGuildUser)context.Guild.GetUser(user.Id)).AddRoleAsync(role);
await context.Channel.SendMessageAsync($"User {user.Mention} got role : {role.Name}");
}
catch (Exception ex) { ex.WriteErrFile(); }
}
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -23,6 +23,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CMD_LevelingSystem", "CMD_L
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roles", "Roles\Roles.csproj", "{954F2AA9-6624-4554-946D-0F17B84487C3}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roles", "Roles\Roles.csproj", "{954F2AA9-6624-4554-946D-0F17B84487C3}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Others", "Others", "{727BBA0B-9114-4BC8-B9A8-3F461449A564}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Updater", "Updater\Updater.csproj", "{24616F7E-E2E9-45A3-8A44-AB51FCD2D525}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeGamesModule", "FreeGamesModule\FreeGamesModule.csproj", "{8959C766-414D-4EF8-BC85-9928B30AAF0A}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -57,6 +63,14 @@ Global
{954F2AA9-6624-4554-946D-0F17B84487C3}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{954F2AA9-6624-4554-946D-0F17B84487C3}.Release|Any CPU.Build.0 = 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
{8959C766-414D-4EF8-BC85-9928B30AAF0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8959C766-414D-4EF8-BC85-9928B30AAF0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8959C766-414D-4EF8-BC85-9928B30AAF0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8959C766-414D-4EF8-BC85-9928B30AAF0A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -69,6 +83,9 @@ Global
{EEC445DC-0C4B-43EA-8694-606BA0390B77} = {A290C028-77C4-4D1D-AB43-DDFE6ABD9012} {EEC445DC-0C4B-43EA-8694-606BA0390B77} = {A290C028-77C4-4D1D-AB43-DDFE6ABD9012}
{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9} = {449FA364-0B72-43FF-B3A3-806E2916200E} {1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9} = {449FA364-0B72-43FF-B3A3-806E2916200E}
{954F2AA9-6624-4554-946D-0F17B84487C3} = {449FA364-0B72-43FF-B3A3-806E2916200E} {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}
{8959C766-414D-4EF8-BC85-9928B30AAF0A} = {449FA364-0B72-43FF-B3A3-806E2916200E}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF} SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}

454
Updater/.gitignore vendored Normal file
View File

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

7
Updater/App.axaml Normal file
View File

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

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

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

12
Updater/MainWindow.axaml Normal file
View File

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

View File

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

34
Updater/Program.cs Normal file
View File

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

27
Updater/Updater.csproj Normal file
View File

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