private string GetAntiRaidString(AntiRaidStats stats) => GetText("raid_stats", Format.Bold(stats.AntiRaidSettings.UserThreshold.ToString()), Format.Bold(stats.AntiRaidSettings.Seconds.ToString()), Format.Bold(stats.AntiRaidSettings.Action.ToString()));
public async Task AntiRaid(int userThreshold = 5, int seconds = 10, PunishmentAction action = PunishmentAction.Mute) { if (userThreshold < 2 || userThreshold > 30) { await ReplyErrorLocalized("raid_cnt", 2, 30).ConfigureAwait(false); return; } if (seconds < 2 || seconds > 300) { await ReplyErrorLocalized("raid_time", 2, 300).ConfigureAwait(false); return; } AntiRaidStats throwaway; if (_antiRaidGuilds.TryRemove(Context.Guild.Id, out throwaway)) { using (var uow = DbHandler.UnitOfWork()) { var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.AntiRaidSetting)); gc.AntiRaidSetting = null; await uow.CompleteAsync().ConfigureAwait(false); } await ReplyConfirmLocalized("prot_disable", "Anti-Raid").ConfigureAwait(false); return; } try { await MuteCommands.GetMuteRole(Context.Guild).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); await ReplyErrorLocalized("prot_error").ConfigureAwait(false); return; } var stats = new AntiRaidStats() { AntiRaidSettings = new AntiRaidSetting() { Action = action, Seconds = seconds, UserThreshold = userThreshold, } }; _antiRaidGuilds.AddOrUpdate(Context.Guild.Id, stats, (key, old) => stats); using (var uow = DbHandler.UnitOfWork()) { var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.AntiRaidSetting)); gc.AntiRaidSetting = stats.AntiRaidSettings; await uow.CompleteAsync().ConfigureAwait(false); } await Context.Channel.SendConfirmAsync(GetText("prot_enable", "Anti-Raid"), $"{Context.User.Mention} {GetAntiRaidString(stats)}") .ConfigureAwait(false); }
static ProtectionCommands() { _log = LogManager.GetCurrentClassLogger(); foreach (var gc in NadekoBot.AllGuildConfigs) { var raid = gc.AntiRaidSetting; var spam = gc.AntiSpamSetting; if (raid != null) { var raidStats = new AntiRaidStats() { AntiRaidSettings = raid }; _antiRaidGuilds.TryAdd((ulong)gc.GuildId, raidStats); } if (spam != null) { _antiSpamGuilds.TryAdd((ulong)gc.GuildId, new AntiSpamStats() { AntiSpamSettings = spam }); } } NadekoBot.Client.MessageReceived += (imsg) => { var msg = imsg as IUserMessage; if (msg == null || msg.Author.IsBot) { return(Task.CompletedTask); } var channel = msg.Channel as ITextChannel; if (channel == null) { return(Task.CompletedTask); } var _ = Task.Run(async() => { try { AntiSpamStats spamSettings; if (!_antiSpamGuilds.TryGetValue(channel.Guild.Id, out spamSettings) || spamSettings.AntiSpamSettings.IgnoredChannels.Contains(new AntiSpamIgnore() { ChannelId = (long)channel.Id })) { return; } var stats = spamSettings.UserStats.AddOrUpdate(msg.Author.Id, (id) => new UserSpamStats(msg), (id, old) => { old.ApplyNextMessage(msg); return(old); }); if (stats.Count >= spamSettings.AntiSpamSettings.MessageThreshold) { if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats)) { stats.Dispose(); await PunishUsers(spamSettings.AntiSpamSettings.Action, ProtectionType.Spamming, (IGuildUser)msg.Author) .ConfigureAwait(false); } } } catch { // ignored } }); return(Task.CompletedTask); }; NadekoBot.Client.UserJoined += (usr) => { if (usr.IsBot) { return(Task.CompletedTask); } AntiRaidStats settings; if (!_antiRaidGuilds.TryGetValue(usr.Guild.Id, out settings)) { return(Task.CompletedTask); } if (!settings.RaidUsers.Add(usr)) { return(Task.CompletedTask); } var _ = Task.Run(async() => { try { ++settings.UsersCount; if (settings.UsersCount >= settings.AntiRaidSettings.UserThreshold) { var users = settings.RaidUsers.ToArray(); settings.RaidUsers.Clear(); await PunishUsers(settings.AntiRaidSettings.Action, ProtectionType.Raiding, users).ConfigureAwait(false); } await Task.Delay(1000 * settings.AntiRaidSettings.Seconds).ConfigureAwait(false); settings.RaidUsers.TryRemove(usr); --settings.UsersCount; } catch { // ignored } }); return(Task.CompletedTask); }; }