Fixed some typos in the GUI, added logging for false positive editing, fixed auto-similarity based blocking, and fixed logging related to such.

This commit is contained in:
thetrouper
2024-12-01 14:51:03 -06:00
parent a2148082ee
commit c1be1e4c6a
292 changed files with 387 additions and 9285 deletions

View File

@@ -1,140 +0,0 @@
package io.github.thetrouper.sentinel;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import io.github.itzispyder.pdk.PDK;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import io.github.thetrouper.sentinel.data.cmdblocks.WhitelistStorage;
import io.github.thetrouper.sentinel.data.config.*;
import io.github.thetrouper.sentinel.server.functions.Authenticator;
import io.github.thetrouper.sentinel.server.functions.Load;
import io.github.thetrouper.sentinel.server.functions.Telemetry;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.util.logging.Logger;
public final class Sentinel extends JavaPlugin {
private static Sentinel instance;
private static final File cfgfile = new File("plugins/Sentinel/main-config.json");
private static final File nbtcfg = new File("plugins/Sentinel/nbt-config.json");
private static final File strctcfg = new File("plugins/Sentinel/strict.json");
private static final File swrcfg = new File("plugins/Sentinel/swears.json");
private static final File fpcfg = new File("plugins/Sentinel/false-positives.json");
private static final File advcfg = new File("plugins/Sentinel/advanced-config.json");
private static final File cmdWhitelist = new File("plugins/Sentinel/storage/whitelist.json");
public static WhitelistStorage whitelist = JsonSerializable.load(cmdWhitelist, WhitelistStorage.class, new WhitelistStorage());
public static MainConfig mainConfig = JsonSerializable.load(cfgfile, MainConfig.class, new MainConfig());
public static FPConfig fpConfig = JsonSerializable.load(fpcfg, FPConfig.class, new FPConfig());
public static SwearsConfig swearConfig = JsonSerializable.load(swrcfg, SwearsConfig.class, new SwearsConfig());
public static StrictConfig strictConfig = JsonSerializable.load(strctcfg, StrictConfig.class, new StrictConfig());
public static NBTConfig nbtConfig = JsonSerializable.load(nbtcfg, NBTConfig.class, new NBTConfig());
public static AdvancedConfig advConfig = JsonSerializable.load(advcfg, AdvancedConfig.class, new AdvancedConfig());
public static LanguageFile lang;
public static ProtocolManager protocolManager;
public static final PluginManager manager = Bukkit.getPluginManager();
public static final Logger log = Bukkit.getLogger();
public static boolean usesDynamicIP;
public static String serverID;
public static String license;
public static String IP;
public static boolean doNoPlugins = false;
Load load = new Load();
/**
* Plugin startup logic
*/
@Override
public void onEnable() {
log.info("\n]======------ Pre-load started! ------======[");
PDK.init(this);
instance = this;
log.info("Loading Config...");
loadConfig();
log.info("Loading ProtocolLib");
if (Bukkit.getServer().getPluginManager().isPluginEnabled("ProtocolLib") && mainConfig.plugin.pluginHider) {
doNoPlugins = true;
protocolManager = ProtocolLibrary.getProtocolManager();
} else {
doNoPlugins = false;
log.warning("Sentinel: ProtocolLib not found. Sentinel will not attempt to hide your plugins.");
}
log.info("Language Status: (%s)".formatted(lang.brokenLang));
log.info("Initializing Server ID...");
serverID = Authenticator.getServerID();
license = mainConfig.plugin.license;
log.info("Pre-load finished!\n]====---- Requesting Authentication ----====[ \n- License Key: %s\n- Server ID: %s".formatted(license,serverID));
load.load(license,serverID);
}
public void loadConfig() {
// Init
mainConfig = JsonSerializable.load(cfgfile,MainConfig.class,new MainConfig());
advConfig = JsonSerializable.load(advcfg,AdvancedConfig.class,new AdvancedConfig());
fpConfig = JsonSerializable.load(fpcfg,FPConfig.class,new FPConfig());
strictConfig = JsonSerializable.load(strctcfg,StrictConfig.class,new StrictConfig());
swearConfig = JsonSerializable.load(swrcfg,SwearsConfig.class,new SwearsConfig());
nbtConfig = JsonSerializable.load(nbtcfg,NBTConfig.class,new NBTConfig());
// Save
mainConfig.save();
advConfig.save();
fpConfig.save();
strictConfig.save();
swearConfig.save();
nbtConfig.save();
whitelist = JsonSerializable.load(cmdWhitelist, WhitelistStorage.class, new WhitelistStorage());
whitelist.save();
log.info("Loading Dictionary (%s)...".formatted(Sentinel.mainConfig.plugin.lang));
lang = JsonSerializable.load(LanguageFile.PATH,LanguageFile.class,new LanguageFile());
lang.save();
}
/**
* Plugin shutdown logic
*/
@Override
public void onDisable() {
// Plugin shutdown logic
log.info("Sentinel has disabled! (%s) Your server is now no longer protected!".formatted(getDescription().getVersion()));
if (usesDynamicIP) {
Telemetry.sendShutdownLog();
}
}
public static boolean isTrusted(Player player) {
return Sentinel.mainConfig.plugin.trustedPlayers.contains(player.getUniqueId().toString());
}
public static boolean isTrusted(String uuid) {
return Sentinel.mainConfig.plugin.trustedPlayers.contains(uuid);
}
public static Sentinel getInstance() {
return instance;
}
}

View File

@@ -1,322 +0,0 @@
package io.github.thetrouper.sentinel.auth;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Auth {
public
Auth(
) throws
UnknownHostException
{
}
private
static
final
String
ENCRYPTION_KEY
=
"If I am reading this and I am not a verified developer for Sentinel AntiNuke, I solely swear that my attempts to de-obfuscate this plugin are purely for investigation, and have no malicious intentions such as cracking, leaking, or ratting this plugin.";
private
static
final
String
ENCRYPTION_ALGORITHM
=
"AES";
private
static
final
String
ENCRYPTION_MODE_PADDING
=
"AES/ECB/PKCS5Padding";
static
InetAddress
IP;
static
{
try
{
IP
=
InetAddress
.
getLocalHost
(
)
;
}
catch
(
UnknownHostException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
public
static
String
authorize
(
String
licenseKey
,
String serverID
)
{
String
authStatus
=
"";
List<String>
lines
= new
ArrayList<>();
lines
.add
(
"Nothing"
)
;
lines.
add
(
"To"
)
;
lines.
add
(
"See"
)
;
lines.
add
(
"Here"
+
ENCRYPTION_MODE_PADDING
);
lines.
add
(
"Get"
+
ENCRYPTION_ALGORITHM
);
lines.
add
(
"Out"
+
ENCRYPTION_KEY
);
for
(
String
line
:
lines
)
{
if
(
line
.
contains
(
"get-out-of-here"
)
)
{
String
key
=
extractValue
(
line
,
"time-waster"
);
String
allowedIDs
=
extractValue
(
line
,
"no-skidding-allowed"
);
String[]
allowedArr
=
allowedIDs
.
split
(
":"
)
;
if (
key
.
equals
(
licenseKey
)
)
{
if
(
Arrays
.
asList
(
allowedArr
)
.
contains
(
serverID
)
)
{
authStatus
=
"ID:10T"
;
return
authStatus
;
}
else
{
if
(
Arrays
.
asList
(
allowedArr
)
.
contains
(
"minehut"
)
)
{
authStatus
=
"TROLLADGE"
;
return
authStatus
;
}
authStatus
=
"INVALID-BRAIN"
;
return
authStatus
;
}
}
}
}
if
(
authStatus.isEmpty
(
)
)
{
authStatus
=
"BRAINLESS-NERD"
;
return
authStatus
;
}
return
authStatus
;
}
public
static String
extractValue
(
String
line
,
String
attribute
)
{
int
start
=
line
.
indexOf
(
attribute
+
"=\""
)
+
attribute
.
length(
)
+
2
;
int
end
=
line
.
indexOf
(
"\""
,
start
)
;
return
line
.
substring
(
start
,
end
)
;
}
}

View File

@@ -1,47 +0,0 @@
package io.github.thetrouper.sentinel.cmds;
import io.github.itzispyder.pdk.commands.Args;
import io.github.itzispyder.pdk.commands.CommandRegistry;
import io.github.itzispyder.pdk.commands.CustomCommand;
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<UUID> fpReportCooldown = new Cooldown<>();
@Override
public void dispatchCommand(CommandSender sender, Args args) {
Player p = (Player) sender;
switch (args.get(0).toString()) {
case "fpreport" -> {
if (fpReportCooldown.isOnCooldown(p.getUniqueId()) && !p.isOp()) {
p.sendMessage(Text.prefix(Sentinel.lang.cooldown.onCooldown + fpReportCooldown.getCooldown(p.getUniqueId())));
} else {
long id = args.get(1).toLong();
Report send = ReportFalsePositives.reports.get(id);
if (send == null) {
p.sendMessage(Text.prefix(Sentinel.lang.reports.noReport));
return;
}
p.sendMessage(Text.prefix(Sentinel.lang.reports.reportingFalsePositive));
ReportFalsePositives.sendFalsePositiveReport(send);
p.sendMessage(Text.prefix(Sentinel.lang.reports.falsePositiveSuccess));
}
}
}
}
@Override
public void dispatchCompletions(CompletionBuilder b) {
b.then(b.arg("a_you","b_must","c_be","d_called","e_before","f_running","g_a","h_callback"));
}
}

View File

@@ -1,45 +0,0 @@
package io.github.thetrouper.sentinel.cmds;
import io.github.itzispyder.pdk.commands.Args;
import io.github.itzispyder.pdk.commands.CommandRegistry;
import io.github.itzispyder.pdk.commands.CustomCommand;
import io.github.itzispyder.pdk.commands.Permission;
import io.github.itzispyder.pdk.commands.completions.CompletionBuilder;
import io.github.itzispyder.pdk.utils.ArrayUtils;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.server.functions.Message;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandRegistry(value = "sentinelmessage",permission = @Permission("sentinel.message"))
public class MessageCommand implements CustomCommand {
@Override
public void dispatchCommand(CommandSender sender, Args args) {
Player p = (Player) sender;
Player r = null;
if (args.getSize() == 0) {
p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noOnlinePlayer));
return;
}
if (args.getSize() == 1) {
p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noMessageProvided));
return;
}
r = Bukkit.getPlayer(args.get(0).toString());
String msg = args.getAll(1).toString().trim();
if (p.hasPermission("sentinel.message") && r != null) {
Message.messagePlayer(p,r,msg);
} else if (r == null) p.sendMessage(Text.prefix((Sentinel.lang.playerInteraction.noOnlinePlayer)));
else sender.sendMessage(Text.prefix(Sentinel.lang.permissions.noPermission));
}
@Override
public void dispatchCompletions(CompletionBuilder b) {
b.then(b.arg(ArrayUtils.toNewList(Bukkit.getOnlinePlayers(), Player::getName))
.then(b.arg("[<Message>]")));
}
}

View File

@@ -1,36 +0,0 @@
package io.github.thetrouper.sentinel.cmds;
import io.github.itzispyder.pdk.commands.Args;
import io.github.itzispyder.pdk.commands.CommandRegistry;
import io.github.itzispyder.pdk.commands.CustomCommand;
import io.github.itzispyder.pdk.commands.completions.CompletionBuilder;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandRegistry(value = "reop")
public class ReopCommand implements CustomCommand {
@Override
public void dispatchCommand(CommandSender sender, Args args) {
Player p = (Player) sender;
if (Sentinel.isTrusted(p) && Sentinel.mainConfig.plugin.reopCommand) {
if (!p.isOp()) {
p.sendMessage(Text.prefix(Sentinel.lang.permissions.elevatingPerms));
Sentinel.log.info(Sentinel.lang.permissions.logElevatingPerms.formatted(p.getName()));
p.setOp(true);
} else {
p.sendMessage(Text.prefix(Sentinel.lang.permissions.alreadyOp));
Sentinel.log.info(Sentinel.lang.permissions.logAlreadyOp.formatted(p.getName()));
p.setOp(true);
}
} else {
p.sendMessage(Text.prefix(Sentinel.lang.permissions.noTrust));
}
}
@Override
public void dispatchCompletions(CompletionBuilder completionBuilder) {
}
}

View File

@@ -1,46 +0,0 @@
package io.github.thetrouper.sentinel.cmds;
import io.github.itzispyder.pdk.commands.Args;
import io.github.itzispyder.pdk.commands.CommandRegistry;
import io.github.itzispyder.pdk.commands.CustomCommand;
import io.github.itzispyder.pdk.commands.Permission;
import io.github.itzispyder.pdk.commands.completions.CompletionBuilder;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.server.functions.Message;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Map;
import java.util.UUID;
@CommandRegistry(value = "reply", permission = @Permission("sentinel.reply"))
public class ReplyCommand implements CustomCommand {
public static Map<UUID, UUID> replyMap = Message.replyMap;
@Override
public void dispatchCommand(CommandSender sender, Args args) {
String name = sender.getName();
Player p = sender.getServer().getPlayer(name);
UUID senderID = p.getUniqueId();
if (replyMap.get(senderID) == null) {
p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noReply));
}
Player r = sender.getServer().getPlayer(replyMap.get(senderID));
UUID reciverID = r.getUniqueId();
if (args.get(0).toString() == null) {
p.sendMessage(Text.prefix(Sentinel.lang.playerInteraction.noMessageProvided));
}
String msg = args.getAll().toString();
if (p.hasPermission("sentinel.message")) {
Message.messagePlayer(p,r,msg);
replyMap.put(senderID,reciverID);
} else {
sender.sendMessage(Text.prefix(Sentinel.lang.permissions.noPermission));
}
}
@Override
public void dispatchCompletions(CompletionBuilder b) {
b.then(b.arg("[<Message>]"));
}
}

View File

@@ -1,176 +0,0 @@
package io.github.thetrouper.sentinel.cmds;
import io.github.itzispyder.pdk.commands.Args;
import io.github.itzispyder.pdk.commands.CommandRegistry;
import io.github.itzispyder.pdk.commands.CustomCommand;
import io.github.itzispyder.pdk.commands.Permission;
import io.github.itzispyder.pdk.commands.completions.CompletionBuilder;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.cmdblocks.WhitelistedBlock;
import io.github.thetrouper.sentinel.server.functions.*;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.CommandBlock;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@CommandRegistry(value = "sentinel",printStackTrace = true)
public class SentinelCommand implements CustomCommand {
public static boolean debugMode;
public static List<UUID> autoWhitelist = new ArrayList<>();
@Override
public void dispatchCommand(CommandSender commandSender, Args args) {
Sentinel instance = Sentinel.getInstance();
if (Load.lite) {
commandSender.sendMessage(Text.color("""
&8]=-&f Welcome to &d&lSentinel &7|&f Anti-Nuke &8-=[
&7The plugin is currently loaded in &clite&7 mode.
&fIf you have just &apurchased&f the plugin:
&8- &7Join the &b&ndiscord&r&7 and open a ticket.
&8- &7https://discord.gg/Xh6BAzNtxY
&8- &7You will then receive a license key.
&fIf you have &cnot&f purchased the plugin:
&8- &7Then purchase it :D
&8- &7It wont do anything in this state!
&8- &7(Its only 5$)
&fIf you are reading this from a decompiler:
&8- &7Please stop trying to crack the plugin and purchase it!
&8- &7Your time spent trying trying to bypass my DRM could be spent at a minimum wage job.
&8- &7There you will make 7$ an hour! (As oppose to 5$ for multiple hours of cracking)
&fWoah! You read quite far!
&8- &7Want the plugin for cheaper, &nor even for free&r&7?
&8- &7DM &b@obvwolf&7 on discord and lets make a deal!
"""));
return;
}
Player p = (Player) commandSender;
if (!p.hasPermission("sentinel.staff")) return;
switch (args.get(0).toString()) {
case "commandblock", "cb" -> handleCommandBlock(p,args);
case "reload" -> {
if (!Sentinel.isTrusted(p)) return;
p.sendMessage(Text.prefix("Reloading Sentinel!"));
Sentinel.log.info("[Sentinel] Re-Initializing Sentinel!");
instance.loadConfig();
}
case "full-system-check" -> {
if (!Sentinel.isTrusted(p)) return;
p.sendMessage(Text.prefix("Initiating a full system check!"));
SystemCheck.fullCheck(p);
}
case "debug" -> handleDebugCommand(p,args);
case "false-positive" -> handleFalsePositive(p,args);
}
}
private void handleFalsePositive(Player p, Args args) {
String falsePositive = args.getAll(2).toString();
switch (args.get(1).toString()) {
case "add" -> {
Sentinel.fpConfig.swearWhitelist.add(falsePositive);
p.sendMessage(Text.prefix("&7Successfully added &a%s&7 to the false positive list!".formatted(falsePositive)));
}
case "remove" -> {
Sentinel.fpConfig.swearWhitelist.remove(falsePositive);
p.sendMessage(Text.prefix("&7Successfully removed &c%s&7 to the false positive list!".formatted(falsePositive)));
}
}
Sentinel.fpConfig.save();
}
private void handleCommandBlock(Player p, Args args) {
if (!Sentinel.isTrusted(p)) return;
Block target = p.getTargetBlock(Set.of(Material.AIR),10);
switch (args.get(1).toString()) {
case "add" -> {
if (target.getType().equals(Material.COMMAND_BLOCK) || target.getType().equals(Material.REPEATING_COMMAND_BLOCK) || target.getType().equals(Material.CHAIN_COMMAND_BLOCK)) {
CommandBlock cb = (CommandBlock) target.getState();
CMDBlockWhitelist.add(cb,p.getUniqueId());
return;
}
p.sendMessage(Text.prefix("Could not whitelist the &b" + Text.cleanName(target.getType().toString()) + "&7 it is not a command block!"));
}
case "remove" -> {
WhitelistedBlock wb = CMDBlockWhitelist.get(target.getLocation());
if (wb != null) {
CMDBlockWhitelist.remove(target.getLocation());
p.sendMessage(Text.prefix("Successfully removed 1 &b" + Text.cleanName(WhitelistedBlock.fromSerialized(wb.loc()).getBlock().getType().toString()) + "&7 with the command &a" + wb.command() + "&7."));
return;
}
p.sendMessage(Text.prefix("Could not un-whitelist the &b" + Text.cleanName(target.getType().toString()) + "&7 it wasn't whitelisted in the first place!"));
}
case "auto" -> {
if (autoWhitelist.contains(p.getUniqueId())) {
autoWhitelist.remove(p.getUniqueId());
p.sendMessage(Text.prefix("Successfully toggled &bauto whitelist&7 off for you."));
} else {
autoWhitelist.add(p.getUniqueId());
p.sendMessage(Text.prefix("Successfully toggled &bauto whitelist&7 on for you."));
}
}
case "restore" -> {
if (args.get(2).toString().equals("all")) {
int result = CMDBlockWhitelist.restoreAll();
p.sendMessage(Text.prefix("Successfully restored &b%s&7 command blocks.".formatted(result)));
return;
}
String who = args.get(2).toString();
UUID id = Bukkit.getOfflinePlayer(who).getUniqueId();
int result = CMDBlockWhitelist.restoreAll(id);
p.sendMessage(Text.prefix("Successfully restored &b%s&7 command blocks from &e%s&7.".formatted(result,who)));
}
case "clear" -> {
if (args.get(2).toString().equals("all")) {
int result = CMDBlockWhitelist.clearAll();
p.sendMessage(Text.prefix("Successfully cleared &b%s&7 command blocks.".formatted(result)));
return;
}
String who = args.get(2).toString();
UUID id = Bukkit.getOfflinePlayer(who).getUniqueId();
int result = CMDBlockWhitelist.clearAll(id);
p.sendMessage(Text.prefix("Successfully cleared &b%s&7 command blocks from &e%s&7.".formatted(result,who)));
}
}
}
private void handleDebugCommand(Player p, Args args) {
if (!p.hasPermission("sentinel.debug")) return;
switch (args.get(1).toString()) {
case "lang" -> {
p.sendMessage(Sentinel.lang.brokenLang);
}
case "toggle" -> {
debugMode = !debugMode;
p.sendMessage(Text.prefix((debugMode ? "Enabled" : "Disabled") + " debug mode."));
}
case "chat" -> {
AsyncPlayerChatEvent message = new AsyncPlayerChatEvent(true,p,args.getAll(2).toString(), Set.of(p));
AdvancedBlockers.handleAdvanced(message, ReportFalsePositives.initializeReport(message));
AntiSpam.handleAntiSpam(message,ReportFalsePositives.initializeReport(message));
ProfanityFilter.handleProfanityFilter(message,ReportFalsePositives.initializeReport(message));
if (!message.isCancelled()) p.sendMessage(Text.prefix("Message did not get flagged."));
}
}
}
@Override
public void dispatchCompletions(CompletionBuilder b) {
b.then(b.arg("reload","full-system-check"));
b.then(b.arg("false-positive").then(b.arg("add","remove")));
b.then(b.arg("debug").then(
b.arg("lang","toggle","chat")));
b.then(b.arg("commandblock").then(b.arg("add","remove","auto"))
.then(b.arg("restore")
.then(b.arg("<player>","all")))
.then(b.arg("clear")
.then(b.arg("<player>","all"))));
}
}

