commit 108e0ecd8e066012ba8adf1a87f0c9b31ffcf0e4 Author: Joey Hines Date: Sun Sep 20 16:34:23 2020 -0500 Initial Commit + Chat monitoring working + Banned phrases kick and ban the player + All phrases send a webhook to discord. + Config can be reloaded on the fly diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c37caf --- /dev/null +++ b/.gitignore @@ -0,0 +1,118 @@ +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Cache of project +.gradletasknamecache + +**/build/ + +# Common working directory +run/ + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..8e87e67 --- /dev/null +++ b/build.gradle @@ -0,0 +1,27 @@ +plugins { + id 'java' +} + +group = 'com.zerohighdef' +version = '0.1' + +sourceCompatibility = '8' + +repositories { + mavenLocal() + maven { + name = 'spigotmc-repo' + url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' + } + maven { + name = 'etztech-repo' + url = 'http://repo.etztech.xyz/' + } +} + +dependencies { + compileOnly 'org.spigotmc:spigot-api:1.16.3-R0.1-SNAPSHOT' + compileOnly 'xyz.etztech:plugin-api:1.0.8' + compileOnly 'xyz.etztech:javacord:0.2.0' +} + diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..e69de29 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7ad10bf --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..d04fcef --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'hush' diff --git a/src/main/java/com/zerohighdef/hush/Hush.java b/src/main/java/com/zerohighdef/hush/Hush.java new file mode 100644 index 0000000..23bd352 --- /dev/null +++ b/src/main/java/com/zerohighdef/hush/Hush.java @@ -0,0 +1,54 @@ +package com.zerohighdef.hush; + +import com.zerohighdef.hush.commands.MainCommand; +import com.zerohighdef.hush.listeners.HushAsyncChatListener; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.LinkedList; +import java.util.List; +import java.util.logging.Logger; + +public final class Hush extends JavaPlugin { + private final Logger log = Logger.getLogger("Minecraft"); + private List watchLists; + + @Override + public void onEnable() { + saveDefaultConfig(); + reloadConfig(); + + if (isEnabled()) { + new HushAsyncChatListener(this); + new MainCommand(this); + } + } + + @Override + public void reloadConfig() { + super.reloadConfig(); + buildWatchLists(); + } + + private void buildWatchLists() { + watchLists = new LinkedList<>(); + ConfigurationSection watchListSection = getConfig().getConfigurationSection("watch_lists"); + + for (String permission: watchListSection.getKeys(false)) { + String banMessage = watchListSection.getString(permission + ".ban_message"); + List banPatterns = watchListSection.getStringList(permission + ".ban"); + List monitorPatterns = watchListSection.getStringList(permission + ".monitor"); + + watchLists.add(new WatchList("hush." + permission, banMessage, banPatterns, monitorPatterns)); + } + } + + public void log(String message) { + log.info( "[Hush]: " + message ); + } + + public List getWatchLists() { + return watchLists; + } +} diff --git a/src/main/java/com/zerohighdef/hush/WatchList.java b/src/main/java/com/zerohighdef/hush/WatchList.java new file mode 100644 index 0000000..523dfd4 --- /dev/null +++ b/src/main/java/com/zerohighdef/hush/WatchList.java @@ -0,0 +1,44 @@ +package com.zerohighdef.hush; + +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class WatchList { + private final String permission; + private final String banMessage; + private final List banPatterns; + private final List monitorPatterns; + + WatchList(String permission, String banMessage, List banPatterns, List monitorPatterns) { + this.permission = permission; + this.banMessage = banMessage; + this.banPatterns = WatchList.buildPattern(banPatterns); + this.monitorPatterns = WatchList.buildPattern(monitorPatterns); + } + + private static List buildPattern(List patternList) { + return patternList + .stream() + .map(Pattern::compile) + .collect(Collectors.toList()); + } + + public String getPermission() { + return permission; + } + + public List getBanPatterns() { + return banPatterns; + } + + public List getMonitorPatterns() { + return monitorPatterns; + } + + public String getBanMessage() { + return banMessage; + } + + +} diff --git a/src/main/java/com/zerohighdef/hush/commands/MainCommand.java b/src/main/java/com/zerohighdef/hush/commands/MainCommand.java new file mode 100644 index 0000000..f38e7a1 --- /dev/null +++ b/src/main/java/com/zerohighdef/hush/commands/MainCommand.java @@ -0,0 +1,57 @@ +package com.zerohighdef.hush.commands; + +import com.zerohighdef.hush.Hush; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + + +public class MainCommand implements CommandExecutor { + private final Hush plugin; + + public MainCommand(Hush plugin) { + this.plugin = plugin; + this.plugin.getCommand("hush").setExecutor(this); + } + + @Override + public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) { + if (!commandSender.hasPermission("hush.admin")) { + + return true; + } + if (args.length == 0) { + help(commandSender); + } else { + switch (args[0]) { + case "help": + help(commandSender); + break; + case "reload": + reload(commandSender); + break; + } + } + return true; + } + + public void reload(CommandSender commandSender) { + plugin.reloadConfig(); + BaseComponent[] message = new ComponentBuilder().append("Plugin reloaded").color(ChatColor.GREEN).create(); + commandSender.spigot().sendMessage(message); + } + + public void help(CommandSender commandSender) { + String version = Bukkit.getPluginManager().getPlugin("MineAlert").getDescription().getVersion(); + BaseComponent[] message = new ComponentBuilder() + .append(String.format("*** Hush v%s ***", version)).color(ChatColor.DARK_AQUA) + .append("\n/hush help - Show this message").color(ChatColor.AQUA) + .append("\n/hush reload - Reload the config").color(ChatColor.AQUA) + .create(); + commandSender.spigot().sendMessage(message); + } +} \ No newline at end of file diff --git a/src/main/java/com/zerohighdef/hush/listeners/HushAsyncChatListener.java b/src/main/java/com/zerohighdef/hush/listeners/HushAsyncChatListener.java new file mode 100644 index 0000000..0cd399c --- /dev/null +++ b/src/main/java/com/zerohighdef/hush/listeners/HushAsyncChatListener.java @@ -0,0 +1,99 @@ +package com.zerohighdef.hush.listeners; + +import com.zerohighdef.hush.Hush; +import com.zerohighdef.hush.WatchList; +import org.apache.commons.lang.ObjectUtils; +import org.bukkit.BanList; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import xyz.etztech.Javacord; +import xyz.etztech.Webhook; +import xyz.etztech.embed.Author; +import xyz.etztech.embed.Embed; + +import java.time.OffsetDateTime; +import java.util.List; +import java.util.regex.Pattern; + +interface Action { + void action(); +} + +public class HushAsyncChatListener implements Listener { + private final Hush plugin; + + public HushAsyncChatListener(Hush plugin) { + this.plugin = plugin; + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = false) + public boolean onChat(AsyncPlayerChatEvent event) { + String chatMessage = event.getMessage(); + Player sender = event.getPlayer(); + for (WatchList list : plugin.getWatchLists()) { + if (sender.hasPermission(list.getPermission())) { + boolean phraseFound = checkPhraseList(list.getBanPatterns(), sender, chatMessage, (() -> { + banPlayer(sender, list.getBanMessage()); + })); + + if (phraseFound) { + event.setCancelled(true); + return true; + } + + checkPhraseList(list.getMonitorPatterns(), sender, chatMessage, null); + } + } + + return true; + } + + private void banPlayer(Player player, String banMessage) { + Bukkit.getBanList(BanList.Type.NAME) + .addBan(player.getName(), banMessage, null, null); + Bukkit.getScheduler().runTask(plugin, new Runnable() { + @Override + public void run() { + player.kickPlayer("You have been banned: " + banMessage); + } + }); + } + + private boolean checkPhraseList(List patternList, Player player, String chatMessage, Action action) { + for (Pattern pattern: patternList) { + if (pattern.matcher(chatMessage).find()) { + if (action != null) { + action.action(); + } + + String playerName = player.getName(); + String webhook = plugin.getConfig().getString("webhook"); + + if (webhook != null) { + String message = playerName + " said: " + "`" + Javacord.escapeFormat(chatMessage) + "`"; + Embed embed = new Embed() + .color(0xC70039) + .description(message) + .author(new Author(playerName, "", String.format("https://minotar.net/helm/%s/100.png", playerName), "")) + .timestamp(OffsetDateTime.now()); + + this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, () -> { + try { + Javacord.sendWebhook(webhook, new Webhook("@here", embed)); + } catch (Exception e) { + this.plugin.log("Webhook failed to send"); + } + }); + } + + return true; + } + } + return false; + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..c75f977 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,15 @@ +# Discord webhook +webhook: "" + +watch_lists: + # Permission to check + # To enable check give the group the 'hush.' permission + guest: + ban_message: "Please respect our players and staff. Appeal online" + #Phrases to ban for + ban: + - "heck" + - "fricks" + #Phrases to monitor + monitor: + - "hypixel" \ 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..62e74c2 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,14 @@ +name: Hush +version: v0.1.0 +main: com.zerohighdef.hush.Hush +api-version: "1.16" +authors: [ZeroHighDef] +description: Monitor chat for forbidden phrases. + +commands: + hush: + description: Admin command +permissions: + hush.admin: + description: Allows use of the admin command + default: op