diff --git a/src/main/java/client/Character.java b/src/main/java/client/Character.java index ee08af1f7b..ca8d5331f5 100644 --- a/src/main/java/client/Character.java +++ b/src/main/java/client/Character.java @@ -327,7 +327,7 @@ public class Character extends AbstractCharacterObject { private final List blockedPortals = new ArrayList<>(); private final Map area_info = new LinkedHashMap<>(); private AutobanManager autoban; - private boolean isbanned = false; + private volatile boolean isBanned = false; private boolean blockCashShop = false; private boolean allowExpGain = true; private byte pendantExp = 0, lastmobcount = 0, doorSlot = -1; @@ -10006,29 +10006,12 @@ public class Character extends AbstractCharacterObject { return area_info; } - public void block(int reason, int days, String desc) { - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.DATE, days); - final Timestamp TS = new Timestamp(cal.getTimeInMillis()); - - try (Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("UPDATE accounts SET banreason = ?, tempban = ?, greason = ? WHERE id = ?")) { - ps.setString(1, desc); - ps.setTimestamp(2, TS); - ps.setInt(3, reason); - ps.setInt(4, accountid); - ps.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - public boolean isBanned() { - return isbanned; + return isBanned; } public void setBanned() { - isbanned = true; + isBanned = true; } public List getTrockMaps() { diff --git a/src/main/java/database/account/AccountRepository.java b/src/main/java/database/account/AccountRepository.java index 95e33dd973..835756570e 100644 --- a/src/main/java/database/account/AccountRepository.java +++ b/src/main/java/database/account/AccountRepository.java @@ -45,6 +45,20 @@ public class AccountRepository { } } + public Optional findIdByChrNameIgnoreCase(String name) { + String sql = """ + SELECT id + FROM account AS a + INNER JOIN chr AS c ON a.id = c.account + WHERE lower(c.name) = lower(:name)"""; + try (Handle handle = connection.getHandle()) { + return handle.createQuery(sql) + .bind("name", name) + .mapTo(Account.class) + .findOne(); + } + } + public Integer insert(Account account) { String sql = """ INSERT INTO account (name, password, birthdate, chr_slots, login_state) @@ -140,4 +154,19 @@ public class AccountRepository { .execute() > 0; } } + + public boolean setBanned(int accountId, Instant bannedUntil, byte banReason, String description) { + String sql = """ + UPDATE account + SET banned = true, banned_until = :bannedUntil, ban_reason = :banReason, description = :description + WHERE id = :id"""; + try (Handle handle = connection.getHandle()) { + return handle.createUpdate(sql) + .bind("id", accountId) + .bind("bannedUntil", bannedUntil) + .bind("banReason", banReason) + .bind("description", description) + .execute() > 0; + } + } } diff --git a/src/main/java/net/PacketProcessor.java b/src/main/java/net/PacketProcessor.java index f41be30a24..39e83cc039 100644 --- a/src/main/java/net/PacketProcessor.java +++ b/src/main/java/net/PacketProcessor.java @@ -417,7 +417,8 @@ public final class PacketProcessor { registerHandler(RecvOpcode.SCRIPTED_ITEM, new ScriptedItemHandler()); registerHandler(RecvOpcode.TOUCHING_REACTOR, new TouchReactorHandler()); registerHandler(RecvOpcode.BEHOLDER, new BeholderHandler()); - registerHandler(RecvOpcode.ADMIN_COMMAND, new AdminCommandHandler(channelDeps.transitionService())); + registerHandler(RecvOpcode.ADMIN_COMMAND, new AdminCommandHandler(channelDeps.accountService(), + channelDeps.transitionService())); registerHandler(RecvOpcode.ADMIN_LOG, new AdminLogHandler()); registerHandler(RecvOpcode.ALLIANCE_OPERATION, new AllianceOperationHandler()); registerHandler(RecvOpcode.DENY_ALLIANCE_REQUEST, new DenyAllianceRequestHandler()); diff --git a/src/main/java/net/server/channel/handlers/AdminCommandHandler.java b/src/main/java/net/server/channel/handlers/AdminCommandHandler.java index f17508a92c..f1112a0d9d 100644 --- a/src/main/java/net/server/channel/handlers/AdminCommandHandler.java +++ b/src/main/java/net/server/channel/handlers/AdminCommandHandler.java @@ -26,10 +26,9 @@ import client.Client; import client.inventory.Inventory; import client.inventory.InventoryType; import client.inventory.manipulator.InventoryManipulator; +import lombok.extern.slf4j.Slf4j; import net.AbstractPacketHandler; import net.packet.InPacket; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import server.ItemInformationProvider; import server.TimerManager; import server.life.LifeFactory; @@ -37,19 +36,24 @@ import server.life.Monster; import server.maps.MapObject; import server.maps.MapObjectType; import server.quest.Quest; +import service.AccountService; import service.TransitionService; import tools.PacketCreator; import tools.Randomizer; +import java.time.Duration; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; +@Slf4j public final class AdminCommandHandler extends AbstractPacketHandler { - private static final Logger log = LoggerFactory.getLogger(AdminCommandHandler.class); + + private final AccountService accountService; private final TransitionService transitionService; - public AdminCommandHandler(TransitionService transitionService) { + public AdminCommandHandler(AccountService accountService, TransitionService transitionService) { + this.accountService = accountService; this.transitionService = transitionService; } @@ -89,28 +93,7 @@ public final class AdminCommandHandler extends AbstractPacketHandler { c.getPlayer().yellowMessage("Please use !ban "); break; case 0x04: // /block - victim = p.readString(); - int type = p.readByte(); //reason - int duration = p.readInt(); - String description = p.readString(); - String reason = c.getPlayer().getName() + " used /ban to ban"; - target = c.getChannelServer().getPlayerStorage().getCharacterByName(victim); - if (target != null) { - String readableTargetName = Character.makeMapleReadable(target.getName()); - String ip = target.getClient().getRemoteAddress(); - reason += readableTargetName + " (IP: " + ip + ")"; - if (duration == -1) { - target.ban(description + " " + reason); - } else { - target.block(type, duration, description); - sendPolice(target.getClient(), reason); - } - c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0)); - } else if (Character.ban(victim, reason, false)) { - c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0)); - } else { - c.sendPacket(PacketCreator.getGMEffect(6, (byte) 1)); - } + handleBlock(p, c); break; case 0x10: // /h, information added by vana -- ... hide ofcourse c.getPlayer().Hide(p.readByte() == 1); @@ -192,10 +175,37 @@ public final class AdminCommandHandler extends AbstractPacketHandler { } } - private void sendPolice(Client c, String reason) { - c.sendPacket(PacketCreator.sendPolice(String.format("You have been blocked by the#b %s Police for %s.#k", "Cosmic", reason))); - c.getPlayer().setBanned(); + private void handleBlock(InPacket p, Client c) { + String victimName = p.readString(); + byte reason = p.readByte(); + int duration = p.readInt(); + String description = p.readString(); + Character victim = c.getChannelServer().getPlayerStorage().getCharacterByName(victimName); + if (victim != null) { + banOnlineChr(c, victim, reason, duration, description); + } else if (Character.ban(victimName, c.getPlayer().getName() + " used /ban to ban", false)) { // TODO: find account id from chr name and ban + c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0)); + } else { + c.sendPacket(PacketCreator.getGMEffect(6, (byte) 1)); + } + } + + private void banOnlineChr(Client c, Character victim, byte reason, int durationDays, String description) { + victim.setBanned(); + String readableTargetName = Character.makeMapleReadable(victim.getName()); + String ip = victim.getClient().getRemoteAddress(); + description += readableTargetName + " (IP: " + ip + ")"; + int accountId = victim.getAccountID(); + if (durationDays == -1) { + accountService.permaBan(accountId, reason, description); + } else { + Duration duration = Duration.ofDays(durationDays); + accountService.tempBan(accountId, duration, reason, description); + } + victim.setBanned(); + victim.sendPacket(PacketCreator.sendPolice(String.format("You have been blocked by the#b %s Police.#k", "Cosmic"))); TimerManager.getInstance().schedule(() -> transitionService.disconnect(c, false), TimeUnit.SECONDS.toMillis(6)); + c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0)); } } diff --git a/src/main/java/service/AccountService.java b/src/main/java/service/AccountService.java index 715bbde164..c73c5ac74f 100644 --- a/src/main/java/service/AccountService.java +++ b/src/main/java/service/AccountService.java @@ -14,6 +14,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.util.Optional; @@ -66,6 +67,10 @@ public class AccountService { return accountRepository.findById(accountId); } + public Optional getAccountIdByChrName(String chrName) { + return accountRepository.findIdByChrNameIgnoreCase(chrName); + } + public boolean acceptTos(int accountId) { acceptTosMysql(accountId); acceptTosPostgres(accountId); @@ -274,4 +279,13 @@ public class AccountService { } } + public void permaBan(int accountId, byte banReason, String description) { + accountRepository.setBanned(accountId, null, banReason, description); + } + + public void tempBan(int accountId, Duration duration, byte banReason, String description) { + Instant bannedUntil = Instant.now().plus(duration); + accountRepository.setBanned(accountId, bannedUntil, banReason, description); + } + }