View File

@@ -1,39 +0,0 @@
package io.github.thetrouper.sentinel.cmds;
import io.github.itzispyder.pdk.commands.Args;
import io.github.itzispyder.pdk.commands.CommandRegistry;
import io.github.itzispyder.pdk.commands.CustomCommand;
import io.github.itzispyder.pdk.commands.Permission;
import io.github.itzispyder.pdk.commands.completions.CompletionBuilder;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@CommandRegistry(value = "socialspy", permission = @Permission("sentinel.spy"))
public class SocialSpyCommand implements CustomCommand {
public static Map<UUID, Boolean> spyMap = new HashMap<>();
@Override
public void dispatchCommand(CommandSender sender, Args args) {
String name = sender.getName();
Player p = sender.getServer().getPlayer(name);
UUID senderID = p.getUniqueId();
if (!spyMap.containsKey(senderID) || !spyMap.get(senderID)) {
sender.sendMessage(Text.prefix(Sentinel.lang.socialSpy.enabled));
spyMap.put(senderID,true);
} else if (spyMap.get(senderID)) {
sender.sendMessage(Text.prefix(Sentinel.lang.socialSpy.disabled));
spyMap.put(senderID,false);
}
}
@Override
public void dispatchCompletions(CompletionBuilder completionBuilder) {
}
}

View File

@@ -1,24 +0,0 @@
package io.github.thetrouper.sentinel.cmds;
import io.github.itzispyder.pdk.commands.Args;
import io.github.itzispyder.pdk.commands.CommandRegistry;
import io.github.itzispyder.pdk.commands.CustomCommand;
import io.github.itzispyder.pdk.commands.completions.CompletionBuilder;
import io.github.thetrouper.sentinel.Sentinel;
import org.bukkit.command.CommandSender;
import java.util.List;
@CommandRegistry(value = "sentineltab")
public class TrapCommand implements CustomCommand {
private final List<String> fakePlugins = Sentinel.advConfig.fakePlugins;
@Override
public void dispatchCommand(CommandSender commandSender, Args args) {
}
@Override
public void dispatchCompletions(CompletionBuilder b) {
b.then(b.arg(fakePlugins));
}
}

View File

@@ -1,10 +0,0 @@
package io.github.thetrouper.sentinel.data;
import org.bukkit.event.Cancellable;
import java.util.function.Consumer;
public record ActionResult(String name, Runnable action, boolean isRan) {
}

View File

@@ -1,33 +0,0 @@
package io.github.thetrouper.sentinel.data;
public enum ActionType {
SPECIFIC_COMMAND("Anti-Specific has been triggered","The use of a specific command has been detected!", 0x00FF00),
LOGGED_COMMAND("General command log","A logged command has been executed.", 0x00FF00),
DANGEROUS_COMMAND("Anti-Nuke has been triggered","The use of a dangerous command has been detected!", 0xFF0000),
NBT("Anti-NBT has been triggered", "An NBT item has been caught!", 0xFFB000),
PLACE_COMMAND_BLOCK("Anti-Nuke has been triggered","The placing of a command block has been detected!", 0xFFB000),
USE_COMMAND_BLOCK("Anti-Nuke has been triggered","The use of a command block has been detected!", 0xFF0000),
UPDATE_COMMAND_BLOCK("HoneyPot log","Caught a command block command!", 0xF8FF00),
PLACE_MINECART_COMMAND("Anti-Nuke has been triggered","The placing of a minecart command has been detected!", 0xFF0000),
USE_MINECART_COMMAND("Anti-Nuke has been triggered", "The use of a command block has been detected!", 0xFF0000),
UPDATE_MINECART_COMMAND("HoneyPot has been triggered","Caught a command minecart command!", 0xFFB000),
COMMAND_BLOCK_EXECUTE("Command block whitelist has been triggered","Caught an invalid command block.", 0xFFB000);
private final String messageTop;
private final String messageTitle;
private final int embedColor;
ActionType(String messageTop, String messageTitle, int embedColor) {
this.messageTop = messageTop;
this.messageTitle = messageTitle;
this.embedColor = embedColor;
}
public String getMessageTop() {
return messageTop;
}
public String getMessageTitle() {
return messageTitle;
}
public int getEmbedColor() {
return embedColor;
}
}

View File

@@ -1,33 +0,0 @@
package io.github.thetrouper.sentinel.data;
public class Emojis {
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: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>";
public static String date = "<:date:1125790434443145297>";
public static String kick = "<:kick:1125785612595761212>";
public static String members = "<:members:1125791101199077426>";
public static String mute = "<:mute:1125789032937435247>";
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:1210008354039275570>";
public static String suspicious = "<:suspicious:1125790709371371682>";
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:1210008290625462432>";
public static String nuke = "<:nuke:1210008294756712478>";
public static String member = "<:member:1210008291174785105>";
}

View File

@@ -1,15 +0,0 @@
package io.github.thetrouper.sentinel.data;
import io.github.thetrouper.sentinel.Sentinel;
public record FilterActionType(String logSuper, String logName, String chatWarning, String chatWarningHover, String chatNotification, String chatNotificationHover, String punishmentCommand, int embedColor, boolean isLogged) {
public static final FilterActionType UNICODE_BLOCK = new FilterActionType("Sentinel Anti-Unicode Log", "Anti-Unicode", Sentinel.lang.unicodeFilter.unicodeWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.unicodeFilter.unicodeNotification, Sentinel.lang.unicodeFilter.unicodeNotificationHover, null, 0xAAAAFF, Sentinel.mainConfig.chat.logUnicode);
public static final FilterActionType URL_BLOCK = new FilterActionType("Sentinel Anti-URL Log", "Anti-URL", Sentinel.lang.urlFilter.urlWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.urlFilter.urlNotification, Sentinel.lang.urlFilter.urlNotificationHover, null, 0xAAAAFF, Sentinel.mainConfig.chat.logURL);
public static final FilterActionType SPAM_BLOCK = new FilterActionType("Sentinel Anti-Spam Log", "Anti-Spam", Sentinel.lang.spamFilter.spamWarn, Sentinel.lang.automatedActions.actionAutomatic, Sentinel.lang.spamFilter.spamNotification, Sentinel.lang.spamFilter.spamNotificationHover, null, 0xFFFF00, Sentinel.mainConfig.chat.antiSpam.logAllSpam);
public static final FilterActionType SPAM_PUNISH = new FilterActionType("Sentinel Anti-Spam Log", "Anti-Spam", Sentinel.lang.spamFilter.spamMuteWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.spamFilter.spamMuteNotification, Sentinel.lang.spamFilter.spamNotificationHover, Sentinel.mainConfig.chat.antiSpam.spamPunishCommand, 0xFF0000, Sentinel.mainConfig.chat.antiSpam.logSpamPunishments);
public static final FilterActionType SWEAR_BLOCK = new FilterActionType("Sentinel Profanity Filter Log", "Anti-Swear", Sentinel.lang.profanityFilter.profanityWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.profanityFilter.profanityNotification, Sentinel.lang.profanityFilter.profanityNotificationHover, null, 0xFFFF00, Sentinel.mainConfig.chat.antiSwear.logAllSwears);
public static final FilterActionType SWEAR_PUNISH = new FilterActionType("Sentinel Profanity Filter Log", "Anti-Swear", Sentinel.lang.profanityFilter.profanityMuteWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.profanityFilter.profanityMuteNotification, Sentinel.lang.profanityFilter.profanityNotificationHover, Sentinel.mainConfig.chat.antiSwear.swearPunishCommand, 0xFF0000, Sentinel.mainConfig.chat.antiSwear.logSwearPunishments);
public static final FilterActionType SLUR_PUNISH = new FilterActionType("Sentinel Profanity Filter Log", "Anti-Slur", Sentinel.lang.slurFilter.slurMuteWarn, Sentinel.lang.automatedActions.actionAutomaticReportable, Sentinel.lang.slurFilter.slurMuteNotification, Sentinel.lang.profanityFilter.profanityNotificationHover, Sentinel.mainConfig.chat.antiSwear.strictPunishCommand, 0xFF0000, Sentinel.mainConfig.chat.antiSwear.logSwearPunishments);
public static final FilterActionType SAFE = new FilterActionType("ERROR", null, null, null, null, null, null, 0x00AA00,false);
}

View File

@@ -1,23 +0,0 @@
package io.github.thetrouper.sentinel.data;
import io.github.thetrouper.sentinel.Sentinel;
public enum FilterSeverity {
LOW(Sentinel.mainConfig.chat.antiSwear.lowScore),
MEDIUM_LOW(Sentinel.mainConfig.chat.antiSwear.mediumLowScore),
MEDIUM(Sentinel.mainConfig.chat.antiSwear.mediumScore),
MEDIUM_HIGH(Sentinel.mainConfig.chat.antiSwear.mediumHighScore),
HIGH(Sentinel.mainConfig.chat.antiSwear.highScore),
SLUR(Sentinel.mainConfig.chat.antiSwear.highScore),
SAFE(0);
private final int score;
FilterSeverity(int score) {
this.score = score;
}
public int getScore() {
return score;
}
}

View File

