Compare commits

..

No commits in common. "main" and "master" have entirely different histories.
main ... master

10 changed files with 103 additions and 126 deletions

42
.drone.yml 100644
View File

@ -0,0 +1,42 @@
---
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"

View File

@ -1,29 +0,0 @@
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,37 +1,26 @@
# Hush [![Build Status](https://ci.jojodev.com/api/badges/Minecraft/Hush/status.svg)](https://ci.jojodev.com/Minecraft/Hush) # Hush [![Build Status](https://drone.etztech.xyz/api/badges/Minecraft/Hush/status.svg)](https://drone.etztech.xyz/Minecraft/Hush)
A plugin to monitor chat for forbidden phrases. A plugin to monitor chat for forbidden phrases.
## Watch Lists ## Watch Lists
Watchlist are groups of categories Hush monitors for. To enable a watchlist for a player, Watch lists specifies phrases to monitor. Each watch list has an associated permission. In the form of
they should be given the `hush.<watchlist_name>` permission. `hush.<watchlist_name>`. A user with this permission will have their chat messages checked to see if
they match the corresponding watch list.
### Categories Watch lists contain two types of phrases, Monitored and Banned.
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:
```yaml ### Monitored
# "ban" category Phrases that should be checked for context. If a user says one of these phrases, a Discord webhook is
ban: sent out.
# 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
```
## Permissions ### Banned
* `hush.admin` - allows access to the `hush` command A banned phrase results in an immediate ban. If a user says a banned phrase, they are kicked and added
* `hush.<watchlist_name>` - used to determine if a player's messages should be checked by a watchlist to the ban list. A webhook is also sent to Discord.
### 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)

View File

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

View File

@ -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-7.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -44,8 +44,7 @@ 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");
boolean cancelMsg = categorySection.getBoolean("cancel_msg", false); watchCategories.add(new WatchCategory(category, filters, commands));
watchCategories.add(new WatchCategory(category, filters, commands, cancelMsg));
} }
watchLists.put(permission, watchCategories); watchLists.put(permission, watchCategories);
} }

View File

@ -9,13 +9,11 @@ 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, boolean cancelMsg) { public WatchCategory(String categoryName, List<String> patterns, List<String> commands) {
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) {
@ -44,8 +42,4 @@ public class WatchCategory {
public List<String> getCommands() { public List<String> getCommands() {
return commands; return commands;
} }
public boolean getCancelMsg() {
return cancelMsg;
}
} }

View File

@ -21,10 +21,6 @@ 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) {

View File

@ -26,69 +26,59 @@ public class HushAsyncChatListener implements Listener {
} }
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onChat(AsyncPlayerChatEvent event) { public boolean 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)) {
boolean is_match = checkMessage(category, permission, sender, chatMessage); 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 boolean checkMessage(WatchCategory category, String watchList, Player player, String chatMessage) { private void 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;
} }
} }

View File

@ -5,22 +5,18 @@ cooldown: 5
watch_lists: watch_lists:
# Permission to check # Permission to check
# To enable the check for a user, give the 'hush.<watch_list>' permission # To enable the check, give the group the 'hush.<watch_list>' permission
guest: guest:
# "ban" category
ban: ban:
# Filters to search for in chat # Filters to search for
filters: filters:
- "heck" - "heck"
- "fricks" - "fricks"
# Optional, commands to run when a filter matches. {player} is replaced with the player's name. # Commands to run {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 in chat # Filters to search for
filters: filters:
- "stupid" - "stupid"
- "dumb" - "dumb"