add warning cooldown to prevent some duplicate warns

This commit is contained in:
13xforever
2026-01-23 17:22:35 +05:00
parent 691f364838
commit defcf8a4fe
5 changed files with 44 additions and 19 deletions

View File

@@ -3,6 +3,7 @@ using DSharpPlus.Commands.Processors.MessageCommands;
using DSharpPlus.Commands.Processors.UserCommands;
using DSharpPlus.Interactivity;
using Microsoft.Extensions.DependencyInjection;
using ResultNet;
namespace CompatBot.Commands;
@@ -60,13 +61,17 @@ internal static class WarningsContextMenus
).ConfigureAwait(false);
user ??= message?.Author!;
var reason = ((TextInputModalSubmission)value).Value;
var (saved, suppress, recent, total) = await Warnings.AddAsync(user.Id, ctx.User, reason, message?.Content.Sanitize()).ConfigureAwait(false);
if (!saved)
var result = await Warnings.AddAsync(user.Id, ctx.User, reason, message?.Content.Sanitize()).ConfigureAwait(false);
if (result.IsFailure())
{
await ctx.RespondAsync($"{Config.Reactions.Failure} Couldn't save the warning, please try again", ephemeral: true).ConfigureAwait(false);
var response = new DiscordInteractionResponseBuilder()
.WithContent($"{Config.Reactions.Failure} {result.Message ?? "Couldn't save the warning, please try again"}")
.AsEphemeral();
await interaction.EditOriginalResponseAsync(new(response)).ConfigureAwait(false);
return;
}
var(suppress, recent, total) = result.Data;
if (!suppress)
{
var userMsgContent = await Warnings.GetDefaultWarningMessageAsync(ctx.Client, user, reason, recent, total, ctx.User).ConfigureAwait(false);
@@ -85,7 +90,7 @@ internal static class WarningsContextMenus
Config.Log.Error(e);
var msg = new DiscordInteractionResponseBuilder()
.AsEphemeral()
.WithContent($"{Config.Reactions.Failure} Failed to change nickname, check bot's permissions");
.WithContent($"{Config.Reactions.Failure} Failed to save warning");
await interaction.EditOriginalResponseAsync(new(msg)).ConfigureAwait(false);
}
}

View File

