diff --git a/api/build.gradle.kts b/api/build.gradle.kts index cdc3ada..29999fe 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -1,5 +1,5 @@ group = "org.reprogle" -version = "3.3.0" +version = "3.3.2" extra["platform"] = "api" diff --git a/build.gradle.kts b/build.gradle.kts index ea25d6a..8cf4ed6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ group = "org.reprogle" -version = "3.3.0" +version = "3.3.2" -java.toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +java.toolchain.languageVersion.set(JavaLanguageVersion.of(21)) plugins { java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6a6bc40..fa92ae4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,6 +19,7 @@ boosted-yaml = "1.3.5" bstats = "3.0.2" guice = '7.0.0' +okhttp = '4.12.0' [plugins] shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } @@ -39,4 +40,5 @@ placeholder-api = { module = "me.clip:placeholderapi", version.ref = "placeholde boosted-yaml = { module = "dev.dejvokep:boosted-yaml", version.ref = "boosted-yaml" } bstats = { module = "org.bstats:bstats-bukkit", version.ref = "bstats" } -guice = { module = "com.google.inject:guice", version.ref = "guice"} +guice = { module = "com.google.inject:guice", version.ref = "guice" } +okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index 42db3be..128e025 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -1,5 +1,5 @@ group = "org.reprogle" -version = "3.3.0" +version = "3.3.2" extra["platform"] = "spigot" @@ -39,6 +39,7 @@ dependencies { compileOnly(libs.lands) implementation(libs.guice) + implementation(libs.okhttp) } // Configure the file output names of most files (Excluding shadow, which needs tweaking itself to avoid a "-all" being tagged onto it) diff --git a/spigot/src/main/java/org/reprogle/honeypot/common/events/BlockBreakEventListener.java b/spigot/src/main/java/org/reprogle/honeypot/common/events/BlockBreakEventListener.java index 6dc4bd2..e0eec9a 100644 --- a/spigot/src/main/java/org/reprogle/honeypot/common/events/BlockBreakEventListener.java +++ b/spigot/src/main/java/org/reprogle/honeypot/common/events/BlockBreakEventListener.java @@ -34,213 +34,237 @@ import org.reprogle.honeypot.common.utils.ActionHandler; import org.reprogle.honeypot.common.utils.HoneypotConfigManager; import org.reprogle.honeypot.common.utils.HoneypotLogger; +import org.reprogle.honeypot.common.utils.discord.DiscordWebhookNotifier; +import org.reprogle.honeypot.common.utils.discord.WebhookActionType; public class BlockBreakEventListener implements Listener { - private static final String BREAK_PERMISSION = "honeypot.break"; - - private static final String WILDCARD_PERMISSION = "honeypot.*"; - - private static final String EXEMPT_PERMISSION = "honeypot.exempt"; - - private final ActionHandler actionHandler; - private final HoneypotLogger logger; - private final HoneypotBlockManager blockManager; - private final HoneypotConfigManager configManager; - private final CommandFeedback commandFeedback; - private final HoneypotPlayerHistoryManager playerHistoryManager; - private final HoneypotPlayerManager playerManager; - - /** - * Create a private constructor to hide the implicit one - */ - @Inject - public BlockBreakEventListener(ActionHandler actionHandler, HoneypotLogger logger, HoneypotBlockManager blockManager, - HoneypotConfigManager configManager, CommandFeedback commandFeedback, - HoneypotPlayerHistoryManager playerHistoryManager, HoneypotPlayerManager playerManager) { - this.actionHandler = actionHandler; - this.logger = logger; - this.blockManager = blockManager; - this.configManager = configManager; - this.commandFeedback = commandFeedback; - this.playerHistoryManager = playerHistoryManager; - this.playerManager = playerManager; - } - - // Player block break event - @EventHandler(priority = EventPriority.LOWEST) - @SuppressWarnings({ "java:S3776", "java:S1192" }) - public void blockBreakEvent(BlockBreakEvent event) { - // Check to see if the event is cancelled before doing any logic. - // Ex: Creative mode player with Sword in hand - if (event.isCancelled()) - return; - if (blockManager.isHoneypotBlock(event.getBlock())) { - // Fire HoneypotPrePlayerBreakEvent - HoneypotPrePlayerBreakEvent hppbe = new HoneypotPrePlayerBreakEvent(event.getPlayer(), event.getBlock()); - Bukkit.getPluginManager().callEvent(hppbe); - logger.debug("Pre block break event is being called for " + event.getPlayer()); - - // Check if the event was cancelled. If it is, delete the block. - if (hppbe.isCancelled()) { - blockManager.deleteBlock(event.getBlock()); - logger.debug("The event was cancelled, not continuing."); - return; - } - - // Create a boolean for if we should remove the block from the DB or not - boolean deleteBlock = false; - - // If Allow Player Destruction is true, the player has permissions, or is Op, - // flag the block for deletion from the DB - // Otherwise, set the BlockBreakEvent to cancelled - if (configManager.getPluginConfig().getBoolean("allow-player-destruction") - || event.getPlayer().hasPermission(BREAK_PERMISSION) - || event.getPlayer().hasPermission(WILDCARD_PERMISSION) || event.getPlayer().isOp()) { - deleteBlock = true; - } else { - event.setCancelled(true); - logger.debug( - "The player who broke this block is either allowed to break it, or has some sort of permission. This Honeypot will be removed from the world"); - } - - // If blocks broken before action is less than or equal to 1, go to the break - // action. - // Otherwise, check if the player should have the action triggered - if (configManager.getPluginConfig().getInt("blocks-broken-before-action-taken") <= 1) { - // This is just a precaution to ensure that the player count is always less than - // 1 if the value in the - // config is 1 - - playerManager.setPlayerCount(event.getPlayer(), 0); - logger.debug("Action is being taken for this event."); - breakAction(event); - } else { - logger.debug("The break is just being counted, no action is taken yet"); - countBreak(event); - } - - // Fire HoneypotPlayerBreakEvent - HoneypotPlayerBreakEvent hpbe = new HoneypotPlayerBreakEvent(event.getPlayer(), event.getBlock()); - Bukkit.getPluginManager().callEvent(hpbe); - - // If we flagged the block for deletion, remove it from the DB. Do this after - // other actions have been - // completed, otherwise the other actions will fail with NPEs - if (deleteBlock) { - blockManager.deleteBlock(event.getBlock()); - } - } - } - - // This is a separate event from the one above. We want to know if any Honeypots - // were broken due to breaking a - // supporting block, such as torches breaking due to - // the block they're on being broken - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - @SuppressWarnings("java:S1192") - public void checkBlockBreakSideEffects(BlockBreakEvent event) { - if (!configManager.getPluginConfig().getBoolean("allow-player-destruction")) - return; - if (!event.getPlayer().hasPermission(BREAK_PERMISSION) - && !event.getPlayer().hasPermission(WILDCARD_PERMISSION) && !event.getPlayer().isOp()) - return; - - Block block = event.getBlock(); - - Block[] adjacentBlocks = new Block[] { block.getRelative(BlockFace.DOWN), block.getRelative(BlockFace.NORTH), - block.getRelative(BlockFace.SOUTH), block.getRelative(BlockFace.EAST), - block.getRelative(BlockFace.WEST), block.getRelative(BlockFace.UP) }; - - // Check all the blocks on the *side* first - for (Block adjacentBlock : adjacentBlocks) { - if(!adjacentBlock.getType().equals(Material.AIR)) continue; - - if (blockManager.isHoneypotBlock(adjacentBlock)) { - blockBreakEvent(new BlockBreakEvent(adjacentBlock, event.getPlayer())); - blockManager.deleteBlock(adjacentBlock); - logger.warning( - "A Honeypot has been removed due to the block it's attached to being broken. It was located at " - + adjacentBlock.getX() + ", " + adjacentBlock.getY() + ", " + adjacentBlock.getZ() - + ". " + event.getPlayer().getName() - + " is the player that indirectly broke it, so the assigned action was ran against them. If needed, please recreate the Honeypot"); - } - } - } - - @SuppressWarnings({ "java:S3776", "java:S2629", "java:S1192" }) - private void breakAction(BlockBreakEvent event) { - - // Get the block broken and the chat prefix for prettiness - Block block = event.getBlock(); - - // If the player isn't exempt, doesn't have permissions, and isn't Op - if (!event.getPlayer().hasPermission(EXEMPT_PERMISSION) && !event.getPlayer().hasPermission(BREAK_PERMISSION) - && !event.getPlayer().hasPermission(WILDCARD_PERMISSION) && !event.getPlayer().isOp()) { - - // Log the event in the history table - playerHistoryManager.addPlayerHistory(event.getPlayer(), - blockManager.getHoneypotBlock(event.getBlock()), "break"); - - // Grab the action from the block via the storage manager - String action = blockManager.getAction(block); - - // Run certain actions based on the action of the Honeypot Block - assert action != null; - logger.debug("BlockBreakEvent being called for player: " + event.getPlayer().getName() - + ", UUID of " + event.getPlayer().getUniqueId() + ". Action is: " + action); - - actionHandler.handleCustomAction(action, block, event.getPlayer()); - - // At this point we know the player has one of those permissions above. Now we - // need to figure out which - } else if (event.getPlayer().hasPermission(BREAK_PERMISSION) - || event.getPlayer().hasPermission(WILDCARD_PERMISSION) || event.getPlayer().isOp()) { - event.getPlayer().sendMessage(commandFeedback.sendCommandFeedback("staffbroke")); - - // If it got to here, then they are exempt but can't break blocks anyway. - } else { - event.setCancelled(true); - event.getPlayer().sendMessage(commandFeedback.sendCommandFeedback("exemptnobreak")); - } - } - - private void countBreak(BlockBreakEvent event) { - - // Don't count the break if they are exempt, have the remove permission, - // wildcard permission, or are Op - if (event.getPlayer().hasPermission(EXEMPT_PERMISSION) || event.getPlayer().isOp() - || event.getPlayer().hasPermission(BREAK_PERMISSION) - || event.getPlayer().hasPermission(WILDCARD_PERMISSION)) - return; - - // Get the config value and the amount of blocks broken - int breaksBeforeAction = configManager.getPluginConfig().getInt("blocks-broken-before-action-taken"); - int blocksBroken = playerManager.getCount(event.getPlayer()); - - // getCount returns -1 if the player doesn't exist in the DB. If that's the - // case, add the player to the DB - if (blocksBroken == -1) { - playerManager.addPlayer(event.getPlayer(), 0); - blocksBroken = 0; - } - - // Increment the blocks broken counter - blocksBroken += 1; - - // If the blocks broken are larger than or equals 'breaks before action' or if - // breaks before action equal equals - // 1, - // reset the count and perform the break - if (blocksBroken >= breaksBeforeAction || breaksBeforeAction == 1) { - playerManager.setPlayerCount(event.getPlayer(), 0); - breakAction(event); - } else { - // Just count it - playerManager.setPlayerCount(event.getPlayer(), blocksBroken); - // Log the event in the history table - playerHistoryManager.addPlayerHistory(event.getPlayer(), - blockManager.getHoneypotBlock(event.getBlock()), "prelimBreak"); - } - } + private static final String BREAK_PERMISSION = "honeypot.break"; + + private static final String WILDCARD_PERMISSION = "honeypot.*"; + + private static final String EXEMPT_PERMISSION = "honeypot.exempt"; + + private final ActionHandler actionHandler; + private final HoneypotLogger logger; + private final HoneypotBlockManager blockManager; + private final HoneypotConfigManager configManager; + private final CommandFeedback commandFeedback; + private final HoneypotPlayerHistoryManager playerHistoryManager; + private final HoneypotPlayerManager playerManager; + + /** + * Create a private constructor to hide the implicit one + */ + @Inject + public BlockBreakEventListener(ActionHandler actionHandler, HoneypotLogger logger, HoneypotBlockManager blockManager, + HoneypotConfigManager configManager, CommandFeedback commandFeedback, + HoneypotPlayerHistoryManager playerHistoryManager, HoneypotPlayerManager playerManager) { + this.actionHandler = actionHandler; + this.logger = logger; + this.blockManager = blockManager; + this.configManager = configManager; + this.commandFeedback = commandFeedback; + this.playerHistoryManager = playerHistoryManager; + this.playerManager = playerManager; + } + + // Player block break event + @EventHandler(priority = EventPriority.LOWEST) + @SuppressWarnings({"java:S3776", "java:S1192"}) + public void blockBreakEvent(BlockBreakEvent event) { + // Check to see if the event is cancelled before doing any logic. + // Ex: Creative mode player with Sword in hand + if (event.isCancelled()) + return; + if (blockManager.isHoneypotBlock(event.getBlock())) { + // Fire HoneypotPrePlayerBreakEvent + HoneypotPrePlayerBreakEvent hppbe = new HoneypotPrePlayerBreakEvent(event.getPlayer(), event.getBlock()); + Bukkit.getPluginManager().callEvent(hppbe); + logger.debug("Pre block break event is being called for " + event.getPlayer()); + + // Check if the event was cancelled. If it is, delete the block. + if (hppbe.isCancelled()) { + blockManager.deleteBlock(event.getBlock()); + logger.debug("The event was cancelled, not continuing."); + return; + } + + // Create a boolean for if we should remove the block from the DB or not + boolean deleteBlock = false; + + // If Allow Player Destruction is true, the player has permissions, or is Op, + // flag the block for deletion from the DB + // Otherwise, set the BlockBreakEvent to cancelled + if (configManager.getPluginConfig().getBoolean("allow-player-destruction") + || event.getPlayer().hasPermission(BREAK_PERMISSION) + || event.getPlayer().hasPermission(WILDCARD_PERMISSION) || event.getPlayer().isOp()) { + deleteBlock = true; + } else { + event.setCancelled(true); + logger.debug( + "The player who broke this block is either allowed to break it, or has some sort of permission. This Honeypot will be removed from the world"); + } + + // If blocks broken before action is less than or equal to 1, go to the break + // action. + // Otherwise, check if the player should have the action triggered + if (configManager.getPluginConfig().getInt("blocks-broken-before-action-taken") <= 1) { + // This is just a precaution to ensure that the player count is always less than + // 1 if the value in the + // config is 1 + + playerManager.setPlayerCount(event.getPlayer(), 0); + logger.debug("Action is being taken for this event."); + breakAction(event); + } else { + logger.debug("The break is just being counted, no action is taken yet"); + countBreak(event); + } + + // Fire HoneypotPlayerBreakEvent + HoneypotPlayerBreakEvent hpbe = new HoneypotPlayerBreakEvent(event.getPlayer(), event.getBlock()); + Bukkit.getPluginManager().callEvent(hpbe); + + // If we flagged the block for deletion, remove it from the DB. Do this after + // other actions have been + // completed, otherwise the other actions will fail with NPEs + if (deleteBlock) { + blockManager.deleteBlock(event.getBlock()); + } + } + } + + // This is a separate event from the one above. We want to know if any Honeypots + // were broken due to breaking a + // supporting block, such as torches breaking due to + // the block they're on being broken + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + @SuppressWarnings("java:S1192") + public void checkBlockBreakSideEffects(BlockBreakEvent event) { + if (!configManager.getPluginConfig().getBoolean("allow-player-destruction")) + return; + if (!event.getPlayer().hasPermission(BREAK_PERMISSION) + && !event.getPlayer().hasPermission(WILDCARD_PERMISSION) && !event.getPlayer().isOp()) + return; + + Block block = event.getBlock(); + + Block[] adjacentBlocks = new Block[]{block.getRelative(BlockFace.DOWN), block.getRelative(BlockFace.NORTH), + block.getRelative(BlockFace.SOUTH), block.getRelative(BlockFace.EAST), + block.getRelative(BlockFace.WEST), block.getRelative(BlockFace.UP)}; + + // Check all the blocks on the *side* first + for (Block adjacentBlock : adjacentBlocks) { + if (!adjacentBlock.getType().equals(Material.AIR)) continue; + + if (blockManager.isHoneypotBlock(adjacentBlock)) { + blockBreakEvent(new BlockBreakEvent(adjacentBlock, event.getPlayer())); + blockManager.deleteBlock(adjacentBlock); + logger.warning( + "A Honeypot has been removed due to the block it's attached to being broken. It was located at " + + adjacentBlock.getX() + ", " + adjacentBlock.getY() + ", " + adjacentBlock.getZ() + + ". " + event.getPlayer().getName() + + " is the player that indirectly broke it, so the assigned action was ran against them. If needed, please recreate the Honeypot"); + } + } + } + + @SuppressWarnings({"java:S3776", "java:S2629", "java:S1192"}) + private void breakAction(BlockBreakEvent event) { + + // Get the block broken and the chat prefix for prettiness + Block block = event.getBlock(); + + // If the player isn't exempt, doesn't have permissions, and isn't Op + if (!event.getPlayer().hasPermission(EXEMPT_PERMISSION) && !event.getPlayer().hasPermission(BREAK_PERMISSION) + && !event.getPlayer().hasPermission(WILDCARD_PERMISSION) && !event.getPlayer().isOp()) { + + // Log the event in the history table + playerHistoryManager.addPlayerHistory(event.getPlayer(), + blockManager.getHoneypotBlock(event.getBlock()), "break"); + + // Grab the action from the block via the storage manager + String action = blockManager.getAction(block); + + // Run certain actions based on the action of the Honeypot Block + assert action != null; + logger.debug("BlockBreakEvent being called for player: " + event.getPlayer().getName() + + ", UUID of " + event.getPlayer().getUniqueId() + ". Action is: " + action); + + actionHandler.handleCustomAction(action, block, event.getPlayer()); + + sendWebhook(event); + + // At this point we know the player has one of those permissions above. Now we + // need to figure out which + } else if (event.getPlayer().hasPermission(BREAK_PERMISSION) + || event.getPlayer().hasPermission(WILDCARD_PERMISSION) || event.getPlayer().isOp()) { + event.getPlayer().sendMessage(commandFeedback.sendCommandFeedback("staffbroke")); + + // If it got to here, then they are exempt but can't break blocks anyway. + } else { + event.setCancelled(true); + event.getPlayer().sendMessage(commandFeedback.sendCommandFeedback("exemptnobreak")); + } + } + + private void countBreak(BlockBreakEvent event) { + + // Don't count the break if they are exempt, have the remove permission, + // wildcard permission, or are Op + if (event.getPlayer().hasPermission(EXEMPT_PERMISSION) || event.getPlayer().isOp() + || event.getPlayer().hasPermission(BREAK_PERMISSION) + || event.getPlayer().hasPermission(WILDCARD_PERMISSION)) + return; + + // Get the config value and the amount of blocks broken + int breaksBeforeAction = configManager.getPluginConfig().getInt("blocks-broken-before-action-taken"); + int blocksBroken = playerManager.getCount(event.getPlayer()); + + // getCount returns -1 if the player doesn't exist in the DB. If that's the + // case, add the player to the DB + if (blocksBroken == -1) { + playerManager.addPlayer(event.getPlayer(), 0); + blocksBroken = 0; + } + + // Increment the blocks broken counter + blocksBroken += 1; + + // If the blocks broken are larger than or equals 'breaks before action' or if + // breaks before action equal equal 1, reset the count and perform the break + if (blocksBroken >= breaksBeforeAction || breaksBeforeAction == 1) { + playerManager.setPlayerCount(event.getPlayer(), 0); + breakAction(event); + } else { + // Just count it + playerManager.setPlayerCount(event.getPlayer(), blocksBroken); + // Log the event in the history table + playerHistoryManager.addPlayerHistory(event.getPlayer(), + blockManager.getHoneypotBlock(event.getBlock()), "prelimBreak"); + + sendWebhook(event); + } + } + + private void sendWebhook(BlockBreakEvent event) { + if (configManager.getPluginConfig().getBoolean("discord.enable")) { + WebhookActionType actionType; + String sendWhen = configManager.getPluginConfig().getString("discord.send-when"); + switch (sendWhen) { + case "onbreak": + actionType = WebhookActionType.BREAK; + break; + case "action": + actionType = WebhookActionType.ACTION; + break; + default: + actionType = WebhookActionType.ACTION; + break; + } + + new DiscordWebhookNotifier(actionType, configManager.getPluginConfig().getString("discord.url"), event.getBlock(), event.getPlayer(), logger).send(); + } + } } diff --git a/spigot/src/main/java/org/reprogle/honeypot/common/utils/HoneypotConfigManager.java b/spigot/src/main/java/org/reprogle/honeypot/common/utils/HoneypotConfigManager.java index f01f5d3..736bc39 100644 --- a/spigot/src/main/java/org/reprogle/honeypot/common/utils/HoneypotConfigManager.java +++ b/spigot/src/main/java/org/reprogle/honeypot/common/utils/HoneypotConfigManager.java @@ -25,8 +25,6 @@ import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings.OptionSorting; import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; -import org.reprogle.honeypot.Honeypot; import java.io.File; import java.io.IOException; @@ -52,7 +50,7 @@ public class HoneypotConfigManager { * decoding the jar to get the files that way but that's suuuuper icky. * (https://www.spigotmc.org/threads/getresources-function.226318/ if anyone wants an example) */ - private final List languages = Arrays.asList("en_US", "es_MX", "fr_FR", "ja_JP"); + private final List languages = Arrays.asList("en_US", "es_MX", "fr_FR", "ja_JP", "zh_CN"); /** * Sets up the plugin config and saves it to private variables for use later. Will shut down the plugin if there are diff --git a/spigot/src/main/java/org/reprogle/honeypot/common/utils/discord/DiscordWebhookNotifier.java b/spigot/src/main/java/org/reprogle/honeypot/common/utils/discord/DiscordWebhookNotifier.java new file mode 100644 index 0000000..c2bbccc --- /dev/null +++ b/spigot/src/main/java/org/reprogle/honeypot/common/utils/discord/DiscordWebhookNotifier.java @@ -0,0 +1,108 @@ +package org.reprogle.honeypot.common.utils.discord; + +import okhttp3.*; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.reprogle.honeypot.common.utils.HoneypotLogger; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class DiscordWebhookNotifier { + + private final WebhookActionType webhookType; + private final String webhookUrl; + private final Block block; + private final Player player; + private final HoneypotLogger logger; + + private String jsonTemplate = """ + { + "content": "", + "tts": false, + "embeds": [ + { + "id": 595876530, + "description": "The honeypot located at %coordinates% in world %world% was triggered by %player%!", + "fields": [], + "title": "Honeypot Discord Alert - %webhookType%", + "timestamp": "2024-06-24T00:32:00.000Z", + "color": 11636736, + "thumbnail": { + "url": "https://mc-heads.net/avatar/%UUID%" + } + } + ], + "components": [], + "actions": {}, + "username": "Honeypot" + } + """; + + /** + * Create a Discord webhook to send. This method does not automatically send the webhook, giving the developer more control over when it is actually sent. + * + * @param webhookType The type of webhook. See {@link WebhookActionType} + * @param webhookUrl The url of the Discord webhook to send it to + * @param block The block that triggered the webhook + * @param player The player that triggered the webhook + * @param logger The HoneypotLogger to log to in case something goes wrong + */ + public DiscordWebhookNotifier(WebhookActionType webhookType, String webhookUrl, Block block, Player player, HoneypotLogger logger) { + this.webhookType = webhookType; + this.webhookUrl = webhookUrl; + this.block = block; + this.player = player; + this.logger = logger; + } + + /** + * Send the webhook that was created. This will send asynchronously, so no success or failure result can be obtained from it. + * In the future this may be changed to a Future to allow receiving of a result. + */ + public void send() { + String tempBody; + + switch (webhookType) { + case ACTION: + tempBody = jsonTemplate.replace("%webhookType%", "Action Taken"); + break; + case BREAK: + tempBody = jsonTemplate.replace("%webhookType%", "Block Broken"); + break; + default: + tempBody = jsonTemplate.replace("%webhookType%", "Unknown"); + break; + } + + final String finalBody = tempBody.replace("%coordinates%", block.getX() + ", " + block.getY() + ", " + block.getZ()) + .replace("%world%", "\\\"" + block.getWorld().getName() + "\\\"") + .replace("%player%", player.getName()) + .replace("%UUID%", player.getUniqueId().toString()); + + new Thread(() -> { + RequestBody body = RequestBody.create(finalBody, MediaType.get("application/json")); + + Request request = new Request.Builder() + .url(webhookUrl) + .post(body) + .build(); + + new OkHttpClient().newCall(request).enqueue(new Callback() { + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + e.printStackTrace(); + } + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + response.close(); + return; + } + }); + }).start(); + + } +} diff --git a/spigot/src/main/java/org/reprogle/honeypot/common/utils/discord/WebhookActionType.java b/spigot/src/main/java/org/reprogle/honeypot/common/utils/discord/WebhookActionType.java new file mode 100644 index 0000000..aab653e --- /dev/null +++ b/spigot/src/main/java/org/reprogle/honeypot/common/utils/discord/WebhookActionType.java @@ -0,0 +1,6 @@ +package org.reprogle.honeypot.common.utils.discord; + +public enum WebhookActionType { + ACTION, + BREAK +} diff --git a/spigot/src/main/java/org/reprogle/honeypot/common/utils/integrations/AdapterManager.java b/spigot/src/main/java/org/reprogle/honeypot/common/utils/integrations/AdapterManager.java index c26d87e..a530e74 100644 --- a/spigot/src/main/java/org/reprogle/honeypot/common/utils/integrations/AdapterManager.java +++ b/spigot/src/main/java/org/reprogle/honeypot/common/utils/integrations/AdapterManager.java @@ -4,25 +4,28 @@ import com.google.inject.Singleton; import org.bukkit.Server; import org.reprogle.honeypot.Honeypot; +import org.reprogle.honeypot.common.utils.HoneypotConfigManager; @Singleton public class AdapterManager { private final Honeypot plugin; + private final HoneypotConfigManager configManager; /** * Private constructor to hide implicit one */ @Inject - public AdapterManager(Honeypot plugin) { + public AdapterManager(Honeypot plugin, HoneypotConfigManager configManager) { + this.configManager = configManager; this.plugin = plugin; } - private static WorldGuardAdapter wga = null; + private WorldGuardAdapter wga = null; - private static GriefPreventionAdapter gpa = null; + private GriefPreventionAdapter gpa = null; - private static LandsAdapter la = null; + private LandsAdapter la = null; public void onLoadAdapters(Server server) { if (server.getPluginManager().getPlugin("WorldGuard") != null) { @@ -32,7 +35,7 @@ public void onLoadAdapters(Server server) { public void onEnableAdapters(Server server) { if (server.getPluginManager().getPlugin("GriefPrevention") != null) - gpa = new GriefPreventionAdapter(); + gpa = new GriefPreventionAdapter(configManager); if (server.getPluginManager().getPlugin("Lands") != null) { la = new LandsAdapter(plugin); diff --git a/spigot/src/main/java/org/reprogle/honeypot/common/utils/integrations/GriefPreventionAdapter.java b/spigot/src/main/java/org/reprogle/honeypot/common/utils/integrations/GriefPreventionAdapter.java index 6ac5a3d..91fe4df 100644 --- a/spigot/src/main/java/org/reprogle/honeypot/common/utils/integrations/GriefPreventionAdapter.java +++ b/spigot/src/main/java/org/reprogle/honeypot/common/utils/integrations/GriefPreventionAdapter.java @@ -29,8 +29,11 @@ */ public class GriefPreventionAdapter { - @Inject - private HoneypotConfigManager configManager; + private final HoneypotConfigManager configManager; + + protected GriefPreventionAdapter(HoneypotConfigManager configManager) { + this.configManager = configManager; + } /** * Check if the player has permission diff --git a/spigot/src/main/resources/config.yml b/spigot/src/main/resources/config.yml index 0277012..0166459 100644 --- a/spigot/src/main/resources/config.yml +++ b/spigot/src/main/resources/config.yml @@ -3,7 +3,7 @@ ###################################################################### # File verison (do NOT edit): -file-version: 19 +file-version: 20 # How many Honeypots to store in cache at any given time. The maximum size is 50, and anything larger than that is ignored. # Setting this to <=0 will disable caching @@ -60,11 +60,20 @@ ghost-honeypot-checker: # Enable more detailed logging, stored in a honeypot.log file in the Honeypot folder enable-logging: true +# Enable Discord Webhooks. This will send messages to Discord via your webhook URL if a Honeypot is broken and/or activated +# Change "send-when" to "onbreak" when you want to be notified of all breaks (Including when action is taken). +# Change it to "action" if you want to be notified of only actions taken +# If none of these match. the default will be "action" +discord: + enable: false + url: "https://www.example.com" + send-when: action + ###################################################################### # C H A T S E T T I N G S # ###################################################################### -# Select your language. Current supported languages are: [en_US, es_MX, fr_FR, ja_JP] +# Select your language. Current supported languages are: [en_US, es_MX, fr_FR, ja_JP, zh_CN] # Want to create your own translation? Visit here: https://github.com/TerrorByteTW/Honeypot/wiki/Translating-Honeypot language: en_US @@ -127,7 +136,7 @@ enable-debug-mode: false # Credit where credit is due! If you contribute to Honeypot in any way, you'll get your name here # Code Contributions: TerrorByte, SandwichBtw (Build tools modernization) # Feature Contributions: MattVid#3488, Jammers, melaniebeedot -# Translation Contributions: siyukatu#4489 (ja_JP) +# Translation Contributions: siyukatu#4489 (ja_JP), HaHaWTH (zh_CN) # Bug Reports: Casper#9647, siyukatu#4489, MattVid#3488 # The next line is ignored, just a dummy value so the credits above get populated within the config! thank-you: true \ No newline at end of file diff --git a/spigot/src/main/resources/lang/zh_CN.yml b/spigot/src/main/resources/lang/zh_CN.yml new file mode 100644 index 0000000..d387568 --- /dev/null +++ b/spigot/src/main/resources/lang/zh_CN.yml @@ -0,0 +1,32 @@ +language-version: 4 +prefix: "&6[Honeypot]&r" +kick-reason: "你因破坏蜜罐方块被踢出, 请勿破坏!" +ban-reason: "你因破坏蜜罐方块被封禁!" +warn-message: "请勿破坏建筑!" +already-exists: "目标方块已经是一个蜜罐方块了, 如果你想修改惩罚方式, 请删除后重新创建." +success: + created: "成功创建 Honeypot!" + removed: "成功移除 Honeypot!" + default: "操作成功完成!" +not-a-honeypot: "&c目标方块不是蜜罐方块" +no-permission: "&c你没有权限执行该命令" +reload: "配置文件重载中, 如果你修改了语言配置, 请重启服务器以应用更改." +found-pots: "正在高亮附近的蜜罐方块" +no-pots-found: "范围内没有找到任何蜜罐方块" +update-available: "Honeypot 有更新可用. 更新以享受最新功能和安全补丁! 下载链接: &6https://github.com/TerrorByteTW/Honeypot" +against-filter: "你无法这样做, 该方块不在过滤列表中!" +not-looking-at-block: "你需要看向一个方块才能执行此命令!" +no-exist: "配置文件中找不到选定的Honeypot类型!" +deleted: + all: "已删除所有蜜罐方块" + near: "已删除附近的蜜罐方块" +worldguard: "Honeypot 在这片区域已被WorldGuard禁用" +griefprevention: "这片区域由GriefPrevention保护, 你无权在受保护的区域中放置" +lands: "这片区域由Lands保护, 你不能在Lands领地中放置蜜罐方块" +unknown-error: "未知错误, 请联系服务器管理员" +staff-broke: "提醒: 你破坏的是一个蜜罐方块. 已将其自动移除." +exempt-no-break: "你不受破坏惩罚影响, 但是你没有权限破坏蜜罐方块!" +searching: "搜索中..." +truncating: "正在过滤结果..." +not-online: "&c该玩家不在线!" +no-history: "找不到该玩家相关的历史记录!" diff --git a/supported-versions/3.3.0 b/supported-versions/3.3.0 index e69de29..a26d9d2 100644 --- a/supported-versions/3.3.0 +++ b/supported-versions/3.3.0 @@ -0,0 +1 @@ +1.18-1.20.6 \ No newline at end of file diff --git a/supported-versions/3.3.1 b/supported-versions/3.3.1 new file mode 100644 index 0000000..5b3cbca --- /dev/null +++ b/supported-versions/3.3.1 @@ -0,0 +1 @@ +1.18-1.21 \ No newline at end of file diff --git a/supported-versions/3.3.2 b/supported-versions/3.3.2 new file mode 100644 index 0000000..127f56a --- /dev/null +++ b/supported-versions/3.3.2 @@ -0,0 +1 @@ +1.21-1.21 \ No newline at end of file diff --git a/version.txt b/version.txt index 0fa4ae4..5436ea0 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.3.0 \ No newline at end of file +3.3.2 \ No newline at end of file