This commit is contained in:
Telesphoreo 2022-04-08 21:23:38 -05:00
commit a58b6fbba8
12 changed files with 295 additions and 8 deletions

View File

@ -8,6 +8,7 @@ import dev.plex.cache.player.PlayerCache;
import dev.plex.cache.player.SQLPlayerData; import dev.plex.cache.player.SQLPlayerData;
import dev.plex.cache.sql.SQLNotes; import dev.plex.cache.sql.SQLNotes;
import dev.plex.cache.sql.SQLPunishment; import dev.plex.cache.sql.SQLPunishment;
import dev.plex.command.blocker.CommandBlockerManager;
import dev.plex.config.Config; import dev.plex.config.Config;
import dev.plex.handlers.CommandHandler; import dev.plex.handlers.CommandHandler;
import dev.plex.handlers.ListenerHandler; import dev.plex.handlers.ListenerHandler;
@ -44,6 +45,7 @@ public class Plex extends JavaPlugin
public Config config; public Config config;
public Config messages; public Config messages;
public Config indefBans; public Config indefBans;
public Config blockedCommands;
public File modulesFolder; public File modulesFolder;
private StorageType storageType = StorageType.SQLITE; private StorageType storageType = StorageType.SQLITE;
@ -62,6 +64,7 @@ public class Plex extends JavaPlugin
private RankManager rankManager; private RankManager rankManager;
private ServiceManager serviceManager; private ServiceManager serviceManager;
private PunishmentManager punishmentManager; private PunishmentManager punishmentManager;
private CommandBlockerManager commandBlockerManager;
private AdminList adminList; private AdminList adminList;
private UpdateChecker updateChecker; private UpdateChecker updateChecker;
@ -79,6 +82,7 @@ public class Plex extends JavaPlugin
config = new Config(this, "config.yml"); config = new Config(this, "config.yml");
messages = new Config(this, "messages.yml"); messages = new Config(this, "messages.yml");
indefBans = new Config(this, "indefbans.yml"); indefBans = new Config(this, "indefbans.yml");
blockedCommands = new Config(this, "commands.yml");
build.load(this); build.load(this);
modulesFolder = new File(this.getDataFolder() + File.separator + "modules"); modulesFolder = new File(this.getDataFolder() + File.separator + "modules");
@ -99,6 +103,7 @@ public class Plex extends JavaPlugin
messages.load(); messages.load();
// Don't add default entries to indefinite ban file // Don't add default entries to indefinite ban file
indefBans.load(false); indefBans.load(false);
blockedCommands.load();
sqlConnection = new SQLConnection(); sqlConnection = new SQLConnection();
mongoConnection = new MongoConnection(); mongoConnection = new MongoConnection();
@ -158,6 +163,9 @@ public class Plex extends JavaPlugin
punishmentManager.mergeIndefiniteBans(); punishmentManager.mergeIndefiniteBans();
PlexLog.log("Punishment System initialized"); PlexLog.log("Punishment System initialized");
commandBlockerManager = new CommandBlockerManager();
PlexLog.log("Command Blocker initialized");
generateWorlds(); generateWorlds();
serviceManager = new ServiceManager(); serviceManager = new ServiceManager();

View File

@ -0,0 +1,22 @@
package dev.plex.command.blocker;
import dev.plex.rank.enums.Rank;
import lombok.Getter;
@Getter
public class BaseCommand
{
private final Rank rank;
private final String message;
public BaseCommand(Rank r, String m)
{
rank = r;
message = m;
}
public String toString()
{
return "BaseCommand (Rank: " + (rank == null ? "ALL" : rank.name()) + ", Message: " + message + ")";
}
}

View File

