Added auto updater

This commit is contained in:
Lenni0451 2023-01-12 19:43:52 +01:00
parent 86fcd183fd
commit ad8c7d2a62
5 changed files with 339 additions and 51 deletions

View File

@ -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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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();
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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();
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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");
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<Throwable> stopConsumer;
private JProgressBar progressBar;
private Thread downloadThread;
public DownloadPopup(final ViaProxyUI parent, final String url, final File file, final Runnable finishListener, final Consumer<Throwable> 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();
}
}