Better handling for updates checking, can now autoupdate on dev and release builds
This commit is contained in:
		| @@ -13,6 +13,7 @@ import me.libraryaddict.disguise.utilities.parser.DisguiseParseException; | ||||
| import me.libraryaddict.disguise.utilities.parser.DisguiseParser; | ||||
| import me.libraryaddict.disguise.utilities.parser.DisguisePerm; | ||||
| import me.libraryaddict.disguise.utilities.reflection.NmsVersion; | ||||
| import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; | ||||
| import me.libraryaddict.disguise.utilities.translations.LibsMsg; | ||||
| import me.libraryaddict.disguise.utilities.translations.TranslateType; | ||||
| import org.bukkit.Bukkit; | ||||
| @@ -26,16 +27,16 @@ import org.bukkit.configuration.file.YamlConfiguration; | ||||
| import org.bukkit.entity.Entity; | ||||
| import org.bukkit.permissions.Permission; | ||||
| import org.bukkit.permissions.PermissionDefault; | ||||
| import org.bukkit.scheduler.BukkitTask; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.PrintWriter; | ||||
| import java.io.*; | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.Iterator; | ||||
| import java.util.Map.Entry; | ||||
| import java.util.Random; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | ||||
| public class DisguiseConfig { | ||||
|     @Getter | ||||
| @@ -46,9 +47,6 @@ public class DisguiseConfig { | ||||
|     private static HashMap<DisguisePerm, String> customDisguises = new HashMap<>(); | ||||
|     @Getter | ||||
|     @Setter | ||||
|     private static String updateNotificationPermission; | ||||
|     @Getter | ||||
|     @Setter | ||||
|     private static UpdatesBranch updatesBranch = UpdatesBranch.SAME_BUILDS; | ||||
|     @Getter | ||||
|     @Setter | ||||
| @@ -231,6 +229,127 @@ public class DisguiseConfig { | ||||
|     @Getter | ||||
|     @Setter | ||||
|     private static int tablistRemoveDelay; | ||||
|     @Getter | ||||
|     private static boolean usingReleaseBuild = true; | ||||
|     @Getter | ||||
|     private static boolean bisectHosted = true; | ||||
|     @Getter | ||||
|     private static String savedServerIp = ""; | ||||
|     @Getter | ||||
|     private static boolean autoUpdate; | ||||
|     @Getter | ||||
|     private static boolean notifyUpdate; | ||||
|     private static BukkitTask updaterTask; | ||||
|  | ||||
|     public static void setAutoUpdate(boolean update) { | ||||
|         if (isAutoUpdate() == update) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         autoUpdate = update; | ||||
|         doUpdaterTask(); | ||||
|     } | ||||
|  | ||||
|     public static void setNotifyUpdate(boolean update) { | ||||
|         if (isNotifyUpdate() == update) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         notifyUpdate = update; | ||||
|         doUpdaterTask(); | ||||
|     } | ||||
|  | ||||
|     private static void doUpdaterTask() { | ||||
|         boolean startTask = isAutoUpdate() || isNotifyUpdate(); | ||||
|  | ||||
|         // Don't ever run the auto updater on a custom build.. | ||||
|         if (!LibsDisguises.getInstance().isNumberedBuild()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (updaterTask == null != startTask) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!startTask) { | ||||
|             updaterTask.cancel(); | ||||
|             updaterTask = null; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         updaterTask = Bukkit.getScheduler().runTaskTimerAsynchronously(LibsDisguises.getInstance(), new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 LibsDisguises.getInstance().getUpdateChecker().doAutoUpdateCheck(); | ||||
|             } | ||||
|         }, 0, (20 * TimeUnit.HOURS.toSeconds(6))); // Check every 6 hours | ||||
|     } | ||||
|  | ||||
|     public static void setUsingReleaseBuilds(boolean useReleaseBuilds) { | ||||
|         if (useReleaseBuilds == isUsingReleaseBuild()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         usingReleaseBuild = useReleaseBuilds; | ||||
|         saveInternalConfig(); | ||||
|     } | ||||
|  | ||||
|     public static void setBisectHosted(boolean isBisectHosted, String serverIP) { | ||||
|         if (isBisectHosted() == isBisectHosted && getSavedServerIp().equals(serverIP)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         bisectHosted = isBisectHosted; | ||||
|         savedServerIp = serverIP; | ||||
|         saveInternalConfig(); | ||||
|     } | ||||
|  | ||||
|     public static void loadInternalConfig() { | ||||
|         File internalFile = new File(LibsDisguises.getInstance().getDataFolder(), "internal.yml"); | ||||
|  | ||||
|         if (!internalFile.exists()) { | ||||
|             saveInternalConfig(); | ||||
|         } | ||||
|  | ||||
|         YamlConfiguration configuration = YamlConfiguration.loadConfiguration(internalFile); | ||||
|  | ||||
|         bisectHosted = configuration.getBoolean("Bisect-Hosted", isBisectHosted()); | ||||
|         savedServerIp = configuration.getString("Server-IP", getSavedServerIp()); | ||||
|         usingReleaseBuild = configuration.getBoolean("ReleaseBuild", isUsingReleaseBuild()); | ||||
|  | ||||
|         if (!configuration.contains("Bisect-Hosted") || !configuration.contains("Server-IP") || | ||||
|                 !configuration.contains("ReleaseBuild")) { | ||||
|             saveInternalConfig(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void saveInternalConfig() { | ||||
|         File internalFile = new File(LibsDisguises.getInstance().getDataFolder(), "internal.yml"); | ||||
|  | ||||
|         String internalConfig = ReflectionManager | ||||
|                 .getResourceAsString(LibsDisguises.getInstance().getFile(), "internal.yml"); | ||||
|  | ||||
|         // Bisect hosted, server ip, release builds | ||||
|         for (Object s : new Object[]{isBisectHosted(), getSavedServerIp(), isUsingReleaseBuild()}) { | ||||
|             internalConfig = internalConfig.replaceFirst("%data%", "" + s); | ||||
|         } | ||||
|  | ||||
|         internalFile.delete(); | ||||
|  | ||||
|         try { | ||||
|             internalFile.createNewFile(); | ||||
|         } | ||||
|         catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|  | ||||
|         try (PrintWriter writer = new PrintWriter(internalFile, "UTF-8")) { | ||||
|             writer.write(internalConfig); | ||||
|         } | ||||
|         catch (FileNotFoundException | UnsupportedEncodingException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static PermissionDefault getCommandVisibility() { | ||||
|         return commandVisibility; | ||||
| @@ -438,7 +557,6 @@ public class DisguiseConfig { | ||||
|         setUUIDGeneratedVersion(config.getInt("UUIDVersion")); | ||||
|         setUndisguiseOnWorldChange(config.getBoolean("UndisguiseOnWorldChange")); | ||||
|         setUpdateGameProfiles(config.getBoolean("UpdateGameProfiles")); | ||||
|         setUpdateNotificationPermission(config.getString("Permission")); | ||||
|         setUseTranslations(config.getBoolean("Translations")); | ||||
|         setVelocitySent(config.getBoolean("SendVelocity")); | ||||
|         setViewDisguises(config.getBoolean("ViewSelfDisguises")); | ||||
| @@ -447,6 +565,7 @@ public class DisguiseConfig { | ||||
|         setWolfDyeable(config.getBoolean("DyeableWolf")); | ||||
|         setScoreboardDisguiseNames(config.getBoolean("ScoreboardNames")); | ||||
|         setTablistRemoveDelay(config.getInt("TablistRemoveDelay")); | ||||
|         setAutoUpdate(config.getBoolean("AutoUpdate")); | ||||
|  | ||||
|         if (!LibsPremium.isPremium() && (isSavePlayerDisguises() || isSaveEntityDisguises())) { | ||||
|             DisguiseUtilities.getLogger().warning("You must purchase the plugin to use saved disguises!"); | ||||
| @@ -561,7 +680,8 @@ public class DisguiseConfig { | ||||
|             if (missingConfigs > 0) { | ||||
|                 DisguiseUtilities.getLogger().warning("Your config is missing " + missingConfigs + | ||||
|                         " options! Please consider regenerating your config!"); | ||||
|                 DisguiseUtilities.getLogger().info("You can also add the missing entries yourself! Try '/libsdisguises config'"); | ||||
|                 DisguiseUtilities.getLogger() | ||||
|                         .info("You can also add the missing entries yourself! Try '/libsdisguises config'"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -17,7 +17,7 @@ import me.libraryaddict.disguise.commands.undisguise.UndisguiseRadiusCommand; | ||||
| import me.libraryaddict.disguise.commands.utils.*; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||
| import me.libraryaddict.disguise.utilities.LibsPremium; | ||||
| import me.libraryaddict.disguise.utilities.UpdateChecker; | ||||
| import me.libraryaddict.disguise.utilities.updates.UpdateChecker; | ||||
| import me.libraryaddict.disguise.utilities.listeners.DisguiseListener; | ||||
| import me.libraryaddict.disguise.utilities.metrics.MetricsInitalizer; | ||||
| import me.libraryaddict.disguise.utilities.packets.PacketsManager; | ||||
| @@ -31,10 +31,13 @@ import org.bukkit.command.CommandExecutor; | ||||
| import org.bukkit.command.PluginCommand; | ||||
| import org.bukkit.command.TabCompleter; | ||||
| import org.bukkit.configuration.file.YamlConfiguration; | ||||
| import org.bukkit.craftbukkit.libs.org.apache.commons.io.FileUtils; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.bukkit.plugin.java.JavaPlugin; | ||||
| import org.bukkit.util.FileUtil; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.util.Arrays; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| @@ -81,6 +84,8 @@ public class LibsDisguises extends JavaPlugin { | ||||
|  | ||||
|         getLogger().info("Build Date: " + pluginYml.getString("build-date")); | ||||
|  | ||||
|         DisguiseConfig.loadInternalConfig(); | ||||
|  | ||||
|         LibsPremium.check(getDescription().getVersion(), getFile()); | ||||
|  | ||||
|         if (!LibsPremium.isPremium()) { | ||||
| @@ -98,6 +103,17 @@ public class LibsDisguises extends JavaPlugin { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // If this is a release build, even if jenkins build.. | ||||
|         if (isReleaseBuild()) { | ||||
|             // If downloaded from spigot, forcibly set release build to true | ||||
|             if (LibsPremium.getUserID().matches("[0-9]+")) { | ||||
|                 DisguiseConfig.setUsingReleaseBuilds(true); | ||||
|             } | ||||
|             // Otherwise leave it untouched as they might've just happened to hit a dev build, which is a release build | ||||
|         } else { | ||||
|             DisguiseConfig.setUsingReleaseBuilds(false); | ||||
|         } | ||||
|  | ||||
|         ReflectionManager.init(); | ||||
|  | ||||
|         PacketsManager.init(); | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| package me.libraryaddict.disguise.commands.libsdisguises; | ||||
|  | ||||
| import me.libraryaddict.disguise.LibsDisguises; | ||||
| import me.libraryaddict.disguise.utilities.UpdateChecker; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||
| import me.libraryaddict.disguise.utilities.updates.UpdateChecker; | ||||
| import me.libraryaddict.disguise.utilities.plugin.PluginInformation; | ||||
| import me.libraryaddict.disguise.utilities.translations.LibsMsg; | ||||
| import org.bukkit.Bukkit; | ||||
| @@ -18,7 +19,10 @@ import java.util.List; | ||||
| public class LDUpdate implements LDCommand { | ||||
|     @Override | ||||
|     public List<String> getTabComplete() { | ||||
|         return Arrays.asList("update", "update!"); | ||||
|         // Update by download | ||||
|         // Update check | ||||
|         // Update to latest dev build | ||||
|         return Arrays.asList("update", "update?", "update!"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -35,16 +39,21 @@ public class LDUpdate implements LDCommand { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         boolean check = args[0].endsWith("?"); | ||||
|         boolean force = args[0].endsWith("!"); | ||||
|  | ||||
|         if (!force) { | ||||
|             if (checker.getLatestSnapshot() <= 0) { | ||||
|                 sender.sendMessage(LibsMsg.UPDATE_NOT_READY.get()); | ||||
|         if (!check && !force && checker.getUpdate() != null) { | ||||
|             if (checker.getUpdate().getVersion().equals(checker.getUpdate().isReleaseBuild() ? | ||||
|                     LibsDisguises.getInstance().getDescription().getDescription() : | ||||
|                     LibsDisguises.getInstance().getBuildNumber())) { | ||||
|                 sender.sendMessage(LibsMsg.UPDATE_ON_LATEST.get()); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             if (checker.getLatestSnapshot() == LibsDisguises.getInstance().getBuildNumber()) { | ||||
|                 sender.sendMessage(LibsMsg.UPDATE_ON_LATEST.get()); | ||||
|             if (checker.getLastDownload() != null && checker.getUpdate().getVersion() | ||||
|                     .equals(checker.isUsingReleaseBuilds() ? checker.getLastDownload().getVersion() : | ||||
|                             checker.getLastDownload().getBuildNumber())) { | ||||
|                 sender.sendMessage(LibsMsg.UPDATE_ALREADY_DOWNLOADED.get()); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
| @@ -52,29 +61,49 @@ public class LDUpdate implements LDCommand { | ||||
|         new BukkitRunnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 PluginInformation result; | ||||
|                 LibsMsg updateResult = null; | ||||
|  | ||||
|                 if (force) { | ||||
|                     result = checker.grabLatestSnapshot(); | ||||
|                 } else { | ||||
|                     result = checker.grabSnapshotBuild(); | ||||
|                 if (check || checker.getUpdate() == null || force) { | ||||
|                     updateResult = checker.doUpdateCheck(); | ||||
|                 } | ||||
|  | ||||
|                 if (checker.getUpdate() == null) { | ||||
|                     sender.sendMessage(LibsMsg.UPDATE_FAILED.get()); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (!checker.isUpdateReady()) { | ||||
|                     sender.sendMessage(LibsMsg.UPDATE_ON_LATEST.get()); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (check) { | ||||
|                     if (updateResult != null) { | ||||
|                         sender.sendMessage(updateResult.get()); | ||||
|                     } else { | ||||
|                         for (String msg : checker.getUpdateMessage()) { | ||||
|                             sender.sendMessage(msg); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 PluginInformation result = checker.doUpdate(); | ||||
|  | ||||
|                 if (result == null) { | ||||
|                     sender.sendMessage(LibsMsg.UPDATE_FAILED.get()); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 sender.sendMessage(LibsMsg.UPDATE_SUCCESS.get()); // Update success, please restart to update | ||||
|                 sender.sendMessage(LibsMsg.UPDATE_INFO | ||||
|                         .get(result.getVersion(), result.getBuildNumber(), result.getParsedBuildDate().toString(), | ||||
|                                 result.getSize() / 1024)); | ||||
|                 for (String msg : checker.getUpdateMessage()) { | ||||
|                     sender.sendMessage(msg); | ||||
|                 } | ||||
|  | ||||
|                 if (sender instanceof Player) { | ||||
|                     Bukkit.getConsoleSender().sendMessage(LibsMsg.UPDATE_SUCCESS.get()); | ||||
|                     Bukkit.getConsoleSender().sendMessage(LibsMsg.UPDATE_INFO | ||||
|                             .get(result.getVersion(), result.getBuildNumber(), result.getParsedBuildDate().toString(), | ||||
|                                     result.getSize() / 1024)); | ||||
|                     for (String msg : checker.getUpdateMessage()) { | ||||
|                         DisguiseUtilities.getLogger().info(msg); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }.runTaskAsynchronously(LibsDisguises.getInstance()); | ||||
|   | ||||
| @@ -1,286 +0,0 @@ | ||||
| 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<String, Object> 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<String, Object> 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<String, Object> 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; | ||||
|     } | ||||
| } | ||||
| @@ -14,7 +14,7 @@ import me.libraryaddict.disguise.disguisetypes.TargetedDisguise; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||
| import me.libraryaddict.disguise.utilities.LibsEntityInteract; | ||||
| import me.libraryaddict.disguise.utilities.LibsPremium; | ||||
| import me.libraryaddict.disguise.utilities.UpdateChecker; | ||||
| import me.libraryaddict.disguise.utilities.updates.UpdateChecker; | ||||
| import me.libraryaddict.disguise.utilities.modded.ModdedEntity; | ||||
| import me.libraryaddict.disguise.utilities.modded.ModdedManager; | ||||
| import me.libraryaddict.disguise.utilities.plugin.PluginInformation; | ||||
| @@ -53,13 +53,9 @@ import java.util.Set; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | ||||
| public class DisguiseListener implements Listener { | ||||
|     private String currentVersion; | ||||
|     private HashMap<String, LibsEntityInteract> interactions = new HashMap<>(); | ||||
|     private HashMap<String, BukkitRunnable> disguiseRunnable = new HashMap<>(); | ||||
|     private String latestVersion; | ||||
|     private LibsMsg updateMessage; | ||||
|     private LibsDisguises plugin; | ||||
|     private BukkitTask updaterTask; | ||||
|  | ||||
|     public DisguiseListener(LibsDisguises libsDisguises) { | ||||
|         plugin = libsDisguises; | ||||
| @@ -117,87 +113,6 @@ public class DisguiseListener implements Listener { | ||||
|             DisguiseUtilities.getLogger() | ||||
|                     .info("Plugin will attempt to auto update when new builds are ready! Check config to disable."); | ||||
|         } | ||||
|  | ||||
|         updaterTask = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 try { | ||||
|                     UpdateChecker updateChecker = LibsDisguises.getInstance().getUpdateChecker(); | ||||
|                     boolean checkReleases = isCheckReleases(); | ||||
|  | ||||
|                     if (checkReleases) { | ||||
|                         currentVersion = plugin.getDescription().getVersion(); | ||||
|                         updateChecker.checkOfficialUpdate(currentVersion); | ||||
|                         String version = updateChecker.getLatestVersion(); | ||||
|  | ||||
|                         if (version == null) { | ||||
|                             return; | ||||
|                         } | ||||
|  | ||||
|                         latestVersion = version; | ||||
|                         updateMessage = LibsMsg.UPDATE_READY; | ||||
|                     } else { | ||||
|                         updateChecker.checkSnapshotUpdate(plugin.getBuildNumber()); | ||||
|  | ||||
|                         if (updateChecker.getLatestSnapshot() <= 0) { | ||||
|                             return; | ||||
|                         } | ||||
|  | ||||
|                         latestVersion = "" + updateChecker.getLatestSnapshot(); | ||||
|  | ||||
|                         if (autoUpdate && plugin.isNumberedBuild()) { | ||||
|                             PluginInformation result = updateChecker.grabSnapshotBuild(); | ||||
|                             updateMessage = result != null ? LibsMsg.UPDATE_SUCCESS : LibsMsg.UPDATE_FAILED; | ||||
|                             Bukkit.getConsoleSender().sendMessage(LibsMsg.UPDATE_INFO | ||||
|                                     .get(result.getVersion(), result.getBuildNumber(), | ||||
|                                             result.getParsedBuildDate().toString(), result.getSize() / 1024)); | ||||
|                         } else { | ||||
|                             currentVersion = plugin.getBuildNo(); | ||||
|                             updateMessage = LibsMsg.UPDATE_READY_SNAPSHOT; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     Bukkit.getScheduler().runTask(plugin, new Runnable() { | ||||
|                         @Override | ||||
|                         public void run() { | ||||
|                             notifyUpdate(Bukkit.getConsoleSender()); | ||||
|  | ||||
|                             for (Player p : Bukkit.getOnlinePlayers()) { | ||||
|                                 notifyUpdate(p); | ||||
|                             } | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|                 catch (Exception ex) { | ||||
|                     DisguiseUtilities.getLogger() | ||||
|                             .warning(String.format("Failed to check for update: %s", ex.getMessage())); | ||||
|                 } | ||||
|             } | ||||
|         }, 0, (20 * TimeUnit.HOURS.toSeconds(6))); // Check every 6 hours | ||||
|     } | ||||
|  | ||||
|     private void notifyUpdate(CommandSender player) { | ||||
|         if (!player.hasPermission(DisguiseConfig.getUpdateNotificationPermission())) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (latestVersion == null) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (updateMessage == LibsMsg.UPDATE_SUCCESS || updateMessage == LibsMsg.UPDATE_FAILED) { | ||||
|             if (player instanceof Player) { | ||||
|                 player.sendMessage(updateMessage.get()); | ||||
|             } else { | ||||
|                 DisguiseUtilities.getLogger().info(updateMessage.get()); | ||||
|             } | ||||
|         } else { | ||||
|             if (player instanceof Player) { | ||||
|                 player.sendMessage(updateMessage.get(currentVersion, latestVersion)); | ||||
|             } else { | ||||
|                 DisguiseUtilities.getLogger().info(updateMessage.get(currentVersion, latestVersion)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void cleanup() { | ||||
| @@ -206,7 +121,6 @@ public class DisguiseListener implements Listener { | ||||
|         } | ||||
|  | ||||
|         interactions.clear(); | ||||
|         updaterTask.cancel(); | ||||
|     } | ||||
|  | ||||
|     private void checkPlayerCanBlowDisguise(Player player) { | ||||
| @@ -423,7 +337,7 @@ public class DisguiseListener implements Listener { | ||||
|     public void onJoin(PlayerJoinEvent event) { | ||||
|         Player p = event.getPlayer(); | ||||
|  | ||||
|         notifyUpdate(p); | ||||
|         plugin.getUpdateChecker().notifyUpdate(p); | ||||
|  | ||||
|         if (DisguiseConfig.isSaveGameProfiles() && DisguiseConfig.isUpdateGameProfiles() && | ||||
|                 DisguiseUtilities.hasGameProfile(p.getName())) { | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package me.libraryaddict.disguise.utilities.plugin; | ||||
|  | ||||
| import me.libraryaddict.disguise.DisguiseConfig; | ||||
| import me.libraryaddict.disguise.LibsDisguises; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.configuration.file.YamlConfiguration; | ||||
| @@ -13,24 +14,15 @@ import java.net.URL; | ||||
|  */ | ||||
| public class BisectHosting { | ||||
|     public boolean isBisectHosted(String pluginName) { | ||||
|         File configFile = new File("plugins/" + pluginName + "/internal.yml"); | ||||
|         boolean claimedHosted = false; | ||||
|         String serverIp = Bukkit.getIp().replaceAll("[^:0-9.]", ""); | ||||
|         boolean claimedHosted = DisguiseConfig.isBisectHosted(); | ||||
|         String ip = Bukkit.getIp(); | ||||
|         String parsedIP = ip.replaceAll("[^:0-9.]", ""); | ||||
|  | ||||
|         if (configFile.exists()) { | ||||
|             YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile); | ||||
|  | ||||
|             if (configuration.contains("Bisect-Hosted") && configuration.contains("Server-IP")) { | ||||
|                 claimedHosted = configuration.getBoolean("Bisect-Hosted"); | ||||
|  | ||||
|                 // If not hosted by bisect | ||||
|                 if (!claimedHosted && configuration.getString("Server-IP").equals(serverIp)) { | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|         // If not hosted by bisect | ||||
|         if (!claimedHosted && DisguiseConfig.getSavedServerIp().equals(parsedIP)) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         String ip = Bukkit.getIp(); | ||||
|         boolean hostedBy = false; | ||||
|  | ||||
|         if (ip.matches("((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\\.(?!$)|$)){4}")) { | ||||
| @@ -45,27 +37,11 @@ public class BisectHosting { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // If config doesn't exist, or it's not a bisect server | ||||
|         if (!configFile.exists()) { | ||||
|             if (!configFile.getParentFile().exists()) { | ||||
|                 configFile.getParentFile().mkdirs(); | ||||
|             } | ||||
|         if (claimedHosted != hostedBy || !DisguiseConfig.getSavedServerIp().equals(parsedIP)) { | ||||
|             DisguiseConfig.setBisectHosted(hostedBy, Bukkit.getIp()); | ||||
|         } | ||||
|  | ||||
|             try (PrintWriter writer = new PrintWriter(configFile, "UTF-8")) { | ||||
|                 // This setting is if the server should check if you are using Bisect Hosting", | ||||
|                 writer.write("# If you're using BisectHosting, this will tell the server to enable premium for free!"); | ||||
|                 writer.write("\n# However if you're not using BisectHosting, this is false so the server won't waste " + | ||||
|                         "time"); | ||||
|                 writer.write( | ||||
|                         "\n# Coupon 'libraryaddict' for 25% off your first invoice on any of their gaming servers"); | ||||
|                 writer.write("\n# Be sure to visit through this link! https://bisecthosting.com/libraryaddict"); | ||||
|                 writer.write("\nBisect-Hosted: " + hostedBy); | ||||
|                 writer.write("\nServer-IP: " + serverIp); | ||||
|             } | ||||
|             catch (FileNotFoundException | UnsupportedEncodingException e) { | ||||
|                 e.printStackTrace(); | ||||
|             } | ||||
|         } else if (claimedHosted) { | ||||
|         if (!hostedBy && !DisguiseConfig.getSavedServerIp().equals("")) { | ||||
|             // Just a small message for those who tried to enable it | ||||
|             LibsDisguises.getInstance().getLogger().severe("Check for BisectHosting failed! Connection error?"); | ||||
|         } | ||||
|   | ||||
| @@ -16,6 +16,7 @@ import me.libraryaddict.disguise.utilities.LibsPremium; | ||||
| import org.apache.commons.lang.ArrayUtils; | ||||
| import org.apache.commons.lang.StringUtils; | ||||
| import org.bukkit.*; | ||||
| import org.bukkit.configuration.InvalidConfigurationException; | ||||
| import org.bukkit.configuration.file.YamlConfiguration; | ||||
| import org.bukkit.entity.*; | ||||
| import org.bukkit.inventory.EquipmentSlot; | ||||
| @@ -158,21 +159,13 @@ public class ReflectionManager { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Copied from Bukkit | ||||
|      */ | ||||
|     public static YamlConfiguration getPluginYAML(File file) { | ||||
|     public static String getResourceAsString(File file, String fileName) { | ||||
|         try (JarFile jar = new JarFile(file)) { | ||||
|             JarEntry entry = jar.getJarEntry("plugin.yml"); | ||||
|             JarEntry entry = jar.getJarEntry(fileName); | ||||
|  | ||||
|             try (InputStream stream = jar.getInputStream(entry)) { | ||||
|                 YamlConfiguration config = new YamlConfiguration(); | ||||
|  | ||||
|                 String configString = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)).lines() | ||||
|                 return new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)).lines() | ||||
|                         .collect(Collectors.joining("\n")); | ||||
|                 config.loadFromString(configString); | ||||
|  | ||||
|                 return config; | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) { | ||||
| @@ -182,6 +175,30 @@ public class ReflectionManager { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Copied from Bukkit | ||||
|      */ | ||||
|     public static YamlConfiguration getPluginYAML(File file) { | ||||
|         try { | ||||
|             String s = getResourceAsString(file, "plugin.yml"); | ||||
|  | ||||
|             if (s == null) { | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|             YamlConfiguration config = new YamlConfiguration(); | ||||
|  | ||||
|             config.loadFromString(getResourceAsString(file, "plugin.yml")); | ||||
|  | ||||
|             return config; | ||||
|         } | ||||
|         catch (InvalidConfigurationException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public static int getNewEntityId() { | ||||
|         return getNewEntityId(true); | ||||
|     } | ||||
|   | ||||
| @@ -143,9 +143,8 @@ public enum LibsMsg { | ||||
|     NO_MODS(ChatColor.RED + "%s is not using any mods!"), | ||||
|     MODS_LIST(ChatColor.DARK_GREEN + "%s has the mods:" + ChatColor.AQUA + " %s"), | ||||
|     NO_PERM(ChatColor.RED + "You are forbidden to use this command."), | ||||
|     UPDATE_NOT_READY(ChatColor.RED + | ||||
|             "Lib's Disguises doesn't know what's the latest update! Use 'update!' to force an update to latest!"), | ||||
|     UPDATE_ON_LATEST(ChatColor.RED + "You are already on the latest version of LibsDisguises!"), | ||||
|     UPDATE_ALREADY_DOWNLOADED(ChatColor.RED + "That update has already been downloaded!"), | ||||
|     UPDATE_FAILED(ChatColor.RED + "LibsDisguises update failed! Check console for errors."), | ||||
|     UPDATE_SUCCESS(ChatColor.DARK_GREEN + "LibsDisguises update success! Restart server to update!"), | ||||
|     UPDATE_INFO(ChatColor.DARK_GREEN + "Lib's Disguises v%s, build %s, built %s and size %skb"), | ||||
|   | ||||
| @@ -0,0 +1,24 @@ | ||||
| package me.libraryaddict.disguise.utilities.updates; | ||||
|  | ||||
| import java.util.Date; | ||||
|  | ||||
| /** | ||||
|  * Created by libraryaddict on 26/04/2020. | ||||
|  */ | ||||
| public interface DisguiseUpdate { | ||||
|     /** | ||||
|      * Null if invalid | ||||
|      */ | ||||
|     String getVersion(); | ||||
|  | ||||
|     boolean isReleaseBuild(); | ||||
|  | ||||
|     String getDownload(); | ||||
|  | ||||
|     String[] getChangelog(); | ||||
|  | ||||
|     /** | ||||
|      * When was this update fetched? | ||||
|      */ | ||||
|     Date getFetched(); | ||||
| } | ||||
| @@ -0,0 +1,95 @@ | ||||
| package me.libraryaddict.disguise.utilities.updates; | ||||
|  | ||||
| import com.google.gson.Gson; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Getter; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||
|  | ||||
| import java.io.BufferedReader; | ||||
| 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.stream.Collectors; | ||||
|  | ||||
| /** | ||||
|  * Created by libraryaddict on 26/04/2020. | ||||
|  */ | ||||
| public class LDGithub { | ||||
|     @Getter | ||||
|     @AllArgsConstructor | ||||
|     private class GithubUpdate implements DisguiseUpdate { | ||||
|         private String version; | ||||
|         private String[] changelog; | ||||
|         private String download; | ||||
|         private final Date fetched = new Date(); | ||||
|  | ||||
|         @Override | ||||
|         public boolean isReleaseBuild() { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Getter | ||||
|     private class GithubData { | ||||
|         @Getter | ||||
|         class Asset { | ||||
|             String browser_download_url; | ||||
|             String name; | ||||
|             String content_type; | ||||
|         } | ||||
|  | ||||
|         String name; | ||||
|         String tag_name; | ||||
|         String body; | ||||
|         Date published_at; | ||||
|         Asset[] assets; | ||||
|     } | ||||
|  | ||||
|     public DisguiseUpdate getLatestRelease() { | ||||
|         try { | ||||
|             // We're connecting to md_5's jenkins REST api | ||||
|             URL url = new URL("https://api.github.com/repos/libraryaddict/LibsDisguises/releases/latest"); | ||||
|             // Creating a connection | ||||
|             HttpURLConnection con = (HttpURLConnection) url.openConnection(); | ||||
|             con.setRequestProperty("User-Agent", "libraryaddict/LibsDisguises"); | ||||
|             con.setRequestProperty("Accept", "application/vnd.github.v3+json"); | ||||
|  | ||||
|             GithubData gitData; | ||||
|  | ||||
|             // 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")); | ||||
|  | ||||
|                 gitData = new Gson().fromJson(json, GithubData.class); | ||||
|             } | ||||
|  | ||||
|             String download = null; | ||||
|  | ||||
|             for (GithubData.Asset asset : gitData.getAssets()) { | ||||
|                 if (!asset.getName().endsWith(".jar")) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 download = asset.getBrowser_download_url(); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             if (download == null) { | ||||
|                 throw new IllegalStateException("Download url is missing"); | ||||
|             } | ||||
|  | ||||
|             return new GithubUpdate(gitData.getTag_name().replace("v", ""), gitData.getBody().split("(\\r|\\n)+"), download); | ||||
|         } | ||||
|         catch (Exception ex) { | ||||
|             DisguiseUtilities.getLogger().warning("Failed to check for a release on Github"); | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,104 @@ | ||||
| package me.libraryaddict.disguise.utilities.updates; | ||||
|  | ||||
| import com.google.gson.Gson; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Getter; | ||||
| import me.libraryaddict.disguise.LibsDisguises; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||
| import me.libraryaddict.disguise.utilities.plugin.PluginInformation; | ||||
|  | ||||
| import java.io.BufferedReader; | ||||
| import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.net.HttpURLConnection; | ||||
| import java.net.URL; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Date; | ||||
| import java.util.Map; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| /** | ||||
|  * Created by libraryaddict on 26/04/2020. | ||||
|  */ | ||||
| public class LDJenkins { | ||||
|     private UpdateChecker updateChecker; | ||||
|  | ||||
|     @AllArgsConstructor | ||||
|     @Getter | ||||
|     private class JenkinsUpdate implements DisguiseUpdate { | ||||
|         private final Date fetched = new Date(); | ||||
|         private final String version; | ||||
|         private final String[] changelog; | ||||
|  | ||||
|         @Override | ||||
|         public String getDownload() { | ||||
|             return "https://ci.md-5.net/job/LibsDisguises/" + getVersion() + "/artifact/target/LibsDisguises.jar"; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public boolean isReleaseBuild() { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Fetches from jenkins, using the REST api the last snapshot build information | ||||
|      */ | ||||
|     private Map<String, Object> 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<String, Object> 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."); | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public DisguiseUpdate getLatestSnapshot() { | ||||
|         Map<String, Object> lastBuild = fetchLastSnapshotBuild(); | ||||
|  | ||||
|         if (lastBuild == null || !lastBuild.containsKey("id") || !lastBuild.containsKey("timestamp")) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         ArrayList<String> changelog = new ArrayList<>(); | ||||
|  | ||||
|         if (lastBuild.get("changeSet") instanceof Map) { | ||||
|             Object items = ((Map) lastBuild.get("changeSet")).get("items"); | ||||
|  | ||||
|             if (items instanceof Map[]) { | ||||
|                 for (Map item : (Map[]) items) { | ||||
|                     String msg = (String) item.get("msg"); | ||||
|  | ||||
|                     if (msg == null) { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     changelog.add(msg); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return new JenkinsUpdate((String) lastBuild.get("id"), changelog.toArray(new String[0])); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,290 @@ | ||||
| package me.libraryaddict.disguise.utilities.updates; | ||||
|  | ||||
| import lombok.Getter; | ||||
| import me.libraryaddict.disguise.DisguiseConfig; | ||||
| import me.libraryaddict.disguise.LibsDisguises; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||
| import me.libraryaddict.disguise.utilities.LibsPremium; | ||||
| import me.libraryaddict.disguise.utilities.plugin.PluginInformation; | ||||
| import me.libraryaddict.disguise.utilities.translations.LibsMsg; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.craftbukkit.libs.org.apache.commons.io.FileUtils; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.bukkit.scheduler.BukkitTask; | ||||
|  | ||||
| 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.concurrent.TimeUnit; | ||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| public class UpdateChecker { | ||||
|     private final String resourceID; | ||||
|     private final long started = System.currentTimeMillis(); | ||||
|     @Getter | ||||
|     private PluginInformation lastDownload; | ||||
|     private final AtomicBoolean downloading = new AtomicBoolean(false); | ||||
|     @Getter | ||||
|     private DisguiseUpdate update; | ||||
|     private LDGithub githubUpdater = new LDGithub(); | ||||
|     private LDJenkins jenkinsUpdater = new LDJenkins(); | ||||
|     @Getter | ||||
|     private String[] updateMessage = new String[0]; | ||||
|  | ||||
|     public UpdateChecker(String resourceID) { | ||||
|         this.resourceID = resourceID; | ||||
|     } | ||||
|  | ||||
|     public boolean isDownloading() { | ||||
|         return downloading.get(); | ||||
|     } | ||||
|  | ||||
|     public boolean isUsingReleaseBuilds() { | ||||
|         DisguiseConfig.UpdatesBranch builds = DisguiseConfig.getUpdatesBranch(); | ||||
|  | ||||
|         return builds == DisguiseConfig.UpdatesBranch.RELEASES || | ||||
|                 (builds == DisguiseConfig.UpdatesBranch.SAME_BUILDS && DisguiseConfig.isUsingReleaseBuild()); | ||||
|     } | ||||
|  | ||||
|     public void notifyUpdate(CommandSender player) { | ||||
|         if (!DisguiseConfig.isNotifyUpdate() || !player.hasPermission("libsdisguises.update")) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (updateMessage == null || updateMessage.length == 0) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (player instanceof Player) { | ||||
|             player.sendMessage(updateMessage); | ||||
|         } else { | ||||
|             for (String s : updateMessage) { | ||||
|                 DisguiseUtilities.getLogger().info(s); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public boolean isUpdateReady() { | ||||
|         if (getUpdate() == null) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         String version; | ||||
|  | ||||
|         if (getUpdate().isReleaseBuild()) { | ||||
|             if (lastDownload != null) { | ||||
|                 version = lastDownload.getVersion(); | ||||
|             } else { | ||||
|                 version = LibsDisguises.getInstance().getDescription().getVersion(); | ||||
|             } | ||||
|         } else { | ||||
|             if (lastDownload != null) { | ||||
|                 version = lastDownload.getBuildNumber(); | ||||
|             } else { | ||||
|                 version = LibsDisguises.getInstance().getBuildNo(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return getUpdate() != null && !getUpdate().getVersion().equals(version); | ||||
|     } | ||||
|  | ||||
|     public void doAutoUpdateCheck() { | ||||
|         try { | ||||
|             DisguiseUpdate oldUpdate = getUpdate(); | ||||
|  | ||||
|             updateMessage = new String[0]; | ||||
|  | ||||
|             doUpdateCheck(); | ||||
|  | ||||
|             if (!isUpdateReady() || (oldUpdate != null && oldUpdate.getVersion().equals(getUpdate().getVersion()))) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             notifyUpdate(Bukkit.getConsoleSender()); | ||||
|  | ||||
|             if (DisguiseConfig.isAutoUpdate()) { | ||||
|                 // Update message changed by download | ||||
|                 grabJarDownload(getUpdate().getDownload()); | ||||
|  | ||||
|                 notifyUpdate(Bukkit.getConsoleSender()); | ||||
|             } | ||||
|  | ||||
|             Bukkit.getScheduler().runTask(LibsDisguises.getInstance(), () -> { | ||||
|                 for (Player p : Bukkit.getOnlinePlayers()) { | ||||
|                     notifyUpdate(p); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|         catch (Exception ex) { | ||||
|             DisguiseUtilities.getLogger().warning(String.format("Failed to check for update: %s", ex.getMessage())); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public PluginInformation doUpdate() { | ||||
|         // If no update on file, or more than 6 hours hold. Check for update | ||||
|         if (getUpdate() == null || | ||||
|                 getUpdate().getFetched().before(new Date(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(6)))) { | ||||
|             doUpdateCheck(); | ||||
|         } | ||||
|  | ||||
|         if (getUpdate() == null) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return grabJarDownload(getUpdate().getDownload()); | ||||
|     } | ||||
|  | ||||
|     public LibsMsg doUpdateCheck() { | ||||
|         downloading.set(false); | ||||
|  | ||||
|         try { | ||||
|             update = null; | ||||
|  | ||||
|             if (isUsingReleaseBuilds()) { | ||||
|                 update = githubUpdater.getLatestRelease(); | ||||
|             } else { | ||||
|                 update = jenkinsUpdater.getLatestSnapshot(); | ||||
|             } | ||||
|         } | ||||
|         finally { | ||||
|             downloading.set(false); | ||||
|         } | ||||
|  | ||||
|         if (getUpdate() == null) { | ||||
|             return LibsMsg.UPDATE_FAILED; | ||||
|         } | ||||
|  | ||||
|         if (getUpdate().isReleaseBuild()) { | ||||
|             String currentVersion = LibsDisguises.getInstance().getDescription().getVersion(); | ||||
|  | ||||
|             if (!isNewerVersion(currentVersion, getUpdate().getVersion())) { | ||||
|                 return LibsMsg.UPDATE_ON_LATEST; | ||||
|             } | ||||
|  | ||||
|             updateMessage = new String[]{LibsMsg.UPDATE_READY.get(currentVersion, getUpdate().getVersion())}; | ||||
|         } else { | ||||
|             if (!getUpdate().getVersion().matches("[0-9]+")) { | ||||
|                 return LibsMsg.UPDATE_FAILED; | ||||
|             } | ||||
|  | ||||
|             int newBuild = Integer.parseInt(getUpdate().getVersion()); | ||||
|  | ||||
|             if (newBuild <= LibsDisguises.getInstance().getBuildNumber()) { | ||||
|                 return LibsMsg.UPDATE_ON_LATEST; | ||||
|             } | ||||
|  | ||||
|             updateMessage = new String[]{ | ||||
|                     LibsMsg.UPDATE_READY_SNAPSHOT.get(LibsDisguises.getInstance().getBuildNo(), newBuild)}; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private PluginInformation grabJarDownload(String urlString) { | ||||
|         downloading.set(true); | ||||
|  | ||||
|         DisguiseUtilities.getLogger().info("Now downloading build of Lib's Disguises from " + urlString); | ||||
|  | ||||
|         File dest = new File(Bukkit.getUpdateFolderFile(), LibsDisguises.getInstance().getFile().getName()); | ||||
|  | ||||
|         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!"); | ||||
|  | ||||
|             PluginInformation result = LibsPremium.getInformation(dest); | ||||
|             lastDownload = result; | ||||
|  | ||||
|             updateMessage = new String[]{LibsMsg.UPDATE_SUCCESS.get(), | ||||
|                     LibsMsg.UPDATE_INFO.get(result.getVersion(), result.getBuildNumber(), | ||||
|                             result.getParsedBuildDate().toString(), result.getSize() / 1024)}; | ||||
|  | ||||
|             return result; | ||||
|         } | ||||
|         catch (Exception ex) { | ||||
|             // Failed, set the last download back to previous build | ||||
|             dest.delete(); | ||||
|             DisguiseUtilities.getLogger().warning("Failed to download snapshot build."); | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|         finally { | ||||
|             downloading.set(false); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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); | ||||
|     } | ||||
| } | ||||
| @@ -99,19 +99,16 @@ Scoreboard: | ||||
|   WarnConflict: true | ||||
|  | ||||
| # Shall I notify those with the correct permission when there's a LibsDisguises update? | ||||
| # Disabling this will also disable auto updating | ||||
| # Disabling this will also disable notifications when the plugin updated | ||||
| NotifyUpdate: true | ||||
|  | ||||
| # Whats the permission to get the notification? | ||||
| Permission: 'libsdisguises.update' | ||||
| # Should the plugin automatically update? | ||||
| AutoUpdate: true | ||||
|  | ||||
| # Where should the plugin check for updates? | ||||
| # SAME_BUILDS - Will check snapshots if you're not using a release build | ||||
| # RELEASES - Only check for actual releases | ||||
| # SNAPSHOTS - Only check for new snapshots | ||||
| UpdatesBranch: SAME_BUILDS | ||||
| # Should the plugin automatically update if the server is using dev builds? | ||||
| AutoUpdateDev: true | ||||
|  | ||||
| # Whats the max size allowed for command disguiseradius | ||||
| DisguiseRadiusMax: 50 | ||||
|   | ||||
							
								
								
									
										8
									
								
								src/main/resources/internal.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/main/resources/internal.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| # If you're using BisectHosting, this will tell the server to enable premium for free! | ||||
| # However if you're not using BisectHosting, this is false so the server won't waste time | ||||
| # Coupon 'libraryaddict' for 25% off your first invoice on any of their gaming server | ||||
| # Be sure to visit through this link! https://bisecthosting.com/libraryaddict | ||||
| Bisect-Hosted: %data% | ||||
| Server-IP: %data% | ||||
| # Should the plugin be doing release or dev builds updating? | ||||
| ReleaseBuild: %data% | ||||
		Reference in New Issue
	
	Block a user