New ServerID system finished, filteraction has a string formatting bug.

This commit is contained in:
obvWolf
2024-02-01 07:20:48 -06:00
parent 90871100f9
commit d6bebef07c
8 changed files with 191 additions and 148 deletions

View File

@@ -29,9 +29,8 @@ repositories {
dependencies {
compileOnly 'org.spigotmc:spigot-api:1.20.4-R0.1-SNAPSHOT'
implementation 'com.google.code.gson:gson:2.10.1'
implementation("club.minnced:discord-webhooks:0.8.4")
implementation 'club.minnced:discord-webhooks:0.8.4'
implementation files("libs/PDK-1.3.3.jar")
}
def targetJavaVersion = 16

View File

@@ -2,9 +2,6 @@ package io.github.thetrouper.sentinel;
import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.WebhookClientBuilder;
import club.minnced.discord.webhook.send.WebhookEmbed;
import club.minnced.discord.webhook.send.WebhookEmbedBuilder;
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
import io.github.itzispyder.pdk.PDK;
import io.github.itzispyder.pdk.utils.misc.JsonSerializable;
import io.github.thetrouper.sentinel.auth.Auth;
@@ -21,7 +18,6 @@ import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.time.temporal.TemporalAccessor;
import java.util.logging.Logger;
public final class Sentinel extends JavaPlugin {
@@ -46,6 +42,9 @@ public final class Sentinel extends JavaPlugin {
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 WebhookClient webclient;
/**
@@ -65,9 +64,9 @@ public final class Sentinel extends JavaPlugin {
log.info("Language Status: (" + language.get("if-you-see-this-lang-is-broken") + ")");
log.info("Initializing Server ID...");
String serverID = Authenticator.getServerID();
serverID = Authenticator.getServerID();
String license = mainConfig.plugin.license;
license = mainConfig.plugin.license;
log.info("Pre-load finished!\n]====---- Requesting Authentication ----====[ \n- License Key: " + license + " \n- Server ID: " + serverID);
log.info("Auth Requested...");
@@ -76,7 +75,7 @@ public final class Sentinel extends JavaPlugin {
try {
authStatus = Authenticator.authorize(license, serverID);
authstatus = Auth.authorize(license, serverID);
IP = Authenticator.getPublicIPAddress();
} catch (Exception e) {
e.printStackTrace();
log.info("WTFFFF ARE YOU DOING MAN??????");
@@ -89,19 +88,17 @@ public final class Sentinel extends JavaPlugin {
}
case "MINEHUT" -> {
usesDynamicIP = true;
String minehutStatus = Telemetry.loadTelemetryHook(serverID, license);
switch (minehutStatus) {
case "SUCCESS" -> {
Telemetry.initTelemetryHook();
boolean minehutStatus = Telemetry.sendStartupLog();
if (minehutStatus) {
authstatus = authstatus.replaceAll("ur a skid lmao", "get out of here kiddo");
log.info("Dynamic IP auth Success! " + authstatus);
startup();
}
case "FAILURE" -> {
} else {
log.info("Dynamic IP Failure. Webhook Error possible? Please contact obvWolf to fix this.");
manager.disablePlugin(this);
}
}
}
case "INVALID-ID" -> {
log.info("Authentication Failure, You have not whitelisted this server ID yet.");
manager.disablePlugin(this);
@@ -214,7 +211,7 @@ public final class Sentinel extends JavaPlugin {
// Plugin shutdown logic
log.info("Sentinel has disabled! (" + getDescription().getVersion() + ") Your server is now no longer protected!");
if (usesDynamicIP) {
Telemetry.sendShutdownLog(Authenticator.getServerID(), mainConfig.plugin.license);
Telemetry.sendShutdownLog();
}
}

View File

@@ -20,7 +20,7 @@ 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 virus investigation, and have malicious intentions such as cracking, leaking, or ratting this plugin.";
"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 rat checking, and have malicious intentions such as cracking, leaking, or ratting this plugin.";
private
static
final

View File

@@ -7,12 +7,18 @@ 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.ProfanityFilter;
import io.github.thetrouper.sentinel.server.functions.Telemetry;
import io.github.thetrouper.sentinel.server.util.CipherUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.awt.*;
import java.util.HashSet;
@CommandRegistry(value = "sentinel",permission = @Permission("sentinel.debug"))
public class SentinelCommand implements CustomCommand {
@@ -51,6 +57,20 @@ public class SentinelCommand implements CustomCommand {
debugMode = !debugMode;
p.sendMessage(Text.prefix((debugMode ? "Enabled" : "Disabled") + " debug mode."));
}
case "encrypt" -> {
final String enc = CipherUtils.encrypt(args.getAll(2).toString());
final String check = CipherUtils.decrypt(enc);
final String main = Text.prefix("Successfully encrypted \"&e" + check + "&7\" using AES.\n &7> &b" + enc);
Sentinel.log.info(args.getAll(2).toString() + "\n" + enc + "\n" + check);
TextComponent message = new TextComponent();
message.setText(main);
message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new net.md_5.bungee.api.chat.hover.content.Text("&bClick to copy!")));
message.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, enc));
p.spigot().sendMessage(message);
}
case "tele" -> {
p.sendMessage(Telemetry.fetchTelemetryHook());
}
}
}
case "getHeat" -> {

View File

@@ -122,7 +122,7 @@ public class FilterAction {
description.append("%1$sPlayer: `%2$s` %3$s".formatted(Emojis.rightSort,offender.getName(),Emojis.target));
switch (type) {
case SPAM_PUNISH -> {
description.append("%1$s%2$sHeat: `%3$s/%4$s`".formatted(
description.append("\n%1$s%2$sHeat: `%3$s/%4$s`".formatted(
Emojis.space,
Emojis.arrowRight,
heatMap.get(offender),
@@ -135,7 +135,7 @@ public class FilterAction {
currentValue = e.getMessage();
}
case SWEAR_PUNISH -> {
description.append("%1$s%2$sScore: `%3$s/%4$s`".formatted(
description.append("\n%1$s%2$sScore: `%3$s/%4$s`".formatted(
Emojis.space,
Emojis.arrowRight,
scoreMap.get(offender),
@@ -158,7 +158,7 @@ public class FilterAction {
.setDescription(String.valueOf(description))
.addField(new WebhookEmbed.EmbedField(true,historyTitle,historyValue))
.addField(new WebhookEmbed.EmbedField(true,currentTitle,currentValue))
.addField(new WebhookEmbed.EmbedField(false,"Executed: ", executed))
.addField(new WebhookEmbed.EmbedField(false,"Executed: ", executed.replaceAll("%player%",offender.getName())))
.setThumbnailUrl("https://crafatar.com/avatars/" + offender.getUniqueId() + "?size=64&&overlay")
.setColor(type.getColor().getRGB())
.build())

View File

@@ -23,8 +23,8 @@ public class Authenticator {
public static String getServerID() {
try {
return MathUtils.SHA512(getPublicIPAddress());
} catch (IOException e) {
return e.getMessage();
} catch (Exception e) {
return "NULL";
}
}

View File

@@ -1,145 +1,137 @@
package io.github.thetrouper.sentinel.server.functions;
import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.WebhookClientBuilder;
import club.minnced.discord.webhook.send.WebhookEmbed;
import club.minnced.discord.webhook.send.WebhookEmbedBuilder;
import club.minnced.discord.webhook.send.WebhookMessage;
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.discord.DiscordWebhook;
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.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Telemetry {
public Telemetry() throws UnknownHostException {
public static WebhookClient telemetryHook;
public static void initTelemetryHook() {
WebhookClientBuilder builder = new WebhookClientBuilder(fetchTelemetryHook());
builder.setThreadFactory((job) -> {
Thread thread = new Thread(job);
thread.setName("WebhookThread");
thread.setDaemon(true);
return thread;
});
builder.setWait(true);
telemetryHook = builder.build();
}
static InetAddress IP;
static {
public static boolean sendStartupLog() {
WebhookMessage embed = new WebhookMessageBuilder()
.setUsername("Sentinel Anti-Nuke | Telemetry")
.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png").
addEmbeds(new WebhookEmbedBuilder()
.setAuthor(new WebhookEmbed.EmbedAuthor("Server Startup Log",null,"https://builtbybit.com/resources/sentinel-anti-nuke.30130/"))
.setTitle(new WebhookEmbed.EmbedTitle("A server has started up successfully",null))
.setDescription("Server " + Sentinel.serverID + "\n" +
Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" +
Emojis.rightSort + " IP: ||" + Sentinel.IP + "||")
.setColor(Color.GREEN.getRGB())
.build())
.build();
try {
IP = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
public static String telemetryHook;
public static String loadTelemetryHook(String serverID, String licenseKey) {
String hook = "";
try {
URL url = new URL("https://sentinelauth.000webhostapp.com/telemetrykey.html");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
List<String> lines = readLines(reader);
for (String line : lines) {
if (line.contains("data-id")) {
hook = extractValue(line, "data-hook");
telemetryHook = hook;
Map<String,String> response = sendStartupLog(serverID,licenseKey);
if (response.containsKey("SUCCESS")) {
Sentinel.log.info("Successfully grabbed telemetry hook");
return "SUCCESS";
} else {
Sentinel.log.info("An Error occurred while attempting to connect to the telemetry hook: " + response.get("ERROR"));
return "FAIL";
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return "ERROR";
}
public static Map<String, String> testWebhook(String hook) {
Map<String, String> response = new HashMap<>();
response.put("SUCCESS", "NULL");
DiscordWebhook webhook = new DiscordWebhook(hook);
DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject()
.setAuthor("Test Success!", "", "")
.setDescription("Connected to webhook")
.setColor(Color.GREEN);
webhook.addEmbed(embed);
try {
webhook.execute();
} catch (IOException e) {
response.clear();
response.put("ERROR", e.toString());
return response;
}
return response;
}
public static List<String> readLines(BufferedReader reader) {
try {
List<String> lines = new ArrayList<>();
String line = reader.readLine();
while (line != null) {
lines.add(line);
line = reader.readLine();
}
reader.close();
return lines;
telemetryHook.send(embed);
return true;
} catch (Exception ex) {
Sentinel.log.info("Failed to initialize dynamic auth!");
return false;
}
}
public static boolean sendShutdownLog() {
WebhookMessage embed = new WebhookMessageBuilder()
.setUsername("Sentinel Anti-Nuke | Telemetry")
.setAvatarUrl("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png").
addEmbeds(new WebhookEmbedBuilder()
.setAuthor(new WebhookEmbed.EmbedAuthor("Server Shutdown Log",null,"https://builtbybit.com/resources/sentinel-anti-nuke.30130/"))
.setTitle(new WebhookEmbed.EmbedTitle("A server has shut down successfully",null))
.setDescription("Server " + Sentinel.serverID + "\n" +
Emojis.rightSort + " License: ||" + Sentinel.license + "||\n" +
Emojis.rightSort + " IP: ||" + Sentinel.IP + "||")
.setColor(Color.RED.getRGB())
.build())
.build();
try {
telemetryHook.send(embed);
return true;
} catch (Exception ex) {
Sentinel.log.info("Failed to send dynamic shutdown!");
return false;
}
}
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";
}
return new ArrayList<>();
}
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);
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);
}
public static Map<String, String> sendStartupLog(String serverID, String licenseKey) {
Map<String, String> response = new HashMap<>();
response.put("SUCCESS", "NULL");
DiscordWebhook webhook = new DiscordWebhook(telemetryHook);
DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject()
.setAuthor("Server Startup Log", "", "")
.setTitle("Dynamic IP server connected")
.setDescription("License key: `"+ licenseKey + "`\\n" +
"Server ID: `" + serverID + "`")
.setColor(Color.GREEN);
webhook.addEmbed(embed);
try {
webhook.execute();
} catch (IOException e) {
response.clear();
response.put("ERROR", e.toString());
return response;
reader.close();
connection.disconnect();
return response.toString();
}
return response;
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";
}
}
}
public static Map<String, String> sendShutdownLog(String serverID, String licenseKey) {
Map<String, String> response = new HashMap<>();
response.put("SUCCESS", "NULL");
DiscordWebhook webhook = new DiscordWebhook(telemetryHook);
DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject()
.setAuthor("Server Shutdown Log", "", "")
.setTitle("Dynamic IP server disconnected")
.setDescription("License key: `"+ licenseKey + "`\\n" +
"Server ID: `" + serverID + "`")
.setColor(Color.RED);
webhook.addEmbed(embed);
try {
webhook.execute();
} catch (IOException e) {
response.clear();
response.put("ERROR", e.toString());
return response;
}
return response;
}
}

View File

@@ -0,0 +1,35 @@
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;
}
}