diff --git a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java index 8bbe2e5..ac0944a 100644 --- a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java +++ b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java @@ -137,10 +137,6 @@ public final class Sentinel extends JavaPlugin { // Plugin startup logic log.info("Starting Up! (%s)...".formatted(getDescription().getVersion())); - // Enable Functions - AntiSpam.enableAntiSpam(); - ProfanityFilter.enableAntiSwear(); - // Commands new SentinelCommand().register(); new MessageCommand().register(); diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java b/src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java index 58ff740..55da171 100644 --- a/src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java +++ b/src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java @@ -7,12 +7,14 @@ import io.github.itzispyder.pdk.commands.Permission; import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; import io.github.itzispyder.pdk.utils.misc.Cooldown; import io.github.thetrouper.sentinel.Sentinel; +import io.github.thetrouper.sentinel.data.Report; import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives; import io.github.thetrouper.sentinel.server.util.Text; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.UUID; + @CommandRegistry(value = "sentinelcallback", permission = @Permission("sentinel.callbacks"), printStackTrace = true) public class ChatClickCallback implements CustomCommand { Cooldown fpReportCooldown = new Cooldown<>(); @@ -24,7 +26,14 @@ public class ChatClickCallback implements CustomCommand { if (fpReportCooldown.isOnCooldown(p.getUniqueId()) && !p.isOp()) { p.sendMessage(Text.prefix(Sentinel.language.get("cooldown") + fpReportCooldown.getCooldown(p.getUniqueId()))); } else { - ReportFalsePositives.sendFalsePositiveReport(ReportFalsePositives.reports.get(args.get(1).toLong())); + long id = args.get(1).toLong(); + Report send = ReportFalsePositives.reports.get(id); + if (send == null) { + p.sendMessage(Text.prefix(Sentinel.language.get("no-report"))); + return; + } + p.sendMessage(Text.prefix(Sentinel.language.get("reporting-false-positive"))); + ReportFalsePositives.sendFalsePositiveReport(send); p.sendMessage(Text.prefix(Sentinel.language.get("false-positive-report-success"))); } } diff --git a/src/main/java/io/github/thetrouper/sentinel/data/Emojis.java b/src/main/java/io/github/thetrouper/sentinel/data/Emojis.java index 88a332f..22b4177 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/Emojis.java +++ b/src/main/java/io/github/thetrouper/sentinel/data/Emojis.java @@ -1,13 +1,13 @@ package io.github.thetrouper.sentinel.data; public class Emojis { - public static String space = "<:space:1125871914334818446>"; - public static String rightSort = "<:rightSort:1125785837255270520>"; - public static String arrowRight = "<:arrowRight:1125785471520354304>"; - public static String rightDoubleArrow = "<:rightDoubleArrow:1125785800353783868>"; + public static String space = "<:space:1210008300515762238>"; + public static String rightSort = "<:rightSort:1210008337144479754>"; + public static String rightArrow = "<:rightArrow:1210008295738179594>"; + public static String rightDoubleArrow = "<:rightDoubleArrow:1210008296723976224>"; public static String activity = "<:activity:1125785527468167178>"; - public static String alarm = "<:alarm:1125790301873770606>"; - public static String target = "<:target:1125788461371232307>"; + public static String alarm = "<:alarm:1210008289635475547>"; + public static String target = "<:target:1210008303992701068>"; public static String bot = "<:bot:1125791121851826206>"; public static String cancel = "<:cancel:1125785769471127694>"; public static String creation = "<:creation:1125790610729730109>"; @@ -15,19 +15,19 @@ public class Emojis { public static String kick = "<:kick:1125785612595761212>"; public static String members = "<:members:1125791101199077426>"; public static String mute = "<:mute:1125789032937435247>"; - public static String noDM = "<:noDM:1125790359423824022>"; + public static String noDM = "<:noDM:1210008293729370204>"; public static String owner = "<:owner:1125791175559876669>"; public static String potentialDanger = "<:potentialDanger:1125788513971998741>"; public static String roles = "<:roles:1125790513933594645>"; public static String separator = "<:separator:1125790817626357861>"; public static String splash = "<:splash:1125791213933563905>"; - public static String success = "<:success:1125785728161419356>"; + public static String success = "<:success:1210008354039275570>"; public static String suspicious = "<:suspicious:1125790709371371682>"; - public static String trustedAdmin = "<:trustedAdmin:1125785574591180822>"; + public static String trustedAdmin = "<:trustedAdmin:1210008362230743080>"; public static String upvoter = "<:upvoter:1125790659735977994>"; public static String vanity = "<:vanity:1125791060594004039>"; public static String webhook = "<:webhook:1125790545638330388>"; - public static String failure = "<:failure:1125241087909429369>"; - public static String nuke = "<:nuke:1125244368807280702>"; - public static String member = "<:member:1125244044407218176>"; + public static String failure = "<:failure:1210008290625462432>"; + public static String nuke = "<:nuke:1210008294756712478>"; + public static String member = "<:member:1210008291174785105>"; } diff --git a/src/main/java/io/github/thetrouper/sentinel/data/Report.java b/src/main/java/io/github/thetrouper/sentinel/data/Report.java index 9f354f2..cdefdaa 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/Report.java +++ b/src/main/java/io/github/thetrouper/sentinel/data/Report.java @@ -3,7 +3,8 @@ package io.github.thetrouper.sentinel.data; import org.bukkit.event.player.AsyncPlayerChatEvent; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; -public record Report(long id, AsyncPlayerChatEvent event, HashMap stepsTaken) { +public record Report(long id, AsyncPlayerChatEvent event, LinkedHashMap stepsTaken) { } diff --git a/src/main/java/io/github/thetrouper/sentinel/data/config/LanguageFile.java b/src/main/java/io/github/thetrouper/sentinel/data/config/LanguageFile.java index 56217cf..039fa84 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/config/LanguageFile.java +++ b/src/main/java/io/github/thetrouper/sentinel/data/config/LanguageFile.java @@ -50,6 +50,8 @@ public class LanguageFile implements JsonSerializable { put("unicode-notification", "§b§n%1$s§7 has triggered the anti-unicode."); put("unicode-notification-hover", "§8]==-- §d§lSentinel §8--==[\n§bMessage: §f%1$s"); put("no-plugins-for-u", "§cThis server wishes to keep their plugins confidential."); + put("reporting-false-positive","Sending report to staff..."); + put("no-report","§cThe report you requested either does not exist, or has expired!"); }}; public LanguageFile() {} diff --git a/src/main/java/io/github/thetrouper/sentinel/data/config/MainConfig.java b/src/main/java/io/github/thetrouper/sentinel/data/config/MainConfig.java index 0062718..365dc11 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/config/MainConfig.java +++ b/src/main/java/io/github/thetrouper/sentinel/data/config/MainConfig.java @@ -22,9 +22,9 @@ public class MainConfig implements JsonSerializable { public String prefix = "§d§lSentinel §8» §7"; public String webhook = "https://discord.com/api/webhooks/id/token"; public String lang = "en-us.json"; - public List trustedPlayers = new ArrayList<>() {{ - add("049460f7-21cb-42f5-8059-d42752bf406f"); - }}; + public List trustedPlayers = List.of( + "049460f7-21cb-42f5-8059-d42752bf406f" + ); public boolean blockSpecific = true; public boolean preventNBT = true; public boolean preventCmdBlockPlace = true; @@ -53,25 +53,30 @@ public class MainConfig implements JsonSerializable { "perms", "perm", "permission", - "permissions" + "permissions", + "pm", + "pluginmanager", + "rl", + "reload", + "plugman" ); public boolean logDangerous = true; public boolean logCmdBlocks = true; public boolean logNBT = true; public boolean logSpecific = false; - public List logged = new ArrayList<>() {{ - add("give"); - add("item"); - }}; + public List logged = List.of( + "give", + "item" + ); public boolean deop = true; public boolean nbtPunish = false; public boolean cmdBlockPunish = false; public boolean commandPunish = false; public boolean specificPunish = false; - public List punishCommands = new ArrayList<>() {{ - add("smite %player%"); - add("ban %player% ]=- Sentinel -=[ You have been banned for attempting a dangerous action. If you believe this to be a mistake, please contact the server owner."); - }}; + public List punishCommands = List.of( + "smite %player%", + "ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner." + ); public boolean reopCommand = false; public boolean pluginHider = true; } diff --git a/src/main/java/io/github/thetrouper/sentinel/data/config/SwearsConfig.java b/src/main/java/io/github/thetrouper/sentinel/data/config/SwearsConfig.java index d4bbf2e..fd00e37 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/config/SwearsConfig.java +++ b/src/main/java/io/github/thetrouper/sentinel/data/config/SwearsConfig.java @@ -14,84 +14,84 @@ public class SwearsConfig implements JsonSerializable { return file; } - public List swears = new ArrayList<>() {{ - add("anal"); - add("anus"); - add("arse"); - add("ass"); - add("ballsack"); - add("balls"); - add("bastard"); - add("bitch"); - add("btch"); - add("biatch"); - add("blowjob"); - add("bollock"); - add("bollok"); - add("boner"); - add("boob"); - add("bugger"); - add("butt"); - add("choad"); - add("clitoris"); - add("cock"); - add("coon"); - add("crap"); - add("cum"); - add("cunt"); - add("dick"); - add("dildo"); - add("douchebag"); - add("dyke"); - add("feck"); - add("fellate"); - add("fellatio"); - add("felching"); - add("fuck"); - add("fudgepacker"); - add("flange"); - add("gtfo"); - add("hoe"); - add("horny"); - add("incest"); - add("jerk"); - add("jizz"); - add("labia"); - add("masturb"); - add("muff"); - add("nazi"); - add("nipple"); - add("nips"); - add("nude"); - add("pedophile"); - add("penis"); - add("piss"); - add("poop"); - add("porn"); - add("prick"); - add("prostit"); - add("pube"); - add("pussie"); - add("pussy"); - add("queer"); - add("rape"); - add("rapist"); - add("retard"); - add("rimjob"); - add("scrotum"); - add("sex"); - add("shit"); - add("slut"); - add("spunk"); - add("stfu"); - add("suckmy"); - add("tits"); - add("tittie"); - add("titty"); - add("turd"); - add("twat"); - add("vagina"); - add("wank"); - add("whore"); - }}; + public List swears = List.of( + "anal", + "anus", + "arse", + "ass", + "ballsack", + "balls", + "bastard", + "bitch", + "btch", + "biatch", + "blowjob", + "bollock", + "bollok", + "boner", + "boob", + "bugger", + "butt", + "choad", + "clitoris", + "cock", + "coon", + "crap", + "cum", + "cunt", + "dick", + "dildo", + "douchebag", + "dyke", + "feck", + "fellate", + "fellatio", + "felching", + "fuck", + "fudgepacker", + "flange", + "gtfo", + "hoe", + "horny", + "incest", + "jerk", + "jizz", + "labia", + "masturb", + "muff", + "nazi", + "nipple", + "nips", + "nude", + "pedophile", + "penis", + "piss", + "poop", + "porn", + "prick", + "prostit", + "pube", + "pussie", + "pussy", + "queer", + "rape", + "rapist", + "retard", + "rimjob", + "scrotum", + "sex", + "shit", + "slut", + "spunk", + "stfu", + "suckmy", + "tits", + "tittie", + "titty", + "turd", + "twat", + "vagina", + "wank", + "whore" + ); } diff --git a/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java b/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java index 371171b..7a23835 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java @@ -1,6 +1,7 @@ package io.github.thetrouper.sentinel.events; import io.github.itzispyder.pdk.events.CustomListener; +import io.github.itzispyder.pdk.utils.ArrayUtils; import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.data.Report; import io.github.thetrouper.sentinel.server.functions.AdvancedBlockers; @@ -26,6 +27,14 @@ public class ChatEvent implements CustomListener { Report report = ReportFalsePositives.initializeReport(e); + ServerUtils.sendDebugMessage(""" + Creating a chat report... + ID %s + Player %s + Message %s + Fields %s + """.formatted(report.id(),report.event().getPlayer(),report.event().getMessage(), report.stepsTaken().toString())); + handleEventIfNotBypassed(p, "sentinel.chat.antiunicode.bypass", Sentinel.mainConfig.chat.useAntiUnicode, "unicode", @@ -52,16 +61,22 @@ public class ChatEvent implements CustomListener { ProfanityFilter.handleProfanityFilter(event,report); }); + ServerUtils.sendDebugMessage(""" + Adding a report to the list... + ID %s + Fields %s + """.formatted(report.id(), report.stepsTaken().toString())); ReportFalsePositives.reports.put(report.id(),report); + AntiSpam.lastMessageMap.put(p, e.getMessage()); } private static void handleEventIfNotBypassed(Player p, String permission, boolean isEnabled, String eventType, AsyncPlayerChatEvent e, Consumer handler) { if (!Sentinel.isTrusted(p) || !p.hasPermission(permission)) { ServerUtils.sendDebugMessage("ChatEvent: Permission bypass failed, checking for " + eventType); - if (isEnabled) { - ServerUtils.sendDebugMessage("ChatEvent: " + eventType + " check enabled, continuing!"); - handler.accept(e); - } + if (e.isCancelled()) return; + if (!isEnabled) return; + ServerUtils.sendDebugMessage("ChatEvent: " + eventType + " check enabled, continuing!"); + handler.accept(e); } } } diff --git a/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java b/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java index 2b225c4..b935e45 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java @@ -6,8 +6,7 @@ import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.data.Emojis; import io.github.thetrouper.sentinel.data.FAT; import io.github.thetrouper.sentinel.data.FilterSeverity; -import io.github.thetrouper.sentinel.server.functions.AdvancedBlockers; -import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives; +import io.github.thetrouper.sentinel.data.Report; import io.github.thetrouper.sentinel.server.util.ServerUtils; import io.github.thetrouper.sentinel.server.util.Text; import net.kyori.adventure.text.Component; @@ -16,6 +15,7 @@ import net.kyori.adventure.text.event.ClickEvent; import org.bukkit.entity.Player; import org.bukkit.event.player.AsyncPlayerChatEvent; +import java.util.Map; import java.util.concurrent.CompletableFuture; import static io.github.thetrouper.sentinel.server.functions.AntiSpam.heatMap; @@ -24,118 +24,145 @@ import static io.github.thetrouper.sentinel.server.functions.ProfanityFilter.*; public class FilterAction { - public static void filterPunish(AsyncPlayerChatEvent e, FAT type, Double similarity, FilterSeverity severity) { - String report = "This action is not reportable."; - TextComponent staffNotif = Component.text(""); - TextComponent playerWarning = Component.text(""); + public static void filterPunish(AsyncPlayerChatEvent e, FAT type, Double similarity, FilterSeverity severity, long reportID) { + long similar = Math.round(similarity); + long report = reportID; Player offender = e.getPlayer(); switch (type) { - case BLOCK_UNICODE -> { - staffNotif = Component - .text(Text.prefix(Sentinel.language.get("unicode-notification") - .formatted(offender.getName()))) - .hoverEvent(Component.text(Sentinel.language.get("unicode-notification-hover") - .formatted(e.getMessage()))); - playerWarning = Component - .text(Text.prefix(Sentinel.language.get("unicode-warn"))); - } - case BLOCK_URL -> { - staffNotif = Component - .text(Text.prefix(Sentinel.language.get("url-notification") - .formatted(offender.getName()))) - .hoverEvent(Component.text(Sentinel.language.get("url-notification-hover") - .formatted(Text.color(Text.regexHighlighter(e.getMessage(),Sentinel.advConfig.urlRegex," &e> &n","&r &e<&f "))))); - playerWarning = Component - .text(Text.prefix(Sentinel.language.get("url-warn"))); - } - case BLOCK_SPAM -> { - if (Sentinel.mainConfig.chat.antiSpam.clearChat) ServerUtils.sendCommand(Sentinel.mainConfig.chat.antiSpam.chatClearCommand); - - staffNotif = Component - .text(Text.prefix(String.format(Sentinel.language.get("spam-notification"), - offender.getName(), - heatMap.get(offender), - Sentinel.mainConfig.chat.antiSpam.punishHeat - ))) - .hoverEvent(Component.text(String.format(Sentinel.language.get("spam-notification-hover"), - lastMessageMap.get(offender), - e.getMessage(), - similarity - ))); - - playerWarning = Component.text(Text.prefix(Sentinel.language.get("spam-block-warn"))); - } - case SPAM_PUNISH -> { - if (Sentinel.mainConfig.chat.antiSpam.clearChat) ServerUtils.sendCommand(Sentinel.mainConfig.chat.antiSpam.chatClearCommand); - staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("spam-mute-notification"), - offender.getName(), - heatMap.get(offender), - Sentinel.mainConfig.chat.antiSpam.punishHeat - ))) - .hoverEvent(Component.text(String.format(Sentinel.language.get("spam-notification-hover"), - lastMessageMap.get(offender), - e.getMessage(), - similarity - ))); - - playerWarning = Component.text(Sentinel.language.get("spam-mute-warn")); - sendConsoleLog(offender,e,type); - if (Sentinel.mainConfig.chat.antiSpam.logSpam) sendDiscordLog(offender,e,type); - } - case BLOCK_SWEAR -> { - report = ReportFalsePositives.generateReport(e); - staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("profanity-block-notification"), - offender.getName(), - scoreMap.get(offender), - Sentinel.mainConfig.chat.antiSwear.punishScore - ))) - .hoverEvent(Component.text(String.format(Sentinel.language.get("severity-notification-hover"), - e.getMessage(), - highlightProfanity(fullSimplify(e.getMessage())), - severity.name() - ))); - - playerWarning = Component.text(Text.prefix(Sentinel.language.get("profanity-block-warn"))) - .hoverEvent(Component.text(Sentinel.language.get("action-automatic-reportable"))) - .clickEvent(ClickEvent.runCommand("sentinelcallback fpreport " + report)); - } - case SWEAR_PUNISH -> { - report = ReportFalsePositives.generateReport(e); - staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("profanity-mute-notification"), - offender.getName(), - scoreMap.get(offender), - Sentinel.mainConfig.chat.antiSwear.punishScore - ))) - .hoverEvent(Component.text(String.format(Sentinel.language.get("severity-notification-hover"), - e.getMessage(), - highlightProfanity(fullSimplify(e.getMessage())), - severity.name() - ))); - - playerWarning = Component.text(Text.prefix(Sentinel.language.get("profanity-mute-warn"))) - .hoverEvent(Component.text(Sentinel.language.get("action-automatic-reportable"))); - sendConsoleLog(offender,e,type); - if (Sentinel.mainConfig.chat.antiSwear.logSwears) sendDiscordLog(offender,e,type); - } - case SLUR_PUNISH -> { - report = ReportFalsePositives.generateReport(e); - staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("slur-mute-notification"), - offender.getName(), - scoreMap.get(offender), - Sentinel.mainConfig.chat.antiSwear.punishScore - ))) - .hoverEvent(Component.text(String.format(Sentinel.language.get("severity-notification-hover"), - e.getMessage(), - highlightProfanity(fullSimplify(e.getMessage())), - severity.name() - ))); - - playerWarning = Component.text(Text.prefix(Sentinel.language.get("slur-mute-warn"))) - .hoverEvent(Component.text(Sentinel.language.get("action-automatic-reportable"))); - sendConsoleLog(offender,e,type); - if (Sentinel.mainConfig.chat.antiSwear.logSwears) sendDiscordLog(offender,e,type); - } + case BLOCK_UNICODE -> handleUnicodeBlock(e,offender,type,report); + case BLOCK_URL -> handleURLBlock(e,offender,type,report); + case BLOCK_SPAM -> handleSpamBlock(e,type,offender,report,similar); + case SPAM_PUNISH -> handleSpamPunish(e,type,offender,report,similar); + case BLOCK_SWEAR -> handleSwearBlock(e,type,offender,report,severity); + case SWEAR_PUNISH -> handleSwearPunish(e,type,offender,report,severity); + case SLUR_PUNISH -> handleSlur(e,type,offender,report,severity); } + } + + public static void handleUnicodeBlock(AsyncPlayerChatEvent e, Player offender, FAT type, long report) { + TextComponent staffNotif = Component + .text(Text.prefix(Sentinel.language.get("unicode-notification") + .formatted(offender.getName()))) + .hoverEvent(Component.text(Sentinel.language.get("unicode-notification-hover") + .formatted(e.getMessage()))); + TextComponent playerWarning = Component + .text(Text.prefix(Sentinel.language.get("unicode-warn"))); + + sendWarnings(e,type,offender, staffNotif, playerWarning,report); + } + + public static void handleURLBlock(AsyncPlayerChatEvent e, Player offender, FAT type, long report) { + TextComponent staffNotif = Component + .text(Text.prefix(Sentinel.language.get("url-notification") + .formatted(offender.getName()))) + .hoverEvent(Component.text(Sentinel.language.get("url-notification-hover") + .formatted(Text.color(Text.regexHighlighter(e.getMessage(),Sentinel.advConfig.urlRegex," &e> &n","&r &e<&f "))))); + TextComponent playerWarning = Component + .text(Text.prefix(Sentinel.language.get("url-warn"))); + + sendWarnings(e,type,offender, staffNotif, playerWarning,report); + } + + public static void handleSpamBlock(AsyncPlayerChatEvent e, FAT type, Player offender, long report, double similarity) { + if (Sentinel.mainConfig.chat.antiSpam.clearChat) ServerUtils.sendCommand(Sentinel.mainConfig.chat.antiSpam.chatClearCommand); + + TextComponent staffNotif = Component + .text(Text.prefix(String.format(Sentinel.language.get("spam-notification"), + offender.getName(), + heatMap.get(offender), + Sentinel.mainConfig.chat.antiSpam.punishHeat + ))) + .hoverEvent(Component.text(String.format(Sentinel.language.get("spam-notification-hover"), + lastMessageMap.get(offender), + e.getMessage(), + similarity + ))); + + TextComponent playerWarning = Component.text(Text.prefix(Sentinel.language.get("spam-block-warn"))); + + sendWarnings(e,type,offender, staffNotif, playerWarning,report); + } + + public static void handleSpamPunish(AsyncPlayerChatEvent e, FAT type, Player offender, long report, double similarity) { + if (Sentinel.mainConfig.chat.antiSpam.clearChat) ServerUtils.sendCommand(Sentinel.mainConfig.chat.antiSpam.chatClearCommand); + + TextComponent staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("spam-mute-notification"), + offender.getName(), + heatMap.get(offender), + Sentinel.mainConfig.chat.antiSpam.punishHeat + ))) + .hoverEvent(Component.text(String.format(Sentinel.language.get("spam-notification-hover"), + lastMessageMap.get(offender), + e.getMessage(), + similarity + ))); + + TextComponent playerWarning = Component.text(Sentinel.language.get("spam-mute-warn")); + sendConsoleLog(offender,e,type); + if (Sentinel.mainConfig.chat.antiSpam.logSpam) sendDiscordLog(offender,e,type); + + sendWarnings(e,type,offender, staffNotif, playerWarning,report); + } + + public static void handleSwearBlock(AsyncPlayerChatEvent e, FAT type, Player offender, long report, FilterSeverity severity) { + TextComponent staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("profanity-block-notification"), + offender.getName(), + scoreMap.get(offender), + Sentinel.mainConfig.chat.antiSwear.punishScore + ))) + .hoverEvent(Component.text(String.format(Sentinel.language.get("severity-notification-hover"), + e.getMessage(), + highlightProfanity(fullSimplify(e.getMessage())), + severity.name() + ))); + + TextComponent playerWarning = Component.text(Text.prefix(Sentinel.language.get("profanity-block-warn"))) + .hoverEvent(Component.text(Sentinel.language.get("action-automatic-reportable"))) + .clickEvent(ClickEvent.runCommand("sentinelcallback fpreport " + report)); + + sendWarnings(e,type,offender, staffNotif, playerWarning,report); + } + public static void handleSwearPunish(AsyncPlayerChatEvent e, FAT type, Player offender, long report, FilterSeverity severity) { + TextComponent staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("profanity-mute-notification"), + offender.getName(), + scoreMap.get(offender), + Sentinel.mainConfig.chat.antiSwear.punishScore + ))) + .hoverEvent(Component.text(String.format(Sentinel.language.get("severity-notification-hover"), + e.getMessage(), + highlightProfanity(fullSimplify(e.getMessage())), + severity.name() + ))); + + TextComponent playerWarning = Component.text(Text.prefix(Sentinel.language.get("profanity-mute-warn"))) + .hoverEvent(Component.text(Sentinel.language.get("action-automatic-reportable"))); + sendConsoleLog(offender,e,type); + if (Sentinel.mainConfig.chat.antiSwear.logSwears) sendDiscordLog(offender,e,type); + + sendWarnings(e,type,offender, staffNotif, playerWarning,report); + } + + public static void handleSlur(AsyncPlayerChatEvent e, FAT type, Player offender, long report, FilterSeverity severity) { + TextComponent staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("slur-mute-notification"), + offender.getName(), + scoreMap.get(offender), + Sentinel.mainConfig.chat.antiSwear.punishScore + ))) + .hoverEvent(Component.text(String.format(Sentinel.language.get("severity-notification-hover"), + e.getMessage(), + highlightProfanity(fullSimplify(e.getMessage())), + severity.name() + ))); + + TextComponent playerWarning = Component.text(Text.prefix(Sentinel.language.get("slur-mute-warn"))) + .hoverEvent(Component.text(Sentinel.language.get("action-automatic-reportable"))); + sendConsoleLog(offender,e,type); + if (Sentinel.mainConfig.chat.antiSwear.logSwears) sendDiscordLog(offender,e,type); + + sendWarnings(e,type,offender, staffNotif, playerWarning,report); + } + + public static void sendWarnings(AsyncPlayerChatEvent e, FAT type, Player offender, TextComponent staffNotif, TextComponent playerWarning, long report) { if (type.getExecutedCommand() != null) { ServerUtils.sendCommand(type.getExecutedCommand().replace("%player%", offender.getName())); } @@ -196,7 +223,7 @@ public class FilterAction { case SPAM_PUNISH -> { description.append(String.format("\n%1$s%2$sHeat: `%3$s/%4$s`", Emojis.space, - Emojis.arrowRight, + Emojis.rightArrow, heatMap.get(offender), Sentinel.mainConfig.chat.antiSpam.punishHeat )); @@ -209,7 +236,7 @@ public class FilterAction { case SWEAR_PUNISH, SLUR_PUNISH -> { description.append(String.format("\n%1$s%2$sScore: `%3$s/%4$s`", Emojis.space, - Emojis.arrowRight, + Emojis.rightArrow, scoreMap.get(offender), Sentinel.mainConfig.chat.antiSwear.punishScore )); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/AdvancedBlockers.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/AdvancedBlockers.java index c4b898d..451f87b 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/AdvancedBlockers.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/AdvancedBlockers.java @@ -24,19 +24,22 @@ public class AdvancedBlockers { } public static void handleAntiUnicode(AsyncPlayerChatEvent e, Report report) { + if (e.isCancelled()) return; String message = Text.removeFirstColor(e.getMessage()); report.stepsTaken().put("Anti-Unicode", "`%s`".formatted(message)); ServerUtils.sendDebugMessage("AdvBlocker: Checking for unicode: " + message); String nonAllowed = message.replaceAll(Sentinel.advConfig.allowedCharRegex, "").trim(); + if (nonAllowed.length() != 0) { ServerUtils.sendDebugMessage("AdvBlocker: Caught Unicode: " + nonAllowed); e.setCancelled(true); report.stepsTaken().replace("Anti-Unicode", "`%s` %s".formatted(message, Emojis.alarm)); - FilterAction.filterPunish(e,FAT.BLOCK_UNICODE,null,null); + FilterAction.filterPunish(e,FAT.BLOCK_UNICODE,null,null,report.id()); } } public static void handleSwearRegex(AsyncPlayerChatEvent e, Report report) { + if (e.isCancelled()) return; String swearRegex = Sentinel.advConfig.swearRegex; Pattern pattern = Pattern.compile(swearRegex, Pattern.CASE_INSENSITIVE); @@ -44,16 +47,16 @@ public class AdvancedBlockers { report.stepsTaken().put("Anti-Swear Regex", "`%s`".formatted(e.getMessage())); - String highlighted = Text.regexHighlighter(swearRegex,e.getMessage()," > "," < "); - if (matcher.find()) { e.setCancelled(true); + String highlighted = Text.regexHighlighter(swearRegex,e.getMessage()," > "," < "); report.stepsTaken().replace("Anti-Swear Regex", "`%s` %s".formatted(highlighted, Emojis.alarm)); - FilterAction.filterPunish(e,FAT.SWEAR_PUNISH,null,FilterSeverity.HIGH); + FilterAction.filterPunish(e,FAT.SWEAR_PUNISH,null,FilterSeverity.HIGH,report.id()); } } public static void handleStrictRegex(AsyncPlayerChatEvent e, Report report) { + if (e.isCancelled()) return; String strictRegex = Sentinel.advConfig.strictRegex; Pattern pattern = Pattern.compile(strictRegex, Pattern.CASE_INSENSITIVE); @@ -61,23 +64,27 @@ public class AdvancedBlockers { report.stepsTaken().put("Strict Regex", "`%s`".formatted(e.getMessage())); - String highlighted = Text.regexHighlighter(strictRegex,e.getMessage()," > "," < "); + if (matcher.find()) { e.setCancelled(true); + String highlighted = Text.regexHighlighter(strictRegex,e.getMessage()," > "," < "); report.stepsTaken().replace("Strict Regex", "`%s` %s".formatted(highlighted, Emojis.alarm)); - FilterAction.filterPunish(e, FAT.SLUR_PUNISH,null, FilterSeverity.SLUR); + FilterAction.filterPunish(e, FAT.SLUR_PUNISH,null, FilterSeverity.SLUR,report.id()); } } public static void handleAntiURL(AsyncPlayerChatEvent e, Report report) { + if (e.isCancelled()) return; String urlRegex = Sentinel.advConfig.urlRegex; Pattern pattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(e.getMessage()); ServerUtils.sendDebugMessage("AdvBlocker: Checking for URLs against regex `%1$s`:%2$s".formatted(urlRegex, e.getMessage())); - report.stepsTaken().replace("Anti-URL", "`%s` %s".formatted(e.getMessage(), Emojis.alarm)); + report.stepsTaken().put("Anti-URL", "`%s`".formatted( + e.getMessage() + )); if (matcher.find()) { e.setCancelled(true); @@ -85,7 +92,7 @@ public class AdvancedBlockers { ServerUtils.sendDebugMessage("AdvBlocker: Caught URL: " + highlighted); report.stepsTaken().replace("Anti-URL", "`%s` %s".formatted(highlighted, Emojis.alarm)); - FilterAction.filterPunish(e,FAT.BLOCK_URL,null,null); + FilterAction.filterPunish(e,FAT.BLOCK_URL,null,null,report.id()); } } } diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java index be3cfea..fd6b97c 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java @@ -1,5 +1,6 @@ package io.github.thetrouper.sentinel.server.functions; +import io.github.itzispyder.pdk.utils.SchedulerUtils; import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.data.Emojis; import io.github.thetrouper.sentinel.data.FAT; @@ -15,67 +16,52 @@ import java.util.HashMap; import java.util.Map; public class AntiSpam { - public static Map heatMap; - public static Map lastMessageMap; - - public static void enableAntiSpam() { - heatMap = new HashMap<>(); - lastMessageMap = new HashMap<>(); - } + public static Map heatMap = new HashMap<>(); + public static Map lastMessageMap = new HashMap<>(); public static void handleAntiSpam(AsyncPlayerChatEvent e, Report report) { Player p = e.getPlayer(); String message = Text.removeFirstColor(e.getMessage()); - if (!lastMessageMap.containsKey(p)) { - lastMessageMap.put(p,"/* Placeholder Message from Sentinel */"); - ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " did not have a previous message, setting to placeholder!"); + String lastMessage = lastMessageMap.getOrDefault(p,"/* Placeholder Message from Sentinel */"); + int currentHeat = heatMap.getOrDefault(p,0); + double similarity = GPTUtils.calcSim(message, lastMessage); + + int addHeat = Sentinel.mainConfig.chat.antiSpam.defaultGain; + + ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " has a heat of " + currentHeat + "/" + Sentinel.mainConfig.chat.antiSpam.punishHeat + ". Current Message: \"" + message + "\" Last message: \"" + lastMessage + "\""); + if (similarity > 90) { + addHeat = Sentinel.mainConfig.chat.antiSpam.highGain; + ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 90% for " + p.getName() + ". Adding " + Sentinel.mainConfig.chat.antiSpam.highGain); + } else if (similarity > 50) { + addHeat = Sentinel.mainConfig.chat.antiSpam.mediumGain; + ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 50% for " + p.getName() + ". Adding " + Sentinel.mainConfig.chat.antiSpam.mediumGain); + } else if (similarity > 25) { + addHeat = Sentinel.mainConfig.chat.antiSpam.lowGain; + ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 25% for " + p.getName() + ". Adding " + Sentinel.mainConfig.chat.antiSpam.lowGain); } - if (!heatMap.containsKey(p)) { - heatMap.put(p,0); - ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " did not have a heat, setting it to 0!"); - } + report.stepsTaken().put("Anti-Spam", "Heat: %s\nMessage: `%s`".formatted(currentHeat,message)); - if (lastMessageMap.containsKey(p)) { - String lastMessage = lastMessageMap.get(p); - double similarity = GPTUtils.calcSim(message, lastMessage); - ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " has a heat of " + heatMap.get(p) + "/" + Sentinel.mainConfig.chat.antiSpam.punishHeat + ". Current Message: \"" + message + "\" Last message: \"" + lastMessage + "\""); - if (similarity > 90) { - heatMap.put(p, heatMap.get(p) + Sentinel.mainConfig.chat.antiSpam.highGain); - ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 90% for " + p.getName() + ". Adding " + Sentinel.mainConfig.chat.antiSpam.highGain); - } else if (similarity > 50) { - heatMap.put(p, heatMap.get(p) + Sentinel.mainConfig.chat.antiSpam.mediumGain); - ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 50% for " + p.getName() + ". Adding " + Sentinel.mainConfig.chat.antiSpam.mediumGain); - } else if (similarity > 25) { - heatMap.put(p, heatMap.get(p) + Sentinel.mainConfig.chat.antiSpam.lowGain); - ServerUtils.sendDebugMessage("AntiSpam: Similarity: " + similarity + ", is greater than 25% for " + p.getName() + ". Adding " + Sentinel.mainConfig.chat.antiSpam.lowGain); - } - } - - report.stepsTaken().put("Anti-Spam", "Heat: %s\nMessage: `%s`".formatted(heatMap.get(p),message)); - - lastMessageMap.put(p, message); - - if (heatMap.get(p) > Sentinel.mainConfig.chat.antiSpam.punishHeat) { + if (currentHeat > Sentinel.mainConfig.chat.antiSpam.punishHeat) { e.setCancelled(true); - report.stepsTaken().replace("Anti-Spam", "Heat: %s\nMessage: `%s` %s".formatted(heatMap.get(p),message, Emojis.alarm)); - FilterAction.filterPunish(e,FAT.SPAM_PUNISH,GPTUtils.calcSim(e.getMessage(),lastMessageMap.get(p)), null); + report.stepsTaken().replace("Anti-Spam", "Heat: %s\nMessage: `%s` %s".formatted(currentHeat,message, Emojis.alarm)); + FilterAction.filterPunish(e,FAT.SPAM_PUNISH,GPTUtils.calcSim(e.getMessage(),lastMessage), null,report.id()); return; } - if (heatMap.get(p) > Sentinel.mainConfig.chat.antiSpam.blockHeat) { + if (currentHeat > Sentinel.mainConfig.chat.antiSpam.blockHeat) { e.setCancelled(true); - report.stepsTaken().replace("Anti-Spam", "Heat: %s\nMessage: `%s` %s".formatted(heatMap.get(p),message, Emojis.alarm)); - FilterAction.filterPunish(e,FAT.BLOCK_SPAM, GPTUtils.calcSim(e.getMessage(),lastMessageMap.get(p)), null); - heatMap.put(p, heatMap.get(p) + Sentinel.mainConfig.chat.antiSpam.highGain); + report.stepsTaken().replace("Anti-Spam", "Heat: %s\nMessage: `%s` %s".formatted(currentHeat,message, Emojis.alarm)); + FilterAction.filterPunish(e,FAT.BLOCK_SPAM, GPTUtils.calcSim(e.getMessage(),lastMessage), null,report.id()); + heatMap.put(p, currentHeat + Sentinel.mainConfig.chat.antiSpam.highGain); return; } - heatMap.put(p,heatMap.get(p) + Sentinel.mainConfig.chat.antiSpam.defaultGain); + heatMap.put(p,currentHeat + addHeat); } public static void decayHeat() { for (Player p : heatMap.keySet()) { - int heat = heatMap.get(p); + int heat = heatMap.getOrDefault(p,0); if (heat > 0) { heat = heat - Sentinel.mainConfig.chat.antiSpam.heatDecay; heatMap.put(p, Math.max(0, heat)); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java index e4e3d85..3666218 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java @@ -1,6 +1,7 @@ package io.github.thetrouper.sentinel.server.functions; import io.github.thetrouper.sentinel.Sentinel; +import io.github.thetrouper.sentinel.data.Emojis; import io.github.thetrouper.sentinel.data.FAT; import io.github.thetrouper.sentinel.data.FilterSeverity; import io.github.thetrouper.sentinel.data.Report; @@ -15,15 +16,11 @@ import java.util.List; import java.util.Map; public class ProfanityFilter { - public static Map scoreMap; + public static Map scoreMap = new HashMap<>(); private static final List swearBlacklist = Sentinel.swearConfig.swears; private static final List swearWhitelist = Sentinel.fpConfig.swearWhitelist; private static final List slurs = Sentinel.strictConfig.strict; - public static void enableAntiSwear() { - scoreMap = new HashMap<>(); - } - public static void handleProfanityFilter(AsyncPlayerChatEvent event, Report report) { Player player = event.getPlayer(); String message = Text.removeFirstColor(event.getMessage()); @@ -41,11 +38,11 @@ public class ProfanityFilter { scoreMap.put(player, newScore); if (newScore > Sentinel.mainConfig.chat.antiSwear.punishScore) { - FilterAction.filterPunish(event, FAT.SWEAR_PUNISH, null, severity); + FilterAction.filterPunish(event, FAT.SWEAR_PUNISH, null, severity,report.id()); return; } - FilterAction.filterPunish(event, getFAT(severity), null, severity); + FilterAction.filterPunish(event, getFAT(severity), null, severity,report.id()); } @@ -105,6 +102,7 @@ public class ProfanityFilter { return removePeriodsAndSpaces(simplifiedText); } public static FilterSeverity checkSeverity(String text, Report report) { + FilterSeverity severity = FilterSeverity.SAFE; // 1: String lowercasedText = text.toLowerCase(); report.stepsTaken().put("Lowercased", lowercasedText); @@ -116,8 +114,13 @@ public class ProfanityFilter { ServerUtils.sendDebugMessage(("ProfanityFilter: Removed False positives: " + cleanedText)); // 3: - if (containsSwears(cleanedText)) return FilterSeverity.LOW; - if (containsSlurs(cleanedText)) return FilterSeverity.SLUR; + severity = checkProfanity(cleanedText,FilterSeverity.LOW); + if (severity != FilterSeverity.SAFE) { + report.stepsTaken().replace("Remove False Positives", "%s %s".formatted( + highlightProfanity(cleanedText,"||","||"), + Emojis.alarm)); + return severity; + } // 4: String convertedText = convertLeetSpeakCharacters(cleanedText); @@ -125,42 +128,61 @@ public class ProfanityFilter { ServerUtils.sendDebugMessage(("ProfanityFilter: Leet Converted: " + convertedText)); // 5: - if (containsSwears(convertedText)) return FilterSeverity.MEDIUM_LOW; - if (containsSlurs(cleanedText)) return FilterSeverity.SLUR; - + severity = checkProfanity(convertedText,FilterSeverity.MEDIUM_LOW); + if (severity != FilterSeverity.SAFE) { + report.stepsTaken().replace("Convert LeetSpeak", "%s %s".formatted( + highlightProfanity(cleanedText,"||","||"), + Emojis.alarm)); + return severity; + } // 6: String strippedText = stripSpecialCharacters(convertedText); report.stepsTaken().put("Remove Special Characters", strippedText); ServerUtils.sendDebugMessage(("ProfanityFilter: Specials Removed: " + strippedText)); // 7: - if (containsSwears(strippedText)) return FilterSeverity.MEDIUM; - if (containsSlurs(strippedText)) return FilterSeverity.SLUR; - + severity = checkProfanity(strippedText,FilterSeverity.MEDIUM); + if (severity != FilterSeverity.SAFE) { + report.stepsTaken().replace("Remove Special Characters", "%s %s".formatted( + highlightProfanity(cleanedText,"||","||"), + Emojis.alarm)); + return severity; + } // 8: String simplifiedText = simplifyRepeatingLetters(strippedText); report.stepsTaken().put("Remove Repeats", simplifiedText); ServerUtils.sendDebugMessage(("ProfanityFilter: Removed Repeating: " + simplifiedText)); // 9: - if (containsSwears(simplifiedText)) return FilterSeverity.MEDIUM_HIGH; - if (containsSlurs(simplifiedText)) return FilterSeverity.SLUR; - + severity = checkProfanity(simplifiedText,FilterSeverity.MEDIUM_HIGH); + if (severity != FilterSeverity.SAFE) { + report.stepsTaken().replace("Remove Repeats", "%s %s".formatted( + highlightProfanity(cleanedText,"||","||"), + Emojis.alarm)); + return severity; + } // 10: String finalText = removePeriodsAndSpaces(simplifiedText); report.stepsTaken().put("Remove Punctuation", finalText); ServerUtils.sendDebugMessage(("ProfanityFilter: Remove Punctuation: " + finalText)); // 11: - if (containsSwears(finalText)) return FilterSeverity.HIGH; - if (containsSlurs(finalText)) return FilterSeverity.SLUR; + severity = checkProfanity(finalText,FilterSeverity.HIGH); + if (severity != FilterSeverity.SAFE) { + report.stepsTaken().replace("Remove Punctuation", "%s %s".formatted( + highlightProfanity(cleanedText,"||","||"), + Emojis.alarm)); + return severity; + } - return FilterSeverity.SAFE; + return severity; } - public static boolean ContainsProfanity(String text) { - return containsSwears(text) || containsSlurs(text); + public static FilterSeverity checkProfanity(String text, FilterSeverity severity) { + if (containsSlurs(text)) return FilterSeverity.SLUR; + if (containsSwears(text)) return severity; + return FilterSeverity.SAFE; } private static boolean containsSwears(String text) { ServerUtils.sendDebugMessage("ProfanityFilter: Checking for swears"); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java index e0334d0..73224f8 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java @@ -9,53 +9,42 @@ import io.github.thetrouper.sentinel.data.Report; import io.github.thetrouper.sentinel.server.util.Randomizer; import io.github.thetrouper.sentinel.server.util.ServerUtils; import io.github.thetrouper.sentinel.server.util.Text; -import it.unimi.dsi.fastutil.Hash; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.player.AsyncPlayerChatEvent; import java.io.IOException; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; public class ReportFalsePositives { - public static Map reportMap = new HashMap<>(); public static Map reports = new HashMap<>(); - public static Report initializeReport(AsyncPlayerChatEvent e) { + public static Report initializeReport(AsyncPlayerChatEvent event) { final long reportID = Randomizer.generateID(); - HashMap steps = new HashMap<>(); - steps.put("Original Message", e.getMessage()); - return new Report(reportID,e,steps); - } - - public static String generateReport(AsyncPlayerChatEvent e) { - final long reportLong = Randomizer.generateID(); - final String reportID = Long.toString(reportLong); - ServerUtils.sendDebugMessage("FP Report: Generating chat filter report"); - reportMap.put(reportID,e); - ServerUtils.sendDebugMessage(("FP Report: Generated chat filter report. ID:" + reportID + " Message: \"" + reportMap.get(reportID).getMessage() + "\" Expires in 60 seconds")); + LinkedHashMap steps = new LinkedHashMap<>(); + steps.put("Original Message", "`%s`".formatted(event.getMessage())); SchedulerUtils.later(60000,()->{ - reportMap.remove(reportID); - ServerUtils.sendDebugMessage("FP Report: Chat filter Report expired. ID: " + reportID); + reports.remove(reportID); }); - return reportID; + return new Report(reportID,event,steps); } - public static void sendFalsePositiveReport(Report report) { DiscordEmbed.Builder embed = DiscordEmbed.create() .author(new DiscordEmbed.Author("Anti-Swear False Positive","",null)) - .title("Flag Report:") + .title("A player has reported a false positive") .desc(String.format(""" - %1$sPlayer: %2$s %3$s\n - %4$s %5$sUUID: `%2$s`\n + %1$sPlayer: %2$s %3$s + %4$s %5$sUUID: `%6$s` + ## **Filter Steps Taken:** """, Emojis.rightSort, report.event().getPlayer().getName(), Emojis.target, Emojis.space, - Emojis.arrowRight + Emojis.rightArrow, + report.event().getPlayer().getUniqueId() )); report.stepsTaken().forEach((key, value)->{ @@ -67,59 +56,7 @@ public class ReportFalsePositives { .username("Sentinel Anti-Nuke | Logs") .addEmbed(embed.build()) .send(Sentinel.mainConfig.plugin.webhook); - } - - public static void sendFalsePositiveReport(String reportID) { - AsyncPlayerChatEvent e = reportMap.get(reportID); - String orig = e.getMessage(); - - String lowercasedText = orig.toLowerCase(); - String remFP = ProfanityFilter.removeFalsePositives(lowercasedText); - String convertedLeet = ProfanityFilter.convertLeetSpeakCharacters(remFP); - String remSpecials = ProfanityFilter.stripSpecialCharacters(convertedLeet); - String simplifyRep = ProfanityFilter.simplifyRepeatingLetters(remSpecials); - String sanitized = ProfanityFilter. removePeriodsAndSpaces(simplifyRep); - try { - sendEmbed(e.getPlayer(),orig,lowercasedText,remFP,convertedLeet,remSpecials,simplifyRep,sanitized); - } catch (Exception ex) { - e.getPlayer().sendMessage(Text.prefix("Report Failed!")); - Sentinel.log.warning(ex.getMessage()); - } - } - - public static void sendEmbed(Player player, - String message, - String lowercased, - String remFP, - String convertedLeet, - String remSpecials, - String simplifyRep, - String sanitized) throws IOException { - ServerUtils.sendDebugMessage("Creating FalsePositive Webhook..."); - DiscordWebhook.create() - .avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png") - .username("Sentinel Anti-Nuke | Logs") - .addEmbed(DiscordEmbed.create() - .author(new DiscordEmbed.Author("Anti-Swear False Positive","",null)) - .title("Flag Report:") - .desc(String.format("%1$sPlayer: %2$s %3$s\n%4$s %5$sUUID: `%2$s`\n", - Emojis.rightSort, - player.getName(), - Emojis.target, - Emojis.space, - Emojis.arrowRight - )) - .addField("Original Message", "`" + message + "` " + (ProfanityFilter.ContainsProfanity(message) ? Emojis.alarm : ""), false) - .addField("Lowercase", "`" + lowercased + "` " + (ProfanityFilter.ContainsProfanity(lowercased) ? Emojis.alarm : ""), false) - .addField("Removed FPs", "`" + remFP + "` " + (ProfanityFilter.ContainsProfanity(remFP) ? Emojis.alarm : ""), false) - .addField("Converted Leet", "`" + convertedLeet + "` " + (ProfanityFilter.ContainsProfanity(convertedLeet) ? Emojis.alarm : ""), false) - .addField("Removed Specials", "`" + remSpecials + "` " + (ProfanityFilter.ContainsProfanity(remSpecials) ? Emojis.alarm : ""), false) - .addField("Simplify Repeats", "`" + simplifyRep + "` " + (ProfanityFilter.ContainsProfanity(simplifyRep) ? Emojis.alarm : ""), false) - .addField("Fully Sanitized Message", ProfanityFilter.highlightProfanity(sanitized,"`", "`") + " " + Emojis.noDM, false) - .color(0x00FF00) - .thumbnail("https://crafatar.com/avatars/" + player.getUniqueId() + "?size=64&&overlay") - .build()) - .build().send(Sentinel.mainConfig.plugin.webhook); + reports.remove(report.id()); } } diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/SystemCheck.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/SystemCheck.java index 8c50462..564b0bd 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/SystemCheck.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/SystemCheck.java @@ -144,10 +144,8 @@ public class SystemCheck { AntiSpam.handleAntiSpam(spam,ReportFalsePositives.initializeReport(spam)); }); - String report = ReportFalsePositives.generateReport(falsePositive); - SchedulerUtils.later(20,()->{ - ReportFalsePositives.sendFalsePositiveReport(report); + }); Message.messagePlayer(p,p,"Sentinel Automatic System check > Private Message"); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java index 51e5bb9..3bf257c 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java @@ -51,24 +51,39 @@ public class Text { return input; } } - public static String replaceRepeatingLetters(String message) { - StringBuilder result = new StringBuilder(); - char prevChar = '\0'; - int count = 0; + public static String replaceRepeatingLetters(String input) { + if (input == null || input.isEmpty()) { + return input; + } - for (char c : message.toCharArray()) { - if (c == prevChar) { + StringBuilder simplifiedText = new StringBuilder(); + char currentChar = input.charAt(0); + int count = 1; + + for (int i = 1; i < input.length(); i++) { + char nextChar = input.charAt(i); + + if (Character.toLowerCase(nextChar) == Character.toLowerCase(currentChar)) { count++; - if (count <= 3) { - result.append(c); - } } else { - prevChar = c; + simplifiedText.append(currentChar); + + if (count > 1) { + simplifiedText.append(currentChar); + } + + currentChar = nextChar; count = 1; - result.append(c); } } - return result.toString(); + + simplifiedText.append(currentChar); + + if (count > 1) { + simplifiedText.append(currentChar); + } + + return simplifiedText.toString(); } public static String fromLeetString(String s) { Map dictionary = Sentinel.advConfig.leetPatterns;