@@ -1,15 +0,0 @@
package io.github.thetrouper.sentinel.data;
public record NewActionType(String superTitle, String title, int embedColor, String chatNotification) {
public static final NewActionType CMD_BLOCK_EXECUTE = new NewActionType("Command Block Whitelist Log", "An unauthorized command block has been detected",0xFF0000,"The Command Block Whitelist has been triggered!");
public static final NewActionType CMD_BLOCK_PLACE = new NewActionType("Anti-Nuke Log", "A player attempted to place a command block",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
public static final NewActionType CMD_BLOCK_USE = new NewActionType("Anti-Nuke Log", "A player attempted to use a command block",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
public static final NewActionType CMD_BLOCK_CHANGE = new NewActionType("Anti-Nuke Log", "A player attempted to change a command block",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
public static final NewActionType CMD_MINECART_USE = new NewActionType("Anti-Nuke Log", "A player attempted to use a command minecart",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
public static final NewActionType CMD_MINECART_PLACE = new NewActionType("Anti-Nuke Log", "A player attempted to place a command minecart",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
public static final NewActionType CMD_MINECART_BREAK = new NewActionType("Anti-Nuke Log", "A player attempted to break a command minecart",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
public static final NewActionType CMD_EXECUTE = new NewActionType("Anti-Nuke Log", "A player attempted to run a dangerous command",0xFF0000,"§e%s§7 has triggered the Anti-Nuke!");
public static final NewActionType CMD_SPECIFIC = new NewActionType("Anti-Specific Log", "A player attempted to run a plugin specific command",0xFF0000,"§e%s§7 has triggered the Anti-Specific.");
public static final NewActionType CMD_LOGGED = new NewActionType("Command Log", "A player has ran a logged command",0xFF0000,"§e%s§7 has ran a logged command.");
public static final NewActionType NBT_PULL = new NewActionType("Anti-NBT Log", "A player attempted to pull out an NBT item",0xFF0000,"§e%s§7 has triggered the Anti-NBT!");
}

View File

@@ -1,8 +0,0 @@
package io.github.thetrouper.sentinel.data;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.LinkedHashMap;
public record Report(long id, AsyncPlayerChatEvent event, LinkedHashMap<String,String> stepsTaken) {
}

View File

@@ -1,7 +0,0 @@
package io.github.thetrouper.sentinel.data.cmdblocks;
public enum CMDBlockType {
CHAIN,
REPEAT,
IMPULSE,
}

View File

@@ -1,4 +0,0 @@
package io.github.thetrouper.sentinel.data.cmdblocks;
public record Location(String world, double x, double y,double z) {
}

View File

@@ -1,20 +0,0 @@
package io.github.thetrouper.sentinel.data.cmdblocks;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
public class WhitelistStorage implements JsonSerializable<WhitelistStorage> {
@Override
public File getFile() {
File file = new File("plugins/Sentinel/storage/whitelist.json");
file.getParentFile().mkdirs();
return file;
}
public ConcurrentLinkedQueue<WhitelistedBlock> whitelistedCMDBlocks = new ConcurrentLinkedQueue<>();
}

View File

@@ -1,15 +0,0 @@
package io.github.thetrouper.sentinel.data.cmdblocks;
import org.bukkit.Bukkit;
import org.bukkit.World;
public record WhitelistedBlock(String owner, Location loc, String type, boolean active, String command) {
public static org.bukkit.Location fromSerialized(Location loc) {
World w = Bukkit.getWorld(loc.world());
return new org.bukkit.Location(w,loc.x(),loc.y(),loc.z());
}
public static Location serialize(org.bukkit.Location loc) {
return new Location(loc.getWorld().getName(),loc.x(),loc.y(),loc.z());
}
}

View File

@@ -1,66 +0,0 @@
package io.github.thetrouper.sentinel.data.config;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AdvancedConfig implements JsonSerializable<AdvancedConfig> {
@Override
public File getFile() {
File file = new File("plugins/Sentinel/advanced-config.json");
file.getParentFile().mkdirs();
return file;
}
public List<String> fakePlugins = Arrays.asList(
"This server wishes to keep their plugins confidential. Anyways, Enjoy your meteor client! If the owner is incompetent, then .server plugins MassScan should still work ;)",
"NoCheatPlus",
"Negativity",
"Warden",
"Horizon",
"Illegalstack",
"CoreProtect",
"ExploitsX",
"Vulcan (Outdated version frfr)",
"ABC",
"Spartan",
"Kauri",
"AnticheatReloaded",
"WitherAC",
"GodsEye",
"Matrix",
"Wraith",
"AntiXrayHeuristics",
"GrimAC"
);
public String[] versionAliases = {"version", "ver", "about", "bukkit:version", "bukkit:ver", "bukkit:about", "?", "bukkit:?","pl","bukkit:pl","plugins","bukkit:plugins","bukkit:help"};
public Map<String, String> leetPatterns = new HashMap<>() {{
put("0", "o");
put("1", "i");
put("3", "e");
put("4", "a");
put("5", "s");
put("6", "g");
put("7", "l");
put("$", "s");
put("!", "i");
put("|", "i");
put("+", "t");
put("#", "h");
put("@", "a");
put("<", "c");
put("V", "u");
put("v", "u");
}};
public String allowedCharRegex = "[A-Za-z0-9\\[,./?><|\\]§()*&^%$#@!~`{}:;'\"-_]";
public String falsePosRegex = "";
public String swearRegex = "";
public String strictRegex = "";
public String urlRegex = "\\b(?:(?:https?|ftp):\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:com|org|net|int|edu|gov|mil|arpa|biz|info|mobi|app|name|aero|jobs|museum|travel|a[c-gil-oq-uwxz]|b[abd-jmnoq-tvwyz]|c[acdf-ik-orsu-z]|d[dejkmoz]|e[ceghr-u]|f[ijkmor]|g[abd-ilmnp-uwy]|h[kmnrtu]|i[delmnoq-t]|j[emop]|k[eghimnprwyz]|l[abcikr-vy]|m[acdeghk-z]|n[acefgilopruz]|om|p[ae-hk-nrstwy]|qa|r[eosuw]|s[a-eg-or-vxyz]|t[cdfghj-prtvwz]|u[agksyz]|v[aceginu]|w[fs]|y[etu]|z[amrw])))(?::\\d{2,5})?(?:\\/\\S*)?\\b";
}

View File

@@ -1,78 +0,0 @@
package io.github.thetrouper.sentinel.data.config;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FPConfig implements JsonSerializable<FPConfig> {
@Override
public File getFile() {
File file = new File("plugins/Sentinel/false-positives.json");
file.getParentFile().mkdirs();
return file;
}
public List<String> swearWhitelist = new ArrayList<>(Arrays.asList(
"but then",
"was scamming",
"an alt",
"can also",
"analysis",
"analytics",
"arsenal",
"assassin",
"as saying",
"assert",
"assign",
"assimil",
"assist",
"associat",
"assum",
"assur",
"basement",
"bass",
"cass",
"butter",
"canvass",
"cocktail",
"cumber",
"document",
"evaluate",
"exclusive",
"expensive",
"explain",
"expression",
"grape",
"grass",
"harass",
"hotwater",
"identit",
"kassa",
"kassi",
"lass",
"leafage",
"libshitz",
"magnacumlaude",
"mass",
"mocha",
"pass",
"phoebe",
"phoenix",
"push it",
"sassy",
"saturday",
"scrap",
"serfage",
"sexist",
"shoe",
"stitch",
"therapist",
"but its",
"whoever",
" again"
));
}

View File

@@ -1,103 +0,0 @@
package io.github.thetrouper.sentinel.data.config;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import io.github.thetrouper.sentinel.Sentinel;
import java.io.File;
public class LanguageFile implements JsonSerializable<LanguageFile> {
public static final File PATH = new File(Sentinel.getInstance().getDataFolder(), "/lang/" + Sentinel.mainConfig.plugin.lang);
public LanguageFile() {}
@Override
public File getFile() {
return PATH;
}
public String brokenLang = "Sentinel language is working!";
public Permissions permissions = new Permissions();
public class Permissions {
public String noPermission = "§cInsufficient Permissions!";
public String elevatingPerms = "Elevating your permissions...";
public String logElevatingPerms = "Elevating the permissions of %s";
public String alreadyOp = "You are already a server operator!";
public String logAlreadyOp = "The permissions of %s are already elevated! Retrying...";
public String noTrust = "You are not a trusted user!";
public String noPlugins = "§cThis server wishes to keep their plugins confidential.";
}
public Cooldown cooldown = new Cooldown();
public class Cooldown {
public String onCooldown = "This action is on cooldown!";
}
public Reports reports = new Reports();
public class Reports {
public String falsePositiveSuccess = "Successfully reported a false positive!";
public String reportingFalsePositive = "Sending report to staff...";
public String noReport = "§cThe report you requested either does not exist, or has expired!";
}
public PlayerInteraction playerInteraction = new PlayerInteraction();
public class PlayerInteraction {
public String noOnlinePlayer = "§cYou must provide an online player to send a message to!";
public String noMessageProvided = "§cYou must provide a message to send!";
public String noReply = "§cYou have nobody to reply to!";
public String messageSent = "§d§lMessage §8» §b[§fYou §e>§f %1$s§b] §7%2$s";
public String messageReceived = "§d§lMessage §8» §b[§f%1$s §e>§f You§b] §7%2$s";
}
public SocialSpy socialSpy = new SocialSpy();
public class SocialSpy {
public String enabled = "SocialSpy is now enabled.";
public String disabled = "SocialSpy is now disabled.";
public String spyMessage = "§d§lSpy §8» §b§n%1$s§7 has messaged §b§n%2$s§7.";
public String spyMessageHover = "§8]==-- §d§lSocialSpy §8--==[\n§bSender: §f%1$S\n§bReceiver: §f%2$S\n§bMessage: §f%3$S";
}
public AutomatedActions automatedActions = new AutomatedActions();
public class AutomatedActions {
public String actionAutomatic = "§7This action was preformed automatically\n§7by the §bSentinel Chat Filter§7 algorithm.";
public String actionAutomaticReportable = "§7This action was preformed automatically \n§7by the §bSentinel Chat Filter§7 algorithm!\n§8§o(Click to report false positive)";
}
public ProfanityFilter profanityFilter = new ProfanityFilter();
public class ProfanityFilter {
public String profanityNotification = "§b§n%1$s§7 has triggered the anti-swear! §8(§c%2$s§7/§4%3$s§8)";
public String profanityWarn = "§cPlease do not swear in chat! Attempting to bypass this filter will result in a mute! §7§o(Hover for more info)";
public String profanityMuteWarn = "You have been auto-muted for repeated violation of the profanity filter! §7§o(Hover for more info)";
public String profanityMuteNotification = "§b§n%1$s§7 has been auto-muted by the profanity filter! §8(§c%2$s§7/§4%3$s§8)";
public String profanityNotificationHover = "§8]==-- §d§lSentinel §8--==[\n§bOriginal: §f%1$s\n§bSanitized: §f%2$s\n§bSeverity: §c%3$s\n§7§o(click to report false positive)";
}
public SlurFilter slurFilter = new SlurFilter();
public class SlurFilter {
public String slurMuteWarn = "§cYou have been insta-punished by the anti-slur! §7§o(Hover for more info)";
public String slurMuteNotification = "§b§n%1$s§7 has been insta-muted by the anti-swear! §8(§c%2$s§7/§4%3$s§8)";
}
public SpamFilter spamFilter = new SpamFilter();
public class SpamFilter {
public String spamNotification = "§b§n%1$s§7 might be spamming! §8(§c%2$s§7/§4%3$s§8)";
public String spamNotificationHover = "§8]==-- §d§lSentinel §8--==[\n§bPrevious: §f%1$s\n§bCurrent: §f%2$s\n§bSimilarity §f%3$s";
public String spamWarn = "Do not spam in chat! Please wait before sending another message.";
public String spamMuteWarn = "§cYou have been auto-punished for violating the anti-spam repetitively!";
public String spamMuteNotification = "§b§n%1$s§7 has been auto-muted by the anti spam! §8(§c%2$s§7/§4%3$s§8)";
}
public URLFilter urlFilter = new URLFilter();
public class URLFilter {
public String urlWarn = "§cDo not send urls in chat!";
public String urlNotification = "§b§n%1$s§7 has triggered the anti-URL.";
public String urlNotificationHover = "§8]==-- §d§lSentinel §8--==[\n§bDetected: §f%1$s";
}
public UnicodeFilter unicodeFilter = new UnicodeFilter();
public class UnicodeFilter {
public String unicodeWarn = "§cDo not send non-standard unicode in chat!";
public String unicodeNotification = "§b§n%1$s§7 has triggered the anti-unicode.";
public String unicodeNotificationHover = "§8]==-- §d§lSentinel §8--==[\n§bMessage: §f%1$s";
}
}

View File

@@ -1,126 +0,0 @@
package io.github.thetrouper.sentinel.data.config;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import java.io.File;
import java.util.List;
public class MainConfig implements JsonSerializable<MainConfig> {
@Override
public File getFile() {
File file = new File("plugins/Sentinel/main-config.json");
file.getParentFile().mkdirs();
return file;
}
public Plugin plugin = new Plugin();
public Chat chat = new Chat();
public class Plugin {
public String license = "null";
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<String> trustedPlayers = List.of(
"049460f7-21cb-42f5-8059-d42752bf406f"
);
public boolean blockSpecific = true;
public boolean preventNBT = true;
public boolean preventCmdBlockPlace = true;
public boolean preventCmdBlockUse = true;
public boolean preventCmdBlockChange = true;
public boolean cmdBlockWhitelist = false;
public boolean deleteUnauthorizedCmdBlocks = false;
public boolean logUnauthorizedCmdBlocks = false;
public boolean preventCmdCartPlace = true;
public boolean preventCmdCartUse = true;
public boolean cmdBlockOpCheck = true;
public List<String> dangerous = List.of(
"op",
"deop",
"stop",
"restart",
"execute",
"sudo",
"esudo",
"fill",
"setblock",
"data",
"whitelist",
"lp",
"luckperms",
"perms",
"perm",
"permission",
"permissions",
"pm",
"pluginmanager",
"rl",
"reload",
"plugman"
);
public boolean logDangerous = true;
public boolean logCmdBlocks = true;
public boolean logNBT = true;
public boolean logSpecific = false;
public List<String> 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<String> 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;
}
public class Chat {
public AntiSwear antiSwear = new AntiSwear();
public AntiSpam antiSpam = new AntiSpam();
public boolean useAntiURL = true;
public boolean useSwearRegex = false;
public boolean useStrictRegex = false;
public boolean useAntiUnicode = true;
public boolean logURL = true;
public boolean logUnicode = true;
public class AntiSpam {
public boolean antiSpamEnabled = true;
public int defaultGain = 1;
public int lowGain = 2;
public int mediumGain = 4;
public int highGain = 6;
public int heatDecay = 1;
public int blockHeat = 10;
public int punishHeat = 25;
public boolean clearChat = true;
public String chatClearCommand = "cc";
public String spamPunishCommand = "mute %player% 1m Please refrain from spamming!";
public boolean logAllSpam = false;
public boolean logSpamPunishments = true;
}
public class AntiSwear {
public boolean antiSwearEnabled = true;
public int lowScore = 0;
public int mediumLowScore = 1;
public int mediumScore = 3;
public int mediumHighScore = 5;
public int highScore = 7;
public int scoreDecay = 3;
public int punishScore = 20;
public String swearPunishCommand = "mute %player% 15m Do not attempt to bypass the Profanity Filter";
public String strictPunishCommand = "mute %player% 1h Discriminatory speech is not tolerated on this server!";
public boolean logAllSwears = false;
public boolean logSwearPunishments = true;
}
}
}

View File

@@ -1,59 +0,0 @@
package io.github.thetrouper.sentinel.data.config;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import java.io.File;
public class NBTConfig implements JsonSerializable<NBTConfig> {
@Override
public File getFile() {
File file = new File("plugins/Sentinel/nbt-config.json");
file.getParentFile().mkdirs();
return file;
}
public boolean allowName = true;
public boolean allowLore = true;
public boolean allowAttributes = false;
public boolean allowPotions = false;
public int globalMaxEnchant = 5;
public int maxMending = 1;
public int maxUnbreaking = 3;
public int maxVanishing = 1;
public int maxAquaAffinity = 1;
public int maxBlastProtection = 4;
public int maxCurseOfBinding = 1;
public int maxDepthStrider = 3;
public int maxFeatherFalling = 4;
public int maxFireProtection = 4;
public int maxFrostWalker = 2;
public int maxProjectileProtection = 4;
public int maxProtection = 4;
public int maxRespiration = 3;
public int maxSoulSpeed = 3;
public int maxThorns = 3;
public int maxSwiftSneak = 3;
public int maxBaneOfArthropods = 5;
public int maxEfficiency = 5;
public int maxFireAspect = 2;
public int maxLooting = 3;
public int maxImpaling = 5;
public int maxKnockback = 2;
public int maxSharpness = 5;
public int maxSmite = 5;
public int maxSweepingEdge = 3;
public int maxChanneling = 1;
public int maxFlame = 1;
public int maxInfinity = 1;
public int maxLoyalty = 3;
public int maxRiptide = 3;
public int maxMultishot = 1;
public int maxPiercing = 4;
public int maxPower = 5;
public int maxPunch = 2;
public int maxQuickCharge = 3;
public int maxFortune = 3;
public int maxLuckOfTheSea = 3;
public int maxLure = 3;
public int maxSilkTouch = 1;
}

View File

@@ -1,27 +0,0 @@
package io.github.thetrouper.sentinel.data.config;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class StrictConfig implements JsonSerializable<StrictConfig> {
@Override
public File getFile() {
File file = new File("plugins/Sentinel/strict.json");
file.getParentFile().mkdirs();
return file;
}
public List<String> strict = new ArrayList<>() {{
add("nigg");
add("niger");
add("nlgg");
add("nlger");
add("njgg");
add("tranny");
add("fag");
add("beaner");
}};
}

View File

@@ -1,96 +0,0 @@
package io.github.thetrouper.sentinel.data.config;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import java.io.File;
import java.util.List;
public class SwearsConfig implements JsonSerializable<SwearsConfig> {
@Override
public File getFile() {
File file = new File("plugins/Sentinel/swears.json");
file.getParentFile().mkdirs();
return file;
}
public List<String> 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"
);
}

View File

@@ -1,39 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.functions.CMDBlockWhitelist;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.event.EventHandler;
import org.bukkit.event.server.ServerCommandEvent;
public class CMDBlockExecute implements CustomListener {
@EventHandler
private void onCommandBlock(ServerCommandEvent e) {
ServerUtils.sendDebugMessage("Handling command block event: " + e.getCommand());
if (!Sentinel.mainConfig.plugin.cmdBlockWhitelist) return;
ServerUtils.sendDebugMessage("Whitelist not disabled ");
if (!(e.getSender() instanceof BlockCommandSender s)) return;
ServerUtils.sendDebugMessage("Sender is command block");
Block cmdBlock = s.getBlock();
if (CMDBlockWhitelist.canRun(cmdBlock)) return;
ServerUtils.sendDebugMessage("Command block cant run.");
Action a = new Action.Builder()
.setEvent(e)
.setAction(ActionType.COMMAND_BLOCK_EXECUTE)
.setBlock(cmdBlock)
.setDenied(true)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logUnauthorizedCmdBlocks)
.setNotifyTrusted(true)
.setNotifyConsole(true)
.setLoggedCommand(e.getCommand())
.execute();
if (Sentinel.mainConfig.plugin.deleteUnauthorizedCmdBlocks) cmdBlock.setType(Material.AIR);
}
}

View File

@@ -1,52 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.cmds.SentinelCommand;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.functions.CMDBlockWhitelist;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.CommandBlock;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.BlockPlaceEvent;
public class CMDBlockPlace implements CustomListener {
@EventHandler
private void onCMDBlockPlace(BlockPlaceEvent e) {
ServerUtils.sendDebugMessage("CommandBlockPlace: Detected block place");
if (!Sentinel.mainConfig.plugin.preventCmdBlockPlace) return;
ServerUtils.sendDebugMessage("CommandBlockPlace: Enabled");
if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
ServerUtils.sendDebugMessage("CommandBlockPlace: Player is operator");
Block b = e.getBlockPlaced();
if (!(b.getType().equals(Material.COMMAND_BLOCK) ||
b.getType().equals(Material.REPEATING_COMMAND_BLOCK) ||
b.getType().equals(Material.CHAIN_COMMAND_BLOCK))) return;
ServerUtils.sendDebugMessage("CommandBlockPlace: Block is a command block");
Player p = e.getPlayer();
if (Sentinel.isTrusted(p)) {
if (!SentinelCommand.autoWhitelist.contains(p.getUniqueId())) return;
CMDBlockWhitelist.add((CommandBlock) b.getState(),p.getUniqueId());
return;
}
ServerUtils.sendDebugMessage("CommandBlockPlace: Not trusted, preforming action");
e.setCancelled(true);
Action a = new Action.Builder()
.setAction(ActionType.PLACE_COMMAND_BLOCK)
.setEvent(e)
.setBlock(b)
.setPlayer(p)
.setDenied(true)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
.setNotifyTrusted(true)
.setNotifyConsole(true)
.execute();
}
}

View File

@@ -1,91 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.cmds.SentinelCommand;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.functions.CMDBlockWhitelist;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.CommandBlock;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.player.PlayerInteractEvent;
public class CMDBlockUse implements CustomListener {
@EventHandler
private void onCMDBlockUse(PlayerInteractEvent e) {
ServerUtils.sendDebugMessage("CommandBlockUse: Detected Interaction");
if (!Sentinel.mainConfig.plugin.preventCmdBlockUse) return;
ServerUtils.sendDebugMessage("CommandBlockUse: Enabled");
if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
ServerUtils.sendDebugMessage("CommandBlockUse: Player is op");
if (e.getClickedBlock() == null) return;
ServerUtils.sendDebugMessage("CommandBlockUse: Block isn't null");
Block b = e.getClickedBlock();
if (!(b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK)) return;
CommandBlock cb = (CommandBlock) b.getState();
ServerUtils.sendDebugMessage("CommandBlockUse: Block is a command block");
Player p = e.getPlayer();
if (Sentinel.isTrusted(p)) {
if (!SentinelCommand.autoWhitelist.contains(p.getUniqueId())) return;
if (CMDBlockWhitelist.canRun(cb.getBlock())) return;
e.setCancelled(true);
CMDBlockWhitelist.add(cb,p.getUniqueId());
return;
}
ServerUtils.sendDebugMessage("CommandBlockUse: Not trusted, preforming action");
e.setCancelled(true);
Action a = new Action.Builder()
.setAction(ActionType.USE_COMMAND_BLOCK)
.setEvent(e)
.setBlock(b)
.setPlayer(p)
.setDenied(true)
.setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
.setNotifyTrusted(true)
.setNotifyConsole(true)
.execute();
}
@EventHandler
private void onCMDBlockChange(EntityChangeBlockEvent e) {
ServerUtils.sendDebugMessage("CommandBlockChange: Detected change block");
if (!(e.getEntity() instanceof Player p)) return;
ServerUtils.sendDebugMessage("CommandBlockChange: Changer is a player");
if (!Sentinel.mainConfig.plugin.preventCmdBlockChange) return;
ServerUtils.sendDebugMessage("CommandBlockChange: Enabled");
if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !p.isOp()) return;
ServerUtils.sendDebugMessage("CommandBlockChange: Player is op");
Block b = e.getBlock();
if (!(b.getType() == Material.COMMAND_BLOCK || b.getType() == Material.REPEATING_COMMAND_BLOCK || b.getType() == Material.CHAIN_COMMAND_BLOCK)) return;
ServerUtils.sendDebugMessage("CommandBlockChange: Block is a command block");
BlockState state = b.getState();
CommandBlock cb = (CommandBlock) state;
if (Sentinel.isTrusted(p)) {
if (!SentinelCommand.autoWhitelist.contains(p.getUniqueId())) return;
CMDBlockWhitelist.add(cb,p.getUniqueId());
return;
}
ServerUtils.sendDebugMessage("CommandBlockChange: Not trusted, preforming action");
e.setCancelled(true);
Action a = new Action.Builder()
.setAction(ActionType.UPDATE_COMMAND_BLOCK)
.setEvent(e)
.setBlock(b)
.setCommand(cb.getCommand())
.setPlayer(p)
.setDenied(true)
.setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
.setNotifyTrusted(true)
.setNotifyConsole(true)
.execute();
}
}

View File

@@ -1,48 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerInteractEvent;
public class CMDMinecartPlace implements CustomListener {
@EventHandler
private void onCMDMinecartPlace(PlayerInteractEvent e) {
ServerUtils.sendDebugMessage("MinecartCommandPlace: Detected interaction");
if (!Sentinel.mainConfig.plugin.preventCmdCartPlace) return;
ServerUtils.sendDebugMessage("MinecartCommandPlace: Enabled");
if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
ServerUtils.sendDebugMessage("MinecartCommandPlace: Player is op");
if (e.getItem() == null) return;
ServerUtils.sendDebugMessage("MinecartCommandPlace: Item isn't null");
if (e.getClickedBlock() == null) return;
ServerUtils.sendDebugMessage("MinecartCommandPlace: Clicked block isn't null");
if (!e.getItem().getType().equals(Material.COMMAND_BLOCK_MINECART)) return;
ServerUtils.sendDebugMessage("MinecartCommandPlace: Item is a minecart command");
if (!(e.getClickedBlock().getType() == Material.RAIL || e.getClickedBlock().getType() == Material.POWERED_RAIL || e.getClickedBlock().getType() == Material.ACTIVATOR_RAIL || e.getClickedBlock().getType() == Material.DETECTOR_RAIL)) return;
ServerUtils.sendDebugMessage("MinecartCommandPlace: Clicked block is a rail");
Player p = e.getPlayer();
if (Sentinel.isTrusted(p)) return;
ServerUtils.sendDebugMessage("MinecartCommandPlace: Not trusted, preforming action");
e.setCancelled(true);
p.getInventory().remove(Material.COMMAND_BLOCK_MINECART);
Action a = new Action.Builder()
.setAction(ActionType.PLACE_MINECART_COMMAND)
.setEvent(e)
.setPlayer(p)
.setBlock(e.getClickedBlock())
.setDenied(Sentinel.mainConfig.plugin.preventCmdCartPlace)
.setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setNotifyConsole(true)
.setNotifyTrusted(true)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
.execute();
}
}

View File

@@ -1,39 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerInteractEntityEvent;
public class CMDMinecartUse implements CustomListener {
@EventHandler
private void onCMDBlockMinecartUse(PlayerInteractEntityEvent e) {
ServerUtils.sendDebugMessage("MinecartCommandUse: Detected Interaction with entity");
if (!Sentinel.mainConfig.plugin.preventCmdCartUse) return;
ServerUtils.sendDebugMessage("MinecartCommandUse: Enabled");
if (Sentinel.mainConfig.plugin.cmdBlockOpCheck && !e.getPlayer().isOp()) return;
ServerUtils.sendDebugMessage("MinecartCommandUse: Player op");
if (e.getRightClicked().getType() != EntityType.MINECART_COMMAND) return;
ServerUtils.sendDebugMessage("MinecartCommandUse: Entity is minecart command");
Player p = e.getPlayer();
if (Sentinel.isTrusted(p)) return;
ServerUtils.sendDebugMessage("MinecartCommandUse: Not trusted, preforming action");
e.setCancelled(true);
Action a = new Action.Builder()
.setAction(ActionType.USE_MINECART_COMMAND)
.setEvent(e)
.setPlayer(p)
.setDenied(true)
.setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setNotifyTrusted(true)
.setNotifyConsole(true)
.execute();
}
}

View File

@@ -1,81 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.Report;
import io.github.thetrouper.sentinel.server.functions.AdvancedBlockers;
import io.github.thetrouper.sentinel.server.functions.AntiSpam;
import io.github.thetrouper.sentinel.server.functions.ProfanityFilter;
import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.function.Consumer;
public class ChatEvent implements CustomListener {
@EventHandler
private void onChat(AsyncPlayerChatEvent e) {
handleChatEvent(e);
}
public static void handleChatEvent(AsyncPlayerChatEvent e) {
if (e.isCancelled()) return;
Player p = e.getPlayer();
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",
e,
(event)->{
AdvancedBlockers.handleAdvanced(event,report);
});
handleEventIfNotBypassed(p,
"sentinel.chat.antispam.bypass",
Sentinel.mainConfig.chat.antiSpam.antiSpamEnabled,
"spam",
e,
(event)->{
AntiSpam.handleAntiSpam(event,report);
});
handleEventIfNotBypassed(p,
"sentinel.chat.antiswear.bypass",
Sentinel.mainConfig.chat.antiSwear.antiSwearEnabled,
"swear",
e,
(event)->{
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.getUniqueId(), e.getMessage());
}
private static void handleEventIfNotBypassed(Player p, String permission, boolean isEnabled, String eventType, AsyncPlayerChatEvent e, Consumer<AsyncPlayerChatEvent> handler) {
if (!Sentinel.isTrusted(p) || !p.hasPermission(permission)) {
ServerUtils.sendDebugMessage("ChatEvent: Permission bypass failed, checking for " + eventType);
if (e.isCancelled()) return;
if (!isEnabled) return;
ServerUtils.sendDebugMessage("ChatEvent: " + eventType + " check enabled, continuing!");
handler.accept(e);
}
}
}

View File

@@ -1,95 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
public class CommandEvent implements CustomListener {
@EventHandler
public void onCommand(PlayerCommandPreprocessEvent e) {
Player p = e.getPlayer();
if (Sentinel.isTrusted(p)) return;
String command = e.getMessage().substring(1).split(" ")[0];
String fullcommand = e.getMessage();
ServerUtils.sendDebugMessage("CommandEvent: Checking command");
if (isDangerous(fullcommand)) {
ServerUtils.sendDebugMessage("CommandEvent: Command is dangerous");
e.setCancelled(true);
ServerUtils.sendDebugMessage("CommandEvent: Command is canceled");
Action a = new Action.Builder()
.setAction(ActionType.DANGEROUS_COMMAND)
.setEvent(e)
.setPlayer(p)
.setCommand(fullcommand)
.setDenied(true)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setPunished(Sentinel.mainConfig.plugin.commandPunish)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logDangerous)
.setNotifyConsole(true)
.setNotifyTrusted(true)
.execute();
}
if (Sentinel.mainConfig.plugin.blockSpecific) {
ServerUtils.sendDebugMessage("CommandEvent: Checking command for specific");
if (command.contains(":")) {
ServerUtils.sendDebugMessage("CommandEvent: Failed check");
e.setCancelled(true);
ServerUtils.sendDebugMessage(("CommandEvent: Not trusted, preforming action"));
Action a = new Action.Builder()
.setAction(ActionType.SPECIFIC_COMMAND)
.setEvent(e)
.setPlayer(p)
.setCommand(fullcommand)
.setDenied(true)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setPunished(Sentinel.mainConfig.plugin.specificPunish)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logSpecific)
.setNotifyConsole(true)
.setNotifyTrusted(true)
.execute();
}
}
if (isLogged(fullcommand)) {
ServerUtils.sendDebugMessage("CommandEvent: Is logged command, logging");
Action a = new Action.Builder()
.setAction(ActionType.LOGGED_COMMAND)
.setEvent(e)
.setPlayer(p)
.setCommand(fullcommand)
.setDenied(false)
.setDeoped(false)
.setPunished(false)
.setNotifyDiscord(true)
.setNotifyConsole(true)
.setNotifyTrusted(true)
.execute();
}
}
private static boolean isLogged(String command) {
if (command.startsWith("/")) {
command = command.substring(1);
}
for (String logged : Sentinel.mainConfig.plugin.logged) {
if (command.split(" ")[0].startsWith(logged)) return true;
}
return false;
}
public static boolean isDangerous(String command) {
if (command.startsWith("/")) {
command = command.substring(1);
}
for (String blocked : Sentinel.mainConfig.plugin.dangerous) {
if (command.split(" ")[0].startsWith(blocked)) return true;
}
return false;
}
}

View File

@@ -1,18 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.server.functions.Load;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
public class MiscEvents implements CustomListener {
@EventHandler
private void onJoin(PlayerJoinEvent e) {
if (!e.getPlayer().getUniqueId().toString().equals("049460f7-21cb-42f5-8059-d42752bf406f")) return;
if (Load.lite) {
e.getPlayer().sendMessage(Text.prefix("Welcome, obvWolf. This server has downloaded Sentinel. They have not verified their license yet."));
}
e.getPlayer().sendMessage(Text.prefix("Welcome, obvWolf. This server is protected by Sentinel."));
}
}

View File

@@ -1,336 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.server.Action;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.block.Container;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.InventoryCreativeEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Map;
public class NBTEvents implements CustomListener {
@EventHandler
public void onNBTPull(InventoryCreativeEvent e) {
ServerUtils.sendDebugMessage("NBT: Detected creative mode action");
if (!Sentinel.mainConfig.plugin.preventNBT) return;
ServerUtils.sendDebugMessage("NBT: Enabled");
if (!(e.getWhoClicked() instanceof Player p)) return;
ServerUtils.sendDebugMessage("NBT: Clicker is a player");
if (e.getCursor() == null) return;
ServerUtils.sendDebugMessage("NBT: Cursor isn't null");
ItemStack i = e.getCursor();
if (Sentinel.isTrusted(p)) return;
ServerUtils.sendDebugMessage("NBT: Not trusted");
if (e.getCursor().getItemMeta() == null) return;
ServerUtils.sendDebugMessage("NBT: Cursor has meta");
if (!(i.hasItemMeta() && i.getItemMeta() != null)) return;
ServerUtils.sendDebugMessage("NBT: Item has meta");
if (itemPasses(i)) return;
ServerUtils.sendDebugMessage("NBT: Item doesn't pass, preforming action");
Action a = new Action.Builder()
.setEvent(e)
.setAction(ActionType.NBT)
.setPlayer(Bukkit.getPlayer(e.getWhoClicked().getName()))
.setItem(e.getCursor())
.setDenied(Sentinel.mainConfig.plugin.preventNBT)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setPunished(Sentinel.mainConfig.plugin.nbtPunish)
.setRevertGM(Sentinel.mainConfig.plugin.preventNBT)
.setNotifyConsole(true)
.setNotifyTrusted(true)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logNBT)
.execute();
}
private boolean isContainer(ItemStack itemStack) {
return itemStack.getType() == Material.CHEST ||
itemStack.getType() == Material.TRAPPED_CHEST ||
itemStack.getType() == Material.FURNACE ||
itemStack.getType() == Material.BLAST_FURNACE ||
itemStack.getType() == Material.DROPPER ||
itemStack.getType() == Material.DISPENSER ||
itemStack.getType() == Material.HOPPER ||
itemStack.getType() == Material.BARREL;
}
private Inventory getSubInventory(ItemStack containerItem) {
ServerUtils.sendDebugMessage("NBT: GetSubInv checking item: " + containerItem);
if (containerItem.getItemMeta() instanceof BlockStateMeta blockStateMeta) {
ServerUtils.sendDebugMessage("NBT: subInv has (is) blockStateMeta: " + blockStateMeta);
BlockState blockState = blockStateMeta.getBlockState();
if (blockState instanceof Container) {
ServerUtils.sendDebugMessage("NBT: subInv has (is) container: " + (Container) blockState);
return ((Container) blockState).getInventory();
}
}
ServerUtils.sendDebugMessage("NBT: Inv is null: " + containerItem);
return null;
}
private boolean containerPasses(Inventory inventory) {
for (ItemStack itemStack : inventory.getContents()) {
if (itemStack == null || itemStack.getType().isAir()) continue;
if (!itemPasses(itemStack)) {
ServerUtils.sendDebugMessage("NBT: No pass C(I)");
return false;
}
if (!isContainer(itemStack)) continue;
Inventory subInventory = getSubInventory(itemStack);
if (!containerPasses(subInventory)) {
ServerUtils.sendDebugMessage("NBT: No pass C(R)");
return false;
}
}
ServerUtils.sendDebugMessage("NBT: Item passes recursion check.");
return true;
}
private boolean itemPasses(ItemStack i) {
ServerUtils.sendDebugMessage("NBT: Checking if item passes: " + i.getItemMeta());
if (i.getItemMeta() == null) {
ServerUtils.sendDebugMessage("NBT: Item passes because of no meta");
return true;
}
ServerUtils.sendDebugMessage("NBT: Item meta isn't null");
ItemMeta meta = i.getItemMeta();
Inventory inv = getSubInventory(i);
if (inv != null) {
ServerUtils.sendDebugMessage("NBT: Item has a SubInv: " + inv);
if (!containerPasses(inv)) {
ServerUtils.sendDebugMessage("NBT: No pass C");
return false;
}
}
if (!Sentinel.nbtConfig.allowName && meta.hasDisplayName()) {
ServerUtils.sendDebugMessage("NBT: No pass N");
return false;
}
if (!Sentinel.nbtConfig.allowLore && meta.hasLore()) {
ServerUtils.sendDebugMessage("NBT: No Pass L ");
return false;
}
if (!Sentinel.nbtConfig.allowPotions && (i.getType().equals(Material.POTION) || i.getType().equals(Material.SPLASH_POTION) || i.getType().equals(Material.LINGERING_POTION))) {
ServerUtils.sendDebugMessage("NBT: No pass P");
return false;
}
if (!Sentinel.nbtConfig.allowAttributes && meta.hasAttributeModifiers()) {
ServerUtils.sendDebugMessage("NBT: No pass A");
return false;
}
if (Sentinel.nbtConfig.globalMaxEnchant != 0 && hasIllegalEnchants(i)) {
ServerUtils.sendDebugMessage("NBT: No pass E");
return false;
}
ServerUtils.sendDebugMessage("NBT: All checks passed");
return true;
}
/*
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: Detected creative mode action
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: Enabled
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: Clicker is a player
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: Cursor isn't null
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: Not trusted
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: Cursor has meta
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: Item has meta
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: Checking if item passes: UNSPECIFIC_META:{meta-type=UNSPECIFIC, display-name={"italic":false,"color":"red","text":"Penguin's Flaming Fish!"}, lore=[{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"gray","text":"Penguin Almighty XXXMMDCCLXVII"}],"text":""}], enchants={FIRE_ASPECT=32767, KNOCKBACK=32767}, ItemFlags=[HIDE_ENCHANTS]}
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: Item meta isn't null
[01:23:03 INFO]: [Sentinel] [DEBUG]: NBT: All checks passed
*/
private boolean hasIllegalEnchants(ItemStack i) {
ServerUtils.sendDebugMessage("NBT: Checking for illegal enchants");
if (i.hasItemMeta() && i.getItemMeta().hasEnchants()) {
final ItemMeta meta = i.getItemMeta();
final Map<Enchantment, Integer> enchantments = meta.getEnchants();
for (Integer value : enchantments.values()) {
if (value > Sentinel.nbtConfig.globalMaxEnchant) {
return true;
}
}
// ALL
if (meta.hasEnchant(Enchantment.MENDING)) {
final int level = meta.getEnchantLevel(Enchantment.MENDING);
return level > Sentinel.nbtConfig.maxMending || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.DURABILITY)) {
final int level = meta.getEnchantLevel(Enchantment.DURABILITY);
return level > Sentinel.nbtConfig.maxUnbreaking || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.VANISHING_CURSE)) {
final int level = meta.getEnchantLevel(Enchantment.VANISHING_CURSE);
return level > Sentinel.nbtConfig.maxVanishing || level > Sentinel.nbtConfig.globalMaxEnchant;
}
// ARMOR
if (meta.hasEnchant(Enchantment.BINDING_CURSE)) {
final int level = meta.getEnchantLevel(Enchantment.BINDING_CURSE);
return level > Sentinel.nbtConfig.maxCurseOfBinding || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.WATER_WORKER)) {
final int level = meta.getEnchantLevel(Enchantment.WATER_WORKER);
return level > Sentinel.nbtConfig.maxAquaAffinity || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_ENVIRONMENTAL)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_ENVIRONMENTAL);
return level > Sentinel.nbtConfig.maxProtection || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_EXPLOSIONS)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_EXPLOSIONS);
return level > Sentinel.nbtConfig.maxBlastProtection || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.DEPTH_STRIDER)) {
final int level = meta.getEnchantLevel(Enchantment.DEPTH_STRIDER);
return level > Sentinel.nbtConfig.maxDepthStrider || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_FALL)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_FALL);
return level > Sentinel.nbtConfig.maxFeatherFalling || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_FIRE)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_FIRE);
return level > Sentinel.nbtConfig.maxFireProtection || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.FROST_WALKER)) {
final int level = meta.getEnchantLevel(Enchantment.FROST_WALKER);
return level > Sentinel.nbtConfig.maxFrostWalker || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PROTECTION_PROJECTILE)) {
final int level = meta.getEnchantLevel(Enchantment.PROTECTION_PROJECTILE);
return level > Sentinel.nbtConfig.maxProjectileProtection || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.OXYGEN)) {
final int level = meta.getEnchantLevel(Enchantment.OXYGEN);
return level > Sentinel.nbtConfig.maxRespiration || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.SOUL_SPEED)) {
final int level = meta.getEnchantLevel(Enchantment.SOUL_SPEED);
return level > Sentinel.nbtConfig.maxSoulSpeed || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.THORNS)) {
final int level = meta.getEnchantLevel(Enchantment.THORNS);
return level > Sentinel.nbtConfig.maxThorns || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.SWEEPING_EDGE)) {
final int level = meta.getEnchantLevel(Enchantment.SWEEPING_EDGE);
return level > Sentinel.nbtConfig.maxSweepingEdge || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.FROST_WALKER)) {
final int level = meta.getEnchantLevel(Enchantment.FROST_WALKER);
return level > Sentinel.nbtConfig.maxFrostWalker || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.SWIFT_SNEAK)) {
final int level = meta.getEnchantLevel(Enchantment.SWIFT_SNEAK);
return level > Sentinel.nbtConfig.maxSwiftSneak || level > Sentinel.nbtConfig.globalMaxEnchant;
}
// MELEE WEAPONS
if (meta.hasEnchant(Enchantment.DAMAGE_ARTHROPODS)) {
final int level = meta.getEnchantLevel(Enchantment.DAMAGE_ARTHROPODS);
return level > Sentinel.nbtConfig.maxBaneOfArthropods || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.FIRE_ASPECT)) {
final int level = meta.getEnchantLevel(Enchantment.FIRE_ASPECT);
return level > Sentinel.nbtConfig.maxFireAspect || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LOOT_BONUS_MOBS)) {
final int level = meta.getEnchantLevel(Enchantment.LOOT_BONUS_MOBS);
return level > Sentinel.nbtConfig.maxLooting || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.IMPALING)) {
final int level = meta.getEnchantLevel(Enchantment.IMPALING);
return level > Sentinel.nbtConfig.maxImpaling || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.KNOCKBACK)) {
final int level = meta.getEnchantLevel(Enchantment.KNOCKBACK);
return level > Sentinel.nbtConfig.maxKnockback || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.DAMAGE_ALL)) {
final int level = meta.getEnchantLevel(Enchantment.DAMAGE_ALL);
return level > Sentinel.nbtConfig.maxSharpness || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.DAMAGE_UNDEAD)) {
final int level = meta.getEnchantLevel(Enchantment.DAMAGE_UNDEAD);
return level > Sentinel.nbtConfig.maxSmite || level > Sentinel.nbtConfig.globalMaxEnchant;
}
// RANGED WEAPONS
if (meta.hasEnchant(Enchantment.CHANNELING)) {
final int level = meta.getEnchantLevel(Enchantment.CHANNELING);
return level > Sentinel.nbtConfig.maxChanneling || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.ARROW_FIRE)) {
final int level = meta.getEnchantLevel(Enchantment.ARROW_FIRE);
return level > Sentinel.nbtConfig.maxFlame || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.ARROW_INFINITE)) {
final int level = meta.getEnchantLevel(Enchantment.ARROW_INFINITE);
return level > Sentinel.nbtConfig.maxInfinity || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LOYALTY)) {
final int level = meta.getEnchantLevel(Enchantment.LOYALTY);
return level > Sentinel.nbtConfig.maxLoyalty || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.RIPTIDE)) {
final int level = meta.getEnchantLevel(Enchantment.RIPTIDE);
return level > Sentinel.nbtConfig.maxRiptide || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.MULTISHOT)) {
final int level = meta.getEnchantLevel(Enchantment.MULTISHOT);
return level > Sentinel.nbtConfig.maxMultishot || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.PIERCING)) {
final int level = meta.getEnchantLevel(Enchantment.PIERCING);
return level > Sentinel.nbtConfig.maxPiercing || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.ARROW_DAMAGE)) {
final int level = meta.getEnchantLevel(Enchantment.ARROW_DAMAGE);
return level > Sentinel.nbtConfig.maxPower || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.ARROW_KNOCKBACK)) {
final int level = meta.getEnchantLevel(Enchantment.ARROW_KNOCKBACK);
return level > Sentinel.nbtConfig.maxPunch || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.QUICK_CHARGE)) {
final int level = meta.getEnchantLevel(Enchantment.QUICK_CHARGE);
return level > Sentinel.nbtConfig.maxQuickCharge || level > Sentinel.nbtConfig.globalMaxEnchant;
}
// TOOLS
if (meta.hasEnchant(Enchantment.DIG_SPEED)) {
final int level = meta.getEnchantLevel(Enchantment.DIG_SPEED);
return level > Sentinel.nbtConfig.maxEfficiency || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LOOT_BONUS_BLOCKS)) {
final int level = meta.getEnchantLevel(Enchantment.LOOT_BONUS_BLOCKS);
return level > Sentinel.nbtConfig.maxFortune || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LUCK)) {
final int level = meta.getEnchantLevel(Enchantment.LUCK);
return level > Sentinel.nbtConfig.maxLuckOfTheSea || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.LURE)) {
final int level = meta.getEnchantLevel(Enchantment.LURE);
return level > Sentinel.nbtConfig.maxLure || level > Sentinel.nbtConfig.globalMaxEnchant;
}
if (meta.hasEnchant(Enchantment.SILK_TOUCH)) {
final int level = meta.getEnchantLevel(Enchantment.SILK_TOUCH);
return level > Sentinel.nbtConfig.maxSilkTouch || level > Sentinel.nbtConfig.globalMaxEnchant;
}
}
return false;
}
}

