AntiBot cleanup + moved to services

Some test needs to be fixed/added
This commit is contained in:
Gabriele C
2016-10-02 19:41:14 +02:00
parent c8cbd4e853
commit 88ce493438
9 changed files with 282 additions and 273 deletions
-145
View File
@@ -1,145 +0,0 @@
package fr.xephi.authme;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.ProtectionSettings;
import fr.xephi.authme.util.BukkitService;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import java.util.concurrent.CopyOnWriteArrayList;
import static fr.xephi.authme.util.BukkitService.TICKS_PER_MINUTE;
import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND;
/**
* The AntiBot Service Management class.
*/
public class AntiBot {
private final Settings settings;
private final Messages messages;
private final PermissionsManager permissionsManager;
private final BukkitService bukkitService;
private final CopyOnWriteArrayList<String> antibotKicked = new CopyOnWriteArrayList<String>();
private final CopyOnWriteArrayList<String> antibotPlayers = new CopyOnWriteArrayList<String>();
private AntiBotStatus antiBotStatus = AntiBotStatus.DISABLED;
@Inject
AntiBot(Settings settings, Messages messages, PermissionsManager permissionsManager,
BukkitService bukkitService) {
this.settings = settings;
this.messages = messages;
this.permissionsManager = permissionsManager;
this.bukkitService = bukkitService;
setupAntiBotService();
}
private void setupAntiBotService() {
if (settings.getProperty(ProtectionSettings.ENABLE_ANTIBOT)) {
bukkitService.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
antiBotStatus = AntiBotStatus.LISTENING;
}
}, 2 * TICKS_PER_MINUTE);
}
}
public void overrideAntiBotStatus(boolean activated) {
if (antiBotStatus != AntiBotStatus.DISABLED) {
if (activated) {
antiBotStatus = AntiBotStatus.ACTIVE;
} else {
antiBotStatus = AntiBotStatus.LISTENING;
}
}
}
public AntiBotStatus getAntiBotStatus() {
return antiBotStatus;
}
public void activateAntiBot() {
antiBotStatus = AntiBotStatus.ACTIVE;
for (Player player : bukkitService.getOnlinePlayers()) {
if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) {
messages.send(player, MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE);
}
}
final int duration = settings.getProperty(ProtectionSettings.ANTIBOT_DURATION);
bukkitService.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
if (antiBotStatus == AntiBotStatus.ACTIVE) {
antiBotStatus = AntiBotStatus.LISTENING;
antibotPlayers.clear();
antibotKicked.clear();
for (String s : messages.retrieve(MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE)) {
bukkitService.broadcastMessage(s.replace("%m", Integer.toString(duration)));
}
}
}
}, duration * TICKS_PER_MINUTE);
}
/**
* Handles a player joining the server and checks if AntiBot needs to be activated.
*
* @param player the player who joined the server
*/
public void handlePlayerJoin(final Player player) {
if (antiBotStatus == AntiBotStatus.ACTIVE || antiBotStatus == AntiBotStatus.DISABLED) {
return;
}
if (permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) {
return;
}
antibotPlayers.add(player.getName().toLowerCase());
if (antibotPlayers.size() > settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY)) {
activateAntiBot();
return;
}
bukkitService.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
antibotPlayers.remove(player.getName().toLowerCase());
}
}, 15 * TICKS_PER_SECOND);
}
/**
* Returns whether the player was kicked because of activated antibot. The list is reset
* when antibot is deactivated.
*
* @param name the name to check
* @return true if the given name has been kicked because of Antibot
*/
public boolean wasPlayerKicked(String name) {
return antibotKicked.contains(name.toLowerCase());
}
/**
* Adds a name to the list of players kicked by antibot. Should only be used when a player
* is determined to be kicked because of failed antibot verification.
*
* @param name the name to add
*/
public void addPlayerKick(String name) {
antibotKicked.addIfAbsent(name.toLowerCase());
}
public enum AntiBotStatus {
LISTENING,
DISABLED,
ACTIVE
}
}
@@ -1,6 +1,6 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AntiBot;
import fr.xephi.authme.service.AntiBotService;
import fr.xephi.authme.command.CommandMapper;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.command.FoundCommandResult;
@@ -18,7 +18,7 @@ import java.util.List;
public class SwitchAntiBotCommand implements ExecutableCommand {
@Inject
private AntiBot antiBot;
private AntiBotService antiBotService;
@Inject
private CommandMapper commandMapper;
@@ -29,7 +29,7 @@ public class SwitchAntiBotCommand implements ExecutableCommand {
@Override
public void executeCommand(final CommandSender sender, List<String> arguments) {
if (arguments.isEmpty()) {
sender.sendMessage("[AuthMe] AntiBot status: " + antiBot.getAntiBotStatus().name());
sender.sendMessage("[AuthMe] AntiBot status: " + antiBotService.getAntiBotStatus().name());
return;
}
@@ -37,10 +37,10 @@ public class SwitchAntiBotCommand implements ExecutableCommand {
// Enable or disable the mod
if ("ON".equalsIgnoreCase(newState)) {
antiBot.overrideAntiBotStatus(true);
antiBotService.overrideAntiBotStatus(true);
sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!");
} else if ("OFF".equalsIgnoreCase(newState)) {
antiBot.overrideAntiBotStatus(false);
antiBotService.overrideAntiBotStatus(false);
sender.sendMessage("[AuthMe] AntiBot Manual Override: disabled!");
} else {
sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!");
@@ -1,6 +1,5 @@
package fr.xephi.authme.listener;
import fr.xephi.authme.AntiBot;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
@@ -9,6 +8,7 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.service.AntiBotService;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.ProtectionSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
@@ -40,7 +40,7 @@ class OnJoinVerifier implements Reloadable {
@Inject
private PermissionsManager permissionsManager;
@Inject
private AntiBot antiBot;
private AntiBotService antiBotService;
@Inject
private ValidationService validationService;
@Inject
@@ -50,7 +50,8 @@ class OnJoinVerifier implements Reloadable {
private Pattern nicknamePattern;
OnJoinVerifier() { }
OnJoinVerifier() {
}
@PostConstruct
@@ -63,12 +64,15 @@ class OnJoinVerifier implements Reloadable {
/**
* Checks if Antibot is enabled.
*
* @param playerName the name of the player (lowercase)
* @param player the player
* @param isAuthAvailable whether or not the player is registered
*/
public void checkAntibot(String playerName, boolean isAuthAvailable) throws FailedVerificationException {
if (antiBot.getAntiBotStatus() == AntiBot.AntiBotStatus.ACTIVE && !isAuthAvailable) {
antiBot.addPlayerKick(playerName);
public void checkAntibot(Player player, boolean isAuthAvailable) throws FailedVerificationException {
if (permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) {
return;
}
if (antiBotService.shouldKick(isAuthAvailable)) {
antiBotService.addPlayerKick(player.getName());
throw new FailedVerificationException(MessageKey.KICK_ANTIBOT);
}
}
@@ -105,6 +109,7 @@ class OnJoinVerifier implements Reloadable {
* joining player is a VIP.
*
* @param event the login event to verify
*
* @return true if the player's connection should be refused (i.e. the event does not need to be processed
* further), false if the player is not refused
*/
@@ -141,7 +146,7 @@ class OnJoinVerifier implements Reloadable {
* Checks that the casing in the username corresponds to the one in the database, if so configured.
*
* @param player the player to verify
* @param auth the auth object associated with the player
* @param auth the auth object associated with the player
*/
public void checkNameCasing(Player player, PlayerAuth auth) throws FailedVerificationException {
if (auth != null && settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)) {
@@ -160,7 +165,7 @@ class OnJoinVerifier implements Reloadable {
* Checks that the player's country is admitted.
*
* @param isAuthAvailable whether or not the user is registered
* @param playerIp the ip address of the player
* @param playerIp the ip address of the player
*/
public void checkPlayerCountry(boolean isAuthAvailable,
String playerIp) throws FailedVerificationException {
@@ -193,6 +198,7 @@ class OnJoinVerifier implements Reloadable {
* Selects a non-VIP player to kick when a VIP player joins the server when full.
*
* @param onlinePlayers list of online players
*
* @return the player to kick, or null if none applicable
*/
private Player generateKickPlayer(Collection<? extends Player> onlinePlayers) {
@@ -1,11 +1,11 @@
package fr.xephi.authme.listener;
import fr.xephi.authme.AntiBot;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.service.AntiBotService;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.properties.HooksSettings;
@@ -62,7 +62,7 @@ public class PlayerListener implements Listener {
@Inject
private DataSource dataSource;
@Inject
private AntiBot antiBot;
private AntiBotService antiBotService;
@Inject
private Management management;
@Inject
@@ -218,13 +218,13 @@ public class PlayerListener implements Listener {
// Fast stuff
onJoinVerifier.checkSingleSession(name);
onJoinVerifier.checkIsValidName(name);
// Get the auth later as this may cause the single session check to fail
// Slow stuff
final PlayerAuth auth = dataSource.getAuth(name);
final boolean isAuthAvailable = (auth != null);
final String lowerName = name.toLowerCase();
onJoinVerifier.checkAntibot(lowerName, isAuthAvailable);
onJoinVerifier.checkAntibot(player, isAuthAvailable);
onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
onJoinVerifier.checkNameCasing(player, auth);
onJoinVerifier.checkPlayerCountry(isAuthAvailable, event.getAddress().getHostAddress());
@@ -234,7 +234,7 @@ public class PlayerListener implements Listener {
return;
}
antiBot.handlePlayerJoin(player);
antiBotService.handlePlayerJoin();
teleportationService.teleportOnJoin(player);
}
@@ -245,12 +245,12 @@ public class PlayerListener implements Listener {
if (settings.getProperty(RegistrationSettings.REMOVE_LEAVE_MESSAGE)) {
event.setQuitMessage(null);
} else if (settings.getProperty(RegistrationSettings.REMOVE_UNLOGGED_LEAVE_MESSAGE)) {
if(listenerService.shouldCancelEvent(event)) {
if (listenerService.shouldCancelEvent(event)) {
event.setQuitMessage(null);
}
}
if (antiBot.wasPlayerKicked(player.getName())) {
if (antiBotService.wasPlayerKicked(player.getName())) {
return;
}
@@ -268,7 +268,7 @@ public class PlayerListener implements Listener {
}
final Player player = event.getPlayer();
if (!antiBot.wasPlayerKicked(player.getName())) {
if (!antiBotService.wasPlayerKicked(player.getName())) {
management.performQuit(player);
}
}
@@ -0,0 +1,207 @@
package fr.xephi.authme.service;
import fr.xephi.authme.initialization.SettingsDependent;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.ProtectionSettings;
import fr.xephi.authme.util.BukkitService;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import javax.inject.Inject;
import java.util.concurrent.CopyOnWriteArrayList;
import static fr.xephi.authme.util.BukkitService.TICKS_PER_MINUTE;
import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND;
/**
* The AntiBot Service Management class.
*/
public class AntiBotService implements SettingsDependent {
// Instances
private final Messages messages;
private final PermissionsManager permissionsManager;
private final BukkitService bukkitService;
// Settings
private int duration;
private int sensibility;
// Service status
private AntiBotStatus antiBotStatus;
private BukkitTask disableTask;
private int antibotPlayers;
private final CopyOnWriteArrayList<String> antibotKicked = new CopyOnWriteArrayList();
@Inject
AntiBotService(Settings settings, Messages messages, PermissionsManager permissionsManager, BukkitService bukkitService) {
// Instances
this.messages = messages;
this.permissionsManager = permissionsManager;
this.bukkitService = bukkitService;
// Initial status
disableTask = null;
antibotPlayers = 0;
antiBotStatus = AntiBotStatus.DISABLED;
// Load settings and start if required
reload(settings);
}
@Override
public void reload(Settings settings) {
// Load settings
duration = settings.getProperty(ProtectionSettings.ANTIBOT_DURATION);
sensibility = settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY);
// Stop existing protection
stopProtection();
antiBotStatus = AntiBotStatus.DISABLED;
// If antibot is disabled, just stop
if (!settings.getProperty(ProtectionSettings.ENABLE_ANTIBOT)) {
return;
}
// Schedule the bot activation
bukkitService.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
antiBotStatus = AntiBotStatus.LISTENING;
}
}, 90 * TICKS_PER_SECOND);
}
protected void startProtection() {
// Disable existing antibot session
stopProtection();
// Enable the new session
antiBotStatus = AntiBotStatus.ACTIVE;
// Inform admins
for (Player player : bukkitService.getOnlinePlayers()) {
if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) {
messages.send(player, MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE);
}
}
// Schedule auto-disable
disableTask = bukkitService.runTaskLater(new Runnable() {
@Override
public void run() {
stopProtection();
}
}, duration * TICKS_PER_MINUTE);
}
private void stopProtection() {
if(antiBotStatus != AntiBotStatus.ACTIVE) {
return;
}
// Change status
antiBotStatus = AntiBotStatus.LISTENING;
antibotPlayers = 0;
antibotKicked.clear();
// Cancel auto-disable task
disableTask.cancel();
disableTask = null;
// Inform admins
for (Player player : bukkitService.getOnlinePlayers()) {
if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) {
messages.send(player, MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE, Integer.toString(duration));
}
}
}
/**
* Returns the status of the AntiBot service.
*
* @return status of the antibot service
*/
public AntiBotStatus getAntiBotStatus() {
return antiBotStatus;
}
/**
* Allows to override the status of the protection.
*
* @param started the new protection status
*/
public void overrideAntiBotStatus(boolean started) {
if (antiBotStatus == AntiBotStatus.DISABLED) {
return;
}
if (started) {
startProtection();
} else {
stopProtection();
}
}
/**
* Handles a player joining the server and checks if AntiBot needs to be activated.
*/
public void handlePlayerJoin() {
if (antiBotStatus != AntiBotStatus.LISTENING) {
return;
}
antibotPlayers++;
if (antibotPlayers > sensibility) {
startProtection();
return;
}
bukkitService.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
antibotPlayers--;
}
}, 15 * TICKS_PER_SECOND);
}
/**
* Returns if a player should be kicked due to antibot service.
*
* @param isAuthAvailable if the player is registered
* @return if the player should be kicked
*/
public boolean shouldKick(boolean isAuthAvailable) {
return !isAuthAvailable && (antiBotStatus == AntiBotStatus.ACTIVE);
}
/**
* Returns whether the player was kicked because of activated antibot. The list is reset
* when antibot is deactivated.
*
* @param name the name to check
*
* @return true if the given name has been kicked because of Antibot
*/
public boolean wasPlayerKicked(String name) {
return antibotKicked.contains(name.toLowerCase());
}
/**
* Adds a name to the list of players kicked by antibot. Should only be used when a player
* is determined to be kicked because of failed antibot verification.
*
* @param name the name to add
*/
public void addPlayerKick(String name) {
antibotKicked.addIfAbsent(name.toLowerCase());
}
public enum AntiBotStatus {
LISTENING,
DISABLED,
ACTIVE
}
}