feat: code

This commit is contained in:
2026-01-28 18:14:15 -08:00
parent d4ec8ab5ee
commit 0d7537becf
14 changed files with 336 additions and 215 deletions

View File

@@ -0,0 +1,3 @@
package online.mineroo.common.request;
public class CurrencyRequest {}

View File

@@ -0,0 +1,179 @@
package online.mineroo.common.request;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import online.mineroo.common.NetworkServiceInterface;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public class ManagementRequest {
private final Logger logger;
private final NetworkServiceInterface networkService;
// State cache
private String motdToken = "";
private String sessionToken = "";
/**
* Constructs a ManagementRequest instance.
*
* @param logger Logger for logging errors and information
* @param networkService The network service instance (Local or Proxy) that
* handles transport and auth
*/
public ManagementRequest(Logger logger, NetworkServiceInterface networkService) {
this.logger = logger;
this.networkService = networkService;
}
/**
* Checks the bind status asynchronously.
*
* @return A future that completes with true if status is 'bound', false
* otherwise
*/
public CompletableFuture<Boolean> checkBindStatus(String hostname, String port) {
// NetworkService is already configured with BaseURL, only need the path here
String path = "/server/management/status";
Map<String, String> params = new HashMap<>();
params.put("address", hostname);
params.put("port", port);
return networkService.getData(path, params)
.thenApply(response -> {
if (response.getStatusCode() != 200) {
return false;
}
String responseBody = response.getBody();
try {
JsonObject responseData = JsonParser.parseString(responseBody).getAsJsonObject();
boolean bound = responseData.has("bound") && responseData.get("bound").getAsBoolean();
if (bound) {
logger.warn("Mineroo Bind: Server already bound.");
}
return bound;
} catch (Exception e) {
logger.error("Mineroo Bind: Failed to parse bind status response", e);
return false;
}
})
.exceptionally(e -> {
logger.error("Mineroo Bind: Network error while checking status", e);
return false;
});
}
/**
* Initiates a MOTD verification request asynchronously.
*
* @param hostname The server hostname
* @param port The server port
* @return A future that completes with true if tokens are received
*/
public CompletableFuture<Boolean> initialMotdVerifyRequest(String hostname, String port) {
String path = "/server/management/motd-verify";
Integer num_port = -1;
if (!"$port".equals(port)) {
try {
num_port = Integer.valueOf(port);
} catch (NumberFormatException ignored) {
num_port = 25565;
}
}
JsonObject json = new JsonObject();
json.addProperty("server_address", hostname);
if (num_port == -1) {
json.addProperty("server_port", port);
} else {
json.addProperty("server_port", num_port);
}
return networkService.postData(path, json)
.thenApply(response -> {
String responseBody = response.getBody();
if (response.getStatusCode() != 200) {
logger.error("Mineroo Bind: Api fetch failed.");
return false;
}
try {
JsonObject responseData = JsonParser.parseString(responseBody).getAsJsonObject();
if (responseData.has("motd_token")) {
this.motdToken = responseData.get("motd_token").getAsString();
} else {
logger.error("Mineroo Bind: MOTD Token not received.");
return false;
}
if (responseData.has("session_token")) {
this.sessionToken = responseData.get("session_token").getAsString();
} else {
logger.error("Mineroo Bind: Session Token not received.");
return false;
}
return true;
} catch (Exception e) {
logger.error("Mineroo Bind: Failed to parse MOTD verify response: " + responseBody, e);
return false;
}
})
.exceptionally(e -> {
logger.error("Mineroo Bind: Network error during MOTD verify", e);
return false;
});
}
/**
* Finalizes the server binding asynchronously.
*
* @param name The server name (nullable)
* @param description The server description (nullable)
* @return A future that completes with true if the binding is successful
*/
public CompletableFuture<Boolean> finalizeServerBinding(
@Nullable String name, @Nullable String description
) {
String path = "/server/management/bind";
JsonObject json = new JsonObject();
json.addProperty("session_token", this.sessionToken);
json.addProperty("name", name);
json.addProperty("description", description);
return networkService.postData(path, json)
.thenApply(response -> {
// Assume as long as the request returns successfully and no exception is
// thrown, it is considered successful (HTTP 200)
// If the API returns a specific {"success": false}, you need to parse the JSON
// and check here
return true;
})
.exceptionally(e -> {
logger.error("Mineroo Bind: Failed to finalize binding", e);
return false;
});
}
/**
* Gets the MOTD token received from the API.
*
* @return the motdToken string
*/
public String getMotdToken() {
return motdToken;
}
}

View File

@@ -0,0 +1,22 @@
package online.mineroo.common.request;
import online.mineroo.common.NetworkServiceInterface;
import org.slf4j.Logger;
public class RequestClient {
private final ManagementRequest managementRequest;
private final UserRequest userRequest;
public RequestClient(Logger logger, NetworkServiceInterface networkService) {
this.managementRequest = new ManagementRequest(logger, networkService);
this.userRequest = new UserRequest(logger, networkService);
}
public ManagementRequest management() {
return this.managementRequest;
}
public UserRequest user() {
return this.userRequest;
}
}

View File

