9 Commits

Author SHA1 Message Date
8b36c086ef New Command added & Leveling System update 2022-08-17 14:19:46 +03:00
1f5e5d0611 patch 2022-08-17 10:09:02 +03:00
bbc1c601c9 Patching system build 2 2022-08-17 09:58:54 +03:00
5ab3195956 2022-08-16 23:08:56 +03:00
1f1983480a 2022-08-16 16:14:25 +03:00
2fcd86cf12 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-08-16 16:12:38 +03:00
2c83d00c00 2022-08-16 16:12:14 +03:00
Wizzy69
ccac0ca6d0 Update README.md 2022-07-26 15:15:13 +03:00
4c9c7410f0 2022-07-17 19:31:59 +03:00
51 changed files with 767 additions and 148 deletions

13
.idea/.idea.SethDiscordBot/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,13 @@
# 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

1
.idea/.idea.SethDiscordBot/.idea/.name generated Normal file
View File

@@ -0,0 +1 @@
SethDiscordBot

View File

@@ -0,0 +1,4 @@
<?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,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,15 +2,13 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.Loader;
using System.Threading;
using System.Threading.Tasks;
using Discord.WebSocket;
using DiscordBot.Discord.Core;
using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Items;
using PluginManager.Online;
using PluginManager.Others;
@@ -29,11 +27,44 @@ public class Program
[Obsolete]
public static void Main(string[] args)
{
Directory.CreateDirectory("./Data/Resources");
Directory.CreateDirectory("./Data/Plugins/Commands");
Directory.CreateDirectory("./Data/Plugins/Events");
PreLoadComponents().Wait();
if (!Config.ContainsKey("ServerID"))
{
do
{
Console.Clear();
Console.WriteLine("Please enter the server ID: ");
Console_Utilities.WriteColorText("You can find it in the Server Settings at &r\"Widget\"&c section");
Console.WriteLine("Example: 1234567890123456789");
Console.WriteLine("This is not required, but is recommended. If you refuse to provide the ID, just press enter.\nThe server id is required to make easier for the bot to interact with the server.\nRemember: this bot is for one server ONLY.");
Console.Write("User Input > ");
ConsoleKeyInfo key = Console.ReadKey();
if (key.Key == ConsoleKey.Enter)
Config.AddValueToVariables("ServerID", "null", false);
else
{
string SID = key.KeyChar + Console.ReadLine();
if (SID.Length != 18)
{
Console.WriteLine("Your server ID is not 18 characters long. Please try again.");
continue;
}
Config.AddValueToVariables("ServerID", SID, false);
}
break;
} while (true);
}
if (!Config.ContainsKey("token") || Config.GetValue<string>("token") == null || Config.GetValue<string>("token")?.Length != 70)
{
Console.WriteLine("Please insert your token");
@@ -75,26 +106,24 @@ public class Program
private static void NoGUI(Boot discordbooter)
{
var consoleCommandsHandler = new ConsoleCommandsHandler(discordbooter.client);
#if DEBUG
Console.WriteLine();
consoleCommandsHandler.HandleCommand("lp");
#else
if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp");
if (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs");
#endif
Config.SaveConfig();
while (true)
{
Console.ForegroundColor = ConsoleColor.White;
//Console_Utilities.WriteColorText("&rSethBot (&yDEBUG&r) &c> ", false);
var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd!,
#if DEBUG
Console_Utilities.WriteColorText("&rSethBot (&yDEBUG&r) &c> ", false);
var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd!, false) && cmd.Length > 0)
Console.WriteLine("Failed to run command " + cmd);
#else
Console_Utilities.WriteColorText("&rSethBot &c> ", false);
var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd!) && cmd.Length > 0)
Console.WriteLine("Failed to run command " + cmd);
false
#endif
) && cmd.Length > 0)
Console.WriteLine("Failed to run command " + cmd);
}
}
@@ -153,7 +182,7 @@ public class Program
/// <param name="d">Directory path</param>
private static Task ClearFolder(string d)
{
var files = Directory.GetFiles(d);
var files = Directory.GetFiles(d);
var fileNumb = files.Length;
for (var i = 0; i < fileNumb; i++)
{
@@ -174,7 +203,7 @@ public class Program
if (len == 3 && args[0] == "/download")
{
var url = args[1];
var url = args[1];
var location = args[2];
await ServerCom.DownloadFileAsync(url, location);
@@ -195,7 +224,7 @@ public class Program
if (len == 0 || (args[0] != "--exec" && args[0] != "--execute"))
{
var b = await StartNoGUI();
var b = await StartNoGUI();
Thread mainThread = new Thread(() => NoGUI(b));
mainThread.Start();
@@ -238,7 +267,7 @@ public class Program
case "--reset-logs":
await ClearFolder("./Output/Logs");
await ClearFolder("./Output/Errors");
Console.WriteLine("Successfully cleard logs folder");
Console.WriteLine("Successfully clear logs folder");
break;
case "--exit":
case "exit":
@@ -264,9 +293,9 @@ public class Program
Config.PluginConfig.Load();
if (!Config.ContainsKey("Version"))
Config.AddValueToVariables("Version", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), false);
Config.AddValueToVariables("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(), false);
else
Config.SetValue("Version", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
Config.SetValue("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
foreach (var key in OnlineDefaultKeys)
{
@@ -311,7 +340,7 @@ public class Program
Console.WriteLine("\n\n");
await Task.Delay(1000);
int waitTime = 20; //wait time to proceed
int waitTime = 10; //wait time to proceed
Console.Write($"The bot will start in {waitTime} seconds");
while (waitTime > 0)

View File

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

View File

@@ -0,0 +1,21 @@
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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,7 +12,9 @@ namespace PluginManager
internal class AppConfig
{
public Dictionary<string, object>? ApplicationVariables { get; init; }
public List<string>? ProtectedKeyWords { get; init; }
public List<string>? ProtectedKeyWords { get; init; }
public Dictionary<string, string> PluginVersions { get; init; }
}
public static class Config
@@ -29,27 +31,27 @@ namespace PluginManager
private static void LoadCommands()
{
string cmd_path = "./Data/Plugins/Commands/";
string[] files = Directory.GetFiles(cmd_path, $"*.{Loaders.PluginLoader.pluginCMDExtension}", SearchOption.AllDirectories);
string cmd_path = "./Data/Plugins/Commands/";
string[] files = Directory.GetFiles(cmd_path, $"*.{Loaders.PluginLoader.pluginCMDExtension}", SearchOption.AllDirectories);
foreach (var file in files)
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
{
string PluginName = new FileInfo(file).Name;
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginCMDExtension.Length);
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginCMDExtension.Length);
InstalledPlugins.Add(new(name, PluginType.Command));
}
}
private static void LoadEvents()
{
string eve_path = "./Data/Plugins/Events/";
string[] files = Directory.GetFiles(eve_path, $"*.{Loaders.PluginLoader.pluginEVEExtension}", SearchOption.AllDirectories);
string eve_path = "./Data/Plugins/Events/";
string[] files = Directory.GetFiles(eve_path, $"*.{Loaders.PluginLoader.pluginEVEExtension}", SearchOption.AllDirectories);
foreach (var file in files)
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
{
string PluginName = new FileInfo(file).Name;
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginEVEExtension.Length);
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginEVEExtension.Length);
InstalledPlugins.Add(new(name, PluginType.Event));
}
}
@@ -67,9 +69,9 @@ namespace PluginManager
public static PluginType GetPluginType(string pluginName)
{
foreach (var tuple in InstalledPlugins)
{
if (tuple.Item1 == pluginName) return tuple.Item2;
}
if (tuple.Item1 == pluginName)
return tuple.Item2;
return PluginType.Unknown;
}
@@ -77,6 +79,19 @@ namespace PluginManager
private static AppConfig? appConfig { get; set; }
public static string GetPluginVersion(string pluginName) => appConfig.PluginVersions[pluginName];
public static void SetPluginVersion(string pluginName, string newVersion)
{
if (appConfig.PluginVersions.ContainsKey(pluginName))
appConfig.PluginVersions[pluginName] = newVersion;
else appConfig.PluginVersions.Add(pluginName, newVersion);
// SaveConfig();
}
public static void RemovePluginVersion(string pluginName) => appConfig.PluginVersions.Remove(pluginName);
public static bool PluginVersionsContainsKey(string pluginName) => appConfig.PluginVersions.ContainsKey(pluginName);
public static void AddValueToVariables<T>(string key, T value, bool isProtected)
{
if (value == null)
@@ -183,11 +198,11 @@ namespace PluginManager
Functions.WriteLogFile($"Loaded {appConfig.ApplicationVariables!.Keys.Count} application variables.\nLoaded {appConfig.ProtectedKeyWords!.Count} readonly variables.");
}
else
appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>() };
appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>(), PluginVersions = new Dictionary<string, string>() };
}
public static bool ContainsValue<T>(T value) => appConfig!.ApplicationVariables!.ContainsValue(value!);
public static bool ContainsKey(string key) => appConfig!.ApplicationVariables!.ContainsKey(key);
public static bool ContainsKey(string key) => appConfig!.ApplicationVariables!.ContainsKey(key);
public static ReadOnlyDictionary<string, object> GetAllVariables() => new(appConfig!.ApplicationVariables!);
}