@ -0,0 +1,108 @@
package dev.plex.command.blocker;
import dev.plex.Plex;
import dev.plex.PlexBase;
import dev.plex.rank.enums.Rank;
import dev.plex.util.PlexLog;
import dev.plex.util.PlexUtils;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.PluginCommandYamlParser;
import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
@Getter
public class CommandBlockerManager extends PlexBase
{
private List<BaseCommand> blockedCommands = new ArrayList<>();
public boolean loadedYet;
public void syncCommands()
{
loadedYet = false;
blockedCommands.clear();
List<String> raw = plugin.blockedCommands.getStringList("blockedCommands");
for (String cmd : raw)
{
int lastDelim = cmd.lastIndexOf(':');
String cmdWithoutMsg = cmd.substring(0, lastDelim);
String[] rawPieces = cmdWithoutMsg.split(":", 3);
String rawType = rawPieces[0].toLowerCase();
String rawRank = rawPieces[1].toLowerCase();
String regexOrMatch = rawPieces[2];
String message = cmd.substring(lastDelim + 1);
if (message.equals("_"))
{
message = PlexUtils.messageString("commandBlocked");
}
Rank rank = switch (rawRank)
{
case "e" -> null;
case "a" -> Rank.ADMIN;
case "s" -> Rank.SENIOR_ADMIN;
default -> null;
};
if (rawType.equals("r"))
{
blockedCommands.add(new RegexCommand(Pattern.compile(regexOrMatch, Pattern.CASE_INSENSITIVE), rank, message));
}
else if (rawType.equals("m"))
{
int ind = regexOrMatch.indexOf(' ');
if (ind == -1 && regexOrMatch.endsWith(":"))
{
String pluginName = regexOrMatch.substring(0, regexOrMatch.length() - 1);
Plugin plugin = Arrays.stream(Bukkit.getServer().getPluginManager().getPlugins()).filter(pl -> pl.getName().equalsIgnoreCase(pluginName)).findAny().orElse(null);
if (plugin != null)
{
List<Command> commandList = PluginCommandYamlParser.parse(plugin);
for (Command command : commandList)
{
blockedCommands.add(new MatchCommand(command.getName(), rank, message));
blockedCommands.add(new MatchCommand(pluginName + ":" + command.getName(), rank, message));
for (String alias : command.getAliases())
{
blockedCommands.add(new MatchCommand(alias, rank, message));
blockedCommands.add(new MatchCommand(pluginName + ":" + alias, rank, message));
}
}
}
}
String blockedArgs = ind == -1 ? "" : regexOrMatch.substring(ind + 1);
if (!blockedArgs.isEmpty())
{
blockedArgs = " " + blockedArgs; // necessary in case no args
}
PluginCommand pluginCommand = Plex.get().getServer().getPluginCommand(ind == -1 ? regexOrMatch : regexOrMatch.substring(0, ind));
if (pluginCommand != null)
{
String pluginName = pluginCommand.getPlugin().getName();
blockedCommands.add(new MatchCommand(pluginCommand.getName() + blockedArgs, rank, message));
blockedCommands.add(new MatchCommand(pluginName + ":" + pluginCommand.getName() + blockedArgs, rank, message));
List<String> aliases = pluginCommand.getAliases();
for (String alias : aliases)
{
blockedCommands.add(new MatchCommand(alias + blockedArgs, rank, message));
blockedCommands.add(new MatchCommand(pluginName + ":" + alias + blockedArgs, rank, message));
}
}
}
}
loadedYet = true;
}
}

View File

@ -0,0 +1,21 @@
package dev.plex.command.blocker;
import dev.plex.rank.enums.Rank;
import lombok.Getter;
@Getter
public class MatchCommand extends BaseCommand
{
private final String match;
public MatchCommand(String r1, Rank r2, String m1)
{
super(r2, m1);
match = r1;
}
public String toString()
{
return "MatchCommand (Rank: " + (getRank() == null ? "ALL" : getRank().name()) + ", Match: " + match + ", Message: " + getMessage() + ")";
}
}

View File

