forked from Minecraft/Hush
Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Joey Hines | 784ebed9b0 |
42
.drone.yml
42
.drone.yml
|
@ -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"
|
|
|
@ -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
|
39
README.md
39
README.md
|
@ -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.
|
A plugin to monitor chat for forbidden phrases.
|
||||||
|
|
||||||
## Watch Lists
|
## Watch Lists
|
||||||
Watch lists specifies phrases to monitor. Each watch list has an associated permission. In the form of
|
Watchlist are groups of categories Hush monitors for. To enable a watchlist for a player,
|
||||||
`hush.<watchlist_name>`. A user with this permission will have their chat messages checked to see if
|
they should be given the `hush.<watchlist_name>` permission.
|
||||||
they match the corresponding watch list.
|
|
||||||
|
|
||||||
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
|
```yaml
|
||||||
Phrases that should be checked for context. If a user says one of these phrases, a Discord webhook is
|
# "ban" category
|
||||||
sent out.
|
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
|
## Permissions
|
||||||
A banned phrase results in an immediate ban. If a user says a banned phrase, they are kicked and added
|
* `hush.admin` - allows access to the `hush` command
|
||||||
to the ban list. A webhook is also sent to Discord.
|
* `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
|
## Example Config
|
||||||
[Config](src/main/resources/config.yml)
|
[Config](src/main/resources/config.yml)
|
||||||
|
|
||||||
## Permissions
|
|
||||||
[Permissions](src/main/resources/plugin.yml)
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
[MIT](LICENSE)
|
[MIT](LICENSE)
|
||||||
|
|
|
@ -4,7 +4,7 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'com.zerohighdef'
|
group = 'com.zerohighdef'
|
||||||
version = '0.2.1'
|
version = '0.2.2'
|
||||||
|
|
||||||
sourceCompatibility = '8'
|
sourceCompatibility = '8'
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ repositories {
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
name = 'etztech-repo'
|
name = 'etztech-repo'
|
||||||
url = 'http://repo.etztech.xyz/'
|
url = 'https://mvn.jojodev.com/releases/'
|
||||||
}
|
}
|
||||||
maven {url = 'https://jcenter.bintray.com'}
|
maven {url = 'https://jcenter.bintray.com'}
|
||||||
maven {url = 'https://jitpack.io'}
|
maven {url = 'https://jitpack.io'}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
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
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
|
@ -44,7 +44,8 @@ public final class Hush extends JavaPlugin {
|
||||||
ConfigurationSection categorySection = permissionSection.getConfigurationSection(category);
|
ConfigurationSection categorySection = permissionSection.getConfigurationSection(category);
|
||||||
List<String> filters = categorySection.getStringList("filters");
|
List<String> filters = categorySection.getStringList("filters");
|
||||||
List<String> commands = categorySection.getStringList("commands");
|
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);
|
watchLists.put(permission, watchCategories);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,13 @@ public class WatchCategory {
|
||||||
private final String categoryName;
|
private final String categoryName;
|
||||||
private final List<Pattern> patterns;
|
private final List<Pattern> patterns;
|
||||||
private final List<String> commands;
|
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.categoryName = categoryName;
|
||||||
this.patterns = buildPattern(patterns);
|
this.patterns = buildPattern(patterns);
|
||||||
this.commands = commands;
|
this.commands = commands;
|
||||||
|
this.cancelMsg = cancelMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Pattern> buildPattern(List<String> patternList) {
|
private static List<Pattern> buildPattern(List<String> patternList) {
|
||||||
|
@ -42,4 +44,8 @@ public class WatchCategory {
|
||||||
public List<String> getCommands() {
|
public List<String> getCommands() {
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getCancelMsg() {
|
||||||
|
return cancelMsg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,10 @@ public class MainCommand implements CommandExecutor {
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
|
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
|
||||||
if (!commandSender.hasPermission("hush.admin")) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
|
|
|
@ -26,59 +26,69 @@ public class HushAsyncChatListener implements Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
public boolean onChat(AsyncPlayerChatEvent event) {
|
public void onChat(AsyncPlayerChatEvent event) {
|
||||||
String chatMessage = event.getMessage();
|
String chatMessage = event.getMessage();
|
||||||
Player sender = event.getPlayer();
|
Player sender = event.getPlayer();
|
||||||
|
|
||||||
for (String permission : plugin.getWatchLists().keySet()) {
|
for (String permission : plugin.getWatchLists().keySet()) {
|
||||||
if (sender.hasPermission("hush." + permission)) {
|
if (sender.hasPermission("hush." + permission)) {
|
||||||
for (WatchCategory category : plugin.getWatchLists().get(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) {
|
private void runCommand(String command) {
|
||||||
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), 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);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,18 +5,22 @@ cooldown: 5
|
||||||
|
|
||||||
watch_lists:
|
watch_lists:
|
||||||
# Permission to check
|
# 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:
|
guest:
|
||||||
|
# "ban" category
|
||||||
ban:
|
ban:
|
||||||
# Filters to search for
|
# Filters to search for in chat
|
||||||
filters:
|
filters:
|
||||||
- "heck"
|
- "heck"
|
||||||
- "fricks"
|
- "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:
|
commands:
|
||||||
- "ban {player}"
|
- "ban {player}"
|
||||||
|
# Optional, should the message that matched the filter be cancelled. Default is "false".
|
||||||
|
cancel_msg: true
|
||||||
|
# "monitor" category
|
||||||
monitor:
|
monitor:
|
||||||
# Filters to search for
|
# Filters to search for in chat
|
||||||
filters:
|
filters:
|
||||||
- "stupid"
|
- "stupid"
|
||||||
- "dumb"
|
- "dumb"
|
Loading…
Reference in New Issue