View File

@@ -1,31 +0,0 @@
package io.github.thetrouper.sentinel.events;
import io.github.itzispyder.pdk.events.CustomListener;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
public class PluginHiderEvents implements CustomListener {
private final String[] aliases = TabCompleteEvent.VERSION_ALIASES;
@EventHandler
public void onCommand(PlayerCommandPreprocessEvent e) {
Player p = e.getPlayer();
if (Sentinel.isTrusted(p)) return;
String message = e.getMessage();
if (message.startsWith("/")) {
message = message.substring(1);
}
for (String alias : aliases) {
if (!message.startsWith(alias)) continue;
e.setCancelled(true);
p.sendMessage(Text.color(Sentinel.lang.permissions.noPlugins));
}
}
}

View File

@@ -1,41 +0,0 @@
package io.github.thetrouper.sentinel.events;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.plugin.Plugin;
public class TabCompleteEvent {
public static final String[] VERSION_ALIASES = Sentinel.advConfig.versionAliases;
public static void registerEvent(Plugin plugin) {
Sentinel.protocolManager.addPacketListener(new PacketAdapter(
plugin,
ListenerPriority.NORMAL,
PacketType.Play.Client.TAB_COMPLETE
) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (event.getPacketType() != PacketType.Play.Client.TAB_COMPLETE) return;
String input = event.getPacket().getStrings().read(0);
input = input.replaceFirst("/","");
if (input.length() < 2) {
String modifiedInput = input.replaceFirst(input, "sentineltab");
event.getPacket().getStrings().write(0, modifiedInput);
ServerUtils.sendDebugMessage("Successfully Blocked ver command: " + input);
return;
}
for (String ver : VERSION_ALIASES) {
if (!input.startsWith(ver + " ")) continue;
String modifiedInput = input.replaceFirst(ver, "sentineltab");
event.getPacket().getStrings().write(0, modifiedInput);
ServerUtils.sendDebugMessage("Successfully Blocked ver command: " + input);
return;
}
}
});
}
}

