diff --git a/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs b/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs index a3268570..94de43f6 100644 --- a/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs +++ b/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs @@ -14,6 +14,9 @@ namespace NadekoBot.Modules.Permissions.Classes { public static PermissionChecker Instance { get; } = new PermissionChecker(); + //key - sid:command + //value - userid + private ConcurrentDictionary commandCooldowns = new ConcurrentDictionary(); private HashSet timeBlackList { get; } = new HashSet(); static PermissionChecker() { } @@ -50,15 +53,23 @@ namespace NadekoBot.Modules.Permissions.Classes if (timeBlackList.Contains(user.Id)) return false; - timeBlackList.Add(user.Id); - if (!channel.IsPrivate && !channel.Server.CurrentUser.GetPermissions(channel).SendMessages) { return false; } - //{ - // user.SendMessage($"I ignored your command in {channel.Server.Name}/#{channel.Name} because i don't have permissions to write to it. Please use `;acm channel_name 0` in that server instead of muting me.").GetAwaiter().GetResult(); - //} + + timeBlackList.Add(user.Id); + + ServerPermissions perms; + PermissionsHandler.PermissionsDict.TryGetValue(user.Server.Id, out perms); + + AddUserCooldown(user.Server.Id, user.Id, command.Text.ToLower()); + if (commandCooldowns.Keys.Contains(user.Server.Id+":"+command.Text.ToLower())) + { + if(perms?.Verbose == true) + error = $"{user.Mention} You have a cooldown on that command."; + return false; + } try { @@ -76,8 +87,6 @@ namespace NadekoBot.Modules.Permissions.Classes catch { } if (user.Server.Owner.Id == user.Id || (role != null && user.HasRole(role))) return true; - ServerPermissions perms; - PermissionsHandler.PermissionsDict.TryGetValue(user.Server.Id, out perms); throw new Exception($"You don't have the necessary role (**{(perms?.PermissionsControllerRole ?? "Nadeko")}**) to change permissions."); } @@ -129,8 +138,7 @@ namespace NadekoBot.Modules.Permissions.Classes Console.WriteLine($"Exception in canrun: {ex}"); try { - ServerPermissions perms; - if (PermissionsHandler.PermissionsDict.TryGetValue(user.Server.Id, out perms) && perms.Verbose) + if (perms != null && perms.Verbose) //if verbose - print errors error = ex.Message; } @@ -141,5 +149,26 @@ namespace NadekoBot.Modules.Permissions.Classes return false; } } + + public void AddUserCooldown(ulong serverId, ulong userId, string commandName) { + commandCooldowns.TryAdd(commandName, userId); + var tosave = serverId + ":" + commandName; + Task.Run(async () => + { + ServerPermissions perms; + PermissionsHandler.PermissionsDict.TryGetValue(serverId, out perms); + int cd; + if (!perms.CommandCooldowns.TryGetValue(commandName,out cd)) { + return; + } + if (commandCooldowns.TryAdd(tosave, userId)) + { + await Task.Delay(cd * 1000); + ulong throwaway; + commandCooldowns.TryRemove(tosave, out throwaway); + } + + }); + } } } diff --git a/NadekoBot/Modules/Permissions/Classes/PermissionsHandler.cs b/NadekoBot/Modules/Permissions/Classes/PermissionsHandler.cs index 93fa8686..c5d2e64c 100644 --- a/NadekoBot/Modules/Permissions/Classes/PermissionsHandler.cs +++ b/NadekoBot/Modules/Permissions/Classes/PermissionsHandler.cs @@ -424,6 +424,21 @@ namespace NadekoBot.Modules.Permissions.Classes Task.Run(() => WriteServerToJson(serverPerms)); } + public static void SetCommandCooldown(Server server, string commandName, int value) + { + var serverPerms = PermissionsDict.GetOrAdd(server.Id, + new ServerPermissions(server.Id, server.Name)); + if (value == 0) { + int throwaway; + serverPerms.CommandCooldowns.TryRemove(commandName, out throwaway); + } + else { + serverPerms.CommandCooldowns.AddOrUpdate(commandName, value, (str, v) => value); + } + + Task.Run(() => WriteServerToJson(serverPerms)); + } + public static void AddFilteredWord(Server server, string word) { var serverPerms = PermissionsDict.GetOrAdd(server.Id, @@ -537,6 +552,10 @@ namespace NadekoBot.Modules.Permissions.Classes public Dictionary UserPermissions { get; set; } public Dictionary ChannelPermissions { get; set; } public Dictionary RolePermissions { get; set; } + /// + /// Dictionary of command names with their respective cooldowns + /// + public ConcurrentDictionary CommandCooldowns { get; set; } public ServerPermissions(ulong id, string name) { @@ -549,6 +568,7 @@ namespace NadekoBot.Modules.Permissions.Classes UserPermissions = new Dictionary(); ChannelPermissions = new Dictionary(); RolePermissions = new Dictionary(); + CommandCooldowns = new ConcurrentDictionary(); Words = new HashSet(); } } diff --git a/NadekoBot/Modules/Permissions/PermissionsModule.cs b/NadekoBot/Modules/Permissions/PermissionsModule.cs index e210c1e2..82cf1c34 100644 --- a/NadekoBot/Modules/Permissions/PermissionsModule.cs +++ b/NadekoBot/Modules/Permissions/PermissionsModule.cs @@ -776,6 +776,39 @@ namespace NadekoBot.Modules.Permissions await e.Channel.SendMessage($"`Sucessfully blacklisted server {server.Name}`").ConfigureAwait(false); }).ConfigureAwait(false); }); + + cgb.CreateCommand(Prefix + "cmdcooldown") + .Alias(Prefix+ "cmdcd") + .Description($"Sets a cooldown per user for a command. Set 0 to clear. | `{Prefix}cmdcd \"some cmd\" 5`") + .Parameter("command", ParameterType.Required) + .Parameter("secs",ParameterType.Required) + .AddCheck(SimpleCheckers.ManageMessages()) + .Do(async e => + { + try + { + var command = PermissionHelper.ValidateCommand(e.GetArg("command")); + var secsStr = e.GetArg("secs").Trim(); + int secs; + if (!int.TryParse(secsStr, out secs) || secs < 0 || secs > 3600) + throw new ArgumentOutOfRangeException("secs", "Invalid second parameter. (Must be a number between 0 and 3600)"); + + + PermissionsHandler.SetCommandCooldown(e.Server, command, secs); + if(secs == 0) + await e.Channel.SendMessage($"Command **{command}** has no coooldown now.").ConfigureAwait(false); + else + await e.Channel.SendMessage($"Command **{command}** now has a **{secs} {(secs==1 ? "second" : "seconds")}** cooldown.").ConfigureAwait(false); + } + catch (ArgumentException exArg) + { + await e.Channel.SendMessage(exArg.Message).ConfigureAwait(false); + } + catch (Exception ex) + { + await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message).ConfigureAwait(false); + } + }); }); } } diff --git a/NadekoBot/NadekoBot.cs b/NadekoBot/NadekoBot.cs index 9a4b804c..ad1b0031 100644 --- a/NadekoBot/NadekoBot.cs +++ b/NadekoBot/NadekoBot.cs @@ -196,7 +196,7 @@ namespace NadekoBot return; } #if NADEKO_RELEASE - await Task.Delay(120000).ConfigureAwait(false); + await Task.Delay(150000).ConfigureAwait(false); #else await Task.Delay(1000).ConfigureAwait(false); #endif