config command

This commit is contained in:
ImproperIssues
2023-04-15 15:31:08 -07:00
parent 85f8ad6ec3
commit 16d5b4a5a2
11 changed files with 420 additions and 3 deletions

View File

@@ -1,7 +1,11 @@
package io.github.itzispyder.ogredupealias;
import io.github.itzispyder.ogredupealias.commands.commands.ConfigCommand;
import io.github.itzispyder.ogredupealias.commands.commands.MuteChatCommand;
import io.github.itzispyder.ogredupealias.commands.commands.StaffChatCommand;
import io.github.itzispyder.ogredupealias.data.Config;
import io.github.itzispyder.ogredupealias.events.ChatEventListener;
import io.github.itzispyder.ogredupealias.events.PlayerEventListener;
import org.bukkit.Bukkit;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
@@ -31,10 +35,16 @@ public final class OgreDupeAlias extends JavaPlugin {
public void init() {
// Events
pm.registerEvents(new ChatEventListener(),this);
pm.registerEvents(new PlayerEventListener(),this);
// Commands
getCommand("config").setExecutor(new ConfigCommand());
getCommand("config").setTabCompleter(new ConfigCommand());
getCommand("mutechat").setExecutor(new MuteChatCommand());
getCommand("mutechat").setTabCompleter(new MuteChatCommand());
getCommand("staffchat").setExecutor(new StaffChatCommand());
getCommand("staffchat").setTabCompleter(new StaffChatCommand());
}
public void initConfig() {

View File

@@ -0,0 +1,43 @@
package io.github.itzispyder.ogredupealias.commands.commands;
import io.github.itzispyder.ogredupealias.commands.CmdExHandler;
import io.github.itzispyder.ogredupealias.commands.TabComplBuilder;
import io.github.itzispyder.ogredupealias.utils.ChatConstraints;
import io.github.itzispyder.ogredupealias.utils.Text;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import java.util.List;
public class MuteChatCommand implements TabExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
try {
if (args.length == 0) ChatConstraints.setChatMuted(!ChatConstraints.isChatMuted());
else ChatConstraints.setChatMuted(Boolean.parseBoolean(args[0]));
boolean muted = ChatConstraints.isChatMuted();
sender.sendMessage(Text.builder("&3Chat is now " + (muted ? "&cmuted" : "&aunmuted") + "&3!")
.prefix()
.color()
.build());
}
catch (Exception ex) {
CmdExHandler handler = new CmdExHandler(ex,command);
sender.sendMessage(handler.getHelp());
}
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return new TabComplBuilder(sender, command, alias, args)
.add(1, new String[] {
"true",
"false"
})
.build();
}
}

View File

@@ -0,0 +1,41 @@
package io.github.itzispyder.ogredupealias.commands.commands;
import io.github.itzispyder.ogredupealias.commands.CmdExHandler;
import io.github.itzispyder.ogredupealias.commands.TabComplBuilder;
import io.github.itzispyder.ogredupealias.utils.ArrayUtils;
import io.github.itzispyder.ogredupealias.utils.ServerUtils;
import io.github.itzispyder.ogredupealias.utils.Text;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import java.util.List;
public class StaffChatCommand implements TabExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
try {
String msg = String.join(" ", args);
ServerUtils.dmEachPlayer(p -> p.hasPermission("oda.commands.staffchat"), Text.builder()
.message("&7[&bStaffChat&7] &8>> &e" + msg)
.color()
.prefix()
.build());
}
catch (Exception ex) {
CmdExHandler handler = new CmdExHandler(ex,command);
sender.sendMessage(handler.getHelp());
}
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return new TabComplBuilder(sender, command, alias, args)
.add(1, ArrayUtils.toNewList(Bukkit.getOnlinePlayers(), Player::getName))
.build();
}
}

View File

