[AB-349] supporting multiple embeds in templating mechanism

fixing paginator without embeds
This commit is contained in:
Sheldan
2021-12-08 16:26:11 +01:00
parent 0e7ea25aef
commit 7f5d17e4dc
13 changed files with 332 additions and 203 deletions

View File

@@ -8,7 +8,7 @@ import dev.sheldan.abstracto.core.model.PaginatorButtonPayload;
import dev.sheldan.abstracto.core.models.listener.ButtonClickedListenerModel;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.PaginatorServiceBean;
import dev.sheldan.abstracto.core.templating.model.EmbedConfiguration;
import dev.sheldan.abstracto.core.templating.model.MessageConfiguration;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.templating.service.TemplateServiceBean;
@@ -70,8 +70,8 @@ public class PaginatorButtonListener implements ButtonClickedListener {
return ButtonClickedListenerResult.IGNORED;
}
log.debug("Moving to page {} in paginator {}.", targetPage, payload.getPaginatorId());
EmbedConfiguration embedConfiguration = payload.getEmbedConfigs().get(targetPage);
MessageToSend messageToSend = templateServiceBean.convertEmbedConfigurationToMessageToSend(embedConfiguration);
MessageConfiguration messageConfiguration = payload.getEmbedConfigs().get(targetPage);
MessageToSend messageToSend = templateServiceBean.convertEmbedConfigurationToMessageToSend(messageConfiguration);
messageService.editMessageInChannel(model.getEvent().getMessageChannel(), messageToSend, originalMessage.getIdLong())
.thenAccept(unused -> log.info("Updated paginator {} to switch to page {}.", payload.getPaginatorId(), targetPage));
String accessorId = UUID.randomUUID().toString();

View File

