public async Task SetCooldownAsync(CommandContext ctx, [Description("Cooldown.")] TimeSpan cooldown) { if (cooldown.TotalSeconds < 5 || cooldown.TotalSeconds > 60) { throw new CommandFailedException("The cooldown timespan is not in the valid range ([5, 60] seconds)."); } AntifloodSettings settings = await this.Database.GetAntifloodSettingsAsync(ctx.Guild.Id); settings.Cooldown = (short)cooldown.TotalSeconds; await this.Database.SetAntifloodSettingsAsync(ctx.Guild.Id, settings); DiscordChannel logchn = this.Shared.GetLogChannelForGuild((DiscordClientImpl)ctx.Client, ctx.Guild); if (logchn != null) { var emb = new DiscordEmbedBuilder() { Title = "Guild config changed", Color = this.ModuleColor }; emb.AddField("User responsible", ctx.User.Mention, inline: true); emb.AddField("Invoked in", ctx.Channel.Mention, inline: true); emb.AddField("Antiflood cooldown changed to", $"{settings.Cooldown}s"); await logchn.SendMessageAsync(embed : emb.Build()); } await this.InformAsync(ctx, $"Antiflood cooldown for this guild has been changed to {settings.Cooldown}s", important : false); }
public async Task HandleMemberJoinAsync(GuildMemberAddEventArgs e, AntifloodSettings settings) { if (!this.guildFloodUsers.ContainsKey(e.Guild.Id) && !this.TryAddGuildToWatch(e.Guild.Id)) { throw new ConcurrentOperationException("Failed to add guild to antiflood watch list!"); } if (!this.guildFloodUsers[e.Guild.Id].Add(e.Member)) { throw new ConcurrentOperationException("Failed to add member to antiflood watch list!"); } if (this.guildFloodUsers[e.Guild.Id].Count >= settings.Sensitivity) { foreach (DiscordMember m in this.guildFloodUsers[e.Guild.Id]) { await this.PunishMemberAsync(e.Guild, m, settings.Action); await Task.Delay(TimeSpan.FromMilliseconds(100)); } this.guildFloodUsers[e.Guild.Id].Clear(); return; } await Task.Delay(TimeSpan.FromSeconds(settings.Cooldown)); if (this.guildFloodUsers.ContainsKey(e.Guild.Id) && !this.guildFloodUsers[e.Guild.Id].TryRemove(e.Member)) { throw new ConcurrentOperationException("Failed to remove member from antiflood watch list!"); } }
public async Task SetSensitivityAsync(CommandContext ctx, [Description("Sensitivity (number of users allowed to join within a given timespan).")] short sensitivity) { if (sensitivity < 2 || sensitivity > 20) { throw new CommandFailedException("The sensitivity is not in the valid range ([2, 20])."); } AntifloodSettings settings = await this.Database.GetAntifloodSettingsAsync(ctx.Guild.Id); settings.Sensitivity = sensitivity; await this.Database.SetAntifloodSettingsAsync(ctx.Guild.Id, settings); DiscordChannel logchn = this.Shared.GetLogChannelForGuild((DiscordClientImpl)ctx.Client, ctx.Guild); if (logchn != null) { var emb = new DiscordEmbedBuilder() { Title = "Guild config changed", Color = this.ModuleColor }; emb.AddField("User responsible", ctx.User.Mention, inline: true); emb.AddField("Invoked in", ctx.Channel.Mention, inline: true); emb.AddField("Antiflood sensitivity changed to", $"Max {settings.Sensitivity} users per {settings.Cooldown}s"); await logchn.SendMessageAsync(embed : emb.Build()); } await this.InformAsync(ctx, $"Antiflood sensitivity for this guild has been changed to {Formatter.Bold(sensitivity.ToString())} users per {settings.Cooldown}s", important : false); }
public async Task SetActionAsync(CommandContext ctx, [Description("Action type.")] PunishmentActionType action) { AntifloodSettings settings = await this.Database.GetAntifloodSettingsAsync(ctx.Guild.Id); settings.Action = action; await this.Database.SetAntifloodSettingsAsync(ctx.Guild.Id, settings); DiscordChannel logchn = this.Shared.GetLogChannelForGuild((DiscordClientImpl)ctx.Client, ctx.Guild); if (logchn != null) { var emb = new DiscordEmbedBuilder() { Title = "Guild config changed", Color = this.ModuleColor }; emb.AddField("User responsible", ctx.User.Mention, inline: true); emb.AddField("Invoked in", ctx.Channel.Mention, inline: true); emb.AddField("Antiflood action changed to", action.ToTypeString()); await logchn.SendMessageAsync(embed : emb.Build()); } await this.InformAsync(ctx, $"Antiflood action for this guild has been changed to {Formatter.Bold(settings.Action.ToTypeString())}", important : false); }
public async Task ExecuteGroupAsync(CommandContext ctx, [Description("Enable?")] bool enable, [Description("Sensitivity (number of users allowed to join within a given timespan).")] short sensitivity, [Description("Action type.")] PunishmentActionType action = PunishmentActionType.Kick, [Description("Cooldown.")] TimeSpan?cooldown = null) { if (sensitivity < 2 || sensitivity > 20) { throw new CommandFailedException("The sensitivity is not in the valid range ([2, 20])."); } if (cooldown?.TotalSeconds < 5 || cooldown?.TotalSeconds > 60) { throw new CommandFailedException("The cooldown timespan is not in the valid range ([5, 60] seconds)."); } var settings = new AntifloodSettings { Action = action, Cooldown = (short?)cooldown?.TotalSeconds ?? 10, Enabled = enable, Sensitivity = sensitivity }; using (DatabaseContext db = this.Database.CreateContext()) { DatabaseGuildConfig gcfg = await this.GetGuildConfigAsync(ctx.Guild.Id); gcfg.AntifloodSettings = settings; db.GuildConfig.Update(gcfg); await db.SaveChangesAsync(); } DiscordChannel logchn = this.Shared.GetLogChannelForGuild(ctx.Client, ctx.Guild); if (!(logchn is null)) { var emb = new DiscordEmbedBuilder { Title = "Guild config changed", Description = $"Antiflood {(enable ? "enabled" : "disabled")}", Color = this.ModuleColor }; emb.AddField("User responsible", ctx.User.Mention, inline: true); emb.AddField("Invoked in", ctx.Channel.Mention, inline: true); if (enable) { emb.AddField("Antiflood sensitivity", settings.Sensitivity.ToString(), inline: true); emb.AddField("Antiflood cooldown", settings.Cooldown.ToString(), inline: true); emb.AddField("Antiflood action", settings.Action.ToTypeString(), inline: true); } await logchn.SendMessageAsync(embed : emb.Build()); } await this.InformAsync(ctx, $"{Formatter.Bold(enable ? "Enabled" : "Disabled")} antiflood actions.", important : false); }
public async Task ResetAsync(CommandContext ctx) { await ctx.WithGuildConfigAsync(gcfg => { return(!gcfg.AntifloodEnabled ? throw new CommandFailedException(ctx, "cmd-err-reset-af-off") : Task.CompletedTask); }); if (!await ctx.WaitForBoolReplyAsync("q-setup-reset")) { return; } var settings = new AntifloodSettings(); await this.ExecuteGroupAsync(ctx, true, settings.Action, settings.Sensitivity, TimeSpan.FromSeconds(settings.Cooldown)); }
public static Task SetAntifloodSettingsAsync(this DBService db, ulong gid, AntifloodSettings settings) { return(db.ExecuteCommandAsync(cmd => { cmd.CommandText = $"UPDATE gf.guild_cfg SET " + $"(antiflood_enabled, antiflood_sens, antiflood_cooldown, antiflood_action) = " + $"(@antiflood_enabled, @antiflood_sens, @antiflood_cooldown, @antiflood_action) " + $"WHERE gid = @gid;"; cmd.Parameters.Add(new NpgsqlParameter <long>("gid", (long)gid)); cmd.Parameters.Add(new NpgsqlParameter <bool>("antiflood_enabled", settings.Enabled)); cmd.Parameters.Add(new NpgsqlParameter <short>("antiflood_action", (short)settings.Action)); cmd.Parameters.Add(new NpgsqlParameter <short>("antiflood_cooldown", settings.Cooldown)); cmd.Parameters.Add(new NpgsqlParameter <short>("antiflood_sens", settings.Sensitivity)); return cmd.ExecuteNonQueryAsync(); })); }
public async Task ExecuteGroupAsync(CommandContext ctx) { AntifloodSettings settings = (await this.GetGuildConfigAsync(ctx.Guild.Id)).AntifloodSettings; if (settings.Enabled) { var sb = new StringBuilder(); sb.Append(Formatter.Bold("Sensitivity: ")).AppendLine(settings.Sensitivity.ToString()); sb.Append(Formatter.Bold("Cooldown: ")).AppendLine(settings.Cooldown.ToString()); sb.Append(Formatter.Bold("Action: ")).AppendLine(settings.Action.ToString()); await this.InformAsync(ctx, $"Antiflood watch for this guild is {Formatter.Bold("enabled")}\n\n{sb.ToString()}"); } else { await this.InformAsync(ctx, $"Antiflood watch for this guild is {Formatter.Bold("disabled")}"); } }
public async Task ExecuteGroupAsync(CommandContext ctx, [Description("desc-enable")] bool enable, [Description("desc-sens")] short sens, [Description("desc-punish-action")] PunishmentAction action = PunishmentAction.Kick, [Description("desc-cooldown")] TimeSpan?cooldown = null) { if (sens is < AntifloodSettings.MinSensitivity or > AntifloodSettings.MaxSensitivity) { throw new CommandFailedException(ctx, "cmd-err-range-sens", AntifloodSettings.MinSensitivity, AntifloodSettings.MaxSensitivity); } cooldown ??= TimeSpan.FromSeconds(10); if (cooldown.Value.TotalSeconds is < AntifloodSettings.MinCooldown or > AntifloodSettings.MaxCooldown) { throw new CommandFailedException(ctx, "cmd-err-range-cd", AntifloodSettings.MinCooldown, AntifloodSettings.MaxCooldown); } var settings = new AntifloodSettings { Action = action, Cooldown = (short)cooldown.Value.TotalSeconds, Enabled = enable, Sensitivity = sens }; await ctx.Services.GetRequiredService <GuildConfigService>().ModifyConfigAsync(ctx.Guild.Id, gcfg => gcfg.AntifloodSettings = settings); await ctx.GuildLogAsync(emb => { emb.WithLocalizedTitle("evt-cfg-upd"); emb.WithColor(this.ModuleColor); if (enable) { emb.WithLocalizedDescription("evt-af-enable"); emb.AddLocalizedTitleField("str-sensitivity", settings.Sensitivity, inline: true); emb.AddLocalizedTitleField("str-cooldown", settings.Cooldown, inline: true); emb.AddLocalizedTitleField("str-punish-action", settings.Action.Humanize(), inline: true); } else { emb.WithLocalizedDescription("evt-af-disable"); } }); await ctx.InfoAsync(this.ModuleColor, enable? "evt-af-enable" : "evt-af-disable"); }
public static async Task <AntifloodSettings> GetAntifloodSettingsAsync(this DBService db, ulong gid) { var settings = new AntifloodSettings(); await db.ExecuteCommandAsync(async (cmd) => { cmd.CommandText = $"SELECT antiflood_enabled, antiflood_sens, antiflood_cooldown, antiflood_action FROM gf.guild_cfg WHERE gid = @gid LIMIT 1;"; cmd.Parameters.Add(new NpgsqlParameter <long>("gid", (long)gid)); using (var reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) { if (await reader.ReadAsync().ConfigureAwait(false)) { settings.Action = (PunishmentActionType)(short)reader["antiflood_action"]; settings.Cooldown = (short)reader["antiflood_cooldown"]; settings.Enabled = (bool)reader["antiflood_enabled"]; settings.Sensitivity = (short)reader["antiflood_sens"]; } } }); return(settings); }
public static async Task MemberJoinProtectionEventHandlerAsync(TheGodfatherShard shard, GuildMemberAddEventArgs e) { if (e.Member == null || e.Member.IsBot) { return; } AntifloodSettings antifloodSettings = await shard.DatabaseService.GetAntifloodSettingsAsync(e.Guild.Id); if (antifloodSettings.Enabled) { await shard.CNext.Services.GetService <AntifloodService>().HandleMemberJoinAsync(e, antifloodSettings); } AntiInstantLeaveSettings antiILSettings = await shard.DatabaseService.GetAntiInstantLeaveSettingsAsync(e.Guild.Id); if (antiILSettings.Enabled) { await shard.CNext.Services.GetService <AntiInstantLeaveService>().HandleMemberJoinAsync(e, antiILSettings); } }