govno kod
Some checks failed
Build / build (push) Failing after 3h3m20s
Some checks failed
Build / build (push) Failing after 3h3m20s
This commit is contained in:
13
Mojang_API/.gitignore
vendored
Normal file
13
Mojang_API/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#IntelliJ
|
||||
.idea/*
|
||||
**.iml
|
||||
|
||||
#Maven
|
||||
target/*
|
||||
|
||||
#Eclipse
|
||||
**/.settings/*
|
||||
**/.project
|
||||
**/.classpath
|
||||
|
||||
/target/
|
||||
110
Mojang_API/pom.xml
Normal file
110
Mojang_API/pom.xml
Normal file
@@ -0,0 +1,110 @@
|
||||
<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">
|
||||
<parent>
|
||||
<artifactId>invsee-plus-plus</artifactId>
|
||||
<groupId>com.janboerman.invsee</groupId>
|
||||
<version>0.31.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>mojang-api</artifactId>
|
||||
<name>Mojang API</name>
|
||||
|
||||
<build>
|
||||
<defaultGoal>clean package</defaultGoal>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>${maven-shade-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.json.simple</pattern>
|
||||
<shadedPattern>com.janboerman.invsee.jsonsimple</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>junit:junit</exclude>
|
||||
<exclude>org.hamcrest:hamcrest-core</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile-java-8</id>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<release>8</release>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>compile-java-11</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<release>11</release>
|
||||
<compileSourceRoots>
|
||||
<compileSourceRoot>${project.basedir}/src/main/java11</compileSourceRoot>
|
||||
</compileSourceRoots>
|
||||
<multiReleaseOutput>true</multiReleaseOutput>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>${maven-jar-plugin.version}</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Multi-Release>true</Multi-Release>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.janboerman.invsee</groupId>
|
||||
<artifactId>utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.janboerman.invsee.mojangapi;
|
||||
|
||||
import static com.janboerman.invsee.mojangapi.ResponseUtils.readJSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import com.janboerman.invsee.utils.Rethrow;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class ElectroidAPI {
|
||||
|
||||
private final Executor asyncExecutor;
|
||||
|
||||
public ElectroidAPI(Executor asyncExecutor) {
|
||||
this.asyncExecutor = asyncExecutor;
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<UUID>> lookupUniqueId(String userName) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
URL url = new URL("https://api.ashcon.app/mojang/v2/user/" + userName);
|
||||
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5 * 1000); //5 seconds
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
connection.setRequestProperty("User-Agent", "InvSee++/ElectroidAPI");
|
||||
|
||||
int statusCode = connection.getResponseCode();
|
||||
switch (statusCode) {
|
||||
case HttpURLConnection.HTTP_OK:
|
||||
JSONObject json = readJSONObject(connection);
|
||||
String uuid = (String) json.get("uuid");
|
||||
return Optional.of(UUID.fromString(uuid));
|
||||
case HttpURLConnection.HTTP_NO_CONTENT:
|
||||
return Optional.empty();
|
||||
default:
|
||||
throw new RuntimeException("Unexpected response from Electroid mojang api, status code=" + statusCode + ".");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return Rethrow.unchecked(e);
|
||||
}
|
||||
}, asyncExecutor);
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<String>> lookupUserName(UUID uniqueId) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
URL url = new URL("https://api.ashcon.app/mojang/v2/user/" + uniqueId.toString());
|
||||
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5 * 1000); //5 seconds
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
connection.setRequestProperty("User-Agent", "InvSee++/ElectroidAPI");
|
||||
|
||||
int statusCode = connection.getResponseCode();
|
||||
switch (statusCode) {
|
||||
case HttpURLConnection.HTTP_OK:
|
||||
JSONObject json = readJSONObject(connection);
|
||||
String userName = (String) json.get("username");
|
||||
return Optional.of(userName);
|
||||
case HttpURLConnection.HTTP_NO_CONTENT:
|
||||
return Optional.empty();
|
||||
default:
|
||||
throw new RuntimeException("Unexpected response from Electroid mojang api, status code=" + statusCode + ".");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return Rethrow.unchecked(e);
|
||||
}
|
||||
}, asyncExecutor);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package com.janboerman.invsee.mojangapi;
|
||||
|
||||
import static com.janboerman.invsee.mojangapi.ResponseUtils.readJSONObject;
|
||||
import static com.janboerman.invsee.mojangapi.ResponseUtils.charsetFromHeader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import com.janboerman.invsee.utils.Compat;
|
||||
import com.janboerman.invsee.utils.Rethrow;
|
||||
import com.janboerman.invsee.utils.UUIDHelper;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class MojangAPI {
|
||||
|
||||
private final Executor asyncExecutor;
|
||||
|
||||
public MojangAPI(Executor asyncExecutor) {
|
||||
this.asyncExecutor = asyncExecutor;
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<UUID>> lookupUniqueId(String userName) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
URL url = new URL("https://api.mojang.com/users/profiles/minecraft/" + userName);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5 * 1000); //5 seconds
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
connection.setRequestProperty("User-Agent", "InvSee++/MojangAPI");
|
||||
|
||||
int statusCode = connection.getResponseCode();
|
||||
|
||||
if (statusCode == HttpURLConnection.HTTP_OK) {
|
||||
JSONObject json = readJSONObject(connection);
|
||||
String id = (String) json.get("id");
|
||||
UUID uuid = UUIDHelper.dashed(id);
|
||||
return Optional.of(uuid);
|
||||
}
|
||||
|
||||
else {
|
||||
return handleNotOk(statusCode, connection);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
return Rethrow.unchecked(e);
|
||||
}
|
||||
}, asyncExecutor);
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<String>> lookupUserName(UUID uniqueId) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
URL url = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + UUIDHelper.unDashed(uniqueId));
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5 * 1000); //5 seconds
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
connection.setRequestProperty("User-Agent", "InvSee++/MojangAPI");
|
||||
|
||||
int statusCode = connection.getResponseCode();
|
||||
|
||||
if (statusCode == HttpURLConnection.HTTP_OK) {
|
||||
JSONObject profileJson = readJSONObject(connection);
|
||||
String userName = (String) profileJson.get("name");
|
||||
return Optional.of(userName);
|
||||
}
|
||||
|
||||
else {
|
||||
return handleNotOk(statusCode, connection);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
return Rethrow.unchecked(e);
|
||||
}
|
||||
}, asyncExecutor);
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleNotOk(int statusCode, HttpURLConnection connection) throws IOException {
|
||||
assert statusCode == connection.getResponseCode();
|
||||
|
||||
switch (statusCode) {
|
||||
case ResponseUtils.HTTP_NO_CONTENT: return handleNoContent(connection);
|
||||
case ResponseUtils.HTTP_BAD_REQUEST: return handleBadRequest(connection);
|
||||
case ResponseUtils.HTTP_TOO_MANY_REQUESTS: return handleTooManyRequests(connection);
|
||||
default: return handleUnknownStatusCode(statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleNoContent(HttpURLConnection connection) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleBadRequest(HttpURLConnection connection) {
|
||||
JSONObject jsonObject = readJSONObject(connection);
|
||||
|
||||
String error = (String) jsonObject.get("error");
|
||||
String errorMessage = (String) jsonObject.get("errorMessage");
|
||||
|
||||
throw new RuntimeException("We sent a bad request to Mojang. We got a(n) " + error + " with the following message: " + errorMessage);
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleTooManyRequests(HttpURLConnection connection) {
|
||||
try (InputStream inputStream = connection.getInputStream()) {
|
||||
byte[] bytes = Compat.readAllBytes(inputStream);
|
||||
Charset charset = charsetFromHeader(connection.getHeaderField("Content-Type"));
|
||||
String errorMessage = new String(bytes, charset);
|
||||
throw new RuntimeException("We were rate limited by Mojang. Error message: " + errorMessage);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Exception occurred when processing 429 (rate limited) response.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleUnknownStatusCode(int statusCode) {
|
||||
throw new RuntimeException("Unexpected status code from Mojang API: " + statusCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.janboerman.invsee.mojangapi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
class ResponseUtils {
|
||||
|
||||
static final int HTTP_NO_CONTENT = HttpURLConnection.HTTP_NO_CONTENT;
|
||||
static final int HTTP_BAD_REQUEST = HttpURLConnection.HTTP_BAD_REQUEST;
|
||||
static final int HTTP_TOO_MANY_REQUESTS = 429;
|
||||
|
||||
private ResponseUtils() {}
|
||||
|
||||
static JSONObject readJSONObject(HttpURLConnection connection) {
|
||||
Charset charset = charsetFromHeader(connection.getHeaderField("Content-Type"));
|
||||
try (InputStream inputStream = connection.getInputStream();
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, charset)) {
|
||||
|
||||
Object json = new JSONParser().parse(inputStreamReader);
|
||||
if (json instanceof JSONObject) {
|
||||
return (JSONObject) json;
|
||||
} else {
|
||||
throw new RuntimeException("Expected response to be represented as a JSON Object, instead we got: " + json);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Could not read http response body", ioe);
|
||||
} catch (ParseException pe) {
|
||||
throw new RuntimeException("Invalid JSON from api", pe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Charset charsetFromHeader(String contentType) {
|
||||
if (contentType != null) {
|
||||
int indexOfSemi = contentType.indexOf(';');
|
||||
if (indexOfSemi != -1) {
|
||||
String charsetPart = contentType.substring(indexOfSemi + 1).trim();
|
||||
String[] charSetKeyAndValue = charsetPart.split("=", 2);
|
||||
if (charSetKeyAndValue.length == 2 && "charset".equalsIgnoreCase(charSetKeyAndValue[0])) {
|
||||
String charsetName = charSetKeyAndValue[1];
|
||||
return Charset.forName(charsetName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return StandardCharsets.UTF_8;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.janboerman.invsee.mojangapi;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import static com.janboerman.invsee.mojangapi.ResponseUtils.*;
|
||||
|
||||
/**
|
||||
* API to resolve players' usernames and unique IDs via <a href="https://github.com/Electroid/mojang-api">Electroid/mojang-api</a>.
|
||||
*/
|
||||
public class ElectroidAPI {
|
||||
//https://github.com/Electroid/mojang-api
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public ElectroidAPI(Executor asyncExecutor) {
|
||||
this.httpClient = HttpClient.newBuilder()
|
||||
.executor(asyncExecutor)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ElectroidAPI(HttpClient httpClient) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ElectroidAPI() {
|
||||
this(HttpClient.newHttpClient());
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<UUID>> lookupUniqueId(String userName) {
|
||||
CompletableFuture<HttpResponse<InputStream>> future = httpClient.sendAsync(HttpRequest
|
||||
.newBuilder(URI.create("https://api.ashcon.app/mojang/v2/user/" + userName))
|
||||
.header("Accept", "application/json")
|
||||
.header("User-Agent", "InvSee++/ElectroidAPI")
|
||||
.timeout(Duration.ofSeconds(5))
|
||||
.build(), HttpResponse.BodyHandlers.ofInputStream());
|
||||
|
||||
return future.thenApply(response -> {
|
||||
if (response.statusCode() == 200) {
|
||||
//ok!
|
||||
JSONObject json = readJSONObject(response);
|
||||
String uuid = (String) json.get("uuid"); // already contains dashes.
|
||||
return Optional.of(UUID.fromString(uuid));
|
||||
} else if (response.statusCode() == 204) {
|
||||
//no content
|
||||
return Optional.empty();
|
||||
} else {
|
||||
//unexpected
|
||||
throw new RuntimeException("Unexpected response from Electroid mojang api, status code=" + response.statusCode() + ".");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<String>> lookupUserName(UUID uniqueId) {
|
||||
CompletableFuture<HttpResponse<InputStream>> future = httpClient.sendAsync(HttpRequest
|
||||
.newBuilder(URI.create("https://api.ashcon.app/mojang/v2/user/" + uniqueId.toString())) // uuid with dashes allowed
|
||||
.header("Accept", "application/json")
|
||||
.header("User-Agent", "InvSee++/ElectroidAPI")
|
||||
.timeout(Duration.ofSeconds(5))
|
||||
.build(), HttpResponse.BodyHandlers.ofInputStream());
|
||||
|
||||
return future.thenApply(response -> {
|
||||
if (response.statusCode() == 200) {
|
||||
//ok!
|
||||
JSONObject json = readJSONObject(response);
|
||||
String userName = (String) json.get("username");
|
||||
return Optional.of(userName);
|
||||
} else if (response.statusCode() == 204) {
|
||||
//no content
|
||||
return Optional.empty();
|
||||
} else {
|
||||
//unexpected
|
||||
throw new RuntimeException("Unexpected response from Electroid mojang api, status code=" + response.statusCode() + ".");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.janboerman.invsee.mojangapi;
|
||||
|
||||
import com.janboerman.invsee.utils.UUIDHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.Charset;
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import static com.janboerman.invsee.mojangapi.ResponseUtils.*;
|
||||
|
||||
public class MojangAPI {
|
||||
//https://wiki.vg/Mojang_API
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public MojangAPI(Executor asyncExecutor) {
|
||||
this.httpClient = HttpClient.newBuilder()
|
||||
.executor(asyncExecutor)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Mojang API instance using the given HTTP client for all requests.
|
||||
* @param httpClient the client to use for HTTP requests
|
||||
*/
|
||||
@Deprecated
|
||||
public MojangAPI(HttpClient httpClient) {
|
||||
this.httpClient = Objects.requireNonNull(httpClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the instance of the Mojang API using {@link HttpClient#newHttpClient()}.
|
||||
*/
|
||||
@Deprecated
|
||||
public MojangAPI() {
|
||||
this(HttpClient.newHttpClient());
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<UUID>> lookupUniqueId(String userName) {
|
||||
CompletableFuture<HttpResponse<InputStream>> future = httpClient.sendAsync(HttpRequest
|
||||
.newBuilder(URI.create("https://api.mojang.com/users/profiles/minecraft/" + userName))
|
||||
.header("Accept", "application/json")
|
||||
.header("User-Agent", "InvSee++/MojangAPI")
|
||||
.timeout(Duration.ofSeconds(5))
|
||||
.build(), HttpResponse.BodyHandlers.ofInputStream());
|
||||
|
||||
return future.thenApply((HttpResponse<InputStream> response) -> {
|
||||
int statusCode = response.statusCode();
|
||||
|
||||
if (statusCode == 200) {
|
||||
//ok!
|
||||
JSONObject json = readJSONObject(response);
|
||||
String id = (String) json.get("id");
|
||||
UUID uuid = UUIDHelper.dashed(id);
|
||||
return Optional.of(uuid);
|
||||
}
|
||||
|
||||
else {
|
||||
//not ok
|
||||
return handleNotOk(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Optional<String>> lookupUserName(UUID uniqueId) {
|
||||
//no longer use name history api: https://wiki.vg/Mojang_API#UUID_to_Name_History_.28Removed.29,
|
||||
//use profile api instead:
|
||||
CompletableFuture<HttpResponse<InputStream>> future = httpClient.sendAsync(HttpRequest
|
||||
.newBuilder(URI.create("https://sessionserver.mojang.com/session/minecraft/profile/" + UUIDHelper.unDashed(uniqueId)))
|
||||
.header("Accept", "application/json")
|
||||
.header("User-Agent", "InvSee++/MojangAPI")
|
||||
.timeout(Duration.ofSeconds(5))
|
||||
.build(), HttpResponse.BodyHandlers.ofInputStream());
|
||||
|
||||
return future.thenApply((HttpResponse<InputStream> response) -> {
|
||||
int statusCode = response.statusCode();
|
||||
|
||||
if (statusCode == 200) {
|
||||
//ok!
|
||||
JSONObject profileJson = readJSONObject(response);
|
||||
String userName = (String) profileJson.get("name");
|
||||
return Optional.of(userName);
|
||||
}
|
||||
|
||||
else {
|
||||
//not ok
|
||||
return handleNotOk(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleNotOk(HttpResponse<InputStream> response) {
|
||||
int statusCode = response.statusCode();
|
||||
|
||||
if (statusCode == HTTP_NO_CONTENT) {
|
||||
//no content - a player with that username does not exist.
|
||||
return handleNoContent(response);
|
||||
}
|
||||
|
||||
else if (statusCode == HTTP_BAD_REQUEST) {
|
||||
//bad request
|
||||
return handleBadRequest(response);
|
||||
}
|
||||
|
||||
else if (statusCode == HTTP_TOO_MANY_REQUESTS) {
|
||||
//rate limited
|
||||
return handleTooManyRequests(response);
|
||||
}
|
||||
|
||||
else {
|
||||
//unknown response code - undocumented behaviour from mojang's api
|
||||
return handleUnknownStatusCode(response);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleNoContent(HttpResponse<InputStream> response) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleBadRequest(HttpResponse<InputStream> response) {
|
||||
JSONObject jsonObject = readJSONObject(response);
|
||||
|
||||
String error = (String) jsonObject.get("error");
|
||||
String errorMessage = (String) jsonObject.get("errorMessage");
|
||||
|
||||
throw new RuntimeException("We sent a bad request to Mojang. We got a(n) " + error + " with the following message: " + errorMessage);
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleTooManyRequests(HttpResponse<InputStream> response) {
|
||||
try (InputStream inputStream = response.body()) {
|
||||
byte[] bytes = inputStream.readAllBytes();
|
||||
Charset charset = charsetFromHeaders(response.headers());
|
||||
String errorMessage = new String(bytes, charset);
|
||||
throw new RuntimeException("We were rate limited by Mojang. Error message: " + errorMessage);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Exception occurred when processing 429 (rate limited) response.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Optional<T> handleUnknownStatusCode(HttpResponse<InputStream> response) {
|
||||
throw new RuntimeException("Unexpected status code from Mojang API: " + response.statusCode());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.janboerman.invsee.mojangapi;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.http.HttpHeaders;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
|
||||
final class ResponseUtils {
|
||||
|
||||
static final int HTTP_NO_CONTENT = 204;
|
||||
static final int HTTP_BAD_REQUEST = 400;
|
||||
static final int HTTP_TOO_MANY_REQUESTS = 429;
|
||||
|
||||
private ResponseUtils() {}
|
||||
|
||||
static JSONObject readJSONObject(HttpResponse<InputStream> response) {
|
||||
Charset charset = charsetFromHeaders(response.headers());
|
||||
try (InputStream inputStream = response.body();
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, charset)) {
|
||||
|
||||
Object json = new JSONParser().parse(inputStreamReader);
|
||||
if (json instanceof JSONObject) {
|
||||
return (JSONObject) json;
|
||||
} else {
|
||||
throw new RuntimeException("Expected response to be represented as a JSON Object, instead we got: " + json);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Could not read http response body", ioe);
|
||||
} catch (ParseException pe) {
|
||||
throw new RuntimeException("Invalid JSON from api", pe);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static JSONArray readJSONArray(HttpResponse<InputStream> response) {
|
||||
Charset charset = charsetFromHeaders(response.headers());
|
||||
try (InputStream inputStream = response.body();
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, charset)) {
|
||||
|
||||
Object json = new JSONParser().parse(inputStreamReader);
|
||||
if (json instanceof JSONArray) {
|
||||
return (JSONArray) json;
|
||||
} else {
|
||||
throw new RuntimeException("Expected response to be represented as a JSON Array, instead we got: " + json);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Could not read http response body", ioe);
|
||||
} catch (ParseException pe) {
|
||||
throw new RuntimeException("Invalid JSON from Mojang api", pe);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static Charset charsetFromHeaders(HttpHeaders headers) {
|
||||
Optional<String> optionalContentType = headers.firstValue("Content-Type");
|
||||
if (optionalContentType.isPresent()) {
|
||||
String contentType = optionalContentType.get();
|
||||
int indexOfSemi = contentType.indexOf(';');
|
||||
if (indexOfSemi != -1) {
|
||||
String charsetPart = contentType.substring(indexOfSemi + 1).trim();
|
||||
String[] charSetKeyAndValue = charsetPart.split("=", 2);
|
||||
if (charSetKeyAndValue.length == 2 && "charset".equalsIgnoreCase(charSetKeyAndValue[0])) {
|
||||
String charsetName = charSetKeyAndValue[1];
|
||||
return Charset.forName(charsetName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//fallback
|
||||
return StandardCharsets.UTF_8;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user