Allow configurable commands for each watch category (#8)

iKnowHowToCamelCase

Added fields to webhook and added Shadow gradle plugin

+ Update .drone.yml

Allow configurable commands for each watch category

+ Fixes #7
+ Each watchlist has an associated permission and a list of categories
+ Each category has a list of filters and an optional list of commands
+ When a match occurs, a warning is sent out and the commands are run

Co-authored-by: Joey Hines <joey@ahines.net>
Reviewed-on: https://git.etztech.xyz/Minecraft/Hush/pulls/8
Reviewed-by: Etzelia <etzelia@hotmail.com>
master
Joey Hines 2020-10-03 18:34:26 +02:00
parent a266178098
commit 8cd551112e
10 changed files with 122 additions and 127 deletions

View File

@ -30,7 +30,7 @@ steps:
pull: always
image: gradle:6.6
commands:
- gradle build
- gradle shadowjar
- name: gitea-release
pull: always
image: jolheiser/drone-gitea-main:latest

View File

@ -3,7 +3,7 @@ A plugin to monitor chat for forbidden phrases.
## Watch Lists
Watch lists specifies phrases to monitor. Each watch list has an associated permission. In the form of
`hush.<list_name>`. A user with this permission will have their chat messages checked to see if
`hush.<watchlist_name>`. A user with this permission will have their chat messages checked to see if
they match the corresponding watch list.
Watch lists contain two types of phrases, Monitored and Banned.

View File

@ -1,9 +1,10 @@
plugins {
id 'com.github.johnrengelman.shadow' version '6.0.0'
id 'java'
}
group = 'com.zerohighdef'
version = '0.1'
version = '0.2.0'
sourceCompatibility = '8'
@ -23,7 +24,10 @@ repositories {
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'
compile 'xyz.etztech:javacord:0.2.2'
}
shadowJar {
configurations = [project.configurations.compile]
archiveClassifier = ""
}

View File

@ -3,16 +3,17 @@ 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.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public final class Hush extends JavaPlugin {
private final Logger log = Logger.getLogger("Minecraft");
private List<WatchList> watchLists;
private HashMap<String, List<WatchCategory>> watchLists;
@Override
public void onEnable() {
@ -32,15 +33,20 @@ public final class Hush extends JavaPlugin {
}
private void buildWatchLists() {
watchLists = new LinkedList<>();
watchLists = new HashMap<>();
ConfigurationSection watchListSection = getConfig().getConfigurationSection("watch_lists");
for (String permission: watchListSection.getKeys(false)) {
String banMessage = watchListSection.getString(permission + ".ban_message");
List<String> banPatterns = watchListSection.getStringList(permission + ".ban");
List<String> monitorPatterns = watchListSection.getStringList(permission + ".monitor");
ConfigurationSection permissionSection = watchListSection.getConfigurationSection(permission);
LinkedList<WatchCategory> watchCategories = new LinkedList<>();
watchLists.add(new WatchList("hush." + permission, banMessage, banPatterns, monitorPatterns));
for (String category: permissionSection.getKeys(false)) {
ConfigurationSection categorySection = permissionSection.getConfigurationSection(category);
List<String> filters = categorySection.getStringList("filters");
List<String> commands = categorySection.getStringList("commands");
watchCategories.add(new WatchCategory(category, filters, commands));
}
watchLists.put(permission, watchCategories);
}
}
@ -48,7 +54,7 @@ public final class Hush extends JavaPlugin {
log.info( "[Hush]: " + message );
}
public List<WatchList> getWatchLists() {
public Map<String, List<WatchCategory>> getWatchLists() {
return watchLists;
}
}

View File

@ -0,0 +1,45 @@
package com.zerohighdef.hush;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class WatchCategory {
private final String categoryName;
private final List<Pattern> patterns;
private final List<String> commands;
public WatchCategory(String categoryName, List<String> patterns, List<String> commands) {
this.categoryName = categoryName;
this.patterns = buildPattern(patterns);
this.commands = commands;
}
private static List<Pattern> buildPattern(List<String> patternList) {
return patternList
.stream()
.map(p -> Pattern.compile(String.format("(%s)", p)))
.collect(Collectors.toList());
}
public Matcher checkPatterns(String string) {
for (Pattern p: patterns) {
Matcher matcher = p.matcher(string);
if (matcher.find()) {
return matcher;
}
}
return null;
}
public String getCategoryName() {
return categoryName;
}
public List<String> getCommands() {
return commands;
}
}

View File

@ -1,44 +0,0 @@
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<Pattern> banPatterns;
private final List<Pattern> monitorPatterns;
WatchList(String permission, String banMessage, List<String> banPatterns, List<String> monitorPatterns) {
this.permission = permission;
this.banMessage = banMessage;
this.banPatterns = WatchList.buildPattern(banPatterns);
this.monitorPatterns = WatchList.buildPattern(monitorPatterns);
}
private static List<Pattern> buildPattern(List<String> patternList) {
return patternList
.stream()
.map(p -> Pattern.compile(String.format("(%s)", p)))
.collect(Collectors.toList());
}
public String getPermission() {
return permission;
}
public List<Pattern> getBanPatterns() {
return banPatterns;
}
public List<Pattern> getMonitorPatterns() {
return monitorPatterns;
}
public String getBanMessage() {
return banMessage;
}
}

View File

@ -21,7 +21,6 @@ public class MainCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
if (!commandSender.hasPermission("hush.admin")) {
return true;
}
if (args.length == 0) {
@ -46,7 +45,7 @@ public class MainCommand implements CommandExecutor {
}
public void help(CommandSender commandSender) {
String version = Bukkit.getPluginManager().getPlugin("MineAlert").getDescription().getVersion();
String version = Bukkit.getPluginManager().getPlugin("Hush").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)

View File

@ -1,9 +1,7 @@
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 com.zerohighdef.hush.WatchCategory;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -14,14 +12,10 @@ import xyz.etztech.Javacord;
import xyz.etztech.Webhook;
import xyz.etztech.embed.Author;
import xyz.etztech.embed.Embed;
import xyz.etztech.embed.Field;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.regex.Pattern;
interface Action {
void action();
}
import java.util.regex.Matcher;
public class HushAsyncChatListener implements Listener {
private final Hush plugin;
@ -31,71 +25,57 @@ public class HushAsyncChatListener implements Listener {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = false)
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
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;
for (String permission : plugin.getWatchLists().keySet()) {
if (sender.hasPermission("hush." + permission)) {
for (WatchCategory category : plugin.getWatchLists().get(permission)) {
checkMessage(category, permission, sender, chatMessage);
}
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 void runCommand(String command) {
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command));
}
private boolean checkPhraseList(List<Pattern> patternList, Player player, String chatMessage, Action action) {
for (Pattern pattern: patternList) {
if (pattern.matcher(chatMessage).find()) {
if (action != null) {
action.action();
}
private void checkMessage(WatchCategory category, String watchList, Player player, String chatMessage) {
Matcher match = category.checkPatterns(chatMessage);
if (match != null) {
String playerName = player.getName();
String webhookURL = plugin.getConfig().getString("webhook");
String playerName = player.getName();
String webhook = plugin.getConfig().getString("webhook");
chatMessage = Javacord.escapeFormat(chatMessage);
chatMessage = pattern.matcher(chatMessage).replaceAll("**$0**");
if (webhook != null) {
String message = playerName + " said: " + 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;
for (String command: category.getCommands()) {
runCommand(command.replace("{player}", playerName));
}
if (webhookURL != null) {
chatMessage = match.replaceAll("**$0**");
String message = Javacord.escapeFormat(playerName) + " said: " + chatMessage;
Embed embed = new Embed()
.color(0xC70039)
.description(message)
.addField(new Field("Watchlist", String.format("`%s`", watchList)))
.addField(new Field("Category", String.format("`%s`", category.getCategoryName())))
.author(new Author(playerName, "", String.format("https://minotar.net/helm/%s/100.png", playerName), ""))
.timestamp(OffsetDateTime.now());
Webhook webhook = new Webhook("@here", embed);
this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, () -> {
try {
Javacord.sendWebhook(webhookURL, webhook);
} catch (Exception e) {
this.plugin.log("Webhook failed to send.");
}
});
}
}
return false;
}
}

View File

@ -3,13 +3,18 @@ webhook: ""
watch_lists:
# Permission to check
# To enable check give the group the 'hush.<perm>' permission
# To enable the check, give the group the 'hush.<watch_list>' permission
guest:
ban_message: "Please respect our players and staff. Appeal online"
#Phrases to ban for
ban:
- "heck"
- "fricks"
#Phrases to monitor
# Filters to search for
filters:
- "heck"
- "fricks"
# Commands to run {player} is replaced with the player's name
commands:
- "ban {player}"
monitor:
- "hypixel"
# Filters to search for
filters:
- "stupid"
- "dumb"

View File

@ -1,5 +1,5 @@
name: Hush
version: 0.1.0
version: 0.2.0
main: com.zerohighdef.hush.Hush
api-version: "1.16"
authors: [ZeroHighDef]