@@ -1,6 +1,8 @@
package io.github.itzispyder.ogredupealias.data;
import io.github.itzispyder.ogredupealias.OgreDupeAlias;
import io.github.itzispyder.ogredupealias.utils.Text;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -90,6 +92,9 @@ public abstract class Config {
public static class Player {
private static final String path = "player.";
public static String firstJoinMessage() {
return Text.color(get().getString(path + "first-join-message","&e%player% has joined the game for their first time!"));
}
public static String joinMessage() {
return Text.color(get().getString(path + "join-message","&e%player% has joined the game"));
}

View File

@@ -0,0 +1,19 @@
package io.github.itzispyder.ogredupealias.events;
import io.github.itzispyder.ogredupealias.utils.ChatConstraints;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
public class ChatEventListener implements Listener {
@EventHandler
public void onChat(AsyncPlayerChatEvent e) {
final Player p = e.getPlayer();
final String msg = e.getMessage();
final ChatConstraints cc = new ChatConstraints(p,msg);
if (!cc.passAllChecks()) e.setCancelled(true);
}
}

View File

@@ -0,0 +1,26 @@
package io.github.itzispyder.ogredupealias.events;
import io.github.itzispyder.ogredupealias.data.Config;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class PlayerEventListener implements Listener {
@EventHandler
public void onJoin(PlayerJoinEvent e) {
final Player p = e.getPlayer();
e.setJoinMessage((p.hasPlayedBefore() ? Config.Player.joinMessage() : Config.Player.firstJoinMessage()).replaceAll("%player%",p.getDisplayName()));
Config.Player.onJoin().forEach(p::chat);
}
@EventHandler
public void onLeave(PlayerQuitEvent e) {
final Player p = e.getPlayer();
e.setQuitMessage(Config.Player.quitMessage().replaceAll("%player%",p.getDisplayName()));
}
}

View File

@@ -1,6 +1,7 @@
package io.github.itzispyder.ogredupealias.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
@@ -19,4 +20,14 @@ public abstract class ArrayUtils {
e.forEach(i -> list.add(a.apply(i)));
return list;
}
public static <T> String list2string(List<T> list) {
return Text.color("&7[&e" + String.join("&7, &e", ArrayUtils.toNewList(list, Object::toString)) + "&7]");
}
public static <T> List<T> bind(Iterable<T> tList, T... ts) {
List<T> list = Arrays.asList(ts);
tList.forEach(list::add);
return list;
}
}

View File

@@ -0,0 +1,168 @@
package io.github.itzispyder.ogredupealias.utils;
import io.github.itzispyder.ogredupealias.data.Config;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.entity.Player;
import java.util.*;
public class ChatConstraints {
private static final Map<String,Long> chatCooldown = new HashMap<>();
private static final Map<String,String> lastMessage = new HashMap<>();
private static boolean isChatMuted = false;
private final Player player;
private final String message;
public ChatConstraints(Player player, String message) {
this.player = player;
this.message = this.removeColors(message);
}
public boolean passAllChecks() {
return passChatMuted() && passRepeat() && passSwear() && passUnicode() && passSpam();
}
public boolean passChatMuted() {
if (!isChatMuted) return true;
if (player.hasPermission("oda.chat.bypass")) return true;
player.sendMessage(Text.builder()
.message("&cChat is currently muted! Please contact an administrator if you believe this is a mistake!")
.prefix()
.color()
.build());
return false;
}
public boolean passRepeat() {
if (!Config.Chat.AntiRepeat.enabled()) return true;
if (player.hasPermission("oda.chat.bypass.repeat")) return true;
if (lastMessage.containsKey(player.getName()) && isSimilar(message, lastMessage.get(player.getName()))) {
player.sendMessage(Text.builder("&cPlease do not repeat similar messages!")
.prefix()
.color()
.build());
return false;
}
lastMessage.put(player.getName(), message);
return true;
}
public boolean passSpam() {
if (!Config.Chat.AntiSpam.enabled()) return true;
if (player.hasPermission("oda.chat.bypass.spam")) return true;
if (chatCooldown.containsKey(player.getName()) && chatCooldown.get(player.getName()) > System.currentTimeMillis()) {
player.sendMessage(Text.builder("&cYou can chat again in &e" + getChatCooldown(player) + "&c seconds!")
.prefix()
.color()
.build());
return false;
}
int cooldownMillis = (int) (Config.Chat.AntiSpam.cooldown() * 1000);
chatCooldown.put(player.getName(), System.currentTimeMillis() + cooldownMillis);
return true;
}
public boolean passUnicode() {
if (!Config.Chat.AntiUnicode.enabled()) return true;
if (player.hasPermission("oda.chat.bypass.unicode")) return true;
String nonAllowed = message.replaceAll("[A-Za-z0-9\\[,./?><|\\]()*&^%$#@!~`{}:;'\"-_]","").trim();
if (nonAllowed.length() == 0) return true;
TextComponent text = new TextComponent();
text.setText(Text.builder(
"&cPlease do not send unsupported characters in chat!"
+ "\n&cMessage: &f" + message
+ "\n&cCaught: &e" + nonAllowed
).prefix()
.color()
.build());
text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Text.color(
"&cMessage: &f" + message
+ "\n&cCaught: &e" + nonAllowed
))));
player.spigot().sendMessage(text);
ServerUtils.forEachStaff(p -> {
p.spigot().sendMessage(text);
});
return false;
}
public boolean passSwear() {
if (!Config.Chat.AntiSwear.enabled()) return true;
if (player.hasPermission("oda.chat.bypass.swear")) return true;
String s = message.toLowerCase().replaceAll("[^a-z0-9]","");
String d = s;
List<String> caught = new ArrayList<>();
for (String whitelisted : Config.Chat.AntiSwear.whitelist()) {
s = s.replaceAll(whitelisted.toLowerCase(),"");
}
for (String blacklisted : Config.Chat.AntiSwear.blacklist()) {
if (s.contains(blacklisted.toLowerCase())) {
caught.add(blacklisted);
d = d.replaceAll(blacklisted, Text.color("&e" + blacklisted + "&f"));
}
}
if (caught.isEmpty()) return true;
String warn = ArrayUtils.list2string(caught);
TextComponent text = new TextComponent();
text.setText(Text.builder(
"&cPlease do not swear in chat!"
+ "\n&cMessage: &f" + d
+ "\n&cCaught: &e" + warn
).prefix()
.color()
.build());
text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Text.color(
"&cMessage: &f" + d
+ "\n&cCaught: &e" + warn
))));
player.spigot().sendMessage(text);
ServerUtils.forEachStaff(p -> {
p.spigot().sendMessage(text);
});
return false;
}
private String removeColors(String msg) {
return String.join(" ", Arrays.stream(msg.split(" "))
.filter(s -> !(s.length() >= 1 && s.charAt(0) == '§'))
.toList());
}
public double getChatCooldown() {
return getChatCooldown(player);
}
public static double getChatCooldown(Player p) {
if (!chatCooldown.containsKey(p.getName())) return 0.0;
if (chatCooldown.get(p.getName()) <= System.currentTimeMillis()) return 0.0;
return Math.floor((chatCooldown.get(p.getName()) - System.currentTimeMillis()) / 10.0) / 100.0;
}
private boolean isSimilar(String s1, String s2) {
float max = Math.max(s1.length(), s2.length());
float min = Math.min(s1.length(), s2.length());
double lengthRatio = min / max;
if (lengthRatio < 0.6) return false;
return s1.toLowerCase().contains(s2.toLowerCase()) || s2.toLowerCase().contains(s1.toLowerCase());
}
public static void setChatMuted(boolean muted) {
isChatMuted = muted;
}
public static boolean isChatMuted() {
return isChatMuted;
}
}

