package me.libraryaddict.disguise.utilities; import com.google.gson.Gson; import lombok.Getter; import me.libraryaddict.disguise.LibsDisguises; import me.libraryaddict.disguise.utilities.plugin.PluginInformation; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.libs.org.apache.commons.io.FileUtils; import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; public class UpdateChecker { private final String resourceID; @Getter private String latestVersion; @Getter private int latestSnapshot; private final long started = System.currentTimeMillis(); private int lastDownload; public UpdateChecker(String resourceID) { this.resourceID = resourceID; } public PluginInformation grabSnapshotBuild() { if (getLatestSnapshot() == 0) { throw new IllegalArgumentException(); } if (lastDownload == -1) { return null; } if (getLatestSnapshot() == lastDownload) { return null; } return grabSnapshotBuild(getLatestSnapshot()); } public PluginInformation grabSnapshotBuild(int buildNo) { PluginInformation result = grabSnapshotBuild( "https://ci.md-5.net/job/LibsDisguises/" + buildNo + "/artifact/target/LibsDisguises.jar"); if (result != null) { lastDownload = buildNo; } return result; } public PluginInformation grabLatestSnapshot() { PluginInformation result = grabSnapshotBuild( "https://ci.md-5.net/job/LibsDisguises/lastSuccessfulBuild/artifact/target/LibsDisguises.jar"); if (result != null) { lastDownload = LibsDisguises.getInstance().getBuildNumber(); } return result; } public boolean isDownloading() { return lastDownload == -1; } public int getLastDownload() { return lastDownload; } public PluginInformation grabSnapshotBuild(String urlString) { DisguiseUtilities.getLogger().info("Now downloading latest build of Lib's Disguises from " + urlString); lastDownload = -1; File dest = new File(Bukkit.getUpdateFolderFile(), "LibsDisguises.jar"); if (dest.exists()) { dest.delete(); } dest.getParentFile().mkdirs(); try { // We're connecting to spigot's API URL url = new URL(urlString); // Creating a connection HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setDefaultUseCaches(false); // Get the input stream, what we receive try (InputStream input = con.getInputStream()) { FileUtils.copyInputStreamToFile(input, dest); } DisguiseUtilities.getLogger().info("Download success!"); return LibsPremium.getInformation(dest); } catch (Exception ex) { // Failed, set the last download back to previous build dest.delete(); DisguiseUtilities.getLogger().warning("Failed to download snapshot build."); lastDownload = 0; ex.printStackTrace(); } return null; } public void checkSnapshotUpdate(int buildNumber) { Map lastBuild = fetchLastSnapshotBuild(); if (lastBuild == null || !lastBuild.containsKey("id") || !lastBuild.containsKey("timestamp")) { return; } int newBuildNumber = Integer.parseInt((String) lastBuild.get("id")); // If new build number is same or older if (newBuildNumber <= buildNumber) { return; } Date newBuildDate = new Date(((Number) lastBuild.get("timestamp")).longValue()); // If the new snapshot is at least 3 days old /*if (newBuildDate.getTime() >= System.currentTimeMillis() - TimeUnit.DAYS.toMillis(3)) { return; }*/ latestSnapshot = newBuildNumber; } public void checkOfficialUpdate(String currentVersion) { String version = fetchSpigotVersion(); if (version == null) { return; } if (!isNewerVersion(currentVersion, version)) { return; } latestVersion = version; } /** * Asks spigot for the version */ private String fetchSpigotVersion() { try { // We're connecting to spigot's API URL url = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + resourceID); // Creating a connection HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setDefaultUseCaches(false); // Get the input stream, what we receive try (InputStream input = con.getInputStream()) { // Read it to string String version = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines() .collect(Collectors.joining("\n")); // If the version is not empty, return it if (!version.isEmpty()) { return version; } } } catch (Exception ex) { DisguiseUtilities.getLogger().warning("Failed to check for a update on spigot."); } return null; } private boolean isNewerVersion(String currentVersion, String newVersion) { currentVersion = currentVersion.replaceAll("(v)|(-SNAPSHOT)", ""); newVersion = newVersion.replaceAll("(v)|(-SNAPSHOT)", ""); // If the server has been online for less than 6 hours and both versions are 1.1.1 kind of versions if (started + TimeUnit.HOURS.toMillis(6) > System.currentTimeMillis() && currentVersion.matches("[0-9]+(\\.[0-9]+)*") && newVersion.matches("[0-9]+(\\.[0-9]+)*")) { int cVersion = Integer.parseInt(currentVersion.replace(".", "")); int nVersion = Integer.parseInt(newVersion.replace(".", "")); // If the current version is a higher version, and is only a higher version by 3 minor numbers // Then we have a cache problem if (cVersion > nVersion && nVersion + 3 > cVersion) { return false; } } // Lets just ignore all this fancy logic, and say that if you're not on the current release, you're outdated! return !currentVersion.equals(newVersion); /* // Remove 'v' and '-SNAPSHOT' from string, split by decimal points String[] cSplit = currentVersion.replaceAll("(v)|(-SNAPSHOT)", "").split("\\."); String[] nSplit = newVersion.replaceAll("(v)|(-SNAPSHOT)", "").split("\\."); // Lets just ignore all this fancy logic, and say that if you're not on the current release, you're outdated! return !Arrays.equals(cSplit, nSplit); // Iterate over the versions from left to right for (int i = 0; i < Math.max(cSplit.length, nSplit.length); i++) { // If the current version doesn't have the next version, then it's older if (cSplit.length <= i) { return true; } else if (nSplit.length <= i) { // If the new version doesn't have the next version, then it's older return false; } // If both strings are numerical if (cSplit[i].matches("[0-9]+") && nSplit[i].matches("[0-9]+")) { int cInt = Integer.parseInt(cSplit[i]); int nInt = Integer.parseInt(nSplit[i]); // Same version if (cInt == nInt) { continue; } // Return if current version is inferior to new version return cInt < nInt; } // String compare the versions, should perform the same as an int compare int compareResult = cSplit[i].compareTo(nSplit[i]); // Same version if (compareResult == 0) { continue; } // Return if current version is inferior to new versio return compareResult < 0; } // Both versions should be the same, return false as it's not a newer version return false;*/ } /** * Fetches from jenkins, using the REST api the last snapshot build information */ private Map fetchLastSnapshotBuild() { try { // We're connecting to md_5's jenkins REST api URL url = new URL("https://ci.md-5.net/job/LibsDisguises/lastSuccessfulBuild/api/json"); // Creating a connection HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setDefaultUseCaches(false); Map jsonObject; // Get the input stream, what we receive try (InputStream input = con.getInputStream()) { // Read it to string String json = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines() .collect(Collectors.joining("\n")); jsonObject = new Gson().fromJson(json, Map.class); } return jsonObject; } catch (Exception ex) { DisguiseUtilities.getLogger().warning("Failed to check for a snapshot update on jenkins."); } return null; } }