@@ -1,183 +1,32 @@
package online.mineroo.common;
package online.mineroo.common.request;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.jetbrains.annotations.Nullable;
import online.mineroo.common.NetworkServiceInterface;
import org.slf4j.Logger;
/**
* BindRequest handles server binding and verification with the Mineroo API.
* <p>
* This class operates asynchronously and relies on the injected
* {@link NetworkService}
* to handle the actual HTTP transport and authentication.
*/
public class BindRequest {
public class UserRequest {
private final Logger logger;
private final NetworkServiceInterface networkService;
// State cache
private String motdToken = "";
private String sessionToken = "";
/**
* Constructs a BindRequest instance.
* Constructs a UserRequest instance.
*
* @param logger Logger for logging errors and information
* @param networkService The network service instance (Local or Proxy) that
* handles transport and auth
*/
public BindRequest(Logger logger, NetworkServiceInterface networkService) {
public UserRequest(Logger logger, NetworkServiceInterface networkService) {
this.logger = logger;
this.networkService = networkService;
}
/**
* Checks the bind status asynchronously.
*
* @return A future that completes with true if status is 'bound', false
* otherwise
*/
public CompletableFuture<Boolean> checkBindStatus(String hostname, String port) {
// NetworkService is already configured with BaseURL, only need the path here
String path = "/server/server-bind-status";
Map<String, String> params = new HashMap<>();
params.put("address", hostname);
params.put("port", port);
return networkService.getData(path, params)
.thenApply(response -> {
if (response.getStatusCode() != 200) {
return false;
}
String responseBody = response.getBody();
try {
JsonObject responseData = JsonParser.parseString(responseBody).getAsJsonObject();
boolean bound = responseData.has("bound") && responseData.get("bound").getAsBoolean();
if (bound) {
logger.warn("Mineroo Bind: Server already bound.");
}
return bound;
} catch (Exception e) {
logger.error("Mineroo Bind: Failed to parse bind status response", e);
return false;
}
})
.exceptionally(e -> {
logger.error("Mineroo Bind: Network error while checking status", e);
return false;
});
}
/**
* Initiates a MOTD verification request asynchronously.
*
* @param hostname The server hostname
* @param port The server port
* @return A future that completes with true if tokens are received
*/
public CompletableFuture<Boolean> initialMotdVerifyRequest(String hostname, String port) {
String path = "/server/motd-verify";
Integer num_port = -1;
if (!"$port".equals(port)) {
try {
num_port = Integer.valueOf(port);
} catch (NumberFormatException ignored) {
num_port = 25565;
}
}
JsonObject json = new JsonObject();
json.addProperty("server_address", hostname);
if (num_port == -1) {
json.addProperty("server_port", port);
} else {
json.addProperty("server_port", num_port);
}
return networkService.postData(path, json)
.thenApply(response -> {
String responseBody = response.getBody();
if (response.getStatusCode() != 200) {
logger.error("Mineroo Bind: Api fetch failed.");
return false;
}
try {
JsonObject responseData = JsonParser.parseString(responseBody).getAsJsonObject();
if (responseData.has("motd_token")) {
this.motdToken = responseData.get("motd_token").getAsString();
} else {
logger.error("Mineroo Bind: MOTD Token not received.");
return false;
}
if (responseData.has("session_token")) {
this.sessionToken = responseData.get("session_token").getAsString();
} else {
logger.error("Mineroo Bind: Session Token not received.");
return false;
}
return true;
} catch (Exception e) {
logger.error("Mineroo Bind: Failed to parse MOTD verify response: " + responseBody, e);
return false;
}
})
.exceptionally(e -> {
logger.error("Mineroo Bind: Network error during MOTD verify", e);
return false;
});
}
/**
* Finalizes the server binding asynchronously.
*
* @param name The server name (nullable)
* @param description The server description (nullable)
* @return A future that completes with true if the binding is successful
*/
public CompletableFuture<Boolean> finalizeServerBinding(
@Nullable String name, @Nullable String description
) {
String path = "/server/server-bind";
JsonObject json = new JsonObject();
json.addProperty("session_token", this.sessionToken);
json.addProperty("name", name);
json.addProperty("description", description);
return networkService.postData(path, json)
.thenApply(response -> {
// Assume as long as the request returns successfully and no exception is
// thrown, it is considered successful (HTTP 200)
// If the API returns a specific {"success": false}, you need to parse the JSON
// and check here
return true;
})
.exceptionally(e -> {
logger.error("Mineroo Bind: Failed to finalize binding", e);
return false;
});
}
public class PlayerBindStatusResponse implements Serializable {
@SerializedName("status") private PlayerBindStatusEnum status;
@@ -278,7 +127,7 @@ public class BindRequest {
public CompletableFuture<PlayerBindStatusResponse> checkPlayerBindStatus(
UUID playerUuid, String userEmail
) {
String path = "/server/user-bind-status";
String path = "/server/user/status";
Map<String, String> params = new HashMap<>();
@@ -360,7 +209,7 @@ public class BindRequest {
public CompletableFuture<PlayerBindResponse> PlayerBindRequest(
String webEmail, UUID playerUuid, String playerUsername
) {
String path = "/server/user-bind";
String path = "/server/user/bind";
JsonObject json = new JsonObject();
@@ -395,13 +244,4 @@ public class BindRequest {
return createPlayerBindErrorResponse("Network Error: " + e.getMessage());
});
}
/**
* Gets the MOTD token received from the API.
*
* @return the motdToken string
*/
public String getMotdToken() {
return motdToken;
}
}