From ad8c7d2a62f263a04c5c6e14d73580cee6c2305c Mon Sep 17 00:00:00 2001
From: Lenni0451 <20379977+Lenni0451@users.noreply.github.com>
Date: Thu, 12 Jan 2023 19:43:52 +0100
Subject: [PATCH] Added auto updater
---
.../java/net/raphimc/viaproxy/ViaProxy.java | 61 ++------
.../viaproxy/tasks/AccountRefreshTask.java | 36 +++++
.../raphimc/viaproxy/tasks/LoaderTask.java | 31 ++++
.../viaproxy/tasks/UpdatedCheckTask.java | 117 ++++++++++++++
.../viaproxy/ui/popups/DownloadPopup.java | 145 ++++++++++++++++++
5 files changed, 339 insertions(+), 51 deletions(-)
create mode 100644 src/main/java/net/raphimc/viaproxy/tasks/AccountRefreshTask.java
create mode 100644 src/main/java/net/raphimc/viaproxy/tasks/LoaderTask.java
create mode 100644 src/main/java/net/raphimc/viaproxy/tasks/UpdatedCheckTask.java
create mode 100644 src/main/java/net/raphimc/viaproxy/ui/popups/DownloadPopup.java
diff --git a/src/main/java/net/raphimc/viaproxy/ViaProxy.java b/src/main/java/net/raphimc/viaproxy/ViaProxy.java
index 7038afa..f0c1a05 100644
--- a/src/main/java/net/raphimc/viaproxy/ViaProxy.java
+++ b/src/main/java/net/raphimc/viaproxy/ViaProxy.java
@@ -17,8 +17,6 @@
*/
package net.raphimc.viaproxy;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
@@ -36,20 +34,18 @@ import net.raphimc.netminecraft.netty.connection.NetServer;
import net.raphimc.viaproxy.cli.ConsoleHandler;
import net.raphimc.viaproxy.cli.options.Options;
import net.raphimc.viaproxy.injection.Java17ToJava8;
-import net.raphimc.viaproxy.plugins.PluginManager;
-import net.raphimc.viaproxy.protocolhack.ProtocolHack;
import net.raphimc.viaproxy.proxy.ProxyConnection;
import net.raphimc.viaproxy.proxy.client2proxy.Client2ProxyChannelInitializer;
import net.raphimc.viaproxy.proxy.client2proxy.Client2ProxyHandler;
import net.raphimc.viaproxy.saves.SaveManager;
+import net.raphimc.viaproxy.tasks.AccountRefreshTask;
+import net.raphimc.viaproxy.tasks.LoaderTask;
+import net.raphimc.viaproxy.tasks.UpdatedCheckTask;
import net.raphimc.viaproxy.ui.ViaProxyUI;
import net.raphimc.viaproxy.util.logging.Logger;
import javax.swing.*;
import java.awt.*;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
public class ViaProxy {
@@ -58,6 +54,7 @@ public class ViaProxy {
public static SaveManager saveManager;
public static NetServer currentProxyServer;
public static ChannelGroup c2pChannels;
+ public static ViaProxyUI ui;
public static void main(String[] args) throws Throwable {
final IClassProvider classProvider = new GuavaClassPathProvider();
@@ -81,60 +78,22 @@ public class ViaProxy {
setNettyParameters();
MCPipeline.useOptimizedPipeline();
c2pChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
- Thread loaderThread = new Thread(() -> {
- ProtocolHack.init();
- PluginManager.loadPlugins();
- }, "ViaProtocolHack-Loader");
- Thread accountRefreshThread = new Thread(() -> {
- saveManager.accountsSave.refreshAccounts();
- saveManager.save();
- }, "AccountRefresh");
- Thread updateCheckThread = new Thread(() -> {
- if (VERSION.startsWith("$")) return; // Dev env check
- try {
- URL url = new URL("https://api.github.com/repos/RaphiMC/ViaProxy/releases/latest");
- HttpURLConnection con = (HttpURLConnection) url.openConnection();
- con.setRequestMethod("GET");
- con.setRequestProperty("User-Agent", "ViaProxy/" + VERSION);
- con.setConnectTimeout(5000);
- con.setReadTimeout(5000);
-
- InputStream in = con.getInputStream();
- byte[] bytes = new byte[1024];
- int read;
- StringBuilder builder = new StringBuilder();
- while ((read = in.read(bytes)) != -1) builder.append(new String(bytes, 0, read));
- con.disconnect();
-
- JsonObject object = JsonParser.parseString(builder.toString()).getAsJsonObject();
- String latestVersion = object.get("tag_name").getAsString().substring(1);
- if (!VERSION.equals(latestVersion)) {
- Logger.LOGGER.warn("You are running an outdated version of ViaProxy! Latest version: " + latestVersion);
- if (hasUI) {
- SwingUtilities.invokeLater(() -> {
- JFrame frontFrame = new JFrame();
- frontFrame.setAlwaysOnTop(true);
- JOptionPane.showMessageDialog(frontFrame, "You are running an outdated version of ViaProxy!\nCurrent version: " + VERSION + "\nLatest version: " + latestVersion, "ViaProxy", JOptionPane.WARNING_MESSAGE);
- });
- }
- }
- } catch (Throwable ignored) {
- }
- }, "UpdateCheck");
+ Thread loaderThread = new Thread(new LoaderTask(), "ViaProtocolHack-Loader");
+ Thread accountRefreshThread = new Thread(new AccountRefreshTask(saveManager), "AccountRefresh");
+ Thread updateCheckThread = new Thread(new UpdatedCheckTask(hasUI), "UpdateCheck");
if (hasUI) {
loaderThread.start();
accountRefreshThread.start();
- final ViaProxyUI[] ui = new ViaProxyUI[1];
- SwingUtilities.invokeLater(() -> ui[0] = new ViaProxyUI());
+ SwingUtilities.invokeLater(() -> ui = new ViaProxyUI());
updateCheckThread.start();
loaderThread.join();
accountRefreshThread.join();
- while (ui[0] == null) {
+ while (ui == null) {
Logger.LOGGER.info("Waiting for UI to be initialized...");
Thread.sleep(1000);
}
- ui[0].setReady();
+ ui.setReady();
Logger.LOGGER.info("ViaProxy started successfully!");
return;
}
diff --git a/src/main/java/net/raphimc/viaproxy/tasks/AccountRefreshTask.java b/src/main/java/net/raphimc/viaproxy/tasks/AccountRefreshTask.java
new file mode 100644
index 0000000..6fbedf1
--- /dev/null
+++ b/src/main/java/net/raphimc/viaproxy/tasks/AccountRefreshTask.java
@@ -0,0 +1,36 @@
+/*
+ * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
+ * Copyright (C) 2023 RK_01/RaphiMC and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package net.raphimc.viaproxy.tasks;
+
+import net.raphimc.viaproxy.saves.SaveManager;
+
+public class AccountRefreshTask implements Runnable {
+
+ private final SaveManager saveManager;
+
+ public AccountRefreshTask(final SaveManager saveManager) {
+ this.saveManager = saveManager;
+ }
+
+ @Override
+ public void run() {
+ this.saveManager.accountsSave.refreshAccounts();
+ this.saveManager.save();
+ }
+
+}
diff --git a/src/main/java/net/raphimc/viaproxy/tasks/LoaderTask.java b/src/main/java/net/raphimc/viaproxy/tasks/LoaderTask.java
new file mode 100644
index 0000000..8aa320b
--- /dev/null
+++ b/src/main/java/net/raphimc/viaproxy/tasks/LoaderTask.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
+ * Copyright (C) 2023 RK_01/RaphiMC and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package net.raphimc.viaproxy.tasks;
+
+import net.raphimc.viaproxy.plugins.PluginManager;
+import net.raphimc.viaproxy.protocolhack.ProtocolHack;
+
+public class LoaderTask implements Runnable {
+
+ @Override
+ public void run() {
+ ProtocolHack.init();
+ PluginManager.loadPlugins();
+ }
+
+}
diff --git a/src/main/java/net/raphimc/viaproxy/tasks/UpdatedCheckTask.java b/src/main/java/net/raphimc/viaproxy/tasks/UpdatedCheckTask.java
new file mode 100644
index 0000000..8a39854
--- /dev/null
+++ b/src/main/java/net/raphimc/viaproxy/tasks/UpdatedCheckTask.java
@@ -0,0 +1,117 @@
+/*
+ * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
+ * Copyright (C) 2023 RK_01/RaphiMC and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package net.raphimc.viaproxy.tasks;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import net.raphimc.viaproxy.ViaProxy;
+import net.raphimc.viaproxy.ui.popups.DownloadPopup;
+import net.raphimc.viaproxy.util.logging.Logger;
+
+import javax.swing.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import static net.raphimc.viaproxy.ViaProxy.VERSION;
+
+public class UpdatedCheckTask implements Runnable {
+
+ private final boolean hasUI;
+
+ public UpdatedCheckTask(final boolean hasUI) {
+ this.hasUI = hasUI;
+ }
+
+ @Override
+ public void run() {
+ if (VERSION.startsWith("$")) return; // Dev env check
+ try {
+ URL url = new URL("https://api.github.com/repos/RaphiMC/ViaProxy/releases/latest");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ con.setRequestProperty("User-Agent", "ViaProxy/" + VERSION);
+ con.setConnectTimeout(5000);
+ con.setReadTimeout(5000);
+
+ InputStream in = con.getInputStream();
+ byte[] bytes = new byte[1024];
+ int read;
+ StringBuilder builder = new StringBuilder();
+ while ((read = in.read(bytes)) != -1) builder.append(new String(bytes, 0, read));
+ con.disconnect();
+
+ JsonObject object = JsonParser.parseString(builder.toString()).getAsJsonObject();
+ String latestVersion = object.get("tag_name").getAsString().substring(1);
+ if (!VERSION.equals(latestVersion)) {
+ Logger.LOGGER.warn("You are running an outdated version of ViaProxy! Latest version: " + latestVersion);
+ if (this.hasUI) {
+ JsonArray assets = object.getAsJsonArray("assets");
+ boolean found = false;
+ for (JsonElement asset : assets) {
+ JsonObject assetObject = asset.getAsJsonObject();
+ if (isViaProxyJar(object, assetObject)) {
+ found = true;
+ SwingUtilities.invokeLater(() -> this.showUpdateQuestion(assetObject.get("name").getAsString(), assetObject.get("browser_download_url").getAsString(), latestVersion));
+ break;
+ }
+ }
+ if (!found) SwingUtilities.invokeLater(() -> this.showUpdateWarning(latestVersion));
+ }
+ }
+ } catch (Throwable ignored) {
+ }
+ }
+
+ private void showUpdateWarning(final String latestVersion) {
+ JOptionPane.showMessageDialog(ViaProxy.ui, "You are running an outdated version of ViaProxy!\nCurrent version: " + VERSION + "\nLatest version: " + latestVersion, "ViaProxy", JOptionPane.WARNING_MESSAGE);
+ }
+
+ private void showUpdateQuestion(final String name, final String downloadUrl, final String latestVersion) {
+ int chosen = JOptionPane.showConfirmDialog(ViaProxy.ui, "You are running an outdated version of ViaProxy!\nCurrent version: " + VERSION + "\nLatest version: " + latestVersion + "\n\nDo you want to update?", "ViaProxy", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
+ if (chosen == JOptionPane.YES_OPTION) {
+ File f = new File(name);
+ new DownloadPopup(ViaProxy.ui, downloadUrl, f, () -> {
+ SwingUtilities.invokeLater(() -> {
+ JOptionPane.showMessageDialog(ViaProxy.ui, "Downloaded the latest version of ViaProxy!\nPress OK to restart.", "ViaProxy", JOptionPane.INFORMATION_MESSAGE);
+ try {
+ Runtime.getRuntime().exec(new String[]{System.getProperty("java.home") + "/bin/java", "-jar", f.getAbsolutePath()});
+ System.exit(0);
+ } catch (IOException e) {
+ Logger.LOGGER.error("Could not start the new ViaProxy jar", e);
+ ViaProxy.ui.showException(e);
+ }
+ });
+ }, t -> {
+ if (t != null) {
+ Logger.LOGGER.error("Could not download the latest version of ViaProxy", t);
+ ViaProxy.ui.showException(t);
+ }
+ });
+ }
+ }
+
+ private boolean isViaProxyJar(final JsonObject root, final JsonObject assetObject) {
+ return assetObject.get("name").getAsString().equals(root.get("name").getAsString() + ".jar");
+ }
+
+}
diff --git a/src/main/java/net/raphimc/viaproxy/ui/popups/DownloadPopup.java b/src/main/java/net/raphimc/viaproxy/ui/popups/DownloadPopup.java
new file mode 100644
index 0000000..1034f50
--- /dev/null
+++ b/src/main/java/net/raphimc/viaproxy/ui/popups/DownloadPopup.java
@@ -0,0 +1,145 @@
+/*
+ * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
+ * Copyright (C) 2023 RK_01/RaphiMC and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package net.raphimc.viaproxy.ui.popups;
+
+import net.raphimc.viaproxy.ViaProxy;
+import net.raphimc.viaproxy.ui.ViaProxyUI;
+
+import javax.swing.*;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.function.Consumer;
+
+public class DownloadPopup extends JDialog {
+
+ private final ViaProxyUI parent;
+ private final String url;
+ private final File file;
+ private final Runnable finishListener;
+ private final Consumer stopConsumer;
+
+ private JProgressBar progressBar;
+ private Thread downloadThread;
+
+ public DownloadPopup(final ViaProxyUI parent, final String url, final File file, final Runnable finishListener, final Consumer stopConsumer) {
+ super(parent, true);
+ this.parent = parent;
+ this.url = url;
+ this.file = file;
+ this.finishListener = finishListener;
+ this.stopConsumer = stopConsumer;
+
+ this.initWindow();
+ this.initComponents();
+ this.setVisible(true);
+ }
+
+ private void initWindow() {
+ this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+ this.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ DownloadPopup.this.close(false);
+ }
+ });
+ this.setTitle("Downloading...");
+ this.setSize(400, 110);
+ this.setResizable(false);
+ this.setLocationRelativeTo(this.parent);
+ }
+
+ private void initComponents() {
+ JPanel contentPane = new JPanel();
+ contentPane.setLayout(null);
+ this.setContentPane(contentPane);
+ {
+ this.progressBar = new JProgressBar();
+ this.progressBar.setBounds(10, 10, 365, 20);
+ this.progressBar.setStringPainted(true);
+ contentPane.add(this.progressBar);
+ }
+ {
+ JButton cancelButton = new JButton("Cancel");
+ cancelButton.setBounds(10, 40, 365, 20);
+ cancelButton.addActionListener(e -> this.close(false));
+ contentPane.add(cancelButton);
+ }
+ this.start();
+ }
+
+ private void start() {
+ this.downloadThread = new Thread(() -> {
+ try {
+ HttpURLConnection con = (HttpURLConnection) new URL(this.url).openConnection();
+ con.setRequestMethod("GET");
+ con.setRequestProperty("User-Agent", "Viaproxy/" + ViaProxy.VERSION);
+ con.setConnectTimeout(5000);
+ con.setReadTimeout(5000);
+
+ int contentLength = con.getContentLength();
+ int current = 0;
+ File tempFile = File.createTempFile("ViaProxy-download", "");
+ InputStream is = con.getInputStream();
+ FileOutputStream fos = new FileOutputStream(tempFile);
+ byte[] buffer = new byte[1024 * 1024];
+ int len;
+ while ((len = is.read(buffer)) != -1) {
+ if (this.downloadThread.isInterrupted()) throw new InterruptedException();
+ fos.write(buffer, 0, len);
+
+ if (contentLength != -1) {
+ current += len;
+ this.progressBar.setValue((int) (100F / contentLength * current));
+ }
+ }
+ fos.close();
+ is.close();
+ con.disconnect();
+
+ Files.move(tempFile.toPath(), this.file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+ this.close(true);
+ this.finishListener.run();
+ } catch (InterruptedException ignored) {
+ } catch (Throwable t) {
+ this.close(false);
+ this.stopConsumer.accept(t);
+ }
+ }, "Download Popup Thread");
+ this.downloadThread.setDaemon(true);
+ this.downloadThread.start();
+ }
+
+ private void close(final boolean success) {
+ if (!success && this.downloadThread != null && this.downloadThread.isAlive()) {
+ this.downloadThread.interrupt();
+ this.stopConsumer.accept(null);
+ }
+
+ this.setVisible(false);
+ this.dispose();
+ }
+
+}