@ -0,0 +1,23 @@
package dev.plex.command.blocker;
import dev.plex.rank.enums.Rank;
import lombok.Getter;
import java.util.regex.Pattern;
@Getter
public class RegexCommand extends BaseCommand
{
private final Pattern regex;
public RegexCommand(Pattern r1, Rank r2, String m1)
{
super(r2, m1);
regex = r1;
}
public String toString()
{
return "RegexCommand (Rank: " + (getRank() == null ? "ALL" : getRank().name()) + ", Regex: " + regex.toString() + ", Message: " + getMessage() + ")";
}
}

View File

@ -18,6 +18,7 @@ import dev.plex.util.PlexLog;
import dev.plex.util.PlexUtils; import dev.plex.util.PlexUtils;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -51,13 +52,16 @@ public class PlexCMD extends PlexCommand
plugin.indefBans.load(false); plugin.indefBans.load(false);
plugin.getPunishmentManager().mergeIndefiniteBans(); plugin.getPunishmentManager().mergeIndefiniteBans();
send(sender, "Reloaded indefinite bans"); send(sender, "Reloaded indefinite bans");
plugin.blockedCommands.load();
plugin.getCommandBlockerManager().syncCommands();
send(sender, "Reloaded blocked commands file");
plugin.getRankManager().importDefaultRanks(); plugin.getRankManager().importDefaultRanks();
send(sender, "Imported ranks"); send(sender, "Imported ranks");
send(sender, "Plex successfully reloaded.");
plugin.setSystem(plugin.config.getString("system")); plugin.setSystem(plugin.config.getString("system"));
plugin.getServiceManager().endServices(); plugin.getServiceManager().endServices();
plugin.getServiceManager().startServices(); plugin.getServiceManager().startServices();
PlexLog.debug("Restarted services"); PlexLog.debug("Restarted services");
send(sender, "Plex successfully reloaded.");
return null; return null;
} }
else if (args[0].equalsIgnoreCase("redis")) else if (args[0].equalsIgnoreCase("redis"))

View File

@ -1,7 +1,14 @@
package dev.plex.listener.impl; package dev.plex.listener.impl;
import dev.plex.cache.DataUtils;
import dev.plex.cache.player.PlayerCache; import dev.plex.cache.player.PlayerCache;
import dev.plex.command.blocker.BaseCommand;
import dev.plex.command.blocker.MatchCommand;
import dev.plex.command.blocker.RegexCommand;
import dev.plex.listener.PlexListener; import dev.plex.listener.PlexListener;
import dev.plex.player.PlexPlayer;
import dev.plex.util.PlexUtils;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -23,5 +30,44 @@ public class CommandListener extends PlexListener
pl.sendMessage(ChatColor.GRAY + player.getName() + ": " + command); pl.sendMessage(ChatColor.GRAY + player.getName() + ": " + command);
} }
}); });
if (!plugin.getCommandBlockerManager().loadedYet)
{
event.setCancelled(true);
return;
}
Player player = event.getPlayer();
String message = event.getMessage().substring(1).stripLeading(); // stripLeading() is VITAL for workaround blocking (/ minecraft:summon)
for (BaseCommand blockedCommand : plugin.getCommandBlockerManager().getBlockedCommands())
{
PlexPlayer plexPlayer = DataUtils.getPlayer(player.getUniqueId());
if (blockedCommand.getRank() != null && plexPlayer.getRankFromString().isAtLeast(blockedCommand.getRank()))
{
continue;
}
boolean isBlocked = false;
if (blockedCommand instanceof RegexCommand regexCommand)
{
if (regexCommand.getRegex().matcher(message).lookingAt())
{
isBlocked = true;
}
}
else if (blockedCommand instanceof MatchCommand matchCommand)
{
if (message.toLowerCase().startsWith(matchCommand.getMatch().toLowerCase()))
{
isBlocked = true;
}
}
if (isBlocked)
{
event.setCancelled(true);
//PlexLog.debug("Command blocked.");
player.sendMessage(MiniMessage.miniMessage().deserialize(PlexUtils.messageString("blockedCommandColor") + blockedCommand.getMessage()));
return;
}
}
} }
} }

View File