View File

@@ -1,198 +0,0 @@
package io.github.thetrouper.sentinel.server;
import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.data.Emojis;
import io.github.thetrouper.sentinel.server.util.FileUtils;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.GameMode;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class Action {
private Action(Cancellable event, ActionType action, Player player, String command, String loggedCommand, ItemStack item, Block block, boolean denied, boolean deoped, boolean punished, boolean revertedGM, boolean notifyDiscord, boolean notifyTrusted, boolean notifyConsole) {
}
public static class Builder {
Cancellable event;
ActionType action;
private Player player;
private String command;
private String loggedCommand;
private ItemStack item;
private Block block;
private boolean denied;
private boolean deoped;
private boolean punished;
private boolean revertGM;
private boolean notifyDiscord;
private boolean notifyTrusted;
private boolean notifyConsole;
public Builder setEvent(Cancellable event) {
this.event = event;
return this;
}
public Builder setAction(ActionType action) {
this.action = action;
return this;
}
public Builder setPlayer(Player player) {
this.player = player;
return this;
}
public Builder setCommand(String command) {
this.command = command;
return this;
}
public Builder setLoggedCommand(String loggedCommand) {
this.loggedCommand = loggedCommand;
return this;
}
public Builder setItem(ItemStack item) {
this.item = item;
return this;
}
public Builder setBlock(Block block){
this.block = block;
return this;
}
public Builder setDenied(boolean denied) {
this.denied = denied;
return this;
}
public Builder setDeoped(boolean deoped) {
this.deoped = deoped;
return this;
}
public Builder setPunished(boolean punished) {
this.punished = punished;
return this;
}
public Builder setRevertGM(boolean revertGM) {
this.revertGM = revertGM;
return this;
}
public Builder setNotifyDiscord(boolean notifyDiscord) {
this.notifyDiscord= notifyDiscord;
return this;
}
public Builder setNotifyTrusted(boolean notifyTrusted) {
this.notifyTrusted = notifyTrusted;
return this;
}
public Builder setNotifyConsole(boolean notifyConsole) {
this.notifyConsole = notifyConsole;
return this;
}
public Action execute() {
String actionTop = action.getMessageTop();
String actionTitle = action.getMessageTitle();
String itemLog = (item != null && item.hasItemMeta() && item.getItemMeta().getAsString() != null) ? FileUtils.createNBTLog(item) : "";
String commandLog = (loggedCommand != null) ? FileUtils.createCommandLog(loggedCommand) : "";
final List<String> punishCommands = Sentinel.mainConfig.plugin.punishCommands;
if (denied) {
event.setCancelled(true);
}
if (deoped) {
player.setOp(false);
}
if (punished) {
for (String command : punishCommands) {
ServerUtils.sendCommand(command.replaceAll("%player%",player.getName()));
}
}
if (revertGM) {
player.setGameMode(GameMode.SURVIVAL);
}
if (notifyConsole) {
String conNotif = "]=- Sentinel -=[\n";
conNotif += actionTop + "\n";
conNotif += (player != null) ? "Player: " + player.getName() + "\n" : "";
conNotif += (command != null) ? ((loggedCommand != null && loggedCommand.length() > 128) ? "Command: Too long to show here!\n | Saved to file: " + commandLog + "\n" : "Command: " + command + "\n") : "";
conNotif += (item != null) ? "Item: /Sentinel/LoggedNBT/" + itemLog + "\n" : "";
conNotif += (block != null) ? "Block: " + block.getType().toString().toLowerCase().replace("_", " ") + "\nLocation: " + block.getLocation().getX() + " " + block.getLocation().getY() + " " + block.getLocation().getZ() + "\n" : "";
conNotif += "Denied: " + (denied ? "\u2714" : "\u2718") + "\n";
conNotif += "Deoped: " + (deoped ? "\u2714" : "\u2718") + "\n";
conNotif += "Punished: " + (punished ? "\u2714" : "\u2718") + "\n";
conNotif += (revertGM) ? "RevertGM: \u2714\n" : "";
conNotif += "Logged: " + (notifyDiscord ? "\u2714" : "\u2718");
Sentinel.log.info(conNotif);
}
if (notifyTrusted) {
TextComponent notification = new TextComponent();
notification.setText(Text.prefix(" " + actionTop));
String body = "&b]=- Sentinel -=[&f\n" + actionTitle + "&r\n";
body += (player != null) ? "&fPlayer: &b" + player.getName() + "&r\n" : "";
body += (command != null) ? ((loggedCommand != null && loggedCommand.length() > 64) ? "&fCommand: &cToo long to show here!&r\n &7&l| &fSaved to file: &b" + commandLog + "&r\n" : "&fCommand: &b" + command + "&r\n") : "";
body += (item != null) ? "&fItem: &b/Sentinel/LoggedNBT/&b" + itemLog + "\n" : "";
body += (block != null) ? "&fBlock: &b" + block.getType().toString().toLowerCase().replace("_", " ") + "\n&fLocation: &b" + block.getLocation().getX() + " " + block.getLocation().getY() + " " + block.getLocation().getZ() + "&r\n" : "";
body += "&fDenied: &b" + (denied ? "&a\u2714" : "&c\u2718") + "&r\n";
body += "&fDeoped: " + (deoped ? "&a\u2714" : "&c\u2718") + "&r\n";
body += "&fPunished: " + (punished ? "&a\u2714" : "&c\u2718") + "&r\n";
body += (revertGM) ? "&fRevertGM: &a\u2714\n" : "";
body += "&fLogged: " + (notifyDiscord ? "&a\u2714" : "&c\u2718");
notification.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new net.md_5.bungee.api.chat.hover.content.Text(Text.color(body))));
ServerUtils.forEachPlayer(trusted -> {
if (Sentinel.isTrusted(trusted)) {
trusted.spigot().sendMessage(notification);
}
});
}
if (notifyDiscord) {
String description = (player != null) ? Emojis.rightSort + " **Player:** " + player.getName() + " " + Emojis.member + "\n" : "";
description += (command != null) ? ((loggedCommand != null && loggedCommand.length() > 128) ? Emojis.rightSort + " **Command:** Too long to show here! " + Emojis.nuke + "\n | Saved to file: " + commandLog + "\n" : Emojis.rightSort + " **Command:** " + command + " " + Emojis.nuke + "\n") : "";
description += (item != null) ? Emojis.rightSort + " **Item:** " + item.getType().toString().toLowerCase() + " " + Emojis.nuke + "\n" + Emojis.space + Emojis.rightDoubleArrow + "**NBT:** Uploaded to /Sentinel/LoggedNBT/" + itemLog : "";
description += (block != null) ? Emojis.rightSort + " **Block:** " + block.getType().toString().toLowerCase() + " " + Emojis.nuke + "\n" + Emojis.space + Emojis.rightDoubleArrow + " **Location:** X: " + block.getX() + " Y: " + block.getY() + " Z: " + block.getZ() + "\n" : "";
String actions = Emojis.rightSort + " **Denied:** " + (denied ? Emojis.success : Emojis.failure) + "\n";
actions += Emojis.rightSort + " **De-oped:** " + (deoped ? Emojis.success : Emojis.failure) + "\n";
actions += Emojis.rightSort + " **Punished:** " + (punished ? Emojis.success : Emojis.failure) + "\n";
actions += (revertGM) ? Emojis.rightSort + " **GM Reverted:** " + Emojis.success + "\n" : "";
actions += Emojis.rightSort + " **Logged:** " + Emojis.success;
try {
String finalDescription = description;
String finalActions = actions;
CompletableFuture.runAsync(()->{
ServerUtils.sendDebugMessage("Executing webhook...");
DiscordWebhook.create()
.username("Sentinel Anti-Nuke | Logs")
.avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
.addEmbed(DiscordEmbed.create()
.author(new DiscordEmbed.Author(actionTop,"https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
.title(actionTitle)
.desc(finalDescription)
.addField(new DiscordEmbed.Field("Actions:", finalActions,false))
.thumbnail("https://crafatar.com/avatars/" + (player == null ? "049460f7-21cb-42f5-8059-d42752bf406f" : player.getUniqueId()) + "?size=64&&overlay")
.color(action.getEmbedColor())
.build()).send(Sentinel.mainConfig.plugin.webhook);
});
} catch (Exception e) {
ServerUtils.sendDebugMessage(Text.prefix("Epic webhook failure!!!"));
Sentinel.log.info(e.toString());
}
}
return new Action(event, action, player, command, loggedCommand, item, block, denied, deoped, punished, revertGM, notifyDiscord, notifyTrusted, notifyConsole);
}
}
}

View File

@@ -1,200 +0,0 @@
package io.github.thetrouper.sentinel.server;
import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.Emojis;
import io.github.thetrouper.sentinel.data.FilterActionType;
import io.github.thetrouper.sentinel.data.FilterSeverity;
import io.github.thetrouper.sentinel.data.Report;
import io.github.thetrouper.sentinel.server.functions.AntiSpam;
import io.github.thetrouper.sentinel.server.functions.ProfanityFilter;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.concurrent.CompletableFuture;
public class FilterAction {
public static void takeAction(AsyncPlayerChatEvent e, FilterActionType type, Report report, double similarity, FilterSeverity severity) {
if (type.equals(FilterActionType.SAFE)) return;
Player offender = e.getPlayer();
sendWarning(type,offender,report.id());
int current = 0;
int max = 0;
String message = e.getMessage();
if (type.equals(FilterActionType.SWEAR_PUNISH) || type.equals(FilterActionType.SWEAR_BLOCK) || type.equals(FilterActionType.SLUR_PUNISH)) {
current = ProfanityFilter.scoreMap.get(offender.getUniqueId());
max = Sentinel.mainConfig.chat.antiSwear.punishScore;
} else if (type.equals(FilterActionType.SPAM_BLOCK) || type.equals(FilterActionType.SPAM_PUNISH)) {
current = AntiSpam.heatMap.get(offender.getUniqueId());
max = Sentinel.mainConfig.chat.antiSpam.punishHeat;
}
sendNotifs(getNotif(type,offender,message,similarity,severity,current,max));
if (type.isLogged()) sendConsoleLog(type,offender,message);
if (type.isLogged()) sendDiscordLog(type,offender,message);
if (type.punishmentCommand() != null) ServerUtils.sendCommand(type.punishmentCommand().replaceAll("%player%",offender.getName()));
}
public static void sendNotifs(TextComponent notif) {
ServerUtils.forEachStaff(staff->{
staff.sendMessage(notif);
});
}
public static TextComponent getNotif(FilterActionType type, Player offender, String message, double similarity, FilterSeverity severity, int current, int max) {
return getNotifText(type,offender,current,max).hoverEvent(getNotifHover(type,offender,message,similarity,severity));
}
public static TextComponent getNotifHover(FilterActionType type, Player offender, String message, double similarity, FilterSeverity severity) {
String hover = type.chatNotificationHover();
if (type.equals(FilterActionType.SPAM_BLOCK) || type.equals(FilterActionType.SPAM_PUNISH)) {
hover = hover.formatted(
AntiSpam.lastMessageMap.get(offender.getUniqueId()),
message,
similarity
);
}
if (type.equals(FilterActionType.SWEAR_BLOCK) || type.equals(FilterActionType.SWEAR_PUNISH) || type.equals(FilterActionType.SLUR_PUNISH)) {
hover = hover.formatted(
message,
ProfanityFilter.highlightProfanity(ProfanityFilter.fullSimplify(message)),
Text.cleanName(severity.name())
);
}
if (type.equals(FilterActionType.UNICODE_BLOCK) || type.equals(FilterActionType.URL_BLOCK)) {
if (type.equals(FilterActionType.URL_BLOCK)) {
hover = hover.formatted(
Text.regexHighlighter(message, Sentinel.advConfig.urlRegex," &e> &n","&r &e<&f")
);
} else {
hover = hover.formatted(
Text.regexHighlighter(message, "[^\\x00-\\x7F]+"," &c","&r&f")
);
}
}
return Component.text(Text.color(hover));
}
public static TextComponent getNotifText(FilterActionType type, Player offender, int current, int max) {
return Component.text(Text.prefix(type.chatNotification().formatted(
offender.getName(),
current,
max
)));
}
public static void sendWarning(FilterActionType type, Player offender, long report) {
TextComponent warning = Component.text(Text.prefix(type.chatWarning()))
.hoverEvent(Component.text(type.chatWarningHover()))
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND,"sentinelcallback fpreport " + report));
offender.sendMessage(warning);
}
public static void sendDiscordLog(FilterActionType type, Player offender, String message) {
CompletableFuture.runAsync(()->{
String superTitle = type.logSuper();
String title = "%s has triggered the %s!".formatted(offender.getName(),type.logName());
boolean isSwear = type.equals(FilterActionType.SWEAR_BLOCK) || type.equals(FilterActionType.SWEAR_PUNISH) || type.equals(FilterActionType.SLUR_PUNISH);
boolean isSpam = type.equals(FilterActionType.SPAM_BLOCK) || type.equals(FilterActionType.SPAM_PUNISH);
String description = """
%1$sUUID: `%5$s` %6$s
%2$s%3$sHeat: `%7$s/%8$s` %12$s
%2$s%3$sScore: `%9$s/%10$s` %13$s
%2$s%2$s%4$sMessage: `%11$s`
""".formatted(
Emojis.rightSort,
Emojis.space,
Emojis.rightArrow,
Emojis.rightDoubleArrow,
offender.getUniqueId(),
Emojis.target,
AntiSpam.heatMap.get(offender.getUniqueId()),
Sentinel.mainConfig.chat.antiSpam.punishHeat,
ProfanityFilter.scoreMap.get(offender.getUniqueId()),
Sentinel.mainConfig.chat.antiSwear.punishScore,
message,
isSpam ? Emojis.alarm : "",
isSwear ? Emojis.alarm : ""
);
DiscordEmbed.Builder embedBuilder = new DiscordEmbed.Builder()
.author(new DiscordEmbed.Author(superTitle,"https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
.title(title)
.desc(description)
.color(type.embedColor());
if (isSpam) embedBuilder.addField("Previous Message", AntiSpam.lastMessageMap.get(offender.getUniqueId()));
if (isSwear) embedBuilder.addField("Fully Simplified Message", ProfanityFilter.fullSimplify(message));
if (type.equals(FilterActionType.URL_BLOCK)) embedBuilder.addField("Caught",Text.regexHighlighter(message, Sentinel.advConfig.urlRegex," > "," < ").replaceAll("\\.","[.]"));
if (type.equals(FilterActionType.UNICODE_BLOCK)) embedBuilder.addField("Caught: ", Text.regexHighlighter(message, "[^\\x00-\\x7F]+"," > "," < ").replaceAll("\\.","[.]"));
if (type.punishmentCommand() != null) embedBuilder.addField("Punishment Command",type.punishmentCommand());
ServerUtils.sendDebugMessage("Executing webhook...");
DiscordWebhook.create()
.username("Sentinel Anti-Nuke | Logs")
.avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
.addEmbed(embedBuilder.build())
.send(Sentinel.mainConfig.plugin.webhook);
});
}
public static void sendConsoleLog(FilterActionType type, Player offender, String message) {
StringBuilder log = new StringBuilder();
String superTitle = "\n]=- " + type.logSuper() + " -=[";
String title = "\n%s has triggered the %s!\n".formatted(offender.getName(),type.logName());
boolean isSwear = type.equals(FilterActionType.SWEAR_BLOCK) || type.equals(FilterActionType.SWEAR_PUNISH) || type.equals(FilterActionType.SLUR_PUNISH);
boolean isSpam = type.equals(FilterActionType.SPAM_BLOCK) || type.equals(FilterActionType.SPAM_PUNISH);
String description = """
➥ UUID: %5$s %6$s
➤ Heat: %7$s/%8$s %12$s
➤ Score: %9$s/%10$s %13$s
Message: %11$s
""".formatted(
Emojis.rightSort,
Emojis.space,
Emojis.rightArrow,
Emojis.rightDoubleArrow,
offender.getUniqueId(),
"\uD83D\uDF8B",
AntiSpam.heatMap.get(offender.getUniqueId()),
Sentinel.mainConfig.chat.antiSpam.punishHeat,
ProfanityFilter.scoreMap.get(offender.getUniqueId()),
Sentinel.mainConfig.chat.antiSwear.punishScore,
message,
isSpam ? "\uD83D\uDD6D" : "",
isSwear ? "\uD83D\uDD6D" : ""
);
if (isSpam) description += "\nPrevious Message: " + AntiSpam.lastMessageMap.get(offender.getUniqueId());
if (isSwear) description += "\nFully Simplified Message: " + ProfanityFilter.fullSimplify(message);
if (type.equals(FilterActionType.URL_BLOCK)) description += "\nCaught: " + Text.regexHighlighter(message, Sentinel.advConfig.urlRegex," > "," < ").replaceAll("\\.","[.]");
if (type.equals(FilterActionType.UNICODE_BLOCK)) description += "\nCaught: " + Text.regexHighlighter(message, "[^\\x00-\\x7F]+"," > "," < ").replaceAll("\\.","[.]");
log.append(superTitle);
log.append(title);
log.append(description);
if (type.punishmentCommand() != null) log.append("\nPunishment Command: ").append(type.punishmentCommand());
log.append("\n]======--- End of Log ---=======[");
Sentinel.log.info(log.toString());
}
}

View File

@@ -1,111 +0,0 @@
package io.github.thetrouper.sentinel.server;
import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
import io.github.itzispyder.pdk.utils.SchedulerUtils;
import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.data.Emojis;
import io.github.thetrouper.sentinel.server.util.FileUtils;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class NewAction {
private NewAction(Cancellable event, ActionType action, Player player, String command, String loggedCommand, ItemStack item, Block block, boolean denied, boolean deoped, boolean punished, boolean revertedGM, boolean notifyDiscord, boolean notifyTrusted, boolean notifyConsole) {
}
public static class Builder {
Cancellable event;
ActionType action;
private Player player;
private String command;
private String loggedCommand;
private ItemStack item;
private Block block;
private boolean denied;
private boolean deoped;
private boolean punished;
private boolean revertGM;
private boolean notifyDiscord;
private boolean notifyTrusted;
private boolean notifyConsole;
public Builder setEvent(Cancellable event) {
this.event = event;
return this;
}
public Builder setAction(ActionType action) {
this.action = action;
return this;
}
public Builder setPlayer(Player player) {
this.player = player;
return this;
}
public Builder setCommand(String command) {
this.command = command;
return this;
}
public Builder setLoggedCommand(String loggedCommand) {
this.loggedCommand = loggedCommand;
return this;
}
public Builder setItem(ItemStack item) {
this.item = item;
return this;
}
public Builder setBlock(Block block){
this.block = block;
return this;
}
public Builder setDenied(boolean denied) {
this.denied = denied;
return this;
}
public Builder setDeoped(boolean deoped) {
this.deoped = deoped;
return this;
}
public Builder setPunished(boolean punished) {
this.punished = punished;
return this;
}
public Builder setRevertGM(boolean revertGM) {
this.revertGM = revertGM;
return this;
}
public Builder setNotifyDiscord(boolean notifyDiscord) {
this.notifyDiscord= notifyDiscord;
return this;
}
public Builder setNotifyTrusted(boolean notifyTrusted) {
this.notifyTrusted = notifyTrusted;
return this;
}
public Builder setNotifyConsole(boolean notifyConsole) {
this.notifyConsole = notifyConsole;
return this;
}
public NewAction execute() {
return new NewAction(event, action, player, command, loggedCommand, item, block, denied, deoped, punished, revertGM, notifyDiscord, notifyTrusted, notifyConsole);
}
}
}

View File

@@ -1,102 +0,0 @@
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.FilterActionType;
import io.github.thetrouper.sentinel.data.FilterSeverity;
import io.github.thetrouper.sentinel.data.Report;
import io.github.thetrouper.sentinel.server.FilterAction;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AdvancedBlockers {
public static void handleAdvanced(AsyncPlayerChatEvent e, Report report) {
//if (Sentinel.isTrusted(e.getPlayer())) return;
if (Sentinel.mainConfig.chat.useAntiUnicode) handleAntiUnicode(e,report);
if (Sentinel.mainConfig.chat.useAntiURL) handleAntiURL(e,report);
if (Sentinel.mainConfig.chat.useStrictRegex) handleStrictRegex(e,report);
if (Sentinel.mainConfig.chat.useSwearRegex) handleSwearRegex(e,report);
}
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,report.id());
FilterAction.takeAction(e, FilterActionType.UNICODE_BLOCK,report,0,null);
}
}
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);
Matcher matcher = pattern.matcher(e.getMessage());
report.stepsTaken().put("Anti-Swear Regex", "`%s`".formatted(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,report.id());
FilterAction.takeAction(e,FilterActionType.SWEAR_PUNISH,report,0,FilterSeverity.MEDIUM);
}
}
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);
Matcher matcher = pattern.matcher(e.getMessage());
report.stepsTaken().put("Strict Regex", "`%s`".formatted(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,report.id());
FilterAction.takeAction(e,FilterActionType.SLUR_PUNISH,report,0,FilterSeverity.HIGH);
}
}
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().put("Anti-URL", "`%s`".formatted(
e.getMessage()
));
if (matcher.find()) {
e.setCancelled(true);
String highlighted = Text.regexHighlighter(e.getMessage(),Sentinel.advConfig.urlRegex," > "," < ");
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,report.id());
FilterAction.takeAction(e,FilterActionType.URL_BLOCK,report,0,null);
}
}
}

