Added cancel_msg config and update docs (#3)

+ cancel_msg allows a category to cancel the offending message, blocking it from going to chat
+ Updated docs to be a bit more clear
+ Switched to woodpecker
+ Fixes #1 and #2

Reviewed-on: Minecraft/Hush#3
Co-authored-by: Joey Hines <joey@ahines.net>
Co-committed-by: Joey Hines <joey@ahines.net>
latest
Joey Hines 2022-02-12 21:58:58 +00:00 committed by jolheiser
parent 237328ab50
commit 784ebed9b0
No known key found for this signature in database
GPG Key ID: 454E7F878890995A
10 changed files with 126 additions and 103 deletions

View File

@ -1,42 +0,0 @@
---
kind: pipeline
name: compliance
type: docker
trigger:
event:
- pull_request
steps:
- name: build
pull: always
image: gradle:6.6
commands:
- gradle build
---
kind: pipeline
name: release
type: docker
trigger:
branch:
- master
event:
- push
steps:
- name: build
pull: always
image: gradle:6.6
commands:
- gradle shadowjar
- name: gitea-release
pull: always
image: jolheiser/drone-gitea-main:latest
settings:
token:
from_secret: gitea_token
base: https://git.etztech.xyz
files:
- "build/libs/*.jar"

29
.woodpecker.yml 100644
View File

@ -0,0 +1,29 @@
clone:
git:
image: "woodpeckerci/plugin-git:next"
pipeline:
compliance:
commands:
- "gradle build"
- "gradle test"
image: "gradle:7.4-jdk17"
when:
event: pull_request
build:
commands:
- "gradle shadowJar"
image: "gradle:7.4-jdk17"
when:
branch: main
event: push
release:
image: jolheiser/drone-gitea-main:latest
settings:
token:
from_secret: gitea_token
base: https://git.jojodev.com
files:
- "build/libs/*.jar"
when:
branch: main
event: push

View File

@ -1,26 +1,37 @@
# Hush [![Build Status](https://drone.etztech.xyz/api/badges/Minecraft/Hush/status.svg)](https://drone.etztech.xyz/Minecraft/Hush)
# Hush [![Build Status](https://ci.jojodev.com/api/badges/Minecraft/Hush/status.svg)](https://ci.jojodev.com/Minecraft/Hush)
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.<watchlist_name>`. A user with this permission will have their chat messages checked to see if
they match the corresponding watch list.
Watchlist are groups of categories Hush monitors for. To enable a watchlist for a player,
they should be given the `hush.<watchlist_name>` permission.
Watch lists contain two types of phrases, Monitored and Banned.
### Categories
A category is a group of regex filters, and the actions to run when a player matches one of those filters.
An example of a category is shown below:
### Monitored
Phrases that should be checked for context. If a user says one of these phrases, a Discord webhook is
sent out.
```yaml
# "ban" category
ban:
# Filters to search for in chat
filters:
- "heck"
- "fricks"
# Optional, commands to run when a filter matches. {player} is replaced with the player's name.
commands:
- "ban {player}"
# Optional, should the message that matched the filter be cancelled? Default is "false".
cancel_msg: true
```
### Banned
A banned phrase results in an immediate ban. If a user says a banned phrase, they are kicked and added
to the ban list. A webhook is also sent to Discord.
## Permissions
* `hush.admin` - allows access to the `hush` command
* `hush.<watchlist_name>` - used to determine if a player's messages should be checked by a watchlist
### Commands
* `hush reload` - reloads the plugin config
## Example Config
[Config](src/main/resources/config.yml)
## Permissions
[Permissions](src/main/resources/plugin.yml)
## License
[MIT](LICENSE)

View File

@ -4,7 +4,7 @@ plugins {
}
group = 'com.zerohighdef'
version = '0.2.1'
version = '0.2.2'
sourceCompatibility = '8'
@ -16,7 +16,7 @@ repositories {
}
maven {
name = 'etztech-repo'
url = 'http://repo.etztech.xyz/'
url = 'https://mvn.jojodev.com/releases/'
}
maven {url = 'https://jcenter.bintray.com'}
maven {url = 'https://jitpack.io'}

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStorePath=wrapper/dists

View File

@ -44,7 +44,8 @@ public final class Hush extends JavaPlugin {
ConfigurationSection categorySection = permissionSection.getConfigurationSection(category);
List<String> filters = categorySection.getStringList("filters");
List<String> commands = categorySection.getStringList("commands");
watchCategories.add(new WatchCategory(category, filters, commands));
boolean cancelMsg = categorySection.getBoolean("cancel_msg", false);
watchCategories.add(new WatchCategory(category, filters, commands, cancelMsg));
}
watchLists.put(permission, watchCategories);
}

View File

@ -9,11 +9,13 @@ public class WatchCategory {
private final String categoryName;
private final List<Pattern> patterns;
private final List<String> commands;
private final boolean cancelMsg;
public WatchCategory(String categoryName, List<String> patterns, List<String> commands) {
public WatchCategory(String categoryName, List<String> patterns, List<String> commands, boolean cancelMsg) {
this.categoryName = categoryName;
this.patterns = buildPattern(patterns);
this.commands = commands;
this.cancelMsg = cancelMsg;
}
private static List<Pattern> buildPattern(List<String> patternList) {
@ -42,4 +44,8 @@ public class WatchCategory {
public List<String> getCommands() {
return commands;
}
public boolean getCancelMsg() {
return cancelMsg;
}
}

View File

@ -21,6 +21,10 @@ public class MainCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
if (!commandSender.hasPermission("hush.admin")) {
BaseComponent[] message = new ComponentBuilder()
.append("You don't have permission to to use this command.").color(ChatColor.RED)
.create();
commandSender.spigot().sendMessage(message);
return true;
}
if (args.length == 0) {

View File

@ -26,59 +26,69 @@ public class HushAsyncChatListener implements Listener {
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public boolean onChat(AsyncPlayerChatEvent event) {
public void onChat(AsyncPlayerChatEvent event) {
String chatMessage = event.getMessage();
Player sender = event.getPlayer();
for (String permission : plugin.getWatchLists().keySet()) {
if (sender.hasPermission("hush." + permission)) {
for (WatchCategory category : plugin.getWatchLists().get(permission)) {
checkMessage(category, permission, sender, chatMessage);
boolean is_match = checkMessage(category, permission, sender, chatMessage);
// If the message matched, and the category requires the event to be canceled
if (is_match && category.getCancelMsg()) {
// cancel event
event.setCancelled(true);
}
}
}
}
return true;
}
private void runCommand(String command) {
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command));
}
private void checkMessage(WatchCategory category, String watchList, Player player, String chatMessage) {
private boolean 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");
for (String command: category.getCommands()) {
runCommand(command.replace("{player}", playerName));
}
plugin.log(String.format("%s matched filter in %s.%s", playerName, watchList, category.getCategoryName()));
if (webhookURL != null && !plugin.isInCoolDown(player)) {
plugin.addCoolDown(player);
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.");
}
});
}
if (match == null) {
// message was not a match
return false;
}
String playerName = player.getName();
String webhookURL = plugin.getConfig().getString("webhook");
for (String command: category.getCommands()) {
runCommand(command.replace("{player}", playerName));
}
plugin.log(String.format("%s matched filter in %s.%s", playerName, watchList, category.getCategoryName()));
if (webhookURL != null && !plugin.isInCoolDown(player)) {
plugin.addCoolDown(player);
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 true;
}
}

View File

@ -5,18 +5,22 @@ cooldown: 5
watch_lists:
# Permission to check
# To enable the check, give the group the 'hush.<watch_list>' permission
# To enable the check for a user, give the 'hush.<watch_list>' permission
guest:
# "ban" category
ban:
# Filters to search for
# Filters to search for in chat
filters:
- "heck"
- "fricks"
# Commands to run {player} is replaced with the player's name
# Optional, commands to run when a filter matches. {player} is replaced with the player's name.
commands:
- "ban {player}"
# Optional, should the message that matched the filter be cancelled. Default is "false".
cancel_msg: true
# "monitor" category
monitor:
# Filters to search for
# Filters to search for in chat
filters:
- "stupid"
- "dumb"