diff --git a/DeukBot4/DeukBot4.csproj.DotSettings b/DeukBot4/DeukBot4.csproj.DotSettings index 7646070..1ffadd4 100644 --- a/DeukBot4/DeukBot4.csproj.DotSettings +++ b/DeukBot4/DeukBot4.csproj.DotSettings @@ -1,2 +1,3 @@  - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/DeukBot4/MessageHandlers/Attributes/BlockUsageInPMAttribute.cs b/DeukBot4/MessageHandlers/Attributes/BlockUsageInPMAttribute.cs new file mode 100644 index 0000000..76dc46b --- /dev/null +++ b/DeukBot4/MessageHandlers/Attributes/BlockUsageInPMAttribute.cs @@ -0,0 +1,10 @@ +using System; + +namespace DeukBot4.MessageHandlers +{ + [AttributeUsage(AttributeTargets.Method)] + public class BlockUsageInPmAttribute : Attribute + { + + } +} \ No newline at end of file diff --git a/DeukBot4/MessageHandlers/Attributes/CommandParametersAttribute.cs b/DeukBot4/MessageHandlers/Attributes/CommandParametersAttribute.cs index 0789b2d..de1290b 100644 --- a/DeukBot4/MessageHandlers/Attributes/CommandParametersAttribute.cs +++ b/DeukBot4/MessageHandlers/Attributes/CommandParametersAttribute.cs @@ -12,5 +12,20 @@ namespace DeukBot4.MessageHandlers { Types = types; } + + public CommandParametersAttribute(ParameterMatcher.ParameterType type) + { + Types = new []{type}; + } + public CommandParametersAttribute(ParameterMatcher.ParameterType type, ParameterMatcher.ParameterType type2) + { + Types = new []{type, type2}; + } + public CommandParametersAttribute(ParameterMatcher.ParameterType type, ParameterMatcher.ParameterType type2, + ParameterMatcher.ParameterType type3) + { + Types = new []{type, type2, type3}; + } + } } \ No newline at end of file diff --git a/DeukBot4/MessageHandlers/CommandHandler/Command.cs b/DeukBot4/MessageHandlers/CommandHandler/Command.cs index f0d58f2..010673e 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/Command.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/Command.cs @@ -9,7 +9,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler { public class Command { - public Command(string name, PermissionLevel permission, string shortHelp, string longHelp, + public Command(string name, PermissionLevel permission, string shortHelp, string longHelp, bool forbidInPm, ParameterMatcher.ParameterType[][] parameterTypes, MethodInfo function, CommandContainerBase commandContainer) { Name = name; @@ -20,9 +20,10 @@ namespace DeukBot4.MessageHandlers.CommandHandler CommandContainer = commandContainer; ParameterTypes = parameterTypes; HasHelp = true; + ForbidInPm = forbidInPm; } - public Command(string name, PermissionLevel permission, ParameterMatcher.ParameterType[][] parameterTypes, + public Command(string name, PermissionLevel permission, ParameterMatcher.ParameterType[][] parameterTypes, bool forbidInPm, MethodInfo function, CommandContainerBase commandContainer) { Name = name; @@ -31,6 +32,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler CommandContainer = commandContainer; ParameterTypes = parameterTypes; HasHelp = false; + ForbidInPm = forbidInPm; } public string Name { get; } @@ -41,6 +43,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler public CommandContainerBase CommandContainer { get; } public bool HasHelp { get; } public ParameterMatcher.ParameterType[][] ParameterTypes { get; } + public bool ForbidInPm { get; } private string[] _parameterMatchers; diff --git a/DeukBot4/MessageHandlers/CommandHandler/CommandContainerBase.cs b/DeukBot4/MessageHandlers/CommandHandler/CommandContainerBase.cs index f84b7ed..a9557e7 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/CommandContainerBase.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/CommandContainerBase.cs @@ -33,19 +33,21 @@ namespace DeukBot4.MessageHandlers.CommandHandler parametersAttributes.ToArray(); var parameters = commandParametersAttributes.Select(x => x.Types).ToArray(); + var forbidPm = methodInfo.GetCustomAttributes(typeof(BlockUsageInPmAttribute), true).Any(); + foreach (var commandAttribute in commandAttributes) { if (commandAttribute == null) continue; if (helpAttribute == null) { - commands.Add(new Command(commandAttribute.Command, commandAttribute.Permission, parameters, + commands.Add(new Command(commandAttribute.Command, commandAttribute.Permission, parameters, forbidPm, methodInfo, this)); } else { commands.Add(new Command(commandAttribute.Command, commandAttribute.Permission, - helpAttribute.ShortHelp, helpAttribute.LongHelp, parameters, methodInfo, this)); + helpAttribute.ShortHelp, helpAttribute.LongHelp, forbidPm, parameters, methodInfo, this)); } } diff --git a/DeukBot4/MessageHandlers/CommandHandler/CommandHandler.cs b/DeukBot4/MessageHandlers/CommandHandler/CommandHandler.cs index c9ed185..7b9f586 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/CommandHandler.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/CommandHandler.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using DeukBot4.MessageHandlers.CommandHandler.RequestStructure; using DeukBot4.MessageHandlers.Permissions; using DeukBot4.Utilities; +using Discord; using Discord.WebSocket; namespace DeukBot4.MessageHandlers.CommandHandler @@ -53,10 +54,17 @@ namespace DeukBot4.MessageHandlers.CommandHandler { await Logger.Log( $"Unauthorized user tried to run command: {message.Author.Username} -> {message.Content}"); - } + else if (resultCode == CommandRequest.RequestCode.OK) { + if (!(message.Channel is IGuildChannel) && req.Item1.Command.ForbidInPm) + { + await Logger.Log( + $"User is trying to use blocked command in PM: {message.Author.Username}"); + return; + } + await req.Item1.Command.Invoke(req.Item1); } diff --git a/DeukBot4/MessageHandlers/CommandHandler/GeneralCommands.cs b/DeukBot4/MessageHandlers/CommandHandler/Commands/GeneralCommands.cs similarity index 100% rename from DeukBot4/MessageHandlers/CommandHandler/GeneralCommands.cs rename to DeukBot4/MessageHandlers/CommandHandler/Commands/GeneralCommands.cs diff --git a/DeukBot4/MessageHandlers/CommandHandler/Commands/ModeratorCommands.cs b/DeukBot4/MessageHandlers/CommandHandler/Commands/ModeratorCommands.cs new file mode 100644 index 0000000..f63152b --- /dev/null +++ b/DeukBot4/MessageHandlers/CommandHandler/Commands/ModeratorCommands.cs @@ -0,0 +1,55 @@ +using System.Threading.Tasks; +using DeukBot4.MessageHandlers.CommandHandler.RequestStructure; +using DeukBot4.MessageHandlers.Permissions; +using Discord; +using Discord.WebSocket; + +namespace DeukBot4.MessageHandlers.CommandHandler +{ + public class ModeratorCommands : CommandContainerBase + { + public override string Name => "Moderator"; + + [Command("kick", PermissionLevel.Moderator)] + [CommandParameters(ParameterMatcher.ParameterType.User, ParameterMatcher.ParameterType.Remainder)] + [BlockUsageInPm] + public async Task KickUser(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; + + // if no parameters are found, stop + if (request.Parameters.Length == 0) + return; + // if the first parameter is empty, stop, this means it's not a valid user id + if (string.IsNullOrWhiteSpace(request.Parameters[0].AsString())) + return; + + // get the id, this parses the string to an id + var id = request.Parameters[0].AsUlong(); + // get the user using this id and the channel object. + var user = await channel.Guild.GetUserAsync(id); + + // 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 this bot, 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 kick 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 kick + await user.KickAsync(reason); + } + } +} \ No newline at end of file diff --git a/DeukBot4/MessageHandlers/CommandHandler/RolePermissionCommands.cs b/DeukBot4/MessageHandlers/CommandHandler/Commands/RolePermissionCommands.cs similarity index 99% rename from DeukBot4/MessageHandlers/CommandHandler/RolePermissionCommands.cs rename to DeukBot4/MessageHandlers/CommandHandler/Commands/RolePermissionCommands.cs index 8b8ea96..cddfed9 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/RolePermissionCommands.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/Commands/RolePermissionCommands.cs @@ -14,6 +14,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler [Command("roles", PermissionLevel.Admin)] [CommandHelp("Lists all roles on the server along with their IDs", "Lists all roles on the server along with their IDs")] + [BlockUsageInPm] public async Task ListServerRoles(CommandRequest request) { var channel = request.OriginalMessage.Channel; diff --git a/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/ParameterMatcher.cs b/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/ParameterMatcher.cs index aea5009..6121d3e 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/ParameterMatcher.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/ParameterMatcher.cs @@ -12,6 +12,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler.RequestStructure Word, Number, Remainder, + User, } public static string[] GenerateRegex(Command command) @@ -38,6 +39,8 @@ namespace DeukBot4.MessageHandlers.CommandHandler.RequestStructure return " *(\\d+)"; case ParameterType.Remainder: return " *(.*)"; + case ParameterType.User: + return " *(?:<@(?\\d*)>)|(?\\d*)"; default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } diff --git a/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/RequestParameter.cs b/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/RequestParameter.cs index 3b77c6e..48b8667 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/RequestParameter.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/RequestStructure/RequestParameter.cs @@ -24,5 +24,14 @@ namespace DeukBot4.MessageHandlers.CommandHandler.RequestStructure { return _value; } + + public ulong AsUlong() + { + if (ulong.TryParse(_value, out var i)) + { + return i; + } + throw new ArgumentException(); + } } } \ No newline at end of file diff --git a/DeukBot4/MessageHandlers/Permissions/PermissionValidator.cs b/DeukBot4/MessageHandlers/Permissions/PermissionValidator.cs index ed272c0..eef3a43 100644 --- a/DeukBot4/MessageHandlers/Permissions/PermissionValidator.cs +++ b/DeukBot4/MessageHandlers/Permissions/PermissionValidator.cs @@ -80,25 +80,32 @@ namespace DeukBot4.MessageHandlers.Permissions public static async Task GetUserPermissionLevel(SocketMessage message) { - if (message.Author.Id == Program.Settings.OwnerId) + return await GetUserPermissionLevel(message.Channel, message.Author); + } + + public static async Task GetUserPermissionLevel(ISocketMessageChannel channel, SocketUser user) + { + if (user.Id == Program.Settings.OwnerId) { return PermissionLevel.BotCreator; } - if (message.Author.IsBot) + if (user.IsBot) { return PermissionLevel.Bot; } - if (!(message.Channel is IGuildChannel serverChannel)) + if (!(channel is IGuildChannel serverChannel)) return PermissionLevel.Everyone; - if (serverChannel.Guild.OwnerId == message.Author.Id) + + if (serverChannel.Guild.OwnerId == user.Id) return PermissionLevel.ServerOwner; - if (!(message.Author is IGuildUser user)) + if (!(user is IGuildUser guildUser)) return PermissionLevel.Everyone; - var perms = await GetDatabasePermissionLevel(serverChannel.GuildId, user.RoleIds.ToArray()); + var perms = await GetDatabasePermissionLevel(serverChannel.GuildId, guildUser.RoleIds.ToArray()); return perms; + } } } \ No newline at end of file