diff --git a/Pootis-Bot/Core/CommandHandler.cs b/Pootis-Bot/Core/CommandHandler.cs index 31759a56..cac72fc0 100644 --- a/Pootis-Bot/Core/CommandHandler.cs +++ b/Pootis-Bot/Core/CommandHandler.cs @@ -67,6 +67,8 @@ private async Task HandleCommandAsync(SocketMessage messageParam) var result = await _commands.ExecuteAsync(context, argPos, services: null); if (!result.IsSuccess && result.Error == CommandError.BadArgCount) await context.Channel.SendMessageAsync($"The command `{msg.Content.Replace(Global.botPrefix, "")}` either has too many or too little arguments!"); + else if (!result.IsSuccess && result.Error == CommandError.UnmetPrecondition) + await context.Channel.SendMessageAsync(result.ErrorReason); else if (!result.IsSuccess && result.Error != CommandError.UnknownCommand) Global.Log(result.ErrorReason, ConsoleColor.Red); } diff --git a/Pootis-Bot/Core/Global.cs b/Pootis-Bot/Core/Global.cs index d0159496..249687e1 100644 --- a/Pootis-Bot/Core/Global.cs +++ b/Pootis-Bot/Core/Global.cs @@ -21,7 +21,7 @@ internal static class Global // Main Server - Development Server internal static readonly string[] discordServers = { "https://discord.creepysin.com", "https://discord.gg/m4YcsUa" }; - internal static readonly string version = "0.2.7"; + internal static readonly string version = "0.2.8"; internal static readonly string aboutMessage = $"Pootis Bot --- | --- {version}\n" + $"Created by Creepysin licensed under the MIT license. Vist {githubPage}/blob/master/LICENSE.md for more info.\n\n" + $"Pootis Robot icon by Valve\n" + diff --git a/Pootis-Bot/Entities/GlobalServerList.cs b/Pootis-Bot/Entities/GlobalServerList.cs index 58a5bb6b..384812bb 100644 --- a/Pootis-Bot/Entities/GlobalServerList.cs +++ b/Pootis-Bot/Entities/GlobalServerList.cs @@ -29,6 +29,12 @@ public struct VoiceChannel { public ulong ID { get; set; } public string Name { get; set;} + + public VoiceChannel(ulong id, string name) + { + ID = id; + Name = name; + } } public class CommandInfo diff --git a/Pootis-Bot/Modules/Audio/Music.cs b/Pootis-Bot/Modules/Audio/Music.cs index 0b8fd72d..648c3a82 100644 --- a/Pootis-Bot/Modules/Audio/Music.cs +++ b/Pootis-Bot/Modules/Audio/Music.cs @@ -2,6 +2,7 @@ using Discord; using Discord.Commands; using Pootis_Bot.Core; +using Pootis_Bot.Preconditions; using Pootis_Bot.Services; namespace Pootis_Bot.Modules.Audio @@ -22,6 +23,7 @@ public Music() [Command("join", RunMode = RunMode.Async)] [Summary("Joins in the current voice channel you are in")] + [Cooldown(5)] [RequireBotPermission(GuildPermission.Connect)] [RequireBotPermission(GuildPermission.Speak)] public async Task JoinCmd() @@ -50,6 +52,7 @@ public async Task LeaveCmd() [Command("play", RunMode = RunMode.Async)] [Summary("Plays a song")] + [Cooldown(5)] [RequireBotPermission(GuildPermission.Speak)] public async Task PlayCmd([Remainder] string song = "") { diff --git a/Pootis-Bot/Modules/Audio/VoiceChannels.cs b/Pootis-Bot/Modules/Audio/VoiceChannels.cs index 1b99ce30..0386cfd2 100644 --- a/Pootis-Bot/Modules/Audio/VoiceChannels.cs +++ b/Pootis-Bot/Modules/Audio/VoiceChannels.cs @@ -5,6 +5,7 @@ using Discord.Rest; using Pootis_Bot.Core; using Pootis_Bot.Entities; +using Pootis_Bot.Preconditions; namespace Pootis_Bot.Modules.Audio { @@ -14,17 +15,14 @@ public class VoiceChannels : ModuleBase [RequireBotPermission(GuildPermission.ManageChannels)] [RequireBotPermission(GuildPermission.MoveMembers)] [RequireUserPermission(GuildPermission.ManageChannels)] + [Cooldown(5)] public async Task AddVoiceChannel(string baseName) { RestVoiceChannel channel = await (Context.Guild as SocketGuild).CreateVoiceChannelAsync($"➕ New {baseName} VC"); await Context.Channel.SendMessageAsync($"Added {baseName} as an auto voice channel."); - GlobalServerList.VoiceChannel voiceChannel = new GlobalServerList.VoiceChannel - { - ID = channel.Id, - Name = baseName - }; + GlobalServerList.VoiceChannel voiceChannel = new GlobalServerList.VoiceChannel(channel.Id, baseName); ServerLists.GetServer((SocketGuild)Context.Guild).VoiceChannels.Add(voiceChannel); ServerLists.SaveServerList(); diff --git a/Pootis-Bot/Modules/Basic/Basic.cs b/Pootis-Bot/Modules/Basic/Basic.cs index ff0c6bd0..d0bd8e2b 100644 --- a/Pootis-Bot/Modules/Basic/Basic.cs +++ b/Pootis-Bot/Modules/Basic/Basic.cs @@ -5,6 +5,7 @@ using Discord.Commands; using Discord.WebSocket; using Pootis_Bot.Core; +using Pootis_Bot.Preconditions; using Pootis_Bot.Entities; namespace Pootis_Bot.Modules.Basic @@ -18,6 +19,7 @@ public class BasicCommands : ModuleBase [Command("hello")] [Summary("Displays the 'hello' message")] + [Cooldown(5)] public async Task Hello() { var embed = new EmbedBuilder(); @@ -37,6 +39,7 @@ public async Task Hello() [Command("server")] [Summary("Gets details about the server you are in")] + [Cooldown(5)] public async Task ServerGuild() { var guilduser = (SocketGuildUser)Context.User; diff --git a/Pootis-Bot/Modules/Server/ServerAdminCommands.cs b/Pootis-Bot/Modules/Server/ServerAdminCommands.cs index a6ef6915..0318fa71 100644 --- a/Pootis-Bot/Modules/Server/ServerAdminCommands.cs +++ b/Pootis-Bot/Modules/Server/ServerAdminCommands.cs @@ -1,5 +1,6 @@ using Discord; using Discord.Commands; +using Discord.WebSocket; using System.Threading.Tasks; namespace Pootis_Bot.Modules.Server @@ -30,5 +31,20 @@ public async Task BanUser(IGuildUser user, int days = 0, [Remainder]string reaso await user.BanAsync(days, reason); await Context.Channel.SendMessageAsync($"The user {user.Username} was banned"); } + + [Command("purge", RunMode = RunMode.Async)] + [Summary("Deletes bulk messages")] + [RequireBotPermission(GuildPermission.ManageMessages)] + [RequireUserPermission(GuildPermission.ManageMessages)] + public async Task Purge(int messageCount = 10) + { + var messages = Context.Channel.GetMessagesAsync(messageCount + 1).FlattenAsync(); + + await (Context.Channel as SocketTextChannel).DeleteMessagesAsync(messages.Result); + + var message = await Context.Channel.SendMessageAsync($"{messageCount} message were deleted, the message will be deleted in a moment."); + await Task.Delay(3000); + await message.DeleteAsync(); + } } } \ No newline at end of file diff --git a/Pootis-Bot/Preconditions/CooldownAttribute.cs b/Pootis-Bot/Preconditions/CooldownAttribute.cs new file mode 100644 index 00000000..07978cac --- /dev/null +++ b/Pootis-Bot/Preconditions/CooldownAttribute.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Concurrent; +using System.Threading.Tasks; +using Discord.Commands; + +namespace Pootis_Bot.Preconditions +{ + public class CooldownAttribute : PreconditionAttribute + { + TimeSpan CooldownLength { get; set; } + readonly ConcurrentDictionary _cooldowns = new ConcurrentDictionary(); + + public CooldownAttribute(int seconds) + { + CooldownLength = TimeSpan.FromSeconds(seconds); + } + + public struct CooldownInfo + { + public ulong UserId { get; } + public int CommandHashCode { get; } + + public CooldownInfo(ulong userId, int commandHashCode) + { + UserId = userId; + CommandHashCode = commandHashCode; + } + } + + public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services) + { + var key = new CooldownInfo(context.User.Id, command.GetHashCode()); + + if (_cooldowns.TryGetValue(key, out DateTime endsAt)) + { + var difference = endsAt.Subtract(DateTime.Now); + if (difference.Ticks > 0) + { + return Task.FromResult(PreconditionResult.FromError($"Please wait {difference.ToString(@"ss")} seconds before trying again!")); + } + + var time = DateTime.Now.Add(CooldownLength); + _cooldowns.TryUpdate(key, time, endsAt); + } + else + { + _cooldowns.TryAdd(key, DateTime.Now.Add(CooldownLength)); + } + + return Task.FromResult(PreconditionResult.FromSuccess()); + } + } +} diff --git a/Pootis-Bot/Preconditions/GuildOwnerAttribute.cs b/Pootis-Bot/Preconditions/GuildOwnerAttribute.cs index abdbe72b..efcbf915 100644 --- a/Pootis-Bot/Preconditions/GuildOwnerAttribute.cs +++ b/Pootis-Bot/Preconditions/GuildOwnerAttribute.cs @@ -4,9 +4,6 @@ namespace Pootis_Bot.Preconditions { - // - // Summary: - // Requires the command to be invoked by the owner of the Discord server. [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)] public class RequireGuildOwnerAttribute : PreconditionAttribute { @@ -15,7 +12,7 @@ public override Task CheckPermissionsAsync(ICommandContext c if (context.User.Id == context.Guild.OwnerId) return Task.FromResult(PreconditionResult.FromSuccess()); else - return Task.FromResult(PreconditionResult.FromError("You are not the owner of this Discord server!")); + return Task.FromResult(PreconditionResult.FromError("You are not the owner of this Discord server, you cannot run this command!")); } } }