public async Task DisableRaidRecovery() { if (!RaidRecoveryTracker.Exists(Context.Channel.Id)) { await BetterReplyAsync($"The raid recovery system is not enabled. Use `@{Context.Guild.CurrentUser.Username} rr enable` to enable."); return; } int previousSlowModeInterval = RaidRecoveryTracker.PreviousSlowModeInterval(Context.Channel.Id); if (Context.Channel is SocketTextChannel channel) { await channel.ModifyAsync(x => { x.SlowModeInterval = previousSlowModeInterval; }); } RaidRecoveryTracker.Untrack(Context.Channel.Id); EmbedBuilder builder = new EmbedBuilder() { Color = new Color(Constants.GeneralColor.R, Constants.GeneralColor.G, Constants.GeneralColor.B), Title = "Raid Recovery System Disabled", Description = "This channel has returned to normal." }; LoggingManager.Log.Warn($"Raid recovery system disabled. {BetterLogFormat()}"); await BetterReplyAsync(builder.Build()); await LogMessageEmbedAsync("Raid recovery system disabled"); }
public async Task SkipRaidRecovery(SocketUser user = null) { if (!RaidRecoveryTracker.Exists(Context.Channel.Id)) { await BetterReplyAsync($"The raid recovery system is not enabled. Use `@{Context.Guild.CurrentUser.Username} rr enable` to enable."); return; } if (user == null) { await BetterReplyAsync("You must provide a user to skip them from being banned.", parameters : "user null"); return; } if (RaidRecoveryTracker.SkipUserToBan(Context.Channel.Id, user.Id)) { await BetterReplyAsync($"{BetterUserFormat(user)} will be skipped and **not** banned.", parameters : $"{user} ({user.Id})"); await LogMessageEmbedAsync("Raid recovery system", $"{BetterUserFormat(user)} will be skipped and **not** banned."); } else { await BetterReplyAsync($"{BetterUserFormat(user)} was not suspected and will **not** be banned.", parameters : $"{user} ({user.Id})"); } }
public async Task CleanRaidRecovery(int minutes = 10) { if (!RaidRecoveryTracker.Exists(Context.Channel.Id)) { await BetterReplyAsync($"The raid recovery system is not enabled. Use `@{Context.Guild.CurrentUser.Username} rr enable` to enable."); return; } if (minutes == 0 || minutes > 20160) { await BetterReplyAsync("Must be between 1 and 20160 (2 weeks). Rarely should this be greater than 10 unless a raid went unnoticed for longer.", minutes.ToString()); return; } IUserMessage message = await BetterReplyAsync(embed : LoadingEmbed("Deleting messages", "Staff messages will be preserved."), parameters : minutes.ToString()); SocketTextChannel channel = Context.Channel as SocketTextChannel; ConcurrentBag <IMessage> messages = await GetMessagesAsync(); IEnumerable <IMessage> messagesToDelete = messages.OrderByDescending(x => x.CreatedAt) .Where(x => x.CreatedAt > DateTime.UtcNow.AddMinutes(-minutes)) .Where(x => IsSuspected(x.Author)); await channel.DeleteMessagesAsync(messagesToDelete); await message.ModifyAsync(x => { x.Embed = null; x.Content = $"Deleted {messagesToDelete.Count()} messages from the past {minutes.Minutes().Humanize(3)}."; }); await LogMessageEmbedAsync("Raid recovery system", $"Deleted {messagesToDelete.Count()} messages from the past {minutes.Minutes().Humanize(3)}."); }
public async Task ListRaidRecovery(int minutes = 10) { if (!RaidRecoveryTracker.Exists(Context.Channel.Id)) { await BetterReplyAsync($"The raid recovery system is not enabled. Use `@{Context.Guild.CurrentUser.Username} rr enable` to enable."); return; } if (minutes == 0 || minutes > 20160) { await BetterReplyAsync("Must be between 1 and 20160 (2 weeks). Rarely should this be greater than 10 unless a raid went unnoticed for longer.", minutes.ToString()); return; } IUserMessage message = await BetterReplyAsync(embed : LoadingEmbed("Generating list"), parameters : minutes.ToString()); ConcurrentBag <IMessage> messages = await GetMessagesAsync(); List <IGrouping <IUser, IMessage> > messagesPerUser = messages.OrderByDescending(x => x.CreatedAt) .Where(x => x.CreatedAt > DateTime.UtcNow.AddMinutes(-minutes)) .Where(x => IsSuspected(x.Author)) .GroupBy(x => x.Author) .Where(x => x.Count() > _MessageThreshold) .OrderByDescending(x => x.Count()) .ToList(); if (messagesPerUser.Count > 0) { StringBuilder builder = new StringBuilder(); builder.AppendLine($"{messagesPerUser.Count} different users sent at least {_MessageThreshold} messages within the last {minutes.Minutes().Humanize(3)}."); builder.AppendLine("```"); foreach (IGrouping <IUser, IMessage> user in messagesPerUser) { builder.Append($"{user.Key}: {user.Count()}; "); } builder.AppendLine("```"); await message.ModifyAsync(x => { x.Embed = null; x.Content = builder.ToString(); }); } else { await message.ModifyAsync(x => { x.Embed = null; x.Content = $"There are no suspected users from the past {minutes.Minutes().Humanize(3)}."; }); } }
public async Task BanRaidRecovery(int minutes = 10, [Remainder] string banToken = "") { if (!RaidRecoveryTracker.Exists(Context.Channel.Id)) { await BetterReplyAsync($"The raid recovery system is not enabled. Use `@{Context.Guild.CurrentUser.Username} rr enable` to enable."); return; } if (minutes == 0 || minutes > 20160) { await BetterReplyAsync("Must be between 1 and 20160 (2 weeks). Rarely should this be greater than 10 unless a raid went unnoticed for longer.", minutes.ToString()); return; } if (!string.IsNullOrWhiteSpace(banToken)) { if (RaidRecoveryTracker.ValidateBanToken(Context.Channel.Id, banToken)) { IUserMessage banningMessage = await BetterReplyAsync(embed : LoadingEmbed("Banning users"), parameters : minutes.ToString()); HashSet <ulong> usersIdsToBan = RaidRecoveryTracker.UsersToBan(Context.Channel.Id); try { foreach (ulong user in usersIdsToBan) { await Context.Guild.AddBanAsync(user, 1, $"Banned by '{Context.User}' using the bot '{Context.Guild.CurrentUser.Username}' raid recovery system at {DateTime.UtcNow:o}"); } } catch { } await banningMessage.ModifyAsync(x => { x.Embed = null; x.Content = $"Banned {usersIdsToBan.Count} users."; }); await LogMessageEmbedAsync("Raid recovery system", $"Banned {usersIdsToBan.Count} users.{Environment.NewLine}{Environment.NewLine}{string.Join(", ", usersIdsToBan)}"); TrackStatistics(banningMessage.Id, parameters: $"token: {banToken}; banned: {string.Join(", ", usersIdsToBan)}"); return; } else { await BetterReplyAsync("Invalid ban token."); return; } } IUserMessage message = await BetterReplyAsync(embed : LoadingEmbed("Generating list of users to ban"), parameters : minutes.ToString()); ConcurrentBag <IMessage> messages = await GetMessagesAsync(); IEnumerable <IUser> usersToBan = messages.OrderByDescending(x => x.CreatedAt) .Where(x => x.CreatedAt > DateTime.UtcNow.AddMinutes(-minutes)) .Where(x => IsSuspected(x.Author)) .GroupBy(x => x.Author) .Where(x => x.Count() > _MessageThreshold) .Select(x => x.Key) .Distinct(); if (usersToBan.Count() > 0) { RaidRecoveryTracker.AddUsersToBan(Context.Channel.Id, usersToBan.Select(x => x.Id).ToHashSet()); StringBuilder builder = new StringBuilder(); builder.AppendLine($"The following {usersToBan.Count()} users will be banned."); builder.AppendLine("```"); foreach (IUser banUser in usersToBan) { builder.Append($"{banUser}; "); } builder.AppendLine("```"); await message.ModifyAsync(x => { x.Embed = null; x.Content = builder.ToString(); }); await BetterReplyAsync($"**Ban confirmation.** Selected time frame: {minutes.Minutes().Humanize(3)}; Token: `{RaidRecoveryTracker.BanToken(Context.Channel.Id)}`{Environment.NewLine}{Environment.NewLine}" + $"Type `@{Context.Guild.CurrentUser.Username} rr skip @User` to remove them from the ban list.{Environment.NewLine}" + $"Type `@{Context.Guild.CurrentUser.Username} rr ban {minutes} {RaidRecoveryTracker.BanToken(Context.Channel.Id)}` to ban the users above."); } else { await message.ModifyAsync(x => { x.Embed = null; x.Content = $"There are no suspected users to ban from the past {minutes.Minutes().Humanize(3)}."; }); } }