diff --git a/DeukBot4/MessageHandlers/CommandHandler/CommandHandler.cs b/DeukBot4/MessageHandlers/CommandHandler/CommandHandler.cs index bfc2f53..2c4b897 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/CommandHandler.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/CommandHandler.cs @@ -14,7 +14,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler public static class CommandHandler { public static Dictionary Commands { get; } = new Dictionary(); - private const char CommandTrigger = '!'; + public const char CommandTrigger = '!'; public static void Build() { @@ -43,7 +43,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler if (string.IsNullOrWhiteSpace(message.Content)) return; - if (message.Content[0] != CommandTrigger) + if (message.Content[0] != CommandTrigger && message.MentionedUsers.All(x => x.Id != Program.BotId)) return; var req = await CommandRequest.Create(message); @@ -53,6 +53,9 @@ namespace DeukBot4.MessageHandlers.CommandHandler case CommandRequest.RequestCode.Invalid: await Logger.LogError("Invalid content: " + message.Content); return; + case CommandRequest.RequestCode.InvalidParameters: + await Logger.LogError("Invalid parameters: " + message.Content); + break; case CommandRequest.RequestCode.Forbidden: await Logger.Log( $"Unauthorized user tried to run command: {message.Author.Username} -> {message.Content}"); @@ -67,21 +70,25 @@ namespace DeukBot4.MessageHandlers.CommandHandler await req.Item1.Command.Invoke(req.Item1); break; case CommandRequest.RequestCode.UnknownCommand: - var similar = await GetSimilarCommand(req.Item3.ToString()); + var permission = await PermissionValidator.GetUserPermissionLevel(message); + var similar = await GetSimilarCommand(req.Item3.ToString(), permission); await message.Channel.SendMessageAsync( - $"Unknown command: ``{req.Item3.ToString()}``. Did you mean: ``{similar}``?"); + $"Unknown command: ``{req.Item3.ToString()}``. Did you mean: ``{similar}``? " + + $"Alternatively, use ``{CommandTrigger}help`` for a list of all commands"); break; default: throw new ArgumentOutOfRangeException(); } } - private static async Task GetSimilarCommand(string command) + private static async Task GetSimilarCommand(string command, PermissionLevel permission) { var closestString = ""; var similarity = int.MaxValue; foreach (var cmd in Commands) { + if (cmd.Value.Permission > permission) + continue; var distance = Lehvenstein.LevenshteinDistance(command, cmd.Key); if (distance >= similarity) continue; diff --git a/DeukBot4/MessageHandlers/CommandHandler/Commands/ModeratorCommands.cs b/DeukBot4/MessageHandlers/CommandHandler/Commands/ModeratorCommands.cs index 6830cd8..d858da4 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/Commands/ModeratorCommands.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/Commands/ModeratorCommands.cs @@ -47,5 +47,36 @@ namespace DeukBot4.MessageHandlers.CommandHandler // and kick await user.KickAsync(reason); } + + [Command("ban", PermissionLevel.Moderator)] + public async Task BanUser(CommandRequest request) + { + // get the server channel object out of message. Return if it's somehow not a server channel + if (!(request.OriginalMessage.Channel is IGuildChannel channel)) + return; + + // get the id of the user, this parses the string to an id + var user = await request.Parameters[0].AsDiscordUser(channel.Guild); + + // get the permissions of the user we want to kick + var userPermissions = + await PermissionValidator.GetUserPermissionLevel(request.OriginalMessage.Channel, (SocketUser) user); + // if the user has sufficient permissions, or is deukbot, warn the user that he's not allowed to do that, and stop + if (userPermissions >= PermissionLevel.Helper || user.Id == Program.Client.CurrentUser.Id) + { + await request.OriginalMessage.Channel.SendMessageAsync("You are not allowed to ban that user"); + return; + } + + // see if a reason was given, use that if so + var reason = string.Empty; + if (request.Parameters.Length >= 2) + { + reason = request.Parameters[1].AsString(); + } + + // and ban + await channel.Guild.AddBanAsync(user, 0, reason); + } } } \ No newline at end of file diff --git a/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/CommandRequest.cs b/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/CommandRequest.cs index 1a87245..ff6147c 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/CommandRequest.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/CommandRequest.cs @@ -9,11 +9,11 @@ namespace DeukBot4.MessageHandlers.CommandHandler.RequestStructure { public class CommandRequest { - private const string CommandNamePattern = "!([a-zA-Z0-9_]*) *(.*)"; + private static readonly string CommandNamePattern = + "(?:" + CommandHandler.CommandTrigger + "+|<@\\d*> !*)([^ ]+) *(.*)"; private static readonly Regex CommandNameMatcher = new Regex(CommandNamePattern); public Command Command { get; } - //public string ParameterString { get; } public SocketMessage OriginalMessage { get; } public RequestParameter[] Parameters { get; private set; } public PermissionLevel RequestPermissions { get; } @@ -28,7 +28,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler.RequestStructure public enum RequestCode { - OK, UnknownCommand, Invalid, Forbidden + OK, UnknownCommand, Invalid, Forbidden, InvalidParameters } public static async Task<(CommandRequest, RequestCode, object)> Create(SocketMessage message) @@ -64,7 +64,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler.RequestStructure var parameters = ParameterMatcher.GetParameterValues(command, parameterString); if (parameters == null) { - return (null, RequestCode.Invalid, parameterString); + return (null, RequestCode.InvalidParameters, parameterString); } return (new CommandRequest(originalMessage, command, permission, parameters), RequestCode.OK, null); } diff --git a/DeukBot4/Program.cs b/DeukBot4/Program.cs index a97739f..b9060ce 100644 --- a/DeukBot4/Program.cs +++ b/DeukBot4/Program.cs @@ -9,10 +9,11 @@ using Discord.WebSocket; namespace DeukBot4 { - class Program + internal static class Program { public static DiscordSocketClient Client { get; private set; } public static Settings Settings { get; private set; } + public static ulong BotId { get; private set; } private static void Main(string[] args) { @@ -46,6 +47,7 @@ namespace DeukBot4 { properties.Username = Settings.Username; }); + BotId = Client.CurrentUser.Id; } } } \ No newline at end of file