package javastory.channel.server; import java.rmi.RemoteException; import java.util.List; import java.util.Map; import java.util.Set; import javastory.channel.ChannelCharacter; import javastory.channel.ChannelClient; import javastory.channel.ChannelServer; import javastory.tools.packets.ChannelPackets; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; public final class AutobanManager implements Runnable { private static class ExpirationEntry implements Comparable<ExpirationEntry> { public long time; public int acc; public int points; public ExpirationEntry(final long time, final int acc, final int points) { this.time = time; this.acc = acc; this.points = points; } @Override public int compareTo(final AutobanManager.ExpirationEntry o) { return (int) (this.time - o.time); } } private final Map<Integer, Integer> points = Maps.newHashMap(); private final Map<Integer, List<String>> reasons = Maps.newHashMap(); private final Set<ExpirationEntry> expirations = Sets.newTreeSet(); private static final int AUTOBAN_POINTS = 1000; private static AutobanManager instance = new AutobanManager(); public static AutobanManager getInstance() { return instance; } public final void autoban(final ChannelClient c, final String reason) { if (c.getPlayer().isGM()) { c.getPlayer().sendNotice(5, "[WARNING] A/b triggled : " + reason); return; } this.addPoints(c, AUTOBAN_POINTS, 0, reason); } public final synchronized void addPoints(final ChannelClient c, final int points, final long expiration, final String reason) { List<String> reasonList; final ChannelCharacter player = c.getPlayer(); final int acc = player.getAccountId(); if (this.points.containsKey(acc)) { final int SavedPoints = this.points.get(acc); if (SavedPoints >= AUTOBAN_POINTS) { // Already auto ban'd. return; } this.points.put(acc, SavedPoints + points); // Add reasonList = this.reasons.get(acc); reasonList.add(reason); } else { this.points.put(acc, points); reasonList = Lists.newLinkedList(); reasonList.add(reason); this.reasons.put(acc, reasonList); } if (this.points.get(acc) >= AUTOBAN_POINTS) { // See if it's sufficient // to auto ban if (player.isGM()) { player.sendNotice(5, "[WARNING] A/b triggled : " + reason); return; } final StringBuilder sb = new StringBuilder("a/b "); sb.append(player.getName()); sb.append(" (IP "); sb.append(c.getSessionIP()); sb.append("): "); for (final String s : this.reasons.get(acc)) { sb.append(s); sb.append(", "); } try { ChannelServer.getWorldInterface().broadcastMessage( ChannelPackets.serverNotice(0, "[Autoban] " + player.getName() + " banned by the system (Last reason: " + reason + ")")); } catch (final RemoteException e) { ChannelServer.pingWorld(); } // Calendar cal = Calendar.getInstance(); // cal.add(Calendar.DATE, 60); // c.getPlayer().tempban(sb.toString(), cal, 1, false); player.ban(sb.toString(), true); c.disconnect(); } else { if (expiration > 0) { this.expirations.add(new ExpirationEntry(System.currentTimeMillis() + expiration, acc, points)); } } } @Override public final void run() { final long now = System.currentTimeMillis(); for (final ExpirationEntry e : this.expirations) { if (e.time <= now) { this.points.put(e.acc, this.points.get(e.acc) - e.points); } else { return; } } } }