package net.kuraczyk.banhammer.cmds; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.papermc.paper.configuration.type.fallback.FallbackValue; 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 net.kyori.adventure.title.Title; 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.*; import java.util.Objects; import java.util.UUID; import java.util.concurrent.TimeUnit; import com.google.gson.Gson; public class Ban implements CommandExecutor { BanHammer plugin; public Ban(BanHammer p){ plugin = p; p.getCommand("ban").setExecutor(this); } @Override public boolean onCommand(CommandSender sender, Command cmd, String lab, String[] args) { if(sender instanceof Player) return banCommand((Player)sender, args); else return banCommand(args); } 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]); 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))) { p.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: p.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()){ 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) { 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))); p.sendMessage(TextUtils.colorString(resolveBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.ban.successfulBanMessagePerm")), 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(); 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))); p.sendMessage(TextUtils.colorString(resolveBanMessagePlaceholders(addPrefix(plugin.translations.getString("command.ban.successfulBanMessageTemp")), 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; } 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.ban.unexpectedError")))); return false; } } return false; } private boolean banCommand(String[] args) { 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; } private String addPrefix(String s) { return (String)(plugin.translations.getString("prefix")+s); } private PlayerBan banPlayer(String playerName, UUID playerUuid, String reason, String scope, Timestamp endDate, String op, UUID opUuid) { try { Connection conn = plugin.db.getConnection(); PreparedStatement ps = conn.prepareStatement("INSERT INTO player_bans (player_name, player_uuid, reason, scope, operator_name, operator_uuid, end_time) VALUES (?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS); ps.setString(1, playerName); ps.setObject(2, playerUuid); ps.setString(3, reason); ps.setString(4, scope); ps.setString(5, op); ps.setObject(6, opUuid); ps.setObject(7, 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); } PlayerBan b = new PlayerBan(playerName, playerUuid, reason, parsedDate, op, rs.getObject("id", UUID.class)); return b; } catch (SQLException e) { plugin.getLogger().severe(e.toString()); return null; } } private void createPlayerKickJob(IPBan b, String scope){ final Gson gson = new Gson(); try { Connection conn = plugin.db.getConnection(); JsonElement banObject = gson.toJsonTree(b); JsonObject wrapper = new JsonObject(); wrapper.addProperty("ban_type", "player"); wrapper.addProperty("ban_scope", scope); wrapper.add("ban_data", banObject); String json = gson.toJson(wrapper); PreparedStatement ps = conn.prepareStatement("SELECT pg_notify('ban_jobs', ?)"); ps.setString(1, json); ps.execute(); } catch (SQLException e) { plugin.getLogger().severe(e.toString()); } } private String resolveBanMessagePlaceholders(String s, String player, String scope, String reason, String operator) { return s.replace("{player}", player) .replace("{scope}", scope) .replace("{reason}", reason) .replace("{operator}", operator) .replace("{prefix}", plugin.translations.getString("prefix")); } private String resolveBanMessagePlaceholders(String s, String player, String scope, String reason, String operator, String duration) { return resolveBanMessagePlaceholders(s, player, scope, reason, operator).replace("{duration}", duration); } }