diff --git a/pom.xml b/pom.xml index 8ad200d..3bc3761 100644 --- a/pom.xml +++ b/pom.xml @@ -47,17 +47,12 @@ org.github.spigot 1.8.8 1.8.8 + provided cc.funkemunky.plugins Atlas - 1.6.6 - provided - - - cc.funkemunky.utils - Atlas - 1.7 + 1.7.1 provided diff --git a/src/main/java/dev/brighten/pl/AntiVPN.java b/src/main/java/dev/brighten/pl/AntiVPN.java old mode 100644 new mode 100755 index 8296462..8d7785c --- a/src/main/java/dev/brighten/pl/AntiVPN.java +++ b/src/main/java/dev/brighten/pl/AntiVPN.java @@ -1,14 +1,12 @@ package dev.brighten.pl; import cc.funkemunky.api.Atlas; -import cc.funkemunky.api.reflections.types.WrappedClass; import cc.funkemunky.api.utils.MiscUtils; import dev.brighten.pl.handlers.AlertsHandler; import dev.brighten.pl.handlers.VPNHandler; import dev.brighten.pl.vpn.VPNAPI; import org.bukkit.Bukkit; import org.bukkit.event.HandlerList; -import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; public class AntiVPN extends JavaPlugin { @@ -19,8 +17,6 @@ public class AntiVPN extends JavaPlugin { public VPNHandler vpnHandler; public AlertsHandler alertsHandler; - public String atlasVersion; - public Plugin atlasInstance; public void onEnable() { INSTANCE = this; @@ -33,19 +29,15 @@ public class AntiVPN extends JavaPlugin { public void enable() { System.out.println("Enabling Atlas hook..."); - if((atlasInstance = Bukkit.getPluginManager().getPlugin("Atlas")) != null) { - atlasVersion = atlasInstance.getDescription().getVersion(); - } else { + if(Bukkit.getPluginManager().getPlugin("Atlas") == null) { System.out.println("Atlas not found! Disabling..."); this.disable(); return; } saveDefaultConfig(); + print(true, "scanner"); - //We use reflection and check versions to add backwards compatibility for the time being. - new WrappedClass(Atlas.class).getMethod("initializeScanner", - atlasVersion.startsWith("1.6") ? JavaPlugin.class : Plugin.class, boolean.class, boolean.class) - .invoke(atlasInstance, this, true, true); + Atlas.getInstance().initializeScanner(this, true, true); print(true, "vpn api and handlers"); vpnAPI = new VPNAPI(); @@ -65,16 +57,10 @@ public class AntiVPN extends JavaPlugin { print(false, "tasks"); Bukkit.getScheduler().cancelTasks(this); - print("Save", "database"); - AntiVPN.INSTANCE.vpnAPI.database.saveDatabase(); - print(false, "threads"); - AntiVPN.INSTANCE.vpnAPI.vpnThread.shutdownNow(); + AntiVPN.INSTANCE.vpnHandler.shutdown(); print(false, "handlers"); - AntiVPN.INSTANCE.vpnAPI.vpnThread = null; - AntiVPN.INSTANCE.vpnHandler = null; - AntiVPN.INSTANCE.alertsHandler = null; MiscUtils.printToConsole("&aCompleted shutdown."); } @@ -82,8 +68,4 @@ public class AntiVPN extends JavaPlugin { private void print(boolean enable, String task) { MiscUtils.printToConsole((enable ? "&7Enabling " : "&7Disabling ") + task + "..."); } - - private void print(String custom, String task) { - MiscUtils.printToConsole("&7" + custom + "ing " + task + "..."); - } } diff --git a/src/main/java/dev/brighten/pl/commands/AlertsCommand.java b/src/main/java/dev/brighten/pl/commands/AlertsCommand.java old mode 100644 new mode 100755 diff --git a/src/main/java/dev/brighten/pl/commands/InfoCommand.java b/src/main/java/dev/brighten/pl/commands/InfoCommand.java old mode 100644 new mode 100755 index 746799f..3732238 --- a/src/main/java/dev/brighten/pl/commands/InfoCommand.java +++ b/src/main/java/dev/brighten/pl/commands/InfoCommand.java @@ -5,7 +5,8 @@ import cc.funkemunky.api.commands.ancmd.CommandAdapter; import cc.funkemunky.api.utils.Color; import cc.funkemunky.api.utils.Init; import cc.funkemunky.api.utils.MiscUtils; -import cc.funkemunky.carbon.utils.json.JSONException; +import dev.brighten.db.utils.json.JSONException; +import dev.brighten.pl.AntiVPN; import dev.brighten.pl.data.UserData; import lombok.val; import org.bukkit.Bukkit; @@ -40,6 +41,42 @@ public class InfoCommand { private static void sendData(CommandAdapter cmd, UserData data) { if(data.response != null) { + cmd.getSender().sendMessage(LINE); + sendMsg(cmd, "&6&l" + data.getPlayer().getName() + "'s Information"); + sendMsg(cmd, ""); + try { + val json = data.response.toJson(); + json.keySet().stream() + .filter(key -> { + switch(key) { + case "ip": + case "city": + case "success": + case "queriesLeft": + case "locationString": + case "usedAdvanced": + return false; + default: + return true; + } + }) + .forEach(key -> { + try { + sendMsg(cmd, "&7" + key.toUpperCase() + "&8: &f" + json.get(key)); + } catch (JSONException e) { + e.printStackTrace(); + } + }); + } catch (JSONException e) { + sendMsg(cmd, "&cThere was an error parsing the VPN response."); + e.printStackTrace(); + } + cmd.getSender().sendMessage(LINE); + } else if(AntiVPN.INSTANCE.vpnHandler.getCached().containsKey(data.uuid)) { + data.response = AntiVPN.INSTANCE.vpnHandler.getCached() + .computeIfPresent(data.uuid, + (key, value) -> AntiVPN.INSTANCE.vpnHandler.getCached().remove(key)); + cmd.getSender().sendMessage(LINE); sendMsg(cmd, "&6&l" + data.getPlayer().getName() + "'s Information"); sendMsg(cmd, ""); diff --git a/src/main/java/dev/brighten/pl/commands/ReloadCommand.java b/src/main/java/dev/brighten/pl/commands/ReloadCommand.java old mode 100644 new mode 100755 diff --git a/src/main/java/dev/brighten/pl/commands/VpnCommand.java b/src/main/java/dev/brighten/pl/commands/VpnCommand.java old mode 100644 new mode 100755 diff --git a/src/main/java/dev/brighten/pl/utils/Config.java b/src/main/java/dev/brighten/pl/config/Config.java old mode 100644 new mode 100755 similarity index 69% rename from src/main/java/dev/brighten/pl/utils/Config.java rename to src/main/java/dev/brighten/pl/config/Config.java index 889ba6a..70ba853 --- a/src/main/java/dev/brighten/pl/utils/Config.java +++ b/src/main/java/dev/brighten/pl/config/Config.java @@ -1,12 +1,13 @@ -package dev.brighten.pl.utils; +package dev.brighten.pl.config; import cc.funkemunky.api.utils.ConfigSetting; import cc.funkemunky.api.utils.Init; +import cc.funkemunky.api.utils.Priority; import java.util.ArrayList; import java.util.List; -@Init +@Init(priority = Priority.HIGH) public class Config { @ConfigSetting(name = "license") public static String license = ""; @@ -17,6 +18,9 @@ public class Config { @ConfigSetting(name = "kick-message") public static String kickMessage = ""; + @ConfigSetting(name = "kick-commands") + public static List kickCommands = new ArrayList<>(); + @ConfigSetting(name = "kick-bungee") public static boolean kickBungee = false; @@ -37,4 +41,11 @@ public class Config { @ConfigSetting(name = "fire-event") public static boolean fireEvent = true; + + /* Database Stuff */ + @ConfigSetting(path = "database.general", name = "hashIp") + public static boolean hashIp = true; + + @ConfigSetting(path = "database.general", name = "hashType") + public static String hashType = "SHA2"; } diff --git a/src/main/java/dev/brighten/pl/config/FlatfileConfig.java b/src/main/java/dev/brighten/pl/config/FlatfileConfig.java new file mode 100644 index 0000000..bdd0d06 --- /dev/null +++ b/src/main/java/dev/brighten/pl/config/FlatfileConfig.java @@ -0,0 +1,15 @@ +package dev.brighten.pl.config; + +import cc.funkemunky.api.utils.ConfigSetting; +import cc.funkemunky.api.utils.Init; +import cc.funkemunky.api.utils.Priority; + +@Init(priority = Priority.LOW) +public class FlatfileConfig { + + @ConfigSetting(path = "database.flatfile", name = "enabled") + public static boolean enabled = true; + + @ConfigSetting(path = "database.flatfile", name = "database") + public static String database = "kaurivpn"; +} diff --git a/src/main/java/dev/brighten/pl/config/MongoConfig.java b/src/main/java/dev/brighten/pl/config/MongoConfig.java new file mode 100644 index 0000000..dbb430e --- /dev/null +++ b/src/main/java/dev/brighten/pl/config/MongoConfig.java @@ -0,0 +1,30 @@ +package dev.brighten.pl.config; + +import cc.funkemunky.api.utils.ConfigSetting; +import cc.funkemunky.api.utils.Init; +import cc.funkemunky.api.utils.Priority; + +@Init(priority = Priority.LOW) +public class MongoConfig { + + @ConfigSetting(path = "database.mongo", name = "enabled") + public static boolean enabled = false; + + @ConfigSetting(path = "database.mongo", name = "ip") + public static String ip = "127.0.0.1"; + + @ConfigSetting(path = "database.mongo", name = "port") + public static int port = 27017; + + @ConfigSetting(path = "database.mongo", name = "username") + public static String username = ""; + + @ConfigSetting(path = "database.mongo", name = "password") + public static String password = ""; + + @ConfigSetting(path = "database.mongo", name = "database") + public static String database = "kaurivpn"; + + @ConfigSetting(path = "database.mongo", name = "authDatabase") + public static String authDatabase = ""; +} diff --git a/src/main/java/dev/brighten/pl/config/MySQLConfig.java b/src/main/java/dev/brighten/pl/config/MySQLConfig.java new file mode 100644 index 0000000..f5b5d68 --- /dev/null +++ b/src/main/java/dev/brighten/pl/config/MySQLConfig.java @@ -0,0 +1,31 @@ +package dev.brighten.pl.config; + +import cc.funkemunky.api.utils.ConfigSetting; +import cc.funkemunky.api.utils.Init; +import cc.funkemunky.api.utils.Priority; + +@Init(priority = Priority.LOW) +public class MySQLConfig { + + @ConfigSetting(path = "database.mysql", name = "enabled") + public static boolean enabled = false; + + @ConfigSetting(path = "database.mysql", name = "ip") + public static String ip = "127.0.0.1"; + + @ConfigSetting(path = "database.mysql", name = "port") + public static int port = 3306; + + @ConfigSetting(path = "database.mysql", name = "username") + public static String username = "root"; + + @ConfigSetting(path = "database.mysql", name = "password") + public static String password = "password"; + + @ConfigSetting(path = "database.mysql", name = "database") + public static String database = "kaurivpn"; + + @ConfigSetting(path = "database.mysql", name = "ssl") + public static boolean ssl = true; + +} diff --git a/src/main/java/dev/brighten/pl/data/UserData.java b/src/main/java/dev/brighten/pl/data/UserData.java old mode 100644 new mode 100755 diff --git a/src/main/java/dev/brighten/pl/handlers/AlertsHandler.java b/src/main/java/dev/brighten/pl/handlers/AlertsHandler.java old mode 100644 new mode 100755 index 8045406..bf8e16b --- a/src/main/java/dev/brighten/pl/handlers/AlertsHandler.java +++ b/src/main/java/dev/brighten/pl/handlers/AlertsHandler.java @@ -1,17 +1,14 @@ package dev.brighten.pl.handlers; import cc.funkemunky.api.utils.JsonMessage; +import dev.brighten.pl.config.Config; import dev.brighten.pl.data.UserData; -import dev.brighten.pl.utils.Config; import dev.brighten.pl.utils.StringUtils; import dev.brighten.pl.vpn.VPNResponse; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; import java.util.UUID; public class AlertsHandler { diff --git a/src/main/java/dev/brighten/pl/handlers/VPNHandler.java b/src/main/java/dev/brighten/pl/handlers/VPNHandler.java old mode 100644 new mode 100755 index 0f2bb74..b466cb2 --- a/src/main/java/dev/brighten/pl/handlers/VPNHandler.java +++ b/src/main/java/dev/brighten/pl/handlers/VPNHandler.java @@ -1,54 +1,58 @@ package dev.brighten.pl.handlers; -import cc.funkemunky.api.Atlas; -import cc.funkemunky.api.utils.MiscUtils; +import cc.funkemunky.api.bungee.BungeeAPI; import cc.funkemunky.api.utils.RunUtils; import cc.funkemunky.api.utils.Tuple; import dev.brighten.pl.AntiVPN; +import dev.brighten.pl.config.Config; import dev.brighten.pl.data.UserData; -import dev.brighten.pl.listeners.impl.VPNCheckEvent; -import dev.brighten.pl.utils.Config; import dev.brighten.pl.utils.StringUtils; import dev.brighten.pl.vpn.VPNResponse; +import lombok.Getter; import lombok.val; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import java.util.*; -import java.util.concurrent.TimeUnit; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.atomic.AtomicBoolean; public class VPNHandler { - private LinkedList> queue = new LinkedList<>(); - private AtomicBoolean checking = new AtomicBoolean(false); - private List> toAdd = new ArrayList<>(); - public Map toKick = new HashMap<>(); + public final Deque> queue = new LinkedBlockingDeque<>(); + public final AtomicBoolean checking = new AtomicBoolean(true); + @Getter + private Map cached = new HashMap<>(); + public ExecutorService thread = Executors.newSingleThreadScheduledExecutor(); public void run() { - AntiVPN.INSTANCE.vpnAPI.vpnThread.scheduleAtFixedRate(() -> { - if(!checking.get()) { - Tuple element; - checking.set(true); - while(queue.size() > 0 && (element = queue.poll()) != null) { - val response = AntiVPN.INSTANCE.vpnAPI.getResponse(element.two); - if(response != null && response.isSuccess()) { - UserData data = UserData.getData(element.one); - data.response = response; - VPNCheckEvent event = new VPNCheckEvent(response); - if(Config.fireEvent) - RunUtils.task(() -> Bukkit.getPluginManager().callEvent(event), AntiVPN.INSTANCE); + thread.execute(() -> { + if(checking.get()) { + Tuple value; - if(response.isProxy()) { - if(Config.alertStaff) alert(response, element.one); - if(Config.kickPlayers) kick(response, element.one); - } - } else MiscUtils.printToConsole((response != null) + "?"); + while((value = queue.poll()) != null) { + val response = AntiVPN.INSTANCE.vpnAPI.getResponse(value.two); + + if(response != null) { + UserData data = UserData.getData(value.one); + + if(data != null && data.getPlayer() != null) { + data.response = response; + + if(data.response.isProxy()) { + alert(response, value.one); + kick(response, value.one); + } + } else cached.put(value.one, response); + } else queue.add(value); } - checking.set(false); - queue.addAll(toAdd); - toAdd.clear(); + run(); } - }, 0L, 20L, TimeUnit.MILLISECONDS); + }); } private void alert(VPNResponse response, UUID uuid) { if(Config.alertBungee) { @@ -60,23 +64,29 @@ public class VPNHandler { private void kick(VPNResponse response, UUID uuid) { if(Config.kickBungee) { - Atlas.getInstance().getBungeeManager().getBungeeAPI() - .kickPlayer(uuid, StringUtils.formatString(Config.kickMessage, response)); + BungeeAPI.kickPlayer(uuid, StringUtils.formatString(Config.kickMessage, response)); } else { Player player = Bukkit.getPlayer(uuid); - RunUtils.task(() -> { - String message = StringUtils.formatString(Config.kickMessage, response); - if(player != null) + if(player != null) { + RunUtils.task(() -> { + String message = StringUtils.formatString(Config.kickMessage, response); player.kickPlayer(message); - else toKick.put(uuid, message); - }); + }); + } } } + public void shutdown() { + checking.set(false); + thread.shutdown(); + } + public void checkPlayer(Player player) { - if(!checking.get()) - queue.add(new Tuple<>(player.getUniqueId(), player.getAddress().getAddress().getHostAddress())); - else toAdd.add(new Tuple<>(player.getUniqueId(), player.getAddress().getAddress().getHostAddress())); + checkPlayer(player.getUniqueId(), player.getAddress().getAddress().getHostAddress()); + } + + public void checkPlayer(UUID uuid, String address) { + queue.add(new Tuple<>(uuid, address)); } } diff --git a/src/main/java/dev/brighten/pl/listeners/JoinListener.java b/src/main/java/dev/brighten/pl/listeners/JoinListener.java old mode 100644 new mode 100755 index ac2c07c..2ecc1cc --- a/src/main/java/dev/brighten/pl/listeners/JoinListener.java +++ b/src/main/java/dev/brighten/pl/listeners/JoinListener.java @@ -1,27 +1,38 @@ package dev.brighten.pl.listeners; import cc.funkemunky.api.utils.Init; +import cc.funkemunky.api.utils.Tuple; import dev.brighten.pl.AntiVPN; +import dev.brighten.pl.config.Config; import dev.brighten.pl.data.UserData; +import dev.brighten.pl.utils.StringUtils; +import lombok.val; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; +import org.bukkit.event.player.PlayerLoginEvent; @Init public class JoinListener implements Listener { - @EventHandler(priority = EventPriority.MONITOR) - public void onJoin(PlayerJoinEvent event) { - if(AntiVPN.INSTANCE.vpnHandler.toKick.containsKey(event.getPlayer().getUniqueId())) { - event.getPlayer().kickPlayer(AntiVPN.INSTANCE.vpnHandler.toKick - .compute(event.getPlayer().getUniqueId(), - (key, val) -> AntiVPN.INSTANCE.vpnHandler.toKick.remove(key))); - return; - } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) + public void onEvent(AsyncPlayerPreLoginEvent event) { + AntiVPN.INSTANCE.vpnHandler.checkPlayer(event.getUniqueId(), event.getAddress().getHostAddress()); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onEvent(PlayerLoginEvent event) { UserData data = UserData.getData(event.getPlayer().getUniqueId()); - data.getPlayer(); - AntiVPN.INSTANCE.vpnHandler.checkPlayer(event.getPlayer()); + + if(AntiVPN.INSTANCE.vpnHandler.getCached().containsKey(event.getPlayer().getUniqueId())) { + val result = AntiVPN.INSTANCE.vpnHandler.getCached().get(event.getPlayer().getUniqueId()); + if(result.isProxy()) { + event.setKickMessage(StringUtils.formatString(Config.kickMessage, result)); + event.setResult(PlayerLoginEvent.Result.KICK_BANNED); + } + } } } diff --git a/src/main/java/dev/brighten/pl/listeners/impl/VPNCheckEvent.java b/src/main/java/dev/brighten/pl/listeners/impl/VPNCheckEvent.java old mode 100644 new mode 100755 diff --git a/src/main/java/dev/brighten/pl/utils/JsonReader.java b/src/main/java/dev/brighten/pl/utils/JsonReader.java deleted file mode 100644 index df61e2d..0000000 --- a/src/main/java/dev/brighten/pl/utils/JsonReader.java +++ /dev/null @@ -1,32 +0,0 @@ -package dev.brighten.pl.utils; - -import cc.funkemunky.carbon.utils.json.JSONException; -import cc.funkemunky.carbon.utils.json.JSONObject; - -import java.io.*; -import java.net.URL; -import java.nio.charset.Charset; - -public class JsonReader { - - private static String readAll(Reader rd) throws IOException { - StringBuilder sb = new StringBuilder(); - int cp; - while ((cp = rd.read()) != -1) { - sb.append((char) cp); - } - return sb.toString(); - } - - public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException { - InputStream is = new URL(url).openStream(); - try { - BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8"))); - String jsonText = readAll(rd); - JSONObject json = new JSONObject(jsonText); - return json; - } finally { - is.close(); - } - } -} \ No newline at end of file diff --git a/src/main/java/dev/brighten/pl/utils/StringUtils.java b/src/main/java/dev/brighten/pl/utils/StringUtils.java old mode 100644 new mode 100755 index 9502617..2c01bef --- a/src/main/java/dev/brighten/pl/utils/StringUtils.java +++ b/src/main/java/dev/brighten/pl/utils/StringUtils.java @@ -1,7 +1,7 @@ package dev.brighten.pl.utils; import cc.funkemunky.api.utils.Color; -import cc.funkemunky.carbon.utils.json.JSONException; +import dev.brighten.db.utils.json.JSONException; import dev.brighten.pl.vpn.VPNResponse; import lombok.val; diff --git a/src/main/java/dev/brighten/pl/vpn/VPNAPI.java b/src/main/java/dev/brighten/pl/vpn/VPNAPI.java old mode 100644 new mode 100755 index ea93354..2994b14 --- a/src/main/java/dev/brighten/pl/vpn/VPNAPI.java +++ b/src/main/java/dev/brighten/pl/vpn/VPNAPI.java @@ -1,40 +1,74 @@ package dev.brighten.pl.vpn; -import cc.funkemunky.api.utils.MathUtils; import cc.funkemunky.api.utils.MiscUtils; -import cc.funkemunky.api.utils.RunUtils; -import cc.funkemunky.carbon.db.Database; -import cc.funkemunky.carbon.db.StructureSet; -import cc.funkemunky.carbon.db.flatfile.FlatfileDatabase; -import cc.funkemunky.carbon.utils.Pair; -import cc.funkemunky.carbon.utils.json.JSONException; -import cc.funkemunky.carbon.utils.json.JSONObject; -import dev.brighten.pl.AntiVPN; -import dev.brighten.pl.utils.Config; -import dev.brighten.pl.utils.JsonReader; +import dev.brighten.db.db.*; +import dev.brighten.db.utils.json.JSONException; +import dev.brighten.db.utils.json.JSONObject; +import dev.brighten.db.utils.json.JsonReader; +import dev.brighten.db.utils.security.hash.Hash; +import dev.brighten.db.utils.security.hash.HashType; +import dev.brighten.pl.config.Config; +import dev.brighten.pl.config.FlatfileConfig; +import dev.brighten.pl.config.MongoConfig; +import dev.brighten.pl.config.MySQLConfig; import lombok.val; import org.bukkit.entity.Player; import java.io.IOException; -import java.util.Objects; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; +import java.util.Arrays; +import java.util.Comparator; +import java.util.concurrent.TimeUnit; public class VPNAPI { public Database database; - public ScheduledExecutorService vpnThread; + + public Hash hashAlgorithm; public VPNAPI() { MiscUtils.printToConsole("&cLoading VPNHandler&7..."); - MiscUtils.printToConsole("&7Setting up Carbon database &eVPN-Cache&7..."); - database = new FlatfileDatabase("VPN-Cache"); - MiscUtils.printToConsole("&7Registering listener..."); - vpnThread = Executors.newScheduledThreadPool(2); + MiscUtils.printToConsole("&7Setting up Carbon database..."); + if(FlatfileConfig.enabled) { + setupFlatfile(); + } else if(MySQLConfig.enabled && MongoConfig.enabled) { + MiscUtils.printToConsole("&7Both MySQL and Mongo enabled! Defaulting to Flatfile."); + setupFlatfile(); + } else if(MongoConfig.enabled) { + MiscUtils.printToConsole("&7Setting up Mongo database &f" + MongoConfig.database + "&7..."); + database = new MongoDatabase(MongoConfig.database); - //Running saveDatabase task. - MiscUtils.printToConsole("&7Running database saving task..."); - RunUtils.taskTimerAsync(database::saveDatabase, AntiVPN.INSTANCE, 0, 20 * 60 * 2); + if(MongoConfig.username.length() > 0) { + val authDB = MongoConfig.authDatabase.length() > 0 ? MongoConfig.authDatabase : MongoConfig.database; + + MiscUtils.printToConsole("&7Connecting to database with credentials to " + authDB + "..."); + database.connect(MongoConfig.ip, String.valueOf(MongoConfig.port), + authDB, MongoConfig.username, MongoConfig.password, MongoConfig.database); + } else { + MiscUtils.printToConsole("&7Connecting to database without credentials..."); + database.connect(MongoConfig.ip, String.valueOf(MongoConfig.port), MongoConfig.database); + } + } else if(MySQLConfig.enabled) { + database = new MySQLDatabase(MySQLConfig.database); + + MiscUtils.printToConsole("&7Connecting to MySQL database..."); + database.connect(MySQLConfig.ip, String.valueOf(MySQLConfig.port), MySQLConfig.database, + String.valueOf(MySQLConfig.ssl), MySQLConfig.username, MySQLConfig.password); + } else { + MiscUtils.printToConsole("&7No database enabled! No caching will occur."); + } + + if(database != null) { + MiscUtils.printToConsole("&7Loading database mappings..."); + database.loadMappings(); + } + + MiscUtils.printToConsole("&7Checking hash algorithm " + Config.hashType + "..."); + if(Config.hashIp) { + Hash.loadHashes(); + hashAlgorithm = Hash.getHashByType(Arrays.stream(HashType.values()) + .filter(type -> type.name().equalsIgnoreCase(Config.hashType)).findFirst().orElse(HashType.SHA1)); + MiscUtils.printToConsole("&7Using Hash algorithm &f" + hashAlgorithm.hashType.name() + "&7."); + } else MiscUtils.printToConsole("&7Hashing is not enabled."); } public VPNResponse getResponse(Player player) { @@ -42,30 +76,25 @@ public class VPNAPI { } public void cacheReponse(VPNResponse response) { - if(response.isSuccess()) { + if(database != null && response.isSuccess()) { try { //Removing old value if it contains it. if(database.contains(response.getIp())) database.remove(response.getIp()); val json = response.toJson(); - - val pairs = json.keySet().stream().map(key -> { - try { - return new Pair<>(key, json.get(key)); - } catch (JSONException e) { - e.printStackTrace(); - } - return null; - }).filter(Objects::nonNull).toArray(Pair[]::new); - - StructureSet set = database.createStructure(response.getIp(), pairs); - - if(MathUtils.getDelta(set.getObjects().size(), pairs.length) > 1) { - MiscUtils.printToConsole("&cThere was an error saving response for IP &f" - + response.getIp() + "&c. &7Removing from database..."); - database.remove(response.getIp()); + if(hashAlgorithm != null && json.has("ip")) { + json.put("ip", hashAlgorithm.hash(json.getString("ip"))); } + + StructureSet set = database.create(response.getIp()); + + for (String key : json.keySet()) { + set.input(key, json.get(key)); + } + + set.save(database); + } catch (JSONException e) { e.printStackTrace(); } @@ -73,11 +102,44 @@ public class VPNAPI { } public VPNResponse getIfCached(String ipAddress) { - if(database.contains(ipAddress)) { - return VPNResponse.fromSet(database.get(ipAddress)); - } else { - return null; + if(database != null && database.contains(ipAddress)) { + val list = hashAlgorithm != null + ? database.get(set -> hashAlgorithm.hashEqualsKey(set.getObject("ip"), ipAddress)) + : database.get(ipAddress); + + if(list.size() > 0) { + long timeStamp = System.currentTimeMillis(); + if(list.size() == 1) { + val response = VPNResponse.fromSet(database.get(ipAddress).get(0)); + + if(timeStamp - response.getCacheTime() < TimeUnit.DAYS.toMillis(7)) { + return response; + } else { + database.remove(response.getIp()); + } + } else {; + for (StructureSet set : list) { + if(!set.contains("cacheTime")){ + set.input("cacheTime", timeStamp); + continue; + } + long cacheTime = set.getObject("cacheTime"); + if(timeStamp - cacheTime > TimeUnit.DAYS.toMillis(7)) { + database.remove(set.getId()); + list.remove(set); + } + } + + if(list.size() > 0) { + val ip = list.stream() + .max(Comparator.comparing(set -> (long)set.getObject("cacheTime"))).get(); + + return VPNResponse.fromSet(ip); + } + } + } } + return null; } public VPNResponse getResponse(String ipAddress) { @@ -92,14 +154,21 @@ public class VPNAPI { JSONObject object = JsonReader.readJsonFromUrl(url); - val toCacheAndReturn = VPNResponse.fromJson(object.toString()); + if(object.has("success") && object.getBoolean("success")) { + val toCacheAndReturn = VPNResponse.fromJson(object.toString()); - cacheReponse(toCacheAndReturn); + cacheReponse(toCacheAndReturn); - return toCacheAndReturn; + return toCacheAndReturn; + } else System.out.println("failed"); } catch (IOException | JSONException e) { e.printStackTrace(); } return null; } + + private void setupFlatfile() { + MiscUtils.printToConsole("&7Setting up Flatfile Database &f" + FlatfileConfig.database + "&7..."); + database = new FlatfileDatabase(FlatfileConfig.database); + } } \ No newline at end of file diff --git a/src/main/java/dev/brighten/pl/vpn/VPNResponse.java b/src/main/java/dev/brighten/pl/vpn/VPNResponse.java old mode 100644 new mode 100755 index 860a406..19f251e --- a/src/main/java/dev/brighten/pl/vpn/VPNResponse.java +++ b/src/main/java/dev/brighten/pl/vpn/VPNResponse.java @@ -1,8 +1,8 @@ package dev.brighten.pl.vpn; -import cc.funkemunky.carbon.db.StructureSet; -import cc.funkemunky.carbon.utils.json.JSONException; -import cc.funkemunky.carbon.utils.json.JSONObject; +import dev.brighten.db.db.StructureSet; +import dev.brighten.db.utils.json.JSONException; +import dev.brighten.db.utils.json.JSONObject; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @@ -13,6 +13,7 @@ import lombok.Setter; public class VPNResponse { private String ip, countryName, countryCode, method, state, city, isp, timeZone, locationString; private boolean proxy, usedAdvanced, cached, success; + private long cacheTime; private double score; private int queriesLeft; @@ -29,6 +30,7 @@ public class VPNResponse { json.put("score", score); json.put("proxy", proxy); json.put("success", success); + json.put("cacheTime", cacheTime); json.put("timeZone", timeZone); json.put("success", true); json.put("queriesLeft", queriesLeft); @@ -48,20 +50,21 @@ public class VPNResponse { jsonObject.getString("city"), jsonObject.getString("isp"), jsonObject.getString("timeZone"), jsonObject.getString("locationString"), jsonObject.getBoolean("proxy"), jsonObject.getBoolean("usedAdvanced"), - jsonObject.getBoolean("cached"), jsonObject.getBoolean("success"), + jsonObject.getBoolean("cached"), jsonObject.getBoolean("success"), -1, jsonObject.has("score") ? jsonObject.getDouble("score") : -1, jsonObject.getInt("queriesLeft")); } public static VPNResponse fromSet(StructureSet set) { - return new VPNResponse(set.getField("ip"), set.getField("countryName"), - set.containsKey("method") ? set.getField("method") : "N/A", - set.getField("countryCode"), set.getField("state"), - set.getField("city"), set.getField("isp"), - set.getField("timeZone"), set.getField("locationString"), - set.getField("proxy"), set.getField("usedAdvanced"), - set.getField("cached"), set.getField("success"), - set.containsKey("score") ? set.getDouble("score") : -1, - set.getField("queriesLeft")); + return new VPNResponse(set.getObject("ip"), set.getObject("countryName"), + set.contains("method") ? set.getObject("method") : "N/A", + set.getObject("countryCode"), set.getObject("state"), + set.getObject("city"), set.getObject("isp"), + set.getObject("timeZone"), set.getObject("locationString"), + set.getObject("proxy"), set.getObject("usedAdvanced"), + set.getObject("cached"), set.getObject("success"), + set.contains("cacheTime") ? set.getObject("cacheTime") : 01, + set.contains("score") ? (double)set.getObject("score") : -1, + set.getObject("queriesLeft")); } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml old mode 100644 new mode 100755 index 3a6ed1b..88532a0 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -5,6 +5,51 @@ # license: "" # +# Caching Database # +# Types: Mongo, Flatfile, MySQL. +# +# FLATFILE INFORMATION # +# Flatfile is enabled by default if nothing else is enabled. +# Make sure to only enable one at a time or plugin will default to Flatfile. +# The database will be stored in the root directory of the user that started the server. +# Each entry will be stored as a .json file in the directory with the ID of as its name. +# (user directory)/CarbonFFDBs/{database} +# +# MONGO INFORMATION # +# For Mongo, leave credentials empty if your mongo instance doesn't require it. +# The authDatabase is used if your mongo credentials are tied to a different database. +# +# MYSQL INFORMATION # +# It is recommended you turn SSL to true for secure transfer of information. +# +# GENERAL INFORMATION # +# It is highly recommended you leave the hashIp setting to true and the hash algorithm to SHA2. +# Hash Options: CRC16, SHA1, SHA2, Argon. +# This will hash the IPs into a SHA1 or SHA2 string to protect your users privacy. +# More information on SHA-2: https://en.wikipedia.org/wiki/SHA-2 +database: + flatfile: + enabled: true + database: "kaurivpn" + mongo: + enabled: false + ip: "127.0.0.1" + port: 27017 + username: "" + password: "" + database: "kaurivpn" + authDatabase: "" + mysql: + enabled: false + ip: "127.0.0.1" + port: 3306 + username: "root" + password: "password" + database: "kaurivpn" + ssl: true + general: + hashIp: true + hashType: "SHA2" # Enable kicking # # You can disable the function of removing players from the server. kick-players: true @@ -21,6 +66,10 @@ kick-message: |- # This will allow the command to be run in Bungee. kick-bungee: false # +# Kick Commands # +# These will be run on player kicks. +kick-commands: [] +# # VPN Use Alerts # # A great way to find nefarious players quickly (i.e. cheaters) without them knowing what is going on. alert-staff: true diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml old mode 100644 new mode 100755