@@ -1,7 +1,7 @@
package dev.sheldan.abstracto.core.model;
import dev.sheldan.abstracto.core.models.template.button.ButtonPayload;
import dev.sheldan.abstracto.core.templating.model.EmbedConfiguration;
import dev.sheldan.abstracto.core.templating.model.MessageConfiguration;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -12,7 +12,7 @@ import java.util.List;
@Setter
@Builder
public class PaginatorButtonPayload implements ButtonPayload {
private List<EmbedConfiguration> embedConfigs;
private List<MessageConfiguration> embedConfigs;
private String paginatorId;
private String exitButtonId;
private String startButtonId;

View File

@@ -1,7 +1,7 @@
package dev.sheldan.abstracto.core.model;
import dev.sheldan.abstracto.core.models.template.button.ButtonConfigModel;
import dev.sheldan.abstracto.core.templating.model.EmbedConfiguration;
import dev.sheldan.abstracto.core.templating.model.MessageConfiguration;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -12,7 +12,7 @@ import java.util.List;
@Setter
@Builder
public class PaginatorConfiguration {
private List<EmbedConfiguration> embedConfigs;
private List<MessageConfiguration> embedConfigs;
private String paginatorId;
private Long timeoutSeconds;
private Boolean restrictUser;

View File

@@ -205,26 +205,42 @@ public class ChannelServiceBean implements ChannelService {
}
List<CompletableFuture<Message>> futures = new ArrayList<>();
List<MessageAction> allMessageActions = new ArrayList<>();
int iterations = Math.min(messageToSend.getMessages().size(), messageToSend.getEmbeds().size());
for (int i = 0; i < iterations; i++) {
metricService.incrementCounter(MESSAGE_SEND_METRIC);
String text = messageToSend.getMessages().get(i);
MessageEmbed embed = messageToSend.getEmbeds().get(i);
MessageAction messageAction = textChannel.sendMessage(text).setEmbeds(embed);
allMessageActions.add(messageAction);
}
// one of these loops will get additional iterations, if the number is different, not both
for (int i = iterations; i < messageToSend.getMessages().size(); i++) {
Iterator<MessageEmbed> embedIterator = messageToSend.getEmbeds().iterator();
for (int i = 0; i < messageToSend.getMessages().size(); i++) {
metricService.incrementCounter(MESSAGE_SEND_METRIC);
String text = messageToSend.getMessages().get(i);
List<MessageEmbed> messageEmbeds = new ArrayList<>();
while(embedIterator.hasNext()) {
MessageEmbed embedToAdd = embedIterator.next();
if((currentEmbedLength(messageEmbeds) + embedToAdd.getLength()) >= MessageEmbed.EMBED_MAX_LENGTH_BOT) {
break;
}
messageEmbeds.add(embedToAdd);
embedIterator.remove();
}
MessageAction messageAction = textChannel.sendMessage(text);
if(!messageEmbeds.isEmpty()) {
messageAction.setEmbeds(messageEmbeds);
}
allMessageActions.add(messageAction);
}
for (int i = iterations; i < messageToSend.getEmbeds().size(); i++) {
List<MessageEmbed> messageEmbeds = new ArrayList<>();
// reset the iterator, because if the if in the above while iterator loop applied, we already took it out from the iterator
// but we didnt add it yet, so it would be lost
embedIterator = messageToSend.getEmbeds().iterator();
while(embedIterator.hasNext()) {
MessageEmbed embedToAdd = embedIterator.next();
if((currentEmbedLength(messageEmbeds) + embedToAdd.getLength()) >= MessageEmbed.EMBED_MAX_LENGTH_BOT && !messageEmbeds.isEmpty()) {
allMessageActions.add(textChannel.sendMessageEmbeds(messageEmbeds));
metricService.incrementCounter(MESSAGE_SEND_METRIC);
messageEmbeds = new ArrayList<>();
}
messageEmbeds.add(embedToAdd);
}
if(!messageEmbeds.isEmpty()) {
allMessageActions.add(textChannel.sendMessageEmbeds(messageEmbeds));
metricService.incrementCounter(MESSAGE_SEND_METRIC);
MessageEmbed embed = messageToSend.getEmbeds().get(i);
MessageAction messageAction = textChannel.sendMessageEmbeds(embed);
allMessageActions.add(messageAction);
}
List<ActionRow> actionRows = messageToSend.getActionRows();
@@ -270,6 +286,10 @@ public class ChannelServiceBean implements ChannelService {
return futures;
}
private Integer currentEmbedLength(List<MessageEmbed> messageEmbeds) {
return messageEmbeds.stream().mapToInt(MessageEmbed::getLength).sum();
}
@Override
public void editMessageInAChannel(MessageToSend messageToSend, AChannel channel, Long messageId) {
Optional<TextChannel> textChannelFromServer = getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());

View File

@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.model.PaginatorModel;
import dev.sheldan.abstracto.core.models.template.button.ButtonConfigModel;
import dev.sheldan.abstracto.core.service.management.ComponentPayloadManagementService;
import dev.sheldan.abstracto.core.templating.model.EmbedConfiguration;
import dev.sheldan.abstracto.core.templating.model.MessageConfiguration;
import dev.sheldan.abstracto.core.templating.model.EmbedFooter;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
@@ -109,8 +110,8 @@ public class PaginatorServiceBean implements PaginatorService {
configuration.setLastButton(initializeButton(lastButtonId, buttonPayload));
}
EmbedConfiguration embedConfiguration = configuration.getEmbedConfigs().get(0);
MessageToSend messageToSend = templateServiceBean.convertEmbedConfigurationToMessageToSend(embedConfiguration);
MessageConfiguration messageConfiguration = configuration.getEmbedConfigs().get(0);
MessageToSend messageToSend = templateServiceBean.convertEmbedConfigurationToMessageToSend(messageConfiguration);
List<CompletableFuture<Message>> paginatorFutures = channelService.sendMessageToSendToChannel(messageToSend, textChannel);
return FutureUtils.toSingleFutureGeneric(paginatorFutures)
.thenAccept(unused -> self.setupButtonPayloads(paginatorFutures.get(0).join(), configuration, serverId, buttonPayload));
@@ -124,11 +125,15 @@ public class PaginatorServiceBean implements PaginatorService {
.pageCount(configuration.getEmbedConfigs().size())
.build();
String footerText = templateService.renderTemplate(PAGINATOR_FOOTER_TEMPLATE_KEY, paginatorModel);
EmbedConfiguration embedConfiguration = configuration.getEmbedConfigs().get(i);
if(embedConfiguration.getFooter() == null) {
embedConfiguration.setFooter(EmbedFooter.builder().text(footerText).build());
MessageConfiguration messageConfig = configuration.getEmbedConfigs().get(i);
if(messageConfig.getEmbeds() == null || messageConfig.getEmbeds().isEmpty()) {
messageConfig.setEmbeds(new ArrayList<>(Arrays.asList(EmbedConfiguration.builder().build())));
}
EmbedConfiguration messageConfiguration = messageConfig.getEmbeds().get(0);
if(messageConfiguration.getFooter() == null) {
messageConfiguration.setFooter(EmbedFooter.builder().text(footerText).build());
} else {
embedConfiguration.getFooter().setText(footerText);
messageConfiguration.getFooter().setText(footerText);
}
}
}

View File

@@ -7,10 +7,6 @@ import lombok.Setter;
import java.time.OffsetDateTime;
import java.util.List;
/**
* The whole container object used to deserialize the whole embed configuration
* https://raw.githubusercontent.com/DV8FromTheWorld/JDA/assets/assets/docs/embeds/07-addField.png
*/
@Getter
@Setter
@Builder
@@ -51,11 +47,6 @@ public class EmbedConfiguration {
* The {@link OffsetDateTime} object used as the time stamp in the {@link net.dv8tion.jda.api.entities.MessageEmbed}
*/
private OffsetDateTime timeStamp;
private Long referencedMessageId;
/**
* The message which is posted along the {@link net.dv8tion.jda.api.entities.MessageEmbed} as a normal message.
*/
private String additionalMessage;
private MetaEmbedConfiguration metaConfig;
private List<ButtonConfig> buttons;
}

View File

@@ -24,7 +24,7 @@ public class EmbedField {
* This means, if multiple fields can be put on the same height in the {@link net.dv8tion.jda.api.entities.MessageEmbed} this will be done by discord.
*/
private Boolean inline;
private Boolean forceNewMessage;
private Boolean forceNewEmbed;
/**
* this will actively limit the length, not create another field
*/

View File

@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.core.templating.model;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* The whole container object used to deserialize the whole embed configuration
* https://raw.githubusercontent.com/DV8FromTheWorld/JDA/assets/assets/docs/embeds/07-addField.png
*/
@Getter
@Setter
@Builder
public class MessageConfiguration {
private List<EmbedConfiguration> embeds;
private Long referencedMessageId;
/**
* The message which is posted along the {@link net.dv8tion.jda.api.entities.MessageEmbed} as a normal message.
*/
private String additionalMessage;
private MetaMessageConfiguration messageConfig;
private List<ButtonConfig> buttons;
}

View File

@@ -8,19 +8,6 @@ import lombok.Setter;
@Setter
@Builder
public class MetaEmbedConfiguration {
private Integer additionalMessageLengthLimit;
private Integer additionalMessageSplitLength;
private Integer descriptionMessageLengthLimit;
private Integer messageLimit;
@Builder.Default
private boolean ephemeral = false;
private boolean preventEmptyEmbed;
private boolean allowsRoleMention;
private boolean allowsEveryoneMention;
@Builder.Default
private boolean allowsUserMention = true;
@Builder.Default
private boolean mentionsReferencedMessage = true;
}

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.core.templating.model;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class MetaMessageConfiguration {
@Builder.Default
private boolean ephemeral = false;
private boolean allowsRoleMention;
private boolean allowsEveryoneMention;
@Builder.Default
private boolean allowsUserMention = true;
@Builder.Default
private boolean mentionsReferencedMessage = true;
private Integer messageLimit;
private Integer additionalMessageLengthLimit;
private Integer additionalMessageSplitLength;
}

View File

@@ -67,9 +67,9 @@ public class TemplateServiceBean implements TemplateService {
/**
* Retrieves the key which gets suffixed with '_embed' and this retrieves the embed configuration. This configuration is then rendered
* and de-serialized with GSON into a {@link EmbedConfiguration} object. This object is then rendered into a {@link MessageToSend} and returned.
* and de-serialized with GSON into a {@link MessageConfiguration} object. This object is then rendered into a {@link MessageToSend} and returned.
* If the individual element do not fit in an embed, for example, if the field count is to high, another embed will be created in the {@link MessageToSend} object.
* If multiple embeds are necessary to provide what the {@link EmbedConfiguration} wanted, this method will automatically set the footer of the additional {@link MessageEmbed}
* If multiple embeds are necessary to provide what the {@link MessageConfiguration} wanted, this method will automatically set the footer of the additional {@link MessageEmbed}
* with a formatted page count.
* This method will to try its best to provided a message which can be handled by discord without rejecting it. Besides that, the content from the rendered template, will be passed
* into the {@link EmbedBuilder} directly.
@@ -81,35 +81,21 @@ public class TemplateServiceBean implements TemplateService {
@Override
public MessageToSend renderEmbedTemplate(String key, Object model) {
String embedConfig = this.renderTemplate(key + "_embed", model);
EmbedConfiguration embedConfiguration = gson.fromJson(embedConfig, EmbedConfiguration.class);
return convertEmbedConfigurationToMessageToSend(embedConfiguration);
MessageConfiguration messageConfiguration = gson.fromJson(embedConfig, MessageConfiguration.class);
return convertEmbedConfigurationToMessageToSend(messageConfiguration);
}
public MessageToSend convertEmbedConfigurationToMessageToSend(EmbedConfiguration embedConfiguration) {
public MessageToSend convertEmbedConfigurationToMessageToSend(MessageConfiguration messageConfiguration) {
List<EmbedBuilder> embedBuilders = new ArrayList<>();
embedBuilders.add(new EmbedBuilder());
if(embedConfiguration.getMetaConfig() != null &&
embedConfiguration.getDescription() != null &&
embedConfiguration.getMetaConfig().getDescriptionMessageLengthLimit() != null &&
embedConfiguration.getDescription().length() > embedConfiguration.getMetaConfig().getDescriptionMessageLengthLimit())
{
embedConfiguration.setDescription(embedConfiguration.getDescription().substring(0,
embedConfiguration.getMetaConfig().getDescriptionMessageLengthLimit()));
}
String description = embedConfiguration.getDescription();
if (description != null) {
handleEmbedDescription(embedBuilders, description);
}
EmbedAuthor author = embedConfiguration.getAuthor();
EmbedBuilder firstBuilder = embedBuilders.get(0);
if (author != null) {
firstBuilder.setAuthor(author.getName(), author.getUrl(), author.getAvatar());
if(messageConfiguration.getEmbeds() != null && !messageConfiguration.getEmbeds().isEmpty()) {
convertEmbeds(messageConfiguration, embedBuilders);
}
List<ActionRow> buttons = new ArrayList<>();
Map<String, MessageToSend.ComponentConfig> componentPayloads = new HashMap<>();
if(embedConfiguration.getButtons() != null) {
if(messageConfiguration.getButtons() != null) {
ActionRow currentRow = null;
for (ButtonConfig buttonConfig : embedConfiguration.getButtons()) {
for (ButtonConfig buttonConfig : messageConfiguration.getButtons()) {
ButtonMetaConfig metaConfig = buttonConfig.getMetaConfig() != null ? buttonConfig.getMetaConfig() : null;
String id = metaConfig != null && Boolean.TRUE.equals(metaConfig.getGenerateRandomUUID()) ?
UUID.randomUUID().toString() : buttonConfig.getId();
@@ -155,57 +141,36 @@ public class TemplateServiceBean implements TemplateService {
}
}
String thumbnail = embedConfiguration.getThumbnail();
if (thumbnail != null) {
firstBuilder.setThumbnail(thumbnail);
}
EmbedTitle title = embedConfiguration.getTitle();
if (title != null) {
firstBuilder.setTitle(title.getTitle(), title.getUrl());
}
EmbedFooter footer = embedConfiguration.getFooter();
if (footer != null) {
firstBuilder.setFooter(footer.getText(), footer.getIcon());
}
if (embedConfiguration.getFields() != null) {
createFieldsForEmbed(embedBuilders, embedConfiguration);
}
firstBuilder.setTimestamp(embedConfiguration.getTimeStamp());
firstBuilder.setImage(embedConfiguration.getImageUrl());
EmbedColor color = embedConfiguration.getColor();
if (color != null) {
int colorToSet = new Color(color.getR(), color.getG(), color.getB()).getRGB();
embedBuilders.forEach(embedBuilder -> embedBuilder.setColor(colorToSet));
}
setPagingFooters(embedBuilders);
List<MessageEmbed> embeds = new ArrayList<>();
if ((embedBuilders.size() > 1 || !embedBuilders.get(0).isEmpty()) && !isEmptyEmbed(embedConfiguration)) {
embeds = embedBuilders.stream().map(EmbedBuilder::build).collect(Collectors.toList());
if (!embedBuilders.isEmpty()) {
embeds = embedBuilders
.stream()
.filter(embedBuilder -> !embedBuilder.isEmpty())
.map(EmbedBuilder::build)
.collect(Collectors.toList());
}
List<String> messages = new ArrayList<>();
if(
embedConfiguration.getMetaConfig() != null &&
embedConfiguration.getMetaConfig().getAdditionalMessageLengthLimit() != null &&
embedConfiguration.getAdditionalMessage().length() > embedConfiguration.getMetaConfig().getAdditionalMessageLengthLimit()
messageConfiguration.getMessageConfig() != null &&
messageConfiguration.getMessageConfig().getAdditionalMessageLengthLimit() != null &&
messageConfiguration.getAdditionalMessage().length() > messageConfiguration.getMessageConfig().getAdditionalMessageLengthLimit()
) {
embedConfiguration.setAdditionalMessage(embedConfiguration.getAdditionalMessage().substring(0, embedConfiguration.getMetaConfig().getAdditionalMessageLengthLimit()));
messageConfiguration.setAdditionalMessage(messageConfiguration.getAdditionalMessage().substring(0, messageConfiguration.getMessageConfig().getAdditionalMessageLengthLimit()));
}
boolean isEphemeral = false;
if(embedConfiguration.getMetaConfig() != null) {
isEphemeral = Boolean.TRUE.equals(embedConfiguration.getMetaConfig().isEphemeral());
if(messageConfiguration.getMessageConfig() != null) {
isEphemeral = Boolean.TRUE.equals(messageConfiguration.getMessageConfig().isEphemeral());
}
String additionalMessage = embedConfiguration.getAdditionalMessage();
String additionalMessage = messageConfiguration.getAdditionalMessage();
if(additionalMessage != null) {
Long segmentLimit = embedConfiguration.getMetaConfig() != null
&& embedConfiguration.getMetaConfig().getAdditionalMessageSplitLength() != null ?
embedConfiguration.getMetaConfig().getAdditionalMessageSplitLength() :
Long segmentLimit = messageConfiguration.getMessageConfig() != null
&& messageConfiguration.getMessageConfig().getAdditionalMessageSplitLength() != null ?
messageConfiguration.getMessageConfig().getAdditionalMessageSplitLength() :
Long.valueOf(Message.MAX_CONTENT_LENGTH);
if(additionalMessage.length() > segmentLimit) {
int segmentStart = 0;
@@ -233,8 +198,8 @@ public class TemplateServiceBean implements TemplateService {
if(serverContext.getServerId() != null) {
messageLimit = Math.min(messageLimit, configService.getLongValueOrConfigDefault(CoreFeatureConfig.MAX_MESSAGES_KEY, serverContext.getServerId()));
}
if(embedConfiguration.getMetaConfig() != null && embedConfiguration.getMetaConfig().getMessageLimit() != null) {
messageLimit = Math.min(messageLimit, embedConfiguration.getMetaConfig().getMessageLimit());
if(messageConfiguration.getMessageConfig() != null && messageConfiguration.getMessageConfig().getMessageLimit() != null) {
messageLimit = Math.min(messageLimit, messageConfiguration.getMessageConfig().getMessageLimit());
}
if(embeds.size() > messageLimit) {
log.info("Limiting size of embeds. Max allowed: {}, currently: {}.", messageLimit, embeds.size());
@@ -244,11 +209,11 @@ public class TemplateServiceBean implements TemplateService {
log.info("Limiting size of messages. Max allowed: {}, currently: {}.", messageLimit, messages.size());
messages.subList(messageLimit.intValue(), messages.size()).clear();
}
Long referencedMessageId = embedConfiguration.getReferencedMessageId();
Long referencedMessageId = messageConfiguration.getReferencedMessageId();
return MessageToSend.builder()
.embeds(embeds)
.messageConfig(createMessageConfig(embedConfiguration.getMetaConfig()))
.messageConfig(createMessageConfig(messageConfiguration.getMessageConfig()))
.messages(messages)
.ephemeral(isEphemeral)
.actionRows(buttons)
@@ -257,16 +222,75 @@ public class TemplateServiceBean implements TemplateService {
.build();
}
private MessageConfig createMessageConfig(MetaEmbedConfiguration metaEmbedConfiguration) {
if(metaEmbedConfiguration == null) {
private void convertEmbeds(MessageConfiguration messageConfiguration, List<EmbedBuilder> embedBuilders) {
int currentEffectiveEmbed;
for (int embedIndex = 0; embedIndex < messageConfiguration.getEmbeds().size(); embedIndex++) {
currentEffectiveEmbed = embedBuilders.size();
EmbedConfiguration embedConfiguration = messageConfiguration.getEmbeds().get(embedIndex);
if(isEmptyEmbed(embedConfiguration)) {
continue;
}
EmbedBuilder mainEmbedBuilder = new EmbedBuilder();
if(embedConfiguration.getMetaConfig() != null &&
embedConfiguration.getDescription() != null &&
embedConfiguration.getMetaConfig().getDescriptionMessageLengthLimit() != null &&
embedConfiguration.getDescription().length() > embedConfiguration.getMetaConfig().getDescriptionMessageLengthLimit())
{
embedConfiguration.setDescription(embedConfiguration.getDescription().substring(0,
embedConfiguration.getMetaConfig().getDescriptionMessageLengthLimit()));
}
EmbedAuthor author = embedConfiguration.getAuthor();
if (author != null) {
mainEmbedBuilder.setAuthor(author.getName(), author.getUrl(), author.getAvatar());
}
String thumbnail = embedConfiguration.getThumbnail();
if (thumbnail != null) {
mainEmbedBuilder.setThumbnail(thumbnail);
}
EmbedTitle title = embedConfiguration.getTitle();
if (title != null) {
mainEmbedBuilder.setTitle(title.getTitle(), title.getUrl());
}
EmbedFooter footer = embedConfiguration.getFooter();
if (footer != null) {
mainEmbedBuilder.setFooter(footer.getText(), footer.getIcon());
}
mainEmbedBuilder.setTimestamp(embedConfiguration.getTimeStamp());
mainEmbedBuilder.setImage(embedConfiguration.getImageUrl());
embedBuilders.add(mainEmbedBuilder);
String description = embedConfiguration.getDescription();
if (description != null) {
handleEmbedDescription(embedBuilders, description);
}
if (embedConfiguration.getFields() != null) {
createFieldsForEmbed(embedBuilders, embedConfiguration);
}
EmbedColor color = embedConfiguration.getColor();
if (color != null) {
int colorToSet = new Color(color.getR(), color.getG(), color.getB()).getRGB();
for (int i = currentEffectiveEmbed; i < embedBuilders.size(); i++) {
EmbedBuilder embedBuilder = embedBuilders.get(i);
embedBuilder.setColor(colorToSet);
}
}
}
}
private MessageConfig createMessageConfig(MetaMessageConfiguration messageconfiguration) {
if(messageconfiguration == null) {
return null;
}
return MessageConfig
.builder()
.allowsEveryoneMention(metaEmbedConfiguration.isAllowsEveryoneMention())
.allowsUserMention(metaEmbedConfiguration.isAllowsUserMention())
.allowsRoleMention(metaEmbedConfiguration.isAllowsRoleMention())
.mentionsReferencedMessage(metaEmbedConfiguration.isMentionsReferencedMessage())
.allowsEveryoneMention(messageconfiguration.isAllowsEveryoneMention())
.allowsUserMention(messageconfiguration.isAllowsUserMention())
.allowsRoleMention(messageconfiguration.isAllowsRoleMention())
.mentionsReferencedMessage(messageconfiguration.isMentionsReferencedMessage())
.build();
}
@@ -278,7 +302,8 @@ public class TemplateServiceBean implements TemplateService {
}
private void handleEmbedDescription(List<EmbedBuilder> embedBuilders, String description) {
int segmentCounter = 0;
// we need to start with the "current" one, and can then extend onto it
int segmentCounter = Math.max(embedBuilders.size() - 1, 0);
int segmentStart = 0;
int segmentEnd = MessageEmbed.TEXT_MAX_LENGTH;
int handledIndex = 0;
@@ -334,6 +359,10 @@ public class TemplateServiceBean implements TemplateService {
}
}
/**
* This method limits the fields: if there are limits configured.
* It also splits the fields into multiple fields, if the length is over the limit. The newly created fields, get a title with a suffixed 2.
*/
private void splitFieldsIntoAppropriateLengths(EmbedConfiguration configuration) {
Comparator<AdditionalEmbedField> comparator = Comparator.comparing(o -> o.fieldIndex);
// we need to reverse this, because the insertion need to be done from the back to the front, because we only insert according to field index
@@ -358,19 +387,27 @@ public class TemplateServiceBean implements TemplateService {
int handledIndex = 0;
String fullFieldValue = field.getValue();
while(handledIndex < fullFieldValue.length()) {
// lets determine how much text we can handle, if we iterated multiple times over this, the segement
// start has a value, so some things are cut off
int segmentLength = fullFieldValue.length() - segmentStart;
// if its over the hard limit for a field
if(segmentLength > MessageEmbed.VALUE_MAX_LENGTH) {
// find the last space in the text, as a natural "splitting point"
int lastSpace = fullFieldValue.substring(segmentStart, segmentEnd).lastIndexOf(" ");
if(lastSpace != -1) {
// and use this as the new end
segmentEnd = segmentStart + lastSpace;
}
} else {
// just use the full length
segmentEnd = fullFieldValue.length();
}
// cut the field value to be appropriate
String fieldValue = fullFieldValue.substring(segmentStart, segmentEnd);
if(segmentCounter == 0) {
field.setValue(fieldValue);
} else {
// if we are in an additional segment, we have to create a new embed field, to hold our values
EmbedField newField = EmbedField
.builder()
.inline(field.getInline())
@@ -386,6 +423,7 @@ public class TemplateServiceBean implements TemplateService {
}
}
}
// insert additional fields
for (AdditionalEmbedField field : toInsert) {
configuration.getFields().add(field.getFieldIndex() + 1, field.getField());
}
@@ -393,24 +431,30 @@ public class TemplateServiceBean implements TemplateService {
private void createFieldsForEmbed(List<EmbedBuilder> embedBuilders, EmbedConfiguration configuration) {
splitFieldsIntoAppropriateLengths(configuration);
int actualCurrentIndex = 0;
int neededMessages = 0;
int embedLocalFieldIndex = 0;
int neededEmbeds = embedBuilders.size() - 1;
for (int i = 0; i < configuration.getFields().size(); i++) {
EmbedField field = configuration.getFields().get(i);
boolean lastMessageInEmbed = ((actualCurrentIndex + 1) % MAX_FIELD_COUNT) == 0;
boolean isStartOfNewMessage = (actualCurrentIndex % MAX_FIELD_COUNT) == 0;
boolean newMessageForcedWithinEmbeds = Boolean.TRUE.equals(field.getForceNewMessage()) && !lastMessageInEmbed;
boolean startOfNewMessage = actualCurrentIndex != 0 && isStartOfNewMessage;
if (newMessageForcedWithinEmbeds || startOfNewMessage) {
actualCurrentIndex = 0;
neededMessages++;
// determine if we are the last field allowed in this embed
boolean lastMessageInEmbed = ((embedLocalFieldIndex + 1) % MAX_FIELD_COUNT) == 0;
// determine if we are at the beginning of a new message, that means we have the embed index 0
boolean isStartOfNewEmbed = (embedLocalFieldIndex % MAX_FIELD_COUNT) == 0;
// whether or not we have to force a new embed, but only if we are not the last message, then its fine anyway
boolean newMessageForcedWithinEmbeds = Boolean.TRUE.equals(field.getForceNewEmbed()) && !lastMessageInEmbed;
// if we are at the start of an _additional_ embed, this is false at the first embed
boolean startOfNewMessage = embedLocalFieldIndex != 0 && isStartOfNewEmbed;
int fieldLength = field.getName().length() + field.getValue().length();
boolean currentEmbedOverTotalLimit = (embedBuilders.get(neededEmbeds).length() + fieldLength) > MessageEmbed.EMBED_MAX_LENGTH_BOT;
if (newMessageForcedWithinEmbeds || startOfNewMessage || currentEmbedOverTotalLimit) {
embedLocalFieldIndex = 0;
neededEmbeds++;
} else {
actualCurrentIndex++;
embedLocalFieldIndex++;
}
extendIfNecessary(embedBuilders, neededMessages);
extendIfNecessary(embedBuilders, neededEmbeds);
EmbedField embedField = configuration.getFields().get(i);
boolean inline = embedField.getInline() != null ? embedField.getInline() : Boolean.FALSE;
embedBuilders.get(neededMessages).addField(embedField.getName(), embedField.getValue(), inline);
embedBuilders.get(neededEmbeds).addField(embedField.getName(), embedField.getValue(), inline);
}
Comparator<AdditionalEmbed> comparator = Comparator.comparing(o -> o.embedIndex);
// we need to reverse this, because the insertion need to be done from the back to the front, because we only insert according to field index