@ -98,7 +98,7 @@ public class PlexPlayer
public Rank getRankFromString() public Rank getRankFromString()
{ {
OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
if (rank.isEmpty()) if (rank.isEmpty() || !isAdminActive())
{ {
if (player.isOp()) if (player.isOp())
{ {

View File

@ -2,10 +2,7 @@ package dev.plex.services;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import dev.plex.Plex; import dev.plex.Plex;
import dev.plex.services.impl.AutoWipeService; import dev.plex.services.impl.*;
import dev.plex.services.impl.BanService;
import dev.plex.services.impl.GameRuleService;
import dev.plex.services.impl.UpdateCheckerService;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
@ -21,6 +18,7 @@ public class ServiceManager
registerService(new GameRuleService()); registerService(new GameRuleService());
registerService(new UpdateCheckerService()); registerService(new UpdateCheckerService());
registerService(new AutoWipeService()); registerService(new AutoWipeService());
registerService(new CommandBlockerService());
} }
public void startServices() public void startServices()
@ -45,7 +43,16 @@ public class ServiceManager
{ {
if (!service.isRepeating()) if (!service.isRepeating())
{ {
BukkitTask task = Bukkit.getScheduler().runTask(Plex.get(), service::run); int time = service.repeatInSeconds();
BukkitTask task;
if (time == 0)
{
task = Bukkit.getScheduler().runTask(Plex.get(), service::run);
}
else
{
task = Bukkit.getScheduler().runTaskLater(Plex.get(), service::run, time);
}
service.setTaskId(task.getTaskId()); service.setTaskId(task.getTaskId());
} }
else if (service.isRepeating() && service.isAsynchronous()) else if (service.isRepeating() && service.isAsynchronous())

View File

@ -0,0 +1,25 @@
package dev.plex.services.impl;
import dev.plex.services.AbstractService;
import dev.plex.util.PlexLog;
public class CommandBlockerService extends AbstractService
{
public CommandBlockerService()
{
super(false, true);
}
@Override
public void run()
{
plugin.getCommandBlockerManager().syncCommands();
PlexLog.log("Command Blocker commands loaded");
}
@Override
public int repeatInSeconds()
{
return 0;
}
}

View File

@ -0,0 +1,21 @@
#
# Command Blocker
#
# Format:
# - "<regex or match>:<rank>:command name no slash:Block message"
#
# Symbols to use:
# - r for RegEx
# - m for matching
# - The ranks are "e" for everyone, "s" for senior admin, and "a" for admin
# - MATCHING MODE: The command is just the command without slashes. Optional arguments are specified as well. It also accepts full plugins via specifying the plugin name followed by a ":" (e.g. "viaversion:")
# - REGEX MODE: The command is regex that matches the desired command. It matches case insensitively.
# - Finally the block message. MUST NOT CONTAIN ":". Use _ to use the default command blocked message as specified in messages.yml, or you can optionally put your own in
#
# So these would be valid:
# - "m:e:mail sendall:You cannot send messages to everyone on the server"
# - "r:e:(.*:):Plugin specific commands are disabled"
blockedCommands:
- "r:e:^[^ :]+::Plugin specific commands are disabled."
- "m:e:mail sendall:You cannot send messages to everyone on the server."
- "m:e:mail sendtempall:You cannot send messages to everyone on the server."

View File

@ -166,4 +166,6 @@ noRemovedEntities: "<gray>No entities were removed."
removedMobs: "<red>{0} - Removed {1} mobs" removedMobs: "<red>{0} - Removed {1} mobs"
autoWipeDisabled: "<gray>Item wiping is currently disabled in the config!" autoWipeDisabled: "<gray>Item wiping is currently disabled in the config!"
allowDropsDisabled: "<gray>No longer allowing drops from players." allowDropsDisabled: "<gray>No longer allowing drops from players."
allowDropsEnabled: "<gray>Now allowing drops from players." allowDropsEnabled: "<gray>Now allowing drops from players."
blockedCommandColor: "<gray>"
commandBlocked: "That command is blocked."