@@ -2,6 +2,7 @@
using CompatBot.Commands.AutoCompleteProviders;
using CompatBot.Database;
using Microsoft.EntityFrameworkCore;
using ResultNet;
namespace CompatBot.Commands;
@@ -20,13 +21,14 @@ internal static partial class Warnings
)
{
await ctx.DeferResponseAsync(ephemeral: true).ConfigureAwait(false);
var (saved, suppress, recent, total) = await AddAsync(user.Id, ctx.User, reason).ConfigureAwait(false);
if (!saved)
var result = await AddAsync(user.Id, ctx.User, reason).ConfigureAwait(false);
if (result.IsFailure())
{
await ctx.RespondAsync($"{Config.Reactions.Failure} Couldn't save the warning, please try again", ephemeral: true).ConfigureAwait(false);
await ctx.RespondAsync($"{Config.Reactions.Failure} {result.Message ?? "Couldn't save the warning, please try again"}", ephemeral: true).ConfigureAwait(false);
return;
}
var (suppress, recent, total) = result.Data;
if (!suppress)
{
var userMsgContent = await GetDefaultWarningMessageAsync(ctx.Client, user, reason, recent, total, ctx.User).ConfigureAwait(false);
@@ -193,9 +195,19 @@ internal static partial class Warnings
""";
}
internal static async ValueTask<(bool saved, bool suppress, int recentCount, int totalCount)>
internal static async ValueTask<Result<(bool suppress, int recentCount, int totalCount)>>
AddAsync(ulong userId, DiscordUser issuer, string reason, string? fullReason = null)
{
await using (var rdb = await BotDb.OpenReadAsync().ConfigureAwait(false))
{
var lastWarn = await rdb.Warning.AsNoTracking()
.Where(w => w.DiscordId == userId && !w.Retracted)
.OrderByDescending(w => w.Timestamp)
.FirstOrDefaultAsync();
if (lastWarn?.Timestamp > DateTime.UtcNow.AddSeconds(-20).Ticks)
return Result.Failure<(bool, int, int)>().WithMessage("Duplicate warning cooldown");
}
try
{
await using var wdb = await BotDb.OpenWriteAsync().ConfigureAwait(false);
@@ -215,15 +227,16 @@ internal static partial class Warnings
var totalCount = wdb.Warning.Count(w => w.DiscordId == userId && !w.Retracted);
var recentCount = wdb.Warning.Count(w => w.DiscordId == userId && !w.Retracted && w.Timestamp > threshold);
if (recentCount < 4)
return (true, false, recentCount, totalCount);
return Result.Success((false, recentCount, totalCount));
Config.Log.Debug("Suicide behavior detected, not spamming with warning responses");
return (true, true, recentCount, totalCount);
return Result.Success((true, recentCount, totalCount));
}
catch (Exception e)
{
Config.Log.Error(e, "Couldn't save the warning");
return default;
const string msg = "Couldn't save the warning";
Config.Log.Error(e, msg);
return Result.Failure<(bool, int, int)>().WithMessage(msg);
}
}

View File

@@ -6,6 +6,7 @@ using CompatBot.Utils.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using NReco.Text;
using ResultNet;
namespace CompatBot.Database.Providers;
@@ -225,14 +226,17 @@ internal static class ContentFilter
try
{
warningReason ??= "Mention of piracy";
var (saved, suppress, recent, total) = await Warnings.AddAsync(
var result = await Warnings.AddAsync(
message.Author!.Id,
client.CurrentUser,
warningReason,
message.Content.Sanitize()
).ConfigureAwait(false);
if (saved && !suppress && message.Channel is not null)
if (result.IsSuccess()
&& !result.Data.suppress
&& message.Channel is not null)
{
var (_, recent, total) = result.Data;
var msgContent = await Warnings.GetDefaultWarningMessageAsync(client, message.Author, warningReason, recent, total, client.CurrentUser).ConfigureAwait(false);
var msg = new DiscordMessageBuilder()
.WithContent(msgContent)

View File

@@ -10,6 +10,7 @@ using CompatBot.Database;
using CompatBot.Database.Providers;
using CompatBot.Utils.Extensions;
using Microsoft.Extensions.Caching.Memory;
using ResultNet;
namespace CompatBot.EventHandlers;
@@ -125,14 +126,15 @@ internal static partial class DiscordInviteFilter
if (circumventionAttempt)
{
var reason = "Attempted to circumvent discord invite filter";
var (saved, suppress, recent, total) = await Warnings.AddAsync(
var result = await Warnings.AddAsync(
message.Author.Id,
client.CurrentUser,
reason,
codeResolveMsg
).ConfigureAwait(false);
if (saved && !suppress)
if (result.IsSuccess() && !result.Data.suppress)
{
var (_, recent, total) = result.Data;
var content = await Warnings.GetDefaultWarningMessageAsync(client, message.Author, reason, recent, total, client.CurrentUser).ConfigureAwait(false);
var msg = new DiscordMessageBuilder()
.WithContent(content)

View File

@@ -225,14 +225,15 @@ public static class LogParsingHandler
//if (!(message.Channel!.IsPrivate || message.Channel.Name.Contains("spam")))
{
var reason = "Logs showing use of pirated content";
var (saved, suppress, recent, total) = await Warnings.AddAsync(
var warnSaveResult = await Warnings.AddAsync(
message.Author.Id,
client.CurrentUser,
reason,
$"{result.SelectedFilter.String} - {result.SelectedFilterContext?.Sanitize()}"
);
if (saved && !suppress)
if (warnSaveResult.IsSuccess() && !warnSaveResult.Data.suppress)
{
var (_, recent, total) = warnSaveResult.Data;
var content = await Warnings.GetDefaultWarningMessageAsync(client, message.Author, reason, recent, total, client.CurrentUser).ConfigureAwait(false);
var msg = new DiscordMessageBuilder()
.WithContent(content)