FlexPlex api wrapper first version
This commit is contained in:
commit
7e096d3d9e
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
36
pom.xml
Normal file
36
pom.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>fi.flexplex</groupId>
|
||||
<artifactId>lib</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<name>FlexConnect</name>
|
||||
<build>
|
||||
<finalName>${project.name}-${project.version}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<configuration>
|
||||
<source>16</source>
|
||||
<target>16</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.neovisionaries</groupId>
|
||||
<artifactId>nv-websocket-client</artifactId>
|
||||
<version>2.14</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.9</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
98
src/main/java/fi/flexplex/lib/FlexLib.java
Normal file
98
src/main/java/fi/flexplex/lib/FlexLib.java
Normal file
@ -0,0 +1,98 @@
|
||||
package fi.flexplex.lib;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class FlexLib {
|
||||
|
||||
private final String token;
|
||||
private final Logger logger;
|
||||
private final GraphQLApi graphQLApi;
|
||||
private final Set<FlexLibAdapter> eventListeners = new HashSet<>();
|
||||
private WebSocketClient webSocketClient;
|
||||
private final HashMap<String, PlayerFriends> playerFriends = new HashMap<>();
|
||||
|
||||
protected Set<FlexLibAdapter> getEventListeners() {
|
||||
return this.eventListeners;
|
||||
}
|
||||
|
||||
protected void updatePlayerFriends(final String player) {
|
||||
final PlayerFriends pFriends = this.playerFriends.get(player);
|
||||
if (pFriends != null) {
|
||||
pFriends.update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates FlexLib API
|
||||
* @param token token for FlexPlex API
|
||||
*/
|
||||
public FlexLib(final String token, final Logger logger) {
|
||||
this.token = token;
|
||||
this.logger = logger;
|
||||
this.logger.info("Initializing FlexLib");
|
||||
|
||||
this.graphQLApi = new GraphQLApi(this, "https://api.flexplex.fi/graphql");
|
||||
new FlexLibAdapterImpl(this);
|
||||
|
||||
try {
|
||||
this.webSocketClient = new WebSocketClient(this, "wss://api.flexplex.fi/flexlib", this.token);
|
||||
} catch (final IOException e) {
|
||||
this.logger.warning("Failed to initialize FlexLib WebSocket client");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get API token
|
||||
* @return API Token used to connect FlexPlex
|
||||
*/
|
||||
public String getToken() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logger used by FlexLib
|
||||
* @return FlexLib logger
|
||||
*/
|
||||
public Logger getLogger() {
|
||||
return this.logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new event listener
|
||||
* @param listener
|
||||
*/
|
||||
public void addListener(final FlexLibAdapter listener) {
|
||||
this.eventListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Friends API
|
||||
* @return Friends API if available
|
||||
*/
|
||||
public Optional<PlayerFriends> getPlayerFriends(final String player) {
|
||||
PlayerFriends pFriends = this.playerFriends.get(player);
|
||||
if (pFriends == null) {
|
||||
try {
|
||||
pFriends = new PlayerFriends(this.graphQLApi, this.token, player);
|
||||
} catch (final IOException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
this.playerFriends.put(player, pFriends);
|
||||
}
|
||||
return Optional.of(pFriends);
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
if (this.webSocketClient != null) {
|
||||
this.webSocketClient.disable();
|
||||
}
|
||||
this.eventListeners.clear();
|
||||
this.playerFriends.clear();
|
||||
}
|
||||
|
||||
}
|
39
src/main/java/fi/flexplex/lib/FlexLibAdapter.java
Normal file
39
src/main/java/fi/flexplex/lib/FlexLibAdapter.java
Normal file
@ -0,0 +1,39 @@
|
||||
package fi.flexplex.lib;
|
||||
|
||||
public interface FlexLibAdapter {
|
||||
|
||||
/**
|
||||
* Called when player friend list or friend requests are updated
|
||||
* @param player
|
||||
*/
|
||||
public default void onFriendsUpdate(final String player) {}
|
||||
|
||||
/**
|
||||
* New friend request event
|
||||
* @param player
|
||||
* @param targetPlayer
|
||||
*/
|
||||
public default void onFriendRequest(final String player, final String targetPlayer) {}
|
||||
|
||||
/**
|
||||
* Friend request accepted event
|
||||
* @param player
|
||||
* @param targetPlayer
|
||||
*/
|
||||
public default void onFriendRequestAccept(final String player, final String targetPlayer) {}
|
||||
|
||||
/**
|
||||
* Friend request deleted event
|
||||
* @param player
|
||||
* @param targetPlayer
|
||||
*/
|
||||
public default void onFriendRequestDelete(final String player, final String targetPlayer) {}
|
||||
|
||||
/**
|
||||
* Friend deleted event
|
||||
* @param player
|
||||
* @param targetPlayer
|
||||
*/
|
||||
public default void onFriendDelete(final String player, final String targetPlayer) {}
|
||||
|
||||
}
|
17
src/main/java/fi/flexplex/lib/FlexLibAdapterImpl.java
Normal file
17
src/main/java/fi/flexplex/lib/FlexLibAdapterImpl.java
Normal file
@ -0,0 +1,17 @@
|
||||
package fi.flexplex.lib;
|
||||
|
||||
public final class FlexLibAdapterImpl implements FlexLibAdapter {
|
||||
|
||||
private final FlexLib flexLib;
|
||||
|
||||
protected FlexLibAdapterImpl(final FlexLib flexLib) {
|
||||
this.flexLib = flexLib;
|
||||
this.flexLib.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFriendsUpdate(final String player) {
|
||||
this.flexLib.updatePlayerFriends(player);
|
||||
}
|
||||
|
||||
}
|
60
src/main/java/fi/flexplex/lib/GraphQLApi.java
Normal file
60
src/main/java/fi/flexplex/lib/GraphQLApi.java
Normal file
@ -0,0 +1,60 @@
|
||||
package fi.flexplex.lib;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
public final class GraphQLApi {
|
||||
|
||||
private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder()
|
||||
.version(HttpClient.Version.HTTP_1_1)
|
||||
.build();
|
||||
|
||||
private final FlexLib flexLib;
|
||||
private final URI uri;
|
||||
|
||||
protected GraphQLApi(final FlexLib flexLib, final String url) {
|
||||
this.flexLib = flexLib;
|
||||
this.uri = URI.create(url);
|
||||
}
|
||||
|
||||
protected Optional<JsonObject> execute(final String query) {
|
||||
final HttpResponse<String> response;
|
||||
final HttpRequest request = HttpRequest.newBuilder()
|
||||
.POST(HttpRequest.BodyPublishers.ofString("{\"query\":\"" + query + "\"}"))
|
||||
.uri(this.uri)
|
||||
.build();
|
||||
|
||||
try {
|
||||
response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
} catch (final IOException e) {
|
||||
this.flexLib.getLogger().warning("Failed to send GraphQL query to FlexPlex server.");
|
||||
return Optional.empty();
|
||||
} catch (final InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
final JsonObject json;
|
||||
try {
|
||||
json = JsonParser.parseString(response.body()).getAsJsonObject();
|
||||
} catch (final JsonSyntaxException | IllegalStateException e) {
|
||||
this.flexLib.getLogger().warning("Received invalid json from FlexPlex GraphQL API");
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (json.has("data")) {
|
||||
return Optional.of(json.get("data").getAsJsonObject());
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
164
src/main/java/fi/flexplex/lib/PlayerFriends.java
Normal file
164
src/main/java/fi/flexplex/lib/PlayerFriends.java
Normal file
@ -0,0 +1,164 @@
|
||||
package fi.flexplex.lib;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public final class PlayerFriends {
|
||||
|
||||
private final GraphQLApi graphQLApi;
|
||||
private final String token;
|
||||
private final String player;
|
||||
private final Set<UUID> friends = new HashSet<>();
|
||||
private final Set<UUID> incomingFriendRequests = new HashSet<>();
|
||||
private final Set<UUID> outcomingFriendRequests = new HashSet<>();
|
||||
|
||||
protected PlayerFriends(final GraphQLApi graphQLApi, final String token, final String player) throws IOException {
|
||||
this.graphQLApi = graphQLApi;
|
||||
this.token = token;
|
||||
this.player = player;
|
||||
if (!this.update()) {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean update() {
|
||||
final Optional<JsonObject> result = this.graphQLApi.execute(
|
||||
"query{" +
|
||||
"player(uuid:\"" + this.player + "\"){" +
|
||||
"friends{uuid}" +
|
||||
"incomingFriendRequests(token:\"" + this.token + "\"){uuid}" +
|
||||
"outcomingFriendRequests(token:\"" + this.token + "\"){uuid}" +
|
||||
"}" +
|
||||
"}"
|
||||
);
|
||||
if (result.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final JsonObject playerObject = result.get().get("player").getAsJsonObject();
|
||||
|
||||
this.friends.clear();
|
||||
for (final JsonElement element : playerObject.get("friends").getAsJsonArray()) {
|
||||
this.friends.add(UUID.fromString(element.getAsJsonObject().get("uuid").getAsString()));
|
||||
}
|
||||
|
||||
this.incomingFriendRequests.clear();
|
||||
for (final JsonElement element : playerObject.get("incomingFriendRequests").getAsJsonArray()) {
|
||||
this.incomingFriendRequests.add(UUID.fromString(element.getAsJsonObject().get("uuid").getAsString()));
|
||||
}
|
||||
|
||||
this.outcomingFriendRequests.clear();
|
||||
for (final JsonElement element : playerObject.get("outcomingFriendRequests").getAsJsonArray()) {
|
||||
this.outcomingFriendRequests.add(UUID.fromString(element.getAsJsonObject().get("uuid").getAsString()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get friends
|
||||
* @return friends
|
||||
*/
|
||||
public Set<UUID> getFriends() {
|
||||
return this.friends;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get incoming friend requests
|
||||
* @return friend requests
|
||||
*/
|
||||
public Set<UUID> getIncomingFriendRequests() {
|
||||
return this.incomingFriendRequests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get outcoming friend requests
|
||||
* @return friend requests
|
||||
*/
|
||||
public Set<UUID> getOutcomingFriendRequests() {
|
||||
return this.outcomingFriendRequests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new friend request
|
||||
* @param player from
|
||||
* @param targetPlayer to
|
||||
* @return true if was created successfully
|
||||
*/
|
||||
public boolean createFriendRequest(final String player, final String targetPlayer) {
|
||||
final Optional<JsonObject> result = this.graphQLApi.execute(
|
||||
"mutation{" +
|
||||
"createFriendRequest(" +
|
||||
"token:\"" + this.token + "\"," +
|
||||
"player:\"" + player + "\"," +
|
||||
"targetPlayer:\"" + targetPlayer + "\"" +
|
||||
")" +
|
||||
"}"
|
||||
);
|
||||
return result.isPresent() && result.get().get("createFriendRequest").getAsBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept incoming friend request
|
||||
* @param player coming from
|
||||
* @param targetPlayer who is accepting
|
||||
* @return true if was accepted successfully
|
||||
*/
|
||||
public boolean acceptFriendRequest(final String player, final String targetPlayer) {
|
||||
final Optional<JsonObject> result = this.graphQLApi.execute(
|
||||
"mutation{" +
|
||||
"acceptFriendRequest(" +
|
||||
"token:\"" + this.token + "\"," +
|
||||
"player:\"" + player + "\"," +
|
||||
"targetPlayer:\"" + targetPlayer + "\"" +
|
||||
")" +
|
||||
"}"
|
||||
);
|
||||
return result.isPresent() && result.get().get("acceptFriendRequest").getAsBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete friend or friend request
|
||||
* @param player
|
||||
* @param targetPlayer
|
||||
* @return true if was deleted successfully
|
||||
*/
|
||||
public boolean deleteFriend(final String player, final String targetPlayer) {
|
||||
final Optional<JsonObject> result = this.graphQLApi.execute(
|
||||
"mutation{" +
|
||||
"deleteFriend(" +
|
||||
"token:\"" + this.token + "\"," +
|
||||
"player:\"" + player + "\"," +
|
||||
"targetPlayer:\"" + targetPlayer + "\"" +
|
||||
")" +
|
||||
"}"
|
||||
);
|
||||
return result.isPresent() && result.get().get("deleteFriend").getAsBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change settings does player accept incoming friend requests
|
||||
* @param player
|
||||
* @param enabled
|
||||
* @return true if was changed successfully
|
||||
*/
|
||||
public boolean setFriendRequestsEnabled(final String player, final boolean enabled) {
|
||||
final Optional<JsonObject> result = this.graphQLApi.execute(
|
||||
"mutation{" +
|
||||
"updateAcceptFriendRequests(" +
|
||||
"token:\"" + this.token + "\"," +
|
||||
"player:\"" + player + "\"," +
|
||||
"acceptRequests:\"" + (enabled ? "true" : "false") + "\"" +
|
||||
")" +
|
||||
"}"
|
||||
);
|
||||
return result.isPresent() && result.get().get("updateAcceptFriendRequests").getAsBoolean();
|
||||
}
|
||||
|
||||
}
|
97
src/main/java/fi/flexplex/lib/WebSocketClient.java
Normal file
97
src/main/java/fi/flexplex/lib/WebSocketClient.java
Normal file
@ -0,0 +1,97 @@
|
||||
package fi.flexplex.lib;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
||||
import com.neovisionaries.ws.client.WebSocketFactory;
|
||||
|
||||
public final class WebSocketClient {
|
||||
|
||||
private final FlexLib flexLib;
|
||||
private final Timer timer;
|
||||
private final TimerTask timerTask;
|
||||
private final WebSocket webSocket;
|
||||
|
||||
protected WebSocketClient(final FlexLib flexLib, final String url, final String token) throws IOException {
|
||||
this.flexLib = flexLib;
|
||||
this.webSocket = this.createWebSocket(url, token);
|
||||
this.timer = new Timer();
|
||||
this.timerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!webSocket.isOpen()) {
|
||||
try {
|
||||
webSocket.connect();
|
||||
} catch (final WebSocketException e) {
|
||||
flexLib.getLogger().warning("WebSocket connection to FlexPlex server failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.timer.schedule(this.timerTask, 0, 60_000);
|
||||
}
|
||||
|
||||
protected void disable() {
|
||||
this.timerTask.cancel();
|
||||
this.timer.cancel();
|
||||
this.webSocket.disconnect();
|
||||
}
|
||||
|
||||
private WebSocket createWebSocket(final String url, final String token) throws IOException {
|
||||
return new WebSocketFactory()
|
||||
.createSocket(url)
|
||||
.addHeader("Token", token)
|
||||
.addListener(new WebSocketAdapter() {
|
||||
@Override
|
||||
public void onTextMessage(final WebSocket ws, final String message) {
|
||||
final String[] args = message.split(" ");
|
||||
switch (args[0]) {
|
||||
case "FRIEND_REQUEST":
|
||||
if (args.length == 3) {
|
||||
for (final FlexLibAdapter listener : flexLib.getEventListeners()) {
|
||||
listener.onFriendRequest(args[1], args[2]);
|
||||
listener.onFriendsUpdate(args[1]);
|
||||
listener.onFriendsUpdate(args[2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "FRIEND_ACCEPT":
|
||||
if (args.length == 3) {
|
||||
for (final FlexLibAdapter listener : flexLib.getEventListeners()) {
|
||||
listener.onFriendRequestAccept(args[1], args[2]);
|
||||
listener.onFriendsUpdate(args[1]);
|
||||
listener.onFriendsUpdate(args[2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "FRIEND_REQUEST_DELETE":
|
||||
if (args.length == 3) {
|
||||
for (final FlexLibAdapter listener : flexLib.getEventListeners()) {
|
||||
listener.onFriendRequestDelete(args[1], args[2]);
|
||||
listener.onFriendsUpdate(args[1]);
|
||||
listener.onFriendsUpdate(args[2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "FRIEND_DELETE":
|
||||
if (args.length == 3) {
|
||||
for (final FlexLibAdapter listener : flexLib.getEventListeners()) {
|
||||
listener.onFriendDelete(args[1], args[2]);
|
||||
listener.onFriendsUpdate(args[1]);
|
||||
listener.onFriendsUpdate(args[2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
flexLib.getLogger().warning("Received invalid WebSocket message from FlexPlex. Message: " + args[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user