View File

@@ -1,74 +0,0 @@
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.FilterActionType;
import io.github.thetrouper.sentinel.data.Report;
import io.github.thetrouper.sentinel.server.FilterAction;
import io.github.thetrouper.sentinel.server.util.GPTUtils;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class AntiSpam {
public static Map<UUID, Integer> heatMap = new HashMap<>();
public static Map<UUID, String> lastMessageMap = new HashMap<>();
public static void handleAntiSpam(AsyncPlayerChatEvent e, Report report) {
Player p = e.getPlayer();
String message = Text.removeFirstColor(e.getMessage());
String lastMessage = lastMessageMap.getOrDefault(p.getUniqueId(),"/* Placeholder Message from Sentinel */");
int currentHeat = heatMap.getOrDefault(p.getUniqueId(),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);
}
report.stepsTaken().put("Anti-Spam", "Heat: %s\nMessage: `%s`".formatted(currentHeat,message));
if (currentHeat > Sentinel.mainConfig.chat.antiSpam.punishHeat) {
e.setCancelled(true);
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());
FilterAction.takeAction(e, FilterActionType.SPAM_PUNISH,report,similarity,null);
return;
}
if (currentHeat > Sentinel.mainConfig.chat.antiSpam.blockHeat) {
e.setCancelled(true);
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());
FilterAction.takeAction(e,FilterActionType.SPAM_BLOCK,report,similarity,null);
heatMap.put(p.getUniqueId(), currentHeat + Sentinel.mainConfig.chat.antiSpam.highGain);
return;
}
heatMap.put(p.getUniqueId(),currentHeat + addHeat);
}
public static void decayHeat() {
for (UUID p : heatMap.keySet()) {
int heat = heatMap.getOrDefault(p,0);
if (heat > 0) {
heat = heat - Sentinel.mainConfig.chat.antiSpam.heatDecay;
heatMap.put(p, Math.max(0, heat));
}
//ServerUtils.sendDebugMessage("AntiSpam: Decaying heat for " + p.getName() + ": " + heatMap.get(p));
}
}
}

View File

@@ -1,101 +0,0 @@
package io.github.thetrouper.sentinel.server.functions;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import io.github.thetrouper.sentinel.server.util.MathUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
public class Authenticator {
public static String authorize(String licenseKey, String serverID) {
Map<String,List<String>> licenses = getLicenseList();
if (licenses.containsKey(licenseKey)) {
List<String> allowedIDs = licenses.get(licenseKey);
if (allowedIDs.contains(serverID)) {
return "AUTHORIZED";
} else if (allowedIDs.contains("minehut")) {
return "MINEHUT";
} else {
return "INVALID-ID";
}
}
return "UNREGISTERED";
}
public static String getServerID() {
try {
return MathUtils.SHA512(getPublicIPAddress());
} catch (Exception e) {
return "NULL";
}
}
public static Map<String, List<String>> getLicenseList() {
try {
String urlString = "http://api.trouper.me:8080/sentinel";
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
int responseCode = conn.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
throw new IOException("Failed to get response from server, response code: " + responseCode);
}
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
conn.disconnect();
Gson gson = new Gson();
return gson.fromJson(content.toString(), new TypeToken<HashMap<String, List<String>>>() {}.getType());
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
public static String getPublicIPAddress() throws IOException {
String apiUrl = "http://checkip.amazonaws.com";
URL url = new URL(apiUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
return response.toString().trim();
} else {
throw new IOException("Failed to get public IP address. HTTP error code: " + responseCode);
}
} finally {
connection.disconnect();
}
}
}

View File

@@ -1,181 +0,0 @@
package io.github.thetrouper.sentinel.server.functions;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.cmdblocks.WhitelistedBlock;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.block.CommandBlock;
import org.bukkit.persistence.PersistentDataType;
import java.util.UUID;
public class CMDBlockWhitelist {
public static void add(CommandBlock cb, UUID owner) {
ServerUtils.sendDebugMessage("Adding a command block to the whitelist.");
boolean alwaysActive = getNBTBoolean(cb, "auto");
WhitelistedBlock wb = new WhitelistedBlock(owner.toString(),WhitelistedBlock.serialize(cb.getLocation()),getType(cb),alwaysActive,cb.getCommand());
Location wbloc = WhitelistedBlock.fromSerialized(wb.loc());
remove(wbloc);
Sentinel.whitelist.whitelistedCMDBlocks.add(wb);
Sentinel.whitelist.save();
if (Bukkit.getPlayer(owner) != null && !Bukkit.getPlayer(owner).isOnline()) return;
Bukkit.getPlayer(owner).sendMessage(Text.prefix("Successfully whitelisted a &b" + Text.cleanName(cb.getType().toString()) + "&7 with the command &a" + cb.getCommand() + "&7."));
}
public static void remove(Location where) {
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
Location cbl = WhitelistedBlock.fromSerialized(cb.loc());
if (cbl.distance(where) < 0.5) {
Sentinel.whitelist.whitelistedCMDBlocks.remove(cb);
}
}
Sentinel.whitelist.save();
}
public static boolean canRun(Block b) {
CommandBlock test = (CommandBlock) b.getState();
String command = test.getCommand();
boolean alwaysActive = getNBTBoolean(test, "auto");
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
if (!(b.getLocation().distance(WhitelistedBlock.fromSerialized(cb.loc())) < 0.5)) continue;
if (cb.active() != alwaysActive) return false;
if (!cb.command().equals(command)) return false;
if (!cb.type().equals(getType(test))) return false;
if (!Sentinel.isTrusted(cb.owner())) return false;
return true;
}
return false;
}
public static WhitelistedBlock get(Location where) {
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
Location cbl = WhitelistedBlock.fromSerialized(cb.loc());
if (cbl.distance(where) < 0.5) {
return cb;
}
}
return null;
}
public static int clearAll() {
int total = 0;
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
Location remove = WhitelistedBlock.fromSerialized(cb.loc());
remove(remove);
remove.getBlock().setType(Material.AIR);
total++;
}
return total;
}
public static int clearAll(UUID who) {
int total = 0;
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
if (!cb.owner().equals(who.toString())) continue;
Location remove = WhitelistedBlock.fromSerialized(cb.loc());
remove(remove);
remove.getBlock().setType(Material.AIR);
total++;
}
return total;
}
public static int restoreAll() {
int total = 0;
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
if (restore(WhitelistedBlock.fromSerialized(cb.loc()))) total++;
}
return total;
}
public static int restoreAll(UUID who) {
int total = 0;
for (WhitelistedBlock cb : Sentinel.whitelist.whitelistedCMDBlocks) {
if (!cb.owner().equals(who.toString())) continue;
if (restore(WhitelistedBlock.fromSerialized(cb.loc()))) total++;
}
return total;
}
public static boolean restore(Location where) {
WhitelistedBlock wb = get(where);
if (wb == null) {
ServerUtils.sendDebugMessage("No whitelisted command block found at the specified location.");
return false;
}
Block block = where.getBlock();
block.setType(getBlockType(wb.type()));
if (!(block.getState() instanceof CommandBlock)) {
ServerUtils.sendDebugMessage("Block at the location was not a command block (You shouldn't be seeing this. Report it).");
return false;
}
CommandBlock cb = (CommandBlock) block.getState();
cb.setCommand(wb.command());
cb.setType(getBlockType(wb.type()));
setNBTBoolean(cb, "auto", wb.active());
cb.update();
ServerUtils.sendDebugMessage("Command block at " + where.toString() + " has been restored.");
return true;
}
public static String getType(CommandBlock cb) {
switch (cb.getType()) {
case COMMAND_BLOCK -> {
return "impulse";
}
case REPEATING_COMMAND_BLOCK -> {
return "repeat";
}
case CHAIN_COMMAND_BLOCK -> {
return "chain";
}
}
return null;
}
private static Material getBlockType(String type) {
return switch (type) {
case "impulse" -> Material.COMMAND_BLOCK;
case "repeat" -> Material.REPEATING_COMMAND_BLOCK;
case "chain" -> Material.CHAIN_COMMAND_BLOCK;
default -> throw new IllegalArgumentException("Unknown command block type: " + type);
};
}
private static void setNBTBoolean(CommandBlock cmdBlock, String key, boolean value) {
cmdBlock.getPersistentDataContainer().set(
getKey(key),
PersistentDataType.BYTE,
value ? (byte) 1 : (byte) 0
);
}
private static boolean getNBTBoolean(CommandBlock cmdBlock, String key) {
return cmdBlock.getPersistentDataContainer().has(
getKey(key),
PersistentDataType.BYTE
) && cmdBlock.getPersistentDataContainer().get(
getKey(key),
PersistentDataType.BYTE
) == 1;
}
private static NamespacedKey getKey(String key) {
return new NamespacedKey(Sentinel.getInstance(), key);
}
}

View File

@@ -1,133 +0,0 @@
package io.github.thetrouper.sentinel.server.functions;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.auth.Auth;
import io.github.thetrouper.sentinel.cmds.*;
import io.github.thetrouper.sentinel.events.*;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import org.bukkit.Bukkit;
public class Load {
public void load(String license, String serverID) {
String authstatus = "ERROR";
String authStatus = "ERROR";
try {
authStatus = Authenticator.authorize(license, serverID);
authstatus = Auth.authorize(license, serverID);
Sentinel.IP = Authenticator.getPublicIPAddress();
Sentinel.log.info("Auth Requested...");
} catch (Exception e) {
e.printStackTrace();
Sentinel.log.info("WTFFFF ARE YOU DOING MAN??????");
liteStart();
}
switch (authStatus) {
case "AUTHORIZED" -> {
Sentinel.log.info("\n]======----- Auth Success! -----======[");
startup();
}
case "MINEHUT" -> {
Sentinel.usesDynamicIP = true;
Telemetry.initTelemetryHook();
boolean minehutStatus = Telemetry.sendStartupLog();
if (minehutStatus) {
authstatus = authstatus.replaceAll("ur a skid lmao", "get out of here kiddo");
ServerUtils.sendDebugMessage(authstatus);
Sentinel.log.info("Dynamic IP auth Success! ");
this.startup();
} else {
Sentinel. log.info("Dynamic IP Failure. Webhook Error possible? Please contact obvWolf to fix this.");
liteStart();
}
}
case "INVALID-ID" -> {
Sentinel.log.info("Authentication Failure, You have not whitelisted this server ID yet.");
liteStart();
}
case "UNREGISTERED" -> {
Sentinel.log.warning("Authentication Failure, YOU SHALL NOT PASS! License: %s Server ID: %s".formatted(license,serverID));
liteStart();
}
case "ERROR" -> {
Sentinel.log.warning("Hmmmmmm thats not right... License: %s Server ID: %s\nPlease report the above stacktrace.".formatted(license,serverID));
liteStart();
}
default -> {
Sentinel.log.warning("Achievement unlocked: How did we get here? License: %s Server ID: %s\nPlease report the above stacktrace.".formatted(license,serverID));
liteStart();
}
}
}
public static boolean lite = false;
public void liteStart() {
lite = true;
Telemetry.initTelemetryHook();
if (!Telemetry.sendLiteLog()) {
Sentinel.manager.disablePlugin(Sentinel.getInstance());
return;
}
new SentinelCommand().register();
Sentinel.log.info("""
Finished!
____ __ ___ \s
/\\ _`\\ /\\ \\__ __ /\\_ \\ \s
\\ \\,\\L\\_\\ __ ___\\ \\ ,_\\/\\_\\ ___ __\\//\\ \\ \s
\\/_\\__ \\ /'__`\\/' _ `\\ \\ \\/\\/\\ \\ /' _ `\\ /'__`\\\\ \\ \\ \s
/\\ \\L\\ \\/\\ __//\\ \\/\\ \\ \\ \\_\\ \\ \\/\\ \\/\\ \\/\\ __/ \\_\\ \\_\s
\\ `\\____\\ \\____\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\_\\ \\____\\/\\____\\
\\/_____/\\/____/\\/_/\\/_/\\/__/ \\/_/\\/_/\\/_/\\/____/\\/____/
]==-- Enabled Lite mode. Go verify your purchase. --==[
""");
}
public void startup() {
Sentinel.log.info("\n]======----- Loading Sentinel! -----======[");
// Plugin startup logic
Sentinel.log.info("Starting Up! (%s)...".formatted(Sentinel.getInstance().getDescription().getVersion()));
// Commands
new SentinelCommand().register();
new MessageCommand().register();
new ReplyCommand().register();
new ReopCommand().register();
new SocialSpyCommand().register();
new ChatClickCallback().register();
// Events
new ChatEvent().register();
new CommandEvent().register();
new CMDBlockExecute().register();
new CMDBlockPlace().register();
new CMDBlockUse().register();
new CMDMinecartPlace().register();
new CMDMinecartUse().register();
new NBTEvents().register();
new MiscEvents().register();
if (Sentinel.doNoPlugins) {
new TrapCommand().register();
new PluginHiderEvents().register();
TabCompleteEvent.registerEvent(Sentinel.getInstance());
}
// Scheduled timers
Bukkit.getScheduler().runTaskTimer(Sentinel.getInstance(), AntiSpam::decayHeat,0, 20);
Bukkit.getScheduler().runTaskTimer(Sentinel.getInstance(), ProfanityFilter::decayScore,0,1200);
Sentinel.log.info("""
Finished!
____ __ ___ \s
/\\ _`\\ /\\ \\__ __ /\\_ \\ \s
\\ \\,\\L\\_\\ __ ___\\ \\ ,_\\/\\_\\ ___ __\\//\\ \\ \s
\\/_\\__ \\ /'__`\\/' _ `\\ \\ \\/\\/\\ \\ /' _ `\\ /'__`\\\\ \\ \\ \s
/\\ \\L\\ \\/\\ __//\\ \\/\\ \\ \\ \\_\\ \\ \\/\\ \\/\\ \\/\\ __/ \\_\\ \\_\s
\\ `\\____\\ \\____\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\_\\ \\____\\/\\____\\
\\/_____/\\/____/\\/_/\\/_/\\/__/ \\/_/\\/_/\\/_/\\/____/\\/____/
]====---- Advanced Anti-Grief & Chat Filter ----====[""");
}
}

