feat: implement DISCORD <- MC

This commit is contained in:
Soph :3 2024-10-28 01:25:13 +02:00
parent b2178db695
commit d3d1d2fcf3
Signed by: sophie
GPG key ID: EDA5D222A0C270F2
6 changed files with 106 additions and 8 deletions

View file

@ -45,6 +45,8 @@ dependencies {
implementation("net.dv8tion:JDA:${project.jda_version}") { implementation("net.dv8tion:JDA:${project.jda_version}") {
exclude module: 'opus-java' exclude module: 'opus-java'
} }
include implementation("club.minnced:discord-webhooks:${project.webhooks_version}")
} }
processResources { processResources {

View file

@ -15,3 +15,4 @@ fabric_version=0.107.0+1.21.1
owo_version=0.12.15+1.21 owo_version=0.12.15+1.21
jda_version=5.1.2 jda_version=5.1.2
webhooks_version=0.8.4

View file

@ -13,7 +13,7 @@ public class Discord implements ModInitializer {
@Override @Override
public void onInitialize() { public void onInitialize() {
LOGGER.info("slop's custom discord plugin"); LOGGER.info("slop's custom discord plugin");
DiscordRegistration.createClient(); DiscordRegistration.register();
MinecraftRegistration.register();
} }
} }

View file

@ -1,14 +1,12 @@
package sad.ovh.discord; package sad.ovh.discord;
import io.wispforest.owo.config.Option;
import io.wispforest.owo.config.annotation.Config; import io.wispforest.owo.config.annotation.Config;
import io.wispforest.owo.config.annotation.Sync;
@Sync(Option.SyncMode.NONE)
@Config(name = "slop-discord-config", wrapperName = "DiscordConfig") @Config(name = "slop-discord-config", wrapperName = "DiscordConfig")
public class DiscordConfigModel { public class DiscordConfigModel {
public String token = ""; public String token = "";
public String channelId = ""; public String channelId = "";
public String consoleId = ""; public String consoleId = "";
public String webhookName = "mc-bridge";
public String avatarApiUrl = "https://vzge.me/bust/256/%s"; public String avatarApiUrl = "https://vzge.me/bust/256/%s";
} }

View file

@ -1,7 +1,12 @@
package sad.ovh.discord; package sad.ovh.discord;
import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.WebhookClientBuilder;
import club.minnced.discord.webhook.receive.ReadonlyMessage;
import club.minnced.discord.webhook.send.*;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Webhook;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.events.message.MessageUpdateEvent; import net.dv8tion.jda.api.events.message.MessageUpdateEvent;
@ -12,15 +17,21 @@ import net.dv8tion.jda.api.utils.cache.CacheFlag;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.UUID;
public class DiscordRegistration { public class DiscordRegistration {
static public JDA client; static public JDA client;
static public TextChannel channel; static public TextChannel channel;
static public TextChannel consoleChannel; static public TextChannel consoleChannel;
static public WebhookClient webhookClient;
static public Boolean isReady; static public Boolean isReady;
static public void createClient() { static public Webhook webhook;
static private Long lastId;
static public void register() {
client = JDABuilder client = JDABuilder
.create(Discord.CONFIG.token(), EnumSet.of(GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_MEMBERS, GatewayIntent.MESSAGE_CONTENT)) .create(Discord.CONFIG.token(), EnumSet.of(GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_MEMBERS, GatewayIntent.MESSAGE_CONTENT))
.disableCache(CacheFlag.ACTIVITY, CacheFlag.VOICE_STATE, CacheFlag.EMOJI, CacheFlag.STICKER, CacheFlag.CLIENT_STATUS, CacheFlag.ONLINE_STATUS, CacheFlag.SCHEDULED_EVENTS) .disableCache(CacheFlag.ACTIVITY, CacheFlag.VOICE_STATE, CacheFlag.EMOJI, CacheFlag.STICKER, CacheFlag.CLIENT_STATUS, CacheFlag.ONLINE_STATUS, CacheFlag.SCHEDULED_EVENTS)
@ -28,6 +39,57 @@ public class DiscordRegistration {
.build(); .build();
} }
static public void sendPlayerMessage(String message, String name, UUID playerUuid) {
if (!isReady)
return;
String avatarUrl = String.format(Discord.CONFIG.avatarApiUrl(), playerUuid.toString());
WebhookMessage webhookMessage = new WebhookMessageBuilder()
.setAvatarUrl(avatarUrl)
.setUsername(name)
.setContent(message)
.setAllowedMentions(
new AllowedMentions()
.withParseUsers(true)
.withParseRoles(true)
.withParseEveryone(false)
)
.build();
webhookClient.send(webhookMessage);
}
static public void sendPlayerStatus(String message, int color, UUID playerUuid) {
if (!isReady)
return;
String avatarUrl = String.format(Discord.CONFIG.avatarApiUrl(), playerUuid.toString());
var embed = new WebhookEmbedBuilder()
.setAuthor(new WebhookEmbed.EmbedAuthor(message, avatarUrl, null))
.setColor(color)
.build();
webhookClient.send(embed);
}
static public void sendServerUpdate(String message, int color, Boolean deleteLastOne) {
if (!isReady)
return;
if(deleteLastOne && lastId != null) {
channel.deleteMessageById(lastId).complete();
}
WebhookEmbed webhookMessage = new WebhookEmbedBuilder()
.setDescription(message)
.setColor(color)
.build();
webhookClient.send(webhookMessage)
.thenAccept((msg) -> lastId = msg.getId());
}
private static class DiscordEvents extends ListenerAdapter { private static class DiscordEvents extends ListenerAdapter {
@Override @Override
public void onReady(@NotNull ReadyEvent event) { public void onReady(@NotNull ReadyEvent event) {
@ -45,6 +107,27 @@ public class DiscordRegistration {
if (consoleChannel == null) { if (consoleChannel == null) {
Discord.LOGGER.warn("No console channel was set."); Discord.LOGGER.warn("No console channel was set.");
} }
var webhookName = Discord.CONFIG.webhookName();
var webhooks = channel.retrieveWebhooks().complete();
webhooks.stream()
.filter((wh) -> wh.getName().equals(webhookName))
.findFirst()
.ifPresent((wh) -> webhook = wh);
if (webhook == null) {
webhook = channel.createWebhook(webhookName).complete();
}
if (webhook == null) {
Discord.LOGGER.error("Attempt to create a webhook failed! Please create a WebHook by the name {} and restart the server", webhookName);
client.shutdown();
return;
}
webhookClient = new WebhookClientBuilder(webhook.getUrl())
.setDaemon(true)
.buildJDA();
isReady = true; isReady = true;
} }

View file

@ -6,32 +6,41 @@ import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import java.awt.*;
public class MinecraftRegistration { public class MinecraftRegistration {
public static void register() { public static void register() {
ServerLifecycleEvents.SERVER_STARTING.register(server -> { ServerLifecycleEvents.SERVER_STARTING.register(server -> {
if (!DiscordRegistration.isReady) if (!DiscordRegistration.isReady)
return; return;
DiscordRegistration.sendServerUpdate(":hourglass: **Server is starting...**", Color.YELLOW.getRGB(), false);
}); });
ServerLifecycleEvents.SERVER_STARTED.register(server -> { ServerLifecycleEvents.SERVER_STARTED.register(server -> {
if (!DiscordRegistration.isReady) if (!DiscordRegistration.isReady)
return; return;
DiscordRegistration.sendServerUpdate(":white_check_mark: **Server has started!**", Color.GREEN.getRGB(), true);
}); });
ServerLifecycleEvents.SERVER_STOPPING.register(server -> { ServerLifecycleEvents.SERVER_STOPPING.register(server -> {
if (!DiscordRegistration.isReady) if (!DiscordRegistration.isReady)
return; return;
DiscordRegistration.sendServerUpdate(":x: **Server stopping.**", Color.RED.getRGB(), false);
}); });
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
if (!DiscordRegistration.isReady) if (!DiscordRegistration.isReady)
return; return;
DiscordRegistration.sendPlayerStatus(String.format("%s has joined the server.", handler.player.getDisplayName().getString()), Color.GREEN.getRGB(), handler.player.getUuid());
}); });
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> { ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
if (!DiscordRegistration.isReady) if (!DiscordRegistration.isReady)
return; return;
DiscordRegistration.sendPlayerStatus(String.format("%s has left the server.", handler.player.getDisplayName().getString()), Color.RED.getRGB(), handler.player.getUuid());
}); });
ServerLivingEntityEvents.AFTER_DEATH.register((entity, damageSource) -> { ServerLivingEntityEvents.AFTER_DEATH.register((entity, damageSource) -> {
@ -39,11 +48,16 @@ public class MinecraftRegistration {
return; return;
if (!(entity instanceof ServerPlayerEntity player)) if (!(entity instanceof ServerPlayerEntity player))
return; return;
var message = damageSource.getDeathMessage(entity).getString();
DiscordRegistration.sendPlayerStatus(message, Color.RED.getRGB(), player.getUuid());
}); });
ServerMessageEvents.CHAT_MESSAGE.register((message, sender, params) -> { ServerMessageEvents.CHAT_MESSAGE.register((message, sender, params) -> {
if (!DiscordRegistration.isReady) if (!DiscordRegistration.isReady)
return; return;
DiscordRegistration.sendPlayerMessage(message.getContent().getString(), sender.getDisplayName().getString(), sender.getUuid());
}); });
} }
} }