diff --git a/Core/src/main/java/com/craftaro/core/http/minecraft/MinecraftApiClient.java b/Core/src/main/java/com/craftaro/core/http/minecraft/MinecraftApiClient.java new file mode 100644 index 00000000..ac21dd61 --- /dev/null +++ b/Core/src/main/java/com/craftaro/core/http/minecraft/MinecraftApiClient.java @@ -0,0 +1,60 @@ +package com.craftaro.core.http.minecraft; + +import com.craftaro.core.SongodaCore; +import com.craftaro.core.http.HttpClient; +import com.craftaro.core.http.HttpResponse; +import com.google.gson.Gson; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class MinecraftApiClient { + private static final String SPRAX_API_URL = "https://api.sprax2013.de/mc/profile/"; + private static final String MOJANG_API_URL = "https://sessionserver.mojang.com/session/minecraft/profile/"; + + private final Gson gson = new Gson(); + private final HttpClient httpClient; + + private long nextSpraxApiRequestAllowed = 0; + + public MinecraftApiClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public CompletableFuture<@Nullable UuidToProfileResult> fetchProfile(UUID uuid) { + return CompletableFuture.supplyAsync(() -> { + HttpResponse profileResponse; + try { + if (this.nextSpraxApiRequestAllowed <= System.currentTimeMillis()) { + throw new IOException("Not allowed to use SpraxAPI"); + } + + this.nextSpraxApiRequestAllowed = 0; + profileResponse = this.httpClient.get(SPRAX_API_URL + uuid); + } catch (IOException ignored) { + try { + profileResponse = this.httpClient.get(MOJANG_API_URL + uuid.toString().replace("-", "")); + + if (this.nextSpraxApiRequestAllowed <= System.currentTimeMillis()) { + this.nextSpraxApiRequestAllowed = System.currentTimeMillis() + 1000 * 60 * 5; + SongodaCore.getLogger().warning("Error contacting api.sprax2013.de while sessionserver.mojang.com is working. Not using SpraxAPI for the next 5 minutes..."); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + try { + if (profileResponse.getResponseCode() == 404 || profileResponse.getResponseCode() == 204) { + return null; + } + + return this.gson.fromJson(profileResponse.getBodyAsString(), UuidToProfileResult.class); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + }); + } +} diff --git a/Core/src/main/java/com/craftaro/core/http/minecraft/UuidToProfileResult.java b/Core/src/main/java/com/craftaro/core/http/minecraft/UuidToProfileResult.java new file mode 100644 index 00000000..55b13848 --- /dev/null +++ b/Core/src/main/java/com/craftaro/core/http/minecraft/UuidToProfileResult.java @@ -0,0 +1,61 @@ +package com.craftaro.core.http.minecraft; + +import com.craftaro.core.nms.Nms; +import com.craftaro.core.nms.entity.player.GameProfile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.regex.Pattern; + +@SuppressWarnings({"unused", "FieldMayBeFinal"}) +public class UuidToProfileResult { + private static final Pattern ADD_HYPHENS_TO_UUID = Pattern.compile("(\\w{8})(\\w{4})(\\w{4})(\\w{3})(\\w{12})"); + + private @Nullable String id; + private @Nullable String name; + private @NotNull List properties = Collections.emptyList(); + private @NotNull List profileActions = Collections.emptyList(); + + public @NotNull UUID getId() { + return UUID.fromString( + ADD_HYPHENS_TO_UUID + .matcher(Objects.requireNonNull(this.id)) + .replaceAll("$1-$2-$3-$4-$5") + ); + } + + public @NotNull String getName() { + return Objects.requireNonNull(this.name); + } + + public @NotNull List getProperties() { + return this.properties; + } + + public @NotNull List getProfileActions() { + return this.profileActions; + } + + public @NotNull GameProfile createGameProfile() { + String textureValue = null; + String textureSignature = null; + for (Property property : this.properties) { + if (property.name.equals("textures")) { + textureValue = property.value; + textureSignature = property.signature; + } + } + + return Nms.getImplementations().getPlayer().createProfile(getId(), getName(), textureValue, textureSignature); + } + + public static class Property { + private String name; + private String value; + private @Nullable String signature; + } +}