View File

@@ -0,0 +1,47 @@
package io.github.itzispyder.ogredupealias.utils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class ServerUtils {
public static List<Player> getPlayers() {
return new ArrayList<>(Bukkit.getOnlinePlayers());
}
public static List<Player> getStaff() {
return getPlayers().stream().filter(Player::isOp).toList();
}
public static void forEachPlayer(Consumer<Player> consumer) {
getPlayers().forEach(consumer);
}
public static void forEachStaff(Consumer<Player> consumer) {
getStaff().forEach(consumer);
}
public static void dmEachPlayer(Predicate<Player> condition, String dm) {
forEachPlayer(p -> {
if (condition.test(p)) p.sendMessage(dm);
});
}
public static void dmEachPlayer(String dm) {
forEachPlayer(p -> p.sendMessage(dm));
}
public static void forEachSpecified(Iterable<Player> players, Consumer<Player> consumer) {
players.forEach(consumer);
}
public static void forEachSpecified(Consumer<Player> consumer, Player... players) {
Arrays.stream(players).forEach(consumer);
}
}

View File

@@ -5,9 +5,9 @@ chat:
anti-swear:
enabled: true
whitelist:
- d
- glass
blacklist:
- d
- ass
anti-spam:
enabled: true
cooldown: 5
@@ -17,6 +17,7 @@ chat:
enabled: true
player:
first-join-message: "%player% has joined the game for their first time!"
join-message: "&e%player% has joined the game"
quit-message: "&e%player% has left the game"
on-join:

View File

@@ -6,7 +6,53 @@ prefix: ODA
authors: [ ImproperIssues, TheTrouper ]
description: Server utilities for OgreDupe.minehut.gg
website: https://itzispyder.github.io/
permissions:
oda.commands.config:
description: Able to manage config from in game
default: op
oda.commands.mutechat:
description: Able to mute chat
default: op
oda.commands.staffchat:
description: Access to staffchat.
default: op
oda.chat.bypass:
description: Bypass chat restrictions
default: op
children:
- oda.chat.bypass.swear
- oda.chat.bypass.spam
- oda.chat.bypass.repeat
- oda.chat.bypass.unicode
oda.chat.bypass.swear:
description: Bypass anti-swear
default: op
oda.chat.bypass.spam:
description: Bypass anti-spam
default: op
oda.chat.bypass.repeat:
description: Bypass anti-repeat
default: op
oda.chat.bypass.unicode:
description: Bypass anti-unicode
default: op
commands:
config:
description: Config management
usage: /config [get|set] <path> <datatype> <value>
usage: /config [get|set] <path> <datatype> <value>
permission: oda.commands.config
aliases:
- configuration
mutechat:
description: Mutes the chat
usage: /mutechat [true|false]
permission: oda.commands.mutechat
staffchat:
description: Staff chat
usage: /staffchat [<message>]
permission: oda.commands.staffchat
aliases:
- sc
- schat