Integrate minecraft server whitelist to FlexPlex API

master
Jonttuuu 2022-05-02 20:15:25 +03:00
parent b598047fef
commit 97c6556d2a
5 changed files with 198 additions and 0 deletions

View File

@ -8,14 +8,21 @@ import java.util.Properties;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import fi.flexplex.connect.util.FileChangeListener;
public final class FlexConnect extends JavaPlugin {
private String token = "";
private FlexPlexGraphQLApi flexPlexGraphQLApi;
public String getToken() {
return this.token;
}
public FlexPlexGraphQLApi getFlexPlexGraphQLApi() {
return this.flexPlexGraphQLApi;
}
@Override
public void onEnable() {
@ -26,6 +33,9 @@ public final class FlexConnect extends JavaPlugin {
this.getLogger().warning("Token for FlexPlex server network has not been set into plugins config file. Please request token from FlexPlex staff members if you don't already have one!");
}
// GraphQL Api
this.flexPlexGraphQLApi = new FlexPlexGraphQLApi(this, "https://api.flexplex.fi/graphql");
boolean configsModified = false;
// Check online mode
@ -81,6 +91,9 @@ public final class FlexConnect extends JavaPlugin {
// Register listener
this.getServer().getPluginManager().registerEvents(new FlexConnectListener(this), this);
// Register file change listener
new FileChangeListener(this, "ops.json", "whitelist.json");
}
}

View File

@ -1,11 +1,16 @@
package fi.flexplex.connect;
import com.destroystokyo.paper.event.server.WhitelistToggleEvent;
import com.destroystokyo.paper.profile.ProfileProperty;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import fi.flexplex.connect.event.AsyncWhitelistChangedEvent;
public final class FlexConnectListener implements Listener {
private final FlexConnect flexConnect;
@ -27,4 +32,16 @@ public final class FlexConnectListener implements Listener {
event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, "Access denied");
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onWhitelistToggle(final WhitelistToggleEvent event) {
Bukkit.getScheduler().runTaskAsynchronously(this.flexConnect, () ->
this.flexConnect.getFlexPlexGraphQLApi().updateWhitelist(event.isEnabled())
);
}
@EventHandler
public void onAsyncWhitelistChanged(final AsyncWhitelistChangedEvent event) {
this.flexConnect.getFlexPlexGraphQLApi().updateWhitelist();
}
}

View File

@ -0,0 +1,77 @@
package fi.flexplex.connect;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.OfflinePlayer;
public final class FlexPlexGraphQLApi {
private final String graphqlEndpoint;
private final FlexConnect flexConnect;
public FlexPlexGraphQLApi(final FlexConnect flexConnect, final String graphQLEndpoint) {
this.flexConnect = flexConnect;
this.graphqlEndpoint = graphQLEndpoint;
}
public void updateWhitelist() {
this.updateWhitelist(this.flexConnect.getServer().hasWhitelist());
}
public void updateWhitelist(final boolean whitelistEnabled) {
final Set<UUID> whitelist = new HashSet<>();
for (final OfflinePlayer player : this.flexConnect.getServer().getWhitelistedPlayers()) {
whitelist.add(player.getUniqueId());
}
for (final OfflinePlayer player : this.flexConnect.getServer().getOperators()) {
whitelist.add(player.getUniqueId());
}
this.updateWhitelist(whitelistEnabled, whitelist);
}
private void updateWhitelist(final boolean whitelistEnabled, final Set<UUID> whitelist) {
final StringBuilder whitelistString = new StringBuilder(" ");
for (final UUID uuid : whitelist) {
whitelistString.append("\\\"" + uuid.toString() + "\\\" ");
}
try {
final URL url = new URL(graphqlEndpoint);
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
final DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes("{\"query\":\"mutation { updateCommunityServerWhitelist ( token: \\\"" + this.flexConnect.getToken() + "\\\" enabled: " + whitelistEnabled + " whitelist: [" + whitelistString + "] )}\"}");
wr.flush();
wr.close();
final JsonObject response = (JsonObject) new JsonParser().parse(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
if (!response.get("data").getAsJsonObject().get("updateCommunityServerWhitelist").getAsBoolean()) {
this.flexConnect.getLogger().warning("Updating whitelist data failed, propably invalid token.");
}
conn.disconnect();
} catch (final IOException e) {
this.flexConnect.getLogger().warning("Updating whitelist data failed, propably connection to FlexPlex API server is down.");
}
}
}

View File

@ -0,0 +1,23 @@
package fi.flexplex.connect.event;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public final class AsyncWhitelistChangedEvent extends Event {
private static final HandlerList HANDLERS = new HandlerList();
public static HandlerList getHandlerList() {
return HANDLERS;
}
public AsyncWhitelistChangedEvent() {
super(true);
}
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
}

View File

@ -0,0 +1,68 @@
package fi.flexplex.connect.util;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import org.bukkit.Bukkit;
import fi.flexplex.connect.FlexConnect;
import fi.flexplex.connect.event.AsyncWhitelistChangedEvent;
public final class FileChangeListener {
final FlexConnect flexConnect;
final Thread thread;
boolean isRunning = true;
// Bukkit API does not provide good way to detect whitelist changes. So we need this quite interesting solution...
public FileChangeListener(final FlexConnect flexConnect, final String...files) {
this.flexConnect = flexConnect;
this.thread = new Thread() {
@Override
public void run() {
try {
final WatchService service = FileSystems.getDefault().newWatchService();
Paths.get(flexConnect.getServer().getWorldContainer().getPath()).register(service, StandardWatchEventKinds.ENTRY_MODIFY);
long lastRun = 0;
while (isRunning) {
final WatchKey key = service.take();
for (final WatchEvent<?> event : key.pollEvents()) {
final String fileName = String.valueOf(event.context());
for (final String file : files) {
if (file.equals(fileName)) {
// Cooldown because file change events are called quite many times
if (lastRun + 100 < System.currentTimeMillis()) {
Bukkit.getScheduler().runTaskLaterAsynchronously(
flexConnect,
() -> Bukkit.getPluginManager().callEvent(new AsyncWhitelistChangedEvent()),
20
);
lastRun = System.currentTimeMillis();
}
break;
}
}
}
key.reset();
}
} catch (final IOException e) {
e.printStackTrace();
} catch (final InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
};
this.thread.start();
}
public void stop() {
this.isRunning = false;
}
}