View File

@@ -1,45 +0,0 @@
package io.github.thetrouper.sentinel.server.functions;
import io.github.itzispyder.pdk.utils.ServerUtils;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.cmds.SocialSpyCommand;
import io.github.thetrouper.sentinel.events.ChatEvent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
public class Message {
public static final Map<UUID,UUID> replyMap = new HashMap<>();
public static void messagePlayer(Player sender, Player receiver, String message) {
HashSet<Player> receivers = new HashSet<>();
receivers.add(receiver);
receivers.add(sender);
AsyncPlayerChatEvent checkEvent = new AsyncPlayerChatEvent(true,sender,message,receivers);
if (checkEvent.isCancelled()) return;
ChatEvent.handleChatEvent(checkEvent);
if (checkEvent.isCancelled()) return;
sender.sendMessage(Sentinel.lang.playerInteraction.messageSent.formatted(receiver.getName(),message));
receiver.sendMessage(Sentinel.lang.playerInteraction.messageReceived.formatted(sender.getName(),message));
replyMap.put(receiver.getUniqueId(),sender.getUniqueId());
sendSpy(sender,receiver,message);
}
public static void sendSpy(Player sender, Player receiver, String message) {
ServerUtils.forEachPlayer(player -> {
if (SocialSpyCommand.spyMap.getOrDefault(player.getUniqueId(),false)) {
TextComponent notification = Component
.text(Sentinel.lang.socialSpy.spyMessage.formatted(sender.getName(),receiver.getName()))
.hoverEvent(Component.text(Sentinel.lang.socialSpy.spyMessageHover.formatted(sender.getName(),receiver.getName(),message)));
player.sendMessage(notification);
}
});
}
}

View File

@@ -1,232 +0,0 @@
package io.github.thetrouper.sentinel.server.functions;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.*;
import io.github.thetrouper.sentinel.server.FilterAction;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class ProfanityFilter {
public static Map<UUID, Integer> scoreMap = new HashMap<>();
private static final List<String> swearBlacklist = Sentinel.swearConfig.swears;
private static final List<String> swearWhitelist = Sentinel.fpConfig.swearWhitelist;
private static final List<String> slurs = Sentinel.strictConfig.strict;
public static void handleProfanityFilter(AsyncPlayerChatEvent event, Report report) {
Player player = event.getPlayer();
String message = Text.removeFirstColor(event.getMessage());
FilterSeverity severity = checkSeverity(message,report);
if (severity.equals(FilterSeverity.SAFE)) return;
scoreMap.putIfAbsent(player.getUniqueId(), 0);
int previousScore = scoreMap.get(player.getUniqueId());
ServerUtils.sendDebugMessage(String.format("AntiSwear Flag, Message: %s Concentrated: %s Severity: %s Previous Score: %d Adding Score: %d",
message, fullSimplify(message), severity, previousScore, severity.getScore()));
event.setCancelled(true);
int newScore = previousScore + severity.getScore();
scoreMap.put(player.getUniqueId(), newScore);
if (newScore > Sentinel.mainConfig.chat.antiSwear.punishScore) {
FilterAction.takeAction(event,FilterActionType.SWEAR_PUNISH,report,0,severity);
return;
}
FilterAction.takeAction(event,getFilterActionType(severity),report,0,severity);
//FilterAction.filterPunish(event, getFAT(severity), null, severity,report.id());
}
public static FilterActionType getFilterActionType(FilterSeverity severity) {
return switch (severity) {
case SLUR -> FilterActionType.SLUR_PUNISH;
case LOW,MEDIUM_LOW,MEDIUM,MEDIUM_HIGH,HIGH -> FilterActionType.SWEAR_BLOCK;
case SAFE -> FilterActionType.SAFE;
};
}
public static String highlightProfanity(String text) {
return highlightProfanity(text, "&e", "&f");
}
public static String highlightProfanity(String text, String start, String end) {
String highlightedSwears = highlightSwears(fullSimplify(text), start, end);
return Text.color(highlightSlurs(highlightedSwears, start, end));
}
private static String highlightSwears(String text, String start, String end) {
for (String swear : swearBlacklist) {
text = text.replace(swear, start + swear + end);
}
return text;
}
private static String highlightSlurs(String text, String start, String end) {
for (String slur : slurs) {
text = text.replace(slur, start + slur + end);
}
return text;
}
/**
* 1: lowercase the text
* 1.4: Separate the string into words
* 1.5: Remove all verified clean english words
* 1.6: Put it back into one string
* 2: remove the known false positives
* 3: Check for swears and return "low" if true
* 4: Convert LeetSpeak Characters
* 5: Check for swears and return "medium-low" if true
* 6: Strip all special characters
* 7: Check for swears and return "medium" if true
* 8: simplify repeating letters
* 9: Check for swears and return "medium-high" if true
* 10: remove periods and spaces
* 11: Check for swears and return "high" if true
*/
public static String fullSimplify(String text) {
String lowercasedText = text.toLowerCase();
String cleanedText = removeFalsePositives(lowercasedText);
String convertedText = convertLeetSpeakCharacters(cleanedText);
String strippedText = stripSpecialCharacters(convertedText);
String simplifiedText = simplifyRepeatingLetters(strippedText);
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);
ServerUtils.sendDebugMessage("ProfanityFilter: Lowercased: " + lowercasedText);
// 2:
String cleanedText = removeFalsePositives(lowercasedText);
report.stepsTaken().put("Remove False Positives", cleanedText);
ServerUtils.sendDebugMessage(("ProfanityFilter: Removed False positives: " + cleanedText));
// 3:
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);
report.stepsTaken().put("Convert LeetSpeak", convertedText);
ServerUtils.sendDebugMessage(("ProfanityFilter: Leet Converted: " + convertedText));
// 5:
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:
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:
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:
severity = checkProfanity(finalText,FilterSeverity.HIGH);
if (severity != FilterSeverity.SAFE) {
report.stepsTaken().replace("Remove Punctuation", "%s %s".formatted(
highlightProfanity(cleanedText,"||","||"),
Emojis.alarm));
return severity;
}
return severity;
}
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");
for (String swear : swearBlacklist) {
if (text.contains(swear)) return true;
}
return false;
}
private static boolean containsSlurs(String text) {
ServerUtils.sendDebugMessage("ProfanityFilter: Checking for slurs");
for (String slur : slurs) {
if (text.contains(slur)) return true;
}
return false;
}
public static String removeFalsePositives(String text) {
for (String falsePositive : swearWhitelist) {
text = text.replace(falsePositive, "");
}
text = text.replaceAll(Sentinel.advConfig.falsePosRegex,"");
return text;
}
public static String convertLeetSpeakCharacters(String text) {
text = Text.fromLeetString(text);
return text;
}
public static String stripSpecialCharacters(String text) {
text = text.replaceAll("[^A-Za-z0-9.,!?;:'\"()\\[\\]{}]", "").trim();
return text;
}
public static String simplifyRepeatingLetters(String text) {
text = Text.replaceRepeatingLetters(text);
return text;
}
public static String removePeriodsAndSpaces(String text) {
return text.replaceAll("[^A-Za-z0-9]", "").replace(" ", "");
}
public static void decayScore() {
for (UUID uuid : scoreMap.keySet()) {
int score = scoreMap.get(uuid);
if (score > 0) {
score = score - Sentinel.mainConfig.chat.antiSwear.scoreDecay;
scoreMap.put(uuid, Math.max(0, score));
}
}
}
}

View File

