[AB-74] changing description and field splitting leading to no fractured texts, decision is based on the last space

removing "safeFieldIteration" as its not necessary anymore
splitting up embeds for the embed size limit
This commit is contained in:
Sheldan
2021-02-21 02:50:57 +01:00
parent 9db5889160
commit 20b6b37151
5 changed files with 308 additions and 256 deletions

View File

@@ -3,7 +3,6 @@ package dev.sheldan.abstracto.core.templating.config;
import dev.sheldan.abstracto.core.templating.loading.DatabaseTemplateLoader;
import dev.sheldan.abstracto.core.templating.method.DateMethod;
import dev.sheldan.abstracto.core.templating.method.DurationMethod;
import dev.sheldan.abstracto.core.templating.method.SafeFieldIterations;
import dev.sheldan.abstracto.core.templating.model.database.AutoLoadMacro;
import dev.sheldan.abstracto.core.templating.service.management.AutoLoadMacroManagementService;
import freemarker.template.Configuration;
@@ -32,9 +31,6 @@ public class FreemarkerConfiguration {
@Autowired
private DateMethod instantMethod;
@Autowired
private SafeFieldIterations safeFieldIterations;
@Autowired
private AutoLoadMacroManagementService macroManagementService;
@@ -51,7 +47,6 @@ public class FreemarkerConfiguration {
Configuration configuration = factory.createConfiguration();
configuration.setSharedVariable("fmtDuration", durationMethod);
configuration.setSharedVariable("formatDate", instantMethod);
configuration.setSharedVariable("safeFieldLength", safeFieldIterations);
List<String> macrosToLoad = macroManagementService.loadAllMacros().stream()
.map(AutoLoadMacro::getKey).collect(Collectors.toList());
configuration.setAutoIncludes(macrosToLoad);

View File

@@ -1,95 +0,0 @@
package dev.sheldan.abstracto.core.templating.method;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import freemarker.template.DefaultListAdapter;
import freemarker.template.SimpleScalar;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@Component
public class SafeFieldIterations implements TemplateMethodModelEx {
@Autowired
private TemplateService service;
@Override
public Object exec(List arguments) throws TemplateModelException {
if(arguments.size() != 4) {
throw new TemplateModelException("Incorrect amount of parameters.");
}
Object adapterObject = arguments.get(0);
if(!(adapterObject instanceof DefaultListAdapter)) {
throw new TemplateModelException("Passed object was not a DefaultListAdapter.");
}
Object wrappedList = ((DefaultListAdapter) adapterObject).getWrappedObject();
if(!(wrappedList instanceof List)) {
throw new TemplateModelException("Passed object was not a List.");
}
List wrappedObject = (List) wrappedList;
Object templateParameter = arguments.get(1);
if(!(templateParameter instanceof SimpleScalar)) {
throw new TemplateModelException("Passed object for template was not a SimpleScalar.");
}
String appliedTemplate = ((SimpleScalar) templateParameter).getAsString();
Object fieldNameTemplateParameter = arguments.get(2);
if(!(fieldNameTemplateParameter instanceof SimpleScalar)) {
throw new TemplateModelException("Passed object for field name template was not a SimpleScalar.");
}
String fieldNameTemplate = ((SimpleScalar) fieldNameTemplateParameter).getAsString();
Object inlineParameter = arguments.get(3);
if(!(inlineParameter instanceof SimpleScalar)) {
throw new TemplateModelException("Passed object for inline was not a SimpleScalar.");
}
String inline = ((SimpleScalar) inlineParameter).getAsString();
List<StringBuilder> result = new ArrayList<>();
StringBuilder currentBuilder = new StringBuilder();
String firstEmbedTitle = service.renderTemplateWithMap(fieldNameTemplate, getEmbedCountParameters(1, wrappedObject));
currentBuilder.append(newFieldHeader(firstEmbedTitle, inline));
String finalClosingString = "\"}";
String closingString = finalClosingString + ",";
int splitFieldCounts = 1;
for (Object ob: wrappedObject) {
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("object", ob);
String s = service.renderTemplateWithMap(appliedTemplate, parameters);
if((currentBuilder.toString().length() + s.length() > 1024)) {
currentBuilder.append(closingString);
result.add(currentBuilder);
currentBuilder = new StringBuilder();
splitFieldCounts += 1;
String renderedName = service.renderTemplateWithMap(fieldNameTemplate, getEmbedCountParameters(splitFieldCounts, wrappedObject));
currentBuilder.append(newFieldHeader(renderedName, inline));
}
currentBuilder.append(s);
}
currentBuilder.append(finalClosingString);
result.add(currentBuilder);
StringBuilder bigBuilder = new StringBuilder();
for (StringBuilder innerBuilder: result) {
bigBuilder.append(innerBuilder.toString());
}
return bigBuilder.toString();
}
private String newFieldHeader(String name, String inline) {
return String.format("{ \"name\": \"%s\", \"inline\": \"%s\", \"value\": \"", name, inline);
}
private HashMap<String, Object> getEmbedCountParameters(Integer count, List<? extends Object> objects) {
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("count", count);
parameters.put("list", objects);
return parameters;
}
}

View File

@@ -8,6 +8,9 @@ import dev.sheldan.abstracto.core.templating.model.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;
@@ -17,8 +20,7 @@ import org.springframework.stereotype.Component;
import java.awt.*;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
@@ -72,12 +74,7 @@ public class TemplateServiceBean implements TemplateService {
embedBuilders.add(new EmbedBuilder());
String description = embedConfiguration.getDescription();
if (description != null) {
double neededIndices = Math.ceil(description.length() / (double) MessageEmbed.TEXT_MAX_LENGTH) - 1;
extendIfNecessary(embedBuilders, neededIndices);
for (int i = 0; i < neededIndices + 1; i++) {
String descriptionText = description.substring(MessageEmbed.TEXT_MAX_LENGTH * i, Math.min(MessageEmbed.TEXT_MAX_LENGTH * (i + 1), description.length()));
embedBuilders.get(i).setDescription(descriptionText);
}
handleEmbedDescription(embedBuilders, description);
}
EmbedAuthor author = embedConfiguration.getAuthor();
EmbedBuilder firstBuilder = embedBuilders.get(0);
@@ -110,6 +107,8 @@ public class TemplateServiceBean implements TemplateService {
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());
@@ -121,6 +120,38 @@ public class TemplateServiceBean implements TemplateService {
.build();
}
private void setPagingFooters(List<EmbedBuilder> embedBuilders) {
// the first footer comes from the configuration
for (int i = 1; i < embedBuilders.size(); i++) {
embedBuilders.get(i).setFooter(getPageString(i + 1));
}
}
private void handleEmbedDescription(List<EmbedBuilder> embedBuilders, String description) {
int segmentCounter = 0;
int segmentStart = 0;
int segmentEnd = MessageEmbed.TEXT_MAX_LENGTH;
int handledIndex = 0;
while(handledIndex < description.length()) {
int segmentLength = description.length() - segmentStart;
if(segmentLength > MessageEmbed.TEXT_MAX_LENGTH) {
int lastSpace = description.substring(segmentStart, segmentEnd).lastIndexOf(" ");
if(lastSpace != -1) {
segmentEnd = segmentStart + lastSpace;
}
} else {
segmentEnd = description.length();
}
String descriptionText = description.substring(segmentStart, segmentEnd);
extendIfNecessary(embedBuilders, segmentCounter);
embedBuilders.get(segmentCounter).setDescription(descriptionText);
segmentCounter++;
handledIndex = segmentEnd;
segmentStart = segmentEnd;
segmentEnd += MessageEmbed.TEXT_MAX_LENGTH;
}
}
@Override
public MessageToSend renderEmbedTemplate(String key, Object model, Long serverId) {
try {
@@ -153,16 +184,56 @@ public class TemplateServiceBean implements TemplateService {
}
}
private void createFieldsForEmbed(List<EmbedBuilder> embedBuilders, EmbedConfiguration configuration) {
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
// and we need to insert the "first" element last, so it actually gets the correct field index
comparator = comparator.thenComparing(additionalEmbedField -> additionalEmbedField.innerFieldIndex).reversed();
TreeSet<AdditionalEmbedField> toInsert = new TreeSet<>(comparator);
for (int i = 0; i < configuration.getFields().size(); i++) {
EmbedField field = configuration.getFields().get(i);
if (field != null && field.getValue() != null && field.getValue().length() > MessageEmbed.VALUE_MAX_LENGTH) {
String substring = field.getValue().substring(MessageEmbed.VALUE_MAX_LENGTH);
field.setValue(field.getValue().substring(0, MessageEmbed.VALUE_MAX_LENGTH));
EmbedField secondPart = EmbedField.builder().inline(field.getInline()).name(field.getName() + " 2").value(substring).build();
configuration.getFields().add(i + 1, secondPart);
int segmentCounter = 0;
int segmentStart = 0;
int segmentEnd = MessageEmbed.VALUE_MAX_LENGTH;
int handledIndex = 0;
String fullFieldValue = field.getValue();
while(handledIndex < fullFieldValue.length()) {
int segmentLength = fullFieldValue.length() - segmentStart;
if(segmentLength > MessageEmbed.VALUE_MAX_LENGTH) {
int lastSpace = fullFieldValue.substring(segmentStart, segmentEnd).lastIndexOf(" ");
if(lastSpace != -1) {
segmentEnd = segmentStart + lastSpace;
}
} else {
segmentEnd = fullFieldValue.length();
}
String fieldValue = fullFieldValue.substring(segmentStart, segmentEnd);
if(segmentCounter == 0) {
field.setValue(fieldValue);
} else {
EmbedField newField = EmbedField
.builder()
.inline(field.getInline())
.name(field.getName() + " " + (segmentCounter + 1))
.value(fieldValue).build();
AdditionalEmbedField additionalField = new AdditionalEmbedField(i, segmentCounter, newField);
toInsert.add(additionalField);
}
segmentCounter++;
handledIndex = segmentEnd;
segmentStart = segmentEnd;
segmentEnd += MessageEmbed.VALUE_MAX_LENGTH;
}
}
}
for (AdditionalEmbedField field : toInsert) {
configuration.getFields().add(field.getFieldIndex() + 1, field.getField());
}
}
private void createFieldsForEmbed(List<EmbedBuilder> embedBuilders, EmbedConfiguration configuration) {
splitFieldsIntoAppropriateLengths(configuration);
int actualCurrentIndex = 0;
int neededMessages = 0;
for (int i = 0; i < configuration.getFields().size(); i++) {
@@ -182,6 +253,67 @@ public class TemplateServiceBean implements TemplateService {
boolean inline = embedField.getInline() != null ? embedField.getInline() : Boolean.FALSE;
embedBuilders.get(neededMessages).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
// and we need to insert the "first" element last, so it actually gets the correct field index
comparator = comparator.thenComparing(additionalEmbedField -> additionalEmbedField.innerEmbedIndex).reversed();
TreeSet<AdditionalEmbed> toInsert = new TreeSet<>(comparator);
for (int i = 0; i < embedBuilders.size(); i++) {
EmbedBuilder embedBuilder = embedBuilders.get(i);
if(!embedBuilder.isValidLength()) {
int totalFieldLength = 0;
// we need to calculate the length without fields this way, because the title property is not public
for (MessageEmbed.Field field: embedBuilder.getFields()) {
totalFieldLength += getFieldLength(field);
}
int currentEmbedLength = embedBuilder.length() - totalFieldLength;
List<MessageEmbed.Field> toRemove = new ArrayList<>();
EmbedBuilder newlyAddedEmbed = new EmbedBuilder();
boolean addToNew = false;
boolean createNewEmbed;
int additionalEmbedIndex = 0;
for (int j = 0; j < embedBuilder.getFields().size(); j++) {
MessageEmbed.Field field = embedBuilder.getFields().get(j);
int fieldLength = getFieldLength(field);
if(currentEmbedLength + fieldLength > MessageEmbed.EMBED_MAX_LENGTH_BOT) {
createNewEmbed = true;
addToNew = true;
currentEmbedLength = 0;
additionalEmbedIndex++;
} else {
createNewEmbed = false;
}
if(createNewEmbed) {
// TODO this always creates a new embed, and does not re-use the existing ones
newlyAddedEmbed = new EmbedBuilder();
toInsert.add(new AdditionalEmbed(i, additionalEmbedIndex, newlyAddedEmbed));
}
if(addToNew) {
toRemove.add(field);
newlyAddedEmbed.addField(field);
}
currentEmbedLength += fieldLength;
}
embedBuilder.getFields().removeAll(toRemove);
}
}
for (AdditionalEmbed embed : toInsert) {
embedBuilders.add(embed.getEmbedIndex() + embed.getInnerEmbedIndex(), embed.getEmbedBuilder());
}
}
private int getFieldLength(MessageEmbed.Field field) {
int nameLength = 0;
if(field.getName() != null) {
nameLength = field.getName().length();
}
int valueLength = 0;
if(field.getValue() != null) {
valueLength = field.getValue().length();
}
return nameLength + valueLength;
}
/**
@@ -317,4 +449,26 @@ public class TemplateServiceBean implements TemplateService {
public void clearCache() {
configuration.getCacheStorage().clear();
}
@Getter
@Setter
@AllArgsConstructor
private class AdditionalEmbedField {
// this is the index of the field where this additional field came from
private Integer fieldIndex;
// this is the index within the field, which means, a field might have been split into three fields
// and in this case this value defines which respective part of that field it is, this is required to
// keep the order of the created fields
private Integer innerFieldIndex;
private EmbedField field;
}
@Getter
@Setter
@AllArgsConstructor
private class AdditionalEmbed {
private Integer embedIndex;
private Integer innerEmbedIndex;
private EmbedBuilder embedBuilder;
}
}

View File

@@ -1,139 +0,0 @@
package dev.sheldan.abstracto.core.templating.method;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import freemarker.template.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class SafeFieldIterationsTest {
public static final String TEMPLATE_KEY = "template";
public static final String FIELD_NAME_TEMPLATE = "fieldName";
public static final String FIELD_NAME_VALUE = "fieldName";
public static final String EXPECTED_START_PART = "{ \"name\": \"" + FIELD_NAME_VALUE + "\", \"inline\": \"true\", \"value\": \"";
public static final String INLINE_VALUE = "true";
public static final String FIRST_LIST_ENTRY = "text";
public static final String SIX_HUNDRED_CHARACTERS = RandomStringUtils.randomAlphabetic(600);
@InjectMocks
private SafeFieldIterations safeFieldIterations;
@Mock
private TemplateService templateService;
@Captor
private ArgumentCaptor<String> templateKeyCaptor;
@Before
public void setup() {
when(templateService.renderTemplateWithMap(eq(FIELD_NAME_TEMPLATE), any())).thenReturn(FIELD_NAME_VALUE);
}
@Test
public void testEmptyList() throws TemplateModelException {
String resultingValue = (String) safeFieldIterations.exec(getSimpleParameters());
verify(templateService, times(1)).renderTemplateWithMap(templateKeyCaptor.capture(), any());
List<String> usedTemplateKeys = templateKeyCaptor.getAllValues();
assertEquals(FIELD_NAME_TEMPLATE, usedTemplateKeys.get(0));
assertEquals(EXPECTED_START_PART + "\"}", resultingValue);
}
@Test
public void testOneElement() throws TemplateModelException {
when(templateService.renderTemplateWithMap(eq(TEMPLATE_KEY), any())).thenReturn(FIRST_LIST_ENTRY);
String resultingValue = (String) safeFieldIterations.exec(oneListEntryParameter());
assertEquals(EXPECTED_START_PART + FIRST_LIST_ENTRY + "\"}", resultingValue);
}
@Test
public void testTwoElements() throws TemplateModelException {
when(templateService.renderTemplateWithMap(eq(TEMPLATE_KEY), any())).thenReturn(FIRST_LIST_ENTRY);
String resultingValue = (String) safeFieldIterations.exec(twoListEntryParameter());
assertEquals(EXPECTED_START_PART + FIRST_LIST_ENTRY + FIRST_LIST_ENTRY + "\"}", resultingValue);
}
@Test
public void testElementsStaySolo() throws TemplateModelException {
when(templateService.renderTemplateWithMap(eq(TEMPLATE_KEY), any())).thenReturn(SIX_HUNDRED_CHARACTERS);
String resultingValue = (String) safeFieldIterations.exec(twoListEntryParameter());
assertEquals(EXPECTED_START_PART + SIX_HUNDRED_CHARACTERS + "\"}," + EXPECTED_START_PART + SIX_HUNDRED_CHARACTERS + "\"}", resultingValue);
}
@Test(expected = TemplateModelException.class)
public void testTooLittleParameters() throws TemplateModelException {
safeFieldIterations.exec(Arrays.asList(""));
}
@Test(expected = TemplateModelException.class)
public void testWrongListAdapterType() throws TemplateModelException {
safeFieldIterations.exec(wrongListAdapter());
}
@Test(expected = TemplateModelException.class)
public void testWrongTemplateKeyParameterType() throws TemplateModelException {
safeFieldIterations.exec(wrongTemplateKeyParameterType());
}
@Test(expected = TemplateModelException.class)
public void testWrongFieldNameTemplateKeyParameterType() throws TemplateModelException {
safeFieldIterations.exec(wrongFieldNameTemplateKeyParameterType());
}
@Test(expected = TemplateModelException.class)
public void testWrongInlineParameterType() throws TemplateModelException {
safeFieldIterations.exec(wrongInLineValueParameterType());
}
public List<Object> wrongListAdapter() {
return Arrays.asList(new Object(), new Object(), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE));
}
public List<Object> wrongTemplateKeyParameterType() {
return Arrays.asList(validEmptyList(), new Object(), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE));
}
public List<Object> wrongFieldNameTemplateKeyParameterType() {
return Arrays.asList(validEmptyList(), new SimpleScalar(TEMPLATE_KEY), new Object(), new SimpleScalar(INLINE_VALUE));
}
public List<Object> wrongInLineValueParameterType() {
return Arrays.asList(validEmptyList(), new SimpleScalar(TEMPLATE_KEY), new SimpleScalar(FIELD_NAME_TEMPLATE), new Object());
}
public List<Object> getSimpleParameters() {
return Arrays.asList(validEmptyList(), new SimpleScalar(TEMPLATE_KEY), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE));
}
private DefaultListAdapter validEmptyList() {
return DefaultListAdapter.adapt(new ArrayList<Object>(), getWrapper());
}
public List<Object> oneListEntryParameter() {
return Arrays.asList(DefaultListAdapter.adapt(Arrays.asList("testing"), getWrapper()), new SimpleScalar(TEMPLATE_KEY), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE));
}
public List<Object> twoListEntryParameter() {
return Arrays.asList(DefaultListAdapter.adapt(Arrays.asList("testing", "otherText"), getWrapper()), new SimpleScalar(TEMPLATE_KEY), new SimpleScalar(FIELD_NAME_TEMPLATE), new SimpleScalar(INLINE_VALUE));
}
private DefaultObjectWrapper getWrapper() {
return new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_0).build();
}
}

View File

@@ -17,6 +17,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.ui.freemarker.FreeMarkerConfigurationFactory;
@@ -127,7 +128,7 @@ public class TemplateServiceBeanTest {
}
@Test
public void testEmbedWithTooLongDescription() throws IOException, TemplateException {
public void testEmbedWithTooLongDescriptionNoSpace() throws IOException, TemplateException {
when(serverContext.getServerId()).thenReturn(SERVER_ID);
int tooMuchCharacterCount = 1024;
String descriptionText = RandomStringUtils.randomAlphabetic(MessageEmbed.TEXT_MAX_LENGTH + tooMuchCharacterCount);
@@ -158,7 +159,7 @@ public class TemplateServiceBeanTest {
}
@Test
public void testEmbedWithTooLongField() throws IOException, TemplateException {
public void testEmbedWithTooLongFieldNoSpace() throws IOException, TemplateException {
when(serverContext.getServerId()).thenReturn(SERVER_ID);
String fieldValue = RandomStringUtils.randomAlphabetic(1500);
when(configuration.getTemplate(getEmbedTemplateKey(), null, SERVER_ID, null, true, false)).thenReturn(getEmbedTemplateWithTooLongField(fieldValue));
@@ -170,6 +171,119 @@ public class TemplateServiceBeanTest {
Assert.assertEquals(fieldValue.substring(MessageEmbed.VALUE_MAX_LENGTH), firstEmbed.getFields().get(1).getValue());
}
@Test
public void testEmbedWithTooLongFieldWithSpace() throws IOException, TemplateException {
when(serverContext.getServerId()).thenReturn(SERVER_ID);
int partsLength = 750;
String firstPart = RandomStringUtils.randomAlphabetic(partsLength);
String secondPart = RandomStringUtils.randomAlphabetic(partsLength);
String fieldValue = firstPart + " " + secondPart;
when(configuration.getTemplate(getEmbedTemplateKey(), null, SERVER_ID, null, true, false)).thenReturn(getEmbedTemplateWithTooLongField(fieldValue));
when(gson.fromJson(getSingleFieldWithValue(fieldValue), EmbedConfiguration.class)).thenReturn(getEmbedWithSingleFieldOfValue(fieldValue));
MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>());
MessageEmbed firstEmbed = messageToSend.getEmbeds().get(0);
Assert.assertEquals(2, firstEmbed.getFields().size());
Assert.assertEquals(firstPart, firstEmbed.getFields().get(0).getValue());
Assert.assertEquals(secondPart, firstEmbed.getFields().get(1).getValue());
}
@Test
public void testDescriptionWithOneSpace() throws IOException, TemplateException {
when(serverContext.getServerId()).thenReturn(SERVER_ID);
int partLengths = 1024;
String firstPart = RandomStringUtils.randomAlphabetic(partLengths);
String secondPart = RandomStringUtils.randomAlphabetic(partLengths);
String descriptionText = firstPart + " " + secondPart;
when(configuration.getTemplate(getEmbedTemplateKey(), null, SERVER_ID, null, true, false)).thenReturn(getEmbedTemplateWithDescription(descriptionText));
when(configuration.getTemplate(EMBED_PAGE_COUNT_TEMPLATE, null, SERVER_ID, null, true, false)).thenReturn(getPageCountTemplate(1));
when(gson.fromJson(embedTemplateWithDescription(descriptionText), EmbedConfiguration.class)).thenReturn(embedConfigWithDescription(descriptionText));
MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>());
Assert.assertEquals(2, messageToSend.getEmbeds().size());
MessageEmbed firstEmbed = messageToSend.getEmbeds().get(0);
Assert.assertEquals(partLengths, firstEmbed.getDescription().length());
Assert.assertEquals(firstPart, firstEmbed.getDescription());
MessageEmbed secondEmbed = messageToSend.getEmbeds().get(1);
Assert.assertEquals(partLengths + 1, secondEmbed.getDescription().length());
Assert.assertEquals(" " + secondPart, secondEmbed.getDescription());
}
@Test
public void testDescriptionWithTwoSpacesAndLongChunks() throws IOException, TemplateException {
when(serverContext.getServerId()).thenReturn(SERVER_ID);
int partLengths = 1024;
String firstPart = RandomStringUtils.randomAlphabetic(partLengths);
String secondPart = RandomStringUtils.randomAlphabetic(partLengths);
String thirdPart = RandomStringUtils.randomAlphabetic(partLengths);
String descriptionText = firstPart + " " + secondPart + " " + thirdPart;
when(configuration.getTemplate(getEmbedTemplateKey(), null, SERVER_ID, null, true, false)).thenReturn(getEmbedTemplateWithDescription(descriptionText));
when(configuration.getTemplate(EMBED_PAGE_COUNT_TEMPLATE, null, SERVER_ID, null, true, false)).thenReturn(getPageCountTemplate(1));
when(gson.fromJson(embedTemplateWithDescription(descriptionText), EmbedConfiguration.class)).thenReturn(embedConfigWithDescription(descriptionText));
MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>());
Assert.assertEquals(3, messageToSend.getEmbeds().size());
MessageEmbed firstEmbed = messageToSend.getEmbeds().get(0);
Assert.assertEquals(partLengths, firstEmbed.getDescription().length());
Assert.assertEquals(firstPart, firstEmbed.getDescription());
MessageEmbed secondEmbed = messageToSend.getEmbeds().get(1);
Assert.assertEquals(partLengths + 1, secondEmbed.getDescription().length());
Assert.assertEquals(" " + secondPart, secondEmbed.getDescription());
MessageEmbed thirdEmbed = messageToSend.getEmbeds().get(2);
Assert.assertEquals(partLengths + 1, thirdEmbed.getDescription().length());
Assert.assertEquals(" " + thirdPart, thirdEmbed.getDescription());
}
@Test
public void testDescriptionWithMultipleSpacesSplitIntoTwo() throws IOException, TemplateException {
when(serverContext.getServerId()).thenReturn(SERVER_ID);
int partLengths = 750;
String firstPart = RandomStringUtils.randomAlphabetic(partLengths);
String secondPart = RandomStringUtils.randomAlphabetic(partLengths);
String thirdPart = RandomStringUtils.randomAlphabetic(partLengths);
String descriptionText = firstPart + " " + secondPart + " " + thirdPart;
when(configuration.getTemplate(getEmbedTemplateKey(), null, SERVER_ID, null, true, false)).thenReturn(getEmbedTemplateWithDescription(descriptionText));
when(configuration.getTemplate(EMBED_PAGE_COUNT_TEMPLATE, null, SERVER_ID, null, true, false)).thenReturn(getPageCountTemplate(1));
when(gson.fromJson(embedTemplateWithDescription(descriptionText), EmbedConfiguration.class)).thenReturn(embedConfigWithDescription(descriptionText));
MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>());
Assert.assertEquals(2, messageToSend.getEmbeds().size());
MessageEmbed firstEmbed = messageToSend.getEmbeds().get(0);
Assert.assertEquals(partLengths + partLengths + 1, firstEmbed.getDescription().length());
Assert.assertEquals(firstPart + " " + secondPart, firstEmbed.getDescription());
MessageEmbed secondEmbed = messageToSend.getEmbeds().get(1);
Assert.assertEquals(1 + partLengths, secondEmbed.getDescription().length());
Assert.assertEquals(" " + thirdPart, secondEmbed.getDescription());
}
@Test
public void testFieldLengthTooLongForEmbed() throws IOException, TemplateException {
when(serverContext.getServerId()).thenReturn(SERVER_ID);
int partLengths = 1000;
String fieldValue = RandomStringUtils.randomAlphabetic(partLengths);
String firstField = fieldValue + "a";
String secondField = fieldValue + "b";
String thirdField = fieldValue + "c";
String fourthField = fieldValue + "d";
String fifthField = fieldValue + "e";
String sixthField = fieldValue + "f";
List<String> fieldValues = Arrays.asList(firstField, secondField, thirdField, fourthField, fifthField, sixthField);
when(configuration.getTemplate(getEmbedTemplateKey(), null, SERVER_ID, null, true, false)).thenReturn(getEmbedTemplateWithFieldValues(fieldValues));
when(configuration.getTemplate(EMBED_PAGE_COUNT_TEMPLATE, null, SERVER_ID, null, true, false)).thenReturn(getPageCountTemplate(1));
when(gson.fromJson(getFields(fieldValues), EmbedConfiguration.class)).thenReturn(getEmbedWithFields(fieldValues));
MessageToSend messageToSend = templateServiceBean.renderEmbedTemplate(TEMPLATE_KEY, new HashMap<>());
Assert.assertEquals(2, messageToSend.getEmbeds().size());
MessageEmbed firstEmbed = messageToSend.getEmbeds().get(0);
List<MessageEmbed.Field> firstFields = firstEmbed.getFields();
Assert.assertEquals(5, firstFields.size());
Assert.assertEquals(firstField, firstFields.get(0).getValue());
Assert.assertEquals(secondField, firstFields.get(1).getValue());
Assert.assertEquals(thirdField, firstFields.get(2).getValue());
Assert.assertEquals(fourthField, firstFields.get(3).getValue());
Assert.assertEquals(fifthField, firstFields.get(4).getValue());
MessageEmbed secondEmbed = messageToSend.getEmbeds().get(1);
List<MessageEmbed.Field> secondFields = secondEmbed.getFields();
Assert.assertEquals(1, secondFields.size());
Assert.assertEquals(sixthField, secondFields.get(0).getValue());
}
@Test(expected = TemplatingException.class)
public void tryToRenderMissingTemplate() throws IOException {
when(serverContext.getServerId()).thenReturn(SERVER_ID);
@@ -205,6 +319,14 @@ public class TemplateServiceBeanTest {
return EmbedConfiguration.builder().fields(fields).build();
}
private EmbedConfiguration getEmbedWithFields(List<String> fieldValues) {
List<EmbedField> fields = new ArrayList<>();
fieldValues.forEach(s -> {
fields.add(EmbedField.builder().name("name").value(s).build());
});
return EmbedConfiguration.builder().fields(fields).build();
}
private EmbedConfiguration getTooManyFieldsEmbedConfiguration() {
List<EmbedField> fields = new ArrayList<>();
for (int i = 0; i < 30; i++) {
@@ -289,6 +411,10 @@ public class TemplateServiceBeanTest {
return new Template(getEmbedTemplateKey(), embedTemplateWithDescription(description), getNonMockedConfiguration());
}
private Template getEmbedTemplateWithFieldValues(List<String> fieldValues) throws IOException, TemplateException {
return new Template(getEmbedTemplateKey(), getFields(fieldValues), getNonMockedConfiguration());
}
private Template getPageCountTemplate(Integer page) throws IOException, TemplateException {
return new Template(EMBED_PAGE_COUNT_TEMPLATE, getEmbedPageCount(page), getNonMockedConfiguration());
}
@@ -305,12 +431,12 @@ public class TemplateServiceBeanTest {
return new Template(getEmbedTemplateKey(), getSingleFieldWithValue(value), getNonMockedConfiguration());
}
private String getFullEmbedConfigString() throws IOException {
private String getFullEmbedConfigString() {
return IOUtils.toString(this.getClass().getResourceAsStream("/src/test/resources/full_embed.json"), StandardCharsets.UTF_8);
}
private String getFieldsEmbedConfigAsString(Integer count) {
StringBuilder sb = new StringBuilder();
StringBuilder sb = new StringBuilder();
sb.append("{\"fields\": [");
for (int i = 0; i < count - 1; i++) {
sb.append(FIELD_TEMPLATE + ",");
@@ -321,6 +447,17 @@ public class TemplateServiceBeanTest {
return sb.toString();
}
private String getFields(List<String> fieldValues) {
StringBuilder sb = new StringBuilder();
sb.append("{\"fields\": [");
for (String fieldValue: fieldValues) {
sb.append(getSingleFieldWithValue(fieldValue));
}
sb.append("]\n" +
"}");
return sb.toString();
}
private String getSingleFieldWithValue(String value) {
return String.format("{\"fields\": [" + FIELD_TEMPLATE_WITH_VALUE + "]\n}",value);
}