From e7f5dc14b6398529414e33702b20b5c1f4bc2013 Mon Sep 17 00:00:00 2001 From: BoomEaro <21033866+BoomEaro@users.noreply.github.com> Date: Mon, 29 Apr 2024 21:53:27 +0300 Subject: [PATCH] Attempt to implement paid unban command --- bukkit/src/main/resources/messages.yml | 6 + bungee/src/main/resources/messages.yml | 6 + bungee/src/main/resources/plugin.yml | 5 + .../banmanager/common/BanManagerPlugin.java | 1 + .../common/commands/BanCommand.java | 8 +- .../common/commands/UnbanPaidCommand.java | 118 ++++++++++++++++++ .../common/listeners/CommonJoinListener.java | 9 ++ .../common/storage/PlayerBanStorage.java | 50 +++++++- common/src/main/resources/messages.yml | 6 + common/src/main/resources/plugin.yml | 5 + 10 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 common/src/main/java/me/confuser/banmanager/common/commands/UnbanPaidCommand.java diff --git a/bukkit/src/main/resources/messages.yml b/bukkit/src/main/resources/messages.yml index 1c820ef7..683ae996 100644 --- a/bukkit/src/main/resources/messages.yml +++ b/bukkit/src/main/resources/messages.yml @@ -175,6 +175,12 @@ messages: noExists: '&c[player] is not abanned' notOwn: '&c[player] was not abanned by you, unable to unban' + unbanpaid: + notify: '&6[player] has been paid unbanned by [actor]' + error: + noExists: '&c[player] is not banned' + notOwn: '&c[player] was not banned by you, unable to paid unban' + unbanall: notify: '&6[player] will be unbanned by [actor]' diff --git a/bungee/src/main/resources/messages.yml b/bungee/src/main/resources/messages.yml index 1c820ef7..683ae996 100644 --- a/bungee/src/main/resources/messages.yml +++ b/bungee/src/main/resources/messages.yml @@ -175,6 +175,12 @@ messages: noExists: '&c[player] is not abanned' notOwn: '&c[player] was not abanned by you, unable to unban' + unbanpaid: + notify: '&6[player] has been paid unbanned by [actor]' + error: + noExists: '&c[player] is not banned' + notOwn: '&c[player] was not banned by you, unable to paid unban' + unbanall: notify: '&6[player] will be unbanned by [actor]' diff --git a/bungee/src/main/resources/plugin.yml b/bungee/src/main/resources/plugin.yml index 81dd7d5e..4866ce19 100644 --- a/bungee/src/main/resources/plugin.yml +++ b/bungee/src/main/resources/plugin.yml @@ -44,6 +44,11 @@ commands: usage: "/unban [reason]" aliases: [ bmunban, pardon ] permission: bm.command.unban + unbanpaid: + description: "unbanpaid a player" + usage: "/unbanpaid [reason]" + aliases: [ bmunbanpaid, pardonpaid ] + permission: bm.command.unbanpaid aunban: description: "aunban a player" usage: "/aunban [reason]" diff --git a/common/src/main/java/me/confuser/banmanager/common/BanManagerPlugin.java b/common/src/main/java/me/confuser/banmanager/common/BanManagerPlugin.java index 6257cf4a..1d9f75c6 100644 --- a/common/src/main/java/me/confuser/banmanager/common/BanManagerPlugin.java +++ b/common/src/main/java/me/confuser/banmanager/common/BanManagerPlugin.java @@ -434,6 +434,7 @@ public CommonCommand[] getCommands() { new TempNameBanCommand(this), new TempWarnCommand(this), new UnbanCommand(this), + new UnbanPaidCommand(this), new AUnbanCommand(this), new UnbanIpCommand(this), new UnbanIpRangeCommand(this), diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/BanCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/BanCommand.java index a6797fa0..9774cfa4 100644 --- a/common/src/main/java/me/confuser/banmanager/common/commands/BanCommand.java +++ b/common/src/main/java/me/confuser/banmanager/common/commands/BanCommand.java @@ -131,9 +131,15 @@ public boolean onCommand(CommonSender sender, CommandParser parser) { } } + if (getPlugin().getPlayerBanStorage().isPaidUnbanned(player.getUUID())) { + if (!sender.hasPermission("bm.unbanpaid.prevent")) { + sender.sendMessage(Message.get("sender.error.exempt").set("player", playerName).toString()); + return; + } + } + final PlayerBanData ban = new PlayerBanData(player, actor, parser.getReason().getMessage(), isSilent); boolean created; - try { created = getPlugin().getPlayerBanStorage().ban(ban); } catch (SQLException e) { diff --git a/common/src/main/java/me/confuser/banmanager/common/commands/UnbanPaidCommand.java b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanPaidCommand.java new file mode 100644 index 00000000..d98db86d --- /dev/null +++ b/common/src/main/java/me/confuser/banmanager/common/commands/UnbanPaidCommand.java @@ -0,0 +1,118 @@ +package me.confuser.banmanager.common.commands; + +import me.confuser.banmanager.common.BanManagerPlugin; +import me.confuser.banmanager.common.data.PlayerBanData; +import me.confuser.banmanager.common.data.PlayerData; +import me.confuser.banmanager.common.util.Message; +import me.confuser.banmanager.common.util.parsers.UnbanCommandParser; + +import java.sql.SQLException; +import java.util.UUID; + +public class UnbanPaidCommand extends CommonCommand { + + public UnbanPaidCommand(BanManagerPlugin plugin) { + super(plugin, "unbanpaid", true, UnbanCommandParser.class, 0); + } + + @Override + public boolean onCommand(final CommonSender sender, CommandParser originalParser) { + final UnbanCommandParser parser = (UnbanCommandParser) originalParser; + final boolean isDelete = parser.isDelete(); + + if (isDelete && !sender.hasPermission(getPermission() + ".delete")) { + sender.sendMessage(Message.getString("sender.error.noPermission")); + return true; + } + + if (parser.args.length < 1) { + return false; + } + + // Check if UUID vs name + final String playerName = parser.args[0]; + final boolean isUUID = playerName.length() > 16; + boolean isBanned; + + if (isUUID) { + try { + isBanned = getPlugin().getPlayerBanStorage().isBanned(UUID.fromString(playerName)); + } catch (IllegalArgumentException e) { + sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + return true; + } + } else { + isBanned = getPlugin().getPlayerBanStorage().isBanned(playerName); + } + + if (!isBanned) { + Message message = Message.get("unbanpaid.error.noExists"); + message.set("player", playerName); + + sender.sendMessage(message.toString()); + return true; + } + + final String reason = parser.getReason().getMessage(); + + getPlugin().getScheduler().runAsync(() -> { + PlayerBanData ban; + + if (isUUID) { + ban = getPlugin().getPlayerBanStorage().getBan(UUID.fromString(playerName)); + } else { + ban = getPlugin().getPlayerBanStorage().getBan(playerName); + } + + if (ban == null) { + sender.sendMessage(Message.get("sender.error.notFound").set("player", playerName).toString()); + return; + } + + final PlayerData actor = sender.getData(); + + //TODO refactor if async perm check is problem + if (!actor.getUUID().equals(ban.getActor().getUUID()) && !sender.hasPermission("bm.exempt.override.aban") + && sender.hasPermission("bm.command.unbanpaid.own")) { + Message.get("unbanpaid.error.notOwn").set("player", ban.getPlayer().getName()).sendTo(sender); + return; + } + + boolean unbanned; + + try { + unbanned = getPlugin().getPlayerBanStorage().unban(ban, actor, reason, isDelete, true); + } catch (SQLException e) { + sender.sendMessage(Message.get("sender.error.exception").toString()); + e.printStackTrace(); + return; + } + + if (!unbanned) { + return; + } + + Message message = Message.get("unbanpaid.notify"); + message + .set("player", ban.getPlayer().getName()) + .set("playerId", ban.getPlayer().getUUID().toString()) + .set("actor", actor.getName()) + .set("id", ban.getId()) + .set("reason", reason); + + if (sender.isTrueNotConsole()) { + sender.sendMessage(message); + } + + if (!sender.hasPermission("bm.notify.unbanpaid") || parser.isSilent()) { + message.sendTo(sender); + } + + if (!parser.isSilent()) { + getPlugin().getServer().broadcast(message.toString(), "bm.notify.unbanpaid"); + } + }); + + return true; + } +} diff --git a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonJoinListener.java b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonJoinListener.java index 436e0935..af77c4b0 100755 --- a/common/src/main/java/me/confuser/banmanager/common/listeners/CommonJoinListener.java +++ b/common/src/main/java/me/confuser/banmanager/common/listeners/CommonJoinListener.java @@ -9,6 +9,7 @@ import me.confuser.banmanager.common.ipaddr.IPAddress; import me.confuser.banmanager.common.maxmind.db.model.CountryResponse; import me.confuser.banmanager.common.ormlite.dao.CloseableIterator; +import me.confuser.banmanager.common.storage.PlayerBanStorage; import me.confuser.banmanager.common.util.*; import java.io.IOException; @@ -271,6 +272,14 @@ public void banCheck(UUID id, String name, IPAddress address, CommonJoinHandler handler.handlePlayerDeny(data.getPlayer(), message); handleJoinDeny(data.getPlayer(), data.getActor(), data.getReason()); + return; + } + + PlayerBanStorage.PaidUnbanData paidUnbanData = plugin.getPlayerBanStorage().getPaidUnbanData(id); + if (paidUnbanData != null) { + if (paidUnbanData.getTimeAdded() == null) { + paidUnbanData.setTimeAdded(System.currentTimeMillis()); + } } } diff --git a/common/src/main/java/me/confuser/banmanager/common/storage/PlayerBanStorage.java b/common/src/main/java/me/confuser/banmanager/common/storage/PlayerBanStorage.java index b2919889..7bcd12d8 100644 --- a/common/src/main/java/me/confuser/banmanager/common/storage/PlayerBanStorage.java +++ b/common/src/main/java/me/confuser/banmanager/common/storage/PlayerBanStorage.java @@ -1,5 +1,6 @@ package me.confuser.banmanager.common.storage; +import lombok.Data; import me.confuser.banmanager.common.BanManagerPlugin; import me.confuser.banmanager.common.api.events.CommonEvent; import me.confuser.banmanager.common.data.PlayerBanData; @@ -22,15 +23,19 @@ import me.confuser.banmanager.common.util.UUIDUtils; import java.sql.SQLException; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; public class PlayerBanStorage extends BaseDaoImpl { private BanManagerPlugin plugin; - private ConcurrentHashMap bans = new ConcurrentHashMap<>(); + private final ConcurrentMap bans = new ConcurrentHashMap<>(); + private final ConcurrentMap paidUnbans = new ConcurrentHashMap<>(); + public PlayerBanStorage(BanManagerPlugin plugin) throws SQLException { super(plugin.getLocalConn(), (DatabaseTableConfig) plugin.getConfig().getLocalDb() @@ -44,7 +49,7 @@ public PlayerBanStorage(BanManagerPlugin plugin) throws SQLException { } else { try { executeRawNoArgs("ALTER TABLE " + tableConfig.getTableName() + " ADD COLUMN `silent` TINYINT(1)"); - } catch (SQLException e) { + } catch (SQLException ignored) { } try { @@ -53,7 +58,7 @@ public PlayerBanStorage(BanManagerPlugin plugin) throws SQLException { + " CHANGE `updated` `updated` BIGINT UNSIGNED," + " CHANGE `expires` `expires` BIGINT UNSIGNED" ); - } catch (SQLException e) { + } catch (SQLException ignored) { } } @@ -148,7 +153,7 @@ private void loadAll() throws SQLException { } } - public ConcurrentHashMap getBans() { + public ConcurrentMap getBans() { return bans; } @@ -220,6 +225,10 @@ public boolean unban(PlayerBanData ban, PlayerData actor, String reason) throws } public boolean unban(PlayerBanData ban, PlayerData actor, String reason, boolean delete) throws SQLException { + return unban(ban, actor, reason, delete, false); + } + + public boolean unban(PlayerBanData ban, PlayerData actor, String reason, boolean delete, boolean paid) throws SQLException { CommonEvent event = plugin.getServer().callEvent("PlayerUnbanEvent", ban, actor, reason); if (event.isCancelled()) { @@ -227,13 +236,36 @@ public boolean unban(PlayerBanData ban, PlayerData actor, String reason, boolean } delete(ban); - bans.remove(ban.getPlayer().getUUID()); + UUID uuid = ban.getPlayer().getUUID(); + bans.remove(uuid); + + if (paid) { + this.paidUnbans.put(uuid, new PaidUnbanData(uuid)); + } if (!delete) plugin.getPlayerBanRecordStorage().addRecord(ban, actor, reason); return true; } + public PaidUnbanData getPaidUnbanData(UUID uuid) { + return this.paidUnbans.get(uuid); + } + + public boolean isPaidUnbanned(UUID uuid) { + PaidUnbanData paidUnbanData = this.paidUnbans.get(uuid); + if (paidUnbanData == null) { + return false; + } + + Long time = paidUnbanData.getTimeAdded(); + if (time == null) { + return false; + } + + return System.currentTimeMillis() - time > Duration.ofMinutes(10).toMillis(); + } + public CloseableIterator findBans(long fromTime) throws SQLException { if (fromTime == 0) { return iterator(); @@ -301,4 +333,12 @@ public boolean isRecentlyBanned(PlayerData player, long cooldown) throws SQLExce .ge("created", (System.currentTimeMillis() / 1000L) - cooldown) .countOf() > 0; } + + @Data + public static class PaidUnbanData { + private final UUID uuid; + + private Long timeAdded; + + } } diff --git a/common/src/main/resources/messages.yml b/common/src/main/resources/messages.yml index 1c820ef7..683ae996 100644 --- a/common/src/main/resources/messages.yml +++ b/common/src/main/resources/messages.yml @@ -175,6 +175,12 @@ messages: noExists: '&c[player] is not abanned' notOwn: '&c[player] was not abanned by you, unable to unban' + unbanpaid: + notify: '&6[player] has been paid unbanned by [actor]' + error: + noExists: '&c[player] is not banned' + notOwn: '&c[player] was not banned by you, unable to paid unban' + unbanall: notify: '&6[player] will be unbanned by [actor]' diff --git a/common/src/main/resources/plugin.yml b/common/src/main/resources/plugin.yml index dc888b4d..1927585c 100644 --- a/common/src/main/resources/plugin.yml +++ b/common/src/main/resources/plugin.yml @@ -44,6 +44,11 @@ commands: usage: "/unban [reason]" aliases: [ bmunban, pardon ] permission: bm.command.unban + unbanpaid: + description: "unbanpaid a player" + usage: "/unbanpaid [reason]" + aliases: [ bmunbanpaid, pardonpaid ] + permission: bm.command.unbanpaid aunban: description: "aunban a player" usage: "/aunban [reason]"