From 6aa8933eca7a92e08e0d0cb25d9aa68dccee6bdb Mon Sep 17 00:00:00 2001 From: Jacob Marshall Date: Sat, 30 Jan 2016 23:22:56 +1300 Subject: [PATCH] Progress --- MelooonCensor.iml | 2 +- README.md | 7 - dependency-reduced-pom.xml | 7 + pom.xml | 8 + .../meloooncensor/MelooonCensor.java | 70 ++----- .../command/CensorCommandExecutor.java | 170 +++++++++++++++ .../command/NoPermissionException.java | 4 + .../meloooncensor/config/Configuration.java | 195 ++++++++++++++++++ .../meloooncensor/filter/ClassicFilter.java | 14 +- .../meloooncensor/filter/Filter.java | 39 +++- .../meloooncensor/filter/StrictFilter.java | 7 +- .../ChatEventListener.java | 18 +- .../PlayerJoinEventListener.java | 2 +- src/main/resources/plugin.yml | 7 +- 14 files changed, 455 insertions(+), 95 deletions(-) create mode 100644 src/main/java/io/github/jacobmarshall/meloooncensor/command/CensorCommandExecutor.java create mode 100644 src/main/java/io/github/jacobmarshall/meloooncensor/command/NoPermissionException.java create mode 100644 src/main/java/io/github/jacobmarshall/meloooncensor/config/Configuration.java rename src/main/java/io/github/jacobmarshall/meloooncensor/{listeners => listener}/ChatEventListener.java (57%) rename src/main/java/io/github/jacobmarshall/meloooncensor/{listeners => listener}/PlayerJoinEventListener.java (63%) diff --git a/MelooonCensor.iml b/MelooonCensor.iml index a30e3ee..05b723a 100644 --- a/MelooonCensor.iml +++ b/MelooonCensor.iml @@ -1,6 +1,6 @@ - + diff --git a/README.md b/README.md index c9781a5..e69de29 100644 --- a/README.md +++ b/README.md @@ -1,7 +0,0 @@ -# MelooonCensor - -A simple censor plugin for Bukkit/CraftBukkit. - -## License - -This repository and code is made available under the [MIT License](./LICENSE.md). \ No newline at end of file diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index 15b93ab..cdff835 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -44,6 +44,13 @@ + + maven-compiler-plugin + + 1.7 + 1.7 + + diff --git a/pom.xml b/pom.xml index 08d7368..54ad322 100644 --- a/pom.xml +++ b/pom.xml @@ -50,6 +50,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 1.7 + 1.7 + + diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/MelooonCensor.java b/src/main/java/io/github/jacobmarshall/meloooncensor/MelooonCensor.java index 062a06d..7bac700 100644 --- a/src/main/java/io/github/jacobmarshall/meloooncensor/MelooonCensor.java +++ b/src/main/java/io/github/jacobmarshall/meloooncensor/MelooonCensor.java @@ -1,47 +1,18 @@ package io.github.jacobmarshall.meloooncensor; -import io.github.jacobmarshall.meloooncensor.filter.ClassicFilter; -import io.github.jacobmarshall.meloooncensor.filter.Filter; -import io.github.jacobmarshall.meloooncensor.filter.StrictFilter; -import io.github.jacobmarshall.meloooncensor.listeners.ChatEventListener; -import org.bukkit.configuration.file.FileConfiguration; +import io.github.jacobmarshall.meloooncensor.config.Configuration; +import io.github.jacobmarshall.meloooncensor.listener.ChatEventListener; +import io.github.jacobmarshall.meloooncensor.command.CensorCommandExecutor; import org.bukkit.plugin.java.JavaPlugin; import org.mcstats.Metrics; import java.io.IOException; -import java.util.List; public class MelooonCensor extends JavaPlugin { - static final String DEFAULT_TYPE = "classic"; - static final char DEFAULT_CHAR = '*'; - static final String[] DEFAULT_LIST = new String[] {"fuck", "shit", "piss", "bitch"}; - static final String[] DEFAULT_IGNORE = new String[] {"shitsu"}; - static final String DEFAULT_MESSAGE = "Please don't use that kind of language on this server."; + private Configuration config; - FileConfiguration config = getConfig(); - Filter filter; - String warning; - - void setupConfig () { - config.options().header("MelooonCensor Configuration"); - config.addDefault("censor.type", DEFAULT_TYPE); - config.addDefault("censor.char", DEFAULT_CHAR); - config.addDefault("censor.list", DEFAULT_LIST); - config.addDefault("censor.ignore", DEFAULT_IGNORE); - config.addDefault("censor.message", DEFAULT_MESSAGE); - config.options().copyDefaults(true); - saveConfig(); - reloadConfig(); - } - - void loadConfig () { - config = getConfig(); - filter = getFilter(); - warning = config.getString("censor.message"); - } - - void startMetrics () { + protected void startMetrics () { try { Metrics metrics = new Metrics(this); metrics.start(); @@ -50,38 +21,23 @@ void startMetrics () { } } - void registerEvents () { + protected void registerEvents () { getServer().getPluginManager().registerEvents( - new ChatEventListener(filter, warning), this + new ChatEventListener(this.config), this ); - } - Filter getFilter () { - Filter filter; - - char replace = config.getString("censor.char", "*").charAt(0); - List censor = config.getStringList("censor.list"); - List ignore = config.getStringList("censor.ignore"); - - String name = config.getString("censor.type", "classic"); - - if (name.equalsIgnoreCase("strict")) { - // StrictFilter extends from ClassicFilter's detection technique, but doesn't allow any messages - // that violate the policy from sending out publicly. - filter = new StrictFilter(replace, censor, ignore); - } else { - // ClassicFilter takes any words that contain/are censored words, which aren't ignored words, - // and censors the whole word. - filter = new ClassicFilter(replace, censor, ignore); - } + getCommand("censor").setExecutor( + new CensorCommandExecutor(this.config) + ); + } - return filter; + protected void setupConfig () { + config = new Configuration(this); } @Override public void onEnable () { setupConfig(); - loadConfig(); startMetrics(); registerEvents(); } diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/command/CensorCommandExecutor.java b/src/main/java/io/github/jacobmarshall/meloooncensor/command/CensorCommandExecutor.java new file mode 100644 index 0000000..4cb38bf --- /dev/null +++ b/src/main/java/io/github/jacobmarshall/meloooncensor/command/CensorCommandExecutor.java @@ -0,0 +1,170 @@ +package io.github.jacobmarshall.meloooncensor.command; + +import io.github.jacobmarshall.meloooncensor.config.Configuration; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +public class CensorCommandExecutor implements CommandExecutor { + + Configuration config; + + public CensorCommandExecutor (Configuration config) { + this.config = config; + } + + public boolean onCommand (CommandSender sender, Command command, String label, String[] args) { + String cmd = ""; + String word = ""; + String type = ""; + + if (args.length >= 1) { + cmd = args[0].toLowerCase(); + } + + if (args.length >= 2) { + type = args[1].toLowerCase(); + } + + if (args.length >= 3) { + word = args[2]; + } + + try { + switch (cmd) { + case "add": + case "a": + switch (type) { + case "censor": + case "censored": + case "c": + assertPermission(sender, "meloooncensor.add.censor"); + + if (config.addCensor(word)) { + config.save(); + sender.sendMessage(ChatColor.GREEN + "Added to censored words."); + } else { + sender.sendMessage(ChatColor.YELLOW + "Already a censored word."); + } + break; + case "ignore": + case "ignored": + case "i": + assertPermission(sender, "meloooncensor.add.ignore"); + + if (config.addIgnore(word)) { + config.save(); + sender.sendMessage(ChatColor.GREEN + "Added to ignored words."); + } else { + sender.sendMessage(ChatColor.YELLOW + "Already an ignored word."); + } + break; + default: + sender.sendMessage(ChatColor.RED + "Provide a list to add a word to (censor/ignore)."); + break; + } + break; + case "remove": + case "r": + case "delete": + case "d": + switch (type) { + case "censor": + case "censored": + case "c": + assertPermission(sender, "meloooncensor.remove.censor"); + + if (config.removeCensor(word)) { + config.save(); + sender.sendMessage(ChatColor.GREEN + "Removed from censored words."); + } else { + sender.sendMessage(ChatColor.YELLOW + "Not a censored word."); + } + break; + case "ignore": + case "ignored": + case "i": + assertPermission(sender, "meloooncensor.remove.ignore"); + + if (config.removeIgnore(word)) { + config.save(); + sender.sendMessage(ChatColor.GREEN + "Removed from ignored words."); + } else { + sender.sendMessage(ChatColor.YELLOW + "Not an ignored word."); + } + break; + default: + sender.sendMessage(ChatColor.RED + "Provide a list to remove a word from (censor/ignore)."); + break; + } + break; + case "list": + case "l": + switch (type) { + case "censor": + case "censored": + case "c": + assertPermission(sender, "meloooncensor.list.censor"); + + sender.sendMessage(toStringArrayPretty(config.getCensor())); + break; + case "ignore": + case "ignored": + case "i": + assertPermission(sender, "meloooncensor.list.ignore"); + + sender.sendMessage(toStringArrayPretty(config.getIgnore())); + break; + default: + assertPermission(sender, "meloooncensor.list.censor"); + assertPermission(sender, "meloooncensor.list.ignore"); + + List all = new ArrayList<>(); + all.addAll(config.getCensor()); + all.addAll(config.getIgnore()); + sender.sendMessage(toStringArrayPretty(all)); + break; + } + break; + default: + return false; + } + } catch (NoPermissionException err) { + sender.sendMessage(ChatColor.RED + "You do not have permission to perform this action."); + } + + return true; + } + + private String toStringArrayPretty (List strings) { + StringBuilder pretty = new StringBuilder(); + + for (int index = 0; index < strings.size(); index++) { + if (index != 0) pretty.append(", "); + pretty.append(strings.get(index)); + } + + if (pretty.length() != 0) { + return pretty.toString(); + } else { + return "*Empty*"; + } + } + + private void assertPermission (CommandSender sender, String permission) throws NoPermissionException { + if (sender instanceof Player) { + Player player = (Player) sender; + + if ( ! player.isOp() || ! player.hasPermission(permission)) { + throw new NoPermissionException(); + } + } + } + +} diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/command/NoPermissionException.java b/src/main/java/io/github/jacobmarshall/meloooncensor/command/NoPermissionException.java new file mode 100644 index 0000000..9549b32 --- /dev/null +++ b/src/main/java/io/github/jacobmarshall/meloooncensor/command/NoPermissionException.java @@ -0,0 +1,4 @@ +package io.github.jacobmarshall.meloooncensor.command; + +public class NoPermissionException extends Exception { +} diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/config/Configuration.java b/src/main/java/io/github/jacobmarshall/meloooncensor/config/Configuration.java new file mode 100644 index 0000000..179e334 --- /dev/null +++ b/src/main/java/io/github/jacobmarshall/meloooncensor/config/Configuration.java @@ -0,0 +1,195 @@ +package io.github.jacobmarshall.meloooncensor.config; + +import io.github.jacobmarshall.meloooncensor.MelooonCensor; +import io.github.jacobmarshall.meloooncensor.filter.ClassicFilter; +import io.github.jacobmarshall.meloooncensor.filter.Filter; +import io.github.jacobmarshall.meloooncensor.filter.StrictFilter; +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.List; + +public class Configuration { + + public static final String TYPE = "censor.type"; + public static final String CHAR = "censor.char"; + public static final String CENSOR = "censor.list"; + public static final String IGNORE = "censor.ignore"; + public static final String MESSAGE = "censor.message"; + + public static final String DEFAULT_TYPE = "classic"; + public static final char DEFAULT_CHAR = '*'; + public static final String[] DEFAULT_CENSOR = new String[] {"fuck", "shit", "piss", "bitch"}; + public static final String[] DEFAULT_IGNORE = new String[] {"shitsu"}; + public static final String DEFAULT_MESSAGE = "Please don't use that kind of language on this server."; + + MelooonCensor plugin; + Filter filter; + String type; + char _char; + List censor; + List ignore; + String message; + + public Configuration (MelooonCensor plugin) { + this.plugin = plugin; + load(); + } + + protected FileConfiguration getConfig () { + return plugin.getConfig(); + } + + private void addDefaults () { + getConfig().options().header("MelooonCensor Configuration"); + getConfig().addDefault(TYPE, DEFAULT_TYPE); + getConfig().addDefault(CHAR, DEFAULT_CHAR); + getConfig().addDefault(CENSOR, DEFAULT_CENSOR); + getConfig().addDefault(IGNORE, DEFAULT_IGNORE); + getConfig().addDefault(MESSAGE, DEFAULT_MESSAGE); + getConfig().options().copyDefaults(true); + saveConfig(); + } + + private void loadConfig () { + plugin.reloadConfig(); + setType(getConfig().getString(TYPE)); + setCharString(getConfig().getString(CHAR)); + setCensor(getConfig().getStringList(CENSOR)); + setIgnore(getConfig().getStringList(IGNORE)); + setMessage(getConfig().getString(MESSAGE)); + updateFilter(); + } + + private void saveConfig () { + plugin.saveConfig(); + } + + public void save () { + getConfig().set(TYPE, type); + getConfig().set(CHAR, _char); + getConfig().set(CENSOR, censor); + getConfig().set(IGNORE, ignore); + getConfig().set(MESSAGE, message); + saveConfig(); + } + + public void load () { + addDefaults(); + loadConfig(); + } + + public void setType (String type) { + this.type = type; + updateFilter(); + } + + public String getType () { + return type; + } + + public Filter getFilter () { + return filter; + } + + private void updateFilter () { + switch (getType()) { + case "strict": + // StrictFilter extends from ClassicFilter's detection technique, but doesn't allow any messages + // that violate the policy from sending out publicly. + filter = new StrictFilter(this); + break; + default: + // ClassicFilter takes any words that contain/are censored words, which aren't ignored words, + // and censors the whole word. + filter = new ClassicFilter(this); + break; + } + } + + public void setCharString (String _char) { + if (_char != null) { + this._char = _char.charAt(0); + } + } + + public void setChar (char _char) { + this._char = _char; + } + + public String getCharString () { + return String.valueOf(getChar()); + } + + public char getChar () { + return _char; + } + + public void setCensor (List censor) { + this.censor = censor; + } + + public List getCensor () { + return censor; + } + + public boolean addCensor (String word) { + if ( ! censor.contains(word)) { + censor.add(word); + return true; + } else { + return false; + } + } + + public boolean removeCensor (String word) { + if (censor.contains(word)) { + censor.remove(word); + return true; + } else { + return false; + } + } + + public void clearCensor () { + censor.clear(); + } + + public void setIgnore (List ignore) { + this.ignore = ignore; + } + + public List getIgnore () { + return ignore; + } + + public boolean addIgnore (String word) { + if ( ! ignore.contains(word)) { + ignore.add(word); + return true; + } else { + return false; + } + } + + public boolean removeIgnore (String word) { + if (ignore.contains(word)) { + ignore.remove(word); + return true; + } else { + return false; + } + } + + public void clearIgnore () { + ignore.clear(); + } + + public void setMessage (String message) { + this.message = message; + } + + public String getMessage () { + return message; + } + +} diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/filter/ClassicFilter.java b/src/main/java/io/github/jacobmarshall/meloooncensor/filter/ClassicFilter.java index 76d9432..504752d 100644 --- a/src/main/java/io/github/jacobmarshall/meloooncensor/filter/ClassicFilter.java +++ b/src/main/java/io/github/jacobmarshall/meloooncensor/filter/ClassicFilter.java @@ -1,12 +1,14 @@ package io.github.jacobmarshall.meloooncensor.filter; -import java.util.List; +import io.github.jacobmarshall.meloooncensor.MelooonCensor; +import io.github.jacobmarshall.meloooncensor.config.Configuration; + import java.util.regex.Pattern; public class ClassicFilter extends Filter { - public ClassicFilter(char replace, List censor, List ignore) { - super(replace, censor, ignore); + public ClassicFilter (Configuration config) { + super(config); } @Override @@ -27,13 +29,13 @@ public String censorMessage (String message) { censoredMessage.append(" "); } - if (wordIsOrContains(word, censor)) { - if (wordIsOrContains(word, ignore)) { + if (isCensoredWord(word)) { + if (isIgnoredWord(word)) { // If the word is/contains an ignored word, allow the word censoredMessage.append(word); } else { // Censor the word if it contains a bad word & isn't an ignored one - censoredMessage.append(censorWord(word, word, true)); + censoredMessage.append(getCensoredWord(word, word, true)); } } else { // Doesn't match a censored word, continue as normal diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/filter/Filter.java b/src/main/java/io/github/jacobmarshall/meloooncensor/filter/Filter.java index fbca0c4..2a6aedc 100644 --- a/src/main/java/io/github/jacobmarshall/meloooncensor/filter/Filter.java +++ b/src/main/java/io/github/jacobmarshall/meloooncensor/filter/Filter.java @@ -1,34 +1,53 @@ package io.github.jacobmarshall.meloooncensor.filter; +import io.github.jacobmarshall.meloooncensor.config.Configuration; + +import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; public abstract class Filter { - char replace; - List censor; - List ignore; + Configuration config; - public Filter (char replace, List censor, List ignore) { - this.replace = replace; - this.censor = censor; - this.ignore = ignore; + public Filter (Configuration config) { + this.config = config; } private String getCensorString (int length) { - return new String(new char[length]).replace("\0", String.valueOf(replace)); + return new String(new char[length]).replace("\0", config.getCharString()); + } + + protected boolean isCensoredWord (String word) { + return wordIsOrContains(word, config.getCensor()); + } + + protected boolean isIgnoredWord (String word) { + return wordIsOrContains(word, config.getIgnore()); } - protected String censorWord (String word, String match, boolean whole) { + protected String getCensoredWord (String word, String match, boolean whole) { if (whole) { // Censor the entire word return getCensorString(word.length()); } else { // Replace any occurrences within the word with the censor string - return word.replaceAll(match, getCensorString(match.length())); + return word.replaceAll("(?i)" + match, getCensorString(match.length())); } } + protected List toLowerCaseStringList (List strings) { + List lowerCaseStringList = new ArrayList<>(); + for (String string : strings) { + lowerCaseStringList.add(string.toLowerCase()); + } + return lowerCaseStringList; + } + protected boolean wordIsOrContains (String word, List list) { + word = word.toLowerCase(); + list = toLowerCaseStringList(list); + if (list.contains(word)) { // If the word is in the list (quick and easy check) return true; diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/filter/StrictFilter.java b/src/main/java/io/github/jacobmarshall/meloooncensor/filter/StrictFilter.java index 8150464..ec63a22 100644 --- a/src/main/java/io/github/jacobmarshall/meloooncensor/filter/StrictFilter.java +++ b/src/main/java/io/github/jacobmarshall/meloooncensor/filter/StrictFilter.java @@ -1,11 +1,14 @@ package io.github.jacobmarshall.meloooncensor.filter; +import io.github.jacobmarshall.meloooncensor.MelooonCensor; +import io.github.jacobmarshall.meloooncensor.config.Configuration; + import java.util.List; public class StrictFilter extends ClassicFilter { - public StrictFilter (char replace, List censor, List ignore) { - super(replace, censor, ignore); + public StrictFilter (Configuration config) { + super(config); } @Override diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/listeners/ChatEventListener.java b/src/main/java/io/github/jacobmarshall/meloooncensor/listener/ChatEventListener.java similarity index 57% rename from src/main/java/io/github/jacobmarshall/meloooncensor/listeners/ChatEventListener.java rename to src/main/java/io/github/jacobmarshall/meloooncensor/listener/ChatEventListener.java index 114f0ad..377243f 100644 --- a/src/main/java/io/github/jacobmarshall/meloooncensor/listeners/ChatEventListener.java +++ b/src/main/java/io/github/jacobmarshall/meloooncensor/listener/ChatEventListener.java @@ -1,6 +1,6 @@ -package io.github.jacobmarshall.meloooncensor.listeners; +package io.github.jacobmarshall.meloooncensor.listener; -import io.github.jacobmarshall.meloooncensor.filter.Filter; +import io.github.jacobmarshall.meloooncensor.config.Configuration; import org.bukkit.ChatColor; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -9,12 +9,10 @@ public class ChatEventListener implements Listener { - Filter filter; - String warning; + Configuration config; - public ChatEventListener (Filter filter, String warning) { - this.filter = filter; - this.warning = warning; + public ChatEventListener (Configuration config) { + this.config = config; } @EventHandler @@ -22,8 +20,8 @@ public void onPlayerChat (AsyncPlayerChatEvent event) { Player player = event.getPlayer(); String message = event.getMessage(); - if (filter.violatesPolicy(message)) { - String censoredMessage = filter.censorMessage(message); + if (config.getFilter().violatesPolicy(message)) { + String censoredMessage = config.getFilter().censorMessage(message); if (censoredMessage == null) { event.setCancelled(true); @@ -31,7 +29,7 @@ public void onPlayerChat (AsyncPlayerChatEvent event) { event.setMessage(censoredMessage); } - player.sendMessage(ChatColor.GRAY + warning); + player.sendMessage(ChatColor.GRAY + config.getMessage()); } } diff --git a/src/main/java/io/github/jacobmarshall/meloooncensor/listeners/PlayerJoinEventListener.java b/src/main/java/io/github/jacobmarshall/meloooncensor/listener/PlayerJoinEventListener.java similarity index 63% rename from src/main/java/io/github/jacobmarshall/meloooncensor/listeners/PlayerJoinEventListener.java rename to src/main/java/io/github/jacobmarshall/meloooncensor/listener/PlayerJoinEventListener.java index ccb790c..c93a9a3 100644 --- a/src/main/java/io/github/jacobmarshall/meloooncensor/listeners/PlayerJoinEventListener.java +++ b/src/main/java/io/github/jacobmarshall/meloooncensor/listener/PlayerJoinEventListener.java @@ -1,4 +1,4 @@ -package io.github.jacobmarshall.meloooncensor.listeners; +package io.github.jacobmarshall.meloooncensor.listener; import org.bukkit.event.Listener; diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 17d5871..8482ac1 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,4 +1,9 @@ name: MelooonCensor main: io.github.jacobmarshall.meloooncensor.MelooonCensor version: 3.0.0 -author: Jacob Marshall \ No newline at end of file +author: Jacob Marshall +commands: + censor: + description: Add/remove censored/ignored words from chat. + aliases: [mcensor, meloooncensor] + usage: "/censor add [censor|ignore] (word),remove [censor|ignore] (word), list [censor|ignore]" \ No newline at end of file