#nullable disable using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Services.Database.Models; namespace NadekoBot.Modules.Permissions.Services; public class CmdCdService : ILateBlocker, INService { public ConcurrentDictionary> CommandCooldowns { get; } public ConcurrentDictionary> ActiveCooldowns { get; } = new(); public int Priority { get; } = 0; public CmdCdService(Bot bot) => CommandCooldowns = new( bot.AllGuildConfigs.ToDictionary(k => k.GuildId, v => new ConcurrentHashSet(v.CommandCooldowns))); public Task TryBlock(IGuild guild, IUser user, string commandName) { if (guild is null) return Task.FromResult(false); var cmdcds = CommandCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet()); CommandCooldown cdRule; if ((cdRule = cmdcds.FirstOrDefault(cc => cc.CommandName == commandName)) != null) { var activeCdsForGuild = ActiveCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet()); if (activeCdsForGuild.FirstOrDefault(ac => ac.UserId == user.Id && ac.Command == commandName) != null) { return Task.FromResult(true); } activeCdsForGuild.Add(new() { UserId = user.Id, Command = commandName, }); var _ = Task.Run(async () => { try { await Task.Delay(cdRule.Seconds * 1000).ConfigureAwait(false); activeCdsForGuild.RemoveWhere(ac => ac.Command == commandName && ac.UserId == user.Id); } catch { // ignored } }); } return Task.FromResult(false); } public Task TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command) { var guild = ctx.Guild; var user = ctx.User; var commandName = command.Name.ToLowerInvariant(); return TryBlock(guild, user, commandName); } } public class ActiveCooldown { public string Command { get; set; } public ulong UserId { get; set; } }