Adding Velocity support to AntiVPN (1.5)

This commit is contained in:
Dawson Hessler
2021-09-14 18:41:24 -04:00
parent e37b4c3e6f
commit 9f05467553
22 changed files with 1420 additions and 12 deletions
@@ -0,0 +1,39 @@
package dev.brighten.antivpn.velocity;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.api.APIPlayer;
import dev.brighten.antivpn.command.CommandExecutor;
import lombok.RequiredArgsConstructor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import java.util.Optional;
@RequiredArgsConstructor
public class VelocityCommandExecutor implements CommandExecutor {
private final CommandSource sender;
@Override
public void sendMessage(String message) {
sender.sendMessage(LegacyComponentSerializer.builder().character('&').build().deserialize(message));
}
@Override
public boolean hasPermission(String permission) {
return sender.hasPermission(permission);
}
@Override
public Optional<APIPlayer> getPlayer() {
if(!isPlayer()) return Optional.empty();
return AntiVPN.getInstance().getPlayerExecutor().getPlayer(((Player) sender).getUniqueId());
}
@Override
public boolean isPlayer() {
return sender instanceof Player;
}
}
@@ -0,0 +1,166 @@
package dev.brighten.antivpn.velocity;
import dev.brighten.antivpn.api.VPNConfig;
import dev.brighten.antivpn.velocity.util.ConfigDefault;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class VelocityConfig implements VPNConfig {
private final ConfigDefault<String> licenseDefault = new ConfigDefault<>("",
"license", VelocityPlugin.INSTANCE), kickStringDefault =
new ConfigDefault<>("Proxies are not allowed on our server",
"kickMessage", VelocityPlugin.INSTANCE),
defaultDatabaseType = new ConfigDefault<>("MySQL",
"database.type", VelocityPlugin.INSTANCE),
defaultDatabaseName = new ConfigDefault<>("kaurivpn",
"database.database", VelocityPlugin.INSTANCE),
defaultUsername = new ConfigDefault<>("root",
"database.username", VelocityPlugin.INSTANCE),
defaultPassword = new ConfigDefault<>("password",
"database.password", VelocityPlugin.INSTANCE),
defaultAuthDatabase = new ConfigDefault<>("admin",
"database.auth", VelocityPlugin.INSTANCE),
defaultIp = new ConfigDefault<>("localhost", "database.ip", VelocityPlugin.INSTANCE),
defaultAlertMsg = new ConfigDefault<>("&8[&6KauriVPN&8] &e%player% &7has joined on a VPN/proxy" +
" &8(&f%reason%&8) &7in location &8(&f%city%&7, &f%country%&8)", "alerts.message",
VelocityPlugin.INSTANCE);
private final ConfigDefault<Boolean> cacheResultsDefault = new ConfigDefault<>(true,
"cachedResults", VelocityPlugin.INSTANCE),
defaultDatabaseEnabled = new ConfigDefault<>(false, "database.enabled",
VelocityPlugin.INSTANCE), defaultCommandsEnable = new ConfigDefault<>(false,
"commands.enabled", VelocityPlugin.INSTANCE), defaultKickPlayers
= new ConfigDefault<>(true, "kickPlayers", VelocityPlugin.INSTANCE),
defaultAlertToStaff = new ConfigDefault<>(true, "alerts.enabled",
VelocityPlugin.INSTANCE),
defaultMetrics = new ConfigDefault<>(true, "bstats", VelocityPlugin.INSTANCE);
private final ConfigDefault<Integer>
defaultPort = new ConfigDefault<>(-1, "database.port", VelocityPlugin.INSTANCE);
private final ConfigDefault<List<String>> prefixWhitelistsDefault = new ConfigDefault<>(new ArrayList<>(),
"prefixWhitelists", VelocityPlugin.INSTANCE), defaultCommands = new ConfigDefault<>(
Collections.singletonList("kick %player% VPNs are not allowed on our server!"), "commands.execute",
VelocityPlugin.INSTANCE);
private String license, kickMessage, databaseType, databaseName, username, password, ip, alertMsg;
private List<String> prefixWhitelists, commands;
private int port;
private boolean cacheResults, databaseEnabled, commandsEnabled, kickPlayers, alertToStaff, metrics;
@Override
public String getLicense() {
return license;
}
@Override
public boolean cachedResults() {
return cacheResults;
}
@Override
public String getKickString() {
return kickMessage;
}
@Override
public String alertMessage() {
return alertMsg;
}
@Override
public boolean alertToStaff() {
return alertToStaff;
}
@Override
public boolean runCommands() {
return commandsEnabled;
}
@Override
public List<String> commands() {
return commands;
}
@Override
public boolean kickPlayersOnDetect() {
return kickPlayers;
}
@Override
public List<String> getPrefixWhitelists() {
return prefixWhitelists;
}
@Override
public boolean isDatabaseEnabled() {
return databaseEnabled;
}
@Override
public String getDatabaseType() {
return databaseType;
}
@Override
public String getDatabaseName() {
return databaseName;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getIp() {
return ip;
}
@Override
public int getPort() {
if(port == -1) {
switch (getDatabaseType().toLowerCase()) {
case "mongodb":
case "mongo":
case "mongod":
return 27017;
case "sql":
case "mysql":
return 3306;
}
}
return port;
}
@Override
public boolean metrics() {
return metrics;
}
public void update() {
license = licenseDefault.get();
kickMessage = kickStringDefault.get();
cacheResults = cacheResultsDefault.get();
prefixWhitelists = prefixWhitelistsDefault.get();
databaseEnabled = defaultDatabaseEnabled.get();
databaseType = defaultDatabaseType.get();
databaseName = defaultDatabaseName.get();
username = defaultUsername.get();
password = defaultPassword.get();
ip = defaultIp.get();
port = defaultPort.get();
commandsEnabled = defaultCommandsEnable.get();
commands = defaultCommands.get();
kickPlayers = defaultKickPlayers.get();
alertToStaff = defaultAlertToStaff.get();
alertMsg = defaultAlertMsg.get();
metrics = defaultMetrics.get();
}
}
@@ -0,0 +1,91 @@
package dev.brighten.antivpn.velocity;
import com.velocitypowered.api.event.connection.LoginEvent;
import com.velocitypowered.api.scheduler.ScheduledTask;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.api.APIPlayer;
import dev.brighten.antivpn.api.VPNExecutor;
import dev.brighten.antivpn.velocity.util.StringUtils;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public class VelocityListener extends VPNExecutor {
private ScheduledTask cacheResetTask;
@Override
public void registerListeners() {
VelocityPlugin.INSTANCE.getServer().getEventManager()
.register(VelocityPlugin.INSTANCE, this);
VelocityPlugin.INSTANCE.getServer().getEventManager().register(VelocityPlugin.INSTANCE, LoginEvent.class,
event -> {
if(event.getResult().isAllowed()) {
if(event.getPlayer().hasPermission("antivpn.bypass") //Has bypass permission
|| AntiVPN.getInstance().getExecutor().isWhitelisted(event.getPlayer().getUniqueId()) //Is exempt
//Or has a name that starts with a certain prefix. This is for Bedrock exempting.
|| AntiVPN.getInstance().getConfig().getPrefixWhitelists().stream()
.anyMatch(prefix -> event.getPlayer().getUsername().startsWith(prefix))) return;
checkIp(event.getPlayer().getRemoteAddress().getAddress().getHostAddress(),
AntiVPN.getInstance().getConfig().cachedResults(), result -> {
if(result.isSuccess() && result.isProxy()) {
if(AntiVPN.getInstance().getConfig().kickPlayersOnDetect())
event.getPlayer().disconnect(LegacyComponentSerializer.builder().character('&')
.build().deserialize(AntiVPN.getInstance().getConfig().getKickString()));
VelocityPlugin.INSTANCE.getLogger().info(event.getPlayer().getUsername()
+ " joined on a VPN/Proxy (" + result.getMethod() + ")");
if(AntiVPN.getInstance().getConfig().alertToStaff()) //Ensuring the user wishes to alert to staff
AntiVPN.getInstance().getPlayerExecutor().getOnlinePlayers().stream()
.filter(APIPlayer::isAlertsEnabled)
.forEach(pl -> pl.sendMessage(AntiVPN.getInstance().getConfig().alertMessage()
.replace("%player%", event.getPlayer().getUsername())
.replace("%reason%", result.getMethod())
.replace("%country%", result.getCountryName())
.replace("%city%", result.getCity())));
//In case the user wants to run their own commands instead of using the built in kicking
if(AntiVPN.getInstance().getConfig().runCommands()) {
for (String command : AntiVPN.getInstance().getConfig().commands()) {
VelocityPlugin.INSTANCE.getServer().getCommandManager()
.executeAsync(VelocityPlugin.INSTANCE.getServer()
.getConsoleCommandSource(),
StringUtils.translateAlternateColorCodes('&',
command.replace("%player%",
event.getPlayer().getUsername())));
}
}
AntiVPN.getInstance().detections++;
} else if(!result.isSuccess()) {
VelocityPlugin.INSTANCE.getLogger()
.log(Level.WARNING,
"The API query was not a success! " +
"You may need to upgrade your license on https://funkemunky.cc/shop");
}
AntiVPN.getInstance().checked++;
});
}
});
}
@Override
public void runCacheReset() {
cacheResetTask = VelocityPlugin.INSTANCE.getServer().getScheduler()
.buildTask(VelocityPlugin.INSTANCE, this::resetCache)
.repeat(20, TimeUnit.MINUTES)
.schedule();
}
@Override
public void shutdown() {
if(cacheResetTask != null) {
cacheResetTask.cancel();
cacheResetTask = null;
}
threadExecutor.shutdown();
VelocityPlugin.INSTANCE.getServer().getEventManager().unregisterListener(VelocityPlugin.INSTANCE, this);
}
}
@@ -0,0 +1,31 @@
package dev.brighten.antivpn.velocity;
import com.velocitypowered.api.proxy.Player;
import dev.brighten.antivpn.api.APIPlayer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public class VelocityPlayer extends APIPlayer {
private final Player player;
public VelocityPlayer(Player player) {
super(player.getUniqueId(), player.getUsername(), player.getRemoteAddress().getAddress());
this.player = player;
}
@Override
public void sendMessage(String message) {
player.sendMessage(LegacyComponentSerializer.builder().character('&').build().deserialize(message));
}
@Override
public void kickPlayer(String reason) {
player.disconnect(LegacyComponentSerializer.builder().character('&').build().deserialize(reason));
}
@Override
public boolean hasPermission(String permission) {
return player.hasPermission(permission);
}
}
@@ -0,0 +1,35 @@
package dev.brighten.antivpn.velocity;
import com.velocitypowered.api.proxy.Player;
import dev.brighten.antivpn.api.APIPlayer;
import dev.brighten.antivpn.api.PlayerExecutor;
import java.util.*;
import java.util.stream.Collectors;
public class VelocityPlayerExecutor implements PlayerExecutor {
private final Map<Player, VelocityPlayer> cachedPlayers = new WeakHashMap<>();
@Override
public Optional<APIPlayer> getPlayer(String name) {
Optional<Player> player = VelocityPlugin.INSTANCE.getServer().getPlayer(name);
return player.map(value -> cachedPlayers.computeIfAbsent(value, VelocityPlayer::new));
}
@Override
public Optional<APIPlayer> getPlayer(UUID uuid) {
Optional<Player> player = VelocityPlugin.INSTANCE.getServer().getPlayer(uuid);
return player.map(value -> cachedPlayers.computeIfAbsent(value, VelocityPlayer::new));
}
@Override
public List<APIPlayer> getOnlinePlayers() {
return VelocityPlugin.INSTANCE.getServer().getAllPlayers().stream()
.map(pl -> cachedPlayers.computeIfAbsent(pl, VelocityPlayer::new))
.collect(Collectors.toList());
}
}
@@ -0,0 +1,93 @@
package dev.brighten.antivpn.velocity;
import com.google.inject.Inject;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.command.Command;
import dev.brighten.antivpn.velocity.util.Config;
import lombok.Getter;
import lombok.val;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.logging.Logger;
import java.util.stream.IntStream;
@Getter
@Plugin(id = "kaurivpn", name = "KauriVPN", version = "${project.version}", authors = {"funkemunky"})
public class VelocityPlugin {
private final ProxyServer server;
private final Logger logger;
public static VelocityPlugin INSTANCE;
@Inject
@DataDirectory
private Path configDir;
private Config config;
@Inject
public VelocityPlugin(ProxyServer server, Logger logger) {
this.server = server;
this.logger = logger;
}
@Subscribe
public void onInit(ProxyInitializeEvent event) {
INSTANCE = this;
logger.info("Loading config...");
config = new Config();
//Loading plugin
logger.info("Starting AntiVPN services...");
AntiVPN.start(new VelocityConfig(), new VelocityListener(), new VelocityPlayerExecutor());
for (Command command : AntiVPN.getInstance().getCommands()) {
server.getCommandManager().register(server.getCommandManager().metaBuilder(command.name())
.aliases(command.aliases()).build(), (SimpleCommand) invocation -> {
CommandSource sender = invocation.source();
if(!invocation.source().hasPermission("antivpn.command.*")
&& !invocation.source().hasPermission(command.permission())) {
invocation.source().sendMessage(Component.text("No permission").toBuilder()
.color(TextColor.color(255,0,0)).build());
return;
}
val children = command.children();
String[] args = invocation.arguments();
if(children.length > 0 && args.length > 0) {
for (Command child : children) {
if(child.name().equalsIgnoreCase(args[0]) || Arrays.stream(child.aliases())
.anyMatch(alias -> alias.equalsIgnoreCase(args[0]))) {
if(!sender.hasPermission("antivpn.command.*")
&& !sender.hasPermission(child.permission())) {
invocation.source().sendMessage(Component.text("No permission")
.toBuilder().color(TextColor.color(255,0,0)).build());
return;
}
sender.sendMessage(LegacyComponentSerializer.builder().character('&').build()
.deserialize(child.execute(new VelocityCommandExecutor(sender), IntStream
.range(0, args.length - 1)
.mapToObj(i -> args[i + 1]).toArray(String[]::new))));
return;
}
}
}
sender.sendMessage(LegacyComponentSerializer.builder().character('&').build()
.deserialize(command.execute(new VelocityCommandExecutor(sender), args)));
});
}
}
}
@@ -0,0 +1,414 @@
package dev.brighten.antivpn.velocity.config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
public final class Configuration
{
private static final char SEPARATOR = '.';
final Map<String, Object> self;
private final Configuration defaults;
public Configuration()
{
this( null );
}
public Configuration(Configuration defaults)
{
this( new LinkedHashMap<String, Object>(), defaults );
}
Configuration(Map<?, ?> map, Configuration defaults)
{
this.self = new LinkedHashMap<>();
this.defaults = defaults;
for ( Map.Entry<?, ?> entry : map.entrySet() )
{
String key = ( entry.getKey() == null ) ? "null" : entry.getKey().toString();
if ( entry.getValue() instanceof Map )
{
this.self.put( key, new Configuration( (Map) entry.getValue(), ( defaults == null ) ? null : defaults.getSection( key ) ) );
} else
{
this.self.put( key, entry.getValue() );
}
}
}
private Configuration getSectionFor(String path)
{
int index = path.indexOf( SEPARATOR );
if ( index == -1 )
{
return this;
}
String root = path.substring( 0, index );
Object section = self.get( root );
if ( section == null )
{
section = new Configuration( ( defaults == null ) ? null : defaults.getSection( root ) );
self.put( root, section );
}
return (Configuration) section;
}
private String getChild(String path)
{
int index = path.indexOf( SEPARATOR );
return ( index == -1 ) ? path : path.substring( index + 1 );
}
/*------------------------------------------------------------------------*/
@SuppressWarnings("unchecked")
public <T> T get(String path, T def)
{
Configuration section = getSectionFor( path );
Object val;
if ( section == this )
{
val = self.get( path );
} else
{
val = section.get( getChild( path ), def );
}
if ( val == null && def instanceof Configuration )
{
self.put( path, def );
}
return ( val != null ) ? (T) val : def;
}
public boolean contains(String path)
{
return get( path, null ) != null;
}
public Object get(String path)
{
return get( path, getDefault( path ) );
}
public Object getDefault(String path)
{
return ( defaults == null ) ? null : defaults.get( path );
}
public void set(String path, Object value)
{
if ( value instanceof Map )
{
value = new Configuration( (Map) value, ( defaults == null ) ? null : defaults.getSection( path ) );
}
Configuration section = getSectionFor( path );
if ( section == this )
{
if ( value == null )
{
self.remove( path );
} else
{
self.put( path, value );
}
} else
{
section.set( getChild( path ), value );
}
}
/*------------------------------------------------------------------------*/
public Configuration getSection(String path)
{
Object def = getDefault( path );
return (Configuration) get( path, ( def instanceof Configuration ) ? def : new Configuration( ( defaults == null ) ? null : defaults.getSection( path ) ) );
}
/**
* Gets keys, not deep by default.
*
* @return top level keys for this section
*/
public Collection<String> getKeys()
{
return new LinkedHashSet<>( self.keySet() );
}
/*------------------------------------------------------------------------*/
public byte getByte(String path)
{
Object def = getDefault( path );
return getByte( path, ( def instanceof Number ) ? ( (Number) def ).byteValue() : 0 );
}
public byte getByte(String path, byte def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).byteValue() : def;
}
public List<Byte> getByteList(String path)
{
List<?> list = getList( path );
List<Byte> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).byteValue() );
}
}
return result;
}
public short getShort(String path)
{
Object def = getDefault( path );
return getShort( path, ( def instanceof Number ) ? ( (Number) def ).shortValue() : 0 );
}
public short getShort(String path, short def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).shortValue() : def;
}
public List<Short> getShortList(String path)
{
List<?> list = getList( path );
List<Short> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).shortValue() );
}
}
return result;
}
public int getInt(String path)
{
Object def = getDefault( path );
return getInt( path, ( def instanceof Number ) ? ( (Number) def ).intValue() : 0 );
}
public int getInt(String path, int def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).intValue() : def;
}
public List<Integer> getIntList(String path)
{
List<?> list = getList( path );
List<Integer> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).intValue() );
}
}
return result;
}
public long getLong(String path)
{
Object def = getDefault( path );
return getLong( path, ( def instanceof Number ) ? ( (Number) def ).longValue() : 0 );
}
public long getLong(String path, long def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).longValue() : def;
}
public List<Long> getLongList(String path)
{
List<?> list = getList( path );
List<Long> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).longValue() );
}
}
return result;
}
public float getFloat(String path)
{
Object def = getDefault( path );
return getFloat( path, ( def instanceof Number ) ? ( (Number) def ).floatValue() : 0 );
}
public float getFloat(String path, float def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).floatValue() : def;
}
public List<Float> getFloatList(String path)
{
List<?> list = getList( path );
List<Float> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).floatValue() );
}
}
return result;
}
public double getDouble(String path)
{
Object def = getDefault( path );
return getDouble( path, ( def instanceof Number ) ? ( (Number) def ).doubleValue() : 0 );
}
public double getDouble(String path, double def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).doubleValue() : def;
}
public List<Double> getDoubleList(String path)
{
List<?> list = getList( path );
List<Double> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).doubleValue() );
}
}
return result;
}
public boolean getBoolean(String path)
{
Object def = getDefault( path );
return getBoolean( path, ( def instanceof Boolean ) ? (Boolean) def : false );
}
public boolean getBoolean(String path, boolean def)
{
Object val = get( path, def );
return ( val instanceof Boolean ) ? (Boolean) val : def;
}
public List<Boolean> getBooleanList(String path)
{
List<?> list = getList( path );
List<Boolean> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Boolean )
{
result.add( (Boolean) object );
}
}
return result;
}
public char getChar(String path)
{
Object def = getDefault( path );
return getChar( path, ( def instanceof Character ) ? (Character) def : '\u0000' );
}
public char getChar(String path, char def)
{
Object val = get( path, def );
return ( val instanceof Character ) ? (Character) val : def;
}
public List<Character> getCharList(String path)
{
List<?> list = getList( path );
List<Character> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Character )
{
result.add( (Character) object );
}
}
return result;
}
public String getString(String path)
{
Object def = getDefault( path );
return getString( path, ( def instanceof String ) ? (String) def : "" );
}
public String getString(String path, String def)
{
Object val = get( path, def );
return ( val instanceof String ) ? (String) val : def;
}
public List<String> getStringList(String path)
{
List<?> list = getList( path );
List<String> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof String )
{
result.add( (String) object );
}
}
return result;
}
/*------------------------------------------------------------------------*/
public List<?> getList(String path)
{
Object def = getDefault( path );
return getList( path, ( def instanceof List<?> ) ? (List<?>) def : Collections.EMPTY_LIST );
}
public List<?> getList(String path, List<?> def)
{
Object val = get( path, def );
return ( val instanceof List<?> ) ? (List<?>) val : def;
}
}
@@ -0,0 +1,60 @@
package dev.brighten.antivpn.velocity.config;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
public abstract class ConfigurationProvider
{
private static final Map<Class<? extends ConfigurationProvider>, ConfigurationProvider> providers = new HashMap<>();
static
{
try
{
providers.put( YamlConfiguration.class, new YamlConfiguration() );
} catch ( NoClassDefFoundError ex )
{
// Ignore, no SnakeYAML
}
try
{
providers.put( JsonConfiguration.class, new JsonConfiguration() );
} catch ( NoClassDefFoundError ex )
{
// Ignore, no Gson
}
}
public static ConfigurationProvider getProvider(Class<? extends ConfigurationProvider> provider)
{
return providers.get( provider );
}
/*------------------------------------------------------------------------*/
public abstract void save(Configuration config, File file) throws IOException;
public abstract void save(Configuration config, Writer writer);
public abstract Configuration load(File file) throws IOException;
public abstract Configuration load(File file, Configuration defaults) throws IOException;
public abstract Configuration load(Reader reader);
public abstract Configuration load(Reader reader, Configuration defaults);
public abstract Configuration load(InputStream is);
public abstract Configuration load(InputStream is, Configuration defaults);
public abstract Configuration load(String string);
public abstract Configuration load(String string, Configuration defaults);
}
@@ -0,0 +1,114 @@
package dev.brighten.antivpn.velocity.config;
import com.google.common.base.Charsets;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PACKAGE)
public class JsonConfiguration extends ConfigurationProvider
{
private final Gson json = new GsonBuilder().serializeNulls().setPrettyPrinting().registerTypeAdapter( Configuration.class, new JsonSerializer<Configuration>()
{
@Override
public JsonElement serialize(Configuration src, Type typeOfSrc, JsonSerializationContext context)
{
return context.serialize( ( (Configuration) src ).self );
}
} ).create();
@Override
public void save(Configuration config, File file) throws IOException
{
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), Charsets.UTF_8 ) )
{
save( config, writer );
}
}
@Override
public void save(Configuration config, Writer writer)
{
json.toJson( config.self, writer );
}
@Override
public Configuration load(File file) throws IOException
{
return load( file, null );
}
@Override
public Configuration load(File file, Configuration defaults) throws IOException
{
try ( FileInputStream is = new FileInputStream( file ) )
{
return load( is, defaults );
}
}
@Override
public Configuration load(Reader reader)
{
return load( reader, null );
}
@Override
@SuppressWarnings("unchecked")
public Configuration load(Reader reader, Configuration defaults)
{
Map<String, Object> map = json.fromJson( reader, LinkedHashMap.class );
if ( map == null )
{
map = new LinkedHashMap<>();
}
return new Configuration( map, defaults );
}
@Override
public Configuration load(InputStream is)
{
return load( is, null );
}
@Override
public Configuration load(InputStream is, Configuration defaults)
{
return load( new InputStreamReader( is, Charsets.UTF_8 ), defaults );
}
@Override
public Configuration load(String string)
{
return load( string, null );
}
@Override
@SuppressWarnings("unchecked")
public Configuration load(String string, Configuration defaults)
{
Map<String, Object> map = json.fromJson( string, LinkedHashMap.class );
if ( map == null )
{
map = new LinkedHashMap<>();
}
return new Configuration( map, defaults );
}
}
@@ -0,0 +1,136 @@
package dev.brighten.antivpn.velocity.config;
import com.google.common.base.Charsets;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.representer.Represent;
import org.yaml.snakeyaml.representer.Representer;
@NoArgsConstructor(access = AccessLevel.PACKAGE)
public class YamlConfiguration extends ConfigurationProvider
{
private final ThreadLocal<Yaml> yaml = new ThreadLocal<Yaml>()
{
@Override
protected Yaml initialValue()
{
Representer representer = new Representer()
{
{
representers.put( Configuration.class, new Represent()
{
@Override
public Node representData(Object data)
{
return represent( ( (Configuration) data ).self );
}
} );
}
};
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
return new Yaml( new Constructor(), representer, options );
}
};
@Override
public void save(Configuration config, File file) throws IOException
{
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), Charsets.UTF_8 ) )
{
save( config, writer );
}
}
@Override
public void save(Configuration config, Writer writer)
{
yaml.get().dump( config.self, writer );
}
@Override
public Configuration load(File file) throws IOException
{
return load( file, null );
}
@Override
public Configuration load(File file, Configuration defaults) throws IOException
{
try ( FileInputStream is = new FileInputStream( file ) )
{
return load( is, defaults );
}
}
@Override
public Configuration load(Reader reader)
{
return load( reader, null );
}
@Override
@SuppressWarnings("unchecked")
public Configuration load(Reader reader, Configuration defaults)
{
Map<String, Object> map = yaml.get().loadAs( reader, LinkedHashMap.class );
if ( map == null )
{
map = new LinkedHashMap<>();
}
return new Configuration( map, defaults );
}
@Override
public Configuration load(InputStream is)
{
return load( is, null );
}
@Override
@SuppressWarnings("unchecked")
public Configuration load(InputStream is, Configuration defaults)
{
Map<String, Object> map = yaml.get().loadAs( is, LinkedHashMap.class );
if ( map == null )
{
map = new LinkedHashMap<>();
}
return new Configuration( map, defaults );
}
@Override
public Configuration load(String string)
{
return load( string, null );
}
@Override
@SuppressWarnings("unchecked")
public Configuration load(String string, Configuration defaults)
{
Map<String, Object> map = yaml.get().loadAs( string, LinkedHashMap.class );
if ( map == null )
{
map = new LinkedHashMap<>();
}
return new Configuration( map, defaults );
}
}
@@ -0,0 +1,115 @@
package dev.brighten.antivpn.velocity.util;
import com.google.common.io.ByteStreams;
import dev.brighten.antivpn.velocity.VelocityPlugin;
import dev.brighten.antivpn.velocity.config.Configuration;
import dev.brighten.antivpn.velocity.config.ConfigurationProvider;
import dev.brighten.antivpn.velocity.config.YamlConfiguration;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Author: nitramleo (Martin)
* Date created: 10-Aug-18
*/
public class Config {
private File file;
private Configuration configuration;
public Config() {
File dataFolder = VelocityPlugin.INSTANCE.getConfigDir().toFile();
this.file = new File(dataFolder, "config.yml");
try {
if (!this.file.exists()) {
if (!dataFolder.exists()) {
dataFolder.mkdir();
}
this.file.createNewFile();
try (final InputStream is =VelocityPlugin.INSTANCE.getClass().getResourceAsStream("config.yml");
final OutputStream os = new FileOutputStream(this.file)) {
ByteStreams.copy(is, os);
}
}
this.configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(this.file);
}
catch (IOException e) {
e.printStackTrace();
}
}
public void load() {
File dataFolder = VelocityPlugin.INSTANCE.getConfigDir().toFile();
this.file = new File(dataFolder, "config.yml");
try {
this.configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(this.file);
}
catch (IOException e) {
e.printStackTrace();
}
}
public void save() {
try {
ConfigurationProvider.getProvider( YamlConfiguration.class).save(this.configuration, this.file);
}
catch (IOException e) {
e.printStackTrace();
}
}
public Configuration getConfiguration() {
return this.configuration;
}
public File getFile() {
return this.file;
}
public double getDouble(final String path) {
if (this.configuration.get(path) != null) {
return this.configuration.getDouble(path);
}
return 0.0;
}
public int getInt(final String path) {
if (this.configuration.get(path) != null) {
return this.configuration.getInt(path);
}
return 0;
}
public Object get(final String path) {
return this.configuration.get(path);
}
public void set(final String path, final Object object) {
configuration.set(path, object);
}
public boolean getBoolean(final String path) {
return this.configuration.get(path) != null && this.configuration.getBoolean(path);
}
public String getString(final String path) {
if (this.configuration.get(path) != null) {
return StringUtils.translateAlternateColorCodes('&', this.configuration.getString(path));
}
return "String at path: " + path + " not found!";
}
public List<String> getStringList(final String path) {
if (this.configuration.get(path) != null) {
final ArrayList<String> strings = new ArrayList<String>();
for (final String string : this.configuration.getStringList(path)) {
strings.add(StringUtils.translateAlternateColorCodes('&', string));
}
return strings;
}
return Arrays.asList("String List at path: " + path + " not found!");
}
}
@@ -0,0 +1,28 @@
package dev.brighten.antivpn.velocity.util;
import dev.brighten.antivpn.velocity.VelocityPlugin;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class ConfigDefault<A> {
private final A defaultValue;
private final String path;
private final VelocityPlugin plugin;
public A get() {
if(plugin.getConfig().get(path) != null)
return (A) plugin.getConfig().get(path);
else {
plugin.getConfig().set(path, defaultValue);
plugin.getConfig().save();
return defaultValue;
}
}
public A set(A value) {
plugin.getConfig().set(path, value);
return value;
}
}
@@ -0,0 +1,17 @@
package dev.brighten.antivpn.velocity.util;
public class StringUtils {
public static String translateAlternateColorCodes(char altColorChar, String textToTranslate) {
char[] b = textToTranslate.toCharArray();
for(int i = 0; i < b.length - 1; ++i) {
if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) {
b[i] = 167;
b[i + 1] = Character.toLowerCase(b[i + 1]);
}
}
return new String(b);
}
}