diff --git a/README.md b/README.md index f6c360c..b824b82 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,47 @@ -# sc-ntfy-plugin +# NTFYNotifier -This is a minecraft plugin for the use with ntfy server for notifications \ No newline at end of file +A lightweight Minecraft plugin that sends real-time alerts to [ntfy.sh](https://ntfy.sh) when players join, leave, or run specific commands. Designed for Paper/Spigot servers on Minecraft 1.14+, this plugin helps admins stay in-the-know wherever they are. + +--- + +## ๐Ÿ”” Features + +- ๐Ÿ”น Join and Quit Notifications +- ๐Ÿ”น Command Watcher (customizable) +- ๐Ÿ”น `%player%` and `%server%` placeholder support +- ๐Ÿ”น Fully configurable messages and settings +- ๐Ÿ”น ntfy.sh API integration (with optional basic auth) + +--- + +## ๐Ÿ›  Installation + +1. Place the compiled `NTFYNotifier-1.0.0.jar` in your serverโ€™s `plugins/` folder. +2. Start the server to generate `config.yml` and `msg.yml`. +3. Customize configuration and messages to your liking. + +--- + +## โš™ Configuration + +### `config.yml` +```yaml +server-name: "NTFYCraft" + +ntfy: + server: "https://ntfy.sh" + topic: "minecraft-events" + auth: + enabled: false + username: "user" + password: "pass" + +notifications: + join: true + quit: true + commands: + enabled: true + watch: + - "stop" + - "ban" + - "kick" diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..ec1b2d5 --- /dev/null +++ b/build.bat @@ -0,0 +1,15 @@ +@echo off +REM === Run Maven clean and package === +echo Building NTFYNotifier with Maven... +mvn clean package + +REM === Check if the build succeeded === +IF EXIST target\NTFYNotifier-1.0.jar ( + echo. + echo โœ… Build successful! JAR created at: target\NTFYNotifier-1.0.jar +) ELSE ( + echo. + echo โŒ Build failed. Please check for compilation errors. +) + +pause \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..fe85a1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + com.minster586 + NTFYNotifier + 1.0.0 + jar + NTFYNotifier + + + UTF-8 + 1.8 + 1.8 + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + + + + org.spigotmc + spigot-api + 1.14.4-R0.1-SNAPSHOT + provided + + + + + + + src/main/resources + false + + + + + maven-compiler-plugin + + + maven-jar-plugin + + + + true + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/minster586/ntfyplugin/CommandMonitor.java b/src/main/java/com/minster586/ntfyplugin/CommandMonitor.java new file mode 100644 index 0000000..11077f0 --- /dev/null +++ b/src/main/java/com/minster586/ntfyplugin/CommandMonitor.java @@ -0,0 +1,41 @@ +package com.minster586.ntfyplugin; + +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +import java.util.List; + +public class CommandMonitor implements Listener { + + private final FileConfiguration config; + private final MessageManager messageManager; + private final NTFYNotifier notifier; + + public CommandMonitor(Main plugin) { + this.config = plugin.getConfig(); + this.messageManager = new MessageManager(plugin); + this.notifier = new NTFYNotifier(plugin); + } + + @EventHandler + public void onPlayerCommand(PlayerCommandPreprocessEvent event) { + if (!config.getBoolean("notifications.commands.enabled", true)) return; + + String commandLine = event.getMessage().toLowerCase().trim(); + CommandSender sender = event.getPlayer(); + + List watched = config.getStringList("notifications.commands.watch"); + for (String keyword : watched) { + if (commandLine.startsWith("/" + keyword.toLowerCase())) { + String title = messageManager.getMessage(keyword + ".title"); + String message = messageManager.formatMessage(keyword + ".message", (sender instanceof Player) ? (Player) sender : null); + notifier.sendNotification(title, message); + break; + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/minster586/ntfyplugin/Main.java b/src/main/java/com/minster586/ntfyplugin/Main.java new file mode 100644 index 0000000..56b98fa --- /dev/null +++ b/src/main/java/com/minster586/ntfyplugin/Main.java @@ -0,0 +1,41 @@ +package com.minster586.ntfyplugin; + +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; + +public class Main extends JavaPlugin { + + private static Main instance; + + @Override + public void onEnable() { + instance = this; + + // Save default config.yml (Bukkit handles this automatically) + saveDefaultConfig(); + + // Save msg.yml if it doesn't exist + File msgFile = new File(getDataFolder(), "msg.yml"); + if (!msgFile.exists()) { + saveResource("msg.yml", false); + } + + // Register listeners + PluginManager pm = getServer().getPluginManager(); + pm.registerEvents(new PlayerEventListener(this), this); + pm.registerEvents(new CommandMonitor(this), this); + + getLogger().info("NTFYNotifier has been enabled."); + } + + @Override + public void onDisable() { + getLogger().info("NTFYNotifier has been disabled."); + } + + public static Main getInstance() { + return instance; + } +} \ No newline at end of file diff --git a/src/main/java/com/minster586/ntfyplugin/MessageManager.java b/src/main/java/com/minster586/ntfyplugin/MessageManager.java new file mode 100644 index 0000000..f66c8f8 --- /dev/null +++ b/src/main/java/com/minster586/ntfyplugin/MessageManager.java @@ -0,0 +1,35 @@ +package com.minster586.ntfyplugin; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; + +import java.io.File; + +public class MessageManager { + + private final Main plugin; + private final YamlConfiguration messages; + + public MessageManager(Main plugin) { + this.plugin = plugin; + File msgFile = new File(plugin.getDataFolder(), "msg.yml"); + this.messages = YamlConfiguration.loadConfiguration(msgFile); + } + + public String getMessage(String path) { + return messages.getString("messages." + path, ""); + } + + public String formatMessage(String path, Player player) { + String message = getMessage(path); + + if (player != null) { + message = message.replace("%player%", player.getName()); + } + + String serverName = plugin.getConfig().getString("server-name", "Minecraft Server"); + message = message.replace("%server%", serverName); + + return message; + } +} \ No newline at end of file diff --git a/src/main/java/com/minster586/ntfyplugin/NTFYNotifier.java b/src/main/java/com/minster586/ntfyplugin/NTFYNotifier.java new file mode 100644 index 0000000..d1f502f --- /dev/null +++ b/src/main/java/com/minster586/ntfyplugin/NTFYNotifier.java @@ -0,0 +1,56 @@ +package com.minster586.ntfyplugin; + +import org.bukkit.configuration.file.FileConfiguration; + +import javax.net.ssl.HttpsURLConnection; +import java.io.OutputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class NTFYNotifier { + + private final FileConfiguration config; + + public NTFYNotifier(Main plugin) { + this.config = plugin.getConfig(); + } + + public void sendNotification(String title, String message) { + try { + String server = config.getString("ntfy.server", "https://ntfy.sh"); + String topic = config.getString("ntfy.topic", "minecraft-events"); + + String urlString = server.endsWith("/") ? server + topic : server + "/" + topic; + URL url = new URL(urlString); + HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); + + conn.setRequestMethod("POST"); + conn.setDoOutput(true); + conn.setRequestProperty("Title", title); + conn.setRequestProperty("Content-Type", "text/plain"); + + // Optional Basic Auth + if (config.getBoolean("ntfy.auth.enabled", false)) { + String username = config.getString("ntfy.auth.username"); + String password = config.getString("ntfy.auth.password"); + if (username != null && password != null) { + String auth = username + ":" + password; + String encoded = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8)); + conn.setRequestProperty("Authorization", "Basic " + encoded); + } + } + + // Send body + try (OutputStream os = conn.getOutputStream()) { + byte[] input = message.getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + + // Close connection to complete POST + conn.getInputStream().close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/minster586/ntfyplugin/PlayerEventListener.java b/src/main/java/com/minster586/ntfyplugin/PlayerEventListener.java new file mode 100644 index 0000000..ffaeb13 --- /dev/null +++ b/src/main/java/com/minster586/ntfyplugin/PlayerEventListener.java @@ -0,0 +1,43 @@ +package com.minster586.ntfyplugin; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class PlayerEventListener implements Listener { + + private final Main plugin; + private final FileConfiguration config; + private final MessageManager messageManager; + private final NTFYNotifier notifier; + + public PlayerEventListener(Main plugin) { + this.plugin = plugin; + this.config = plugin.getConfig(); + this.messageManager = new MessageManager(plugin); + this.notifier = new NTFYNotifier(plugin); + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + if (config.getBoolean("notifications.join", true)) { + Player player = event.getPlayer(); + String title = messageManager.getMessage("join.title"); + String message = messageManager.formatMessage("join.message", player); + notifier.sendNotification(title, message); + } + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + if (config.getBoolean("notifications.quit", true)) { + Player player = event.getPlayer(); + String title = messageManager.getMessage("quit.title"); + String message = messageManager.formatMessage("quit.message", player); + notifier.sendNotification(title, message); + } + } +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..2d9d264 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,22 @@ +ntfy: + server: "https://ntfy.sh" # Default public ntfy.sh server + topic: "minecraft-events" + auth: + enabled: false + username: "user" + password: "pass" + +server-name: "NTFYCraft" # Custom variable used in message placeholders + +notifications: + join: true + quit: true + commands: + enabled: true + watch: + - "stop" + - "ban" + - "kick" + - "mute" + - "warn" + - "op" \ No newline at end of file diff --git a/src/main/resources/msg.yml b/src/main/resources/msg.yml new file mode 100644 index 0000000..2b4d0f3 --- /dev/null +++ b/src/main/resources/msg.yml @@ -0,0 +1,25 @@ +messages: + join: + title: "Player Joined" + message: "%player% has joined the server." + quit: + title: "Player Left" + message: "%player% has left the server." + stop: + title: "Server Stop" + message: "%player% issued /stop" + ban: + title: "Player Banned" + message: "%player% used /ban" + kick: + title: "Player Kicked" + message: "%player% used /kick" + mute: + title: "Player Muted" + message: "%player% used /mute" + warn: + title: "Player Warned" + message: "%player% used /warn" + op: + title: "Player Opped" + message: "%player% used /op" \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..17b2ab1 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,8 @@ +name: NTFYNotifier +version: 1.0.0 +main: com.minster586.ntfyplugin.Main +api-version: 1.14 +author: minster586 +description: Sends customizable join, quit, and command notifications to an ntfy.sh server. +commands: {} +permissions: {} \ No newline at end of file