package xyz.etztech.qol.listeners; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.TextComponent; import org.apache.commons.lang.StringUtils; import org.bukkit.GameMode; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.server.ServerCommandEvent; import org.dynmap.DynmapAPI; import xyz.etztech.core.web.CoreWeb; import xyz.etztech.qol.QoL; import xyz.etztech.qol.other.LinkCommand; import java.util.*; public class CommandPreprocessListener implements Listener { QoL plugin; private Map confirmMap = new HashMap<>(); private Map dynmapVisibleStatusMap = new HashMap<>(); public CommandPreprocessListener(QoL plugin) { this.plugin = plugin; plugin.getServer().getPluginManager().registerEvents(this, plugin); } @EventHandler public void onServerCommand(ServerCommandEvent event) { if (plugin.getConfig().getBoolean("audit.enabled")) { String command = event.getCommand(); if (commandIsAuditable(command)) { sendAuditWebhook("Console", null, command); } } } @EventHandler public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { String command = event.getMessage(); String base = command.split(" ")[0].substring(1).toLowerCase(); // Strip the slash Player sender = event.getPlayer(); DynmapAPI dynmap = plugin.getDynmap(); // Spec dynmap hide if (base.equals("spec") && sender.hasPermission("SafeSpectate.spectate") && dynmap != null) { String message; boolean visibleStatus; if (sender.getGameMode() != GameMode.SPECTATOR){ dynmapVisibleStatusMap.put(sender.getUniqueId(), dynmap.getPlayerVisbility(sender.getName())); visibleStatus = false; message = "You are now being hidden on Dynmap."; } else if (dynmapVisibleStatusMap.containsKey(sender.getUniqueId())){ visibleStatus = dynmapVisibleStatusMap.remove(sender.getUniqueId()); String status = ((visibleStatus) ? "shown" : "hidden"); message = "Your " + status + " status has been restored on Dynmap."; } else { message = "You are now visible on the Dynmap."; visibleStatus = true; } TextComponent textComponent = new TextComponent(message); textComponent.setColor(ChatColor.GREEN); sender.spigot().sendMessage(textComponent); dynmap.setPlayerVisiblity(sender.getName(), visibleStatus); } // Spec confirmation List specConfirm = plugin.getConfig().getStringList("spec-confirm"); if (sender.hasPermission("qol.specconfirm")) { boolean confirm = false; for (String confirmable : specConfirm) { // If the player command either starts with a confirmable command and space (meaning confirmation is needed regardless of arguments) // Or the player command is a full match to the confirmable command if (noSlash(command).toLowerCase().startsWith(confirmable.toLowerCase() + " ") || noSlash(command).toLowerCase().equals(confirmable.toLowerCase())) { confirm = true; } } //check if the command is a spec confirm command if (confirm) { //If the user is in the confirm map, remove them and let the command run if (command.equals(confirmMap.get(sender.getUniqueId()))) { confirmMap.remove(sender.getUniqueId()); } //If the user is running the command for the first time outside of spec else if (sender.getGameMode() != GameMode.SPECTATOR) { //Cancel the command event.setCancelled(true); //Add the user to the spec confirm map confirmMap.put(sender.getUniqueId(), command); TextComponent message = new TextComponent("You are running this command out of spec, run again to confirm."); message.setColor(ChatColor.GREEN); sender.spigot().sendMessage(message); } } } // Command Auditing if (sender.hasPermission("qol.auditable") && plugin.getConfig().getBoolean("audit.enabled")) { if (sender.hasPermission("qol.auditor") && targetIsAuditable(command)) { return; } else { if (commandIsAuditable(command)) { sendAuditWebhook(sender.getName(), sender.getGameMode(), command); } } } // Links for (LinkCommand linkCommand : QoL.getLinks()) { if (base.equalsIgnoreCase(linkCommand.getCommand())) { event.setCancelled(true); TextComponent link = new TextComponent(linkCommand.getMessage()); link.setColor(ChatColor.GREEN); link.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, linkCommand.getUrl())); sender.spigot().sendMessage(link); return; } } } public boolean commandIsAuditable(String command) { for (String audit : QoL.getAudits()) { if (noSlash(command).startsWith(noSlash(audit))) { return true; } } return false; } public void sendAuditWebhook(String commandSource, GameMode gamemode, String command) { String content = ""; if (gamemode != null) { content += "[" + StringUtils.capitalize(gamemode.name().toLowerCase()) + "] "; } content += commandSource + " executed command: " + command; sendWebhook("QoL Auditor", content); } public void sendWebhook(String username, String content) { String webhook = plugin.getConfig().getString("audit.webhook"); if (StringUtils.isNotEmpty(webhook)) { Map post = new HashMap<>(); post.put("username", username); post.put("content", content); CoreWeb.asyncPost(plugin, webhook, post); } } public boolean targetIsAuditable(String command) { String[] commandSplit = command.split(" "); Collection players = plugin.getServer().getOnlinePlayers(); for (String param : commandSplit) { String lowerCaseParam = param.toLowerCase(); for (Player p : players) { if (p.getName().toLowerCase().equals(lowerCaseParam)) { return p.hasPermission("qol.auditable"); } } } return false; } public String noSlash(String command) { return command.startsWith("/") ? command.substring(1) : command; } }