From 1fab21601edebc2e27a16338971d7a12cca58fe6 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 26 Jun 2024 12:29:22 +0200 Subject: [PATCH] new updater --- pom.xml | 5 + .../m724/realweather/RealWeatherPlugin.java | 18 +- .../realweather/commands/AdminCommand.java | 4 +- .../realweather/commands/UpdateCommand.java | 32 ++- .../updater/PluginEnvironment.java | 18 ++ .../realweather/updater/PluginUpdater.java | 37 ++++ .../updater/SignatureValidator.java | 40 ---- .../realweather/updater/UpdateDownloader.java | 109 ---------- .../realweather/updater/UpdateNotifier.java | 68 ++++++ .../eu/m724/realweather/updater/Updater.java | 198 ------------------ .../updater/metadata/MetadataRetriever.java | 110 ---------- .../metadata/MetadataServerException.java | 16 -- .../updater/metadata/VersionMetadata.java | 38 ---- 13 files changed, 156 insertions(+), 537 deletions(-) create mode 100644 src/main/java/eu/m724/realweather/updater/PluginEnvironment.java create mode 100644 src/main/java/eu/m724/realweather/updater/PluginUpdater.java delete mode 100644 src/main/java/eu/m724/realweather/updater/SignatureValidator.java delete mode 100644 src/main/java/eu/m724/realweather/updater/UpdateDownloader.java create mode 100644 src/main/java/eu/m724/realweather/updater/UpdateNotifier.java delete mode 100644 src/main/java/eu/m724/realweather/updater/Updater.java delete mode 100644 src/main/java/eu/m724/realweather/updater/metadata/MetadataRetriever.java delete mode 100644 src/main/java/eu/m724/realweather/updater/metadata/MetadataServerException.java delete mode 100644 src/main/java/eu/m724/realweather/updater/metadata/VersionMetadata.java diff --git a/pom.xml b/pom.xml index ef9dfb9..e433eab 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,11 @@ wtapi 0.7 + + eu.m724 + jarupdater + 0.1.0 + diff --git a/src/main/java/eu/m724/realweather/RealWeatherPlugin.java b/src/main/java/eu/m724/realweather/RealWeatherPlugin.java index 7d628da..d5f8ba4 100644 --- a/src/main/java/eu/m724/realweather/RealWeatherPlugin.java +++ b/src/main/java/eu/m724/realweather/RealWeatherPlugin.java @@ -21,8 +21,7 @@ import eu.m724.realweather.thunder.ThunderConfig; import eu.m724.realweather.thunder.ThunderMaster; import eu.m724.realweather.time.TimeConfig; import eu.m724.realweather.time.TimeMaster; -import eu.m724.realweather.updater.SignatureValidator; -import eu.m724.realweather.updater.Updater; +import eu.m724.realweather.updater.PluginUpdater; import eu.m724.realweather.updater.UpdaterConfig; import eu.m724.realweather.weather.PlayerWeatherDirectory; import eu.m724.realweather.weather.WeatherConfig; @@ -34,7 +33,7 @@ public class RealWeatherPlugin extends JavaPlugin { private WeatherMaster weatherMaster; private ThunderMaster thunderMaster; private TimeMaster timeMaster; - private Updater updater; + private PluginUpdater updater; private Logger logger; @@ -42,17 +41,6 @@ public class RealWeatherPlugin extends JavaPlugin { public void onEnable() { logger = getLogger(); - // TODO remove these lines - SignatureValidator signatureValidator = new SignatureValidator(this); - logger.info("Signature of this JAR: " + signatureValidator.getCertificate().getSubjectX500Principal().getName()); - - if (!signatureValidator.isValid()) { - logger.severe("Key is not valid"); - getServer().getPluginManager().disablePlugin(this); - return; - } - // TODO remove those lines - File dataFolder = getDataFolder(); File modulesFolder = new File("modules"); modulesFolder.mkdir(); @@ -119,7 +107,7 @@ public class RealWeatherPlugin extends JavaPlugin { timeMaster.init(); GlobalConstants.updaterConfig = UpdaterConfig.fromConfiguration(configuration.getConfigurationSection("updater")); - updater = new Updater(GlobalConstants.updaterConfig); + updater = PluginUpdater.build(this, GlobalConstants.updaterConfig); updater.init(); } catch (UserError | NoSuchProviderException e) { logger.severe("There are errors in your config:"); diff --git a/src/main/java/eu/m724/realweather/commands/AdminCommand.java b/src/main/java/eu/m724/realweather/commands/AdminCommand.java index 1904cfe..a945dea 100644 --- a/src/main/java/eu/m724/realweather/commands/AdminCommand.java +++ b/src/main/java/eu/m724/realweather/commands/AdminCommand.java @@ -12,7 +12,7 @@ import eu.m724.realweather.mapper.MapperConfig; import eu.m724.realweather.thunder.ThunderConfig; import eu.m724.realweather.thunder.ThunderMaster; import eu.m724.realweather.time.TimeConfig; -import eu.m724.realweather.updater.Updater; +import eu.m724.realweather.updater.PluginUpdater; import eu.m724.realweather.weather.WeatherConfig; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; @@ -33,7 +33,7 @@ public class AdminCommand implements CommandExecutor { private BaseComponent enabledComponent = TextComponent.fromLegacy("YES\n", ChatColor.GREEN); private BaseComponent disabledComponent = TextComponent.fromLegacy("NO\n", ChatColor.RED); - public AdminCommand(Updater updater) { + public AdminCommand(PluginUpdater updater) { this.updateCommand = new UpdateCommand(updater); } diff --git a/src/main/java/eu/m724/realweather/commands/UpdateCommand.java b/src/main/java/eu/m724/realweather/commands/UpdateCommand.java index edff101..3f3bb5c 100644 --- a/src/main/java/eu/m724/realweather/commands/UpdateCommand.java +++ b/src/main/java/eu/m724/realweather/commands/UpdateCommand.java @@ -1,12 +1,15 @@ package eu.m724.realweather.commands; +import java.nio.file.NoSuchFileException; +import java.time.Instant; +import java.time.format.DateTimeFormatter; import java.util.concurrent.CompletableFuture; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import eu.m724.realweather.updater.Updater; -import eu.m724.realweather.updater.metadata.VersionMetadata; +import eu.m724.jarupdater.Updater; +import eu.m724.jarupdater.object.Version; /** * not actually a command but deserves a separate file @@ -22,13 +25,13 @@ public class UpdateCommand { if (!sender.hasPermission("realweather.admin.update")) return false; sender.sendMessage("Please wait"); - CompletableFuture latestFuture = updater.getLatestVersion(); + CompletableFuture latestFuture = updater.getLatestVersion(); if (args.length == 0) { latestFuture.thenAccept(metadata -> { if (metadata != null) { sender.sendMessage("An update is available!"); - sender.sendMessage("RealWeather %s released %s".formatted(metadata.label, metadata.getFormattedDate())); + sender.sendMessage("RealWeather %s released %s".formatted(metadata.getLabel(), formatDate(metadata.getTimestamp()))); sender.sendMessage("To download: /rwadmin update download"); } else { sender.sendMessage("No new updates"); // TODO color @@ -40,7 +43,7 @@ public class UpdateCommand { if (action.equals("download")) { sender.sendMessage("Started download"); - updater.downloadUpdate().handle((file, ex) -> { + updater.downloadLatestVersion().handle((file, ex) -> { sender.sendMessage("Download failed. See console for details."); ex.printStackTrace(); return null; @@ -50,14 +53,25 @@ public class UpdateCommand { }); } else if (action.equals("install")) { - if (updater.installUpdate()) - sender.sendMessage("Update installed, restart server to apply."); - else sender.sendMessage("Update not installed, see console."); + try { + updater.installLatestVersion().handle((v, ex) -> { + sender.sendMessage("Install failed. See console for details."); + ex.printStackTrace(); + return null; + }).thenAccept(v -> { + sender.sendMessage("Installation completed, restart server to apply"); + }); + } catch (NoSuchFileException e) { + sender.sendMessage("Download the update first"); + } } else return false; } - return true; } + + private String formatDate(long timestamp) { // TODO move this + return DateTimeFormatter.ofPattern("dd.MM.yyyy").format(Instant.ofEpochSecond(timestamp)); + } } diff --git a/src/main/java/eu/m724/realweather/updater/PluginEnvironment.java b/src/main/java/eu/m724/realweather/updater/PluginEnvironment.java new file mode 100644 index 0000000..d072f38 --- /dev/null +++ b/src/main/java/eu/m724/realweather/updater/PluginEnvironment.java @@ -0,0 +1,18 @@ +package eu.m724.realweather.updater; + +import java.nio.file.Path; + +import org.bukkit.plugin.Plugin; + +import eu.m724.jarupdater.environment.ConstantEnvironment; +import eu.m724.realweather.GlobalConstants; + +public class PluginEnvironment extends ConstantEnvironment { + + public PluginEnvironment(Plugin plugin) { + super(plugin.getDescription().getVersion(), + GlobalConstants.getUpdaterConfig().channel, + Path.of(plugin.getClass().getProtectionDomain().getCodeSource().getLocation().getPath())); + } + +} diff --git a/src/main/java/eu/m724/realweather/updater/PluginUpdater.java b/src/main/java/eu/m724/realweather/updater/PluginUpdater.java new file mode 100644 index 0000000..180c088 --- /dev/null +++ b/src/main/java/eu/m724/realweather/updater/PluginUpdater.java @@ -0,0 +1,37 @@ +package eu.m724.realweather.updater; + +import org.bukkit.plugin.Plugin; + +import eu.m724.jarupdater.Updater; +import eu.m724.jarupdater.download.Downloader; +import eu.m724.jarupdater.download.SimpleDownloader; +import eu.m724.jarupdater.environment.Environment; +import eu.m724.jarupdater.live.GiteaMetadataDAO; +import eu.m724.jarupdater.live.MetadataDAO; +import eu.m724.jarupdater.live.MetadataFacade; + +public class PluginUpdater extends Updater { + private UpdaterConfig updaterConfig; + + PluginUpdater(Environment environment, MetadataFacade metadataProvider, Downloader downloader, UpdaterConfig updaterConfig) { + super(environment, metadataProvider, downloader); + this.updaterConfig = updaterConfig; + } + + + public static PluginUpdater build(Plugin plugin, UpdaterConfig updaterConfig) { + Environment environment = new PluginEnvironment(plugin); + MetadataDAO metadataDAO = new GiteaMetadataDAO("https://git.m724.eu/Minecon724/realweather", "master"); + MetadataFacade metadataFacade = new MetadataFacade(environment, metadataDAO); + Downloader downloader = new SimpleDownloader("realweather"); + + return new PluginUpdater(environment, metadataFacade, downloader, updaterConfig); + } + + public void init() { + if (!updaterConfig.notify) return; + + UpdateNotifier updateNotifier = new UpdateNotifier(this, (version) -> {}); + updateNotifier.register(); + } +} diff --git a/src/main/java/eu/m724/realweather/updater/SignatureValidator.java b/src/main/java/eu/m724/realweather/updater/SignatureValidator.java deleted file mode 100644 index 39d03ae..0000000 --- a/src/main/java/eu/m724/realweather/updater/SignatureValidator.java +++ /dev/null @@ -1,40 +0,0 @@ -package eu.m724.realweather.updater; - -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.cert.X509Certificate; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.X509EncodedKeySpec; -import java.util.Base64; - -import eu.m724.realweather.RealWeatherPlugin; - -// TODO rework this for updater -public class SignatureValidator { - public RealWeatherPlugin plugin; - public static final String encodedPublicKey = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAptv/9qIJXrs/4T1MOkY1QPU/TuLsyCsJdoA2PIO1qdS3nRJBPgkRf2sK6nG1VhOaUHLXoj8lZtQQLcY76CNLqFGFmimo7RDnJjHpxHUzI9pKZJOQ9sEVCDFtoLQiit23t6MAO7GBjJXMNFLonxyay6pTABJo3VYyjg2bE4kd1wjg73RPMQY+zykaRQBUE167PAVkmuYxJK680EYmZph9kQTS12autU2qGFTvsPbmmdhtF7Xy8u84CtEucgRT9HSh0y8MuC0esMGhZtB9gsWcGET763DHtArEMekBnjByb3k+gGiG0Y1K9ygBn+nNVKP66KJGCWFuno8xy+LNiZKX4pUnrJcTyLvZg7PvjdZTye54PKkAAOACAbcFBiat38Zes5ZOKZIBEjC2IXbhfySoOn5WAk+XPsm3gVlgO9d51iOVDDBx5MCqq802lOyIGog1BlbhnGZ2+cSvFo7ZWpF0f93uG5UKBqRF+Q9cPA36SMUAoQ2DWFEZOYXwFgCXxVvFAgMBAAE="; - - public SignatureValidator(RealWeatherPlugin plugin) { - this.plugin = plugin; - } - - public X509Certificate getCertificate() { - return (X509Certificate) plugin.getClass().getProtectionDomain().getCodeSource().getCertificates()[0]; - } - - public boolean isValid() { - PublicKey currentPublicKey = getCertificate().getPublicKey(); - PublicKey expectedPublicKey = null; - - try { - X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.getDecoder().decode(encodedPublicKey)); - expectedPublicKey = KeyFactory.getInstance("RSA").generatePublic(spec); - } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return expectedPublicKey.equals(currentPublicKey); - } -} diff --git a/src/main/java/eu/m724/realweather/updater/UpdateDownloader.java b/src/main/java/eu/m724/realweather/updater/UpdateDownloader.java deleted file mode 100644 index d17add4..0000000 --- a/src/main/java/eu/m724/realweather/updater/UpdateDownloader.java +++ /dev/null @@ -1,109 +0,0 @@ -package eu.m724.realweather.updater; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.ProxySelector; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.net.http.HttpClient.Redirect; -import java.net.http.HttpResponse.BodyHandlers; -import java.nio.file.Files; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; -import java.util.Arrays; -import java.util.HexFormat; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; - -public class UpdateDownloader { - - /** - * - * @param url - * @param sha256hex - * @return - * @throws SignatureException if signature doesnt match - */ - public CompletableFuture downloadAndVerify(String url, String sha256hex) { - return download(url).thenApply(file -> { - try { - byte[] hash = computeFileSha256Hash(file); - boolean matches = compareBytesHex(hash, sha256hex); - - if (!matches) { - // TODO clean? - throw new SignatureException(); - } - - return file; - } catch (IOException | SignatureException e) { - throw new CompletionException(e); - } - }); - } - - private CompletableFuture download(String url) { // TODO progress? - - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(url)) - .header("User-Agent", "rwu/1") // real weather updater v1 - .build(); - - CompletableFuture> responseFuture = - HttpClient.newBuilder() - .followRedirects(Redirect.NORMAL) - .proxy(ProxySelector.getDefault()).build(). - sendAsync(request, BodyHandlers.ofInputStream()); - - CompletableFuture fileFuture = - responseFuture.thenApply(response -> { - File downloadFile = null; - try { - InputStream bodyStream = response.body(); - downloadFile = Files.createTempFile("realweather", null).toFile(); - FileOutputStream fileStream = new FileOutputStream(downloadFile); - - while (bodyStream.available() > 0) { - bodyStream.transferTo(fileStream); - } - - bodyStream.close(); - } catch (IOException e) { - throw new CompletionException(e); - } - - return downloadFile; - }); - - return fileFuture; - } - - private byte[] computeFileSha256Hash(File file) throws IOException { - MessageDigest digest = null; - try { - digest = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - - try (FileInputStream fileInputStream = new FileInputStream(file)) { - byte[] buffer = new byte[16384]; - int len; - - while ((len = fileInputStream.read(buffer)) != -1) - digest.update(buffer, 0, len); - } - - return digest.digest(); - } - - private boolean compareBytesHex(byte[] bytes, String hecks) { - return Arrays.equals(bytes, HexFormat.of().parseHex(hecks)); - } -} diff --git a/src/main/java/eu/m724/realweather/updater/UpdateNotifier.java b/src/main/java/eu/m724/realweather/updater/UpdateNotifier.java new file mode 100644 index 0000000..0b80cb8 --- /dev/null +++ b/src/main/java/eu/m724/realweather/updater/UpdateNotifier.java @@ -0,0 +1,68 @@ +package eu.m724.realweather.updater; + +import java.io.IOException; +import java.util.concurrent.CompletionException; +import java.util.function.Consumer; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import eu.m724.jarupdater.Updater; +import eu.m724.jarupdater.object.Version; +import eu.m724.realweather.DebugLogger; +import eu.m724.realweather.GlobalConstants; + +public class UpdateNotifier extends BukkitRunnable implements Listener { // TODO move this to jarupdater + private Updater updater; + private Consumer updateConsumer; + + private Plugin plugin = GlobalConstants.getPlugin(); + private Version latestVersion; + + public UpdateNotifier(Updater updater, Consumer updateConsumer) { + this.updater = updater; + this.updateConsumer = updateConsumer; + } + + public void register() { + this.runTaskTimerAsynchronously(plugin, 0, 432000); // 6h + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @Override + public void run() { + + try { + latestVersion = updater.getLatestVersion().join(); + } catch (CompletionException e) { + Throwable ex = e.getCause(); + + if (ex instanceof IOException) + DebugLogger.info("error trying to contact update server: %d", 0, ex.getMessage()); + else e.printStackTrace(); + } + + if (latestVersion == null) return; + + for (Player player : plugin.getServer().getOnlinePlayers()) { + if (player.hasPermission("realweather.update.notify")) { + player.sendMessage("RealWeather is outdated. /rwadmin update"); + } + } + + updateConsumer.accept(latestVersion); + + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent e) { + Player player = e.getPlayer(); + if (latestVersion != null && player.hasPermission("realweather.update.notify")) { + player.sendMessage("RealWeather is outdated. /rwadmin update"); + } + } +} diff --git a/src/main/java/eu/m724/realweather/updater/Updater.java b/src/main/java/eu/m724/realweather/updater/Updater.java deleted file mode 100644 index d980c8e..0000000 --- a/src/main/java/eu/m724/realweather/updater/Updater.java +++ /dev/null @@ -1,198 +0,0 @@ -package eu.m724.realweather.updater; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; - -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitRunnable; -import eu.m724.realweather.DebugLogger; -import eu.m724.realweather.GlobalConstants; -import eu.m724.realweather.exception.UserError; -import eu.m724.realweather.updater.metadata.MetadataRetriever; -import eu.m724.realweather.updater.metadata.MetadataServerException; -import eu.m724.realweather.updater.metadata.VersionMetadata; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.ComponentBuilder; - -public class Updater extends BukkitRunnable implements Listener { - private UpdaterConfig updaterConfig; - private MetadataRetriever metadataRetriever; - private UpdateDownloader updateDownloader; - - private Plugin plugin = GlobalConstants.getPlugin(); - - private File jarFile; - private CompletableFuture downloadFuture; - - private VersionMetadata currentMetadata; - private VersionMetadata latestMetadata; - private long checkCacheExpires; - - private BaseComponent updateMessage = null; - private BaseComponent updateActionMessage = - new ComponentBuilder("To update: ").color(ChatColor.YELLOW) - .append("/rwadmin update").color(ChatColor.AQUA) - .build(); - - public Updater(UpdaterConfig updaterConfig) { - this.updaterConfig = updaterConfig; - this.metadataRetriever = new MetadataRetriever(plugin, updaterConfig.channel); - } - - public void init() { - try { - DebugLogger.info("probing for channels...", 1); - - List channels = metadataRetriever.getChannels().join(); - if (!channels.contains(updaterConfig.channel)) { - throw new UserError( // TODO replace this with its own error / exception? - "Invalid channel: %s. Valid ones are: %s" - .formatted(updaterConfig.channel, String.join(", ", channels))); // WHY DID NOBODY TELL ME ABOUT .formatted - } - - currentMetadata = metadataRetriever.getCurrentVersionMetadata().join(); - DebugLogger.info("current: %d", 1, currentMetadata.id); - } catch (CompletionException e) { - int statusCode = ((MetadataServerException) e.getCause()).getStatusCode(); - if (statusCode >= 500) { - DebugLogger.info("Unable to contact the update server! %d", 0, statusCode); - DebugLogger.info("As it's a server error, it's probably temporary and not a configuration issue, so proceeding.", 0); - } else { - DebugLogger.info("Update server returned unexpected status code: %d", 0, statusCode); - if (plugin.getDescription().getVersion().endsWith("SNAPSHOT")) { - DebugLogger.info("Ignore as you're running a development snapshot.", 0); - } else { - DebugLogger.info("This is probably critical. RealWeather will continue without updater.", 0); - DebugLogger.info("Try restarting the server. If that doesn't help, contact support.", 0); - } - return; - } - } - - try { - jarFile = new File(plugin.getClass().getProtectionDomain().getCodeSource().getLocation().toURI()); - } catch (URISyntaxException e) { } - updateDownloader = new UpdateDownloader(); - - if (updaterConfig.notify) { - this.runTaskTimerAsynchronously(plugin, 0, 216000); // 3h - plugin.getServer().getPluginManager().registerEvents(this, plugin); - DebugLogger.info("updater will notify", 1); - } - - DebugLogger.info("updater loaded", 1); - } - - /** - * download latest update - * @return null if no update else a future with the file (it can error with ioexcepton or signatureexception if signanture invalid) - */ - public CompletableFuture downloadUpdate() { - if (latestMetadata == null) - return null; - - String url = metadataRetriever.getFileUrl(latestMetadata.label, latestMetadata.fileUrl); - downloadFuture = updateDownloader.downloadAndVerify(url, latestMetadata.sha256); - - return downloadFuture; - } - - public boolean installUpdate() { - File downloadedFile = null; - try { - downloadedFile = downloadFuture.join(); - // TODO what if we changed File to Path and every ref in this file - Files.move(downloadedFile.toPath(), jarFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } catch (CompletionException | IOException e) { - e.printStackTrace(); - return false; - } finally { - downloadFuture = null; - } - - return true; - } - - public CompletableFuture getLatestVersion() { - if (System.currentTimeMillis() < checkCacheExpires) - return CompletableFuture.completedFuture(latestMetadata); - else - return checkForNewVersion().handle((result, ex) -> null); - } - - /** - * this can throw completionexception - * @return - */ - private CompletableFuture checkForNewVersion() { - CompletableFuture latestMetadataFuture = - metadataRetriever.getLatestVersionMetadata(); - - CompletableFuture newMetadataFuture = - latestMetadataFuture.thenApply(latestMetadata -> { - DebugLogger.info("Current version: %s (%d)", 2, currentMetadata.label, currentMetadata.id); - DebugLogger.info("Latest version: %s (%d)", 2, latestMetadata.label, latestMetadata.id); - - if (currentMetadata.id < latestMetadata.id) { - this.latestMetadata = latestMetadata; - this.checkCacheExpires = System.currentTimeMillis() + 10800000; - return latestMetadata; - } - - this.checkCacheExpires = System.currentTimeMillis() + 3600000; - return null; - }); - - return newMetadataFuture; - } - - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - Player player = event.getPlayer(); - if (!player.hasPermission("realweather.update.notify")) return; - - if (updateMessage != null) { // TODO make changelog somewhere - player.spigot().sendMessage(updateMessage); - if (player.hasPermission("realweather.admin")) - player.spigot().sendMessage(updateActionMessage); - } - } - - @Override - public void run() { - DebugLogger.info("Checking for update...", 2); - - CompletableFuture newVersionFuture = checkForNewVersion(); - - try { - newVersionFuture.join(); - } catch (CompletionException e) { - int statusCode = ((MetadataServerException) e.getCause()).getStatusCode(); - DebugLogger.info("Couldn't check for updates: %d", 0, statusCode); - } - - updateMessage = new ComponentBuilder("An update is available!\n") - .color(ChatColor.YELLOW) - .append("RealWeather ").color(ChatColor.GOLD) - .append(latestMetadata.label).color(ChatColor.AQUA).bold(true) - .append(" released ").color(ChatColor.GOLD) - .append(latestMetadata.getFormattedDate()).color(ChatColor.AQUA) - .append("\nCurrent: ").color(ChatColor.GRAY) - .append(currentMetadata.label).color(ChatColor.DARK_AQUA) - .build(); - - DebugLogger.info(updateMessage.toPlainText(), 0); - DebugLogger.info(updateActionMessage.toPlainText(), 0); - } -} diff --git a/src/main/java/eu/m724/realweather/updater/metadata/MetadataRetriever.java b/src/main/java/eu/m724/realweather/updater/metadata/MetadataRetriever.java deleted file mode 100644 index f61c7b1..0000000 --- a/src/main/java/eu/m724/realweather/updater/metadata/MetadataRetriever.java +++ /dev/null @@ -1,110 +0,0 @@ -package eu.m724.realweather.updater.metadata; - -import java.net.ProxySelector; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.net.http.HttpClient.Redirect; -import java.net.http.HttpResponse.BodyHandlers; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; - -import org.bukkit.plugin.Plugin; - -import com.google.gson.Gson; - -public class MetadataRetriever { - private String version; - private String channel; - - private CompletableFuture currentMetadataCached = null; - - public MetadataRetriever(Plugin plugin, String channel) { - this.version = plugin.getDescription().getVersion(); - this.channel = channel; - } - - public String getFileUrl(String version, String file) { - return "https://git.724.rocks/Minecon724/realweather-metadata/raw/branch/master/data/%s/%s/%s" - .formatted(channel, version, file); - } - - /** - * the completablefuture can throw a completionexception with {@link eu.m724.realweather.updater.metadata.MetadataServerException} - */ - private CompletableFuture getMetadataOf(String version) { - String url = getFileUrl(version, "meta-v1.json"); - - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(url)) - .header("User-Agent", "rwu/1") // real weather updater v1 - .build(); - - CompletableFuture> responseFuture = - HttpClient.newBuilder() - .followRedirects(Redirect.NORMAL) - .proxy(ProxySelector.getDefault()).build(). - sendAsync(request, BodyHandlers.ofString()); - - CompletableFuture metadataFuture = - responseFuture.thenApply(response -> { - if (response.statusCode() != 200) - throw new CompletionException(new MetadataServerException(response.statusCode())); - - VersionMetadata versionMetadata = new Gson().fromJson(response.body(), VersionMetadata.class); - return versionMetadata; - }); - - return metadataFuture; - } - - public CompletableFuture> getChannels() { - String url = "https://git.724.rocks/Minecon724/realweather-metadata/raw/branch/master/data/channels.txt"; - - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(url)) - .header("User-Agent", "rwu/1") // real weather updater v1 - .build(); - - CompletableFuture> responseFuture = - HttpClient.newBuilder() - .followRedirects(Redirect.NORMAL) - .proxy(ProxySelector.getDefault()).build(). - sendAsync(request, BodyHandlers.ofString()); - - CompletableFuture> channelsFuture = - responseFuture.thenApply(response -> { - if (response.statusCode() != 200) - throw new CompletionException(new MetadataServerException(response.statusCode())); - - return response.body().lines().toList(); - }); - - return channelsFuture; // TODO remove repeated code? - } - - /** - * the {@link CompletableFuture} can throw a {@link CompletionException} with {@link MetadataServerException} - */ - public CompletableFuture getLatestVersionMetadata() { - return getVersionMetadata("latest"); - } - - /** - * the completablefuture can throw a completionexception with {@link MetadataServerException} - */ - public CompletableFuture getCurrentVersionMetadata() { - if (currentMetadataCached == null) - currentMetadataCached = getVersionMetadata(version); - return currentMetadataCached; // TODO reconsider this - } - - /** - * the completablefuture can throw a completionexception with {@link MetadataServerException} - */ - public CompletableFuture getVersionMetadata(String version) { - return getMetadataOf(version); // TODO remove this and rename that function? - } -} diff --git a/src/main/java/eu/m724/realweather/updater/metadata/MetadataServerException.java b/src/main/java/eu/m724/realweather/updater/metadata/MetadataServerException.java deleted file mode 100644 index 881cd92..0000000 --- a/src/main/java/eu/m724/realweather/updater/metadata/MetadataServerException.java +++ /dev/null @@ -1,16 +0,0 @@ -package eu.m724.realweather.updater.metadata; - -public class MetadataServerException extends Exception { - private int statusCode; - - private static final long serialVersionUID = -782470406494196579L; - - public MetadataServerException(int statusCode) { - this.statusCode = statusCode; - } - - public int getStatusCode() { - return statusCode; - } - -} diff --git a/src/main/java/eu/m724/realweather/updater/metadata/VersionMetadata.java b/src/main/java/eu/m724/realweather/updater/metadata/VersionMetadata.java deleted file mode 100644 index d8c39ec..0000000 --- a/src/main/java/eu/m724/realweather/updater/metadata/VersionMetadata.java +++ /dev/null @@ -1,38 +0,0 @@ -package eu.m724.realweather.updater.metadata; - -import java.text.SimpleDateFormat; -import java.util.Date; - -public class VersionMetadata { - /** - * metadata file version - */ - public final int spec = 1; - - /** - * version id. increments with each version - */ - public int id; - - /** - * release time of a version - */ - public long timestamp; - - /** - * label aka version string - * example: 1.0.0 - */ - public String label; - - /** - * url of the downloadable jar file - */ - public String fileUrl; - - public String sha256; - - public String getFormattedDate() { - return new SimpleDateFormat("dd.MM").format(new Date(timestamp)); - } -}