Ansi serialization, fixes to Minecraft->Discord

This commit is contained in:
Vankka 2023-06-03 23:05:57 +03:00
parent ce055debde
commit aecf67c924
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
6 changed files with 44 additions and 37 deletions

View File

@ -74,6 +74,7 @@ dependencies {
runtimeDownloadApi(libs.adventure.serializer.plain)
runtimeDownloadApi(libs.adventure.serializer.legacy)
runtimeDownloadApi(libs.adventure.serializer.gson)
runtimeDownloadApi(libs.adventure.serializer.ansi)
runtimeDownloadApi(libs.mcdiscordreserializer)
runtimeDownloadApi(libs.enhancedlegacytext)

View File

@ -84,10 +84,10 @@ public class ChannelConfigHelper {
throws SerializationException {
MainConfigManager<?> configManager = discordSRV.configManager();
CommentedConfigurationNode defaultNode = CommentedConfigurationNode.root(configManager.defaultNodeOptions());
CommentedConfigurationNode defaultNode = CommentedConfigurationNode.root(configManager.configNodeOptions());
CommentedConfigurationNode target = CommentedConfigurationNode.root(configManager.configNodeOptions());
configManager.defaultObjectMapper()
configManager.configObjectMapper()
.get((Class<BaseChannelConfig>) defaultConfig.getClass())
.save(defaultConfig, defaultNode);

View File

@ -31,7 +31,9 @@ import dev.vankka.mcdiscordreserializer.minecraft.MinecraftSerializer;
import dev.vankka.mcdiscordreserializer.minecraft.MinecraftSerializerOptions;
import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.serializer.ansi.ANSIComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.kyori.ansi.ColorLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Locale;
@ -52,6 +54,7 @@ public class ComponentFactory implements MinecraftComponentFactory {
private final MinecraftSerializer minecraftSerializer;
private final DiscordSerializer discordSerializer;
private final PlainTextComponentSerializer plainSerializer;
private final ANSIComponentSerializer ansiSerializer;
// Not the same as Adventure's TranslationRegistry
private final TranslationRegistry translationRegistry = new TranslationRegistry();
@ -62,17 +65,20 @@ public class ComponentFactory implements MinecraftComponentFactory {
MinecraftSerializerOptions.defaults()
.addRenderer(new DiscordSRVMinecraftRenderer(discordSRV))
);
this.discordSerializer = new DiscordSerializer();
discordSerializer.setDefaultOptions(
this.discordSerializer = new DiscordSerializer(
DiscordSerializerOptions.defaults()
.withTranslationProvider(this::provideTranslation)
);
ComponentFlattener flattener = ComponentFlattener.basic().toBuilder()
.mapper(TranslatableComponent.class, this::provideTranslation)
.build();
this.plainSerializer = PlainTextComponentSerializer.builder()
.flattener(
ComponentFlattener.basic().toBuilder()
.mapper(TranslatableComponent.class, this::provideTranslation)
.build()
)
.flattener(flattener)
.build();
this.ansiSerializer = ANSIComponentSerializer.builder()
.colorLevel(ColorLevel.INDEXED_16)
.flattener(flattener)
.build();
}
@ -113,6 +119,10 @@ public class ComponentFactory implements MinecraftComponentFactory {
return plainSerializer;
}
public ANSIComponentSerializer ansiSerializer() {
return ansiSerializer;
}
public TranslationRegistry translationRegistry() {
return translationRegistry;
}

View File

@ -31,7 +31,6 @@ import com.discordsrv.api.event.bus.EventPriority;
import com.discordsrv.api.event.bus.Subscribe;
import com.discordsrv.api.event.events.message.forward.game.GameChatMessageForwardedEvent;
import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent;
import com.discordsrv.api.placeholder.DiscordPlaceholders;
import com.discordsrv.api.placeholder.FormattedText;
import com.discordsrv.api.placeholder.util.Placeholders;
import com.discordsrv.common.DiscordSRV;
@ -41,7 +40,6 @@ import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.future.util.CompletableFutureUtil;
import com.discordsrv.common.messageforwarding.game.AbstractGameMessageModule;
import com.discordsrv.common.player.IPlayer;
import dev.vankka.mcdiscordreserializer.discord.DiscordSerializer;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Role;
import net.kyori.adventure.text.Component;
@ -50,6 +48,7 @@ import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<MinecraftToDiscordChatConfig, GameChatMessageReceiveEvent> {
@ -80,8 +79,7 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<Mine
@Override
public String convertComponent(MinecraftToDiscordChatConfig config, Component component) {
DiscordSerializer discordSerializer = discordSRV.componentFactory().discordSerializer();
String content = discordSerializer.serialize(component, discordSerializer.getDefaultOptions().withEscapeMarkdown(false));
String content = discordSRV.placeholderService().getResultAsPlain(component).toString();
Placeholders messagePlaceholders = new Placeholders(content);
config.contentRegexFilters.forEach(messagePlaceholders::replaceAll);
@ -111,9 +109,7 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<Mine
.add(channel);
}
Component component = ComponentUtil.fromAPI(event.getMessage());
String message = convertComponent(config, component);
Component message = ComponentUtil.fromAPI(event.getMessage());
Map<CompletableFuture<ReceivedDiscordMessage>, DiscordMessageChannel> futures = new LinkedHashMap<>();
// Format messages per-Guild
@ -138,7 +134,7 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<Mine
MinecraftToDiscordChatConfig config,
SendableDiscordMessage.Builder format,
Guild guild,
String message,
Component message,
IPlayer player,
Object[] context
) {
@ -149,7 +145,8 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<Mine
&& player.hasPermission("discordsrv.mention.lookup.user")) {
List<CompletableFuture<List<MentionCachingModule.CachedMention>>> futures = new ArrayList<>();
Matcher matcher = MENTION_PATTERN.matcher(message);
String messageContent = discordSRV.componentFactory().plainSerializer().serialize(message);
Matcher matcher = MENTION_PATTERN.matcher(messageContent);
while (matcher.find()) {
futures.add(mentionCaching.lookupMemberMentions(guild, matcher.group()));
}
@ -173,7 +170,7 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<Mine
MinecraftToDiscordChatConfig config,
SendableDiscordMessage.Builder format,
Guild guild,
String message,
Component message,
IPlayer player,
Object[] context,
Set<MentionCachingModule.CachedMention> memberMentions
@ -198,13 +195,9 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<Mine
}
}
Placeholders channelMessagePlaceholders = new Placeholders(
DiscordFormattingUtil.escapeMentions(message));
// From longest to shortest
mentions.stream()
List<MentionCachingModule.CachedMention> orderedMentions = mentions.stream()
.sorted(Comparator.comparingInt(mention -> ((MentionCachingModule.CachedMention) mention).searchLength()).reversed())
.forEachOrdered(mention -> channelMessagePlaceholders.replaceAll(mention.search(), mention.mention()));
.collect(Collectors.toList());
List<AllowedMention> allowedMentions = new ArrayList<>();
if (mentionConfig.users && player.hasPermission("discordsrv.mention.user")) {
@ -232,28 +225,29 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<Mine
.toFormatter()
.addContext(context)
.addPlaceholder("message", () -> {
String convertedComponent = convertComponent(config, message);
Placeholders channelMessagePlaceholders = new Placeholders(
DiscordFormattingUtil.escapeMentions(convertedComponent));
// From longest to shortest
orderedMentions.forEach(mention -> channelMessagePlaceholders.replaceAll(mention.search(), mention.mention()));
String finalMessage = channelMessagePlaceholders.toString();
if (DiscordPlaceholders.FORMATTING.get() != DiscordPlaceholders.Formatting.NORMAL) {
return preventEveryoneMentions(everyone, finalMessage, false);
} else {
String formattedMessage = DiscordFormattingUtil.escapeFormatting(
DiscordFormattingUtil.escapeQuotes(finalMessage));
return new FormattedText(preventEveryoneMentions(everyone, formattedMessage, true));
}
return new FormattedText(preventEveryoneMentions(everyone, finalMessage));
})
.applyPlaceholderService()
.build();
}
private String preventEveryoneMentions(boolean everyoneAllowed, String message, boolean permitBackslash) {
private String preventEveryoneMentions(boolean everyoneAllowed, String message) {
if (everyoneAllowed) {
// Nothing to do
return message;
}
message = message
.replace("@everyone", (permitBackslash ? "\\" : "") + "@\u200Beveryone") // zero-width-space
.replace("@here", (permitBackslash ? "\\" : "") + "@\u200Bhere"); // zero-width-space
.replace("@everyone", "\\@\u200Beveryone") // zero-width-space
.replace("@here", "\\@\u200Bhere"); // zero-width-space
if (message.contains("@everyone") || message.contains("@here")) {
throw new IllegalStateException("@everyone or @here blocking unsuccessful");

View File

@ -44,7 +44,8 @@ public class ComponentResultStringifier implements PlaceholderResultMapper {
Component component = (Component) result;
DiscordPlaceholders.Formatting mappingState = DiscordPlaceholders.FORMATTING.get();
switch (mappingState) {
case ANSI: // TODO: ansi serializer (?)
case ANSI:
return discordSRV.componentFactory().ansiSerializer().serialize(component);
case PLAIN:
return discordSRV.componentFactory().plainSerializer().serialize(component);
default:

View File

@ -116,11 +116,12 @@ dependencyResolutionManagement {
library('log4j-core', 'org.apache.logging.log4j', 'log4j-core').version('2.0-beta9')
// Adventure
version('adventure', '4.13.1')
version('adventure', '4.14.0-SNAPSHOT')
library('adventure-api', 'net.kyori', 'adventure-api').versionRef('adventure')
library('adventure-serializer-plain', 'net.kyori', 'adventure-text-serializer-plain').versionRef('adventure')
library('adventure-serializer-legacy', 'net.kyori', 'adventure-text-serializer-legacy').versionRef('adventure')
library('adventure-serializer-gson', 'net.kyori', 'adventure-text-serializer-gson').versionRef('adventure')
library('adventure-serializer-ansi', 'net.kyori', 'adventure-text-serializer-ansi').versionRef('adventure')
// Adventure Platform
version('adventure-platform', '4.3.0')