Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -83,6 +81,7 @@ public UpdaterImpl(UpdaterPlatform<T> platform, UpdaterPlugin updaterPlugin, Com

public void shutdown() {
updateHandler.shutdown();
config.shutdownNotifiers();
}

public UpdaterPlatform<T> platform() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +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.Notifier;
import org.lushplugins.pluginupdater.common.notifier.NotifierRegistry;
import org.lushplugins.pluginupdater.common.updater.UpdateHandler;
import org.lushplugins.pluginupdater.common.util.ConfigUtil;

Expand All @@ -22,6 +24,8 @@ public class ConfigManager {
private final Map<String, PluginData> plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private final Set<String> disabledPlugins = new HashSet<>();
private Messages messages;
private String discordWebhookUrl;
private List<Notifier> notifiers;

public ConfigManager(UpdaterImpl<?> updater) {
this.updater = updater;
Expand All @@ -46,6 +50,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);
Expand Down Expand Up @@ -90,6 +106,13 @@ public void reload(boolean skipCheck) {
}
});

this.notifiers.forEach(Notifier::shutdown);
if (config.contains("notifications")) {
this.notifiers = NotifierRegistry.deserializeNotifiers(updater, config.get("notifications"));
} else {
this.notifiers = Collections.emptyList();
}

config.close();
}

Expand Down Expand Up @@ -141,6 +164,19 @@ public String getMessage(String name, String def) {
return messages.get(name, def);
}

public String getDiscordWebHookUrl() {
return discordWebhookUrl;
}

public List<Notifier> getNotifiers() {
return notifiers;
}

public void shutdownNotifiers() {
notifiers.forEach(Notifier::shutdown);
notifiers.clear();
}


public record Messages(Map<String, String> messages) {

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
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 implements Notifier {
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;
}
}

@Override
public void notifyDownload(PluginData pluginData) {
try {
Version currentVersion = pluginData.currentVersion();
Optional<Version> latestVersionOptional = pluginData.latestVersion();
if (latestVersionOptional.isEmpty()) {
return;
}

String pluginName = pluginData.pluginName();

String versionString = "%s → %s".formatted(
currentVersion.rawVersionString(),
latestVersionOptional.get().rawVersionString());

List<ContainerableComponent> 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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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() {}
}
Original file line number Diff line number Diff line change
@@ -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<String, BiFunction<UpdaterImpl<?>, 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<Notifier> 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<UpdaterImpl<?>, 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ private void processQueue() {
if (pluginData.downloadUpdate(updater.updaterPlugin().getDownloadDir())) {
pluginData.versionDifference(VersionDifference.UNKNOWN);
pluginData.setAlreadyDownloaded(true);

updater.config().getNotifiers().forEach(notifier -> notifier.notifyDownload(pluginData));

processingData.getFuture().complete(true);
break;
} else {
Expand Down
6 changes: 6 additions & 0 deletions common/impl/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ plugins:
ExamplePlugin:
enabled: false

# Notifications for downloads
notifications:
discord-webhook:
enabled: false
webhook-url: ""

messages:
unchecked-color: "<dark_gray>"
update-available-color: "<#ffda54>"
Expand Down
Loading