Integrate ChatLogHandler across chat modules and add centralized message logging with validation through ChatLogMapper.

This commit is contained in:
2026-07-19 23:00:40 +02:00
parent 92979e9789
commit 7492dfa418
17 changed files with 418 additions and 115 deletions
@@ -35,11 +35,15 @@ public class ChatPlugin extends JavaPlugin {
instance = this;
ALogger.init(getSLF4JLogger());
chatAPI = new ChatImplementation();
chatHandler = new ChatHandler();
ChatLogHandler chatLogHandler = ChatLogHandler.getInstance(true);
chatHandler = new ChatHandler(chatLogHandler);
DatabaseConnection.initialize();
serverConfig = new ServerConfig(ServerName.getServerName());
ChatLogHandler chatLogHandler = ChatLogHandler.getInstance(true);
registerListener(new PlayerListener(serverConfig), new ChatListener(chatLogHandler), new BookListener(), new ShutdownListener(chatLogHandler, this));
registerListener(new PlayerListener(serverConfig),
new ChatListener(chatLogHandler),
new BookListener(),
new ShutdownListener(chatLogHandler, this)
);
if (serverConfig.GLOBALCHAT) {
registerCommand("globalchat", new GlobalChat());
registerCommand("toggleglobalchat", new ToggleGlobalChat());
@@ -58,12 +62,15 @@ public class ChatPlugin extends JavaPlugin {
if (!(channel instanceof CustomChannel customChannel)) {
continue;
}
this.getServer().getCommandMap().register(channel.getChannelName().toLowerCase(), new ChatChannel(customChannel));
this.getServer()
.getCommandMap()
.register(channel.getChannelName().toLowerCase(), new ChatChannel(customChannel));
}
String messageChannel = Config.MESSAGECHANNEL;
getServer().getMessenger().registerOutgoingPluginChannel(this, messageChannel);
getServer().getMessenger().registerIncomingPluginChannel(this, messageChannel, new PluginMessage());
getServer().getMessenger()
.registerIncomingPluginChannel(this, messageChannel, new PluginMessage(chatLogHandler));
NicknamesEvents nicknamesEvents = new NicknamesEvents();
getServer().getMessenger().registerIncomingPluginChannel(this, messageChannel, nicknamesEvents);
@@ -110,7 +117,9 @@ public class ChatPlugin extends JavaPlugin {
chatAPI.reloadConfig();
chatAPI.reloadChatFilters();
serverConfig = new ServerConfig(ServerName.getServerName());
Bukkit.broadcast(Utility.parseMiniMessage("Reloaded ChatPlugin Config.").asComponent(), "command.chat.reloadchat");
Bukkit.broadcast(Utility.parseMiniMessage("Reloaded ChatPlugin Config.").asComponent(),
"command.chat.reloadchat"
);
ALogger.info("Reloaded ChatPlugin config.");
}
}
@@ -8,6 +8,8 @@ import com.alttd.chat.objects.ChatFilter;
import com.alttd.chat.objects.ChatUser;
import com.alttd.chat.objects.ModifiableString;
import com.alttd.chat.objects.channels.CustomChannel;
import com.alttd.chat.objects.chat_log.ChatLogHandler;
import com.alttd.chat.objects.chat_log.ChatLogType;
import com.alttd.chat.util.ALogger;
import com.alttd.chat.util.GalaxyUtility;
import com.alttd.chat.util.ServerName;
@@ -28,6 +30,7 @@ import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jspecify.annotations.Nullable;
import java.util.List;
import java.util.Objects;
@@ -40,8 +43,10 @@ public class ChatHandler {
private final ChatPlugin plugin;
private final ComponentLike GCNOTENABLED;
private final ChatLogHandler chatLogHandler;
public ChatHandler() {
public ChatHandler(ChatLogHandler chatLogHandler) {
this.chatLogHandler = chatLogHandler;
plugin = ChatPlugin.getInstance();
GCNOTENABLED = Utility.parseMiniMessage(Config.GCNOTENABLED);
}
@@ -54,7 +59,7 @@ public class ChatHandler {
Placeholder.component("message", parseMessageContent(player, message)),
Placeholder.component("sendername", player.name()),
Placeholder.parsed("receivername", target)
);
);
ComponentLike component = Utility.parseMiniMessage("<message>", placeholders);
@@ -62,9 +67,10 @@ public class ChatHandler {
// todo a better way for this
if (!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, "privatemessage")) {
GalaxyUtility.sendBlockedNotification("DM Language",
player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
target);
player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
target
);
return; // the message was blocked
}
@@ -73,7 +79,8 @@ public class ChatHandler {
sendPrivateMessage(player, target, "privatemessage", component.asComponent());
ComponentLike spymessage = Utility.parseMiniMessage(Config.MESSAGESPY, placeholders);
for (Player pl : Bukkit.getOnlinePlayers()) {
if (pl.hasPermission(Config.SPYPERMISSION) && ChatUserManager.getChatUser(pl.getUniqueId()).isSpy() && !pl.equals(player) && !pl.getName().equalsIgnoreCase(target)) {
if (pl.hasPermission(Config.SPYPERMISSION) && ChatUserManager.getChatUser(pl.getUniqueId())
.isSpy() && !pl.equals(player) && !pl.getName().equalsIgnoreCase(target)) {
pl.sendMessage(spymessage);
}
}
@@ -88,15 +95,16 @@ public class ChatHandler {
Placeholder.component("message", messageComponent),
Placeholder.component("sendername", player.name()),
Placeholder.parsed("receivername", target)
);
);
ModifiableString modifiableString = new ModifiableString(messageComponent);
// todo a better way for this
if (!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, "privatemessage")) {
GalaxyUtility.sendBlockedNotification("DM Language",
player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
target);
player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
target
);
return; // the message was blocked
}
@@ -108,7 +116,8 @@ public class ChatHandler {
sendPrivateMessage(player, target, "privatemessage", messageComponent);
ComponentLike spymessage = Utility.parseMiniMessage(Config.MESSAGESPY, placeholders);
for (Player pl : Bukkit.getOnlinePlayers()) {
if (pl.hasPermission(Config.SPYPERMISSION) && ChatUserManager.getChatUser(pl.getUniqueId()).isSpy() && !pl.equals(player) && !pl.getName().equalsIgnoreCase(target)) {
if (pl.hasPermission(Config.SPYPERMISSION) && ChatUserManager.getChatUser(pl.getUniqueId())
.isSpy() && !pl.equals(player) && !pl.getName().equalsIgnoreCase(target)) {
pl.sendMessage(spymessage);
}
}
@@ -127,7 +136,9 @@ public class ChatHandler {
long timeLeft = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - user.getGcCooldown());
if (timeLeft <= Config.GCCOOLDOWN && !player.hasPermission("chat.globalchat.cooldownbypass")) { // player is on cooldown and should wait x seconds
player.sendRichMessage(Config.GCONCOOLDOWN, Placeholder.parsed("cooldown", Config.GCCOOLDOWN - timeLeft + ""));
player.sendRichMessage(Config.GCONCOOLDOWN,
Placeholder.parsed("cooldown", Config.GCCOOLDOWN - timeLeft + "")
);
return;
}
@@ -138,7 +149,7 @@ public class ChatHandler {
Placeholder.component("prefix", prefix),
Placeholder.component("message", parseMessageContent(player, message)),
Placeholder.parsed("server", ServerName.getServerName())
);
);
Component component = Utility.parseMiniMessage(Config.GCFORMAT, placeholders).asComponent();
@@ -146,13 +157,24 @@ public class ChatHandler {
// todo a better way for this
if (!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, "globalchat")) {
GalaxyUtility.sendBlockedNotification("GC Language",
player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
"");
player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
""
);
return; // the message was blocked
}
component = modifiableString.component();
chatLogHandler.addChatLog(player.getUniqueId(),
Bukkit.getServerName(),
message,
ChatLogType.GLOBAL,
null,
null,
component,
false
);
user.setGcCooldown(System.currentTimeMillis());
sendPluginMessage(player, "globalchat", component);
}
@@ -176,15 +198,20 @@ public class ChatHandler {
Placeholder.component("message", parseMessageContent(player, message)),
Placeholder.parsed("server", ServerName.getServerName()),
Placeholder.parsed("channel", channel.getChannelName())
);
);
Component component = Utility.parseMiniMessage(channel.getFormat(), placeholders).asComponent();
ModifiableString modifiableString = new ModifiableString(component);
if (!RegexManager.filterText(player.getName(), player.getUniqueId(), modifiableString, channel.getChannelName())) {
if (!RegexManager.filterText(player.getName(),
player.getUniqueId(),
modifiableString,
channel.getChannelName()
)) {
GalaxyUtility.sendBlockedNotification(channel.getChannelName() + " Language",
player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
"");
player,
Utility.parseMiniMessage(Utility.parseColors(modifiableString.string())),
""
);
ALogger.info("Refusing to send blocked chat message");
return;
}
@@ -205,7 +232,7 @@ public class ChatHandler {
out.writeUTF(message);
out.writeUTF(GsonComponentSerializer.gson().serialize(
itemComponent(player.getInventory().getItemInMainHand())
));
));
player.sendPluginMessage(plugin, Config.MESSAGECHANNEL, out.toByteArray());
// if (isMuted(player, message, "[" + party.getPartyName() + " Muted] ")) return;
@@ -255,16 +282,20 @@ public class ChatHandler {
if (!chatChannel.getServers().contains(ServerName.getServerName())) {
player.sendRichMessage("<red>Unable to send messages to <channel> in this server.</red>",
Placeholder.parsed("channel", chatChannel.getChannelName()));
Placeholder.parsed("channel", chatChannel.getChannelName())
);
ALogger.info(String.format("Not sending chat message due to [%s] not being in this channels config",
ServerName.getServerName()));
ServerName.getServerName()
));
return;
}
Stream<? extends Player> stream = Bukkit.getServer().getOnlinePlayers().stream()
.filter(p -> p.hasPermission(chatChannel.getPermission()));
if (!player.hasPermission("chat.ignorebypass")) {
stream = stream.filter(receiver -> !ChatUserManager.getChatUser(receiver.getUniqueId()).getIgnoredPlayers().contains(uuid)
stream = stream.filter(receiver -> !ChatUserManager.getChatUser(receiver.getUniqueId())
.getIgnoredPlayers()
.contains(uuid)
|| receiver.hasPermission("chat.ignorebypass"));
}
if (chatChannel.isLocal()) {
@@ -283,14 +314,39 @@ public class ChatHandler {
List<? extends Player> recipientPlayers = stream.toList();
recipientPlayers.forEach(p -> p.sendMessage(component));
chatLogHandler.addChatLog(player.getUniqueId(),
Bukkit.getServerName(),
message,
ChatLogType.CUSTOM,
chatChannel.getChannelName(),
getLocationIfLocal(chatChannel, player),
component.asComponent(),
false
);
List<UUID> recipientUUIDs = recipientPlayers.stream().map(Entity::getUniqueId).toList();
Bukkit.getServer().getOnlinePlayers().stream()
.filter(onlinePlayer -> onlinePlayer.hasPermission(Config.SPYPERMISSION))
.filter(onlinePlayer -> !recipientUUIDs.contains(onlinePlayer.getUniqueId()))
.forEach(onlinePlayer -> onlinePlayer.sendRichMessage(Config.CHANNEL_SPY,
Placeholder.component("sender", player.name()),
Placeholder.parsed("channel", chatChannel.getChannelName()),
Placeholder.parsed("message", message)));
Placeholder.component("sender", player.name()),
Placeholder.parsed("channel", chatChannel.getChannelName()),
Placeholder.parsed("message", message)
));
}
private static @Nullable String getLocationIfLocal(CustomChannel chatChannel, Player player) {
if (!chatChannel.isLocal()) {
return null;
}
String format = String.format("%s;%s",
player.getLocation().getBlockX(),
player.getLocation().getBlockZ()
);
if (format.length() > 36) {
return null;
}
return format;
}
private void sendPluginMessage(Player player, String channel, Component component) {
@@ -326,9 +382,14 @@ public class ChatHandler {
if (user == null) {
return false;
}
if (user.isMuted() || (ChatPlugin.getInstance().serverMuted() && !player.hasPermission("chat.bypass-server-muted"))) {
if (user.isMuted() || (ChatPlugin.getInstance().serverMuted() && !player.hasPermission(
"chat.bypass-server-muted"))) {
// if (Database.get().isPlayerMuted(player.getUniqueId(), null) || (ChatPlugin.getInstance().serverMuted() && !player.hasPermission("chat.bypass-server-muted"))) {
GalaxyUtility.sendBlockedNotification(prefix, player, Utility.parseMiniMessage(Utility.stripTokens(message)), "");
GalaxyUtility.sendBlockedNotification(prefix,
player,
Utility.parseMiniMessage(Utility.stripTokens(message)),
""
);
return true;
}
return false;
@@ -7,6 +7,7 @@ import com.alttd.chat.managers.ChatUserManager;
import com.alttd.chat.managers.RegexManager;
import com.alttd.chat.objects.*;
import com.alttd.chat.objects.chat_log.ChatLogHandler;
import com.alttd.chat.objects.chat_log.ChatLogType;
import com.alttd.chat.util.ALogger;
import com.alttd.chat.util.GalaxyUtility;
import com.alttd.chat.util.ServerName;
@@ -129,6 +130,9 @@ public class ChatListener implements Listener {
chatLogHandler.addChatLog(uuid,
ServerName.getServerName(),
originalMessage,
ChatLogType.PUBLIC,
null,
null,
render(player, inputComponent).asComponent(),
true
);
@@ -162,6 +166,9 @@ public class ChatListener implements Listener {
chatLogHandler.addChatLog(uuid,
ServerName.getServerName(),
modifiableString.string(),
ChatLogType.PUBLIC,
null,
null,
input.asComponent(),
false
);
@@ -10,6 +10,8 @@ import com.alttd.chat.objects.Party;
import com.alttd.chat.objects.PartyUser;
import com.alttd.chat.objects.channels.Channel;
import com.alttd.chat.objects.channels.CustomChannel;
import com.alttd.chat.objects.chat_log.ChatLogHandler;
import com.alttd.chat.objects.chat_log.ChatLogType;
import com.alttd.chat.util.ALogger;
import com.alttd.chat.util.ServerName;
import com.alttd.chat.util.Utility;
@@ -18,6 +20,7 @@ import com.google.common.io.ByteStreams;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
@@ -29,6 +32,12 @@ import java.util.UUID;
public class PluginMessage implements PluginMessageListener {
private final ChatLogHandler chatLogHandler;
public PluginMessage(ChatLogHandler chatLogHandler) {
this.chatLogHandler = chatLogHandler;
}
@Override
public void onPluginMessageReceived(String channel, @NotNull Player ignored, byte[] bytes) {
if (!channel.equals(Config.MESSAGECHANNEL)) {
@@ -48,13 +57,25 @@ public class PluginMessage implements PluginMessageListener {
}
ChatUser chatUser = ChatUserManager.getChatUser(uuid);
if (isTargetNotIgnored(chatUser, targetuuid)) {
player.sendMessage(GsonComponentSerializer.gson().deserialize(message));
Component component = GsonComponentSerializer.gson().deserialize(message);
player.sendMessage(component);
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1,
1); // todo load this from config
1
); // todo load this from config
ChatUser user = ChatUserManager.getChatUser(uuid);
if (!user.getReplyContinueTarget().equalsIgnoreCase(target)) {
user.setReplyTarget(target);
}
// Handled here since this is after the ignore check and is only send once
chatLogHandler.addChatLog(uuid,
ServerName.getServerName(),
PlainTextComponentSerializer.plainText().serialize(component),
ChatLogType.MSG,
null,
player.getUniqueId().toString(),
component,
false
);
}
}
case "privatemessageout" -> {
@@ -69,9 +90,18 @@ public class PluginMessage implements PluginMessageListener {
ChatUser chatUser = ChatUserManager.getChatUser(uuid);
if (isTargetNotIgnored(chatUser, targetuuid)) {
chatUser.setReplyTarget(target);
player.sendMessage(GsonComponentSerializer.gson().deserialize(message));
// ChatUser user = ChatUserManager.getChatUser(uuid);
// user.setReplyTarget(target);
Component component = GsonComponentSerializer.gson().deserialize(message);
player.sendMessage(component);
// Handled here since this is after the ignore check and is only send once
chatLogHandler.addChatLog(uuid,
ServerName.getServerName(),
PlainTextComponentSerializer.plainText().serialize(component),
ChatLogType.MSG,
null,
player.getUniqueId().toString(),
component,
false
);
}
}
case "globalchat" -> {
@@ -82,10 +112,11 @@ public class PluginMessage implements PluginMessageListener {
UUID uuid = UUID.fromString(in.readUTF());
String message = in.readUTF();
Component component = GsonComponentSerializer.gson().deserialize(message);
Bukkit.getOnlinePlayers().stream().filter(p -> p.hasPermission(Config.GCPERMISSION)).forEach(p -> {
ChatUser chatUser = ChatUserManager.getChatUser(p.getUniqueId());
if (isTargetNotIgnored(chatUser, uuid)) {
p.sendMessage(GsonComponentSerializer.gson().deserialize(message));
p.sendMessage(component);
}
});
}
@@ -107,6 +138,7 @@ public class PluginMessage implements PluginMessageListener {
}
chatChannel(in);
//TODO [Stijn] [2026-07-19]: handle custom channels
}
case "tmppartyupdate" -> {
int id = Integer.parseInt(in.readUTF());