diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/TempWarnCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/TempWarnCommand.java index ba7413f5..53b573ce 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/TempWarnCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/TempWarnCommand.java @@ -176,8 +176,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser final List actionCommands; try { - actionCommands = getPlugin().getConfig().getWarningActions() - .getCommand((int) getPlugin().getPlayerWarnStorage().getPointsCount(player)); + actionCommands = getPlugin().getConfig().getWarningActions().getCommands(player, getPlugin().getPlayerWarnStorage().getPointsCount(player)); } catch (SQLException e) { e.printStackTrace(); return; diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/WarnCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/WarnCommand.java index d1fe51c4..9a272114 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/WarnCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/WarnCommand.java @@ -155,8 +155,7 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser final List actionCommands; try { - actionCommands = getPlugin().getConfig().getWarningActions() - .getCommand(getPlugin().getPlayerWarnStorage().getPointsCount(player)); + actionCommands = getPlugin().getConfig().getWarningActions().getCommands(player, getPlugin().getPlayerWarnStorage().getPointsCount(player)); } catch (SQLException e) { e.printStackTrace(); return; @@ -182,4 +181,4 @@ public boolean onCommand(final CommonSender sender, CommandParser originalParser return true; } -} \ No newline at end of file +} diff --git a/common/src/main/java/me/confuser/banmanager/common/configs/ActionCommand.java b/common/src/main/java/me/confuser/banmanager/common/configs/ActionCommand.java index c15f2681..490d2153 100644 --- a/common/src/main/java/me/confuser/banmanager/common/configs/ActionCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/configs/ActionCommand.java @@ -8,9 +8,12 @@ public class ActionCommand { private final String command; @Getter private final long delay; + @Getter + private final String pointsTimeframe; - public ActionCommand(String command, long delay) { + public ActionCommand(String command, long delay, String pointsTimeframe) { this.command = command; this.delay = delay; + this.pointsTimeframe = pointsTimeframe; } } diff --git a/common/src/main/java/me/confuser/banmanager/common/configs/HooksConfig.java b/common/src/main/java/me/confuser/banmanager/common/configs/HooksConfig.java index 98e5e06b..5f8ccd5c 100644 --- a/common/src/main/java/me/confuser/banmanager/common/configs/HooksConfig.java +++ b/common/src/main/java/me/confuser/banmanager/common/configs/HooksConfig.java @@ -92,7 +92,7 @@ private List getActionCommands(String event, List> mapL delay = delay * 20L; // Convert from seconds to ticks } - actionCommands.add(new ActionCommand((String) map.get("cmd"), delay)); + actionCommands.add(new ActionCommand((String) map.get("cmd"), delay, "")); } return actionCommands; diff --git a/common/src/main/java/me/confuser/banmanager/common/configs/WarningActionsConfig.java b/common/src/main/java/me/confuser/banmanager/common/configs/WarningActionsConfig.java index 06dadbe2..41f230d8 100644 --- a/common/src/main/java/me/confuser/banmanager/common/configs/WarningActionsConfig.java +++ b/common/src/main/java/me/confuser/banmanager/common/configs/WarningActionsConfig.java @@ -1,8 +1,11 @@ package me.confuser.banmanager.common.configs; import lombok.Getter; +import me.confuser.banmanager.common.BanManagerPlugin; import me.confuser.banmanager.common.CommonLogger; import me.confuser.banmanager.common.configuration.ConfigurationSection; +import me.confuser.banmanager.common.data.PlayerData; +import me.confuser.banmanager.common.util.DateUtils; import java.util.ArrayList; import java.util.HashMap; @@ -59,7 +62,20 @@ public WarningActionsConfig(ConfigurationSection config, CommonLogger logger) { delay = delay * 20L; // Convert from seconds to ticks } - actionCommands.add(new ActionCommand((String) map.get("cmd"), delay)); + String timeframe = ""; + + if (map.get("pointsTimeframe") != null) { + try { + DateUtils.parseDateDiff(timeframe, false); + + timeframe = (String) map.get("pointsTimeframe"); + } catch (Exception e) { + logger.severe("Invalid pointsTimeframe for " + map.get("cmd")); + continue; + } + } + + actionCommands.add(new ActionCommand((String) map.get("cmd"), delay, timeframe)); } this.actions.put(amountDbl, actionCommands); @@ -72,7 +88,7 @@ public WarningActionsConfig(ConfigurationSection config, CommonLogger logger) { List actionCommands = new ArrayList<>(actions.size()); for (String action : actions) { - actionCommands.add(new ActionCommand(action, 0)); + actionCommands.add(new ActionCommand(action, 0, "")); } this.actions.put(amountDbl, actionCommands); @@ -80,8 +96,28 @@ public WarningActionsConfig(ConfigurationSection config, CommonLogger logger) { } } - public List getCommand(double amount) { - return actions.get(amount); + public List getCommands(PlayerData player, double overallPoints) { + List commands = new ArrayList<>(); + + for (Map.Entry> entry : actions.entrySet()) { + for (ActionCommand actionCommand : entry.getValue()) { + double totalPoints = overallPoints; + + if (!actionCommand.getPointsTimeframe().isEmpty()) { + try { + totalPoints = BanManagerPlugin.getInstance().getPlayerWarnStorage().getPointsCount(player, DateUtils.parseDateDiff(actionCommand.getPointsTimeframe(), false)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (totalPoints == entry.getKey()) { + commands.add(actionCommand); + } + } + } + + return commands; } } diff --git a/common/src/main/java/me/confuser/banmanager/common/storage/PlayerWarnStorage.java b/common/src/main/java/me/confuser/banmanager/common/storage/PlayerWarnStorage.java index 294d6252..4e2bc760 100644 --- a/common/src/main/java/me/confuser/banmanager/common/storage/PlayerWarnStorage.java +++ b/common/src/main/java/me/confuser/banmanager/common/storage/PlayerWarnStorage.java @@ -143,6 +143,25 @@ public double getPointsCount(PlayerData player) throws SQLException { return 0; } + public double getPointsCount(PlayerData player, long timeframe) throws SQLException { + try (DatabaseConnection connection = connectionSource.getReadOnlyConnection(getTableName())) { + CompiledStatement statement = connection + .compileStatement("SELECT SUM(points) AS points FROM " + getTableName() + " WHERE player_id = ? AND created >= ?", StatementBuilder.StatementType.SELECT, null, DatabaseConnection + .DEFAULT_RESULT_FLAGS, false); + + statement.setObject(0, player.getId(), SqlType.BYTE_ARRAY); + statement.setObject(1, timeframe, SqlType.LONG); + + DatabaseResults results = statement.runQuery(null); + + if (results.next()) return results.getDouble(0); + } catch (IOException e) { + e.printStackTrace(); + } + + return 0; + } + public boolean isRecentlyWarned(PlayerData player, long cooldown) throws SQLException { if (cooldown == 0) { return false; diff --git a/common/src/test/java/me/confuser/banmanager/common/commands/WarnCommandTest.java b/common/src/test/java/me/confuser/banmanager/common/commands/WarnCommandTest.java new file mode 100644 index 00000000..0bfdfdcb --- /dev/null +++ b/common/src/test/java/me/confuser/banmanager/common/commands/WarnCommandTest.java @@ -0,0 +1,144 @@ +package me.confuser.banmanager.common.commands; + +import me.confuser.banmanager.common.BasePluginDbTest; +import me.confuser.banmanager.common.CommonPlayer; +import me.confuser.banmanager.common.CommonServer; +import me.confuser.banmanager.common.configs.ActionCommand; +import me.confuser.banmanager.common.configs.WarningActionsConfig; +import me.confuser.banmanager.common.data.PlayerData; +import me.confuser.banmanager.common.data.PlayerWarnData; +import me.confuser.banmanager.common.util.DateUtils; +import me.confuser.banmanager.common.util.parsers.WarnCommandParser; +import org.junit.Before; +import org.junit.Test; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.*; +import static org.awaitility.Awaitility.await; +import java.lang.reflect.Field; + +public class WarnCommandTest extends BasePluginDbTest { + private WarnCommand cmd; + + @Before + public void setupCmd() { + for (CommonCommand cmd : plugin.getCommands()) { + if (cmd.getCommandName().equals("warn")) { + this.cmd = (WarnCommand) cmd; + break; + } + } + } + + @Test + public void shouldFailIfNoSilentPermission() { + CommonSender sender = spy(plugin.getServer().getConsoleSender()); + String[] args = new String[]{"-s", "confuser", "test"}; + + when(sender.hasPermission(cmd.getPermission() + ".silent")).thenReturn(false); + + assert (cmd.onCommand(sender, new WarnCommandParser(plugin, args, 1))); + verify(sender).sendMessage("&cYou do not have permission to perform that action"); + } + + @Test + public void shouldFailIfNoPointsPermission() { + CommonSender sender = spy(plugin.getServer().getConsoleSender()); + String[] args = new String[]{"-p", "5", "confuser", "test"}; + + when(sender.hasPermission(cmd.getPermission() + ".points")).thenReturn(false); + + assert (cmd.onCommand(sender, new WarnCommandParser(plugin, args, 1))); + verify(sender).sendMessage("&cYou do not have permission to perform that action"); + } + + @Test + public void shouldFailIfSelfWarn() { + CommonSender sender = spy(plugin.getServer().getConsoleSender()); + String[] args = new String[]{"Console", "test"}; + + assert (cmd.onCommand(sender, new WarnCommandParser(plugin, args, 1))); + verify(sender).sendMessage("&cYou cannot perform that action on yourself!"); + } + + @Test + public void shouldFailIfOffline() { + CommonSender sender = spy(plugin.getServer().getConsoleSender()); + String[] args = new String[]{testUtils.createRandomPlayerName(), "test"}; + + when(sender.hasPermission("bm.command.warn.offline")).thenReturn(false); + + assert (cmd.onCommand(sender, new WarnCommandParser(plugin, args, 1))); + verify(sender).sendMessage("&cYou are not allowed to perform this action on an offline player"); + } + + @Test + public void shouldFailIfPlayerExempt() { + CommonSender sender = spy(plugin.getServer().getConsoleSender()); + PlayerData player = testUtils.createRandomPlayer(); + CommonPlayer commonPlayer = spy(server.getPlayer(player.getName())); + String[] args = new String[]{player.getName(), "test"}; + + when(sender.hasPermission("bm.exempt.override.warn")).thenReturn(false); + when(commonPlayer.hasPermission("bm.exempt.warn")).thenReturn(true); + + assert (cmd.onCommand(sender, new WarnCommandParser(plugin, args, 1))); + verify(sender).sendMessage("&c" + player.getName() + " is exempt from that action"); + } + + @Test + public void shouldWarnPlayer() throws SQLException { + PlayerData player = testUtils.createRandomPlayer(); + CommonServer server = spy(plugin.getServer()); + CommonSender sender = spy(server.getConsoleSender()); + String[] args = new String[]{player.getName(), "test"}; + + assert (cmd.onCommand(sender, new WarnCommandParser(plugin, args, 1))); + + await().until(() -> plugin.getPlayerWarnStorage().getCount(player) == 1); + PlayerWarnData data = plugin.getPlayerWarnStorage().getWarnings(player).next(); + + assertEquals(player.getName(), data.getPlayer().getName()); + assertEquals("test", data.getReason()); + assertEquals(sender.getName(), data.getActor().getName()); + } + + @Test + public void shouldTriggerPointsTimeframeWarningActions() throws Exception { + CommonSender sender = spy(plugin.getServer().getConsoleSender()); + PlayerData player = testUtils.createRandomPlayer(); + + ActionCommand commandWithTimeframe = new ActionCommand("kick", 0, "5m"); + ActionCommand commandWithoutTimeframe = new ActionCommand("ban", 0, ""); + ActionCommand commandWithOldTimeframe = new ActionCommand("kick", 0, "30d"); + WarningActionsConfig warningActionsConfig = spy(plugin.getConfig().getWarningActions()); + + plugin.getPlayerWarnStorage().addWarning(new PlayerWarnData(player, sender.getData(), "testing", false, 0, DateUtils.parseDateDiff("31d", false)), false); + plugin.getPlayerWarnStorage().addWarning(new PlayerWarnData(player, sender.getData(), "testing", false, 0, DateUtils.parseDateDiff("1m", false)), false); + + await().until(() -> plugin.getPlayerWarnStorage().getCount(player) == 2); + + HashMap> actions = new HashMap<>(); + actions.put(1.0, Arrays.asList(commandWithoutTimeframe, commandWithTimeframe, commandWithOldTimeframe)); + + Field actionsField = WarningActionsConfig.class.getDeclaredField("actions"); + actionsField.setAccessible(true); + actionsField.set(warningActionsConfig, actions); + + List commands = warningActionsConfig.getCommands(player, 5); + + assertEquals(2, commands.size()); + + assertTrue(commands.contains(commandWithTimeframe)); + assertTrue(commands.contains(commandWithOldTimeframe)); + assertFalse(commands.contains(commandWithoutTimeframe)); + } +}