diff --git a/src/main/java/client/Character.java b/src/main/java/client/Character.java index ca8d5331f5..aeaa96a355 100644 --- a/src/main/java/client/Character.java +++ b/src/main/java/client/Character.java @@ -736,18 +736,6 @@ public class Character extends AbstractCharacterObject { visibleMapObjects.add(mo); } - public void ban(String reason) { - setBanned(); - try (Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("UPDATE accounts SET banned = 1, banreason = ? WHERE id = ?")) { - ps.setString(1, reason); - ps.setInt(2, accountid); - ps.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - public static boolean ban(String id, String reason, boolean accountId) { try (Connection con = DatabaseConnection.getConnection()) { if (id.matches("/[0-9]{1,3}\\..*")) { diff --git a/src/main/java/client/command/CommandContext.java b/src/main/java/client/command/CommandContext.java index 69aab059dd..c643c1f78d 100644 --- a/src/main/java/client/command/CommandContext.java +++ b/src/main/java/client/command/CommandContext.java @@ -3,15 +3,17 @@ package client.command; import database.character.CharacterSaver; import database.drop.DropProvider; import server.shop.ShopFactory; +import service.BanService; import service.TransitionService; /** * @author Ponk */ public record CommandContext(CommandsExecutor commandsExecutor, DropProvider dropProvider, ShopFactory shopFactory, - CharacterSaver characterSaver, TransitionService transitionService) { + CharacterSaver characterSaver, TransitionService transitionService, BanService banService +) { public CommandContext with(CommandsExecutor ce) { - return new CommandContext(ce, this.dropProvider, this.shopFactory, this.characterSaver, this.transitionService); + return new CommandContext(ce, dropProvider, shopFactory, characterSaver, transitionService, banService); } } diff --git a/src/main/java/client/command/commands/gm3/BanCommand.java b/src/main/java/client/command/commands/gm3/BanCommand.java index a3b23708e6..031656200e 100644 --- a/src/main/java/client/command/commands/gm3/BanCommand.java +++ b/src/main/java/client/command/commands/gm3/BanCommand.java @@ -27,15 +27,6 @@ import client.Character; import client.Client; import client.command.Command; import client.command.CommandContext; -import net.server.Server; -import server.TimerManager; -import tools.DatabaseConnection; -import tools.PacketCreator; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.concurrent.TimeUnit; public class BanCommand extends Command { { @@ -51,42 +42,6 @@ public class BanCommand extends Command { } String ign = params[0]; String reason = joinStringFrom(params, 1); - Character target = c.getChannelServer().getPlayerStorage().getCharacterByName(ign); - if (target != null) { - String readableTargetName = Character.makeMapleReadable(target.getName()); - String ip = target.getClient().getRemoteAddress(); - //Ban ip - try (Connection con = DatabaseConnection.getConnection()) { - if (ip.matches("/[0-9]{1,3}\\..*")) { - try (PreparedStatement ps = con.prepareStatement("INSERT INTO ipbans VALUES (DEFAULT, ?, ?)")) { - ps.setString(1, ip); - ps.setString(2, String.valueOf(target.getClient().getAccID())); - - ps.executeUpdate(); - } - } - } catch (SQLException ex) { - ex.printStackTrace(); - c.getPlayer().message("Error occured while banning IP address"); - c.getPlayer().message(target.getName() + "'s IP was not banned: " + ip); - } - target.getClient().banMacs(); - reason = c.getPlayer().getName() + " banned " + readableTargetName + " for " + reason + " (IP: " + ip + ") " + "(MAC: " + c.getMacs() + ")"; - target.ban(reason); - target.yellowMessage("You have been banned by #b" + c.getPlayer().getName() + " #k."); - target.yellowMessage("Reason: " + reason); - c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0)); - final Character rip = target; - TimerManager.getInstance().schedule( - () -> ctx.transitionService().disconnect(rip.getClient(), false), - TimeUnit.SECONDS.toMillis(5) - ); - Server.getInstance().broadcastMessage(c.getWorld(), PacketCreator.serverNotice(6, "[RIP]: " + ign + " has been banned.")); - } else if (Character.ban(ign, reason, false)) { - c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0)); - Server.getInstance().broadcastMessage(c.getWorld(), PacketCreator.serverNotice(6, "[RIP]: " + ign + " has been banned.")); - } else { - c.sendPacket(PacketCreator.getGMEffect(6, (byte) 1)); - } + ctx.banService().permaBan(c, ign, (byte) 0, reason); } } diff --git a/src/main/java/database/account/AccountRepository.java b/src/main/java/database/account/AccountRepository.java index 835756570e..218f758859 100644 --- a/src/main/java/database/account/AccountRepository.java +++ b/src/main/java/database/account/AccountRepository.java @@ -45,7 +45,7 @@ public class AccountRepository { } } - public Optional findIdByChrNameIgnoreCase(String name) { + public Optional findIdByChrNameIgnoreCase(String name) { String sql = """ SELECT id FROM account AS a @@ -54,7 +54,7 @@ public class AccountRepository { try (Handle handle = connection.getHandle()) { return handle.createQuery(sql) .bind("name", name) - .mapTo(Account.class) + .mapTo(Integer.class) .findOne(); } } diff --git a/src/main/java/net/PacketProcessor.java b/src/main/java/net/PacketProcessor.java index 39e83cc039..b09bb336cb 100644 --- a/src/main/java/net/PacketProcessor.java +++ b/src/main/java/net/PacketProcessor.java @@ -417,8 +417,7 @@ 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.accountService(), - channelDeps.transitionService())); + registerHandler(RecvOpcode.ADMIN_COMMAND, new AdminCommandHandler(channelDeps.banService())); 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/Server.java b/src/main/java/net/server/Server.java index 802cb71e5b..d06eba1943 100644 --- a/src/main/java/net/server/Server.java +++ b/src/main/java/net/server/Server.java @@ -829,6 +829,7 @@ public class Server { NoteService noteService = new NoteService(new NoteDao(connection)); DropProvider dropProvider = new DropProvider(new DropRepository(connection)); ShopFactory shopFactory = new ShopFactory(new ShopDao(connection)); + BanService banService = new BanService(accountService, transitionService); ChannelDependencies channelDependencies = ChannelDependencies.builder() .accountService(accountService) .characterCreator(new CharacterCreator(connection, characterRepository)) @@ -839,10 +840,10 @@ public class Server { .makerProcessor(new MakerProcessor(new MakerInfoProvider(new MakerRepository(connection)))) .dropProvider(dropProvider) .commandsExecutor(new CommandsExecutor(new CommandContext(null, dropProvider, shopFactory, - characterSaver, transitionService))) + characterSaver, transitionService, banService))) .shopFactory(shopFactory) .transitionService(transitionService) - .banService(new BanService(transitionService)) + .banService(banService) .build(); PacketProcessor.registerGameHandlerDependencies(channelDependencies); diff --git a/src/main/java/net/server/channel/handlers/AdminCommandHandler.java b/src/main/java/net/server/channel/handlers/AdminCommandHandler.java index f1112a0d9d..fa2106f4ee 100644 --- a/src/main/java/net/server/channel/handlers/AdminCommandHandler.java +++ b/src/main/java/net/server/channel/handlers/AdminCommandHandler.java @@ -30,31 +30,26 @@ import lombok.extern.slf4j.Slf4j; import net.AbstractPacketHandler; import net.packet.InPacket; import server.ItemInformationProvider; -import server.TimerManager; import server.life.LifeFactory; import server.life.Monster; import server.maps.MapObject; import server.maps.MapObjectType; import server.quest.Quest; -import service.AccountService; -import service.TransitionService; +import service.BanService; 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 final AccountService accountService; - private final TransitionService transitionService; + private final BanService banService; - public AdminCommandHandler(AccountService accountService, TransitionService transitionService) { - this.accountService = accountService; - this.transitionService = transitionService; + public AdminCommandHandler(BanService banService) { + this.banService = banService; } @Override @@ -178,34 +173,13 @@ public final class AdminCommandHandler extends AbstractPacketHandler { private void handleBlock(InPacket p, Client c) { String victimName = p.readString(); byte reason = p.readByte(); - int duration = p.readInt(); + int durationDays = 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); + banService.permaBan(c, victimName, reason, description); } else { Duration duration = Duration.ofDays(durationDays); - accountService.tempBan(accountId, duration, reason, description); + banService.tempBan(c, victimName, 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 732cc7db00..cb4fb9364d 100644 --- a/src/main/java/service/AccountService.java +++ b/src/main/java/service/AccountService.java @@ -17,7 +17,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; -import java.time.Duration; import java.time.Instant; import java.time.LocalDate; import java.util.Optional; @@ -90,7 +89,7 @@ public class AccountService { return accountRepository.findById(accountId); } - public Optional getAccountIdByChrName(String chrName) { + public Optional getAccountIdByChrName(String chrName) { return accountRepository.findIdByChrNameIgnoreCase(chrName); } @@ -302,13 +301,8 @@ 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); + public boolean ban(int accountId, Instant bannedUntil, byte banReason, String description) { + return accountRepository.setBanned(accountId, bannedUntil, banReason, description); } } diff --git a/src/main/java/service/BanService.java b/src/main/java/service/BanService.java index 62254c728b..4b73c8acc6 100644 --- a/src/main/java/service/BanService.java +++ b/src/main/java/service/BanService.java @@ -1,22 +1,27 @@ package service; import client.Character; +import client.Client; import client.autoban.AutobanFactory; import config.YamlConfig; +import lombok.extern.slf4j.Slf4j; import net.packet.Packet; import net.server.Server; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import server.TimerManager; import tools.PacketCreator; +import java.time.Duration; +import java.time.Instant; +import java.util.Optional; import java.util.concurrent.TimeUnit; +@Slf4j public class BanService { - private static final Logger log = LoggerFactory.getLogger(BanService.class); + private final AccountService accountService; private final TransitionService transitionService; - public BanService(TransitionService transitionService) { + public BanService(AccountService accountService, TransitionService transitionService) { + this.accountService = accountService; this.transitionService = transitionService; } @@ -29,7 +34,8 @@ public class BanService { return; } - chr.ban(reason); + chr.setBanned(); + accountService.ban(chr.getAccountID(), null, (byte) 0, reason); chr.sendPacket(PacketCreator.sendPolice("You have been blocked by the#b %s Police for HACK reason.#k".formatted("Cosmic"))); TimerManager.getInstance().schedule(() -> transitionService.disconnect(chr.getClient(), false), @@ -59,4 +65,50 @@ public class BanService { private boolean isExempt(Character chr) { return !YamlConfig.config.server.USE_AUTOBAN || chr.isGM() || chr.isBanned(); } + + public void permaBan(Client c, String victimName, byte reason, String description) { + ban(c, victimName, null, reason, description); + } + + public void tempBan(Client c, String victimName, Duration duration, byte reason, String description) { + ban(c, victimName, duration, reason, description); + } + + // TODO: also ban ip and macs. Table "ipbans" and "macbans" (while taking "macfilters" into consideration). + // That's how it was done previously, anyway. + private void ban(Client c, String victimName, Duration duration, byte reason, String description) { + Character victim = c.getChannelServer().getPlayerStorage().getCharacterByName(victimName); + + if (victim == null) { + Optional foundAccountId = accountService.getAccountIdByChrName(victimName); + if (foundAccountId.isEmpty()) { + c.sendPacket(PacketCreator.getGMEffect(6, (byte) 1)); + return; + } + + saveBan(foundAccountId.get(), duration, reason, description); + } else { + victim.setBanned(); + String readableName = Character.makeMapleReadable(victimName); + String ip = victim.getClient().getRemoteAddress(); + String enrichedDescription = "[%s] %s (IP: %s)".formatted(description, readableName, ip); + saveBan(victim.getAccountID(), duration, reason, enrichedDescription); + victim.sendPacket(PacketCreator.sendPolice("You have been banned by %s.".formatted(c.getPlayer().getName()))); + TimerManager.getInstance().schedule(() -> transitionService.disconnect(c, false), + TimeUnit.SECONDS.toMillis(5)); + } + + c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0)); + Server.getInstance().broadcastMessage(c.getWorld(), PacketCreator.serverNotice(6, "%s has been banned.".formatted(victimName))); + } + + private void saveBan(int accountId, Duration duration, byte reason, String description) { + final Instant bannedUntil; + if (duration != null) { + bannedUntil = Instant.now().plus(duration); + } else { + bannedUntil = null; + } + accountService.ban(accountId, bannedUntil, reason, description); + } }