mirror of
https://github.com/Suiranoil/SkinRestorer.git
synced 2026-01-16 04:42:12 +00:00
update WebUtils to use HttpClient
This commit is contained in:
@@ -2,24 +2,25 @@ package net.lionarius.skinrestorer.skin.provider;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import net.lionarius.skinrestorer.skin.SkinVariant;
|
||||
import net.lionarius.skinrestorer.util.JsonUtils;
|
||||
import net.lionarius.skinrestorer.util.PlayerUtils;
|
||||
import net.lionarius.skinrestorer.util.Result;
|
||||
import net.lionarius.skinrestorer.util.WebUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class MineskinSkinProvider implements SkinProvider {
|
||||
|
||||
private static final URI API_URL;
|
||||
private static final URI API_URI;
|
||||
|
||||
static {
|
||||
try {
|
||||
API_URL = new URI("https://api.mineskin.org/generate/url");
|
||||
API_URI = new URI("https://api.mineskin.org/");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
@@ -38,15 +39,31 @@ public final class MineskinSkinProvider implements SkinProvider {
|
||||
@Override
|
||||
public Result<Optional<Property>, Exception> getSkin(String url, SkinVariant variant) {
|
||||
try {
|
||||
String body = ("{\"variant\":\"%s\",\"name\":\"%s\",\"visibility\":%d,\"url\":\"%s\"}")
|
||||
.formatted(variant.toString(), "none", 1, url);
|
||||
|
||||
JsonObject texture = JsonUtils.parseJson(WebUtils.postRequest(API_URL.toURL(), "application/json", body))
|
||||
.getAsJsonObject("data").getAsJsonObject("texture");
|
||||
var result = MineskinSkinProvider.uploadToMineskin(url, variant);
|
||||
var texture = result.getAsJsonObject("data").getAsJsonObject("texture");
|
||||
|
||||
return Result.ofNullable(new Property(PlayerUtils.TEXTURES_KEY, texture.get("value").getAsString(), texture.get("signature").getAsString()));
|
||||
} catch (Exception e) {
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static JsonObject uploadToMineskin(String url, SkinVariant variant) throws IOException {
|
||||
var body = ("{\"variant\":\"%s\",\"name\":\"%s\",\"visibility\":%d,\"url\":\"%s\"}")
|
||||
.formatted(variant.toString(), "none", 0, url);
|
||||
|
||||
var request = HttpRequest.newBuilder()
|
||||
.uri(MineskinSkinProvider.API_URI.resolve("generate/url"))
|
||||
.POST(HttpRequest.BodyPublishers.ofString(body))
|
||||
.header("Content-Type", "application/json")
|
||||
.build();
|
||||
|
||||
var response = WebUtils.executeRequest(request);
|
||||
WebUtils.throwOnClientErrors(response);
|
||||
|
||||
if (response.statusCode() != 200)
|
||||
throw new IllegalArgumentException("could not get mineskin skin");
|
||||
|
||||
return JsonUtils.parseJson(response.body());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,18 +11,18 @@ import net.lionarius.skinrestorer.util.WebUtils;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class MojangSkinProvider implements SkinProvider {
|
||||
|
||||
private static final URI API_URL;
|
||||
private static final URI SESSION_SERVER_URL;
|
||||
private static final URI API_URI;
|
||||
private static final URI SESSION_SERVER_URI;
|
||||
|
||||
static {
|
||||
try {
|
||||
API_URL = new URI("https://api.mojang.com/users/profiles/minecraft/");
|
||||
SESSION_SERVER_URL = new URI("https://sessionserver.mojang.com/session/minecraft/profile/");
|
||||
API_URI = new URI("https://api.mojang.com/");
|
||||
SESSION_SERVER_URI = new URI("https://sessionserver.mojang.com/");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
@@ -42,9 +42,10 @@ public final class MojangSkinProvider implements SkinProvider {
|
||||
@Override
|
||||
public Result<Optional<Property>, Exception> getSkin(String username, SkinVariant variant) {
|
||||
try {
|
||||
UUID uuid = getUUID(username);
|
||||
JsonObject texture = JsonUtils.parseJson(WebUtils.getRequest(SESSION_SERVER_URL.resolve(uuid + "?unsigned=false").toURL()))
|
||||
.getAsJsonArray("properties").get(0).getAsJsonObject();
|
||||
var uuid = MojangSkinProvider.getUuid(username);
|
||||
var profile = MojangSkinProvider.getMojangProfile(uuid);
|
||||
|
||||
var texture = profile.getAsJsonArray("properties").get(0).getAsJsonObject();
|
||||
|
||||
return Result.ofNullable(new Property(PlayerUtils.TEXTURES_KEY, texture.get("value").getAsString(), texture.get("signature").getAsString()));
|
||||
} catch (Exception e) {
|
||||
@@ -52,8 +53,43 @@ public final class MojangSkinProvider implements SkinProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private static UUID getUUID(String name) throws IOException {
|
||||
return UUID.fromString(JsonUtils.parseJson(WebUtils.getRequest(API_URL.resolve(name).toURL())).get("id").getAsString()
|
||||
.replaceFirst("(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)", "$1-$2-$3-$4-$5"));
|
||||
private static String getUuid(final String name) throws IOException {
|
||||
var request = HttpRequest.newBuilder()
|
||||
.uri(MojangSkinProvider.API_URI
|
||||
.resolve("users/profiles/minecraft/")
|
||||
.resolve(name)
|
||||
)
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
var response = WebUtils.executeRequest(request);
|
||||
WebUtils.throwOnClientErrors(response);
|
||||
|
||||
if (response.statusCode() != 200)
|
||||
throw new IllegalArgumentException("no profile with name " + name);
|
||||
|
||||
var profile = JsonUtils.parseJson(response.body());
|
||||
if (profile == null)
|
||||
return null;
|
||||
|
||||
return profile.get("id").getAsString();
|
||||
}
|
||||
|
||||
private static JsonObject getMojangProfile(final String uuid) throws IOException {
|
||||
var request = HttpRequest.newBuilder()
|
||||
.uri(MojangSkinProvider.SESSION_SERVER_URI
|
||||
.resolve("session/minecraft/profile/")
|
||||
.resolve(uuid + "?unsigned=false")
|
||||
)
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
var response = WebUtils.executeRequest(request);
|
||||
WebUtils.throwOnClientErrors(response);
|
||||
|
||||
if (response.statusCode() != 200)
|
||||
throw new IllegalArgumentException("no profile with uuid " + uuid);
|
||||
|
||||
return JsonUtils.parseJson(response.body());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +1,69 @@
|
||||
package net.lionarius.skinrestorer.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.Date;
|
||||
|
||||
public final class WebUtils {
|
||||
|
||||
private WebUtils() {}
|
||||
|
||||
public static final String USER_AGENT = "SkinRestorer";
|
||||
public static final String USER_AGENT;
|
||||
|
||||
public static String postRequest(URL url, String contentType, String body)
|
||||
throws IOException {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", contentType);
|
||||
connection.setRequestProperty("User-Agent", WebUtils.USER_AGENT);
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
|
||||
try (OutputStream os = connection.getOutputStream()) {
|
||||
os.write(body.getBytes(StandardCharsets.UTF_8), 0, body.length());
|
||||
}
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
return StringUtils.readString(br);
|
||||
static {
|
||||
var date = new Date();
|
||||
USER_AGENT = String.format("SkinRestorer/%d", date.getTime() % 65535);
|
||||
}
|
||||
|
||||
private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder().build();
|
||||
|
||||
public static HttpResponse<String> executeRequest(HttpRequest request) throws IOException {
|
||||
try {
|
||||
var modifiedRequest = HttpRequest.newBuilder(request, (name, value) -> true)
|
||||
.header("User-Agent", WebUtils.USER_AGENT)
|
||||
.build();
|
||||
|
||||
final var response = WebUtils.HTTP_CLIENT.send(modifiedRequest, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
if (response.statusCode() >= 500)
|
||||
throw new IOException("server error " + response.statusCode());
|
||||
|
||||
return response;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getRequest(URL url) throws IOException {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setDoOutput(true);
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
return StringUtils.readString(br);
|
||||
public static void throwOnClientErrors(HttpResponse<?> response) {
|
||||
String message = null;
|
||||
switch (response.statusCode()) {
|
||||
case 400:
|
||||
message = "bad request";
|
||||
break;
|
||||
case 401:
|
||||
message = "unauthorized";
|
||||
break;
|
||||
case 403:
|
||||
message = "forbidden";
|
||||
break;
|
||||
case 404:
|
||||
message = "not found";
|
||||
break;
|
||||
case 405:
|
||||
message = "method not allowed";
|
||||
break;
|
||||
case 408:
|
||||
message = "request timeout";
|
||||
break;
|
||||
case 429:
|
||||
message = "too many requests";
|
||||
break;
|
||||
}
|
||||
|
||||
if (message != null)
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user