parent
6f28250a10
commit
a7506bd3c6
12 changed files with 394 additions and 2 deletions
|
@ -29,7 +29,9 @@ public record TweaksConfig(
|
||||||
int compassPrecision,
|
int compassPrecision,
|
||||||
|
|
||||||
boolean pomodoroEnabled,
|
boolean pomodoroEnabled,
|
||||||
boolean pomodoroForce
|
boolean pomodoroForce,
|
||||||
|
|
||||||
|
boolean updaterEnabled
|
||||||
) {
|
) {
|
||||||
public static final int CONFIG_VERSION = 1;
|
public static final int CONFIG_VERSION = 1;
|
||||||
private static TweaksConfig config;
|
private static TweaksConfig config;
|
||||||
|
@ -87,7 +89,8 @@ public record TweaksConfig(
|
||||||
motdEnabled, motdSet,
|
motdEnabled, motdSet,
|
||||||
chatEnabled, chatLocalEvents, chatDefaultName,
|
chatEnabled, chatLocalEvents, chatDefaultName,
|
||||||
compassEnabled, compassWidth, compassPrecision,
|
compassEnabled, compassWidth, compassPrecision,
|
||||||
pomodoroEnabled, pomodoroForce
|
pomodoroEnabled, pomodoroForce,
|
||||||
|
true // TODO
|
||||||
);
|
);
|
||||||
|
|
||||||
return TweaksConfig.config;
|
return TweaksConfig.config;
|
||||||
|
|
|
@ -10,6 +10,7 @@ import eu.m724.tweaks.ping.PingChecker;
|
||||||
import eu.m724.tweaks.ping.PingCommands;
|
import eu.m724.tweaks.ping.PingCommands;
|
||||||
import eu.m724.tweaks.pomodoro.PomodoroCommands;
|
import eu.m724.tweaks.pomodoro.PomodoroCommands;
|
||||||
import eu.m724.tweaks.pomodoro.PomodoroManager;
|
import eu.m724.tweaks.pomodoro.PomodoroManager;
|
||||||
|
import eu.m724.tweaks.updater.UpdaterManager;
|
||||||
import eu.m724.tweaks.worldborder.WorldBorderManager;
|
import eu.m724.tweaks.worldborder.WorldBorderManager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
@ -66,5 +67,12 @@ public class TweaksPlugin extends JavaPlugin {
|
||||||
getCommand("pomodoro").setExecutor(new PomodoroCommands());
|
getCommand("pomodoro").setExecutor(new PomodoroCommands());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.updaterEnabled()) {
|
||||||
|
try {
|
||||||
|
new UpdaterManager(this).init();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
58
src/main/java/eu/m724/tweaks/updater/PluginScanner.java
Normal file
58
src/main/java/eu/m724/tweaks/updater/PluginScanner.java
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package eu.m724.tweaks.updater;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import com.google.gson.annotations.JsonAdapter;
|
||||||
|
import eu.m724.tweaks.updater.cache.SpigotResource;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class PluginScanner {
|
||||||
|
private final Plugin thisPlugin;
|
||||||
|
|
||||||
|
PluginScanner(Plugin thisPlugin) {
|
||||||
|
this.thisPlugin = thisPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<SpigotResource> load() throws IOException {
|
||||||
|
File installedPluginsYml = new File(thisPlugin.getDataFolder(), "installed_plugins.yml");
|
||||||
|
|
||||||
|
if (!installedPluginsYml.exists()) {
|
||||||
|
thisPlugin.saveResource("installed_plugins.yml", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(installedPluginsYml);
|
||||||
|
|
||||||
|
|
||||||
|
Plugin[] plugins = thisPlugin.getServer().getPluginManager().getPlugins();
|
||||||
|
Set<SpigotResource> spigotResources = new HashSet<>();
|
||||||
|
|
||||||
|
for (Plugin plugin : plugins) {
|
||||||
|
System.out.println("Found " + plugin.getName());
|
||||||
|
String pluginName = plugin.getName();
|
||||||
|
|
||||||
|
if (!configuration.isSet(pluginName)) {
|
||||||
|
configuration.set(pluginName, -1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pluginId = configuration.getInt(pluginName);
|
||||||
|
if (pluginId != -1) {
|
||||||
|
spigotResources.add(
|
||||||
|
new SpigotResource(plugin, pluginId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration.save(installedPluginsYml);
|
||||||
|
|
||||||
|
return spigotResources;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
59
src/main/java/eu/m724/tweaks/updater/UpdateChecker.java
Normal file
59
src/main/java/eu/m724/tweaks/updater/UpdateChecker.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package eu.m724.tweaks.updater;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import eu.m724.tweaks.updater.cache.ResourceVersion;
|
||||||
|
import eu.m724.tweaks.updater.cache.SpigotResource;
|
||||||
|
import eu.m724.tweaks.updater.cache.VersionedResource;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.eclipse.aether.impl.UpdateCheck;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class UpdateChecker extends BukkitRunnable {
|
||||||
|
private final Set<VersionedResource> resources;
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
UpdateChecker(Plugin plugin, Set<VersionedResource> resources) {
|
||||||
|
this.logger = Logger.getLogger(plugin.getLogger().getName() + "." + getClass().getSimpleName());
|
||||||
|
this.resources = resources; // TODO make a copy?
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAll() {
|
||||||
|
logger.info("Now checking all plugins");
|
||||||
|
for (VersionedResource versionedResource : Set.copyOf(resources)) {
|
||||||
|
logger.info(versionedResource.resource().resourceId() + " " + versionedResource.resource().plugin().getName());
|
||||||
|
int page = versionedResource.running() != null ? versionedResource.running().page() : 1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
VersionedResource newResource = new VersionFinder(versionedResource.resource(), page).join(); // this runs async so it's ok
|
||||||
|
if (!versionedResource.equals(newResource)) {
|
||||||
|
resources.remove(versionedResource);
|
||||||
|
resources.add(newResource);
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
} catch (CompletionException e) {
|
||||||
|
logger.severe("Unable to refresh %s: %s".formatted(versionedResource.resource().plugin().getName(), e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
checkAll();
|
||||||
|
}
|
||||||
|
}
|
44
src/main/java/eu/m724/tweaks/updater/UpdaterManager.java
Normal file
44
src/main/java/eu/m724/tweaks/updater/UpdaterManager.java
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package eu.m724.tweaks.updater;
|
||||||
|
|
||||||
|
import eu.m724.tweaks.updater.cache.ResourceVersion;
|
||||||
|
import eu.m724.tweaks.updater.cache.SpigotResource;
|
||||||
|
import eu.m724.tweaks.updater.cache.VersionedResource;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class UpdaterManager {
|
||||||
|
private final Plugin plugin;
|
||||||
|
|
||||||
|
public UpdaterManager(Plugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() throws IOException {
|
||||||
|
// scan installed plugins
|
||||||
|
Set<SpigotResource> resources = new PluginScanner(plugin).load();
|
||||||
|
|
||||||
|
// load installed versions from cache
|
||||||
|
File cacheFile = new File(plugin.getDataFolder(), "version cache");
|
||||||
|
Set<ResourceVersion> installedVersions;
|
||||||
|
try (FileInputStream inputStream = new FileInputStream(cacheFile)) {
|
||||||
|
installedVersions = VersionCheckCache.loadAll(inputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<VersionedResource> versionedResources = installedVersions.stream()
|
||||||
|
.map(rv -> new VersionedResource(
|
||||||
|
resources.stream().filter(r -> r.resourceId() == rv.resourceId()).findFirst().get(),
|
||||||
|
rv,
|
||||||
|
null
|
||||||
|
)).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
|
||||||
|
new UpdateChecker(plugin, versionedResources)
|
||||||
|
.runTaskTimerAsynchronously(plugin, 600, 12 * 3600 * 20);
|
||||||
|
}
|
||||||
|
}
|
75
src/main/java/eu/m724/tweaks/updater/VersionCheckCache.java
Normal file
75
src/main/java/eu/m724/tweaks/updater/VersionCheckCache.java
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package eu.m724.tweaks.updater;
|
||||||
|
|
||||||
|
import eu.m724.tweaks.updater.cache.ResourceVersion;
|
||||||
|
import eu.m724.tweaks.updater.cache.VersionedResource;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class VersionCheckCache {
|
||||||
|
private static final byte FILE_VERSION = 1;
|
||||||
|
|
||||||
|
public static Set<ResourceVersion> loadAll(FileInputStream inputStream) throws IOException {
|
||||||
|
byte fileVersion = (byte) inputStream.read();
|
||||||
|
if (fileVersion != FILE_VERSION) throw new FileVersionMismatchException(fileVersion, FILE_VERSION);
|
||||||
|
|
||||||
|
Set<ResourceVersion> versions = new HashSet<>();
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
byte[] buffer = new byte[8]; // 3 + 2 + 3
|
||||||
|
while (inputStream.available() > 0) {
|
||||||
|
int read = inputStream.read(buffer);
|
||||||
|
if (read < 8) break; // end of file
|
||||||
|
if (++i > 10000) throw new RuntimeException("File is too large");
|
||||||
|
|
||||||
|
ResourceVersion resourceVersion = getResourceVersion(buffer);
|
||||||
|
versions.add(resourceVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return versions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ResourceVersion getResourceVersion(byte[] bytes) {
|
||||||
|
int resourceId = ((bytes[0] & 0xFF) << 16) | ((bytes[1] & 0xFF) << 8) | (bytes[2] & 0xFF);
|
||||||
|
int page = ((bytes[3] & 0xFF) << 8) | (bytes[4] & 0xFF);
|
||||||
|
int versionId = ((bytes[5] & 0xFF) << 16) | ((bytes[6] & 0xFF) << 8) | (bytes[7] & 0xFF);
|
||||||
|
|
||||||
|
return new ResourceVersion(resourceId, page, versionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeResourceVersion(ResourceVersion resourceVersion, OutputStream outputStream) throws IOException {
|
||||||
|
int resourceId = resourceVersion.resourceId();
|
||||||
|
outputStream.write((resourceId >> 16) & 0xFF);
|
||||||
|
outputStream.write((resourceId >> 8) & 0xFF);
|
||||||
|
outputStream.write(resourceId & 0xFF);
|
||||||
|
|
||||||
|
int page = resourceVersion.page();
|
||||||
|
outputStream.write((page >> 8) & 0xFF);
|
||||||
|
outputStream.write(page & 0xFF);
|
||||||
|
|
||||||
|
int versionId = resourceVersion.updateId();
|
||||||
|
outputStream.write((versionId >> 16) & 0xFF);
|
||||||
|
outputStream.write((versionId >> 8) & 0xFF);
|
||||||
|
outputStream.write(versionId & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeAll(FileOutputStream outputStream, Set<ResourceVersion> versions) throws IOException {
|
||||||
|
outputStream.write(FILE_VERSION);
|
||||||
|
for (ResourceVersion version : versions) {
|
||||||
|
writeResourceVersion(version, outputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FileVersionMismatchException extends RuntimeException {
|
||||||
|
public final byte fileVersion, expectedVersion;
|
||||||
|
|
||||||
|
public FileVersionMismatchException(byte fileVersion, byte expectedVersion) {
|
||||||
|
this.fileVersion = fileVersion;
|
||||||
|
this.expectedVersion = expectedVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
src/main/java/eu/m724/tweaks/updater/VersionFinder.java
Normal file
109
src/main/java/eu/m724/tweaks/updater/VersionFinder.java
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
package eu.m724.tweaks.updater;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import eu.m724.tweaks.updater.cache.SpigotResource;
|
||||||
|
import eu.m724.tweaks.updater.cache.ResourceVersion;
|
||||||
|
import eu.m724.tweaks.updater.cache.VersionedResource;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
// TODO optimize
|
||||||
|
|
||||||
|
public class VersionFinder extends CompletableFuture<VersionedResource> {
|
||||||
|
private final SpigotResource resource;
|
||||||
|
private final int fromPage;
|
||||||
|
|
||||||
|
VersionFinder(SpigotResource resource, int fromPage) {
|
||||||
|
this.resource = resource;
|
||||||
|
this.fromPage = fromPage;
|
||||||
|
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
VersionFinder(SpigotResource resource) {
|
||||||
|
this(resource, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void start() {
|
||||||
|
System.out.printf("STarting for %d %s\n", resource.resourceId(), resource.plugin().getName());
|
||||||
|
try (ExecutorService executor = Executors.newSingleThreadExecutor()) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
try {
|
||||||
|
ResourceVersion runningVersion = null;
|
||||||
|
ResourceVersion latestVersion = null;
|
||||||
|
|
||||||
|
int page;
|
||||||
|
for (page = fromPage; page < 1000; page++) {
|
||||||
|
System.out.println("Page " + page);
|
||||||
|
String url = "https://api.spigotmc.org/simple/0.2/index.php?action=getResourceUpdates&page=%d&id=%d".formatted(page, resource.resourceId());
|
||||||
|
|
||||||
|
HttpRequest request;
|
||||||
|
try {
|
||||||
|
request = HttpRequest.newBuilder(new URI(url))
|
||||||
|
.header("User-Agent", "twu/1")
|
||||||
|
.build();
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} // this will never happen
|
||||||
|
|
||||||
|
try (HttpClient client = HttpClient.newHttpClient()) {
|
||||||
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
|
||||||
|
String body = response.body();
|
||||||
|
if (body.isBlank()) {
|
||||||
|
page--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArray jsonArray = JsonParser.parseString(body).getAsJsonArray();
|
||||||
|
for (JsonElement ele : jsonArray) {
|
||||||
|
JsonObject versionJson = ele.getAsJsonObject();
|
||||||
|
if (isRunningVersion(versionJson)) {
|
||||||
|
runningVersion = new ResourceVersion(
|
||||||
|
resource.resourceId(),
|
||||||
|
page,
|
||||||
|
versionJson.get("id").getAsInt()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
latestVersion = new ResourceVersion(
|
||||||
|
resource.resourceId(),
|
||||||
|
page,
|
||||||
|
versionJson.get("id").getAsInt()
|
||||||
|
);
|
||||||
|
System.out.printf("%d %d %s\n", page, versionJson.get("id").getAsInt(), versionJson.get("resource_version").getAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonArray.size() < 10) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
System.out.println("Done");
|
||||||
|
|
||||||
|
if (page > 999) {
|
||||||
|
throw new Exception("Too many pages");
|
||||||
|
} else {
|
||||||
|
this.complete(new VersionedResource(resource, runningVersion, latestVersion));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
this.completeExceptionally(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRunningVersion(JsonObject versionJson) {
|
||||||
|
// TODO
|
||||||
|
return versionJson.get("resource_version").getAsString().equals(resource.plugin().getDescription().getVersion());
|
||||||
|
}
|
||||||
|
}
|
12
src/main/java/eu/m724/tweaks/updater/cache/ResourceVersion.java
vendored
Normal file
12
src/main/java/eu/m724/tweaks/updater/cache/ResourceVersion.java
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package eu.m724.tweaks.updater.cache;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record ResourceVersion(
|
||||||
|
int resourceId,
|
||||||
|
int page,
|
||||||
|
int updateId
|
||||||
|
) { }
|
9
src/main/java/eu/m724/tweaks/updater/cache/SpigotResource.java
vendored
Normal file
9
src/main/java/eu/m724/tweaks/updater/cache/SpigotResource.java
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package eu.m724.tweaks.updater.cache;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
public record SpigotResource(
|
||||||
|
Plugin plugin,
|
||||||
|
int resourceId
|
||||||
|
) {
|
||||||
|
}
|
11
src/main/java/eu/m724/tweaks/updater/cache/VersionedResource.java
vendored
Normal file
11
src/main/java/eu/m724/tweaks/updater/cache/VersionedResource.java
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package eu.m724.tweaks.updater.cache;
|
||||||
|
|
||||||
|
public record VersionedResource(
|
||||||
|
SpigotResource resource,
|
||||||
|
ResourceVersion running,
|
||||||
|
ResourceVersion latest
|
||||||
|
) {
|
||||||
|
public VersionedResource update(ResourceVersion latest) {
|
||||||
|
return new VersionedResource(resource, running, latest);
|
||||||
|
}
|
||||||
|
}
|
3
src/main/resources/installed_plugins.yml
Normal file
3
src/main/resources/installed_plugins.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Here go installed plugins and their SpigotMC resource IDs
|
||||||
|
# To ignore a plugin, set it to -1
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
name: Tweaks724
|
name: Tweaks724
|
||||||
|
author: Minecon724
|
||||||
version: ${project.version}
|
version: ${project.version}
|
||||||
|
|
||||||
main: eu.m724.tweaks.TweaksPlugin
|
main: eu.m724.tweaks.TweaksPlugin
|
||||||
|
|
Loading…
Reference in a new issue