diff --git a/StatusAPI/src/main/java/net/viper/status/UpdateChecker.java b/StatusAPI/src/main/java/net/viper/status/UpdateChecker.java index ee509c5..1f8cf12 100644 --- a/StatusAPI/src/main/java/net/viper/status/UpdateChecker.java +++ b/StatusAPI/src/main/java/net/viper/status/UpdateChecker.java @@ -1,211 +1,151 @@ -package net.viper.status; - -import net.md_5.bungee.api.plugin.Plugin; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.chat.TextComponent; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.logging.Level; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * UpdateChecker: - * - Fragt die Gitea Releases API ab - * - Sucht in den Releases nach dem Asset "StatusAPI.jar" - * - Extrahiert die Version (tag_name bevorzugt, name als Fallback) - * - Cache die gefundene Version + URL (volatile fields) - */ -public class UpdateChecker implements Runnable { - - private final Plugin plugin; - private final String currentVersion; - private final int intervalHours; - - // Gitea Releases API für dein Repo - private final String apiUrl = "https://git.viper.ipv64.net/api/v1/repos/M_Viper/Minecraft-BungeeCord-Status/releases"; - - // cached results (volatile für Thread-Sichtbarkeit) - private volatile String latestVersion = ""; - private volatile String latestUrl = ""; - - // Patterns for quick parse (we parse JSON as text; this is lightweight and robust for our needs) - private static final Pattern ASSET_NAME_PATTERN = Pattern.compile("\"name\"\\s*:\\s*\"([^\"]+)\"", Pattern.CASE_INSENSITIVE); - private static final Pattern DOWNLOAD_PATTERN = Pattern.compile("\"browser_download_url\"\\s*:\\s*\"([^\"]+)\"", Pattern.CASE_INSENSITIVE); - private static final Pattern TAG_NAME_PATTERN = Pattern.compile("\"tag_name\"\\s*:\\s*\"([^\"]+)\"", Pattern.CASE_INSENSITIVE); - private static final Pattern NAME_FIELD_PATTERN = Pattern.compile("\"name\"\\s*:\\s*\"([^\"]+)\"", Pattern.CASE_INSENSITIVE); - - public UpdateChecker(Plugin plugin, String currentVersion, int intervalHours) { - this.plugin = plugin; - this.currentVersion = currentVersion != null ? currentVersion : "0.0.0"; - this.intervalHours = Math.max(1, intervalHours); - } - - @Override - public void run() { - // scheduled task calls checkNow - checkNow(); - } - - /** - * Führt einen sofortigen Check aus und updated cache (synchron for the calling thread). - */ - public void checkNow() { - try { - plugin.getLogger().info("Prüfe StatusAPI Releases via Gitea API..."); - - HttpURLConnection conn = (HttpURLConnection) new URL(apiUrl).openConnection(); - conn.setRequestMethod("GET"); - conn.setRequestProperty("Accept", "application/json"); - conn.setRequestProperty("User-Agent", "StatusAPI-UpdateChecker/1.0"); - conn.setConnectTimeout(5000); - conn.setReadTimeout(5000); - - int code = conn.getResponseCode(); - if (code != 200) { - plugin.getLogger().warning("Gitea API nicht erreichbar (HTTP " + code + ")"); - return; - } - - StringBuilder sb = new StringBuilder(); - try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"))) { - String line; - while ((line = br.readLine()) != null) { - sb.append(line).append("\n"); - } - } - - String body = sb.toString(); - - // Suche Release mit Asset "StatusAPI.jar" - String foundVersion = null; - String foundUrl = null; - - // Split releases by top-level objects: we simply find repeating {...} blocks and inspect them - // This is robust enough for Gitea JSON responses. - Pattern releasePattern = Pattern.compile("(?s)\\{.*?\\}"); - Matcher releaseMatcher = releasePattern.matcher(body); - while (releaseMatcher.find()) { - String block = releaseMatcher.group(); - - // extract asset names & download urls inside the block - java.util.List names = new java.util.ArrayList<>(); - java.util.List downloads = new java.util.ArrayList<>(); - - Matcher nm = ASSET_NAME_PATTERN.matcher(block); - while (nm.find()) names.add(nm.group(1)); - - Matcher dm = DOWNLOAD_PATTERN.matcher(block); - while (dm.find()) downloads.add(dm.group(1)); - - int pairs = Math.min(names.size(), downloads.size()); - for (int i = 0; i < pairs; i++) { - String name = names.get(i); - String dl = downloads.get(i); - if ("StatusAPI.jar".equalsIgnoreCase(name.trim())) { - // find tag_name or name field in the same block - Matcher tagM = TAG_NAME_PATTERN.matcher(block); - if (tagM.find()) { - foundVersion = tagM.group(1).trim(); - } else { - Matcher nameFieldM = NAME_FIELD_PATTERN.matcher(block); - if (nameFieldM.find()) { - foundVersion = nameFieldM.group(1).trim(); - } - } - foundUrl = dl; - break; - } - } - - if (foundUrl != null) break; - } - - if (foundVersion == null || foundUrl == null) { - plugin.getLogger().info("Kein Release mit Asset 'StatusAPI.jar' gefunden."); - return; - } - - // Normalize version - if (foundVersion.startsWith("v") || foundVersion.startsWith("V")) { - foundVersion = foundVersion.substring(1); - } - - plugin.getLogger().info("Gefundene Version: " + foundVersion + " (aktuell: " + currentVersion + ")"); - - // set cache - latestVersion = foundVersion; - latestUrl = foundUrl; - - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Fehler beim Update-Check: " + e.getMessage(), e); - } - } - - /** - * Gibt die zuletzt gecachte Version (oder empty string). - */ - public String getLatestVersion() { - return latestVersion != null ? latestVersion : ""; - } - - /** - * Gibt die zuletzt gecachte download-URL (oder empty string). - */ - public String getLatestUrl() { - return latestUrl != null ? latestUrl : ""; - } - - /** - * Prüft ob die gecachte latestVersion größer ist als übergebene version. - */ - public boolean isUpdateAvailable(String currentVer) { - String lv = getLatestVersion(); - if (lv.isEmpty()) return false; - return compareVersions(lv, currentVer) > 0; - } - - /** - * Einfacher SemVer-Vergleich (1.2.3). Liefert >0 wenn a>b, 0 wenn gleich, <0 wenn a names = new java.util.ArrayList<>(); + java.util.List downloads = new java.util.ArrayList<>(); + + Matcher nm = ASSET_NAME_PATTERN.matcher(block); + while (nm.find()) names.add(nm.group(1)); + + Matcher dm = DOWNLOAD_PATTERN.matcher(block); + while (dm.find()) downloads.add(dm.group(1)); + + int pairs = Math.min(names.size(), downloads.size()); + for (int i = 0; i < pairs; i++) { + String name = names.get(i); + String dl = downloads.get(i); + if ("StatusAPI.jar".equalsIgnoreCase(name.trim())) { + foundUrl = dl; + break; + } + } + if (foundUrl != null) break; + } + + if (foundUrl == null) { + plugin.getLogger().warning("Keine JAR-Datei für dieses Release gefunden."); + return; + } + + plugin.getLogger().info("Gefundene Version: " + foundVersion + " (Aktuell: " + currentVersion + ")"); + + latestVersion = foundVersion; + latestUrl = foundUrl; + + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Fehler beim Update-Check: " + e.getMessage(), e); + } + } + + public String getLatestVersion() { + return latestVersion != null ? latestVersion : ""; + } + + public String getLatestUrl() { + return latestUrl != null ? latestUrl : ""; + } + + public boolean isUpdateAvailable(String currentVer) { + String lv = getLatestVersion(); + if (lv.isEmpty()) return false; + return compareVersions(lv, currentVer) > 0; + } + + private int compareVersions(String a, String b) { + try { + String[] aa = a.split("\\."); + String[] bb = b.split("\\."); + int len = Math.max(aa.length, bb.length); + for (int i = 0; i < len; i++) { + int ai = i < aa.length ? Integer.parseInt(aa[i].replaceAll("\\D","")) : 0; + int bi = i < bb.length ? Integer.parseInt(bb[i].replaceAll("\\D","")) : 0; + if (ai != bi) return Integer.compare(ai, bi); + } + return 0; + } catch (Exception ex) { + return a.compareTo(b); + } + } +} \ No newline at end of file