diff --git a/DOMAINS-FIREWALL.md b/DOMAINS-FIREWALL.md
index 17d3a92..f32753e 100644
--- a/DOMAINS-FIREWALL.md
+++ b/DOMAINS-FIREWALL.md
@@ -1,9 +1,11 @@
If you're using a firewall, you must allow the following hosts:
-- core functionality:
- * rw-api.m724.eu
+- updater:
+ * git.724.rocks
- weather:
* api.openweathermap.org
- thunder:
* ws1.blitzortung.org
* ws7.blitzortung.org
- * ws8.blitzortung.org
\ No newline at end of file
+ * ws8.blitzortung.org
+
+Subject to change!
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 65bd95e..6f3bbb7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,7 +59,7 @@
eu.m724:wtapi
- org.java-websocket:Java-WebSocket
+
diff --git a/src/main/java/eu/m724/realweather/RealWeatherPlugin.java b/src/main/java/eu/m724/realweather/RealWeatherPlugin.java
index 0b5f6e5..edefab3 100644
--- a/src/main/java/eu/m724/realweather/RealWeatherPlugin.java
+++ b/src/main/java/eu/m724/realweather/RealWeatherPlugin.java
@@ -17,11 +17,12 @@ import eu.m724.realweather.commands.LocalTimeCommand;
import eu.m724.realweather.mapper.Mapper;
import eu.m724.realweather.mapper.MapperConfig;
import eu.m724.realweather.object.UserException;
-import eu.m724.realweather.sign.SignatureValidator;
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.weather.WeatherConfig;
import eu.m724.realweather.weather.WeatherMaster;
import eu.m724.wtapi.provider.exception.ProviderException;
@@ -135,6 +136,8 @@ public class RealWeatherPlugin extends JavaPlugin {
if (GlobalConstants.timeConfig.enabled)
getCommand("localtime").setExecutor(new LocalTimeCommand());
+
+ new Updater().init();
DebugLogger.info("ended loading", 1);
}
diff --git a/src/main/java/eu/m724/realweather/updater/MetadataRetriever.java b/src/main/java/eu/m724/realweather/updater/MetadataRetriever.java
new file mode 100644
index 0000000..08ec9d3
--- /dev/null
+++ b/src/main/java/eu/m724/realweather/updater/MetadataRetriever.java
@@ -0,0 +1,62 @@
+package eu.m724.realweather.updater;
+
+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.concurrent.CompletableFuture;
+
+import org.bukkit.plugin.Plugin;
+
+import com.google.gson.Gson;
+
+public class MetadataRetriever {
+ private String version;
+
+ private CompletableFuture currentMetadataCached = null;
+
+ public MetadataRetriever(Plugin plugin) {
+ this.version = plugin.getDescription().getVersion();
+ }
+
+ private CompletableFuture getMetadataFromUrl(String url) {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .header("User-Agent", "rwu/1")
+ .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)
+ return null;
+
+ VersionMetadata versionMetadata = new Gson().fromJson(response.body(), VersionMetadata.class);
+ return versionMetadata;
+ });
+
+ return metadataFuture;
+ }
+
+ public CompletableFuture getLatestVersionMetadata() {
+ return getMetadataFromUrl("https://git.724.rocks/Minecon724/realweather-metadata/raw/branch/master/latest/latest-v1.json");
+ }
+
+ public CompletableFuture getCurrentVersionMetadata() {
+ if (currentMetadataCached != null)
+ currentMetadataCached = getVersionMetadata(version);
+ return currentMetadataCached;
+ }
+
+ public CompletableFuture getVersionMetadata(String version) {
+ return getMetadataFromUrl("https://git.724.rocks/Minecon724/realweather-metadata/raw/branch/master/releases/" + version + "/meta-v1.json");
+ }
+}
diff --git a/src/main/java/eu/m724/realweather/sign/SignatureValidator.java b/src/main/java/eu/m724/realweather/updater/SignatureValidator.java
similarity index 97%
rename from src/main/java/eu/m724/realweather/sign/SignatureValidator.java
rename to src/main/java/eu/m724/realweather/updater/SignatureValidator.java
index 3572c1c..39d03ae 100644
--- a/src/main/java/eu/m724/realweather/sign/SignatureValidator.java
+++ b/src/main/java/eu/m724/realweather/updater/SignatureValidator.java
@@ -1,4 +1,4 @@
-package eu.m724.realweather.sign;
+package eu.m724.realweather.updater;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
diff --git a/src/main/java/eu/m724/realweather/updater/Updater.java b/src/main/java/eu/m724/realweather/updater/Updater.java
new file mode 100644
index 0000000..142eb66
--- /dev/null
+++ b/src/main/java/eu/m724/realweather/updater/Updater.java
@@ -0,0 +1,91 @@
+package eu.m724.realweather.updater;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.CompletableFuture;
+
+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 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 Plugin plugin = GlobalConstants.getPlugin();
+ private MetadataRetriever metadataRetriever = new MetadataRetriever(plugin);
+
+ private VersionMetadata availableUpdate = null;
+
+ private BaseComponent updateMessage = null;
+ private BaseComponent updateActionMessage =
+ new ComponentBuilder("To update: ").color(ChatColor.YELLOW)
+ .append("/rwadmin update").color(ChatColor.AQUA)
+ .build();
+
+ public void init() {
+ this.runTaskTimerAsynchronously(plugin, 0, 216000); // 3h
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ public boolean installUpdate() {
+ if (availableUpdate == null)
+ return false;
+
+ // TODO
+ return true;
+ }
+
+ @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 currentMetadataFuture =
+ metadataRetriever.getCurrentVersionMetadata();
+
+ CompletableFuture latestMetadataFuture =
+ metadataRetriever.getLatestVersionMetadata();
+
+ VersionMetadata currentMetadata = currentMetadataFuture.join();
+ VersionMetadata latestMetadata = latestMetadataFuture.join();
+
+ 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) return;
+
+ availableUpdate = latestMetadata;
+
+ String formattedDate = new SimpleDateFormat("dd.MM").format(new Date(latestMetadata.timestamp));
+
+ 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(formattedDate).color(ChatColor.AQUA)
+ .append("\nCurrent: ").color(ChatColor.GRAY)
+ .append(currentMetadata.label).color(ChatColor.DARK_AQUA)
+ .build();
+
+ DebugLogger.info(updateMessage.toString(), 0);
+ DebugLogger.info(updateActionMessage.toString(), 0);
+ }
+}
diff --git a/src/main/java/eu/m724/realweather/updater/VersionMetadata.java b/src/main/java/eu/m724/realweather/updater/VersionMetadata.java
new file mode 100644
index 0000000..f020f06
--- /dev/null
+++ b/src/main/java/eu/m724/realweather/updater/VersionMetadata.java
@@ -0,0 +1,29 @@
+package eu.m724.realweather.updater;
+
+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;
+
+ /**
+ * filename of the jar file in the version directory
+ */
+ public String file;
+}
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 5d209b2..a0905ba 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -4,10 +4,13 @@ version: ${project.version}
author: Minecon724
website: https://forum.m724.eu/topic/3/realweather-1-0
-api-version: 1.20
+api-version: 1.21
load: STARTUP
main: eu.m724.realweather.RealWeatherPlugin
+libraries:
+- org.java-websocket:Java-WebSocket:1.5.6
+
commands:
rwadmin:
description: RealWeather admin command