From 3f4a9f6f36d3ca737fc1b084e9832ac124439706 Mon Sep 17 00:00:00 2001 From: Tomasz Kuraczyk Date: Thu, 26 Feb 2026 16:45:36 +0100 Subject: [PATCH] Add banip and unbanip commands, fix minor issues --- .../net/kuraczyk/banhammer/BanHammer.java | 4 + .../net/kuraczyk/banhammer/cmds/BHConfig.java | 58 +++ .../java/net/kuraczyk/banhammer/cmds/Ban.java | 138 ++++++- .../net/kuraczyk/banhammer/cmds/BanIP.java | 339 ++++++++++++++++++ .../net/kuraczyk/banhammer/cmds/Unban.java | 136 +++++++ .../net/kuraczyk/banhammer/cmds/UnbanIP.java | 152 ++++++++ src/main/resources/plugin.yml | 14 +- src/main/resources/translations.yml | 34 +- 8 files changed, 868 insertions(+), 7 deletions(-) create mode 100644 src/main/java/net/kuraczyk/banhammer/cmds/BHConfig.java create mode 100644 src/main/java/net/kuraczyk/banhammer/cmds/BanIP.java create mode 100644 src/main/java/net/kuraczyk/banhammer/cmds/Unban.java create mode 100644 src/main/java/net/kuraczyk/banhammer/cmds/UnbanIP.java diff --git a/src/main/java/net/kuraczyk/banhammer/BanHammer.java b/src/main/java/net/kuraczyk/banhammer/BanHammer.java index 37ced9b..5675a7c 100644 --- a/src/main/java/net/kuraczyk/banhammer/BanHammer.java +++ b/src/main/java/net/kuraczyk/banhammer/BanHammer.java @@ -51,6 +51,10 @@ public final class BanHammer extends JavaPlugin { getLogger().info(ChatColor.translateAlternateColorCodes('&', "&a&b+&r&8 | &aBan&7Hammer")); new Ban(this); + new Unban(this); + new BanIP(this); + new UnbanIP(this); + new BHConfig(this); getServer().getPluginManager().registerEvents(new PlayerPreLogin(this), this); } diff --git a/src/main/java/net/kuraczyk/banhammer/cmds/BHConfig.java b/src/main/java/net/kuraczyk/banhammer/cmds/BHConfig.java new file mode 100644 index 0000000..372700a --- /dev/null +++ b/src/main/java/net/kuraczyk/banhammer/cmds/BHConfig.java @@ -0,0 +1,58 @@ +package net.kuraczyk.banhammer.cmds; + +import net.kuraczyk.banhammer.BanHammer; +import net.kuraczyk.banhammer.utils.TextUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.yaml.snakeyaml.Yaml; + +import java.io.File; + +public class BHConfig implements CommandExecutor { + + BanHammer plugin; + + public BHConfig(BanHammer p) { + plugin = p; + p.getCommand("bhconfig").setExecutor(this); + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String lab, String[] args) { + if(sender instanceof Player) return reloadConfigurations((Player)sender); + else return reloadConfigurations(); + } + + private boolean reloadConfigurations(Player p) { + if(!p.hasPermission("banhammer.reload")){ + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.bhconfig.noPermission")))); + return false; + } + + plugin.reloadConfig(); + plugin.config = plugin.getConfig(); + plugin.translations = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "translations.yml")); + + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.bhconfig.successfullyReloaded")))); + + return true; + } + private boolean reloadConfigurations() { + plugin.reloadConfig(); + plugin.config = plugin.getConfig(); + plugin.translations = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "translations.yml")); + + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.bhconfig.successfullyReloaded")))); + + return true; + } + + private String addPrefix(String s) { + return (String)(plugin.translations.getString("prefix")+s); + } + +} diff --git a/src/main/java/net/kuraczyk/banhammer/cmds/Ban.java b/src/main/java/net/kuraczyk/banhammer/cmds/Ban.java index 0091d09..7ce7d2e 100644 --- a/src/main/java/net/kuraczyk/banhammer/cmds/Ban.java +++ b/src/main/java/net/kuraczyk/banhammer/cmds/Ban.java @@ -33,6 +33,10 @@ public class Ban implements CommandExecutor { } private boolean banCommand(Player p, String[] args) { + if(!p.hasPermission("banhammer.ban")) { + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.noPermission")))); + return false; + } if(args.length==0) p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.usage")))); else if(args.length>=1) { Player target = Bukkit.getPlayer(args[0]); @@ -89,6 +93,22 @@ public class Ban implements CommandExecutor { if(Objects.equals(duration, "-1") || Objects.equals(duration, "perm")) banEndDate = null; + try { + Connection conn = plugin.db.getConnection(); + PreparedStatement stmt = conn.prepareStatement("SELECT * FROM player_bans WHERE player_name = ? AND scope = ?"); + stmt.setString(1, args[0]); + stmt.setString(2, scope); + ResultSet rs = stmt.executeQuery(); + if(rs.next()){ + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.alreadyBannedInScopeError")))); + return false; + } + } catch (SQLException e){ + plugin.getLogger().severe(e.toString()); + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.unexpectedError")))); + return false; + } + PlayerBan b = banPlayer(args[0], targetUuid, reason, scope, banEndDate, p.getName(), p.getUniqueId()); if(b != null) { @@ -97,7 +117,8 @@ public class Ban implements CommandExecutor { if(target.isOnline()) if(Objects.equals(plugin.config.getString("serverID"), scope) || Objects.equals(scope, "*")) target.kick(TextUtils.colorString(TextUtils.resolvePlaceholders(plugin.translations.getString("banKickMessage.playerBanPerm"), b))); p.sendMessage(TextUtils.colorString(resolveBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.ban.successfulBanMessagePerm")), args[0], scope, reason, p.getName()))); - Bukkit.broadcast(TextUtils.colorString(resolveBanMessagePlaceholders(plugin.translations.getString("command.ban.banPublicAnnouncementPerm"), args[0], scope, reason, p.getName()))); + String bcMess = plugin.translations.getString("command.ban.banPublicAnnouncementPerm"); + if(bcMess!=null) Bukkit.broadcast(TextUtils.colorString(resolveBanMessagePlaceholders(bcMess, args[0], scope, reason, p.getName()))); } else { long timeLeft = banEndDate.getTime() - new Timestamp(System.currentTimeMillis()).getTime(); @@ -114,7 +135,8 @@ public class Ban implements CommandExecutor { if(target.isOnline()) if(Objects.equals(plugin.config.getString("serverID"), scope) || Objects.equals(scope, "*")) target.kick(TextUtils.colorString(TextUtils.resolvePlaceholders(plugin.translations.getString("banKickMessage.playerBanTemp"), b))); p.sendMessage(TextUtils.colorString(resolveBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.ban.successfulBanMessageTemp")), args[0], scope, reason, p.getName(), parsedBanDuration))); - Bukkit.broadcast(TextUtils.colorString(resolveBanMessagePlaceholders(plugin.translations.getString("command.ban.banPublicAnnouncementTemp"), args[0], scope, reason, p.getName(), parsedBanDuration))); + String bcMess = plugin.translations.getString("command.ban.banPublicAnnouncementTemp"); + if(bcMess!=null) Bukkit.broadcast(TextUtils.colorString(resolveBanMessagePlaceholders(bcMess, args[0], scope, reason, p.getName(), parsedBanDuration))); } return true; @@ -129,7 +151,117 @@ public class Ban implements CommandExecutor { return false; } private boolean banCommand(String[] args) { - if(args.length==0) plugin.getServer().getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.usage")))); + if(args.length==0) Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.usage")))); + else if(args.length>=1) { + Player target = Bukkit.getPlayer(args[0]); + UUID targetUuid = Bukkit.getOfflinePlayer(args[0]).getUniqueId(); + Timestamp banEndDate=null; + String scope = "*", reason = plugin.translations.getString("default.reason"), duration="-1"; + if(target!=null) + if(target.isOnline()) targetUuid=target.getUniqueId(); + + if(args.length>=2) scope=args[1]; + if(args.length>=3) { + duration=args[2]; + String regex = "^(perm)|(-1)|\\d+:(s|m|h|d)$"; + String regexOnlyNum = "^\\d+$"; + if(!(duration.matches(regex) || duration.matches(regexOnlyNum))) { + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.durationFormatError")))); + return false; + } + char type = plugin.config.getString("defaultDurationType").charAt(0); + Integer time=0; + boolean chk = false; + for(int i = 0; i < duration.length(); i++){ + if(duration.charAt(i)==':'){ + chk = true; + time = Integer.parseInt(duration.substring(0, i)); + if(i+1 < duration.length()) type = duration.charAt(i+1); + } + } + if(!chk) time = Integer.parseInt(duration); + switch (type){ + case 'd': + banEndDate = new Timestamp(System.currentTimeMillis()+ TimeUnit.DAYS.toMillis(time)); + break; + case 'h': + banEndDate = new Timestamp(System.currentTimeMillis()+TimeUnit.HOURS.toMillis(time)); + break; + case 'm': + banEndDate = new Timestamp(System.currentTimeMillis()+TimeUnit.MINUTES.toMillis(time)); + break; + case 's': + banEndDate = new Timestamp(System.currentTimeMillis()+TimeUnit.SECONDS.toMillis(time)); + break; + default: + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.durationFormatError")))); + return false; + } + } + + StringBuilder newReason = new StringBuilder(); + for(int i = 3; i < args.length; i++){ + newReason.append(args[i]).append(" "); + } + if(!newReason.isEmpty()) reason=newReason.toString(); + + if(Objects.equals(duration, "-1") || Objects.equals(duration, "perm")) banEndDate = null; + + try { + Connection conn = plugin.db.getConnection(); + PreparedStatement stmt = conn.prepareStatement("SELECT * FROM player_bans WHERE player_name = ? AND scope = ?"); + stmt.setString(1, args[0]); + stmt.setString(2, scope); + ResultSet rs = stmt.executeQuery(); + if(rs.next()){ + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.alreadyBannedInScopeError")))); + return false; + } + } catch (SQLException e){ + plugin.getLogger().severe(e.toString()); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.unexpectedError")))); + return false; + } + + PlayerBan b = banPlayer(args[0], targetUuid, reason, scope, banEndDate, "CONSOLE", null); + + if(b != null) { + if(banEndDate == null) { + if(target!=null) + if(target.isOnline()) + if(Objects.equals(plugin.config.getString("serverID"), scope) || Objects.equals(scope, "*")) target.kick(TextUtils.colorString(TextUtils.resolvePlaceholders(plugin.translations.getString("banKickMessage.playerBanPerm"), b))); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(resolveBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.ban.successfulBanMessagePerm")), args[0], scope, reason, "CONSOLE"))); + String bcMess = plugin.translations.getString("command.ban.banPublicAnnouncementPerm"); + if(bcMess!=null) Bukkit.broadcast(TextUtils.colorString(resolveBanMessagePlaceholders(bcMess, args[0], scope, reason, "CONSOLE"))); + } + else { + long timeLeft = banEndDate.getTime() - new Timestamp(System.currentTimeMillis()).getTime(); + long timeLeftDays = TimeUnit.MILLISECONDS.toDays(timeLeft); + timeLeft-=TimeUnit.DAYS.toMillis(timeLeftDays); + long timeLeftHours = TimeUnit.MILLISECONDS.toHours(timeLeft); + timeLeft-=TimeUnit.HOURS.toMillis(timeLeftHours); + long timeLeftMinutes = TimeUnit.MILLISECONDS.toMinutes(timeLeft); + timeLeft-=TimeUnit.MINUTES.toMillis(timeLeftMinutes); + long timeLeftSeconds = TimeUnit.MILLISECONDS.toSeconds(timeLeft); + String parsedBanDuration = TextUtils.parsePolishDate(timeLeftDays, timeLeftHours, timeLeftMinutes, timeLeftSeconds); + + if(target!=null) + if(target.isOnline()) + if(Objects.equals(plugin.config.getString("serverID"), scope) || Objects.equals(scope, "*")) target.kick(TextUtils.colorString(TextUtils.resolvePlaceholders(plugin.translations.getString("banKickMessage.playerBanTemp"), b))); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(resolveBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.ban.successfulBanMessageTemp")), args[0], scope, reason, "CONSOLE", parsedBanDuration))); + String bcMess = plugin.translations.getString("command.ban.banPublicAnnouncementTemp"); + if(bcMess!=null) Bukkit.broadcast(TextUtils.colorString(resolveBanMessagePlaceholders(bcMess, args[0], scope, reason, "CONSOLE", parsedBanDuration))); + + } + return true; + } + else { + plugin.getLogger().severe("BanHammer: Something went wrong while user used ban command... Maybe DB or Technician has skill issue???"); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.ban.unexpectedError")))); + return false; + } + + } return false; } diff --git a/src/main/java/net/kuraczyk/banhammer/cmds/BanIP.java b/src/main/java/net/kuraczyk/banhammer/cmds/BanIP.java new file mode 100644 index 0000000..8a6991d --- /dev/null +++ b/src/main/java/net/kuraczyk/banhammer/cmds/BanIP.java @@ -0,0 +1,339 @@ +package net.kuraczyk.banhammer.cmds; + +import net.kuraczyk.banhammer.BanHammer; +import net.kuraczyk.banhammer.utils.IPBan; +import net.kuraczyk.banhammer.utils.PlayerBan; +import net.kuraczyk.banhammer.utils.TextUtils; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.sql.*; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +public class BanIP implements CommandExecutor { + + BanHammer plugin; + + public BanIP(BanHammer p){ + plugin = p; + p.getCommand("banip").setExecutor(this); + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String lab, String[] args) { + if(sender instanceof Player) return banIpCommand((Player)sender, args); + else return banIpCommand(args); + } + + private boolean banIpCommand(Player p, String[] args) { + if(!p.hasPermission("banhammer.banip")) { + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.noPermission")))); + return false; + } + if(args.length==0) p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.usage")))); + else if(args.length>=1) { + Timestamp banEndDate=null; + String scope = "*", reason = plugin.translations.getString("default.reason"), duration="-1"; + + if(args.length>=2) scope=args[1]; + if(args.length>=3) { + duration=args[2]; + String regex = "^(perm)|(-1)|\\d+:(s|m|h|d)$"; + String regexOnlyNum = "^\\d+$"; + if(!(duration.matches(regex) || duration.matches(regexOnlyNum))) { + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.durationFormatError")))); + return false; + } + char type = plugin.config.getString("defaultDurationType").charAt(0); + Integer time=0; + boolean chk = false; + for(int i = 0; i < duration.length(); i++){ + if(duration.charAt(i)==':'){ + chk = true; + time = Integer.parseInt(duration.substring(0, i)); + if(i+1 < duration.length()) type = duration.charAt(i+1); + } + } + if(!chk) time = Integer.parseInt(duration); + switch (type){ + case 'd': + banEndDate = new Timestamp(System.currentTimeMillis()+ TimeUnit.DAYS.toMillis(time)); + break; + case 'h': + banEndDate = new Timestamp(System.currentTimeMillis()+TimeUnit.HOURS.toMillis(time)); + break; + case 'm': + banEndDate = new Timestamp(System.currentTimeMillis()+TimeUnit.MINUTES.toMillis(time)); + break; + case 's': + banEndDate = new Timestamp(System.currentTimeMillis()+TimeUnit.SECONDS.toMillis(time)); + break; + default: + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.durationFormatError")))); + return false; + } + } + + StringBuilder newReason = new StringBuilder(); + for(int i = 3; i < args.length; i++){ + newReason.append(args[i]).append(" "); + } + if(!newReason.isEmpty()) reason=newReason.toString(); + + if(Objects.equals(duration, "-1") || Objects.equals(duration, "perm")) banEndDate = null; + + InetAddress addr; + try { + addr = InetAddress.getByName(args[0]); + } catch (UnknownHostException e){ + plugin.getLogger().severe(e.toString()); + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.unexpectedError")))); + return false; + } + + try { + Connection conn = plugin.db.getConnection(); + PreparedStatement stmt = conn.prepareStatement("SELECT * FROM ip_bans WHERE (ip_address = ?::inet) AND scope = ?"); + stmt.setObject(1, addr.getHostAddress()); + stmt.setString(2, scope); + ResultSet rs = stmt.executeQuery(); + if(rs.next()){ + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.alreadyBannedInScopeError")))); + return false; + } + } catch (SQLException e){ + plugin.getLogger().severe(e.toString()); + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.unexpectedError")))); + return false; + } + + IPBan b = banIp(addr, reason, scope, banEndDate, p.getName(), p.getUniqueId()); + + if(b != null) { + if(banEndDate == null) { + for(Player target : Bukkit.getOnlinePlayers()) { + if (target.getAddress().getAddress().equals(addr)) + if(Objects.equals(plugin.config.getString("serverID"), scope) || Objects.equals(scope, "*")) target.kick(TextUtils.colorString(TextUtils.resolvePlaceholders(plugin.translations.getString("banKickMessage.playerBanPerm"), b))); + } + p.sendMessage(TextUtils.colorString(resolveIpBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.banip.successfulBanMessagePerm")), args[0], scope, reason, p.getName()))); + String bcMess = plugin.translations.getString("command.banip.banPublicAnnouncementPerm"); + if(bcMess!=null) Bukkit.broadcast(TextUtils.colorString(resolveIpBanMessagePlaceholders(bcMess, args[0], scope, reason, p.getName()))); + } + else { + long timeLeft = banEndDate.getTime() - new Timestamp(System.currentTimeMillis()).getTime(); + long timeLeftDays = TimeUnit.MILLISECONDS.toDays(timeLeft); + timeLeft-=TimeUnit.DAYS.toMillis(timeLeftDays); + long timeLeftHours = TimeUnit.MILLISECONDS.toHours(timeLeft); + timeLeft-=TimeUnit.HOURS.toMillis(timeLeftHours); + long timeLeftMinutes = TimeUnit.MILLISECONDS.toMinutes(timeLeft); + timeLeft-=TimeUnit.MINUTES.toMillis(timeLeftMinutes); + long timeLeftSeconds = TimeUnit.MILLISECONDS.toSeconds(timeLeft); + String parsedBanDuration = TextUtils.parsePolishDate(timeLeftDays, timeLeftHours, timeLeftMinutes, timeLeftSeconds); + + for(Player target : Bukkit.getOnlinePlayers()) { + if (target.getAddress().getAddress().equals(addr)) + if (Objects.equals(plugin.config.getString("serverID"), scope) || Objects.equals(scope, "*")) + target.kick(TextUtils.colorString(TextUtils.resolvePlaceholders(plugin.translations.getString("banKickMessage.playerBanTemp"), b))); + } + p.sendMessage(TextUtils.colorString(resolveIpBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.banip.successfulBanMessageTemp")), args[0], scope, reason, p.getName(), parsedBanDuration))); + String bcMess = plugin.translations.getString("command.banip.banPublicAnnouncementTemp"); + if(bcMess!=null) Bukkit.broadcast(TextUtils.colorString(resolveIpBanMessagePlaceholders(bcMess, args[0], scope, reason, p.getName(), parsedBanDuration))); + + } + return true; + } + else { + plugin.getLogger().severe("BanHammer: Something went wrong while user used ban command... Maybe DB or Technician has skill issue???"); + p.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.unexpectedError")))); + return false; + } + + } + return false; + } + private boolean banIpCommand(String[] args) { + if(args.length==0) Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.usage")))); + else if(args.length>=1) { + Timestamp banEndDate=null; + String scope = "*", reason = plugin.translations.getString("default.reason"), duration="-1"; + + if(args.length>=2) scope=args[1]; + if(args.length>=3) { + duration=args[2]; + String regex = "^(perm)|(-1)|\\d+:(s|m|h|d)$"; + String regexOnlyNum = "^\\d+$"; + if(!(duration.matches(regex) || duration.matches(regexOnlyNum))) { + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.durationFormatError")))); + return false; + } + char type = plugin.config.getString("defaultDurationType").charAt(0); + Integer time=0; + boolean chk = false; + for(int i = 0; i < duration.length(); i++){ + if(duration.charAt(i)==':'){ + chk = true; + time = Integer.parseInt(duration.substring(0, i)); + if(i+1 < duration.length()) type = duration.charAt(i+1); + } + } + if(!chk) time = Integer.parseInt(duration); + switch (type){ + case 'd': + banEndDate = new Timestamp(System.currentTimeMillis()+ TimeUnit.DAYS.toMillis(time)); + break; + case 'h': + banEndDate = new Timestamp(System.currentTimeMillis()+TimeUnit.HOURS.toMillis(time)); + break; + case 'm': + banEndDate = new Timestamp(System.currentTimeMillis()+TimeUnit.MINUTES.toMillis(time)); + break; + case 's': + banEndDate = new Timestamp(System.currentTimeMillis()+TimeUnit.SECONDS.toMillis(time)); + break; + default: + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.durationFormatError")))); + return false; + } + } + + StringBuilder newReason = new StringBuilder(); + for(int i = 3; i < args.length; i++){ + newReason.append(args[i]).append(" "); + } + if(!newReason.isEmpty()) reason=newReason.toString(); + + if(Objects.equals(duration, "-1") || Objects.equals(duration, "perm")) banEndDate = null; + + InetAddress addr; + try { + addr = InetAddress.getByName(args[0]); + } catch (UnknownHostException e){ + plugin.getLogger().severe(e.toString()); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.unexpectedError")))); + return false; + } + + try { + Connection conn = plugin.db.getConnection(); + PreparedStatement stmt = conn.prepareStatement("SELECT * FROM ip_bans WHERE (ip_address = ?::inet) AND scope = ?"); + stmt.setObject(1, addr.getHostAddress()); + stmt.setString(2, scope); + ResultSet rs = stmt.executeQuery(); + if(rs.next()){ + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.alreadyBannedInScopeError")))); + return false; + } + } catch (SQLException e){ + plugin.getLogger().severe(e.toString()); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.unexpectedError")))); + return false; + } + + IPBan b = banIp(addr, reason, scope, banEndDate, "CONSOLE", null); + + if(b != null) { + if(banEndDate == null) { + for(Player target : Bukkit.getOnlinePlayers()) { + if (target.getAddress().getAddress().equals(addr)) + if(Objects.equals(plugin.config.getString("serverID"), scope) || Objects.equals(scope, "*")) target.kick(TextUtils.colorString(TextUtils.resolvePlaceholders(plugin.translations.getString("banKickMessage.playerBanPerm"), b))); + } + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(resolveIpBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.banip.successfulBanMessagePerm")), args[0], scope, reason, "CONSOLE"))); + String bcMess = plugin.translations.getString("command.banip.banPublicAnnouncementPerm"); + if(bcMess!=null) Bukkit.broadcast(TextUtils.colorString(resolveIpBanMessagePlaceholders(bcMess, args[0], scope, reason, "CONSOLE"))); + } + else { + long timeLeft = banEndDate.getTime() - new Timestamp(System.currentTimeMillis()).getTime(); + long timeLeftDays = TimeUnit.MILLISECONDS.toDays(timeLeft); + timeLeft-=TimeUnit.DAYS.toMillis(timeLeftDays); + long timeLeftHours = TimeUnit.MILLISECONDS.toHours(timeLeft); + timeLeft-=TimeUnit.HOURS.toMillis(timeLeftHours); + long timeLeftMinutes = TimeUnit.MILLISECONDS.toMinutes(timeLeft); + timeLeft-=TimeUnit.MINUTES.toMillis(timeLeftMinutes); + long timeLeftSeconds = TimeUnit.MILLISECONDS.toSeconds(timeLeft); + String parsedBanDuration = TextUtils.parsePolishDate(timeLeftDays, timeLeftHours, timeLeftMinutes, timeLeftSeconds); + + for(Player target : Bukkit.getOnlinePlayers()) { + if (target.getAddress().getAddress().equals(addr)) + if (Objects.equals(plugin.config.getString("serverID"), scope) || Objects.equals(scope, "*")) + target.kick(TextUtils.colorString(TextUtils.resolvePlaceholders(plugin.translations.getString("banKickMessage.playerBanTemp"), b))); + } + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(resolveIpBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.banip.successfulBanMessageTemp")), args[0], scope, reason, "CONSOLE", parsedBanDuration))); + String bcMess = plugin.translations.getString("command.banip.banPublicAnnouncementTemp"); + if(bcMess!=null) Bukkit.broadcast(TextUtils.colorString(resolveIpBanMessagePlaceholders(bcMess, args[0], scope, reason, "CONSOLE", parsedBanDuration))); + + } + return true; + } + else { + plugin.getLogger().severe("BanHammer: Something went wrong while user used ban command... Maybe DB or Technician has skill issue???"); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.banip.unexpectedError")))); + return false; + } + + } + return false; + } + + private String addPrefix(String s) { + return (String)(plugin.translations.getString("prefix")+s); + } + + private IPBan banIp(InetAddress ipAddr, String reason, String scope, Timestamp endDate, String op, UUID opUuid) { + try { + Connection conn = plugin.db.getConnection(); + PreparedStatement ps = conn.prepareStatement("INSERT INTO ip_bans (ip_address, reason, scope, operator_name, operator_uuid, end_time) VALUES (?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS); + ps.setObject(1, ipAddr.getHostAddress(), Types.OTHER); + ps.setString(2, reason); + ps.setString(3, scope); + ps.setString(4, op); + ps.setObject(5, opUuid); + ps.setObject(6, endDate); + if(ps.executeUpdate() == 0) return null; + + ResultSet rs = ps.getGeneratedKeys(); + rs.next(); + + Timestamp ts = (Timestamp)rs.getObject("end_time"); + String parsedDate = null; + + if(ts!=null) { + long timeLeft = (ts).getTime() - new Timestamp(System.currentTimeMillis()).getTime(); + long timeLeftDays = TimeUnit.MILLISECONDS.toDays(timeLeft); + timeLeft-=TimeUnit.DAYS.toMillis(timeLeftDays); + long timeLeftHours = TimeUnit.MILLISECONDS.toHours(timeLeft); + timeLeft-=TimeUnit.HOURS.toMillis(timeLeftHours); + long timeLeftMinutes = TimeUnit.MILLISECONDS.toMinutes(timeLeft); + timeLeft-=TimeUnit.MINUTES.toMillis(timeLeftMinutes); + long timeLeftSeconds = TimeUnit.MILLISECONDS.toSeconds(timeLeft); + parsedDate = TextUtils.parsePolishDate(timeLeftDays, timeLeftHours, timeLeftMinutes, timeLeftSeconds); + } + + IPBan b = new IPBan(ipAddr, reason, parsedDate, op, rs.getObject("id", UUID.class)); + return b; + } + catch (SQLException e) { + plugin.getLogger().severe(e.toString()); + return null; + } + } + + private String resolveIpBanMessagePlaceholders(String s, String ipAddr, String scope, String reason, String operator) { + return s.replace("{ipAddr}", ipAddr) + .replace("{scope}", scope) + .replace("{reason}", reason) + .replace("{operator}", operator) + .replace("{prefix}", plugin.translations.getString("prefix")); + } + private String resolveIpBanMessagePlaceholders(String s, String player, String scope, String reason, String operator, String duration) { + return resolveIpBanMessagePlaceholders(s, player, scope, reason, operator).replace("{duration}", duration); + } + +} diff --git a/src/main/java/net/kuraczyk/banhammer/cmds/Unban.java b/src/main/java/net/kuraczyk/banhammer/cmds/Unban.java new file mode 100644 index 0000000..56b521c --- /dev/null +++ b/src/main/java/net/kuraczyk/banhammer/cmds/Unban.java @@ -0,0 +1,136 @@ +package net.kuraczyk.banhammer.cmds; + +import net.kuraczyk.banhammer.BanHammer; +import net.kuraczyk.banhammer.utils.TextUtils; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class Unban implements CommandExecutor { + + BanHammer plugin; + + public Unban(BanHammer p) { + plugin = p; + p.getCommand("unban").setExecutor(this); + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String lab, String[] args) { + if(sender instanceof Player) return unbanCommand((Player)sender, args); + else return unbanCommand(args); + } + + private boolean unbanCommand(Player player, String[] args){ + if(!player.hasPermission("banhammer.unban")) { + player.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unban.noPermission")))); + return false; + } + if(args.length>=3 || args.length==0) { + player.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unban.usage")))); + return false; + } + + String scope = "*"; + String playerName = args[0]; + if(args.length == 2) { + scope=args[1]; + } + + try { + Connection conn = plugin.db.getConnection(); + if(conn!=null) { + PreparedStatement ps; + if(!scope.equals("*")){ + ps = conn.prepareStatement("DELETE FROM player_bans WHERE player_name = ? AND scope = ?"); + ps.setString(1, playerName); + ps.setString(2, scope); + } + else { + ps = conn.prepareStatement("DELETE FROM player_bans WHERE player_name = ?"); + ps.setString(1, playerName); + } + + if(ps.executeUpdate()==0){ + player.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unban.alreadyNotBannedInScopeError")))); + return false; + } + } + } + catch (SQLException e) { + plugin.getLogger().severe(e.toString()); + player.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unban.unexpectedError")))); + return false; + } + + String bcMessage = plugin.translations.getString("command.unban.unbanPublicAnnouncement"); + if(bcMessage!=null) Bukkit.broadcast(TextUtils.colorString(resolveUnbanPlaceholders(bcMessage, playerName, scope, player.getName()))); + player.sendMessage(TextUtils.colorString(addPrefix(resolveUnbanPlaceholders(plugin.translations.getString("command.unban.successfulUnbanMessage"), playerName, scope, player.getName())))); + + return true; + } + private boolean unbanCommand(String[] args){ + if(args.length>=3 || args.length==0) { + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unban.usage")))); + return false; + } + + String scope = "*"; + String playerName = args[0]; + if(args.length == 2) { + scope=args[1]; + } + + try { + Connection conn = plugin.db.getConnection(); + if(conn!=null) { + PreparedStatement ps; + if(!scope.equals("*")){ + ps = conn.prepareStatement("DELETE FROM player_bans WHERE player_name = ? AND scope = ?"); + ps.setString(1, playerName); + ps.setString(2, scope); + } + else { + ps = conn.prepareStatement("DELETE FROM player_bans WHERE player_name = ?"); + ps.setString(1, playerName); + } + + if(ps.executeUpdate()==0){ + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unban.alreadyNotBannedInScopeError")))); + return false; + } + } + } + catch (SQLException e) { + plugin.getLogger().severe(e.toString()); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unban.unexpectedError")))); + return false; + } + + String bcMessage = plugin.translations.getString("command.unban.unbanPublicAnnouncement"); + if(bcMessage!=null) Bukkit.broadcast(TextUtils.colorString(resolveUnbanPlaceholders(bcMessage, playerName, scope, "CONSOLE"))); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(resolveUnbanPlaceholders(plugin.translations.getString("command.unban.successfulUnbanMessage"), playerName, scope, "CONSOLE")))); + + return true; + } + + private String addPrefix(String s) { + return (String)(plugin.translations.getString("prefix")+s); + } + + private String resolveUnbanPlaceholders(String s, String playerName, String scope, String operator){ + return s.replace("{player}", playerName) + .replace("{scope}", scope) + .replace("{operator}", operator) + .replace("{prefix}", plugin.translations.getString("prefix")); + } + +} diff --git a/src/main/java/net/kuraczyk/banhammer/cmds/UnbanIP.java b/src/main/java/net/kuraczyk/banhammer/cmds/UnbanIP.java new file mode 100644 index 0000000..ace6c91 --- /dev/null +++ b/src/main/java/net/kuraczyk/banhammer/cmds/UnbanIP.java @@ -0,0 +1,152 @@ +package net.kuraczyk.banhammer.cmds; + +import net.kuraczyk.banhammer.BanHammer; +import net.kuraczyk.banhammer.utils.TextUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class UnbanIP implements CommandExecutor { + + BanHammer plugin; + + public UnbanIP(BanHammer p) { + plugin = p; + p.getCommand("unbanip").setExecutor(this); + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String lab, String[] args) { + if(sender instanceof Player) return unbanIpCommand((Player)sender, args); + else return unbanIpCommand(args); + } + + private boolean unbanIpCommand(Player player, String[] args){ + if(!player.hasPermission("banhammer.unbanip")) { + player.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unbanip.noPermission")))); + return false; + } + if(args.length>=3 || args.length==0) { + player.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unbanip.usage")))); + return false; + } + + String scope = "*"; + if(args.length == 2) { + scope=args[1]; + } + + InetAddress ipAddr; + try { + ipAddr = InetAddress.getByName(args[0]); + } catch (UnknownHostException e){ + plugin.getLogger().severe(e.toString()); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unbanip.unexpectedError")))); + return false; + } + + try { + Connection conn = plugin.db.getConnection(); + if(conn!=null) { + PreparedStatement ps; + if(!scope.equals("*")){ + ps = conn.prepareStatement("DELETE FROM ip_bans WHERE (ip_address = ?::inet) AND scope = ?"); + ps.setString(1, ipAddr.getHostAddress()); + ps.setString(2, scope); + } + else { + ps = conn.prepareStatement("DELETE FROM ip_bans WHERE (ip_address = ?::inet)"); + ps.setString(1, ipAddr.getHostAddress()); + } + + if(ps.executeUpdate()==0){ + player.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unbanip.alreadyNotBannedInScopeError")))); + return false; + } + } + } + catch (SQLException e) { + plugin.getLogger().severe(e.toString()); + player.sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unbanip.unexpectedError")))); + return false; + } + + String bcMessage = plugin.translations.getString("command.unbanip.unbanPublicAnnouncement"); + if(bcMessage!=null) Bukkit.broadcast(TextUtils.colorString(resolveUnbanIpPlaceholders(bcMessage, ipAddr.getHostAddress().toString(), scope, player.getName()))); + player.sendMessage(TextUtils.colorString(addPrefix(resolveUnbanIpPlaceholders(plugin.translations.getString("command.unbanip.successfulUnbanMessage"), ipAddr.getHostAddress().toString(), scope, player.getName())))); + + return true; + } + private boolean unbanIpCommand(String[] args){ + if(args.length>=3 || args.length==0) { + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unbanip.usage")))); + return false; + } + + String scope = "*"; + if(args.length == 2) { + scope=args[1]; + } + + InetAddress ipAddr; + try { + ipAddr = InetAddress.getByName(args[0]); + } catch (UnknownHostException e){ + plugin.getLogger().severe(e.toString()); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unbanip.unexpectedError")))); + return false; + } + + try { + Connection conn = plugin.db.getConnection(); + if(conn!=null) { + PreparedStatement ps; + if(!scope.equals("*")){ + ps = conn.prepareStatement("DELETE FROM ip_bans WHERE (ip_address = ?::inet) AND scope = ?"); + ps.setString(1, ipAddr.getHostAddress()); + ps.setString(2, scope); + } + else { + ps = conn.prepareStatement("DELETE FROM ip_bans WHERE (ip_address = ?::inet)"); + ps.setString(1, ipAddr.getHostAddress()); + } + + if(ps.executeUpdate()==0){ + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unbanip.alreadyNotBannedInScopeError")))); + return false; + } + } + } + catch (SQLException e) { + plugin.getLogger().severe(e.toString()); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(plugin.translations.getString("command.unbanip.unexpectedError")))); + return false; + } + + String bcMessage = plugin.translations.getString("command.unbanip.unbanPublicAnnouncement"); + if(bcMessage!=null) Bukkit.broadcast(TextUtils.colorString(resolveUnbanIpPlaceholders(bcMessage, ipAddr.getHostAddress().toString(), scope, "CONSOLE"))); + Bukkit.getConsoleSender().sendMessage(TextUtils.colorString(addPrefix(resolveUnbanIpPlaceholders(plugin.translations.getString("command.unbanip.successfulUnbanMessage"), ipAddr.getHostAddress().toString(), scope, "CONSOLE")))); + + return true; + } + + private String addPrefix(String s) { + return (String)(plugin.translations.getString("prefix")+s); + } + + private String resolveUnbanIpPlaceholders(String s, String ipAddr, String scope, String operator){ + return s.replace("{ipAddr}", ipAddr) + .replace("{scope}", scope) + .replace("{operator}", operator) + .replace("{prefix}", plugin.translations.getString("prefix")); + } + +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index e02151b..266f994 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,9 +1,19 @@ name: BanHammer -version: '0.1.0-SNAPSHOT' +version: '1.0' main: net.kuraczyk.banhammer.BanHammer api-version: '1.21' commands: ban: description: "Ban a player" - permission: banhammer.ban + unban: + description: "Unban a player" + aliases: [pardon, ub] + banip: + description: "Ban IP address" + aliases: [ipban] + unbanip: + description: "Unban IP address" + aliases: [ippardon, pardonip, ubip, ipub, ipunban] + bhconfig: + description: "Control BanHammer configuration" diff --git a/src/main/resources/translations.yml b/src/main/resources/translations.yml index b737c9d..335ceaa 100644 --- a/src/main/resources/translations.yml +++ b/src/main/resources/translations.yml @@ -51,8 +51,10 @@ banKickMessage: command: ban: - usage: "<#ffffff>Użycie: <#FF5744>/ban " + noPermission: "<#AAAAAA>Nie posiadasz uprawnień! <#e63030>banhammer.ban" + usage: "<#AAAAAA>Użycie: <#e63030>/ban " durationFormatError: "<#e63030>Błąd! <#AAAAAA>Niepoprawny format <#e63030>długości kary." + alreadyBannedInScopeError: "<#AAAAAA>Gracz <#e63030>{player} już jest zbanowany w zakresie <#e63030>{scope}!" unexpectedError: "<#AAAAAA>Wystąpił <#e63030>nieoczekiwany błąd! Koniecznie skontaktuj się z <#e63030>dowolnym technicznym." successfulBanMessagePerm: "<#AAAAAA>Pomyślnie zbanowano <#e63030>{player} w zakresie <#e63030>{scope} za <#e63030>{reason}" successfulBanMessageTemp: "<#AAAAAA>Pomyślnie zbanowano <#e63030>{player} na <#e63030>{duration} w zakresie <#e63030>{scope} za <#e63030>{reason}" @@ -63,4 +65,32 @@ command: banPublicAnnouncementTemp: |- <#383838> <#383838>[BanHammer<#383838>] <#b64141>Gracz <#e63030>{player} Został zbanowany przez <#e63030>{operator} na <#e63030>{duration} za <#e63030>{reason} - <#383838> \ No newline at end of file + <#383838> + unban: + noPermission: "<#AAAAAA>Nie posiadasz uprawnień! <#e63030>banhammer.unban" + usage: "<#AAAAAA>Użycie: <#e63030>/unban " + alreadyNotBannedInScopeError: "<#AAAAAA>Gracz <#e63030>{player} nie jest zbanowany w zakresie <#e63030>{scope}!" + unexpectedError: "<#AAAAAA>Wystąpił <#e63030>nieoczekiwany błąd! Koniecznie skontaktuj się z <#e63030>dowolnym technicznym." + successfulUnbanMessage: "<#AAAAAA>Pomyślnie odbanowano <#e63030>{player} w zakresie <#e63030>{scope}" + unbanPublicAnnouncement: null + banip: + noPermission: "<#AAAAAA>Nie posiadasz uprawnień! <#e63030>banhammer.banip" + usage: "<#AAAAAA>Użycie: <#e63030>/banip " + durationFormatError: "<#e63030>Błąd! <#AAAAAA>Niepoprawny format <#e63030>długości kary." + alreadyBannedInScopeError: "<#AAAAAA>Adres <#e63030>{ipAddr} już jest zbanowany w zakresie <#e63030>{scope}!" + unexpectedError: "<#AAAAAA>Wystąpił <#e63030>nieoczekiwany błąd! Koniecznie skontaktuj się z <#e63030>dowolnym technicznym." + successfulBanMessagePerm: "<#AAAAAA>Pomyślnie zbanowano <#e63030>{ipAddr} w zakresie <#e63030>{scope} za <#e63030>{reason}" + successfulBanMessageTemp: "<#AAAAAA>Pomyślnie zbanowano <#e63030>{ipAddr} na <#e63030>{duration} w zakresie <#e63030>{scope} za <#e63030>{reason}" + banPublicAnnouncementPerm: null + banPublicAnnouncementTemp: null + unbanip: + noPermission: "<#AAAAAA>Nie posiadasz uprawnień! <#e63030>banhammer.unbanip" + usage: "<#AAAAAA>Użycie: <#e63030>/unbanip " + alreadyNotBannedInScopeError: "<#AAAAAA>Adres <#e63030>{ipAddr} nie jest zbanowany w zakresie <#e63030>{scope}!" + unexpectedError: "<#AAAAAA>Wystąpił <#e63030>nieoczekiwany błąd! Koniecznie skontaktuj się z <#e63030>dowolnym technicznym." + successfulUnbanMessage: "<#AAAAAA>Pomyślnie odbanowano <#e63030>{ipAddr} w zakresie <#e63030>{scope}" + unbanPublicAnnouncement: null + bhconfig: + noPermission: "<#AAAAAA>Nie posiadasz uprawnień! <#e63030>banhammer.unbanip" + successfullyReloaded: "<#AAAAAA><#e63030>Pomyślnie przeładowano <#e63030>konfigurację!" + unexpectedError: "<#AAAAAA>Wystąpił <#e63030>nieoczekiwany błąd! Koniecznie skontaktuj się z <#e63030>dowolnym technicznym."