using System; using System.Linq; using System.Text; using System.Threading.Tasks; using DeukBot4.Database; using DeukBot4.Database.ServerSettings; using DeukBot4.MessageHandlers.CommandHandler.RequestStructure; using DeukBot4.MessageHandlers.Permissions; using DeukBot4.Utilities; using Discord; using Discord.WebSocket; #pragma warning disable 4014 namespace DeukBot4.MessageHandlers.CommandHandler { public class ModeratorCommands : CommandContainerBase { public override string Name => "Moderator"; [Command("purge", PermissionLevel.Moderator)] [CommandHelp("Purges a set number of messages", "Purges a set number of messages. \n" + "Usage: \n" + "``!purge {number}`")] [CommandParameters(ParameterMatcher.ParameterType.Number)] [BlockUsageInPm, RequireParameterMatch] public async Task PurgeMessages(CommandRequest request) { // get the server channel object out of message. Return if it's somehow not a server channel if (!(request.OriginalMessage.Channel is ITextChannel channel)) return; var messageCountParameter = request.Parameters[0].AsInt(); if (!messageCountParameter.HasValue) return; var messageCount = messageCountParameter.Value; var messages = channel.GetMessagesAsync(request.OriginalMessage, Direction.Before, messageCount); messages.ForEachAsync(x => { foreach (var message in x) { message.DeleteAsync(); } }); } [Command("kick", PermissionLevel.Moderator)] [CommandParameters(ParameterMatcher.ParameterType.User, ParameterMatcher.ParameterType.Remainder)] [CommandHelp("Kicks a user from the server", "Kicks a user from the server. Will not work on people with a helper role, or higher.\n" + "Usage: \n" + "``!kick {User Mention} {optional: Reason}``\n" + "``!kick {User ID} {optional: Reason}``")] [BlockUsageInPm, RequireParameterMatch] 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; // get the id of the user, this parses the string to an id var user = await request.Parameters[0].AsDiscordGuildUser(channel.Guild); if (user == null) { await request.SendSimpleEmbed("Kick", "I can't find that user on the server"); return; } // 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.SendSimpleEmbed("Kick", "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); await request.SendSimpleEmbed("Kick", $"User was kicked: {user.Username}"); } [Command("ban", PermissionLevel.Moderator)] [CommandHelp("Bans a user from the server", "Bans a user from the server. Will not work on people with a helper role, or higher.\n" + "Usage: \n" + "``ban {User Mention} {optional: Reason}``\n" + "``ban {User ID} {optional: Reason}``")] [CommandParameters(ParameterMatcher.ParameterType.User, ParameterMatcher.ParameterType.Remainder)] [BlockUsageInPm, RequireParameterMatch] 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].AsDiscordGuildUser(channel.Guild); if (user != null) { // 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.SendSimpleEmbed("Ban", "You are not allowed to ban that user"); return; } } var userId = request.Parameters[0].AsUlong(); if (!userId.HasValue) 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(); } if (user != null) { string desc = "No reason was given."; if (!string.IsNullOrWhiteSpace(reason)) { desc = "The given reason was: " + reason; } var eb = EmbedFactory.GetStandardEmbedBuilder(); eb.Title = "Ban"; eb.Description = desc; user.SendMessageAsync("", embed: eb.Build()); } // and ban await channel.Guild.AddBanAsync(userId.Value, 0, reason, RequestOptions.Default); await request.SendSimpleEmbed("Ban", $"User was banned: <@!{userId}>"); } [Command("silence", PermissionLevel.Helper)] [Command("mute", PermissionLevel.Helper)] [Command("timeout", PermissionLevel.Helper)] [CommandParameters(ParameterMatcher.ParameterType.User, ParameterMatcher.ParameterType.Timespan)] [CommandParameters(ParameterMatcher.ParameterType.User, ParameterMatcher.ParameterType.Number)] [CommandParameters(ParameterMatcher.ParameterType.User)] [CommandHelp("Silences a user for a set amount of time", "Allows you to mute a user for a set amount of time.\n." + "Usage:\n" + "``mute {User Mention} {amount of minutes to silence}``\n" + "``mute {User ID} {amount of minutes to silence}``\n" + "``mute {User Mention} {Timespan (amount + time indicator: i.e. 5s, 10m, 3h, 1d)}``\n" + "``mute {User ID} {Timespan (amount + time indicator: i.e. 5s, 10m, 3h, 1d)}``\n")] [BlockUsageInPm] public async Task SilenceUser(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].AsDiscordGuildUser(channel.Guild); if (user == null) { await request.SendSimpleEmbed("Silence", "I can't find that user on the server"); return; } TimeSpan span; if (request.Parameters.Length == 1) { span = TimeSpan.FromMinutes(5); } else { switch (request.Parameters[1].Type) { case ParameterMatcher.ParameterType.Number: var minutes = request.Parameters[1].AsInt(); if (!minutes.HasValue) return; span = TimeSpan.FromMinutes(minutes.Value); break; case ParameterMatcher.ParameterType.Timespan: var sp = TimespanHelper.Parse(request.Parameters[1].AsString()); if (sp.HasValue) { span = sp.Value; } else { return; } break; default: return; } } var msg = await SilenceUser(user, request.OriginalMessage.Author, span); if (msg != null) { request.SendSimpleEmbed("Silence", msg); } } [Command("warn", PermissionLevel.Helper)] [CommandParameters(ParameterMatcher.ParameterType.User, ParameterMatcher.ParameterType.Remainder)] [BlockUsageInPm, RequireParameterMatch] public async Task WarnUser(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].AsDiscordGuildUser(channel.Guild); if (user == null) { await request.SendSimpleEmbed("Warn", "I can't find that user on the server"); return; } var message = request.Parameters[1].AsString(); if (string.IsNullOrWhiteSpace(message)) { await request.SendSimpleEmbed("Warn", "A warning can't be empty!"); return; } await WarnHandler.AddWarning(channel.GuildId, user.Id, message); var warnEmbed = EmbedFactory.GetStandardEmbedBuilder(); warnEmbed.Title = $"Warning from the {channel.Guild.Name} server!"; warnEmbed.Description = message; await user.SendMessageAsync(embed: warnEmbed.Build()); request.SendSimpleEmbed("Warn", "User was warned!"); } [Command("warns", PermissionLevel.Helper)] [CommandParameters(ParameterMatcher.ParameterType.User)] [BlockUsageInPm, RequireParameterMatch] public async Task GetUserWarns(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].AsDiscordGuildUser(channel.Guild); if (user == null) { await request.SendSimpleEmbed("Warn", "I can't find that user on the server"); return; } var warnings = await WarnHandler.GetWarnings(channel.GuildId, user.Id); var eb = EmbedFactory.GetStandardEmbedBuilder(); eb.Title = $"Warnings for User"; eb.Author = new EmbedAuthorBuilder() { Name = user.Username, IconUrl = user.GetAvatarUrl() }; var desc = new StringBuilder(); foreach (var warn in warnings) { desc.Append($"**{warn.Id} -** {warn.Message}\r\n"); } eb.Description = desc.ToString(); request.OriginalMessage.Channel.SendMessageAsync("", embed: eb.Build()); } private static async Task SilenceUser(IGuildUser user, IUser author, TimeSpan span) { if (user.Id == Program.BotId) { return "Stop trying to mute me."; } if (user.Id == author.Id) return "You can't mute yourself..."; if (span.TotalHours > 24) return "Can't mute for that long."; var silencedRoleId = ServerSettingHandler.GetSettings(user.GuildId).MutedRoleId; if (silencedRoleId == 0) { return "No silenced role has been set. The server owner should do ``!silencedrole {role id}`` to set one first."; } var silencedRole = user.Guild.GetRole(silencedRoleId); if (silencedRole == null) { return "Can't find the silenced role. Has it been deleted?"; } await user.AddRoleAsync(silencedRole); if (span.TotalSeconds <= 0) span = TimeSpan.FromMinutes(5); await Task.Delay(span); await user.RemoveRoleAsync(silencedRole); return null; } } }