diff --git a/common/impl/build.gradle.kts b/common/impl/build.gradle.kts index 4e7af67f..82f42641 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") + 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 be27cc81..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,15 +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.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; @@ -29,6 +27,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; @@ -42,6 +41,17 @@ 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 @@ -83,6 +93,9 @@ public UpdaterImpl(UpdaterPlatform platform, UpdaterPlugin updaterPlugin, Com public void shutdown() { updateHandler.shutdown(); + if (discordWebHookNotifier != null) { + discordWebHookNotifier.shutdown(); + } } public UpdaterPlatform platform() { @@ -109,6 +122,14 @@ public ConfigManager config() { return config; } + 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 ca737c39..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,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,7 @@ public class ConfigManager { private final Map plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private final Set disabledPlugins = new HashSet<>(); private Messages messages; + private String discordWebhookUrl; public ConfigManager(UpdaterImpl updater) { this.updater = updater; @@ -46,6 +48,18 @@ public void reload(boolean skipCheck) { this.allowDownloads = config.getOrElse("allow-downloads", true); + Config discordConfig = config.get("discord-webhook"); + if (discordConfig != null) { + boolean discordWebhookEnabled = discordConfig.getOrElse("enabled", false); + if (!discordWebhookEnabled) { + discordWebhookUrl = ""; + } else { + this.discordWebhookUrl = discordConfig.getOrElse("webhook-url", ""); + } + } else { + this.discordWebhookUrl = ""; + } + Config messagesConfig = config.get("messages"); if (messagesConfig != null) { this.messages = new Messages(messagesConfig); @@ -90,6 +104,18 @@ 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); + } + } + config.close(); } @@ -141,6 +167,10 @@ public String getMessage(String name, String def) { return messages.get(name, def); } + 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..15d1cf52 --- /dev/null +++ b/common/impl/src/main/java/org/lushplugins/pluginupdater/common/notifier/DiscordWebHookNotifier.java @@ -0,0 +1,88 @@ +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.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 { + private final ComponentLogger logger; + private final WebHookClient webHookClient; + + public DiscordWebHookNotifier(ComponentLogger logger, @NotNull String webhookUrl) { + this.logger = logger; + + 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) { + try { + Version currentVersion = pluginData.currentVersion(); + Optional latestVersionOptional = pluginData.latestVersion(); + if (latestVersionOptional.isEmpty()) { + return; + } + + String pluginName = pluginData.pluginName(); + + String versionString = String.format("%s → %s", + currentVersion.rawVersionString(), + latestVersionOptional.get().rawVersionString() + ); + + List components = new ArrayList<>(); + components.add(Component.textDisplay("**" + pluginName + " Updated**")); + components.add(Component.textDisplay("**Version:** " + versionString)); + + 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 + ")"))); + + 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 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 875665b6..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,6 +121,9 @@ private void processQueue() { if (pluginData.downloadUpdate(updater.updaterPlugin().getDownloadDir())) { pluginData.versionDifference(VersionDifference.UNKNOWN); pluginData.setAlreadyDownloaded(true); + + updater.discordWebHookNotifier().ifPresent(notifier -> notifier.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: