From 47f228caa38009874ca8de526572e9ad9b5f8920 Mon Sep 17 00:00:00 2001 From: Oak Date: Tue, 15 Sep 2026 16:57:30 +0100 Subject: [PATCH 01/15] Bumped version to 5.0.0-alpha.1 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index c6d79c83..f1f9b624 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { } group = "org.lushplugins" -version = "4.3.2" +version = "5.0.0-alpha.1" allprojects { plugins.apply("java-library") From 6e8daa60170069ad9c532869f48a2c8aa87ffac9 Mon Sep 17 00:00:00 2001 From: Oak Date: Tue, 15 Sep 2026 17:19:04 +0100 Subject: [PATCH 02/15] Corrected velocity tests package name --- .../velocity/test/VelocityUpdaterTests.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 platform/velocity-plugin/src/test/java/org/lushplugins/pluginupdater/velocity/test/VelocityUpdaterTests.java diff --git a/platform/velocity-plugin/src/test/java/org/lushplugins/pluginupdater/velocity/test/VelocityUpdaterTests.java b/platform/velocity-plugin/src/test/java/org/lushplugins/pluginupdater/velocity/test/VelocityUpdaterTests.java new file mode 100644 index 00000000..7280f053 --- /dev/null +++ b/platform/velocity-plugin/src/test/java/org/lushplugins/pluginupdater/velocity/test/VelocityUpdaterTests.java @@ -0,0 +1,17 @@ +package org.lushplugins.pluginupdater.velocity.test; + +import org.junit.jupiter.api.Test; +import org.lushplugins.pluginupdater.tests.commonplugins.CommonPluginsTest; + +public class VelocityUpdaterTests { + + static { + System.setProperty("platform", "velocity"); + System.setProperty("server-version", "4.1.0"); + } + + @Test + public void test() { + CommonPluginsTest.runTest("common-plugins.yml"); + } +} From 73740a7c4444d3e812aa5bee585453ad7d4b1b0a Mon Sep 17 00:00:00 2001 From: Zoriot Date: Sun, 16 Aug 2026 15:54:46 +0200 Subject: [PATCH 03/15] =?UTF-8?q?feat:=20=E2=9C=A8=20Switch=20to=20Adventu?= =?UTF-8?q?re=20ComponentLogger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements: #187. BREAKING-CHANGE: Api now also uses ComponentLogger instead of java's Logger --- common/api/build.gradle.kts | 2 ++ .../pluginupdater/api/updater/PluginData.java | 22 ++++++++----- .../pluginupdater/api/updater/PluginInfo.java | 4 +-- .../api/util/UpdaterConstants.java | 33 ++----------------- .../api/version/DownloadableRelease.java | 2 +- .../pluginupdater/common/UpdaterImpl.java | 5 ++- .../common/collector/ModrinthCollector.java | 13 +++++--- .../common/command/UpdaterCommand.java | 7 ++-- .../common/config/ConfigManager.java | 5 ++- .../deserializer/PluginDataDeserializer.java | 5 ++- .../deserializer/SourceDataDeserializer.java | 3 +- .../common/platform/UpdaterPlugin.java | 4 +-- .../common/updater/UpdateHandler.java | 11 ++++--- platform/cli/build.gradle.kts | 1 + .../pluginupdater/cli/PluginUpdaterCLI.java | 8 ++--- .../cli/platform/CLIPlatform.java | 5 ++- .../cli/plugin/CLIPluginInfo.java | 4 +-- .../paper/api/plugin/PaperPluginInfo.java | 9 +++-- .../paper/PaperUpdaterPlugin.java | 10 +++++- .../paper/collector/SpigotCollector.java | 16 +++++---- .../velocity/api/VelocityUpdater.java | 4 +-- .../api/platform/VelocityUpdaterPlatform.java | 6 ++-- .../api/plugin/VelocityPluginInfo.java | 6 ++-- .../velocity/VelocityUpdaterPlugin.java | 10 +++--- .../commonplugins/CommonPluginsTest.java | 15 ++++----- 25 files changed, 99 insertions(+), 111 deletions(-) diff --git a/common/api/build.gradle.kts b/common/api/build.gradle.kts index 292582ed..c750bdb9 100644 --- a/common/api/build.gradle.kts +++ b/common/api/build.gradle.kts @@ -17,5 +17,7 @@ sourceSets { dependencies { api("com.google.guava:guava:33.7.1-jre") api("com.google.code.gson:gson:2.14.0") + api("net.kyori:adventure-text-logger-slf4j:5.2.0") + api("org.slf4j:slf4j-api:2.0.17") compileOnlyApi("org.jetbrains:annotations:26.1.0") } \ No newline at end of file diff --git a/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginData.java b/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginData.java index 177168c7..f7ef7636 100644 --- a/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginData.java +++ b/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginData.java @@ -18,7 +18,6 @@ import java.io.IOException; import java.nio.file.Path; import java.util.*; -import java.util.logging.Level; public class PluginData { private final String pluginName; @@ -170,7 +169,7 @@ public boolean checkForUpdate() { latestVersion = fetchedVersion.version(); sourceContext = fetchedVersion.sourceContext(); } catch (InvalidVersionFormatException e) { - UpdaterConstants.LOGGER.severe("Failed to read latest version for '%s': %s".formatted(this.pluginName, e.getMessage())); + UpdaterConstants.LOGGER.error("Failed to read latest version for {}: {}", this.pluginName, e.getMessage()); return false; } @@ -179,7 +178,7 @@ public boolean checkForUpdate() { VersionComparator comparator = versionComparator().orElse(sourceContext.sourceData().defaultComparator()); versionDifference = comparator.compare(this.currentVersion, latestVersion); } catch (InvalidVersionFormatException e) { - UpdaterConstants.LOGGER.severe("Failed to compare versions for '%s': %s".formatted(this.pluginName, e.getMessage())); + UpdaterConstants.LOGGER.error("Failed to compare versions for {}: {}", this.pluginName, e.getMessage()); return false; } @@ -209,8 +208,12 @@ public boolean downloadUpdate(Path destinationDir) { prepareDownloadableRelease() .downloadTo(destinationDir); return true; - } catch (IOException | InterruptedException e) { - UpdaterConstants.LOGGER.log(Level.SEVERE, "Failed to download update for plugin '" + this.pluginName + "'.", e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + UpdaterConstants.LOGGER.error("Failed to download update for plugin '{}'.", this.pluginName, e); + return false; + } catch (IOException e) { + UpdaterConstants.LOGGER.error("Failed to download update for plugin '{}'.", this.pluginName, e); return false; } } @@ -225,9 +228,12 @@ private T attemptOnSources(SourceSupplier supplier) throws FailedAttempts try { return supplier.apply(new SourceContext(source, sourceData)); } catch (InvalidHttpResponse e) { - UpdaterConstants.LOGGER.severe(e.getMessage()); - } catch (Throwable e) { - UpdaterConstants.LOGGER.log(Level.SEVERE, e.getMessage(), e); + UpdaterConstants.LOGGER.error(e.getMessage()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + UpdaterConstants.LOGGER.error("Thread interrupted while fetching data from source '{}' for plugin '{}'.", sourceData.sourceName(), this.pluginName, e); + } catch (Exception e) { + UpdaterConstants.LOGGER.error("Failed to fetch data from source '{}' for plugin '{}'.", sourceData.sourceName(), this.pluginName, e); } } diff --git a/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginInfo.java b/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginInfo.java index b4df5a66..4cd00af5 100644 --- a/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginInfo.java +++ b/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginInfo.java @@ -1,9 +1,9 @@ package org.lushplugins.pluginupdater.api.updater; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.logging.Logger; public interface PluginInfo { @@ -25,5 +25,5 @@ public interface PluginInfo { /** * @return The plugin's logger instance */ - Logger getLogger(); + ComponentLogger getComponentLogger(); } diff --git a/common/api/src/main/java/org/lushplugins/pluginupdater/api/util/UpdaterConstants.java b/common/api/src/main/java/org/lushplugins/pluginupdater/api/util/UpdaterConstants.java index 2b76f453..6e742a37 100644 --- a/common/api/src/main/java/org/lushplugins/pluginupdater/api/util/UpdaterConstants.java +++ b/common/api/src/main/java/org/lushplugins/pluginupdater/api/util/UpdaterConstants.java @@ -1,38 +1,9 @@ package org.lushplugins.pluginupdater.api.util; import com.google.gson.Gson; - -import java.util.logging.*; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; public class UpdaterConstants { - public static final Logger LOGGER = Logger.getLogger("PluginUpdater"); + public static ComponentLogger LOGGER = ComponentLogger.logger("PluginUpdater"); public static final Gson GSON = new Gson(); - - static { - for (Handler handler : LOGGER.getHandlers()) { - LOGGER.removeHandler(handler); - } - - LOGGER.addHandler(new StreamHandler(System.out, new LogFormatter())); - LOGGER.setUseParentHandlers(false); - } - - private static class LogFormatter extends Formatter { - private static final String RESET = "\u001B[0m"; - private static final String YELLOW = "\u001B[33m"; - private static final String RED = "\u001B[31m"; - - @Override - public String format(LogRecord record) { - String message = "[%s] [%s] %s".formatted(record.getLevel(), LOGGER.getName(), record.getMessage()); - - if (record.getLevel() == Level.WARNING) { - message = YELLOW + message + RESET; - } else if (record.getLevel() == Level.SEVERE) { - message = RED + message + RESET; - } - - return message + System.lineSeparator(); - } - } } diff --git a/common/api/src/main/java/org/lushplugins/pluginupdater/api/version/DownloadableRelease.java b/common/api/src/main/java/org/lushplugins/pluginupdater/api/version/DownloadableRelease.java index cafc65c2..a87b28c5 100644 --- a/common/api/src/main/java/org/lushplugins/pluginupdater/api/version/DownloadableRelease.java +++ b/common/api/src/main/java/org/lushplugins/pluginupdater/api/version/DownloadableRelease.java @@ -60,7 +60,7 @@ public void downloadTo(Path destinationDir) throws IOException, InterruptedExcep // Ensures update folder exists Files.createDirectories(downloadPath.getParent()); - UpdaterConstants.LOGGER.info("Saving '" + fileName + "' to '" + downloadPath.toAbsolutePath() + "'"); + UpdaterConstants.LOGGER.info("Saving '{}' to '{}'", fileName, downloadPath.toAbsolutePath()); HttpResponse downloadResponse = client.send( request, HttpResponse.BodyHandlers.ofFile(downloadPath) diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java index c91e864d..be27cc81 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java @@ -20,7 +20,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; -import java.util.logging.Level; import java.util.stream.Collectors; public class UpdaterImpl { @@ -127,8 +126,8 @@ public CompletableFuture> collectUnknownPlugins() { List foundPluginData; try { foundPluginData = collector.collect(unknownPlugins.values()); - } catch (Throwable e) { - updaterPlugin.getLogger().log(Level.WARNING, "Caught exception whilst collecting unknown plugin data: ", e); + } catch (Exception e) { + updaterPlugin.getComponentLogger().warn("Caught exception whilst collecting unknown plugin data: ", e); continue; } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/collector/ModrinthCollector.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/collector/ModrinthCollector.java index b806f91f..df12c64d 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/collector/ModrinthCollector.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/collector/ModrinthCollector.java @@ -16,7 +16,6 @@ import java.io.IOException; import java.net.http.HttpResponse; import java.util.*; -import java.util.logging.Level; public record ModrinthCollector(UpdaterImpl updater) implements PluginDataCollector { @@ -34,7 +33,7 @@ public List collect(Collection plugins) { hash = Files.asByteSource(pluginFile).hash(Hashing.sha512()); pluginHashes.put(hash.toString(), unknownPlugin); } catch (IOException e) { - updater.updaterPlugin().getLogger().log(Level.WARNING, "Caught error whilst hashing plugin file: ", e); + updater.updaterPlugin().getComponentLogger().warn("Caught error whilst hashing plugin file: ", e); } } @@ -49,13 +48,17 @@ public List collect(Collection plugins) { HttpResponse response; try { response = HttpUtil.sendRequest(String.format("%s/version_files", ModrinthSource.ENDPOINT.url()), payload); - } catch (IOException | InterruptedException e) { - updater.updaterPlugin().getLogger().log(Level.WARNING, "Caught error whilst getting project data from hashes: ", e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + updater.updaterPlugin().getComponentLogger().warn("Caught error whilst getting project data from hashes: ", e); + return Collections.emptyList(); + } catch (IOException e) { + updater.updaterPlugin().getComponentLogger().warn("Caught error whilst getting project data from hashes: ", e); return Collections.emptyList(); } if (response.statusCode() != 200) { - updater.updaterPlugin().getLogger().log(Level.WARNING, "Received invalid response code (" + response.statusCode() + ") whilst getting project data from hashes."); + updater.updaterPlugin().getComponentLogger().warn("Received invalid response code ({}) whilst getting project data from hashes.", response.statusCode()); return Collections.emptyList(); } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/command/UpdaterCommand.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/command/UpdaterCommand.java index a1ca125c..90a32ecb 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/command/UpdaterCommand.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/command/UpdaterCommand.java @@ -2,9 +2,9 @@ import org.lushplugins.pluginupdater.api.updater.PluginData; import org.lushplugins.pluginupdater.api.updater.PluginInfo; +import org.lushplugins.pluginupdater.common.UpdaterImpl; import org.lushplugins.pluginupdater.common.command.annotation.CommandPermission; import org.lushplugins.pluginupdater.common.command.annotation.PluginName; -import org.lushplugins.pluginupdater.common.UpdaterImpl; import org.lushplugins.pluginupdater.common.updater.UpdateHandler; import revxrsal.commands.annotation.Subcommand; import revxrsal.commands.annotation.Switch; @@ -13,7 +13,6 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; @SuppressWarnings("unused") public record UpdaterCommand(UpdaterImpl updater) implements OrphanCommand { @@ -23,8 +22,8 @@ public record UpdaterCommand(UpdaterImpl updater) implements OrphanCommand { public String reload(@Switch("skip-check") boolean skipCheck) { try { updater.config().reload(skipCheck); - } catch (Throwable e) { - updater.updaterPlugin().getLogger().log(Level.SEVERE, "Caught error whilst reloading: ", e); + } catch (Exception e) { + updater.updaterPlugin().getComponentLogger().error("Caught error whilst reloading: ", e); return "<#ff6969>Something went wrong whilst reloading the plugin, check the console for errors"; } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java index 93d4487a..ca737c39 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java @@ -6,15 +6,14 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lushplugins.pluginupdater.api.updater.PluginData; -import org.lushplugins.pluginupdater.common.config.deserializer.PluginDataDeserializer; import org.lushplugins.pluginupdater.common.UpdaterImpl; +import org.lushplugins.pluginupdater.common.config.deserializer.PluginDataDeserializer; import org.lushplugins.pluginupdater.common.updater.UpdateHandler; import org.lushplugins.pluginupdater.common.util.ConfigUtil; import java.io.IOException; import java.nio.file.Files; import java.util.*; -import java.util.logging.Level; import java.util.stream.Collectors; public class ConfigManager { @@ -42,7 +41,7 @@ public void reload(boolean skipCheck) { boolean checkOnReload = ConfigUtil.getOrAliasOrElse( config, "check-updates-on-reload", "check-updates-on-start", true, - () -> updater.updaterPlugin().getLogger().log(Level.WARNING, "Deprecated: The config section 'check-updates-on-start' has been renamed to 'check-updates-on-reload'") + () -> updater.updaterPlugin().getComponentLogger().warn("Deprecated: The config section 'check-updates-on-start' has been renamed to 'check-updates-on-reload'") ); this.allowDownloads = config.getOrElse("allow-downloads", true); diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/PluginDataDeserializer.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/PluginDataDeserializer.java index ee193618..e6487fcb 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/PluginDataDeserializer.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/PluginDataDeserializer.java @@ -13,7 +13,6 @@ import java.util.Collections; import java.util.List; -import java.util.logging.Level; public class PluginDataDeserializer { @@ -51,8 +50,8 @@ public static PluginData deserialize(PluginInfo pluginInfo, Config config) { .build(); } } catch (Exception e) { - UpdaterConstants.LOGGER.log(Level.SEVERE, "Caught error whilst reading data for '%s'" - .formatted(pluginInfo.getName()), e); + UpdaterConstants.LOGGER.error("Caught error whilst reading data for '{}'", + pluginInfo.getName(), e); } return null; diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/SourceDataDeserializer.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/SourceDataDeserializer.java index db3de0cb..6cb2ff64 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/SourceDataDeserializer.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/SourceDataDeserializer.java @@ -8,13 +8,12 @@ import java.util.Collections; import java.util.List; -import java.util.logging.Level; public class SourceDataDeserializer { public static SourceData deserialize(Config config) { String source = ConfigUtil.getOrAlias(config, "source", "platform", - () -> UpdaterConstants.LOGGER.log(Level.WARNING, "Deprecated: The config option 'updater' has been renamed to 'source'")); + () -> UpdaterConstants.LOGGER.warn("Deprecated: The config option 'updater' has been renamed to 'source'")); return switch (source) { case GeyserSource.NAME -> geyserSourceData(config); diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/platform/UpdaterPlugin.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/platform/UpdaterPlugin.java index 8febc4eb..3ab9db9b 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/platform/UpdaterPlugin.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/platform/UpdaterPlugin.java @@ -1,10 +1,10 @@ package org.lushplugins.pluginupdater.common.platform; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.lushplugins.pluginupdater.api.updater.PluginInfo; import java.io.InputStream; import java.nio.file.Path; -import java.util.logging.Logger; public interface UpdaterPlugin { @@ -16,5 +16,5 @@ public interface UpdaterPlugin { InputStream getResourceStream(PluginInfo pluginInfo, String path); - Logger getLogger(); + ComponentLogger getComponentLogger(); } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java index 78db3afb..875665b6 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java @@ -7,8 +7,10 @@ import java.io.IOException; import java.util.*; -import java.util.concurrent.*; -import java.util.logging.Level; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; public class UpdateHandler { private final UpdaterImpl updater; @@ -35,7 +37,8 @@ public boolean shutdown() { this.threads.shutdown(); return this.threads.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { - e.printStackTrace(); + Thread.currentThread().interrupt(); + updater.updaterPlugin().getComponentLogger().error("Failed to shutdown update thread.", e); return false; } } @@ -96,7 +99,7 @@ private void processQueue() { pluginData.setCheckRan(true); break; } catch (Exception e) { - updater.updaterPlugin().getLogger().log(Level.SEVERE, e.getMessage(), e); + updater.updaterPlugin().getComponentLogger().error("Failed update checking.", e); } String sourceNames = String.join(", ", pluginData.sourceData().stream().map(SourceData::sourceName).toList()); diff --git a/platform/cli/build.gradle.kts b/platform/cli/build.gradle.kts index 2f4e5c21..d49a06d5 100644 --- a/platform/cli/build.gradle.kts +++ b/platform/cli/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { implementation("net.kyori:adventure-text-serializer-ansi:5.2.0") api("com.electronwill.night-config:json:3.9.0") implementation("org.jline:jline:4.4.3") + implementation("org.slf4j:slf4j-simple:2.0.18") } tasks { diff --git a/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/PluginUpdaterCLI.java b/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/PluginUpdaterCLI.java index 74b08a53..d5003b69 100644 --- a/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/PluginUpdaterCLI.java +++ b/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/PluginUpdaterCLI.java @@ -1,5 +1,7 @@ package org.lushplugins.pluginupdater.cli; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; +import org.jspecify.annotations.NonNull; import org.lushplugins.pluginupdater.api.source.SourceRegistry; import org.lushplugins.pluginupdater.api.source.type.GeyserSource; import org.lushplugins.pluginupdater.api.source.type.HangarSource; @@ -23,8 +25,6 @@ import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.logging.Level; -import java.util.logging.Logger; public class PluginUpdaterCLI implements UpdaterPlugin { private final Platform platform; @@ -74,7 +74,7 @@ public InputStream getResourceStream(PluginInfo pluginInfo, String path) { } @Override - public Logger getLogger() { + public @NonNull ComponentLogger getComponentLogger() { return UpdaterConstants.LOGGER; } @@ -118,7 +118,7 @@ public static void main(String[] args) { ) ); } catch (Exception e) { - UpdaterConstants.LOGGER.log(Level.WARNING, "An error occurred while running the PluginUpdater CLI", e); + UpdaterConstants.LOGGER.warn("An error occurred while running the PluginUpdater CLI", e); } } diff --git a/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/platform/CLIPlatform.java b/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/platform/CLIPlatform.java index 469ba1d8..16a1f191 100644 --- a/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/platform/CLIPlatform.java +++ b/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/platform/CLIPlatform.java @@ -17,7 +17,6 @@ import java.util.function.UnaryOperator; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.logging.Level; import java.util.stream.Collectors; public class CLIPlatform implements UpdaterPlatform { @@ -50,7 +49,7 @@ public CLIPlatform(PluginUpdaterCLI cli) { fallbackInfoParser = fallbackInfoParser.getFallbackInfoParser(); } } catch (IOException e) { - cli.getLogger().log(Level.SEVERE, "Failed to interpret jar file for " + path, e); + cli.getComponentLogger().error("Failed to interpret jar file for {}", path, e); } return null; @@ -93,7 +92,7 @@ public void sendActionBar(Object user, String message) {} @Override public void broadcastMessage(Collection users, String message) { - UpdaterConstants.LOGGER.log(Level.INFO, MiniMessage.miniMessage().stripTags(message)); + UpdaterConstants.LOGGER.info(MiniMessage.miniMessage().deserialize(message)); } @Override diff --git a/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/plugin/CLIPluginInfo.java b/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/plugin/CLIPluginInfo.java index e81b7e3d..54c91557 100644 --- a/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/plugin/CLIPluginInfo.java +++ b/platform/cli/src/main/java/org/lushplugins/pluginupdater/cli/plugin/CLIPluginInfo.java @@ -1,11 +1,11 @@ package org.lushplugins.pluginupdater.cli.plugin; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.jetbrains.annotations.Nullable; import org.lushplugins.pluginupdater.api.updater.PluginInfo; import org.lushplugins.pluginupdater.api.util.UpdaterConstants; import java.io.File; -import java.util.logging.Logger; public record CLIPluginInfo(String name, String version, @Nullable File file) implements PluginInfo { @@ -25,7 +25,7 @@ public String getVersion() { } @Override - public Logger getLogger() { + public ComponentLogger getComponentLogger() { return UpdaterConstants.LOGGER; } } diff --git a/platform/paper-api/src/main/java/org/lushplugins/pluginupdater/paper/api/plugin/PaperPluginInfo.java b/platform/paper-api/src/main/java/org/lushplugins/pluginupdater/paper/api/plugin/PaperPluginInfo.java index fc344191..883bb14a 100644 --- a/platform/paper-api/src/main/java/org/lushplugins/pluginupdater/paper/api/plugin/PaperPluginInfo.java +++ b/platform/paper-api/src/main/java/org/lushplugins/pluginupdater/paper/api/plugin/PaperPluginInfo.java @@ -1,5 +1,6 @@ package org.lushplugins.pluginupdater.paper.api.plugin; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -10,8 +11,6 @@ import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.logging.Level; -import java.util.logging.Logger; public record PaperPluginInfo(Plugin plugin) implements PluginInfo { @@ -33,13 +32,13 @@ public String getName() { return (File) method.invoke(plugin); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - UpdaterConstants.LOGGER.log(Level.WARNING, "Caught error whilst getting plugin file: ", e); + UpdaterConstants.LOGGER.warn("Caught error whilst getting plugin file: ", e); return null; } } @Override - public Logger getLogger() { - return plugin.getLogger(); + public ComponentLogger getComponentLogger() { + return plugin.getComponentLogger(); } } diff --git a/platform/paper-plugin/src/main/java/org/lushplugins/pluginupdater/paper/PaperUpdaterPlugin.java b/platform/paper-plugin/src/main/java/org/lushplugins/pluginupdater/paper/PaperUpdaterPlugin.java index ba4d42de..8c72554e 100644 --- a/platform/paper-plugin/src/main/java/org/lushplugins/pluginupdater/paper/PaperUpdaterPlugin.java +++ b/platform/paper-plugin/src/main/java/org/lushplugins/pluginupdater/paper/PaperUpdaterPlugin.java @@ -1,10 +1,13 @@ package org.lushplugins.pluginupdater.paper; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; import org.jspecify.annotations.NonNull; import org.lushplugins.pluginupdater.api.updater.PluginInfo; import org.lushplugins.pluginupdater.api.util.DownloadLogger; +import org.lushplugins.pluginupdater.api.util.UpdaterConstants; import org.lushplugins.pluginupdater.common.UpdaterImpl; import org.lushplugins.pluginupdater.common.collector.CommonPluginCollector; import org.lushplugins.pluginupdater.common.collector.ModrinthCollector; @@ -17,7 +20,6 @@ import org.lushplugins.pluginupdater.paper.collector.SpigotCollector; import org.lushplugins.pluginupdater.paper.command.PaperCommandHandler; import org.lushplugins.pluginupdater.paper.listener.PlayerListener; -import org.bukkit.plugin.java.JavaPlugin; import java.io.File; import java.io.InputStream; @@ -34,6 +36,7 @@ public final class PaperUpdaterPlugin extends JavaPlugin implements UpdaterPlugi public void onLoad() { PaperUpdater.populateRegistries(); plugin = this; + UpdaterConstants.LOGGER = getComponentLogger(); } @Override @@ -95,4 +98,9 @@ public InputStream getResourceStream(PluginInfo pluginInfo, String path) { public static PaperUpdaterPlugin getInstance() { return plugin; } + + @Override + public @NonNull ComponentLogger getComponentLogger() { + return super.getComponentLogger(); + } } diff --git a/platform/paper-plugin/src/main/java/org/lushplugins/pluginupdater/paper/collector/SpigotCollector.java b/platform/paper-plugin/src/main/java/org/lushplugins/pluginupdater/paper/collector/SpigotCollector.java index 0c532ac8..9bd032cb 100644 --- a/platform/paper-plugin/src/main/java/org/lushplugins/pluginupdater/paper/collector/SpigotCollector.java +++ b/platform/paper-plugin/src/main/java/org/lushplugins/pluginupdater/paper/collector/SpigotCollector.java @@ -5,19 +5,17 @@ import com.google.gson.JsonParser; import org.jetbrains.annotations.Nullable; import org.lushplugins.pluginupdater.api.source.type.SpigotSource; +import org.lushplugins.pluginupdater.api.updater.PluginData; import org.lushplugins.pluginupdater.api.updater.PluginInfo; +import org.lushplugins.pluginupdater.api.util.HttpUtil; import org.lushplugins.pluginupdater.common.UpdaterImpl; import org.lushplugins.pluginupdater.common.collector.PluginDataCollector; -import org.lushplugins.pluginupdater.api.updater.PluginData; -import org.lushplugins.pluginupdater.api.util.HttpUtil; -import org.lushplugins.pluginupdater.api.util.UpdaterConstants; import java.io.IOException; import java.net.http.HttpResponse; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.logging.Level; public record SpigotCollector(UpdaterImpl updater) implements PluginDataCollector { @@ -38,8 +36,12 @@ public List collect(Collection plugins) { HttpResponse response; try { response = HttpUtil.sendRequest(String.format("%s/search/resources/%s", SpigotSource.ENDPOINT.url(), unknownPlugin.getName())); - } catch (IOException | InterruptedException e) { - updater.updaterPlugin().getLogger().log(Level.WARNING, "Caught error whilst searching for project on spiget: ", e); + } catch (IOException e) { + updater.updaterPlugin().getComponentLogger().warn("Caught error whilst searching for project on spiget: ", e); + return null; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + updater.updaterPlugin().getComponentLogger().warn("Caught error whilst searching for project on spiget: ", e); return null; } @@ -48,7 +50,7 @@ public List collect(Collection plugins) { } if (response.statusCode() != 200) { - updater.updaterPlugin().getLogger().log(Level.WARNING, "Received invalid response code (%s) whilst searching for project on spiget (%s)".formatted(response.statusCode(), response.uri())); + updater.updaterPlugin().getComponentLogger().warn("Received invalid response code ({}) whilst searching for project on spiget ({})", response.statusCode(), response.uri()); return null; } diff --git a/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/VelocityUpdater.java b/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/VelocityUpdater.java index c865e2ea..c3ff178c 100644 --- a/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/VelocityUpdater.java +++ b/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/VelocityUpdater.java @@ -3,6 +3,7 @@ import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.lushplugins.pluginupdater.api.source.SourceRegistry; import org.lushplugins.pluginupdater.api.source.type.GeyserSource; import org.lushplugins.pluginupdater.api.source.type.HangarSource; @@ -15,7 +16,6 @@ import org.lushplugins.pluginupdater.velocity.api.util.VelocityUtil; import java.util.List; -import java.util.logging.Logger; public class VelocityUpdater { private static boolean registriesPopulated = false; @@ -32,7 +32,7 @@ public static void populateRegistries(ProxyServer server) { SourceRegistry.register(new SpigotSource(null)); } - public static Updater.Builder builder(ProxyServer server, PluginContainer plugin, Logger logger) { + public static Updater.Builder builder(ProxyServer server, PluginContainer plugin, ComponentLogger logger) { populateRegistries(server); return Updater.builder(new VelocityUpdaterPlatform(server, logger), new VelocityPluginInfo(plugin, logger)) diff --git a/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/platform/VelocityUpdaterPlatform.java b/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/platform/VelocityUpdaterPlatform.java index a2cadf73..404882fd 100644 --- a/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/platform/VelocityUpdaterPlatform.java +++ b/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/platform/VelocityUpdaterPlatform.java @@ -4,6 +4,7 @@ import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import net.kyori.adventure.text.minimessage.MiniMessage; import org.jetbrains.annotations.Nullable; import org.lushplugins.pluginupdater.api.platform.UpdaterPlatform; @@ -13,13 +14,12 @@ import java.util.Collection; import java.util.List; import java.util.Optional; -import java.util.logging.Logger; public class VelocityUpdaterPlatform implements UpdaterPlatform { private final ProxyServer server; - private final Logger logger; + private final ComponentLogger logger; - public VelocityUpdaterPlatform(ProxyServer server, Logger logger) { + public VelocityUpdaterPlatform(ProxyServer server, ComponentLogger logger) { this.server = server; this.logger = logger; } diff --git a/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/plugin/VelocityPluginInfo.java b/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/plugin/VelocityPluginInfo.java index 2c227ad5..f22cd035 100644 --- a/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/plugin/VelocityPluginInfo.java +++ b/platform/velocity-api/src/main/java/org/lushplugins/pluginupdater/velocity/api/plugin/VelocityPluginInfo.java @@ -1,15 +1,15 @@ package org.lushplugins.pluginupdater.velocity.api.plugin; import com.velocitypowered.api.plugin.PluginContainer; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.jetbrains.annotations.Nullable; import org.lushplugins.pluginupdater.api.updater.PluginInfo; import org.lushplugins.pluginupdater.api.util.UpdaterConstants; import java.io.File; import java.nio.file.Path; -import java.util.logging.Logger; -public record VelocityPluginInfo(PluginContainer container, @Nullable Logger logger) implements PluginInfo { +public record VelocityPluginInfo(PluginContainer container, @Nullable ComponentLogger logger) implements PluginInfo { @Override public String getName() { @@ -28,7 +28,7 @@ public String getVersion() { } @Override - public Logger getLogger() { + public ComponentLogger getComponentLogger() { return logger != null ? logger : UpdaterConstants.LOGGER; } } diff --git a/platform/velocity-plugin/src/main/java/org/lushplugins/pluginupdater/velocity/VelocityUpdaterPlugin.java b/platform/velocity-plugin/src/main/java/org/lushplugins/pluginupdater/velocity/VelocityUpdaterPlugin.java index 16de2119..8d9bfb5f 100644 --- a/platform/velocity-plugin/src/main/java/org/lushplugins/pluginupdater/velocity/VelocityUpdaterPlugin.java +++ b/platform/velocity-plugin/src/main/java/org/lushplugins/pluginupdater/velocity/VelocityUpdaterPlugin.java @@ -9,8 +9,10 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.lushplugins.pluginupdater.api.updater.PluginInfo; import org.lushplugins.pluginupdater.api.util.DownloadLogger; +import org.lushplugins.pluginupdater.api.util.UpdaterConstants; import org.lushplugins.pluginupdater.common.UpdaterImpl; import org.lushplugins.pluginupdater.common.collector.CommonPluginCollector; import org.lushplugins.pluginupdater.common.collector.ModrinthCollector; @@ -27,7 +29,6 @@ import java.io.InputStream; import java.nio.file.Path; import java.util.List; -import java.util.logging.Logger; @Plugin( id = "pluginupdater", @@ -38,13 +39,14 @@ public class VelocityUpdaterPlugin implements UpdaterPlugin { private static VelocityUpdaterPlugin instance; private final ProxyServer server; - private final Logger logger; + private final ComponentLogger logger; private final Path dataFolder; private UpdaterImpl updater; private VelocityUpdaterAPI api; @Inject - public VelocityUpdaterPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataFolder) { + public VelocityUpdaterPlugin(ProxyServer server, ComponentLogger logger, @DataDirectory Path dataFolder) { + UpdaterConstants.LOGGER = logger; VelocityUpdater.populateRegistries(server); instance = this; @@ -113,7 +115,7 @@ public InputStream getResourceStream(PluginInfo pluginInfo, String path) { } @Override - public Logger getLogger() { + public ComponentLogger getComponentLogger() { return logger; } diff --git a/tests/common-plugins-test/src/main/java/org/lushplugins/pluginupdater/tests/commonplugins/CommonPluginsTest.java b/tests/common-plugins-test/src/main/java/org/lushplugins/pluginupdater/tests/commonplugins/CommonPluginsTest.java index c29bd583..69becdbe 100644 --- a/tests/common-plugins-test/src/main/java/org/lushplugins/pluginupdater/tests/commonplugins/CommonPluginsTest.java +++ b/tests/common-plugins-test/src/main/java/org/lushplugins/pluginupdater/tests/commonplugins/CommonPluginsTest.java @@ -17,7 +17,6 @@ import java.util.Comparator; import java.util.List; import java.util.Objects; -import java.util.logging.Level; public class CommonPluginsTest { @@ -25,7 +24,7 @@ public class CommonPluginsTest { Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { StringWriter sw = new StringWriter(); throwable.printStackTrace(new PrintWriter(sw)); - UpdaterConstants.LOGGER.severe(sw.toString()); + UpdaterConstants.LOGGER.error(sw.toString()); }); } @@ -56,12 +55,11 @@ public static void runTest(String pluginsResource) { // We fetch all latest versions and then download all jars // This is to ensure that each process is handled in batches for (PluginData pluginData : undownloadedPluginData) { - cli.getLogger().info("Fetching %s's latest version" - .formatted(pluginData.pluginName())); + cli.getComponentLogger().info("Fetching {}'s latest version", pluginData.pluginName()); try { pluginData.latestVersion(pluginData.fetchLatestVersion().version()); } catch (RuntimeException e) { - cli.getLogger().severe(e.getMessage()); + cli.getComponentLogger().error(e.getMessage()); passing = false; } } @@ -70,8 +68,8 @@ public static void runTest(String pluginsResource) { for (PluginData pluginData : undownloadedPluginData) { try { pluginData.downloadUpdate(downloadDir); - } catch (Throwable e) { - cli.getLogger().log(Level.SEVERE, "Failed to download latest version of " + pluginData.pluginName(), e); + } catch (Exception e) { + cli.getComponentLogger().error("Failed to download latest version of {}", pluginData.pluginName(), e); passing = false; } } @@ -83,8 +81,7 @@ public static void runTest(String pluginsResource) { String pluginName = entry.getKey(); PluginInfo pluginInfo = platform.getPlugin(pluginName); if (pluginInfo == null) { - cli.getLogger().log(Level.WARNING, "Failed to find plugin jar for %s" - .formatted(pluginName)); + cli.getComponentLogger().warn("Failed to find plugin jar for {}", pluginName); return null; } From a78c3da49ee6a66f2dd335f00227ab1343995e70 Mon Sep 17 00:00:00 2001 From: Oak Date: Tue, 15 Sep 2026 21:40:16 +0100 Subject: [PATCH 04/15] Removed outdated test file --- .../paper/test/VelocityUpdaterTests.java | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 platform/velocity-plugin/src/test/java/org/lushplugins/pluginupdater/paper/test/VelocityUpdaterTests.java diff --git a/platform/velocity-plugin/src/test/java/org/lushplugins/pluginupdater/paper/test/VelocityUpdaterTests.java b/platform/velocity-plugin/src/test/java/org/lushplugins/pluginupdater/paper/test/VelocityUpdaterTests.java deleted file mode 100644 index 0da1751a..00000000 --- a/platform/velocity-plugin/src/test/java/org/lushplugins/pluginupdater/paper/test/VelocityUpdaterTests.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.lushplugins.pluginupdater.paper.test; - -import org.junit.jupiter.api.Test; -import org.lushplugins.pluginupdater.tests.commonplugins.CommonPluginsTest; - -public class VelocityUpdaterTests { - - static { - System.setProperty("platform", "velocity"); - System.setProperty("server-version", "4.1.0"); - } - - @Test - public void test() { - CommonPluginsTest.runTest("common-plugins.yml"); - } -} From 0a8f5544e5574dcb86fcefac20c903ec22e15bb6 Mon Sep 17 00:00:00 2001 From: Oak Date: Wed, 16 Sep 2026 23:00:14 +0100 Subject: [PATCH 05/15] Add schedule-frequency config option to allow for scheduling update checks --- .../lushplugins/pluginupdater/common/UpdaterImpl.java | 9 +++++++++ .../pluginupdater/common/config/ConfigManager.java | 8 +++++++- .../pluginupdater/common/updater/UpdateHandler.java | 6 +++++- common/impl/src/main/resources/config.yml | 2 ++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java index be27cc81..3c18f2e7 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; public class UpdaterImpl { @@ -42,6 +43,14 @@ public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, Com config = new ConfigManager(this); config.reload(); + int delay = config.getScheduleFrequencyMins(); + if (delay > 0) { + updateHandler.scheduler().scheduleAtFixedRate(() -> { + updateHandler.queueUpdateChecks(config.getPlugins()); + updateHandler.queueBroadcastNotification(); + }, delay, delay, TimeUnit.MINUTES); + } + Lamp lamp = commandPlatform.prepareLamp() .permissionFactory(new CommandPermissionFactory(this)) .parameterTypes(parameterTypes -> parameterTypes diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java index ca737c39..7215d552 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java @@ -19,6 +19,7 @@ public class ConfigManager { private final UpdaterImpl updater; private boolean allowDownloads; + private int scheduleFrequencyMins; private final Map plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private final Set disabledPlugins = new HashSet<>(); private Messages messages; @@ -45,6 +46,7 @@ public void reload(boolean skipCheck) { ); this.allowDownloads = config.getOrElse("allow-downloads", true); + this.scheduleFrequencyMins = config.getOrElse("schedule-frequency", -1); Config messagesConfig = config.get("messages"); if (messagesConfig != null) { @@ -85,7 +87,7 @@ public void reload(boolean skipCheck) { if (checkOnReload && !skipCheck) { UpdateHandler updateHandler = updater.updateHandler(); - getPlugins().forEach(updateHandler::queueUpdateCheck); + updateHandler.queueUpdateChecks(getPlugins()); updateHandler.queueBroadcastNotification(); } }); @@ -101,6 +103,10 @@ public boolean shouldAllowDownloads() { return allowDownloads; } + public int getScheduleFrequencyMins() { + return scheduleFrequencyMins; + } + public boolean canRegisterPluginData(String pluginName) { return !plugins.containsKey(pluginName) && !disabledPlugins.contains(pluginName); } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java index 875665b6..541c1edf 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java @@ -22,7 +22,7 @@ public UpdateHandler(UpdaterImpl updater) { this.updater = updater; } - public ScheduledExecutorService getThreads() { + public ScheduledExecutorService scheduler() { return threads; } @@ -59,6 +59,10 @@ public ProcessingData queueUpdateCheck(String pluginName) { return processingData; } + public void queueUpdateChecks(Collection pluginNames) { + pluginNames.forEach(this::queueUpdateCheck); + } + public ProcessingData queueDownload(String pluginName) { ProcessingData processingData = new ProcessingData(updater, pluginName, ProcessingData.State.DOWNLOAD); queue(processingData); diff --git a/common/impl/src/main/resources/config.yml b/common/impl/src/main/resources/config.yml index 17571d3f..e4707db4 100644 --- a/common/impl/src/main/resources/config.yml +++ b/common/impl/src/main/resources/config.yml @@ -2,6 +2,8 @@ check-updates-on-reload: true # Set to 'false' to disable all download features of PluginUpdater (May require restart) allow-downloads: true +# Time in minutes that update checks should be scheduled (Set to '-1' to disable. Requires restart to change) +schedule-frequency: 60 # To learn how to configure plugins that require different sources check out the wiki: https://github.com/OakLoaf/PluginUpdater/wiki/PluginUpdater-Plugin plugins: From f4009635dc999600c825b47bd7ddffd8a5e6de68 Mon Sep 17 00:00:00 2001 From: Oak Date: Wed, 16 Sep 2026 23:06:04 +0100 Subject: [PATCH 06/15] Bumped ViaVersion in dev environment --- platform/paper-plugin/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/paper-plugin/build.gradle.kts b/platform/paper-plugin/build.gradle.kts index 650dbfda..e2081627 100644 --- a/platform/paper-plugin/build.gradle.kts +++ b/platform/paper-plugin/build.gradle.kts @@ -39,8 +39,8 @@ tasks { minecraftVersion("1.21.4") downloadPlugins { - modrinth("viaversion", "5.7.1") // ViaVersion - modrinth("viabackwards", "5.7.1") // ViaBackwards + modrinth("viaversion", "5.11.0") // ViaVersion + modrinth("viabackwards", "5.11.0") // ViaBackwards // The following plugins are intentionally outdated for testing purposes modrinth("djC8I9ui", "3.2.0") // LushRewards modrinth("discordsrv", "1.27.0") // DiscordSRV From d21f7e35938750b1e181ff22ee46515d4452253e Mon Sep 17 00:00:00 2001 From: Oak Date: Wed, 16 Sep 2026 23:19:11 +0100 Subject: [PATCH 07/15] Changed default Modrinth release channel to 'release' --- .../common/config/deserializer/SourceDataDeserializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/SourceDataDeserializer.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/SourceDataDeserializer.java index 6cb2ff64..0f2d8aa2 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/SourceDataDeserializer.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/SourceDataDeserializer.java @@ -77,7 +77,7 @@ public static ModrinthSource.Data modrinthSourceData(Config config) { .map(String::toLowerCase) .toList(); } else { - releaseChannels = ModrinthSource.ReleaseChannel.ALL; + releaseChannels = Collections.singletonList(ModrinthSource.ReleaseChannel.RELEASE); } return ModrinthSource.Data.builder() From 281445339ce3b289da5fd3c344d73dc5e8263aa5 Mon Sep 17 00:00:00 2001 From: Oak Date: Wed, 16 Sep 2026 23:21:51 +0100 Subject: [PATCH 08/15] Changed BlueMap modrinth source loader to paper --- platform/paper-plugin/src/main/resources/common-plugins.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/paper-plugin/src/main/resources/common-plugins.yml b/platform/paper-plugin/src/main/resources/common-plugins.yml index 97d991d7..b38f981f 100644 --- a/platform/paper-plugin/src/main/resources/common-plugins.yml +++ b/platform/paper-plugin/src/main/resources/common-plugins.yml @@ -4,6 +4,7 @@ BannerMaker: BlueMap: source: modrinth modrinth-project-id: swbUV1cr + loaders: paper CarbonChat: source: modrinth modrinth-project-id: QzooIsZI From 240b691acc9d346f5589eed28a77b4a491ea856d Mon Sep 17 00:00:00 2001 From: Zoriot Date: Tue, 18 Aug 2026 13:27:00 +0200 Subject: [PATCH 09/15] Add Discord webhook notifications for plugin downloads (#157) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement basic Discord webhook support to send notifications when plugins are successfully downloaded. Uses jdwebhooks 2.0.0 library with Discord's Components V2 API. Changes: - Add jdwebhooks 2.0.0 dependency to common/impl - Create DiscordWebhookNotifier class for sending webhook notifications - Add discord-webhook configuration section to config.yml (disabled by default) - Update ConfigManager to load and reload webhook settings - Integrate webhook notifications in UpdateHandler on successful downloads - Update UpdaterImpl to initialize and manage webhook notifier lifecycle Webhook notifications include: - Plugin name - Version change (old → new) - Update type (MAJOR, MINOR, PATCH, etc.) - Changelog link (if available) Users can enable by setting discord-webhook.enabled to true and providing a webhook-url in config.yml. Closes #157 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- common/impl/build.gradle.kts | 1 + .../pluginupdater/common/UpdaterImpl.java | 20 ++++ .../common/config/ConfigManager.java | 30 ++++++ .../notifier/DiscordWebhookNotifier.java | 96 +++++++++++++++++++ .../common/updater/UpdateHandler.java | 6 ++ common/impl/src/main/resources/config.yml | 5 + 6 files changed, 158 insertions(+) create mode 100644 common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebhookNotifier.java diff --git a/common/impl/build.gradle.kts b/common/impl/build.gradle.kts index 4e7af67f..78ab9bca 100644 --- a/common/impl/build.gradle.kts +++ b/common/impl/build.gradle.kts @@ -3,4 +3,5 @@ dependencies { api("io.github.revxrsal:lamp.common:4.0.0-rc.18") api("com.electronwill.night-config:yaml:3.9.0") + api("io.github.4drian3d:jdwebhooks:2.0.0") } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java index be27cc81..7c556f13 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java @@ -10,6 +10,7 @@ import org.lushplugins.pluginupdater.common.command.annotation.PluginName; import org.lushplugins.pluginupdater.common.command.response.StringMessageResponseHandler; import org.lushplugins.pluginupdater.common.config.ConfigManager; +import org.lushplugins.pluginupdater.common.notifier.DiscordWebhookNotifier; import org.lushplugins.pluginupdater.common.platform.CommandHandler; import org.lushplugins.pluginupdater.common.platform.UpdaterPlugin; import org.lushplugins.pluginupdater.common.updater.UpdateHandler; @@ -29,6 +30,7 @@ public class UpdaterImpl { private final List collectors; private final UpdateHandler updateHandler; private final ConfigManager config; + private DiscordWebhookNotifier discordWebhookNotifier; public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, CommandHandler commandPlatform, List collectors) { this.platform = platform; @@ -41,6 +43,13 @@ public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, Com config = new ConfigManager(this); config.reload(); + + // Initialize Discord webhook notifier + this.discordWebhookNotifier = new DiscordWebhookNotifier( + updaterPlugin.getComponentLogger(), + config.isDiscordWebhookEnabled(), + config.getDiscordWebhookUrl() + ); Lamp lamp = commandPlatform.prepareLamp() .permissionFactory(new CommandPermissionFactory(this)) @@ -83,6 +92,9 @@ public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, Com public void shutdown() { updateHandler.shutdown(); + if (discordWebhookNotifier != null) { + discordWebhookNotifier.close(); + } } public UpdaterPlatform platform() { @@ -109,6 +121,14 @@ public ConfigManager config() { return config; } + public DiscordWebhookNotifier discordWebhookNotifier() { + return discordWebhookNotifier; + } + + public void setDiscordWebhookNotifier(DiscordWebhookNotifier notifier) { + this.discordWebhookNotifier = notifier; + } + public CompletableFuture> collectUnknownPlugins() { return CompletableFuture.supplyAsync(() -> { Map unknownPlugins = platform.getPlugins().stream() diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java index ca737c39..e98ff4b5 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java @@ -8,6 +8,7 @@ import org.lushplugins.pluginupdater.api.updater.PluginData; import org.lushplugins.pluginupdater.common.UpdaterImpl; import org.lushplugins.pluginupdater.common.config.deserializer.PluginDataDeserializer; +import org.lushplugins.pluginupdater.common.notifier.DiscordWebhookNotifier; import org.lushplugins.pluginupdater.common.updater.UpdateHandler; import org.lushplugins.pluginupdater.common.util.ConfigUtil; @@ -22,6 +23,8 @@ public class ConfigManager { private final Map plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private final Set disabledPlugins = new HashSet<>(); private Messages messages; + private boolean discordWebhookEnabled; + private String discordWebhookUrl; public ConfigManager(UpdaterImpl updater) { this.updater = updater; @@ -46,6 +49,15 @@ public void reload(boolean skipCheck) { this.allowDownloads = config.getOrElse("allow-downloads", true); + Config discordConfig = config.get("discord-webhook"); + if (discordConfig != null) { + this.discordWebhookEnabled = discordConfig.getOrElse("enabled", false); + this.discordWebhookUrl = discordConfig.getOrElse("webhook-url", ""); + } else { + this.discordWebhookEnabled = false; + this.discordWebhookUrl = ""; + } + Config messagesConfig = config.get("messages"); if (messagesConfig != null) { this.messages = new Messages(messagesConfig); @@ -90,6 +102,16 @@ public void reload(boolean skipCheck) { } }); + // Reinitialize Discord webhook notifier with new config + if (updater.discordWebhookNotifier() != null) { + updater.discordWebhookNotifier().close(); + } + updater.setDiscordWebhookNotifier(new DiscordWebhookNotifier( + updater.updaterPlugin().getComponentLogger(), + this.discordWebhookEnabled, + this.discordWebhookUrl + )); + config.close(); } @@ -141,6 +163,14 @@ public String getMessage(String name, String def) { return messages.get(name, def); } + public boolean isDiscordWebhookEnabled() { + return discordWebhookEnabled; + } + + public String getDiscordWebhookUrl() { + return discordWebhookUrl; + } + public record Messages(Map messages) { diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebhookNotifier.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebhookNotifier.java new file mode 100644 index 00000000..b45430c4 --- /dev/null +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebhookNotifier.java @@ -0,0 +1,96 @@ +package org.lushplugins.pluginupdater.common.notifier; + +import io.github._4drian3d.jdwebhooks.component.Component; +import io.github._4drian3d.jdwebhooks.component.ContainerableComponent; +import io.github._4drian3d.jdwebhooks.webhook.WebHookClient; +import io.github._4drian3d.jdwebhooks.webhook.WebHookExecution; +import net.kyori.adventure.text.logger.slf4j.ComponentLogger; +import org.jetbrains.annotations.Nullable; +import org.lushplugins.pluginupdater.api.updater.PluginData; +import org.lushplugins.pluginupdater.api.version.Version; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class DiscordWebhookNotifier { + private final ComponentLogger logger; + private final WebHookClient webhookClient; + private final boolean enabled; + + public DiscordWebhookNotifier(ComponentLogger logger, boolean enabled, @Nullable String webhookUrl) { + this.logger = logger; + this.enabled = enabled && webhookUrl != null && !webhookUrl.isBlank(); + + if (this.enabled) { + this.webhookClient = WebHookClient.fromURL(webhookUrl); + } else { + this.webhookClient = null; + } + } + + public void notifyDownload(PluginData pluginData) { + if (!enabled || webhookClient == null) { + return; + } + + try { + Version currentVersion = pluginData.currentVersion(); + Optional latestVersionOpt = pluginData.latestVersion(); + + if (latestVersionOpt.isEmpty()) { + return; + } + + Version latestVersion = latestVersionOpt.get(); + String pluginName = pluginData.pluginName(); + + String versionString = String.format("%s → %s", + currentVersion.rawVersionString(), + latestVersion.rawVersionString() + ); + + List components = new ArrayList<>(); + + components.add(Component.textDisplay("**" + pluginName + " Updated**")); + + components.add(Component.textDisplay("**Version:** " + versionString)); + + String versionDiff = pluginData.versionDifference().name(); + if (!versionDiff.equals("UNKNOWN")) { + components.add(Component.textDisplay("**Update Type:** " + versionDiff)); + } + + pluginData.getChangelogUrl().ifPresent(s -> components.add(Component.textDisplay("**Changelog:** [View Changelog](" + s + ")"))); + + WebHookExecution webHook = WebHookExecution.builder() + .username("PluginUpdater") + .avatarURL("https://cdn.modrinth.com/data/IBSpJfbm/172c14d2cdb854064160fa627f9dd0043c1b79ee_96.webp") + .component( + Component.container() + .components(components) + .accentColor(0x66b04f) + .build() + ) + .build(); + + webhookClient.executeWebHook(webHook) + .whenComplete((response, throwable) -> { + int statusCode = response.statusCode(); + + if (throwable != null) { + logger.warn("Failed to send Discord webhook notification", throwable); + } else if (statusCode < 200 || statusCode >= 300) { + logger.warn("Discord webhook returned unsuccessful response. Status code: {}, response: {}", statusCode, response); + } + }); + + } catch (Exception e) { + logger.warn("Failed to send Discord webhook notification", e); + } + } + + public void close() { + // Might come handy in the future + } +} diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java index 875665b6..d02e2437 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java @@ -121,6 +121,12 @@ private void processQueue() { if (pluginData.downloadUpdate(updater.updaterPlugin().getDownloadDir())) { pluginData.versionDifference(VersionDifference.UNKNOWN); pluginData.setAlreadyDownloaded(true); + + // Send Discord webhook notification + if (updater.discordWebhookNotifier() != null) { + updater.discordWebhookNotifier().notifyDownload(pluginData); + } + processingData.getFuture().complete(true); break; } else { diff --git a/common/impl/src/main/resources/config.yml b/common/impl/src/main/resources/config.yml index 17571d3f..2484bfa7 100644 --- a/common/impl/src/main/resources/config.yml +++ b/common/impl/src/main/resources/config.yml @@ -3,6 +3,11 @@ check-updates-on-reload: true # Set to 'false' to disable all download features of PluginUpdater (May require restart) allow-downloads: true +# Discord webhook configuration for download notifications +discord-webhook: + enabled: false + webhook-url: "" + # To learn how to configure plugins that require different sources check out the wiki: https://github.com/OakLoaf/PluginUpdater/wiki/PluginUpdater-Plugin plugins: PluginUpdater: From 1e008e980a080b567cf4ebf26f2a337147092205 Mon Sep 17 00:00:00 2001 From: Zoriot Date: Thu, 17 Sep 2026 14:56:29 +0200 Subject: [PATCH 10/15] Refactor Discord webhook implementation for improved lifecycle management and config handling - Migrate `DiscordWebhookNotifier` to `DiscordWebHookNotifier` with improved error handling. - Update `ConfigManager` to streamline webhook configuration and initialization. - Replace the `isDiscordWebhookEnabled` flag with URL validation. - Revise `UpdateHandler` webhook invocation logic using `Optional`. - Improve lifecycle management by introducing `shutdown` for webhooks. - Adjust `UpdaterImpl` to handle webhook creation more robustly. --- common/impl/build.gradle.kts | 2 +- .../pluginupdater/common/UpdaterImpl.java | 39 ++++++++-------- .../common/config/ConfigManager.java | 36 +++++++-------- ...ifier.java => DiscordWebHookNotifier.java} | 44 ++++++++----------- .../common/updater/UpdateHandler.java | 7 +-- 5 files changed, 59 insertions(+), 69 deletions(-) rename common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/{DiscordWebhookNotifier.java => DiscordWebHookNotifier.java} (71%) diff --git a/common/impl/build.gradle.kts b/common/impl/build.gradle.kts index 78ab9bca..82f42641 100644 --- a/common/impl/build.gradle.kts +++ b/common/impl/build.gradle.kts @@ -3,5 +3,5 @@ dependencies { api("io.github.revxrsal:lamp.common:4.0.0-rc.18") api("com.electronwill.night-config:yaml:3.9.0") - api("io.github.4drian3d:jdwebhooks:2.0.0") + implementation("io.github.4drian3d:jdwebhooks:2.0.0") } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java index 7c556f13..61348ec0 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java @@ -10,16 +10,13 @@ import org.lushplugins.pluginupdater.common.command.annotation.PluginName; import org.lushplugins.pluginupdater.common.command.response.StringMessageResponseHandler; import org.lushplugins.pluginupdater.common.config.ConfigManager; -import org.lushplugins.pluginupdater.common.notifier.DiscordWebhookNotifier; +import org.lushplugins.pluginupdater.common.notifier.DiscordWebHookNotifier; import org.lushplugins.pluginupdater.common.platform.CommandHandler; import org.lushplugins.pluginupdater.common.platform.UpdaterPlugin; import org.lushplugins.pluginupdater.common.updater.UpdateHandler; import revxrsal.commands.Lamp; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; @@ -30,7 +27,7 @@ public class UpdaterImpl { private final List collectors; private final UpdateHandler updateHandler; private final ConfigManager config; - private DiscordWebhookNotifier discordWebhookNotifier; + private DiscordWebHookNotifier discordWebHookNotifier; public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, CommandHandler commandPlatform, List collectors) { this.platform = platform; @@ -43,13 +40,17 @@ public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, Com config = new ConfigManager(this); config.reload(); - - // Initialize Discord webhook notifier - this.discordWebhookNotifier = new DiscordWebhookNotifier( - updaterPlugin.getComponentLogger(), - config.isDiscordWebhookEnabled(), - config.getDiscordWebhookUrl() - ); + + if (config.getDiscordWebHookUrl() != null && !config.getDiscordWebHookUrl().isBlank()) { + try { + discordWebHookNotifier = new DiscordWebHookNotifier( + updaterPlugin.getComponentLogger(), + config.getDiscordWebHookUrl() + ); + } catch (Exception e) { + discordWebHookNotifier = null; + } + } Lamp lamp = commandPlatform.prepareLamp() .permissionFactory(new CommandPermissionFactory(this)) @@ -92,8 +93,8 @@ public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, Com public void shutdown() { updateHandler.shutdown(); - if (discordWebhookNotifier != null) { - discordWebhookNotifier.close(); + if (discordWebHookNotifier != null) { + discordWebHookNotifier.shutdown(); } } @@ -121,12 +122,12 @@ public ConfigManager config() { return config; } - public DiscordWebhookNotifier discordWebhookNotifier() { - return discordWebhookNotifier; + public Optional discordWebHookNotifier() { + return Optional.ofNullable(discordWebHookNotifier); } - public void setDiscordWebhookNotifier(DiscordWebhookNotifier notifier) { - this.discordWebhookNotifier = notifier; + public void discordWebHookNotifier(DiscordWebHookNotifier notifier) { + this.discordWebHookNotifier = notifier; } public CompletableFuture> collectUnknownPlugins() { diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java index e98ff4b5..1f4a3b4f 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java @@ -8,7 +8,7 @@ import org.lushplugins.pluginupdater.api.updater.PluginData; import org.lushplugins.pluginupdater.common.UpdaterImpl; import org.lushplugins.pluginupdater.common.config.deserializer.PluginDataDeserializer; -import org.lushplugins.pluginupdater.common.notifier.DiscordWebhookNotifier; +import org.lushplugins.pluginupdater.common.notifier.DiscordWebHookNotifier; import org.lushplugins.pluginupdater.common.updater.UpdateHandler; import org.lushplugins.pluginupdater.common.util.ConfigUtil; @@ -23,7 +23,6 @@ public class ConfigManager { private final Map plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private final Set disabledPlugins = new HashSet<>(); private Messages messages; - private boolean discordWebhookEnabled; private String discordWebhookUrl; public ConfigManager(UpdaterImpl updater) { @@ -51,10 +50,13 @@ public void reload(boolean skipCheck) { Config discordConfig = config.get("discord-webhook"); if (discordConfig != null) { - this.discordWebhookEnabled = discordConfig.getOrElse("enabled", false); - this.discordWebhookUrl = discordConfig.getOrElse("webhook-url", ""); + boolean discordWebhookEnabled = discordConfig.getOrElse("enabled", false); + if (!discordWebhookEnabled) { + discordWebhookUrl = ""; + } else { + this.discordWebhookUrl = discordConfig.getOrElse("webhook-url", ""); + } } else { - this.discordWebhookEnabled = false; this.discordWebhookUrl = ""; } @@ -102,15 +104,17 @@ public void reload(boolean skipCheck) { } }); - // Reinitialize Discord webhook notifier with new config - if (updater.discordWebhookNotifier() != null) { - updater.discordWebhookNotifier().close(); + updater.discordWebHookNotifier().ifPresent(DiscordWebHookNotifier::shutdown); + if (this.discordWebhookUrl != null && !this.discordWebhookUrl.isBlank()) { + try { + updater.discordWebHookNotifier(new DiscordWebHookNotifier( + updater.updaterPlugin().getComponentLogger(), + this.discordWebhookUrl + )); + } catch (Exception e) { + updater.discordWebHookNotifier(null); + } } - updater.setDiscordWebhookNotifier(new DiscordWebhookNotifier( - updater.updaterPlugin().getComponentLogger(), - this.discordWebhookEnabled, - this.discordWebhookUrl - )); config.close(); } @@ -163,11 +167,7 @@ public String getMessage(String name, String def) { return messages.get(name, def); } - public boolean isDiscordWebhookEnabled() { - return discordWebhookEnabled; - } - - public String getDiscordWebhookUrl() { + public String getDiscordWebHookUrl() { return discordWebhookUrl; } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebhookNotifier.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebHookNotifier.java similarity index 71% rename from common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebhookNotifier.java rename to common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebHookNotifier.java index b45430c4..15d1cf52 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebhookNotifier.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebHookNotifier.java @@ -5,60 +5,52 @@ import io.github._4drian3d.jdwebhooks.webhook.WebHookClient; import io.github._4drian3d.jdwebhooks.webhook.WebHookExecution; import net.kyori.adventure.text.logger.slf4j.ComponentLogger; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import org.lushplugins.pluginupdater.api.updater.PluginData; import org.lushplugins.pluginupdater.api.version.Version; +import org.lushplugins.pluginupdater.api.version.VersionDifference; import java.util.ArrayList; import java.util.List; import java.util.Optional; -public class DiscordWebhookNotifier { +public class DiscordWebHookNotifier { private final ComponentLogger logger; - private final WebHookClient webhookClient; - private final boolean enabled; + private final WebHookClient webHookClient; - public DiscordWebhookNotifier(ComponentLogger logger, boolean enabled, @Nullable String webhookUrl) { + public DiscordWebHookNotifier(ComponentLogger logger, @NotNull String webhookUrl) { this.logger = logger; - this.enabled = enabled && webhookUrl != null && !webhookUrl.isBlank(); - if (this.enabled) { - this.webhookClient = WebHookClient.fromURL(webhookUrl); - } else { - this.webhookClient = null; + try { + this.webHookClient = WebHookClient.fromURL(webhookUrl); + } catch (Exception e) { + logger.warn("Failed to create Discord webhook client. Webhook notifications will be disabled. Possible wrong url.", e); + throw e; } } public void notifyDownload(PluginData pluginData) { - if (!enabled || webhookClient == null) { - return; - } - try { Version currentVersion = pluginData.currentVersion(); - Optional latestVersionOpt = pluginData.latestVersion(); - - if (latestVersionOpt.isEmpty()) { + Optional latestVersionOptional = pluginData.latestVersion(); + if (latestVersionOptional.isEmpty()) { return; } - Version latestVersion = latestVersionOpt.get(); String pluginName = pluginData.pluginName(); String versionString = String.format("%s → %s", currentVersion.rawVersionString(), - latestVersion.rawVersionString() + latestVersionOptional.get().rawVersionString() ); List components = new ArrayList<>(); - components.add(Component.textDisplay("**" + pluginName + " Updated**")); - components.add(Component.textDisplay("**Version:** " + versionString)); - String versionDiff = pluginData.versionDifference().name(); - if (!versionDiff.equals("UNKNOWN")) { - components.add(Component.textDisplay("**Update Type:** " + versionDiff)); + VersionDifference versionDiff = pluginData.versionDifference(); + if (versionDiff != VersionDifference.UNKNOWN) { + components.add(Component.textDisplay("**Update Type:** " + versionDiff.name())); } pluginData.getChangelogUrl().ifPresent(s -> components.add(Component.textDisplay("**Changelog:** [View Changelog](" + s + ")"))); @@ -74,7 +66,7 @@ public void notifyDownload(PluginData pluginData) { ) .build(); - webhookClient.executeWebHook(webHook) + webHookClient.executeWebHook(webHook) .whenComplete((response, throwable) -> { int statusCode = response.statusCode(); @@ -90,7 +82,7 @@ public void notifyDownload(PluginData pluginData) { } } - public void close() { + public void shutdown() { // Might come handy in the future } } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java index d02e2437..34f9da5f 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java @@ -121,11 +121,8 @@ private void processQueue() { if (pluginData.downloadUpdate(updater.updaterPlugin().getDownloadDir())) { pluginData.versionDifference(VersionDifference.UNKNOWN); pluginData.setAlreadyDownloaded(true); - - // Send Discord webhook notification - if (updater.discordWebhookNotifier() != null) { - updater.discordWebhookNotifier().notifyDownload(pluginData); - } + + updater.discordWebHookNotifier().ifPresent(notifier -> notifier.notifyDownload(pluginData)); processingData.getFuture().complete(true); break; From a07b634fdc1a2a861c7ca5df636f4df43a1b359e Mon Sep 17 00:00:00 2001 From: Oak Date: Tue, 22 Sep 2026 22:24:14 +0100 Subject: [PATCH 11/15] Implemented Notifier to allow for future alternative notification types --- .../pluginupdater/common/UpdaterImpl.java | 20 +----- .../common/config/ConfigManager.java | 28 ++++---- .../deserializer/NotifierDeserializer.java | 15 +++++ .../notifier/DiscordWebHookNotifier.java | 12 ++-- .../common/notifier/Notifier.java | 10 +++ .../common/notifier/NotifierRegistry.java | 65 +++++++++++++++++++ .../common/updater/UpdateHandler.java | 2 +- common/impl/src/main/resources/config.yml | 11 ++-- 8 files changed, 119 insertions(+), 44 deletions(-) create mode 100644 common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/NotifierDeserializer.java create mode 100644 common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/Notifier.java create mode 100644 common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/NotifierRegistry.java diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java index 61348ec0..85ca68fc 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java @@ -27,7 +27,6 @@ public class UpdaterImpl { private final List collectors; private final UpdateHandler updateHandler; private final ConfigManager config; - private DiscordWebHookNotifier discordWebHookNotifier; public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, CommandHandler commandPlatform, List collectors) { this.platform = platform; @@ -41,17 +40,6 @@ public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, Com config = new ConfigManager(this); config.reload(); - if (config.getDiscordWebHookUrl() != null && !config.getDiscordWebHookUrl().isBlank()) { - try { - discordWebHookNotifier = new DiscordWebHookNotifier( - updaterPlugin.getComponentLogger(), - config.getDiscordWebHookUrl() - ); - } catch (Exception e) { - discordWebHookNotifier = null; - } - } - Lamp lamp = commandPlatform.prepareLamp() .permissionFactory(new CommandPermissionFactory(this)) .parameterTypes(parameterTypes -> parameterTypes @@ -93,9 +81,7 @@ public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, Com public void shutdown() { updateHandler.shutdown(); - if (discordWebHookNotifier != null) { - discordWebHookNotifier.shutdown(); - } + config.shutdownNotifiers(); } public UpdaterPlatform platform() { @@ -126,10 +112,6 @@ public Optional discordWebHookNotifier() { return Optional.ofNullable(discordWebHookNotifier); } - public void discordWebHookNotifier(DiscordWebHookNotifier notifier) { - this.discordWebHookNotifier = notifier; - } - public CompletableFuture> collectUnknownPlugins() { return CompletableFuture.supplyAsync(() -> { Map unknownPlugins = platform.getPlugins().stream() diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java index 1f4a3b4f..decc0f48 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java @@ -8,7 +8,8 @@ import org.lushplugins.pluginupdater.api.updater.PluginData; import org.lushplugins.pluginupdater.common.UpdaterImpl; import org.lushplugins.pluginupdater.common.config.deserializer.PluginDataDeserializer; -import org.lushplugins.pluginupdater.common.notifier.DiscordWebHookNotifier; +import org.lushplugins.pluginupdater.common.notifier.Notifier; +import org.lushplugins.pluginupdater.common.notifier.NotifierRegistry; import org.lushplugins.pluginupdater.common.updater.UpdateHandler; import org.lushplugins.pluginupdater.common.util.ConfigUtil; @@ -24,6 +25,7 @@ public class ConfigManager { private final Set disabledPlugins = new HashSet<>(); private Messages messages; private String discordWebhookUrl; + private List notifiers; public ConfigManager(UpdaterImpl updater) { this.updater = updater; @@ -104,16 +106,11 @@ public void reload(boolean skipCheck) { } }); - updater.discordWebHookNotifier().ifPresent(DiscordWebHookNotifier::shutdown); - if (this.discordWebhookUrl != null && !this.discordWebhookUrl.isBlank()) { - try { - updater.discordWebHookNotifier(new DiscordWebHookNotifier( - updater.updaterPlugin().getComponentLogger(), - this.discordWebhookUrl - )); - } catch (Exception e) { - updater.discordWebHookNotifier(null); - } + this.notifiers.forEach(Notifier::shutdown); + if (config.contains("notifications")) { + this.notifiers = NotifierRegistry.deserializeNotifiers(updater, config.get("notifications")); + } else { + this.notifiers = Collections.emptyList(); } config.close(); @@ -171,6 +168,15 @@ public String getDiscordWebHookUrl() { return discordWebhookUrl; } + public List getNotifiers() { + return notifiers; + } + + public void shutdownNotifiers() { + notifiers.forEach(Notifier::shutdown); + notifiers.clear(); + } + public record Messages(Map messages) { diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/NotifierDeserializer.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/NotifierDeserializer.java new file mode 100644 index 00000000..2c83e4b8 --- /dev/null +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/deserializer/NotifierDeserializer.java @@ -0,0 +1,15 @@ +package org.lushplugins.pluginupdater.common.config.deserializer; + +import com.electronwill.nightconfig.core.Config; +import org.jetbrains.annotations.Nullable; +import org.lushplugins.pluginupdater.common.UpdaterImpl; +import org.lushplugins.pluginupdater.common.notifier.DiscordWebHookNotifier; +import org.lushplugins.pluginupdater.common.notifier.Notifier; + +public class NotifierDeserializer { + + public static @Nullable Notifier discordWebHookNotifier(UpdaterImpl updater, Config config) { + String webHookUrl = config.get("webhook-url"); + return !webHookUrl.isBlank() ? new DiscordWebHookNotifier(updater.updaterPlugin().getComponentLogger(), webHookUrl) : null; + } +} diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebHookNotifier.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebHookNotifier.java index 15d1cf52..20665688 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebHookNotifier.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebHookNotifier.java @@ -14,7 +14,7 @@ import java.util.List; import java.util.Optional; -public class DiscordWebHookNotifier { +public class DiscordWebHookNotifier implements Notifier { private final ComponentLogger logger; private final WebHookClient webHookClient; @@ -29,6 +29,7 @@ public DiscordWebHookNotifier(ComponentLogger logger, @NotNull String webhookUrl } } + @Override public void notifyDownload(PluginData pluginData) { try { Version currentVersion = pluginData.currentVersion(); @@ -39,10 +40,9 @@ public void notifyDownload(PluginData pluginData) { String pluginName = pluginData.pluginName(); - String versionString = String.format("%s → %s", + String versionString = "%s → %s".formatted( currentVersion.rawVersionString(), - latestVersionOptional.get().rawVersionString() - ); + latestVersionOptional.get().rawVersionString()); List components = new ArrayList<>(); components.add(Component.textDisplay("**" + pluginName + " Updated**")); @@ -81,8 +81,4 @@ public void notifyDownload(PluginData pluginData) { logger.warn("Failed to send Discord webhook notification", e); } } - - public void shutdown() { - // Might come handy in the future - } } diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/Notifier.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/Notifier.java new file mode 100644 index 00000000..5bf405c0 --- /dev/null +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/Notifier.java @@ -0,0 +1,10 @@ +package org.lushplugins.pluginupdater.common.notifier; + +import org.lushplugins.pluginupdater.api.updater.PluginData; + +public interface Notifier { + + void notifyDownload(PluginData pluginData); + + default void shutdown() {} +} diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/NotifierRegistry.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/NotifierRegistry.java new file mode 100644 index 00000000..859669e6 --- /dev/null +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/NotifierRegistry.java @@ -0,0 +1,65 @@ +package org.lushplugins.pluginupdater.common.notifier; + +import com.electronwill.nightconfig.core.Config; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.lushplugins.pluginupdater.common.UpdaterImpl; +import org.lushplugins.pluginupdater.common.config.deserializer.NotifierDeserializer; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.BiFunction; + +public class NotifierRegistry { + private static final Map, Config, Notifier>> notifiers = new HashMap<>(); + + static { + register("discord-webhook", NotifierDeserializer::discordWebHookNotifier); + } + + public static @Nullable Notifier deserializeNotifier(UpdaterImpl updater, String id, Config config) { + if (config.get("enabled") == Boolean.FALSE) { + return null; + } + + try { + return notifiers.containsKey(id) ? notifiers.get(id).apply(updater, config) : null; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static List deserializeNotifiers(UpdaterImpl updater, Config config) { + return config.entrySet().stream() + .map(section -> { + if (section.getValue() instanceof Config sectionConfig) { + String key = section.getKey(); + if (notifiers.containsKey(key)) { + return deserializeNotifier(updater, key, sectionConfig); + } else { + String type = sectionConfig.get("type"); + return deserializeNotifier(updater, type, sectionConfig); + } + } + + return null; + }) + .filter(Objects::nonNull) + .toList(); + } + + public static void register(@NotNull String id, BiFunction, Config, Notifier> constructor) { + if (notifiers.containsKey(id)) { + throw new IllegalStateException("This notifier is already registered"); + } + + notifiers.put(id, constructor); + } + + public static void unregister(String id) { + notifiers.remove(id); + } +} diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java index 34f9da5f..093214bd 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/updater/UpdateHandler.java @@ -122,7 +122,7 @@ private void processQueue() { pluginData.versionDifference(VersionDifference.UNKNOWN); pluginData.setAlreadyDownloaded(true); - updater.discordWebHookNotifier().ifPresent(notifier -> notifier.notifyDownload(pluginData)); + updater.config().getNotifiers().forEach(notifier -> notifier.notifyDownload(pluginData)); processingData.getFuture().complete(true); break; diff --git a/common/impl/src/main/resources/config.yml b/common/impl/src/main/resources/config.yml index 2484bfa7..ec0dab65 100644 --- a/common/impl/src/main/resources/config.yml +++ b/common/impl/src/main/resources/config.yml @@ -3,11 +3,6 @@ check-updates-on-reload: true # Set to 'false' to disable all download features of PluginUpdater (May require restart) allow-downloads: true -# Discord webhook configuration for download notifications -discord-webhook: - enabled: false - webhook-url: "" - # To learn how to configure plugins that require different sources check out the wiki: https://github.com/OakLoaf/PluginUpdater/wiki/PluginUpdater-Plugin plugins: PluginUpdater: @@ -17,6 +12,12 @@ plugins: ExamplePlugin: enabled: false +# Notifications for downloads +notifications: + discord-webhook: + enabled: false + webhook-url: "" + messages: unchecked-color: "" update-available-color: "<#ffda54>" From bc75436a9283d0b33d71f50b2e743bfae56b5d5e Mon Sep 17 00:00:00 2001 From: Oak Date: Tue, 22 Sep 2026 22:24:29 +0100 Subject: [PATCH 12/15] Removed outdated code --- .../org/lushplugins/pluginupdater/common/UpdaterImpl.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java index 85ca68fc..6f6a6829 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/UpdaterImpl.java @@ -108,10 +108,6 @@ public ConfigManager config() { return config; } - public Optional discordWebHookNotifier() { - return Optional.ofNullable(discordWebHookNotifier); - } - public CompletableFuture> collectUnknownPlugins() { return CompletableFuture.supplyAsync(() -> { Map unknownPlugins = platform.getPlugins().stream() From e09270b672a07ad1a0a0ad13150e57cc6aa4b203 Mon Sep 17 00:00:00 2001 From: Oak Date: Mon, 28 Sep 2026 12:22:35 +0100 Subject: [PATCH 13/15] Ensured notifiers field cannot be null --- .../lushplugins/pluginupdater/common/config/ConfigManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java index 0a92e000..f68f0df0 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java @@ -26,7 +26,7 @@ public class ConfigManager { private final Set disabledPlugins = new HashSet<>(); private Messages messages; private String discordWebhookUrl; - private List notifiers; + private List notifiers = Collections.emptyList(); public ConfigManager(UpdaterImpl updater) { this.updater = updater; From a631b9873f96c0c945d8f41d980f7d160a576c62 Mon Sep 17 00:00:00 2001 From: Oak Date: Wed, 30 Sep 2026 22:10:31 +0100 Subject: [PATCH 14/15] Fixed compilation error --- .../org/lushplugins/pluginupdater/api/updater/PluginData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginData.java b/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginData.java index 8e513e0a..3f4f42ec 100644 --- a/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginData.java +++ b/common/api/src/main/java/org/lushplugins/pluginupdater/api/updater/PluginData.java @@ -216,7 +216,7 @@ public boolean downloadUpdate(Path destinationDir) { UpdaterConstants.LOGGER.error("Failed to download update for plugin '{}'.", this.pluginName, e); return false; } catch (RuntimeException e) { - UpdaterConstants.LOGGER.log(Level.SEVERE, "Failed to prepare or download update for plugin '" + this.pluginName + "'.", e); + UpdaterConstants.LOGGER.error("Failed to prepare or download update for plugin '{}'.", this.pluginName, e); return false; } } From bd8b759bb275b3703d85871af4e17bab3a12e21a Mon Sep 17 00:00:00 2001 From: Oak Date: Sun, 18 Oct 2026 13:54:51 +0100 Subject: [PATCH 15/15] Created new empty list instead of clearing --- .../lushplugins/pluginupdater/common/config/ConfigManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java index f68f0df0..de5f596b 100644 --- a/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/config/ConfigManager.java @@ -180,7 +180,7 @@ public List getNotifiers() { public void shutdownNotifiers() { notifiers.forEach(Notifier::shutdown); - notifiers.clear(); + notifiers = Collections.emptyList(); }