Force a delay between MineSkin requests, fixes #543

This commit is contained in:
libraryaddict 2021-01-28 05:21:48 +13:00
parent bd732d256d
commit 1c85ba7586
2 changed files with 36 additions and 38 deletions

View File

@ -52,16 +52,25 @@ public class MineSkinAPI {
* *
* @param url * @param url
*/ */
public MineSkinResponse generateFromUrl(SkinUtils.SkinCallback callback, String url, public MineSkinResponse generateFromUrl(SkinUtils.SkinCallback callback, String url, SkinUtils.ModelType modelType) {
SkinUtils.ModelType modelType) {
return doPost(callback, "/generate/url", url, null, modelType); return doPost(callback, "/generate/url", url, null, modelType);
} }
private MineSkinResponse doPost(SkinUtils.SkinCallback callback, String path, String skinUrl, File file, private MineSkinResponse doPost(SkinUtils.SkinCallback callback, String path, String skinUrl, File file, SkinUtils.ModelType modelType) {
SkinUtils.ModelType modelType) {
lock.lock(); lock.lock();
long sleep = nextRequest - System.currentTimeMillis();
if (sleep > 0) {
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
HttpURLConnection connection = null; HttpURLConnection connection = null;
long nextRequestIn = TimeUnit.SECONDS.toMillis(10);
try { try {
URL url = new URL("https://api.mineskin.org" + path); URL url = new URL("https://api.mineskin.org" + path);
@ -78,8 +87,7 @@ public class MineSkinAPI {
String charset = "UTF-8"; String charset = "UTF-8";
String CRLF = "\r\n"; // Line separator required by multipart/form-data. String CRLF = "\r\n"; // Line separator required by multipart/form-data.
try (OutputStream output = connection.getOutputStream(); PrintWriter writer = new PrintWriter( try (OutputStream output = connection.getOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true)) {
new OutputStreamWriter(output, charset), true)) {
// Send normal param. // Send normal param.
writer.append("--").append(boundary).append(CRLF); writer.append("--").append(boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"visibility\"").append(CRLF); writer.append("Content-Disposition: form-data; name=\"visibility\"").append(CRLF);
@ -89,8 +97,7 @@ public class MineSkinAPI {
if (file != null) { if (file != null) {
// Send binary file. // Send binary file.
writer.append("--").append(boundary).append(CRLF); writer.append("--").append(boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(file.getName()) writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(file.getName()).append("\"").append(CRLF);
.append("\"").append(CRLF);
writer.append("Content-Type: image/png").append(CRLF); writer.append("Content-Type: image/png").append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF); writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush(); writer.append(CRLF).flush();
@ -115,9 +122,8 @@ public class MineSkinAPI {
} }
if (connection.getResponseCode() == 500) { if (connection.getResponseCode() == 500) {
APIError error = new Gson().fromJson( APIError error = new Gson().fromJson(new BufferedReader(new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8)).lines()
new BufferedReader(new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8)) .collect(Collectors.joining("\n")), APIError.class);
.lines().collect(Collectors.joining("\n")), APIError.class);
if (error.code == 403) { if (error.code == 403) {
callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code, LibsMsg.SKIN_API_403.get()); callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code, LibsMsg.SKIN_API_403.get());
@ -129,8 +135,7 @@ public class MineSkinAPI {
callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code, LibsMsg.SKIN_API_TIMEOUT.get()); callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code, LibsMsg.SKIN_API_TIMEOUT.get());
return null; return null;
} else { } else {
callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code, callback.onError(LibsMsg.SKIN_API_FAIL_CODE, "" + error.code, LibsMsg.SKIN_API_IMAGE_HAS_ERROR.get(error.error));
LibsMsg.SKIN_API_IMAGE_HAS_ERROR.get(error.error));
return null; return null;
} }
} else if (connection.getResponseCode() == 400) { } else if (connection.getResponseCode() == 400) {
@ -141,45 +146,42 @@ public class MineSkinAPI {
callback.onError(LibsMsg.SKIN_API_BAD_FILE); callback.onError(LibsMsg.SKIN_API_BAD_FILE);
return null; return null;
} }
} else if (connection.getResponseCode() == 429) {
callback.onError(LibsMsg.SKIN_API_FAIL_TOO_FAST);
return null;
} }
// Get the input stream, what we receive // Get the input stream, what we receive
try (InputStream input = connection.getInputStream()) { try (InputStream input = connection.getInputStream()) {
// Read it to string // Read it to string
String response = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines() String response = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines().collect(Collectors.joining("\n"));
.collect(Collectors.joining("\n"));
MineSkinResponse skinResponse = new Gson().fromJson(response, MineSkinResponse.class); MineSkinResponse skinResponse = new Gson().fromJson(response, MineSkinResponse.class);
nextRequest = System.currentTimeMillis() + (long) (skinResponse.getNextRequest() * 1000); nextRequestIn = (long) (skinResponse.getNextRequest() * 1000);
return skinResponse; return skinResponse;
} }
} } catch (SocketTimeoutException ex) {
catch (SocketTimeoutException ex) {
callback.onError(skinUrl == null ? LibsMsg.SKIN_API_TIMEOUT_ERROR : LibsMsg.SKIN_API_IMAGE_TIMEOUT); callback.onError(skinUrl == null ? LibsMsg.SKIN_API_TIMEOUT_ERROR : LibsMsg.SKIN_API_IMAGE_TIMEOUT);
return null; return null;
} } catch (Exception ex) {
catch (Exception ex) {
nextRequest = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(10);
try { try {
if (connection != null && (connection.getResponseCode() == 524 || connection.getResponseCode() == 408 || if (connection != null && (connection.getResponseCode() == 524 || connection.getResponseCode() == 408 || connection.getResponseCode() == 504 ||
connection.getResponseCode() == 504 || connection.getResponseCode() == 599)) { connection.getResponseCode() == 599)) {
callback.onError(LibsMsg.SKIN_API_TIMEOUT_ERROR); callback.onError(LibsMsg.SKIN_API_TIMEOUT_ERROR);
return null; return null;
} }
} } catch (IOException e) {
catch (IOException e) {
} }
DisguiseUtilities.getLogger().warning("Failed to access MineSkin.org"); DisguiseUtilities.getLogger().warning("Failed to access MineSkin.org");
ex.printStackTrace(); ex.printStackTrace();
callback.onError(LibsMsg.SKIN_API_FAIL); callback.onError(LibsMsg.SKIN_API_FAIL);
} } finally {
finally {
lock.unlock(); lock.unlock();
nextRequest = System.currentTimeMillis() + nextRequestIn + 1000;
} }
return null; return null;
@ -204,8 +206,7 @@ public class MineSkinAPI {
// Get the input stream, what we receive // Get the input stream, what we receive
try (InputStream input = con.getInputStream()) { try (InputStream input = con.getInputStream()) {
// Read it to string // Read it to string
String response = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines() String response = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines().collect(Collectors.joining("\n"));
.collect(Collectors.joining("\n"));
MineSkinResponse skinResponse = new Gson().fromJson(response, MineSkinResponse.class); MineSkinResponse skinResponse = new Gson().fromJson(response, MineSkinResponse.class);
@ -213,19 +214,16 @@ public class MineSkinAPI {
return skinResponse; return skinResponse;
} }
} } catch (Exception ex) {
catch (Exception ex) {
nextRequest = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(10); nextRequest = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(10);
if (ex.getMessage() != null && if (ex.getMessage() != null && ex.getMessage().contains("Server returned HTTP response code: 400 for URL")) {
ex.getMessage().contains("Server returned HTTP response code: 400 for URL")) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
DisguiseUtilities.getLogger().warning("Failed to access MineSkin.org"); DisguiseUtilities.getLogger().warning("Failed to access MineSkin.org");
ex.printStackTrace(); ex.printStackTrace();
} } finally {
finally {
lock.unlock(); lock.unlock();
} }
@ -237,8 +235,7 @@ public class MineSkinAPI {
* *
* @param file * @param file
*/ */
public MineSkinResponse generateFromFile(SkinUtils.SkinCallback callback, File file, public MineSkinResponse generateFromFile(SkinUtils.SkinCallback callback, File file, SkinUtils.ModelType modelType) {
SkinUtils.ModelType modelType) {
return doPost(callback, "/generate/upload", null, file, modelType); return doPost(callback, "/generate/upload", null, file, modelType);
} }
} }

View File

@ -223,6 +223,7 @@ public enum LibsMsg {
SKIN_API_IN_USE(ChatColor.RED + "mineskin.org is currently in use, please try again"), SKIN_API_IN_USE(ChatColor.RED + "mineskin.org is currently in use, please try again"),
SKIN_API_TIMER(ChatColor.RED + "mineskin.org can be used again in %s seconds"), SKIN_API_TIMER(ChatColor.RED + "mineskin.org can be used again in %s seconds"),
SKIN_API_FAIL(ChatColor.RED + "Unexpected error while accessing mineskin.org, please try again"), SKIN_API_FAIL(ChatColor.RED + "Unexpected error while accessing mineskin.org, please try again"),
SKIN_API_FAIL_TOO_FAST(ChatColor.RED + "Too many requests accessing mineskin.org, please slow down!"),
SKIN_API_BAD_URL(ChatColor.RED + "Invalid url provided! Please ensure it is a .png file download!"), SKIN_API_BAD_URL(ChatColor.RED + "Invalid url provided! Please ensure it is a .png file download!"),
SKIN_API_FAILED_URL(ChatColor.RED + "Invalid url provided! mineskin.org failed to grab it!"), SKIN_API_FAILED_URL(ChatColor.RED + "Invalid url provided! mineskin.org failed to grab it!"),
SKIN_API_FAIL_CODE(ChatColor.RED + "Error %s! %s"), SKIN_API_FAIL_CODE(ChatColor.RED + "Error %s! %s"),