View File

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

View File

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

View File

@@ -2,20 +2,31 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Discord.WebSocket;
using PluginManager.Interfaces;
using PluginManager.Loaders;
using PluginManager.Online;
using PluginManager.Online.Helpers;
using PluginManager.Online.Updates;
using PluginManager.Others;
namespace PluginManager.Items;
public class ConsoleCommandsHandler
{
private static readonly PluginsManager manager = new("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Plugins.txt");
private static readonly PluginsManager manager = new("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Plugins.txt");
private static readonly List<ConsoleCommand> commandList = new();
private readonly DiscordSocketClient? client;
private readonly DiscordSocketClient? client;
private static bool isDownloading = false;
private static bool pluginsLoaded = false;
public ConsoleCommandsHandler(DiscordSocketClient client)
{
@@ -26,7 +37,7 @@ public class ConsoleCommandsHandler
private void InitializeBasicCommands()
{
var pluginsLoaded = false;
commandList.Clear();
AddCommand("help", "Show help", "help <command>", args =>
@@ -101,8 +112,10 @@ public class ConsoleCommandsHandler
AddCommand("dwplug", "download plugin", "dwplug [name]", async args =>
{
isDownloading = true;
if (args.Length == 1)
{
isDownloading = false;
Console.WriteLine("Please specify plugin name");
return;
}
@@ -116,10 +129,11 @@ public class ConsoleCommandsHandler
{
if (name == "")
{
isDownloading = false;
Console_Utilities.WriteColorText("Name is invalid");
return;
}
isDownloading = false;
Console_Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" + " Use &glistplugs &ccommand to display all available plugins !");
return;
}
@@ -160,9 +174,9 @@ public class ConsoleCommandsHandler
if (split[0].EndsWith(".zip") || split[0].EndsWith(".pak") || split[0].EndsWith(".pkg"))
{
Console.WriteLine($"Extracting {split[1]}");
var proc = 0f;
var proc = 0f;
var isExtracting = true;
var bar = new Console_Utilities.ProgressBar { Max = 100f, Color = ConsoleColor.Green };
var bar = new Console_Utilities.ProgressBar { Max = 100f, Color = ConsoleColor.Green };
IProgress<float> extractProgress = new Progress<float>(value => { proc = value; });
new Thread(new Task(() =>
@@ -189,6 +203,12 @@ public class ConsoleCommandsHandler
Console.WriteLine();
}
VersionString? ver = await VersionString.GetVersionOfPackageFromWeb(name);
if (ver is null) throw new Exception("Incorrect version");
Config.SetPluginVersion(name, $"{ver.PackageID}.{ver.PackageMainVersion}.{ver.PackageCheckVersion}");
// Console.WriteLine();
isDownloading = false;
}
);
@@ -209,8 +229,8 @@ public class ConsoleCommandsHandler
{
if (args.Length < 4)
return;
var key = args[1];
var value = args[2];
var key = args[1];
var value = args[2];
var isReadOnly = args[3].Equals("true", StringComparison.CurrentCultureIgnoreCase);
try
@@ -233,18 +253,47 @@ public class ConsoleCommandsHandler
}
);
AddCommand("sd", "Shuts down the discord bot", async () =>
AddCommand("sd", "Shuts down the discord bot", () =>
{
if (client is null)
return;
await client.StopAsync();
await client.DisposeAsync();
client.StopAsync();
client.DisposeAsync();
Config.SaveConfig();
Console.WriteLine("Bot is closing in 2 seconds ! Please wait to save data !");
await Task.Delay(2000);
Thread.Sleep(2000);
Environment.Exit(0);
}
);
AddCommand("extern", "Load an external command", "extern [pluginName]", async (args) =>
{
if (args.Length <= 1) return;
string pName = Functions.MergeStrings(args, 1);
HttpClient client = new HttpClient();
string url = (await manager.GetPluginLinkByName(pName))[1];
Stream s = await client.GetStreamAsync(url);
MemoryStream str = new MemoryStream();
await s.CopyToAsync(str);
var asmb = Assembly.Load(str.ToArray());
var types = asmb.GetTypes();
foreach (var type in types)
{
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
{
DBEvent instance = (DBEvent)Activator.CreateInstance(type);
instance.Start(this.client);
Console.WriteLine($"Loaded external {type.FullName}!");
}
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
{
Console.WriteLine("Only events can be loaded from external sources !");
return;
}
}
});
//Sort the commands by name
commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName));
}
@@ -268,7 +317,7 @@ public class ConsoleCommandsHandler
public static bool CommandExists(string command)
{
return !(GetCommand(command) is null);
return GetCommand(command) is not null;
}
public static ConsoleCommand? GetCommand(string command)
@@ -276,8 +325,23 @@ public class ConsoleCommandsHandler
return commandList.FirstOrDefault(t => t.CommandName == command);
}
internal static async Task ExecuteCommad(string command)
{
var args = command.Split(' ');
foreach (var item in commandList.ToList())
if (item.CommandName == args[0])
{
item.Action.Invoke(args);
Console.WriteLine();
while (isDownloading) await Task.Delay(1000);
}
}
public bool HandleCommand(string command, bool removeCommandExecution = true)
{
Console.ForegroundColor = ConsoleColor.White;
var args = command.Split(' ');
foreach (var item in commandList.ToList())
if (item.CommandName == args[0])
@@ -292,6 +356,7 @@ public class ConsoleCommandsHandler
Console.WriteLine();
item.Action(args);
return true;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -57,7 +57,7 @@ namespace PluginManager.Others
if (!File.Exists(archFile)) throw new FileNotFoundException("Failed to load file !");
using ZipArchive archive = ZipFile.OpenRead(archFile);
ZipArchiveEntry? entry = archive.GetEntry(FileName);
ZipArchiveEntry? entry = archive.GetEntry(FileName);
return entry?.Open();
}
@@ -68,7 +68,7 @@ namespace PluginManager.Others
public static void WriteLogFile(string LogMessage)
{
string logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
if (!Directory.Exists(logFolder)) Directory.CreateDirectory(logFolder);
Directory.CreateDirectory(logFolder);
File.AppendAllText(logsPath, LogMessage + " \n");
}
@@ -79,7 +79,7 @@ namespace PluginManager.Others
public static void WriteErrFile(string ErrMessage)
{
string errPath = errFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
if (!Directory.Exists(errFolder)) Directory.CreateDirectory(errFolder);
Directory.CreateDirectory(errFolder);
File.AppendAllText(errPath, ErrMessage + " \n");
}
@@ -91,8 +91,8 @@ namespace PluginManager.Others
/// <returns>A string built based on the array</returns>
public static string MergeStrings(this string[] s, int indexToStart)
{
string r = "";
int len = s.Length;
string r = "";
int len = s.Length;
if (len <= indexToStart) return "";
for (int i = indexToStart; i < len - 1; ++i)
{
@@ -142,9 +142,9 @@ namespace PluginManager.Others
if (!stream.CanRead) throw new InvalidOperationException("The stream is not readable.");
if (!destination.CanWrite) throw new ArgumentException("Destination stream is not writable", nameof(destination));
byte[] buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
byte[] buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
@@ -171,11 +171,11 @@ namespace PluginManager.Others
{
if (type == UnzipProgressType.PercentageFromNumberOfFiles)
{
int totalZIPFiles = archive.Entries.Count();
int totalZIPFiles = archive.Entries.Count();
int currentZIPFile = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith("/"))
if (entry.FullName.EndsWith("/")) // it is a folder
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
else
@@ -261,7 +261,8 @@ namespace PluginManager.Others
/// <returns></returns>
public static async Task SaveToJsonFile<T>(string file, T Data)
{
var s = File.OpenWrite(file);
File.Delete(file);
var s = File.Open(file, FileMode.OpenOrCreate);
await JsonSerializer.SerializeAsync(s, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
s.Close();
}
@@ -276,7 +277,7 @@ namespace PluginManager.Others
{
Stream text;
if (File.Exists(input))
text = File.Open(input, FileMode.OpenOrCreate);
text = File.OpenRead(input);
else
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
@@ -335,7 +336,7 @@ namespace PluginManager.Others
using (MD5 md5 = MD5.Create())
{
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
byte[] hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes);
}
}

View File

@@ -16,9 +16,10 @@ Plugin Types:
1. Commands
2. Events
<!--
Project Structure
![Image](../../blob/gh-pages/Pictures/architecture2.png)
![Image](../../blob/gh-pages/Pictures/architecture2.png)-->
### How to create a plugin

57
Roles/AddRole.cs Normal file
View File

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

View File

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

13
Roles/Roles.csproj Normal file
View File

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

View File

@@ -21,6 +21,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EVE_LevelingSystem", "EVE_L
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CMD_LevelingSystem", "CMD_LevelingSystem\CMD_LevelingSystem.csproj", "{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roles", "Roles\Roles.csproj", "{954F2AA9-6624-4554-946D-0F17B84487C3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -51,6 +53,10 @@ Global
{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9}.Release|Any CPU.Build.0 = Release|Any CPU
{954F2AA9-6624-4554-946D-0F17B84487C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{954F2AA9-6624-4554-946D-0F17B84487C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{954F2AA9-6624-4554-946D-0F17B84487C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{954F2AA9-6624-4554-946D-0F17B84487C3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -62,6 +68,7 @@ Global
{B1B4976E-5112-4217-B57B-3A03C5207B6E} = {449FA364-0B72-43FF-B3A3-806E2916200E}
{EEC445DC-0C4B-43EA-8694-606BA0390B77} = {A290C028-77C4-4D1D-AB43-DDFE6ABD9012}
{1A4E49FF-9A0A-4C54-AF35-CFFBA64353D9} = {449FA364-0B72-43FF-B3A3-806E2916200E}
{954F2AA9-6624-4554-946D-0F17B84487C3} = {449FA364-0B72-43FF-B3A3-806E2916200E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}