mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-11-01 08:39:31 +01:00
Add options for how to handle emojis from Discord, add event for rendering custom emoji to Minecraft components to API
This commit is contained in:
parent
ac84845d67
commit
39036e2b21
@ -25,6 +25,7 @@ package com.discordsrv.api.discord;
|
||||
|
||||
import com.discordsrv.api.discord.entity.DiscordUser;
|
||||
import com.discordsrv.api.discord.entity.channel.*;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordCustomEmoji;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordGuild;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordRole;
|
||||
import com.discordsrv.api.discord.entity.interaction.command.DiscordCommand;
|
||||
@ -143,6 +144,13 @@ public interface DiscordAPI {
|
||||
@Nullable
|
||||
DiscordRole getRoleById(long id);
|
||||
|
||||
/**
|
||||
* Gets a custom emoji for a Discord server by id, the provided entity should not be stored for long periods of time.
|
||||
* @param id the id for the custom emoji
|
||||
* @return the Discord custom emoji
|
||||
*/
|
||||
DiscordCustomEmoji getEmojiById(long id);
|
||||
|
||||
/**
|
||||
* Registers a Discord command.
|
||||
* @param command the command to register
|
||||
|
@ -0,0 +1,54 @@
|
||||
package com.discordsrv.api.event.events.message.process.discord;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordCustomEmoji;
|
||||
import com.discordsrv.api.event.events.Event;
|
||||
import com.discordsrv.api.event.events.Processable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Renders a given {@link DiscordCustomEmoji} into a {@link MinecraftComponent} that can be displayed in Minecraft.
|
||||
* @see #process(MinecraftComponent)
|
||||
*/
|
||||
public class DiscordChatMessageCustomEmojiRenderEvent implements Event, Processable.Argument<MinecraftComponent> {
|
||||
|
||||
private final DiscordCustomEmoji emoji;
|
||||
private MinecraftComponent rendered = null;
|
||||
|
||||
public DiscordChatMessageCustomEmojiRenderEvent(@NotNull DiscordCustomEmoji emoji) {
|
||||
this.emoji = emoji;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DiscordCustomEmoji getEmoji() {
|
||||
return emoji;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rendered representation of the emoji.
|
||||
* @return the rendered representation of the emoji if this event has been processed otherwise {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
public MinecraftComponent getRenderedEmojiFromProcessing() {
|
||||
return rendered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProcessed() {
|
||||
return rendered != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this event as processed, with the given {@link MinecraftComponent} being the representation of {@link DiscordCustomEmoji} in game.
|
||||
* @param renderedEmote the rendered emote
|
||||
*/
|
||||
@Override
|
||||
public void process(@NotNull MinecraftComponent renderedEmote) {
|
||||
if (rendered != null) {
|
||||
throw new IllegalStateException("Cannot process an already processed event");
|
||||
}
|
||||
|
||||
rendered = renderedEmote;
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
package com.discordsrv.api.event.events.message.receive.discord;
|
||||
package com.discordsrv.api.event.events.message.process.discord;
|
||||
|
||||
import com.discordsrv.api.channel.GameChannel;
|
||||
import com.discordsrv.api.discord.entity.channel.DiscordMessageChannel;
|
||||
import com.discordsrv.api.discord.entity.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.event.events.Cancellable;
|
||||
import com.discordsrv.api.event.events.Processable;
|
||||
import com.discordsrv.api.event.events.message.receive.discord.DiscordChatMessageReceiveEvent;
|
||||
|
||||
/**
|
||||
* Indicates that a Discord message is about to be processed, this will run once per {@link GameChannel} destination,
|
@ -29,11 +29,12 @@ import com.discordsrv.api.discord.entity.channel.DiscordThreadChannel;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordGuild;
|
||||
import com.discordsrv.api.discord.entity.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.event.events.Cancellable;
|
||||
import com.discordsrv.api.event.events.message.process.discord.DiscordChatMessageProcessEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Indicates that a Discord message has been received and will be processed unless cancelled.
|
||||
* This runs once per Discord message, before {@link DiscordChatMessageProcessEvent}.
|
||||
* This runs once per Discord message, before {@link DiscordChatMessageProcessEvent}(s).
|
||||
*/
|
||||
public class DiscordChatMessageReceiveEvent implements Cancellable {
|
||||
|
||||
|
@ -40,7 +40,7 @@ public abstract class AbstractGameMessageReceiveEvent implements Cancellable, Pr
|
||||
|
||||
/**
|
||||
* Gets the event that triggered this event to occur. This varies depending on platform and different plugin integrations.
|
||||
* @return an event object, that isn't guaranteed to be of the same type every time or {@code null}
|
||||
* @return an event object, that isn't guaranteed to be of the same type every time, or {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
public Object getTriggeringEvent() {
|
||||
|
@ -20,9 +20,11 @@ package com.discordsrv.common.component.renderer;
|
||||
|
||||
import com.discordsrv.api.component.GameTextBuilder;
|
||||
import com.discordsrv.api.discord.entity.DiscordUser;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordCustomEmoji;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordGuild;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordGuildMember;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordRole;
|
||||
import com.discordsrv.api.event.events.message.process.discord.DiscordChatMessageCustomEmojiRenderEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig;
|
||||
@ -181,6 +183,42 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer {
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component appendEmoteMention(
|
||||
@NotNull Component component,
|
||||
@NotNull String name,
|
||||
@NotNull String id
|
||||
) {
|
||||
Context context = CONTEXT.get();
|
||||
DiscordToMinecraftChatConfig.EmoteBehaviour behaviour = context != null ? context.config.customEmojiBehaviour : null;
|
||||
if (behaviour == null || behaviour == DiscordToMinecraftChatConfig.EmoteBehaviour.HIDE) {
|
||||
return component;
|
||||
}
|
||||
|
||||
System.out.println(name);
|
||||
long emojiId = MiscUtil.parseLong(id);
|
||||
DiscordCustomEmoji emoji = discordSRV.discordAPI().getEmojiById(emojiId);
|
||||
if (emoji == null) {
|
||||
return component;
|
||||
}
|
||||
|
||||
DiscordChatMessageCustomEmojiRenderEvent event = new DiscordChatMessageCustomEmojiRenderEvent(emoji);
|
||||
discordSRV.eventBus().publish(event);
|
||||
|
||||
if (event.isProcessed()) {
|
||||
Component rendered = ComponentUtil.fromAPI(event.getRenderedEmojiFromProcessing());
|
||||
return component.append(rendered);
|
||||
}
|
||||
|
||||
switch (behaviour) {
|
||||
case NAME:
|
||||
return component.append(Component.text(":" + emoji.getName() + ":"));
|
||||
case BLANK:
|
||||
default:
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Context {
|
||||
|
||||
private final DiscordGuild guild;
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
package com.discordsrv.common.config.main.channels;
|
||||
|
||||
import com.discordsrv.common.config.configurate.annotation.Constants;
|
||||
import com.discordsrv.common.config.configurate.annotation.Untranslated;
|
||||
import com.discordsrv.common.config.main.generic.DiscordIgnoresConfig;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
@ -58,10 +57,6 @@ public class DiscordToMinecraftChatConfig {
|
||||
@Comment("The representations of Discord mentions in-game")
|
||||
public Mentions mentions = new Mentions();
|
||||
|
||||
@Comment("The amount of milliseconds to delay processing Discord messages, if the message is deleted in that time it will not be processed.\n"
|
||||
+ "This can be used together with Discord moderation bots, to filter forwarded messages")
|
||||
public long delayMillis = 0L;
|
||||
|
||||
@ConfigSerializable
|
||||
public static class Mentions {
|
||||
|
||||
@ -90,7 +85,35 @@ public class DiscordToMinecraftChatConfig {
|
||||
this.unknownFormat = unknownFormat;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Comment("How should unicode emoji be shown in-game:\n"
|
||||
+ "- hide: hides emojis in-game\n"
|
||||
+ "- show: shows emojis in-game as is (emojis may not be visible without resource packs)\n"
|
||||
//+ "- name: shows the name of the emoji in-game (for example :smiley:)"
|
||||
)
|
||||
public EmojiBehaviour unicodeEmojiBehaviour = EmojiBehaviour.HIDE;
|
||||
|
||||
public enum EmojiBehaviour {
|
||||
HIDE,
|
||||
SHOW
|
||||
// TODO: add and implement name
|
||||
}
|
||||
|
||||
@Comment("How should custom emoji be shown in-game:\n"
|
||||
+ "- hide: custom emoji will not be shown in-game\n"
|
||||
+ "- blank: custom emoji will only be shown in-game if it is rendered by a 3rd party plugin\n"
|
||||
+ "- name: shows the name of the custom emoji in-game (for example :discordsrv:), unless rendered by a 3rd party plugin")
|
||||
public EmoteBehaviour customEmojiBehaviour = EmoteBehaviour.BLANK;
|
||||
|
||||
public enum EmoteBehaviour {
|
||||
HIDE,
|
||||
BLANK,
|
||||
NAME
|
||||
}
|
||||
|
||||
@Comment("The amount of milliseconds to delay processing Discord messages, if the message is deleted in that time it will not be processed.\n"
|
||||
+ "This can be used together with Discord moderation bots, to filter forwarded messages")
|
||||
public long delayMillis = 0L;
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import com.discordsrv.api.discord.connection.details.DiscordGatewayIntent;
|
||||
import com.discordsrv.api.discord.connection.jda.errorresponse.ErrorCallbackContext;
|
||||
import com.discordsrv.api.discord.entity.DiscordUser;
|
||||
import com.discordsrv.api.discord.entity.channel.*;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordCustomEmoji;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordGuild;
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordRole;
|
||||
import com.discordsrv.api.discord.entity.interaction.command.CommandType;
|
||||
@ -36,6 +37,7 @@ import com.discordsrv.common.config.main.generic.ThreadConfig;
|
||||
import com.discordsrv.common.config.main.generic.DestinationConfig;
|
||||
import com.discordsrv.common.discord.api.entity.DiscordUserImpl;
|
||||
import com.discordsrv.common.discord.api.entity.channel.*;
|
||||
import com.discordsrv.common.discord.api.entity.guild.DiscordCustomEmojiImpl;
|
||||
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildImpl;
|
||||
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildMemberImpl;
|
||||
import com.discordsrv.common.discord.api.entity.guild.DiscordRoleImpl;
|
||||
@ -49,6 +51,7 @@ import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.entities.channel.Channel;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.*;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.emoji.CustomEmoji;
|
||||
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
|
||||
import net.dv8tion.jda.api.requests.ErrorResponse;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
@ -498,6 +501,15 @@ public class DiscordAPIImpl implements DiscordAPI {
|
||||
return new DiscordRoleImpl(discordSRV, jda);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscordCustomEmoji getEmojiById(long id) {
|
||||
return mapJDAEntity(jda -> jda.getEmojiById(id), this::getEmoji);
|
||||
}
|
||||
|
||||
public DiscordCustomEmoji getEmoji(CustomEmoji jda) {
|
||||
return new DiscordCustomEmojiImpl(jda);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscordCommand.RegistrationResult registerCommand(DiscordCommand command) {
|
||||
return commandRegistry.register(command, false);
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.discordsrv.common.discord.api.entity.guild;
|
||||
|
||||
import com.discordsrv.api.discord.entity.guild.DiscordCustomEmoji;
|
||||
import net.dv8tion.jda.api.entities.emoji.CustomEmoji;
|
||||
|
||||
public class DiscordCustomEmojiImpl implements DiscordCustomEmoji {
|
||||
|
||||
private final CustomEmoji jda;
|
||||
|
||||
public DiscordCustomEmojiImpl(CustomEmoji jda) {
|
||||
this.jda = jda;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomEmoji asJDA() {
|
||||
return jda;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return jda.getIdLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return jda.getName();
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ import com.discordsrv.api.discord.events.message.DiscordMessageReceiveEvent;
|
||||
import com.discordsrv.api.discord.events.message.DiscordMessageUpdateEvent;
|
||||
import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.message.forward.discord.DiscordChatMessageForwardedEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.discord.DiscordChatMessageProcessEvent;
|
||||
import com.discordsrv.api.event.events.message.process.discord.DiscordChatMessageProcessEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.discord.DiscordChatMessageReceiveEvent;
|
||||
import com.discordsrv.api.placeholder.util.Placeholders;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
@ -60,6 +60,10 @@ public class DiscordChatMessageModule extends AbstractModule<DiscordSRV> {
|
||||
// Notably this excludes, 0x09 HT (\t), 0x0A LF (\n), 0x0B VT (\v) and 0x0D CR (\r) (which may be used for text formatting)
|
||||
private static final Pattern ASCII_CONTROL_FILTER = Pattern.compile("[\\u0000-\\u0008\\u000C\\u000E-\\u001F\\u007F]");
|
||||
|
||||
// A regex filter matching the unicode regular expression character category "Other Symbol"
|
||||
// https://unicode.org/reports/tr18/#General_Category_Property
|
||||
private static final Pattern EMOJI_FILTER = Pattern.compile("\\p{So}");
|
||||
|
||||
private final Map<String, MessageSend> sends = new ConcurrentHashMap<>();
|
||||
|
||||
public DiscordChatMessageModule(DiscordSRV discordSRV) {
|
||||
@ -188,16 +192,25 @@ public class DiscordChatMessageModule extends AbstractModule<DiscordSRV> {
|
||||
|
||||
Placeholders message = new Placeholders(event.getContent());
|
||||
message.replaceAll(ASCII_CONTROL_FILTER, "");
|
||||
if (chatConfig.unicodeEmojiBehaviour == DiscordToMinecraftChatConfig.EmojiBehaviour.HIDE) {
|
||||
message.replaceAll(EMOJI_FILTER, "");
|
||||
}
|
||||
chatConfig.contentRegexFilters.forEach(message::replaceAll);
|
||||
|
||||
String finalMessage = message.toString();
|
||||
if (StringUtils.isEmpty(finalMessage)) {
|
||||
if (finalMessage.trim().isEmpty()) {
|
||||
// No sending empty messages
|
||||
return;
|
||||
}
|
||||
|
||||
Component messageComponent = DiscordSRVMinecraftRenderer.getWithContext(guild, chatConfig, () ->
|
||||
discordSRV.componentFactory().minecraftSerializer().serialize(finalMessage));
|
||||
|
||||
if (discordSRV.componentFactory().plainSerializer().serialize(messageComponent).trim().isEmpty()) {
|
||||
// Check empty-ness again after rendering
|
||||
return;
|
||||
}
|
||||
|
||||
GameTextBuilder componentBuilder = discordSRV.componentFactory()
|
||||
.textBuilder(format)
|
||||
.addContext(discordMessage, author, channel, channelConfig)
|
||||
|
Loading…
Reference in New Issue
Block a user