diff --git a/src/main/java/net/viper/status/modules/network/NetworkInfoModule.java b/src/main/java/net/viper/status/modules/network/NetworkInfoModule.java index 1d9cf73..27a4199 100644 --- a/src/main/java/net/viper/status/modules/network/NetworkInfoModule.java +++ b/src/main/java/net/viper/status/modules/network/NetworkInfoModule.java @@ -84,60 +84,86 @@ public class NetworkInfoModule implements Module { if (webhookEnabled && !webhookUrl.isEmpty()) { if (webhookNotifyStartStop) { - if (isCompactEmbedMode()) { - sendWebhookEmbed( - webhookUrl, - "✅ NetworkInfo gestartet", - "Proxy: **" + ProxyServer.getInstance().getName() + "**\nÜberwachung und Webhook-Alerts sind jetzt aktiv.", - 0x2ECC71 - ); - } else { - StringBuilder fields = new StringBuilder(); - appendEmbedField(fields, "Proxy", ProxyServer.getInstance().getName(), true); - appendEmbedField(fields, "Modus", "Detailed", true); - appendEmbedField(fields, "Check-Intervall", Math.max(10, webhookCheckSeconds) + "s", true); - sendWebhookEmbed( - webhookUrl, - "✅ NetworkInfo gestartet", - "Überwachung und Webhook-Alerts sind jetzt aktiv.", - 0x2ECC71, - fields.toString() - ); + boolean delivered = sendLifecycleStartNotification(); + if (!delivered) { + plugin.getLogger().warning("[NetworkInfoModule] Start-Webhook konnte nicht direkt zugestellt werden. Wiederhole in 10 Sekunden."); + ProxyServer.getInstance().getScheduler().schedule(plugin, () -> { + boolean retryDelivered = sendLifecycleStartNotification(); + if (!retryDelivered) { + plugin.getLogger().warning("[NetworkInfoModule] Start-Webhook auch beim zweiten Versuch fehlgeschlagen."); + } + }, 10L, TimeUnit.SECONDS); } } int interval = Math.max(10, webhookCheckSeconds); ProxyServer.getInstance().getScheduler().schedule(plugin, this::evaluateAndSendAlerts, interval, interval, TimeUnit.SECONDS); } - plugin.getLogger().info("[NetworkInfoModule] aktiviert. commandEnabled=" + commandEnabled + ", includePlayerNames=" + includePlayerNames); + plugin.getLogger().info("[NetworkInfoModule] aktiviert. commandEnabled=" + commandEnabled + ", includePlayerNames=" + includePlayerNames + ", webhookEnabled=" + webhookEnabled + ", notifyStartStop=" + webhookNotifyStartStop + ", webhookUrlPresent=" + !webhookUrl.isEmpty()); } @Override public void onDisable(Plugin plugin) { if (enabled && webhookEnabled && webhookNotifyStartStop && webhookUrl != null && !webhookUrl.isEmpty()) { - if (isCompactEmbedMode()) { - sendWebhookEmbed( - webhookUrl, - "🛑 NetworkInfo gestoppt", - "Die NetworkInfo-Überwachung wurde gestoppt.\nKeine weiteren Auto-Alerts bis zum nächsten Start.", - 0xE74C3C - ); - } else { - StringBuilder fields = new StringBuilder(); - appendEmbedField(fields, "Proxy", ProxyServer.getInstance().getName(), true); - appendEmbedField(fields, "Modus", "Detailed", true); - appendEmbedField(fields, "Status", "Monitoring pausiert", false); - sendWebhookEmbed( - webhookUrl, - "🛑 NetworkInfo gestoppt", - "Die NetworkInfo-Überwachung wurde gestoppt.", - 0xE74C3C, - fields.toString() - ); + boolean delivered = sendLifecycleStopNotification(); + if (!delivered) { + plugin.getLogger().warning("[NetworkInfoModule] Stop-Webhook konnte nicht zugestellt werden."); } } } + private boolean sendLifecycleStartNotification() { + if (isCompactEmbedMode()) { + return sendWebhookEmbed( + webhookUrl, + "✅ NetworkInfo gestartet", + "Proxy: **" + ProxyServer.getInstance().getName() + "**\nÜberwachung und Webhook-Alerts sind jetzt aktiv.", + 0x2ECC71, + null, + false + ); + } + + StringBuilder fields = new StringBuilder(); + appendEmbedField(fields, "Proxy", ProxyServer.getInstance().getName(), true); + appendEmbedField(fields, "Modus", "Detailed", true); + appendEmbedField(fields, "Check-Intervall", Math.max(10, webhookCheckSeconds) + "s", true); + return sendWebhookEmbed( + webhookUrl, + "✅ NetworkInfo gestartet", + "Überwachung und Webhook-Alerts sind jetzt aktiv.", + 0x2ECC71, + fields.toString(), + false + ); + } + + private boolean sendLifecycleStopNotification() { + if (isCompactEmbedMode()) { + return sendWebhookEmbed( + webhookUrl, + "🛑 NetworkInfo gestoppt", + "Die NetworkInfo-Überwachung wurde gestoppt.\nKeine weiteren Auto-Alerts bis zum nächsten Start.", + 0xE74C3C, + null, + false + ); + } + + StringBuilder fields = new StringBuilder(); + appendEmbedField(fields, "Proxy", ProxyServer.getInstance().getName(), true); + appendEmbedField(fields, "Modus", "Detailed", true); + appendEmbedField(fields, "Status", "Monitoring pausiert", false); + return sendWebhookEmbed( + webhookUrl, + "🛑 NetworkInfo gestoppt", + "Die NetworkInfo-Überwachung wurde gestoppt.", + 0xE74C3C, + fields.toString(), + false + ); + } + public boolean isEnabled() { return enabled; } @@ -546,13 +572,17 @@ public class NetworkInfoModule implements Module { } } - private void sendWebhookEmbed(String targetWebhookUrl, String title, String description, int color) { - sendWebhookEmbed(targetWebhookUrl, title, description, color, null); + private boolean sendWebhookEmbed(String targetWebhookUrl, String title, String description, int color) { + return sendWebhookEmbed(targetWebhookUrl, title, description, color, null, true); } - private void sendWebhookEmbed(String targetWebhookUrl, String title, String description, int color, String fieldsJson) { + private boolean sendWebhookEmbed(String targetWebhookUrl, String title, String description, int color, String fieldsJson) { + return sendWebhookEmbed(targetWebhookUrl, title, description, color, fieldsJson, true); + } + + private boolean sendWebhookEmbed(String targetWebhookUrl, String title, String description, int color, String fieldsJson, boolean async) { if (targetWebhookUrl == null || targetWebhookUrl.isEmpty()) { - return; + return false; } StringBuilder embed = new StringBuilder(); @@ -573,7 +603,7 @@ public class NetworkInfoModule implements Module { } embed.append("}]}"); - postWebhookPayload(targetWebhookUrl, embed.toString()); + return postWebhookPayload(targetWebhookUrl, embed.toString(), async); } private void sendWebhookAttackEmbed(String targetWebhookUrl, @@ -599,7 +629,7 @@ public class NetworkInfoModule implements Module { } embed.append("}]}"); - postWebhookPayload(targetWebhookUrl, embed.toString()); + postWebhookPayload(targetWebhookUrl, embed.toString(), true); } private void appendEmbedField(StringBuilder out, String name, String value, boolean inline) { @@ -615,36 +645,65 @@ public class NetworkInfoModule implements Module { .append("}"); } - private void postWebhookPayload(String targetWebhookUrl, String payload) { - ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> { - HttpURLConnection conn = null; - try { - byte[] bytes = payload.getBytes(StandardCharsets.UTF_8); + private boolean postWebhookPayload(String targetWebhookUrl, String payload, boolean async) { + if (async) { + ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> executeWebhookPost(targetWebhookUrl, payload)); + return true; + } + return executeWebhookPost(targetWebhookUrl, payload); + } - conn = (HttpURLConnection) new URL(targetWebhookUrl).openConnection(); - conn.setRequestMethod("POST"); - conn.setConnectTimeout(5000); - conn.setReadTimeout(8000); - conn.setDoOutput(true); - conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); - conn.setRequestProperty("Content-Length", String.valueOf(bytes.length)); + private boolean executeWebhookPost(String targetWebhookUrl, String payload) { + HttpURLConnection conn = null; + try { + byte[] bytes = payload.getBytes(StandardCharsets.UTF_8); - try (OutputStream os = conn.getOutputStream()) { - os.write(bytes); - } + conn = (HttpURLConnection) new URL(targetWebhookUrl).openConnection(); + conn.setRequestMethod("POST"); + conn.setConnectTimeout(5000); + conn.setReadTimeout(8000); + conn.setDoOutput(true); + conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); + conn.setRequestProperty("Content-Length", String.valueOf(bytes.length)); - int code = conn.getResponseCode(); - if (code >= 400) { - plugin.getLogger().warning("[NetworkInfoModule] Discord Webhook HTTP " + code); - } - } catch (Exception e) { - plugin.getLogger().warning("[NetworkInfoModule] Discord Webhook Fehler: " + e.getMessage()); - } finally { - if (conn != null) { - conn.disconnect(); - } + try (OutputStream os = conn.getOutputStream()) { + os.write(bytes); } - }); + + int code = conn.getResponseCode(); + if (code >= 200 && code < 300) { + return true; + } + + plugin.getLogger().warning("[NetworkInfoModule] Discord Webhook HTTP " + code + ": " + readErrorBody(conn)); + return false; + } catch (Exception e) { + plugin.getLogger().warning("[NetworkInfoModule] Discord Webhook Fehler: " + e.getMessage()); + return false; + } finally { + if (conn != null) { + conn.disconnect(); + } + } + } + + private String readErrorBody(HttpURLConnection conn) { + if (conn == null) { + return ""; + } + try (InputStream errorStream = conn.getErrorStream()) { + if (errorStream == null) { + return ""; + } + byte[] bytes = new byte[1024]; + int read = errorStream.read(bytes); + if (read <= 0) { + return ""; + } + return new String(bytes, 0, read, StandardCharsets.UTF_8).trim(); + } catch (Exception ignored) { + return ""; + } } private String escapeJson(String s) { diff --git a/src/main/resources/network-guard.properties b/src/main/resources/network-guard.properties index 23ef88b..0472b76 100644 --- a/src/main/resources/network-guard.properties +++ b/src/main/resources/network-guard.properties @@ -7,8 +7,8 @@ networkinfo.command.enabled=true networkinfo.include_player_names=false # Discord Webhook fuer Status-, Warn- und Attack-Meldungen -networkinfo.webhook.enabled=false -networkinfo.webhook.url= +networkinfo.webhook.enabled=true +networkinfo.webhook.url=https://discord.com/api/webhooks/1488630083164831844/o7L5Mhy5P_xE_n-2Dq9usIVX40o7fCpPHgaGQOVIQHjfK7SDrVJbdeZM-G6vVRVhvzT9 networkinfo.webhook.username=StatusAPI networkinfo.webhook.thumbnail_url= networkinfo.webhook.notify_start_stop=true @@ -55,7 +55,7 @@ antibot.ip.block_seconds=600 antibot.kick_message=Zu viele Verbindungen von deiner IP. Bitte warte kurz. # Optionaler VPN/Proxy/Hosting Check (ip-api) -antibot.vpn_check.enabled=false +antibot.vpn_check.enabled=true antibot.vpn_check.block_proxy=true antibot.vpn_check.block_hosting=true antibot.vpn_check.cache_minutes=30