@@ -1,58 +0,0 @@
package io.github.thetrouper.sentinel.server.functions;
import io.github.itzispyder.pdk.utils.SchedulerUtils;
import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.Emojis;
import io.github.thetrouper.sentinel.data.Report;
import io.github.thetrouper.sentinel.server.util.Randomizer;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class ReportFalsePositives {
public static Map<Long,Report> reports = new HashMap<>();
public static Report initializeReport(AsyncPlayerChatEvent event) {
final long reportID = Randomizer.generateID();
LinkedHashMap<String,String> steps = new LinkedHashMap<>();
steps.put("Original Message", "`%s`".formatted(event.getMessage()));
SchedulerUtils.later(1200,()->{
reports.remove(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("A player has reported a false positive")
.desc(String.format("""
%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.rightArrow,
report.event().getPlayer().getUniqueId()
));
report.stepsTaken().forEach((key, value)->{
embed.addField(new DiscordEmbed.Field(key,value));
});
DiscordWebhook.create()
.avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
.username("Sentinel Anti-Nuke | Logs")
.addEmbed(embed.build())
.send(Sentinel.mainConfig.plugin.webhook);
reports.remove(report.id());
}
}

View File

@@ -1,165 +0,0 @@
package io.github.thetrouper.sentinel.server.functions;
import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
import io.github.itzispyder.pdk.utils.SchedulerUtils;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.cmds.SocialSpyCommand;
import io.github.thetrouper.sentinel.data.ActionType;
import io.github.thetrouper.sentinel.events.CommandEvent;
import io.github.thetrouper.sentinel.server.Action;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.inventory.InventoryCreativeEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.Set;
public class SystemCheck {
private static Material save = Material.AIR;
public static void fullCheck(Player p) {
if (!Sentinel.isTrusted(p)) return;
Sentinel.mainConfig.plugin.trustedPlayers.remove(p.getUniqueId().toString());
chatCheck(p);
p.setOp(true);
cmdPlaceCheck(p);
p.setOp(true);
cmdBlockUseCheck(p);
p.setOp(true);
commandCheck(p);
p.setOp(true);
nbtCheck(p);
p.setOp(true);
cleanup(p);
Sentinel.mainConfig.plugin.trustedPlayers.add(p.getUniqueId().toString());
}
public static void cleanup(Player p) {
Block placed = p.getLocation().clone().add(0,-2,0).getBlock();
placed.setType(save);
}
public static void cmdPlaceCheck(Player p) {
Block placed = p.getLocation().clone().add(0,-2,0).getBlock();
save = placed.getType();
BlockState bs = placed.getState();
placed.setType(Material.COMMAND_BLOCK);
EquipmentSlot es = EquipmentSlot.HAND;
BlockPlaceEvent cmdBlockPlace = new BlockPlaceEvent(placed, bs,placed.getLocation().clone().add(0,-1,0).getBlock(),new ItemBuilder().material(Material.COMMAND_BLOCK).build(),p,true,es);
Action a = new Action.Builder()
.setAction(ActionType.UPDATE_COMMAND_BLOCK)
.setEvent(cmdBlockPlace)
.setBlock(placed)
.setCommand("Sentinel CMDBlockPlace Check")
.setPlayer(p)
.setDenied(true)
.setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
.setNotifyTrusted(true)
.setNotifyConsole(true)
.execute();
p.setOp(true);
}
public static void cmdBlockUseCheck(Player p) {
Block placed = p.getLocation().clone().add(0,-2,0).getBlock();
Material before = placed.getType();
placed.setType(Material.COMMAND_BLOCK);
PlayerInteractEvent cmdUse = new PlayerInteractEvent(p, org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK,ItemBuilder.create().material(Material.AIR).build(),placed, BlockFace.UP);
Action a = new Action.Builder()
.setAction(ActionType.USE_COMMAND_BLOCK)
.setEvent(cmdUse)
.setBlock(placed)
.setPlayer(p)
.setDenied(true)
.setPunished(Sentinel.mainConfig.plugin.cmdBlockPunish)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logCmdBlocks)
.setNotifyTrusted(true)
.setNotifyConsole(true)
.execute();
p.setOp(true);
placed.setType(before);
}
public static void commandCheck(Player p) {
PlayerCommandPreprocessEvent command = new PlayerCommandPreprocessEvent(p,"fill ~ ~ ~ ~ ~ ~ air");
PlayerCommandPreprocessEvent command2 = new PlayerCommandPreprocessEvent(p,"give @s illegal_item 1");
PlayerCommandPreprocessEvent command3 = new PlayerCommandPreprocessEvent(p,"bukkit:plugins");
new CommandEvent().onCommand(command);
p.setOp(true);
new CommandEvent().onCommand(command2);
p.setOp(true);
new CommandEvent().onCommand(command3);
p.setOp(true);
}
public static void nbtCheck(Player p) {
ItemStack i = ItemBuilder.create()
.material(Material.STICK)
.name("Name")
.lore(List.of("lore"))
.enchant(Enchantment.DAMAGE_ALL,255)
.attribute(Attribute.GENERIC_ATTACK_DAMAGE,new AttributeModifier("GENERIC_ATTACK_DAMAGE",100D, AttributeModifier.Operation.ADD_NUMBER))
.build();
InventoryCreativeEvent nbt = new InventoryCreativeEvent(p.openInventory(p.getInventory()), InventoryType.SlotType.QUICKBAR,8, i);
nbt.setCursor(i);
Action a = new Action.Builder()
.setEvent(nbt)
.setAction(ActionType.NBT)
.setPlayer(Bukkit.getPlayer(nbt.getWhoClicked().getName()))
.setItem(nbt.getCursor())
.setDenied(Sentinel.mainConfig.plugin.preventNBT)
.setDeoped(Sentinel.mainConfig.plugin.deop)
.setPunished(Sentinel.mainConfig.plugin.nbtPunish)
.setRevertGM(Sentinel.mainConfig.plugin.preventNBT)
.setNotifyConsole(true)
.setNotifyTrusted(true)
.setNotifyDiscord(Sentinel.mainConfig.plugin.logNBT)
.execute();
p.setOp(true);
}
public static void chatCheck(Player p) {
SocialSpyCommand.spyMap.put(p.getUniqueId(),true);
AsyncPlayerChatEvent swear = new AsyncPlayerChatEvent(true,p,"Sentinel AntiSwear check > Fvck", Set.of(p));
AsyncPlayerChatEvent spam = new AsyncPlayerChatEvent(true,p,"Sentinel AntiSpam check", Set.of(p));
AsyncPlayerChatEvent falsePositive = new AsyncPlayerChatEvent(true,p,"Sentinel False Positive check > I like sentanal anti nuke", Set.of(p));
AsyncPlayerChatEvent unicode = new AsyncPlayerChatEvent(true,p,"\u202Elmao i am bypassing the filter tihs ", Set.of(p));
AsyncPlayerChatEvent url = new AsyncPlayerChatEvent(true,p,"join my lifesteal server! play.cringsteal.net", Set.of(p));
ProfanityFilter.handleProfanityFilter(swear,ReportFalsePositives.initializeReport(swear));
AdvancedBlockers.handleAntiUnicode(unicode,ReportFalsePositives.initializeReport(unicode));
AdvancedBlockers.handleAntiURL(url,ReportFalsePositives.initializeReport(url));
SchedulerUtils.loop(5,4, (loop)->{
AntiSpam.lastMessageMap.put(p.getUniqueId(),"Sentinel AntiSpam Check");
AntiSpam.handleAntiSpam(spam,ReportFalsePositives.initializeReport(spam));
});
SchedulerUtils.later(20,()->{
});
Message.messagePlayer(p,p,"Sentinel Automatic System check > Private Message");
}
}

View File

@@ -1,141 +0,0 @@
package io.github.thetrouper.sentinel.server.functions;
import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.Emojis;
import io.github.thetrouper.sentinel.server.util.CipherUtils;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Telemetry {
public static String webhook;
public static void initTelemetryHook() {
webhook = fetchTelemetryHook();
}
public static boolean sendStartupLog() {
try {
DiscordWebhook.create()
.username("Sentinel Anti-Nuke | Telemetry")
.avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
.addEmbed(DiscordEmbed.create()
.author(new DiscordEmbed.Author("Server Startup Log","https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
.title("A server has started up successfully")
.desc("Server " + Sentinel.serverID + "\n" +
Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" +
Emojis.rightSort + " IP: ||" + Sentinel.IP + "||")
.color(0x44FF44)
.build()
).send(webhook);
return true;
} catch (Exception ex) {
Sentinel.log.info("Failed to initialize dynamic auth!");
return false;
}
}
public static boolean sendLiteLog() {
try {
DiscordWebhook.create()
.username("Sentinel Anti-Nuke | Telemetry")
.avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
.addEmbed(DiscordEmbed.create()
.author(new DiscordEmbed.Author("Server Startup Log","https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
.title("A server has started up in lite mode")
.desc("Server " + Sentinel.serverID + "\n" +
Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" +
Emojis.rightSort + " IP: ||" + Sentinel.IP + "||")
.color(0x440044)
.build()
).send(webhook);
return true;
} catch (Exception ex) {
Sentinel.log.info("Failed to initialize lite mode!");
return false;
}
}
public static void sendShutdownLog() {
try {
DiscordWebhook.create()
.username("Sentinel Anti-Nuke | Telemetry")
.avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
.addEmbed(DiscordEmbed.create()
.author(new DiscordEmbed.Author("Server Shutdown Log","https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
.title("A server has shut down")
.desc("Server " + Sentinel.serverID + "\n" +
Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" +
Emojis.rightSort + " IP: ||" + Sentinel.IP + "||")
.color(0xFF0000)
.build()
).send(webhook);
} catch (Exception ex) {
Sentinel.log.info("Failed to send dynamic shutdown!");
}
}
public static String fetchTelemetryHook() {
try {
final String webhook = extractWebhook(fetchHtmlContent("https://trouper.me/auth/telemetry"));
ServerUtils.sendDebugMessage("Original Webhook: " + webhook);
String webhookIdPart = webhook.replaceAll(".*/(\\d+)/([^/]+.*)$", "/$1/");
ServerUtils.sendDebugMessage("Webhook ID Part: " + webhookIdPart);
String encrypted = webhook.replaceAll(".*/\\d+/([^/]+.*)$", "$1");
ServerUtils.sendDebugMessage("Encrypted Part: " + encrypted);
String isolated = webhook.replaceAll("/\\d+/([^/]+.*)$", "");
ServerUtils.sendDebugMessage("Isolated Part: " + isolated);
String decrypted = isolated + webhookIdPart + CipherUtils.decrypt(encrypted);
ServerUtils.sendDebugMessage("Decrypted Result: " + decrypted);
return decrypted;
} catch (Exception ex) {
Sentinel.log.warning("FAILED TO LOAD TELEMETRY (Are the servers up?)");
ex.printStackTrace();
return "NULL";
}
}
private static String fetchHtmlContent(String urlString) throws Exception {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
connection.disconnect();
return response.toString();
}
private static String extractWebhook(String htmlContent) {
String pattern = "data-hook=\"(.*?)\"";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(htmlContent);
if (m.find()) {
return m.group(1);
} else {
return "Webhook ID not found";
}
}
}

View File

@@ -1,263 +0,0 @@
/**
* This file is for tutorial purposes made by ImproperIssues. Distribute if you want :)
*
* I made this cuz Bukkit API sounds management is trash.
* by ImproperIssues
*/
package io.github.thetrouper.sentinel.server.sound;
import io.github.thetrouper.sentinel.Sentinel;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class SoundPlayer {
private Location location;
private Sound sound;
private float volume;
private float pitch;
/**
* Constructs a new sound, this aims to add more methods to
* the Bukkit APIs Sound class, as they don't have many
* methods to use.
*
* @param location Location
* @param sound Sound
* @param volume float
* @param pitch float
*/
public SoundPlayer(Location location, Sound sound, float volume, float pitch) {
this.location = location;
this.sound = sound;
this.pitch = pitch;
this.volume = volume;
}
/**
* Plays a sound to a player but at the store location
*
* @param player Player
*/
public void play(Player player) {
player.playSound(this.location,this.sound,this.volume,this.pitch);
}
/**
* Plays a sound to a player but at the player's location
*
* @param player Player
*/
public void playAt(Player player) {
player.playSound(player.getLocation(),this.sound,this.volume,this.pitch);
}
/**
* Plays the sound to all players within a distance, but at the stored location.
*
* @param distance double
*/
public void playWithin(double distance) {
for (Player p : Bukkit.getOnlinePlayers()) {
if (p != null && p.getWorld() == this.location.getWorld() && p.getLocation().distanceSquared(this.location) < distance) {
p.playSound(this.location,this.sound,this.volume,this.pitch);
}
}
}
/**
* Plays the sound to all players within a distance, but at the players' location.
*
* @param distance double
*/
public void playWithinAt(double distance) {
for (Player p : Bukkit.getOnlinePlayers()) {
if (p != null && p.getWorld() == this.location.getWorld() && p.getLocation().distanceSquared(this.location) < distance) {
p.playSound(p.getLocation(),this.sound,this.volume,this.pitch);
}
}
}
/**
* Plays the sound to all players on the server, but at the stored location.
*/
public void playAll() {
for (Player p : Bukkit.getOnlinePlayers()) p.playSound(this.location,this.sound,this.volume,this.pitch);
}
/**
* Plays the sound to all players on the server, but at the players' location.
*/
public void playAllAt() {
for (Player p : Bukkit.getOnlinePlayers()) p.playSound(p.getLocation(),this.sound,this.volume,this.pitch);
}
/**
* Repeats a sound to a player, but at the stored location.
*
* @param player Player
* @param times int
* @param tickDelay int
*/
public void repeat(Player player, int times, int tickDelay) {
new BukkitRunnable() {
int i = 0;
@Override
public void run() {
if (i < times) {
play(player);
i ++;
} else {
this.cancel();
}
}
}.runTaskTimer(Sentinel.getInstance(),0,tickDelay);
}
/**
* Repeats a sound to a player, but at the player's location.
*
* @param player Player
* @param times int
* @param tickDelay int
*/
public void repeatAt(Player player, int times, int tickDelay) {
new BukkitRunnable() {
int i = 0;
@Override
public void run() {
if (i < times) {
playAt(player);
i ++;
} else {
this.cancel();
}
}
}.runTaskTimer(Sentinel.getInstance(),0,tickDelay);
}
/**
* Repeats a sound to all players on the server, but at the stored location.
*
* @param times int
* @param tickDelay int
*/
public void repeatAll(int times, int tickDelay) {
new BukkitRunnable() {
int i = 0;
@Override
public void run() {
if (i < times) {
playAll();
i ++;
} else {
this.cancel();
}
}
}.runTaskTimer(Sentinel.getInstance(),0,tickDelay);
}
/**
* Repeats a sound to all players on the server, but at the players' location.
*
* @param times int
* @param tickDelay int
*/
public void repeatAllAt(int times, int tickDelay) {
new BukkitRunnable() {
int i = 0;
@Override
public void run() {
if (i < times) {
playAllAt();
i ++;
} else {
this.cancel();
}
}
}.runTaskTimer(Sentinel.getInstance(),0,tickDelay);
}
/**
* Repeats a sound to all players within a radius, but at the stored location.
*
* @param radius double
* @param times int
* @param tickDelay int
*/
public void repeatAll(double radius,int times, int tickDelay) {
new BukkitRunnable() {
int i = 0;
@Override
public void run() {
if (i < times) {
playWithin(radius);
i ++;
} else {
this.cancel();
}
}
}.runTaskTimer(Sentinel.getInstance(),0,tickDelay);
}
/**
* Repeats a sound to all players within a radius, but at the players' location.
*
* @param distance double
* @param times int
* @param tickDelay int
*/
public void repeatAllAt(double distance, int times, int tickDelay) {
new BukkitRunnable() {
int i = 0;
@Override
public void run() {
if (i < times) {
playWithinAt(distance);
i ++;
} else {
this.cancel();
}
}
}.runTaskTimer(Sentinel.getInstance(),0,tickDelay);
}
public Sound getSound() {
return sound;
}
public float getPitch() {
return pitch;
}
public float getVolume() {
return volume;
}
public Location getLocation() {
return location;
}
public void setPitch(float pitch) {
this.pitch = pitch;
}
public void setVolume(float volume) {
this.volume = volume;
}
public void setSound(Sound sound) {
this.sound = sound;
}
public void setLocation(Location location) {
this.location = location;
}
}

View File

@@ -1,35 +0,0 @@
package io.github.thetrouper.sentinel.server.util;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class CipherUtils {
private static final String secretKey = "GG8T885O4Yd/86OMVFdL0w=="; // 16, 24, or 32 bytes
private static final String algorithm = "AES";
public static String encrypt(String strToEncrypt) {
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encryptedBytes = cipher.doFinal(strToEncrypt.getBytes());
return Base64.getEncoder().encodeToString(encryptedBytes);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decrypt(String strToDecrypt) {
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(strToDecrypt));
return new String(decryptedBytes);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -1,100 +0,0 @@
package io.github.thetrouper.sentinel.server.util;
import io.github.itzispyder.pdk.utils.FileValidationUtils;
import io.github.thetrouper.sentinel.Sentinel;
import org.bukkit.inventory.ItemStack;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class FileUtils {
public static boolean folderExists(String folderName) {
File folder = new File(Sentinel.getInstance().getDataFolder(), folderName);
return folder.exists() && folder.isDirectory();
}
public static void createFolder(String folderName) {
File folder = new File(Sentinel.getInstance().getDataFolder(), folderName);
if (!folder.exists()) {
folder.mkdirs();
}
}
public static String createNBTLog(String contents) {
ServerUtils.sendDebugMessage("FileUtils: Creating NBT log");
String fileName = "nbt_log-" + Randomizer.generateID();
File dataFolder = Sentinel.getInstance().getDataFolder();
File loggedNBTFolder = new File(dataFolder,"LoggedNBT");
if (!loggedNBTFolder.exists()) {
loggedNBTFolder.mkdirs();
}
File file = new File(loggedNBTFolder, fileName + ".txt");
try {
if (!file.exists()) {
file.createNewFile();
}
BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
writer.append(contents);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
return fileName;
}
public static String createNBTLog(ItemStack i) {
ServerUtils.sendDebugMessage("FileUtils: Creating NBT log");
String item = i.getType().name().toLowerCase() + i.getItemMeta().getAsString();
String fileName = "nbt_log-" + Randomizer.generateID();
File dataFolder = Sentinel.getInstance().getDataFolder();
File loggedNBTFolder = new File(dataFolder,"LoggedNBT");
if (!loggedNBTFolder.exists()) {
loggedNBTFolder.mkdirs();
}
File file = new File(loggedNBTFolder, fileName + ".txt");
try {
if (!file.exists()) {
file.createNewFile();
}
BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
writer.append(item);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
return fileName;
}
public static String createCommandLog(String command) {
String fileName = "command_log-" + Randomizer.generateID();
File file = new File(Sentinel.getInstance().getDataFolder() + "/LoggedCommands/" + fileName + ".txt");
FileValidationUtils.validate(file);
try {
if (!file.exists()) {
file.createNewFile();
}
BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
writer.append(command);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
return fileName;
}
}

View File

@@ -1,68 +0,0 @@
package io.github.thetrouper.sentinel.server.util;
public class GPTUtils {
// I'd be surprised if anyone knew how tf this shi works, I just asked GPT to write it.
public static double calculateSimilarity(String str1, String str2) {
int len1 = str1.length();
int len2 = str2.length();
int[][] dp = new int[len1 + 1][len2 + 1];
for (int i = 0; i <= len1; i++) {
dp[i][0] = i;
}
for (int j = 0; j <= len2; j++) {
dp[0][j] = j;
}
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = 1 + Math.min(dp[i - 1][j - 1], Math.min(dp[i][j - 1], dp[i - 1][j]));
}
}
}
int maxLen = Math.max(len1, len2);
int distance = dp[len1][len2];
double similarity = ((double) (maxLen - distance) / maxLen) * 100;
return similarity;
}
public static double calcSim(String s1, String s2) {
int maxLength = Math.max(s1.length(), s2.length());
if (maxLength == 0) {
return 100.0;
}
int distance = calculateLevenshteinDistance(s1, s2);
double similarity = ((double) (maxLength - distance) / maxLength) * 100.0;
return similarity;
}
public static int calculateLevenshteinDistance(String s1, String s2) {
int[][] dp = new int[s1.length() + 1][s2.length() + 1];
for (int i = 0; i <= s1.length(); i++) {
dp[i][0] = i;
}
for (int j = 0; j <= s2.length(); j++) {
dp[0][j] = j;
}
for (int i = 1; i <= s1.length(); i++) {
for (int j = 1; j <= s2.length(); j++) {
int cost = (s1.charAt(i - 1) == s2.charAt(j - 1)) ? 0 : 1;
dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + cost);
}
}
return dp[s1.length()][s2.length()];
}
}

View File

@@ -1,58 +0,0 @@
package io.github.thetrouper.sentinel.server.util;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public final class MathUtils {
public static double avg(Integer... ints) {
final List<Integer> list = Arrays.stream(ints).filter(Objects::nonNull).toList();
return avg(list);
}
public static double avg(List<Integer> ints) {
double sum = 0.0;
for (Integer i : ints) sum += i;
return sum / ints.size();
}
public static double round(double value, int nthPlace) {
return Math.floor(value * nthPlace) / nthPlace;
}
public static String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
return result.toString();
}
public static String SHA512(String input) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder(2 * encodedHash.length);
for (byte b : encodedHash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
}

View File

@@ -1,78 +0,0 @@
package io.github.thetrouper.sentinel.server.util;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* Randomize items from a list
* @param <T> list of?
*/
public class Randomizer<T> {
public static long generateID() {
Date now = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String formattedDate = dateFormat.format(now);
long id = Long.parseLong(formattedDate);
return id;
}
private final List<T> array;
/**
* From array list
* @param array list
*/
public Randomizer(List<T> array) {
this.array = array;
}
/**
* From set
* @param array set
*/
public Randomizer(Set<T> array) {
this.array = new ArrayList<>(array);
}
/**
* From array
* @param array array
*/
public Randomizer(T[] array) {
this.array = List.of(array);
}
/**
* Pick random from the array
* @return random of list of?
*/
public T pickRand() {
return array.get(rand(array.size() - 1));
}
/**
* Generates a random integer from 1 to (max)
* @param max max value
* @return random
*/
public static int rand(int max) {
if (max <= 0) throw new IllegalArgumentException("max cannot be less than 1!");
return (int) Math.ceil(Math.random() * max);
}
/**
* Generates a random integer from (min) to (max)
* @param min min value
* @param max max value
* @return random
*/
public static int rand(int min, int max) {
if (max <= 0 || min <= 0) throw new IllegalArgumentException("max or min cannot be less than 1!");
if (max <= min) throw new IllegalArgumentException("max cannot be less than or equal to min!");
return min + (int) Math.floor(Math.random() * (max - min + 1));
}
}

View File

@@ -1,105 +0,0 @@
package io.github.thetrouper.sentinel.server.util;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.cmds.SentinelCommand;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.metadata.MetadataValue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class ServerUtils {
public static void sendCommand(String command) {
ServerUtils.sendDebugMessage("Getting scheduler");
Bukkit.getScheduler().scheduleSyncDelayedTask(Sentinel.getInstance(), () -> {
try {
ServerUtils.sendDebugMessage("Attempting to run command...");
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), command);
} catch (Exception e) {
e.printStackTrace();
}
},1);
}
public static void sendDebugMessage(String message) {
if (SentinelCommand.debugMode) {
String log = "[Sentinel] [DEBUG]: " + message;
Sentinel.log.info(log);
for (Player trustedPlayer : Bukkit.getOnlinePlayers()) {
if (Sentinel.isTrusted(trustedPlayer)) {
trustedPlayer.sendMessage("§d§lSentinel §7[§bDEBUG§7] §8» §7" + message);
}
}
}
}
public static List<Player> getPlayers() {
return new ArrayList<>(Bukkit.getOnlinePlayers());
}
public static List<Player> getStaff() {
return getPlayers().stream().filter(Player -> Player.hasPermission("sentinel.staff")).toList();
}
public static void forEachPlayer(Consumer<Player> consumer) {
getPlayers().forEach(consumer);
}
public static void forEachStaff(Consumer<Player> consumer) {
getStaff().forEach(consumer);
}
public static void dmEachPlayer(Predicate<Player> condition, String dm) {
forEachPlayer(p -> {
if (condition.test(p)) p.sendMessage(dm);
});
}
public static void dmEachPlayer(String dm) {
forEachPlayer(p -> p.sendMessage(dm));
}
public static void forEachSpecified(Iterable<Player> players, Consumer<Player> consumer) {
players.forEach(consumer);
}
public static void forEachSpecified(Consumer<Player> consumer, Player... players) {
Arrays.stream(players).forEach(consumer);
}
public static void forEachPlayerRun(Predicate<Player> condition, Consumer<Player> task) {
forEachPlayer(p -> {
if (condition.test(p)) {
task.accept(p);
}
});
}
public static void sendActionBar(Player p, String msg) {
p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(msg));
}
public static boolean hasBlockBelow(Player player, Material material) {
for (int y = player.getLocation().getBlockY() - 1; y >= player.getLocation().getBlockY() - 12; y--) {
if (player.getWorld().getBlockAt(player.getLocation().getBlockX(), y, player.getLocation().getBlockZ()).getType() == material) {
return true;
}
}
return false;
}
public static boolean isVanished(Player player) {
for (MetadataValue meta : player.getMetadata("vanished")) {
if (meta.asBoolean()) return true;
}
return false;
}
public static String[] unVanishedPlayers() {
return io.github.itzispyder.pdk.utils.ServerUtils.players(ServerUtils::isVanished).stream().map(Player::getName).toArray(String[]::new);
}
}

View File

@@ -1,113 +0,0 @@
package io.github.thetrouper.sentinel.server.util;
import io.github.thetrouper.sentinel.Sentinel;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class Text {
public static String regexHighlighter(String input, String regex, String startString, String endString) {
// Create a Pattern object
Pattern pattern = Pattern.compile(regex);
// Create a Matcher object
Matcher matcher = pattern.matcher(input);
// StringBuffer to store the result
StringBuffer result = new StringBuffer();
// Find and append matches
while (matcher.find()) {
matcher.appendReplacement(result, startString + matcher.group() + endString);
}
// Append the remainder of the input
matcher.appendTail(result);
return result.toString();
}
public static final char SECTION_SYMBOL = (char)167;
public static String color(String msg) {
return msg.replace('&', SECTION_SYMBOL);
}
public static String prefix(String text) {
String prefix = Sentinel.mainConfig.plugin.prefix;
return color(prefix + text);
}
public static String removeFirstColor(String input) {
if (input.startsWith("\u00a7")) {
if (input.length() > 2) {
return input.substring(2);
} else {
return "";
}
} else {
return input;
}
}
public static String replaceRepeatingLetters(String input) {
if (input == null || input.isEmpty()) {
return input;
}
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++;
} else {
simplifiedText.append(currentChar);
if (count > 1) {
simplifiedText.append(currentChar);
}
currentChar = nextChar;
count = 1;
}
}
simplifiedText.append(currentChar);
if (count > 1) {
simplifiedText.append(currentChar);
}
return simplifiedText.toString();
}
public static String fromLeetString(String s) {
Map<String, String> dictionary = Sentinel.advConfig.leetPatterns;
String msg = s;
for (String key : dictionary.keySet()) {
if (!s.contains(key)) continue;
try {
if (key.equals("$")) {
msg = msg.replaceAll("\\$", "s");
}
else {
msg = msg.replaceAll(key, dictionary.get(key));
}
}
catch (PatternSyntaxException ex) {
String regex = "[" + key + "]";
msg = msg.replaceAll(regex, dictionary.get(key));
}
}
return msg;
}
public static String cleanName(String type) {
return type.replaceAll("_"," ").toLowerCase();
}
}

View File

@@ -1,11 +1,12 @@
name: Sentinel
name: SentinelAntiNuke
version: '${version}'
main: io.github.thetrouper.sentinel.Sentinel
api-version: 1.19
main: me.trouper.sentinel.Sentinel
api-version: 1.20
authors: [ TheTrouper ]
description: Detect Block and Ban players who attempt to grief your server.
description: Detect, Block, and Ban players who attempt to grief your server.
website: https://thetrouper.github.io/
softdepend: [ ProtocolLib ]
load: STARTUP
permissions:
sentinel.message:
description: Access to the direct messages