mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-13 03:26:31 +00:00
[AB-77] moving the templating module into the core module
adding a possibility to overlay specific templates for particular servers adding commands to configure templates adding file parameter support
This commit is contained in:
@@ -68,6 +68,11 @@
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
@@ -106,12 +111,6 @@
|
||||
<type>test-jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.templating</groupId>
|
||||
<artifactId>templating-interface</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.scheduling</groupId>
|
||||
<artifactId>scheduling-int</artifactId>
|
||||
|
||||
@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.exception.IncorrectParameterException;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandManager;
|
||||
@@ -110,7 +111,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
try {
|
||||
String contentStripped = event.getMessage().getContentRaw();
|
||||
List<String> parameters = Arrays.asList(contentStripped.split(" "));
|
||||
UnParsedCommandParameter unParsedParameter = new UnParsedCommandParameter(contentStripped);
|
||||
UnParsedCommandParameter unParsedParameter = new UnParsedCommandParameter(contentStripped, event.getMessage());
|
||||
String commandName = commandManager.getCommandName(parameters.get(0), event.getGuild().getIdLong());
|
||||
foundCommand = commandManager.findCommandByParameters(commandName, unParsedParameter);
|
||||
tryToExecuteFoundCommand(event, foundCommand, unParsedParameter);
|
||||
@@ -254,7 +255,6 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
Parameter param = command.getConfiguration().getParameters().get(0);
|
||||
CommandParameterIterators iterators = new CommandParameterIterators(channelIterator, emoteIterator, memberIterator, roleIterator);
|
||||
boolean reminderActive = false;
|
||||
List<CommandParameterHandler> orderedHandlers = parameterHandlers.stream().sorted(comparing(CommandParameterHandler::getPriority)).collect(Collectors.toList());
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
for (int i = 0; i < unParsedCommandParameter.getParameters().size(); i++) {
|
||||
if(i < command.getConfiguration().getParameters().size() && !param.isRemainder()) {
|
||||
@@ -262,9 +262,9 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
} else {
|
||||
reminderActive = true;
|
||||
}
|
||||
String value = unParsedCommandParameter.getParameters().get(i);
|
||||
UnparsedCommandParameterPiece value = unParsedCommandParameter.getParameters().get(i);
|
||||
boolean handlerMatched = false;
|
||||
for (CommandParameterHandler handler : orderedHandlers) {
|
||||
for (CommandParameterHandler handler : parameterHandlers) {
|
||||
try {
|
||||
if (handler.handles(param.getType())) {
|
||||
handlerMatched = true;
|
||||
@@ -286,24 +286,25 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
}
|
||||
}
|
||||
if(!handlerMatched) {
|
||||
Object valueAsString = value.getValue().toString();
|
||||
if(!reminderActive) {
|
||||
parsedParameters.add(value);
|
||||
parsedParameters.add(valueAsString);
|
||||
} else {
|
||||
if(!param.isListParam()) {
|
||||
if(parsedParameters.isEmpty()) {
|
||||
parsedParameters.add(value);
|
||||
parsedParameters.add(valueAsString);
|
||||
} else {
|
||||
int lastIndex = parsedParameters.size() - 1;
|
||||
parsedParameters.set(lastIndex, parsedParameters.get(lastIndex) + " " + value);
|
||||
parsedParameters.set(lastIndex, parsedParameters.get(lastIndex) + " " + valueAsString);
|
||||
}
|
||||
} else {
|
||||
if(parsedParameters.isEmpty()) {
|
||||
ArrayList<Object> list = new ArrayList<>();
|
||||
list.add(value);
|
||||
list.add(valueAsString);
|
||||
parsedParameters.add(list);
|
||||
} else {
|
||||
int lastIndex = parsedParameters.size() - 1;
|
||||
((List)parsedParameters.get(lastIndex)).add(value);
|
||||
((List)parsedParameters.get(lastIndex)).add(valueAsString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -339,5 +340,6 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(COMMANDS_PROCESSED_COUNTER, "Commands processed");
|
||||
metricService.registerCounter(COMMANDS_WRONG_PARAMETER_COUNTER, "Commands with incorrect parameter");
|
||||
this.parameterHandlers = parameterHandlers.stream().sorted(comparing(CommandParameterHandler::getPriority)).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.AChannelParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.TextChannelParameterHandler;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
@@ -29,10 +30,10 @@ public class AChannelParameterHandlerImpl implements AChannelParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
TextChannel textChannel = (TextChannel) textChannelParameterHandler.handle(input, iterators, clazz, context);
|
||||
if(textChannel == null) {
|
||||
Long channelId = Long.parseLong(input);
|
||||
Long channelId = Long.parseLong((String) input.getValue());
|
||||
AChannel actualInstance = channelManagementService.loadChannel(channelId);
|
||||
return AChannel.builder().fake(true).id(actualInstance.getId()).build();
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.AEmoteParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
@@ -25,12 +26,12 @@ public class AEmoteParameterHandlerImpl implements AEmoteParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context);
|
||||
if(emote != null) {
|
||||
return emoteService.getFakeEmoteFromEmote(emote);
|
||||
} else {
|
||||
return emoteService.getFakeEmote(input);
|
||||
return emoteService.getFakeEmote(input.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.ARoleParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
@@ -25,7 +26,7 @@ public class ARoleParameterHandlerImpl implements ARoleParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
Role role = (Role) roleParameterHandler.handle(input, iterators, Role.class, context);
|
||||
return roleService.getFakeRoleFromRole(role);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.AUserInAServerParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.MemberParameterHandler;
|
||||
import dev.sheldan.abstracto.core.exception.UserInServerNotFoundException;
|
||||
@@ -23,7 +24,7 @@ public class AUserInAServerParameterHandlerImpl implements AUserInAServerParamet
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture handleAsync(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
public CompletableFuture handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
CompletableFuture<AUserInAServer> future = new CompletableFuture<>();
|
||||
memberParameterHandler.handleAsync(input, iterators, Member.class, context).whenComplete((o, throwable) -> {
|
||||
try {
|
||||
@@ -32,7 +33,7 @@ public class AUserInAServerParameterHandlerImpl implements AUserInAServerParamet
|
||||
Member member = (Member) o;
|
||||
actualInstance = userInServerManagementService.loadOrCreateUser(member);
|
||||
} else {
|
||||
Long userId = Long.parseLong(input);
|
||||
Long userId = Long.parseLong((String) input.getValue());
|
||||
actualInstance = userInServerManagementService.loadAUserInAServerOptional(context.getGuild().getIdLong(), userId).orElseThrow(() -> new UserInServerNotFoundException(0L));
|
||||
}
|
||||
future.complete(AUserInAServer.builder().userInServerId(actualInstance.getUserInServerId()).build());
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.BooleanParameterHandler;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -13,8 +14,8 @@ public class BooleanParameterHandlerImpl implements BooleanParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return Boolean.valueOf(input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return Boolean.valueOf((String) input.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.exception.ChannelGroupNotFoundException;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.ChannelGroupParameterHandler;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
@@ -22,10 +23,11 @@ public class ChannelGroupParameterHandlerImpl implements ChannelGroupParameterHa
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
AServer server = serverManagementService.loadServer(context.getGuild().getIdLong());
|
||||
AChannelGroup actualInstance = channelGroupManagementService.findByNameAndServerOptional(input, server)
|
||||
.orElseThrow(() -> new ChannelGroupNotFoundException(input, channelGroupManagementService.getAllAvailableAsString(server)));
|
||||
String inputString = (String) input.getValue();
|
||||
AChannelGroup actualInstance = channelGroupManagementService.findByNameAndServerOptional(inputString, server)
|
||||
.orElseThrow(() -> new ChannelGroupNotFoundException(inputString, channelGroupManagementService.getAllAvailableAsString(server)));
|
||||
ChannelGroupType channelGroupType = ChannelGroupType
|
||||
.builder()
|
||||
.id(actualInstance.getChannelGroupType().getId())
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.ChannelGroupTypeParameterHandler;
|
||||
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupTypeManagementService;
|
||||
@@ -24,8 +25,8 @@ public class ChannelGroupTypeParameterHandlerImpl implements ChannelGroupTypePar
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
ChannelGroupType actualGroupType = channelGroupTypeManagementService.findChannelGroupTypeByKey(input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
ChannelGroupType actualGroupType = channelGroupTypeManagementService.findChannelGroupTypeByKey((String) input.getValue());
|
||||
return ChannelGroupType
|
||||
.builder()
|
||||
.groupTypeKey(actualGroupType.getGroupTypeKey())
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandParameterKey;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.CommandKeyParameterHandler;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -15,8 +16,8 @@ public class CommandKeyParameterHandlerImpl implements CommandKeyParameterHandle
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return CommandParameterKey.getEnumFromKey(clazz, input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return CommandParameterKey.getEnumFromKey(clazz, (String) input.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.DoubleParameterHandler;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -13,8 +14,8 @@ public class DoubleParameterHandlerImpl implements DoubleParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return Double.parseDouble(input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return Double.parseDouble((String) input.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.DurationParameterHandler;
|
||||
import dev.sheldan.abstracto.core.utils.ParseUtils;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
@@ -16,8 +17,8 @@ public class DurationParameterHandlerImpl implements DurationParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return ParseUtils.parseDuration(input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return ParseUtils.parseDuration((String) input.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
@@ -18,13 +19,14 @@ public class EmoteParameterHandlerImpl implements EmoteParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
Matcher matcher = Message.MentionType.EMOTE.getPattern().matcher(input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
String inputString = (String) input.getValue();
|
||||
Matcher matcher = Message.MentionType.EMOTE.getPattern().matcher(inputString);
|
||||
if(matcher.matches()) {
|
||||
return iterators.getEmoteIterator().next();
|
||||
} else {
|
||||
if(StringUtils.isNumeric(input)) {
|
||||
long emoteId = Long.parseLong(input);
|
||||
if(StringUtils.isNumeric(inputString)) {
|
||||
long emoteId = Long.parseLong(inputString);
|
||||
return context.getGuild().getEmoteById(emoteId);
|
||||
} else {
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.exception.NoAttachmentFoundException;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.FileParameterHandler;
|
||||
import dev.sheldan.abstracto.core.service.HttpService;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class FileParameterHandlerImpl implements FileParameterHandler {
|
||||
|
||||
@Autowired
|
||||
private HttpService httpService;
|
||||
|
||||
@Override
|
||||
public boolean async() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Object> handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
if(context.getAttachments().isEmpty()) {
|
||||
throw new NoAttachmentFoundException();
|
||||
}
|
||||
Message.Attachment attachment = (Message.Attachment) input.getValue();
|
||||
CompletableFuture<Object> result = new CompletableFuture<>();
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
result.complete(httpService.downloadFileToTempFile(attachment.getUrl()));
|
||||
} catch (IOException e) {
|
||||
result.completeExceptionally(e);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handles(Class clazz) {
|
||||
return clazz.equals(File.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return CommandConstants.CORE_HANDLER_PRIORITY;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.FullEmoteParameterHandler;
|
||||
import dev.sheldan.abstracto.core.models.FullEmote;
|
||||
@@ -26,13 +27,13 @@ public class FullEmoteParameterHandlerImpl implements FullEmoteParameterHandler
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context);
|
||||
AEmote aEmote;
|
||||
if(emote != null) {
|
||||
aEmote = emoteService.getFakeEmoteFromEmote(emote);
|
||||
} else {
|
||||
aEmote = emoteService.getFakeEmote(input);
|
||||
aEmote = emoteService.getFakeEmote(input.getValue());
|
||||
}
|
||||
return FullEmote.builder().emote(emote).fakeEmote(aEmote).build();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.FullRoleParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler;
|
||||
import dev.sheldan.abstracto.core.models.FullRole;
|
||||
@@ -26,7 +27,7 @@ public class FullRoleParameterHandlerImpl implements FullRoleParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
Role role = (Role) roleParameterHandler.handle(input, iterators, Role.class, context);
|
||||
ARole aRole = roleService.getFakeRoleFromRole(role);
|
||||
return FullRole.builder().role(aRole).serverRole(role).build();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.IntegerParameterHandler;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -14,8 +15,8 @@ public class IntegerParameterHandlerImpl implements IntegerParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return Integer.parseInt(input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return Integer.parseInt((String) input.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.LongParameterHandler;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -14,8 +15,8 @@ public class LongParameterHandlerImpl implements LongParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return Long.parseLong(input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
return Long.parseLong((String) input.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.MemberParameterHandler;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
@@ -22,13 +23,14 @@ public class MemberParameterHandlerImpl implements MemberParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Object> handleAsync(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
Matcher matcher = Message.MentionType.USER.getPattern().matcher(input);
|
||||
public CompletableFuture<Object> handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
String inputString = (String) input.getValue();
|
||||
Matcher matcher = Message.MentionType.USER.getPattern().matcher(inputString);
|
||||
if(matcher.matches()) {
|
||||
return CompletableFuture.completedFuture(iterators.getMemberIterator().next());
|
||||
} else {
|
||||
// TODO add handling for names
|
||||
long userId = Long.parseLong(input);
|
||||
long userId = Long.parseLong(inputString);
|
||||
return context.getGuild().retrieveMemberById(userId).submit().thenApply(member -> member);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
@@ -16,12 +17,13 @@ public class RoleParameterHandlerImpl implements RoleParameterHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
Matcher matcher = Message.MentionType.ROLE.getPattern().matcher(input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
String inputString = (String) input.getValue();
|
||||
Matcher matcher = Message.MentionType.ROLE.getPattern().matcher(inputString);
|
||||
if(matcher.matches()) {
|
||||
return iterators.getRoleIterator().next();
|
||||
} else {
|
||||
long roleId = Long.parseLong(input);
|
||||
long roleId = Long.parseLong(inputString);
|
||||
return context.getGuild().getRoleById(roleId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandConstants;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.TextChannelParameterHandler;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
@@ -16,12 +17,13 @@ public class TextChannelParameterHandlerImpl implements TextChannelParameterHand
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
Matcher matcher = Message.MentionType.CHANNEL.getPattern().matcher(input);
|
||||
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
String inputString = (String) input.getValue();
|
||||
Matcher matcher = Message.MentionType.CHANNEL.getPattern().matcher(inputString);
|
||||
if(matcher.matches()) {
|
||||
return iterators.getChannelIterator().next();
|
||||
} else {
|
||||
long channelId = Long.parseLong(input);
|
||||
long channelId = Long.parseLong(inputString);
|
||||
return context.getGuild().getTextChannelById(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class ConditionPostExecution implements PostCommandExecution {
|
||||
.member(commandContext.getAuthor())
|
||||
.build())
|
||||
.build();
|
||||
channelService.sendEmbedTemplateInChannel(GENERIC_COMMAND_EXCEPTION_MODEL_KEY, conditionModel, commandContext.getChannel());
|
||||
channelService.sendEmbedTemplateInTextChannelList(GENERIC_COMMAND_EXCEPTION_MODEL_KEY, conditionModel, commandContext.getChannel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ResultState;
|
||||
import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -15,9 +14,6 @@ import org.springframework.stereotype.Service;
|
||||
@Slf4j
|
||||
public class ExceptionPostExecution implements PostCommandExecution {
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ExceptionService exceptionService;
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.CommandReceivedHandler;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.exception.CommandNotFoundException;
|
||||
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
|
||||
@@ -47,14 +46,12 @@ public class CommandManager implements CommandRegistry {
|
||||
}
|
||||
boolean parameterFit;
|
||||
if(commandConfiguration.getParameters() != null){
|
||||
boolean paramCountFits = unParsedCommandParameter.getParameters().size() >= commandConfiguration.getNecessaryParameterCount();
|
||||
boolean hasRemainderParameter = commandConfiguration.getParameters().stream().anyMatch(Parameter::isRemainder);
|
||||
if(unParsedCommandParameter.getParameters().size() < commandConfiguration.getNecessaryParameterCount()) {
|
||||
if(commandConfiguration.getNecessaryParameterCount() > unParsedCommandParameter.getParameters().size()) {
|
||||
String nextParameterName = commandConfiguration.getParameters().get(commandConfiguration.getNecessaryParameterCount() - 1).getName();
|
||||
metricService.incrementCounter(CommandReceivedHandler.COMMANDS_WRONG_PARAMETER_COUNTER);
|
||||
throw new InsufficientParametersException(o, nextParameterName);
|
||||
}
|
||||
parameterFit = paramCountFits || hasRemainderParameter;
|
||||
parameterFit = true;
|
||||
} else {
|
||||
parameterFit = unParsedCommandParameter.getParameters().isEmpty();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -120,6 +121,9 @@ public class CommandServiceBean implements CommandService {
|
||||
builder.append(" ");
|
||||
}
|
||||
commandConfig.getParameters().forEach(parameter -> {
|
||||
if(parameter.getType().equals(File.class)) {
|
||||
return;
|
||||
}
|
||||
String[] enclosing = parameter.isOptional() ? OPTIONAL_ENCLOSING : MANDATORY_ENCLOSING;
|
||||
builder.append(enclosing[0]);
|
||||
builder.append(parameter.getName());
|
||||
@@ -163,14 +167,14 @@ public class CommandServiceBean implements CommandService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnParsedCommandParameter getUnParsedCommandParameter(String messageContent) {
|
||||
return new UnParsedCommandParameter(messageContent);
|
||||
public UnParsedCommandParameter getUnParsedCommandParameter(String messageContent, Message message) {
|
||||
return new UnParsedCommandParameter(messageContent, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Parameters> getParametersForCommand(String commandName, Message messageContainingContent) {
|
||||
String contentStripped = messageContainingContent.getContentRaw();
|
||||
UnParsedCommandParameter unParsedParameter = getUnParsedCommandParameter(contentStripped);
|
||||
UnParsedCommandParameter unParsedParameter = getUnParsedCommandParameter(contentStripped, messageContainingContent);
|
||||
Command command = commandRegistry.findCommandByParameters(commandName, unParsedParameter);
|
||||
return commandReceivedHandler.getParsedParameters(unParsedParameter, command, messageContainingContent);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserManagementService;
|
||||
import dev.sheldan.abstracto.templating.Templatable;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
@@ -46,13 +46,13 @@ public class ExceptionServiceBean implements ExceptionService {
|
||||
GenericExceptionModel exceptionModel = buildCommandModel(throwable, context);
|
||||
log.info("Reporting generic exception {} of command {} towards channel {} in server {}.",
|
||||
throwable.getClass().getSimpleName(), command.getConfiguration().getName(), context.getChannel().getId(), context.getGuild().getId());
|
||||
channelService.sendEmbedTemplateInChannel("generic_command_exception", exceptionModel, context.getChannel());
|
||||
channelService.sendEmbedTemplateInTextChannelList("generic_command_exception", exceptionModel, context.getChannel());
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to notify about exception.", e);
|
||||
}
|
||||
} else if(throwable instanceof Templatable){
|
||||
GenericExceptionModel exceptionModel = buildCommandModel(throwable, context);
|
||||
String text = templateService.renderTemplate(MODEL_WRAPPER_TEMPLATE_KEY, exceptionModel);
|
||||
String text = templateService.renderTemplate(MODEL_WRAPPER_TEMPLATE_KEY, exceptionModel, context.getGuild().getIdLong());
|
||||
channelService.sendTextToChannel(text, context.getChannel());
|
||||
} else {
|
||||
channelService.sendTextToChannel(throwable.getLocalizedMessage(), context.getChannel());
|
||||
|
||||
@@ -16,8 +16,8 @@ import dev.sheldan.abstracto.core.models.template.commands.ListChannelGroupsMode
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -48,7 +48,7 @@ public class ListChannelGroups extends AbstractConditionableCommand {
|
||||
List<AChannelGroup> channelGroups = channelGroupManagementService.findAllInServer(server);
|
||||
ListChannelGroupsModel template = (ListChannelGroupsModel) ContextConverter.fromCommandContext(commandContext, ListChannelGroupsModel.class);
|
||||
template.setGroups(convertAChannelGroupToChannelGroupChannel(channelGroups));
|
||||
MessageToSend response = templateService.renderEmbedTemplate("listChannelGroups_response", template);
|
||||
MessageToSend response = templateService.renderEmbedTemplate("listChannelGroups_response", template, commandContext.getGuild().getIdLong());
|
||||
channelService.sendMessageToSendToChannel(response, commandContext.getChannel());
|
||||
return CommandResult.fromIgnored();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.GuildChannel;
|
||||
@@ -45,9 +44,6 @@ public class PostTargetCommand extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@@ -76,7 +72,7 @@ public class PostTargetCommand extends AbstractConditionableCommand {
|
||||
postTargetEntries.add(postTargetEntry);
|
||||
}
|
||||
});
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInChannel(POST_TARGET_SHOW_TARGETS, posttargetDisplayModel, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(POST_TARGET_SHOW_TARGETS, posttargetDisplayModel, commandContext.getChannel()))
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
String targetName = (String) commandContext.getParameters().getParameters().get(0);
|
||||
|
||||
@@ -18,7 +18,7 @@ import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -60,7 +60,7 @@ public class Allow extends AbstractConditionableCommand {
|
||||
commandService.unRestrictCommand(command, server);
|
||||
} else {
|
||||
// TODO refactor to use exception
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE, new Object()));
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE, new Object(), commandContext.getGuild().getIdLong()));
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -57,7 +57,7 @@ public class AllowRole extends AbstractConditionableCommand {
|
||||
ACommand command = commandManagementService.findCommandByName(name);
|
||||
commandService.allowCommandForRole(command, actualRole);
|
||||
} else {
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE, new Object()));
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE, new Object(), commandContext.getGuild().getIdLong()));
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -56,7 +56,8 @@ public class DisAllowRole extends AbstractConditionableCommand {
|
||||
ACommand command = commandManagementService.findCommandByName(name);
|
||||
commandService.disAllowCommandForRole(command, actualRole);
|
||||
} else {
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE, new Object()));
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE,
|
||||
new Object(), commandContext.getGuild().getIdLong()));
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -49,7 +49,7 @@ public class DisableFeature extends AbstractConditionableCommand {
|
||||
if(commandContext.getParameters().getParameters().isEmpty()) {
|
||||
EnableModel model = (EnableModel) ContextConverter.fromCommandContext(commandContext, EnableModel.class);
|
||||
model.setFeatures(featureConfigService.getAllFeatures());
|
||||
String response = templateService.renderTemplate("disable_features_response", model);
|
||||
String response = templateService.renderTemplate("disable_features_response", model, commandContext.getGuild().getIdLong());
|
||||
return channelService.sendTextToChannel(response, commandContext.getChannel())
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
} else {
|
||||
|
||||
@@ -16,7 +16,6 @@ import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureModeManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -38,9 +37,6 @@ public class DisableMode extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private FeatureModeManagementService featureModeManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -52,7 +52,7 @@ public class EnableFeature extends AbstractConditionableCommand {
|
||||
if(commandContext.getParameters().getParameters().isEmpty()) {
|
||||
EnableModel model = (EnableModel) ContextConverter.fromCommandContext(commandContext, EnableModel.class);
|
||||
model.setFeatures(featureConfigService.getAllFeatures());
|
||||
String response = templateService.renderTemplate("enable_features_response", model);
|
||||
String response = templateService.renderTemplate("enable_features_response", model, commandContext.getGuild().getIdLong());
|
||||
return channelService.sendTextToChannel(response, commandContext.getChannel())
|
||||
.thenApply(message -> CommandResult.fromSuccess());
|
||||
} else {
|
||||
@@ -62,7 +62,8 @@ public class EnableFeature extends AbstractConditionableCommand {
|
||||
FeatureValidationResult featureSetup = featureConfigService.validateFeatureSetup(feature, server);
|
||||
if(Boolean.FALSE.equals(featureSetup.getValidationResult())) {
|
||||
log.info("Feature {} has failed the setup validation. Notifying user.", flagKey);
|
||||
channelService.sendTextToChannelNotAsync(templateService.renderTemplatable(featureSetup), commandContext.getChannel());
|
||||
channelService.sendTextToChannelNotAsync(templateService.renderTemplatable(featureSetup, commandContext.getGuild().getIdLong()),
|
||||
commandContext.getChannel());
|
||||
}
|
||||
featureFlagService.enableFeature(feature, server);
|
||||
if(feature.getRequiredFeatures() != null) {
|
||||
|
||||
@@ -16,7 +16,6 @@ import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureModeManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -38,9 +37,6 @@ public class EnableMode extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private FeatureModeManagementService featureModeManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ public class FeatureModes extends AbstractConditionableCommand {
|
||||
featureModes = featureModeService.getEffectiveFeatureModes(server, feature);
|
||||
}
|
||||
FeatureModesModel model = FeatureModesModel.builder().featureModes(featureModes).build();
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInChannel(FEATURE_MODES_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(FEATURE_MODES_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ import dev.sheldan.abstracto.core.service.management.DefaultFeatureFlagManagemen
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -69,7 +69,7 @@ public class Features extends AbstractConditionableCommand {
|
||||
.collect(Collectors.toList());
|
||||
defaultFeatureFlagProperties.sort(Comparator.comparing(FeatureFlagProperty::getFeatureName));
|
||||
featuresModel.setDefaultFeatures(featureFlagConverter.fromFeatureFlagProperties(defaultFeatureFlagProperties));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("features_response", featuresModel);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("features_response", featuresModel, commandContext.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -57,7 +57,8 @@ public class MakeAffected extends AbstractConditionableCommand {
|
||||
commandService.makeRoleAffectedByCommand(command, actualRole);
|
||||
} else {
|
||||
// TODO refactor to use exception
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE, new Object()));
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE,
|
||||
new Object(), commandContext.getGuild().getIdLong()));
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -57,7 +57,8 @@ public class MakeImmune extends AbstractConditionableCommand {
|
||||
commandService.makeRoleImmuneForCommand(command, actualRole);
|
||||
} else {
|
||||
// TODO refactor to use exception
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE, new Object()));
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE,
|
||||
new Object(), commandContext.getGuild().getIdLong()));
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -60,7 +60,8 @@ public class Restrict extends AbstractConditionableCommand {
|
||||
commandService.restrictCommand(command, server);
|
||||
} else {
|
||||
// TODO Refactor to use exception
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE, new Object()));
|
||||
return CommandResult.fromError(templateService.renderTemplate(CommandServiceBean.NO_FEATURE_COMMAND_FOUND_EXCEPTION_TEMPLATE,
|
||||
new Object(), commandContext.getGuild().getIdLong()));
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package dev.sheldan.abstracto.core.commands.config.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.exception.CustomTemplateNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.GetCustomTemplateModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.templating.model.database.CustomTemplate;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.management.CustomTemplateManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class GetCustomTemplate extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private CustomTemplateManagementService customTemplateManagementService;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
private static final String GET_CUSTOM_TEMPLATE_FILE_NAME_TEMPLATE_KEY = "getCustomTemplate_file_name";
|
||||
private static final String GET_CUSTOM_TEMPLATE_RESPONSE_TEMPLATE_KEY = "getCustomTemplate_response";
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
String templateKey = (String) commandContext.getParameters().getParameters().get(0);
|
||||
Optional<CustomTemplate> templateOptional = customTemplateManagementService.getCustomTemplate(templateKey, commandContext.getGuild().getIdLong());
|
||||
if(templateOptional.isPresent()) {
|
||||
CustomTemplate template = templateOptional.get();
|
||||
GetCustomTemplateModel model = (GetCustomTemplateModel) ContextConverter.slimFromCommandContext(commandContext, GetCustomTemplateModel.class);
|
||||
model.setCreated(template.getCreated());
|
||||
model.setLastModified(template.getLastModified());
|
||||
model.setTemplateContent(template.getContent());
|
||||
model.setTemplateKey(templateKey);
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendFileToChannel(template.getContent(),
|
||||
GET_CUSTOM_TEMPLATE_FILE_NAME_TEMPLATE_KEY, GET_CUSTOM_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
throw new CustomTemplateNotFoundException(templateKey, commandContext.getGuild());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter templateKeyParameter = Parameter.builder().name("templateKey").type(String.class).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(templateKeyParameter);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("getCustomTemplate")
|
||||
.module(ConfigModuleInterface.CONFIG)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.async(true)
|
||||
.help(helpInfo)
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return CoreFeatures.CORE_FEATURE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package dev.sheldan.abstracto.core.commands.config.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.exception.TemplateNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.GetTemplateModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.templating.model.database.Template;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.management.TemplateManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class GetTemplate extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private TemplateManagementService templateManagementService;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
private static final String GET_TEMPLATE_FILE_NAME_TEMPLATE_KEY = "getTemplate_file_name";
|
||||
private static final String GET_TEMPLATE_RESPONSE_TEMPLATE_KEY = "getTemplate_response";
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
String templateKey = (String) commandContext.getParameters().getParameters().get(0);
|
||||
Optional<Template> templateOptional = templateManagementService.getTemplateByKey(templateKey);
|
||||
if(templateOptional.isPresent()) {
|
||||
Template template = templateOptional.get();
|
||||
GetTemplateModel model = (GetTemplateModel) ContextConverter.slimFromCommandContext(commandContext, GetTemplateModel.class);
|
||||
model.setCreated(template.getCreated());
|
||||
model.setLastModified(template.getLastModified());
|
||||
model.setTemplateContent(template.getContent());
|
||||
model.setTemplateKey(templateKey);
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendFileToChannel(template.getContent(),
|
||||
GET_TEMPLATE_FILE_NAME_TEMPLATE_KEY, GET_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
throw new TemplateNotFoundException(templateKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
Parameter templateKeyParameter = Parameter.builder().name("templateKey").type(String.class).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(templateKeyParameter);
|
||||
return CommandConfiguration.builder()
|
||||
.name("getTemplate")
|
||||
.module(ConfigModuleInterface.CONFIG)
|
||||
.supportsEmbedException(true)
|
||||
.async(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return CoreFeatures.CORE_FEATURE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package dev.sheldan.abstracto.core.commands.config.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.exception.CustomTemplateNotFoundException;
|
||||
import dev.sheldan.abstracto.core.templating.model.database.CustomTemplate;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.management.CustomTemplateManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class ResetTemplate extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private CustomTemplateManagementService customTemplateManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
String templateKey = (String) commandContext.getParameters().getParameters().get(0);
|
||||
Optional<CustomTemplate> templateOptional = customTemplateManagementService.getCustomTemplate(templateKey, commandContext.getGuild().getIdLong());
|
||||
if (templateOptional.isPresent()) {
|
||||
customTemplateManagementService.deleteCustomTemplate(templateOptional.get());
|
||||
templateService.clearCache();
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
throw new CustomTemplateNotFoundException(templateKey, commandContext.getGuild());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
Parameter templateKeyParameter = Parameter.builder().name("templateKey").type(String.class).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(templateKeyParameter);
|
||||
return CommandConfiguration.builder()
|
||||
.name("resetTemplate")
|
||||
.module(ConfigModuleInterface.CONFIG)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return CoreFeatures.CORE_FEATURE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package dev.sheldan.abstracto.core.commands.config.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.management.CustomTemplateManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SetTemplate extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private CustomTemplateManagementService customTemplateManagementService;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
List<Object> parameter = commandContext.getParameters().getParameters();
|
||||
String templateKey = (String) parameter.get(0);
|
||||
File templateFile = (File) parameter.get(1);
|
||||
try {
|
||||
String templateContent = FileUtils.readFileToString(templateFile, StandardCharsets.UTF_8);
|
||||
customTemplateManagementService.createOrUpdateCustomTemplate(templateKey, templateContent, commandContext.getGuild().getIdLong());
|
||||
templateService.clearCache();
|
||||
return CommandResult.fromSuccess();
|
||||
} catch (IOException e) {
|
||||
log.error("IO Exception when loading input file.", e);
|
||||
throw new AbstractoTemplatedException("Failed to set template.", "failed_to_set_template_exception", e);
|
||||
} finally {
|
||||
try {
|
||||
fileService.safeDelete(templateFile);
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to delete downloaded template file.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return CoreFeatures.CORE_FEATURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter templateKeyParameter = Parameter.builder().name("templateKey").type(String.class).templated(true).build();
|
||||
Parameter fileAttachmentParameter = Parameter.builder().name("file").type(File.class).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(templateKeyParameter, fileAttachmentParameter);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("setTemplate")
|
||||
.module(ConfigModuleInterface.CONFIG)
|
||||
.parameters(parameters)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,8 @@ import dev.sheldan.abstracto.core.models.template.commands.help.HelpModuleOvervi
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.RoleService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -124,7 +124,7 @@ public class Help implements Command {
|
||||
HelpModuleDetailsModel model = (HelpModuleDetailsModel) ContextConverter.fromCommandContext(commandContext, HelpModuleDetailsModel.class);
|
||||
model.setModule(module);
|
||||
model.setSubModules(subModules);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("help_module_details_response", model);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("help_module_details_response", model, commandContext.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
} else if(commandRegistry.commandExists(parameter)) {
|
||||
@@ -141,7 +141,7 @@ public class Help implements Command {
|
||||
}
|
||||
model.setUsage(commandService.generateUsage(command));
|
||||
model.setCommand(command.getConfiguration());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("help_command_details_response", model);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("help_command_details_response", model, commandContext.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
} else {
|
||||
|
||||
@@ -11,7 +11,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.EchoModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -36,7 +36,7 @@ public class Echo extends AbstractConditionableCommand {
|
||||
sb.append(o.toString())
|
||||
);
|
||||
EchoModel model = EchoModel.builder().text(sb.toString()).build();
|
||||
String textToSend = templateService.renderTemplate(TEMPLATE_NAME, model);
|
||||
String textToSend = templateService.renderTemplate(TEMPLATE_NAME, model, commandContext.getGuild().getIdLong());
|
||||
channelService.sendTextToChannel(textToSend, commandContext.getChannel());
|
||||
return CommandResult.fromIgnored();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.PingModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -22,9 +21,6 @@ public class Ping implements Command {
|
||||
|
||||
public static final String PING_TEMPLATE = "ping_response";
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@@ -35,7 +31,7 @@ public class Ping implements Command {
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
long ping = commandContext.getJda().getGatewayPing();
|
||||
PingModel model = PingModel.builder().latency(ping).build();
|
||||
return channelService.sendTextTemplateInChannel(PING_TEMPLATE, model, commandContext.getChannel())
|
||||
return channelService.sendTextTemplateInTextChannel(PING_TEMPLATE, model, commandContext.getChannel())
|
||||
.thenApply(message -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.abstracto.core.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ServerContext {
|
||||
private Long serverId;
|
||||
|
||||
public void clear() {
|
||||
this.serverId = null;
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,7 @@ import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
@@ -26,9 +25,6 @@ import java.util.function.Consumer;
|
||||
@Slf4j
|
||||
public class InteractiveServiceBean implements InteractiveService {
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.interactive;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.templating.Templatable;
|
||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||
|
||||
public class NoChannelProvidedException extends AbstractoRunTimeException implements Templatable {
|
||||
public NoChannelProvidedException() {
|
||||
|
||||
@@ -10,7 +10,7 @@ import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
@@ -67,7 +67,7 @@ public class PostTargetSetupStep extends AbstractConfigSetupStep {
|
||||
.postTargetKey(postTargetStepParameter.getPostTargetKey())
|
||||
.currentTextChannel(currentTextChannel)
|
||||
.build();
|
||||
String messageText = templateService.renderTemplate(FEATURE_SETUP_POST_TARGET_MESSAGE_TEMPLATE_KEY, model);
|
||||
String messageText = templateService.renderTemplate(FEATURE_SETUP_POST_TARGET_MESSAGE_TEMPLATE_KEY, model, user.getGuildId());
|
||||
AChannel channel = channelManagementService.loadChannel(user.getChannelId());
|
||||
CompletableFuture<SetupStepResult> future = new CompletableFuture<>();
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(user.getGuildId(), user.getUserId());
|
||||
|
||||
@@ -7,7 +7,7 @@ import dev.sheldan.abstracto.core.models.template.commands.SetupSummaryModel;
|
||||
import dev.sheldan.abstracto.core.service.DelayedActionService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -46,7 +46,7 @@ public class SetupSummaryStep extends AbstractConfigSetupStep {
|
||||
.builder()
|
||||
.actionConfigs(parameter.getDelayedActionList())
|
||||
.build();
|
||||
String messageToSend = templateService.renderTemplate(FEATURE_SETUP_CONFIRMATION_TEMPLATE_KEY, model);
|
||||
String messageToSend = templateService.renderTemplate(FEATURE_SETUP_CONFIRMATION_TEMPLATE_KEY, model, user.getGuildId());
|
||||
AChannel channel = channelManagementService.loadChannel(user.getChannelId());
|
||||
CompletableFuture<SetupStepResult> future = new CompletableFuture<>();
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(user.getGuildId(), user.getUserId());
|
||||
|
||||
@@ -10,7 +10,7 @@ import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
@@ -58,7 +58,7 @@ public class SystemConfigSetupStep extends AbstractConfigSetupStep {
|
||||
.configKey(systemConfigStepParameter.getConfigKey())
|
||||
.defaultConfig(defaultConfig)
|
||||
.build();
|
||||
String messageText = templateService.renderTemplate(SETUP_SYSTEM_CONFIG_MESSAGE_TEMPLATE_KEY, model);
|
||||
String messageText = templateService.renderTemplate(SETUP_SYSTEM_CONFIG_MESSAGE_TEMPLATE_KEY, model, user.getGuildId());
|
||||
AChannel channel = channelManagementService.loadChannel(user.getChannelId());
|
||||
CompletableFuture<SetupStepResult> future = new CompletableFuture<>();
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(user.getGuildId(), user.getUserId());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.CategoryNotFoundException;
|
||||
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||
import dev.sheldan.abstracto.core.exception.*;
|
||||
import dev.sheldan.abstracto.core.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
@@ -21,6 +20,8 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -47,6 +48,9 @@ public class ChannelServiceBean implements ChannelService {
|
||||
@Autowired
|
||||
private AllowedMentionService allowedMentionService;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
@@ -330,13 +334,27 @@ public class ChannelServiceBean implements ChannelService {
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public List<CompletableFuture<Message>> sendEmbedTemplateInChannel(String templateKey, Object model, MessageChannel channel) {
|
||||
public List<CompletableFuture<Message>> sendEmbedTemplateInTextChannelList(String templateKey, Object model, TextChannel channel) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(templateKey, model, channel.getGuild().getIdLong());
|
||||
return sendMessageToSendToChannel(messageToSend, channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Message>> sendEmbedTemplateInMessageChannelList(String templateKey, Object model, MessageChannel channel) {
|
||||
// message channel on its own, does not have a guild, so we cant say for which server we want to render the template
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(templateKey, model);
|
||||
return sendMessageToSendToChannel(messageToSend, channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> sendTextTemplateInChannel(String templateKey, Object model, MessageChannel channel) {
|
||||
public CompletableFuture<Message> sendTextTemplateInTextChannel(String templateKey, Object model, TextChannel channel) {
|
||||
String text = templateService.renderTemplate(templateKey, model, channel.getGuild().getIdLong());
|
||||
return sendTextToChannel(text, channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> sendTextTemplateInMessageChannel(String templateKey, Object model, MessageChannel channel) {
|
||||
// message channel on its own, does not have a guild, so we cant say for which server we want to render the template
|
||||
String text = templateService.renderTemplate(templateKey, model);
|
||||
return sendTextToChannel(text, channel);
|
||||
}
|
||||
@@ -386,7 +404,7 @@ public class ChannelServiceBean implements ChannelService {
|
||||
@Override
|
||||
public CompletableFuture<Message> sendSimpleTemplateToChannel(Long serverId, Long channelId, String template) {
|
||||
TextChannel textChannel = getTextChannelFromServer(serverId, channelId);
|
||||
return sendTextTemplateInChannel(template, new Object(), textChannel);
|
||||
return sendTextTemplateInTextChannel(template, new Object(), textChannel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -430,6 +448,32 @@ public class ChannelServiceBean implements ChannelService {
|
||||
return textChannel.getManager().setSlowmode(seconds).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Message>> sendFileToChannel(String fileContent, String fileNameTemplate, String messageTemplate, Object model, TextChannel channel) {
|
||||
String fileName = templateService.renderTemplate(fileNameTemplate, model);
|
||||
File tempFile = fileService.createTempFile(fileName);
|
||||
try {
|
||||
fileService.writeContentToFile(tempFile, fileContent);
|
||||
long maxFileSize = channel.getGuild().getMaxFileSize();
|
||||
// in this case, we cannot upload the file, so we need to fail
|
||||
if(tempFile.length() > maxFileSize) {
|
||||
throw new UploadFileTooLargeException(tempFile.length(), maxFileSize);
|
||||
}
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(messageTemplate, model);
|
||||
messageToSend.setFileToSend(tempFile);
|
||||
return sendMessageToSendToChannel(messageToSend, channel);
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to write local temporary file for template download.", e);
|
||||
throw new AbstractoRunTimeException(e);
|
||||
} finally {
|
||||
try {
|
||||
fileService.safeDelete(tempFile);
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to safely delete local temporary file for template download.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
|
||||
@@ -7,7 +7,7 @@ import dev.sheldan.abstracto.core.interactive.*;
|
||||
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.SetupCompletedNotificationModel;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.SetupInitialMessageModel;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -104,7 +104,7 @@ public class FeatureSetupServiceBean implements FeatureSetupService {
|
||||
.featureConfig(featureConfig)
|
||||
.build();
|
||||
TextChannel textChannel = textChannelInGuild.get();
|
||||
String text = templateService.renderTemplate(FEATURE_SETUP_INITIAL_MESSAGE_TEMPLATE_KEY, setupInitialMessageModel);
|
||||
String text = templateService.renderTemplate(FEATURE_SETUP_INITIAL_MESSAGE_TEMPLATE_KEY, setupInitialMessageModel, user.getGuildId());
|
||||
channelService.sendTextToChannel(text, textChannel);
|
||||
return executeFeatureSetup(featureConfig, steps, user, new ArrayList<>());
|
||||
}
|
||||
@@ -181,7 +181,7 @@ public class FeatureSetupServiceBean implements FeatureSetupService {
|
||||
.builder()
|
||||
.featureConfig(featureConfig)
|
||||
.build();
|
||||
String text = templateService.renderTemplate(templateName, model);
|
||||
String text = templateService.renderTemplate(templateName, model, aServerChannelUserId.getGuildId());
|
||||
Optional<TextChannel> textChannel = channelService.getTextChannelFromServerOptional(aServerChannelUserId.getGuildId(), aServerChannelUserId.getChannelId());
|
||||
textChannel.ifPresent(channel -> channelService.sendTextToChannel(text, channel));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
|
||||
import dev.sheldan.abstracto.core.utils.FileUtils;
|
||||
import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
@@ -18,14 +18,14 @@ public class HttpServiceBean implements HttpService {
|
||||
private OkHttpClient client;
|
||||
|
||||
@Autowired
|
||||
private FileUtils fileUtils;
|
||||
private FileService fileService;
|
||||
|
||||
@Override
|
||||
public File downloadFileToTempFile(String url) throws IOException {
|
||||
Request request = new Request.Builder().url(url).get().build();
|
||||
File tempFile = fileUtils.createTempFile(Math.random() + "");
|
||||
File tempFile = fileService.createTempFile(Math.random() + "");
|
||||
Response execute = client.newCall(request).execute();
|
||||
fileUtils.writeBytesToFile(tempFile, execute.body().bytes());
|
||||
fileService.writeBytesToFile(tempFile, execute.body().bytes());
|
||||
return tempFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.requests.restaction.AuditableRestAction;
|
||||
@@ -119,7 +119,7 @@ public class MessageServiceBean implements MessageService {
|
||||
@Override
|
||||
public CompletableFuture<Void> sendEmbedToUser(User user, String template, Object model) {
|
||||
return openPrivateChannelForUser(user).thenCompose(privateChannel ->
|
||||
FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInChannel(template, model, privateChannel)));
|
||||
FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannelList(template, model, privateChannel)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -131,7 +131,7 @@ public class MessageServiceBean implements MessageService {
|
||||
public CompletableFuture<Message> sendEmbedToUserWithMessage(User user, String template, Object model) {
|
||||
log.trace("Sending direct message with template {} to user {}.", template, user.getIdLong());
|
||||
return openPrivateChannelForUser(user).thenCompose(privateChannel ->
|
||||
channelService.sendEmbedTemplateInChannel(template, model, privateChannel).get(0));
|
||||
channelService.sendEmbedTemplateInMessageChannelList(template, model, privateChannel).get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.google.gson.Gson;
|
||||
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
|
||||
import com.jagrosh.jdautilities.menu.Paginator;
|
||||
import dev.sheldan.abstracto.core.model.PaginatorConfiguration;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -29,7 +29,7 @@ public class PaginatorServiceBean implements PaginatorService {
|
||||
private MessageService messageService;
|
||||
|
||||
@Override
|
||||
public Paginator createPaginatorFromTemplate(String templateKey, Object model, EventWaiter waiter) {
|
||||
public Paginator createPaginatorFromTemplate(String templateKey, Object model, EventWaiter waiter, Long server) {
|
||||
String embedConfig = templateService.renderTemplate(templateKey + "_paginator", model);
|
||||
PaginatorConfiguration configuration = gson.fromJson(embedConfig, PaginatorConfiguration.class);
|
||||
List<String> items = configuration.getItems();
|
||||
|
||||
@@ -10,7 +10,7 @@ import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultPostTargetManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.abstracto.core.templating.config;
|
||||
|
||||
import freemarker.cache.TemplateLookupContext;
|
||||
import freemarker.cache.TemplateLookupResult;
|
||||
import freemarker.cache.TemplateLookupStrategy;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class AbstractoTemplateLookupStrategy extends TemplateLookupStrategy {
|
||||
@Override
|
||||
public TemplateLookupResult lookup(TemplateLookupContext ctx) throws IOException {
|
||||
if(ctx.getCustomLookupCondition() != null) {
|
||||
return ctx.lookupWithLocalizedThenAcquisitionStrategy(ctx.getCustomLookupCondition() + "/" + ctx.getTemplateName(), ctx.getTemplateLocale());
|
||||
} else {
|
||||
return ctx.lookupWithLocalizedThenAcquisitionStrategy(ctx.getTemplateName(), ctx.getTemplateLocale());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
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;
|
||||
import freemarker.template.TemplateException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.ui.freemarker.FreeMarkerConfigurationFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Configuration bean used to provide the {@link Configuration} bean to the spring context.
|
||||
*/
|
||||
@org.springframework.context.annotation.Configuration
|
||||
public class FreemarkerConfiguration {
|
||||
|
||||
@Autowired
|
||||
private DatabaseTemplateLoader templateLoader;
|
||||
|
||||
@Autowired
|
||||
private DurationMethod durationMethod;
|
||||
|
||||
@Autowired
|
||||
private DateMethod instantMethod;
|
||||
|
||||
@Autowired
|
||||
private SafeFieldIterations safeFieldIterations;
|
||||
|
||||
@Autowired
|
||||
private AutoLoadMacroManagementService macroManagementService;
|
||||
|
||||
/**
|
||||
* Creates a {@link Configuration} bean with the appropriate configuration which includes:
|
||||
* The correct compatibility version and the provided formatter methods to be used in the templates.
|
||||
* The encoding of the templates is set to UTF-8.
|
||||
* @return A configured {@link Configuration} bean according to the configuration
|
||||
*/
|
||||
@Bean
|
||||
public Configuration freeMarkerConfiguration() throws IOException, TemplateException {
|
||||
FreeMarkerConfigurationFactory factory = new FreeMarkerConfigurationFactory();
|
||||
factory.setPreTemplateLoaders(templateLoader);
|
||||
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);
|
||||
configuration.setTemplateLookupStrategy(new AbstractoTemplateLookupStrategy());
|
||||
configuration.setEncoding(Locale.getDefault(), "utf-8");
|
||||
// needed to support default methods in interfaces
|
||||
configuration.setIncompatibleImprovements(Configuration.VERSION_2_3_29);
|
||||
return configuration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package dev.sheldan.abstracto.core.templating.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.ServerContext;
|
||||
import org.springframework.aop.framework.ProxyFactoryBean;
|
||||
import org.springframework.aop.target.ThreadLocalTargetSource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
@Configuration
|
||||
public class ServerContextConfiguration {
|
||||
@Bean(destroyMethod = "destroy")
|
||||
public ThreadLocalTargetSource threadLocalTenantStore() {
|
||||
ThreadLocalTargetSource result = new ThreadLocalTargetSource();
|
||||
result.setTargetBeanName("serverContext");
|
||||
return result;
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean(name = "proxiedThreadLocalTargetSource")
|
||||
public ProxyFactoryBean proxiedThreadLocalTargetSource(ThreadLocalTargetSource threadLocalTargetSource) {
|
||||
ProxyFactoryBean result = new ProxyFactoryBean();
|
||||
result.setTargetSource(threadLocalTargetSource);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Bean(name = "serverContext")
|
||||
@Scope(scopeName = "prototype")
|
||||
public ServerContext serverContext() {
|
||||
return new ServerContext();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package dev.sheldan.abstracto.core.templating.loading;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.ServerContext;
|
||||
import dev.sheldan.abstracto.core.templating.model.EffectiveTemplate;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.management.EffectiveTemplateManagementService;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Loads the the template from the database to be used by Freemarker. This bean is also used when the templates within
|
||||
* templates are used.
|
||||
*/
|
||||
@Component
|
||||
public class DatabaseTemplateLoader implements TemplateLoader {
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private EffectiveTemplateManagementService effectiveTemplateManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerContext serverContext;
|
||||
|
||||
/**
|
||||
* Loads the content of the template object
|
||||
* @param s The key of the template to load
|
||||
* @return The template loaded from the database
|
||||
*/
|
||||
@Override
|
||||
public Object findTemplateSource(String s) throws IOException {
|
||||
Optional<EffectiveTemplate> templateByKey;
|
||||
if(s.contains("/")) {
|
||||
String[] parts = s.split("/");
|
||||
templateByKey = effectiveTemplateManagementService.getTemplateByKeyAndServer(parts[1], Long.parseLong(parts[0]));
|
||||
} else {
|
||||
templateByKey = effectiveTemplateManagementService.getTemplateByKey(s);
|
||||
}
|
||||
return templateByKey.orElseThrow(() -> new IOException(String.format("Failed to load template. %s", s)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified(Object o) {
|
||||
EffectiveTemplate casted = (EffectiveTemplate) o;
|
||||
Optional<EffectiveTemplate> templateByKey;
|
||||
if(serverContext.getServerId() != null) {
|
||||
templateByKey = effectiveTemplateManagementService.getTemplateByKeyAndServer(casted.getKey(), serverContext.getServerId());
|
||||
} else {
|
||||
templateByKey = effectiveTemplateManagementService.getTemplateByKey(casted.getKey());
|
||||
}
|
||||
return templateByKey.map(template -> template.getLastModified().getEpochSecond()).orElse(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the content of the template from the retrieved {@link EffectiveTemplate} object
|
||||
* @param o The retrieved {@link EffectiveTemplate} object from the database
|
||||
* @param s The encoding of the object
|
||||
* @return The content of the template as a String reader
|
||||
*/
|
||||
@Override
|
||||
public Reader getReader(Object o, String s) throws IOException {
|
||||
return new StringReader(((EffectiveTemplate) o).getContent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeTemplateSource(Object o) throws IOException {
|
||||
// do nothing for now
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.sheldan.abstracto.core.templating.method;
|
||||
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import freemarker.ext.beans.StringModel;
|
||||
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.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Formats the passed {@link Instant} or {@link OffsetDateTime} object with the given Formatter. The format will be directly passed to {@link DateTimeFormatter}.
|
||||
*/
|
||||
@Component
|
||||
public class DateMethod implements TemplateMethodModelEx {
|
||||
|
||||
@Autowired
|
||||
private TemplateService service;
|
||||
|
||||
/**
|
||||
* Renders the given {@link Instant} object with the given String. Internally {@link DateTimeFormatter} will be used.
|
||||
* @param arguments The list of arguments, first element must be an {@link Instant} or {@link OffsetDateTime} and the second one must be a {@link String}.
|
||||
* @return The formatted {@link Instant} as a string.
|
||||
* @throws TemplateModelException If there are less or more arguments in the list and if the first element is not a {@link Instant} of {@link OffsetDateTime}
|
||||
*/
|
||||
@Override
|
||||
public Object exec(List arguments) throws TemplateModelException {
|
||||
if (arguments.size() != 2) {
|
||||
throw new TemplateModelException("Incorrect parameters passed.");
|
||||
}
|
||||
Object wrappedObject = ((StringModel) arguments.get(0)).getWrappedObject();
|
||||
boolean isOffsetDateTime = wrappedObject instanceof OffsetDateTime;
|
||||
boolean isInstant = wrappedObject instanceof Instant;
|
||||
if(!isInstant && !isOffsetDateTime) {
|
||||
throw new TemplateModelException("Passed argument was not a instant object");
|
||||
}
|
||||
|
||||
String formatString = ((SimpleScalar) arguments.get(1)).getAsString();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatString)
|
||||
.withZone(ZoneId.systemDefault());
|
||||
if(isInstant) {
|
||||
Instant timeStamp = (Instant) wrappedObject;
|
||||
return formatter.format(timeStamp);
|
||||
} else {
|
||||
OffsetDateTime offsetDateTime = (OffsetDateTime) wrappedObject;
|
||||
return formatter.format(offsetDateTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.sheldan.abstracto.core.templating.method;
|
||||
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import freemarker.ext.beans.StringModel;
|
||||
import freemarker.template.TemplateMethodModelEx;
|
||||
import freemarker.template.TemplateModelException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Method used to format the {@link Duration} object, as its not natively supported by Freemarker.
|
||||
* This method only accepts a single {@link Duration} object as the first parameter.
|
||||
*/
|
||||
@Component
|
||||
public class DurationMethod implements TemplateMethodModelEx {
|
||||
|
||||
@Autowired
|
||||
private TemplateService service;
|
||||
|
||||
/**
|
||||
* This method expects a single Duration object in the list of arguments. It will throw a {@link TemplateModelException}
|
||||
* otherwise
|
||||
* @param arguments The parameters passed to this method, should be only a single duration.
|
||||
* @return The string representation of the {@link Duration} object
|
||||
* @throws TemplateModelException In case the amount of parameters is not correct, or the first object was not a {@link Duration}
|
||||
*/
|
||||
@Override
|
||||
public Object exec(List arguments) throws TemplateModelException {
|
||||
if (arguments.size() != 1) {
|
||||
throw new TemplateModelException("Incorrect parameters passed.");
|
||||
}
|
||||
Object o = arguments.get(0);
|
||||
if(!(o instanceof StringModel)) {
|
||||
throw new TemplateModelException("Passed object was not a StringModel.");
|
||||
}
|
||||
Object wrappedObject = ((StringModel) o).getWrappedObject();
|
||||
if(!(wrappedObject instanceof Duration)) {
|
||||
throw new TemplateModelException("Passed argument was not a duration object");
|
||||
}
|
||||
Duration duration = (Duration) wrappedObject;
|
||||
// upgrading to java 9 makes this nicer
|
||||
HashMap<String, Object> parameters = new HashMap<>();
|
||||
long days = duration.toDays();
|
||||
parameters.put("days", days);
|
||||
long hours = duration.toHours() % 24;
|
||||
parameters.put("hours", hours);
|
||||
long minutes = duration.toMinutes() % 60;
|
||||
parameters.put("minutes", minutes);
|
||||
|
||||
long seconds = duration.get(ChronoUnit.SECONDS) % 60;
|
||||
parameters.put("seconds", seconds);
|
||||
|
||||
return service.renderTemplateWithMap("duration_formatting", parameters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.sheldan.abstracto.core.templating.model;
|
||||
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* The container class used to deserialize the embed configuration for the author in {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class EmbedAuthor {
|
||||
/**
|
||||
* The name used in the {@link net.dv8tion.jda.api.entities.MessageEmbed} author
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* The URL used in the {@link net.dv8tion.jda.api.entities.MessageEmbed} author
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* The picture used as the avatar of the author in {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private String avatar;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sheldan.abstracto.core.templating.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* The container class used to deserialize the embed configuration for the color in {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@Builder
|
||||
public class EmbedColor {
|
||||
/**
|
||||
* The red part of RGB
|
||||
*/
|
||||
private Integer r;
|
||||
/**
|
||||
* The green part of RGB
|
||||
*/
|
||||
private Integer g;
|
||||
/**
|
||||
* The blue part of RGB
|
||||
*/
|
||||
private Integer b;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.sheldan.abstracto.core.templating.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
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
|
||||
public class EmbedConfiguration {
|
||||
/**
|
||||
* The {@link EmbedAuthor} object holding the configuration for the author of the {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private EmbedAuthor author;
|
||||
/**
|
||||
* The {@link EmbedTitle} object holding the configuration for the title in the {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private EmbedTitle title;
|
||||
/**
|
||||
* The {@link EmbedColor} object holding the configuration for the color in the {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private EmbedColor color;
|
||||
/**
|
||||
* The description which is going to be used in the {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* The link to the image used as a thumbnail in the {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private String thumbnail;
|
||||
/**
|
||||
* The link to the image used as the image in the {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private String imageUrl;
|
||||
/**
|
||||
* The collection containing all the objects containing the configuration for the fields in the {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private List<EmbedField> fields;
|
||||
/**
|
||||
* The {@link EmbedFooter} object holding the configuration for the footer in {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private EmbedFooter footer;
|
||||
/**
|
||||
* The {@link OffsetDateTime} object used as the time stamp in the {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
private OffsetDateTime timeStamp;
|
||||
/**
|
||||
* The message which is posted along the {@link net.dv8tion.jda.api.entities.MessageEmbed} as a normal message.
|
||||
*/
|
||||
private String additionalMessage;
|
||||
|
||||
private boolean preventEmptyEmbed = false;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.sheldan.abstracto.core.templating.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* The container class used to deserialize the embed configuration for a field in {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class EmbedField {
|
||||
/**
|
||||
* The name of the field to be set
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* The value of the field to be set
|
||||
*/
|
||||
private String value;
|
||||
/**
|
||||
* Whether or not the field should be rendered inline within the {@link net.dv8tion.jda.api.entities.MessageEmbed}.
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.abstracto.core.templating.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* The container object used to deserialize the embed configuration for the footer in the {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class EmbedFooter {
|
||||
/**
|
||||
* The text which is going to be used as the footer text
|
||||
*/
|
||||
private String text;
|
||||
/**
|
||||
* The link to the image which is going to be used as the icon of the footer
|
||||
*/
|
||||
private String icon;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.abstracto.core.templating.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* The container class used to deserialize the embed configuration used in the title in {@link net.dv8tion.jda.api.entities.MessageEmbed}
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class EmbedTitle {
|
||||
/**
|
||||
* The text which is going to be used as the title of the embed
|
||||
*/
|
||||
private String title;
|
||||
/**
|
||||
* The link which is used when clicking on the title of the embed
|
||||
*/
|
||||
private String url;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.core.templating.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.templating.model.database.AutoLoadMacro;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface AutoLoadMacroRepository extends JpaRepository<AutoLoadMacro, String> {
|
||||
@NotNull
|
||||
@Override
|
||||
List<AutoLoadMacro> findAll();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package dev.sheldan.abstracto.core.templating.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.templating.model.database.CustomTemplate;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
/**
|
||||
* Repository used to load the templates from the database.
|
||||
*/
|
||||
@Repository
|
||||
public interface CustomTemplateRepository extends JpaRepository<CustomTemplate, String> {
|
||||
Optional<CustomTemplate> findByKeyAndServerId(String key, Long serverId);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package dev.sheldan.abstracto.core.templating.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.templating.model.EffectiveTemplate;
|
||||
import dev.sheldan.abstracto.core.templating.model.database.Template;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
/**
|
||||
* Repository used to load the templates from the database.
|
||||
*/
|
||||
@Repository
|
||||
public interface EffectiveTemplateRepository extends JpaRepository<Template, String> {
|
||||
@Query(value = "SELECT \n" +
|
||||
"t.key AS key, \n" +
|
||||
"COALESCE(c_t.content, t.content) AS content,\n" +
|
||||
"COALESCE(c_t.last_modified, t.last_modified) AS lastModified\n" +
|
||||
"FROM template t\n" +
|
||||
"LEFT OUTER JOIN custom_template c_t\n" +
|
||||
"ON t.key = c_t.key and c_t.server_id = :serverId\n" +
|
||||
"WHERE t.key = :key", nativeQuery = true)
|
||||
Optional<EffectiveTemplate> findByKeyAndServerId(@Param("key") String key, @Param("serverId") Long serverId);
|
||||
|
||||
@Query(value = "SELECT \n" +
|
||||
"t.key AS key, \n" +
|
||||
"t.content AS content,\n" +
|
||||
"t.last_modified AS lastModified\n" +
|
||||
"FROM template t\n" +
|
||||
"WHERE t.key = :key", nativeQuery = true)
|
||||
Optional<EffectiveTemplate> findByKey(@Param("key") String key);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.abstracto.core.templating.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.templating.model.database.Template;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
|
||||
/**
|
||||
* Repository used to load the templates from the database.
|
||||
*/
|
||||
@Repository
|
||||
public interface TemplateRepository extends JpaRepository<Template, String> {
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
package dev.sheldan.abstracto.core.templating.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import dev.sheldan.abstracto.core.config.ServerContext;
|
||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||
import dev.sheldan.abstracto.core.templating.exception.TemplatingException;
|
||||
import dev.sheldan.abstracto.core.templating.model.*;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Bean used to render a template, identified by a key, with the passed model.
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TemplateServiceBean implements TemplateService {
|
||||
|
||||
public static final double MAX_FIELD_COUNT = 25D;
|
||||
@Autowired
|
||||
private Configuration configuration;
|
||||
|
||||
@Autowired
|
||||
private Gson gson;
|
||||
|
||||
@Autowired
|
||||
private ServerContext serverContext;
|
||||
|
||||
/**
|
||||
* Formats the passed passed count with the embed used for formatting pages.
|
||||
*
|
||||
* @param count The index of the page you want formatted.
|
||||
* @return The rendered template as a string object
|
||||
*/
|
||||
private String getPageString(Integer count) {
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("count", count);
|
||||
return renderTemplateWithMap("embed_page_count", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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}
|
||||
* 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.
|
||||
*
|
||||
* @param key The key of the embed template to be used for rendering.
|
||||
* @param model The model providing the properties to be used for rendering
|
||||
* @return The {@link MessageToSend} object which is properly split up in order to be send to discord.
|
||||
*/
|
||||
@Override
|
||||
public MessageToSend renderEmbedTemplate(String key, Object model) {
|
||||
String embedConfig = this.renderTemplate(key + "_embed", model);
|
||||
EmbedConfiguration embedConfiguration = gson.fromJson(embedConfig, EmbedConfiguration.class);
|
||||
List<EmbedBuilder> embedBuilders = new ArrayList<>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
EmbedAuthor author = embedConfiguration.getAuthor();
|
||||
EmbedBuilder firstBuilder = embedBuilders.get(0);
|
||||
if (author != null) {
|
||||
firstBuilder.setAuthor(author.getName(), author.getUrl(), author.getAvatar());
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
List<MessageEmbed> embeds = new ArrayList<>();
|
||||
if ((embedBuilders.size() > 1 || !embedBuilders.get(0).isEmpty()) && !isEmptyEmbed(embedConfiguration)) {
|
||||
embeds = embedBuilders.stream().map(EmbedBuilder::build).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return MessageToSend.builder()
|
||||
.embeds(embeds)
|
||||
.message(embedConfiguration.getAdditionalMessage())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageToSend renderEmbedTemplate(String key, Object model, Long serverId) {
|
||||
try {
|
||||
serverContext.setServerId(serverId);
|
||||
return renderEmbedTemplate(key, model);
|
||||
} finally {
|
||||
serverContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmptyEmbed(EmbedConfiguration configuration) {
|
||||
if (configuration.isPreventEmptyEmbed()) {
|
||||
return configuration.getFields() == null && configuration.getDescription() == null && configuration.getImageUrl() == null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageToSend renderTemplateToMessageToSend(String key, Object model) {
|
||||
return MessageToSend.builder().message(renderTemplate(key, model)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageToSend renderTemplateToMessageToSend(String key, Object model, Long serverId) {
|
||||
try {
|
||||
serverContext.setServerId(serverId);
|
||||
return renderTemplateToMessageToSend(key, model);
|
||||
} finally {
|
||||
serverContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void createFieldsForEmbed(List<EmbedBuilder> embedBuilders, EmbedConfiguration configuration) {
|
||||
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 actualCurrentIndex = 0;
|
||||
int neededMessages = 0;
|
||||
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++;
|
||||
} else {
|
||||
actualCurrentIndex++;
|
||||
}
|
||||
extendIfNecessary(embedBuilders, neededMessages);
|
||||
EmbedField embedField = configuration.getFields().get(i);
|
||||
boolean inline = embedField.getInline() != null ? embedField.getInline() : Boolean.FALSE;
|
||||
embedBuilders.get(neededMessages).addField(embedField.getName(), embedField.getValue(), inline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enlarges the passed list of builders, if the passed index is not yet available within the list.
|
||||
* When a new builder is needed, this will automatically set the footer with a page indicator.
|
||||
*
|
||||
* @param builders The current list of {@link EmbedBuilder} builders used.
|
||||
* @param neededIndex The desired index in the list which should be available for using.
|
||||
*/
|
||||
private void extendIfNecessary(List<EmbedBuilder> builders, double neededIndex) {
|
||||
if (neededIndex > builders.size() - 1) {
|
||||
for (int i = builders.size(); i < neededIndex + 1; i++) {
|
||||
EmbedBuilder e = new EmbedBuilder();
|
||||
e.setFooter(getPageString(i + 1));
|
||||
builders.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the template identified by the key with the passed {@link HashMap}
|
||||
*
|
||||
* @param key The key of the template to be rendered.
|
||||
* @param parameters The {@link HashMap} to be used as the parameters for the template
|
||||
* @return The rendered template as a string
|
||||
*/
|
||||
@Override
|
||||
public String renderTemplateWithMap(String key, HashMap<String, Object> parameters) {
|
||||
try {
|
||||
return renderTemplateToString(key, parameters);
|
||||
} catch (IOException | TemplateException e) {
|
||||
log.warn("Failed to render template. ", e);
|
||||
throw new TemplatingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderTemplateWithMap(String key, HashMap<String, Object> parameters, Long serverId) {
|
||||
try {
|
||||
serverContext.setServerId(serverId);
|
||||
return renderTemplateWithMap(key, parameters);
|
||||
} finally {
|
||||
serverContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the template identified by the key with the passed object as model
|
||||
*
|
||||
* @param key The key of the template to be rendered
|
||||
* @param model The object containing the model to be used in the template
|
||||
* @return The rendered template as a string
|
||||
*/
|
||||
@Override
|
||||
public String renderTemplate(String key, Object model) {
|
||||
try {
|
||||
return renderTemplateToString(key, model);
|
||||
} catch (IOException | TemplateException e) {
|
||||
log.warn("Failed to render template. ", e);
|
||||
throw new TemplatingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderTemplate(String key, Object model, Long serverId) {
|
||||
try {
|
||||
serverContext.setServerId(serverId);
|
||||
return renderTemplate(key, model);
|
||||
} finally {
|
||||
serverContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given key as a template, and renders it, returns the result as a String
|
||||
*
|
||||
* @param key The key of the template to render
|
||||
* @param model The parameters which are given to the template
|
||||
* @return The rendered template in a String
|
||||
* @throws freemarker.template.TemplateNotFoundException In case the template could not be found
|
||||
* @throws TemplateException In case the rendering failed
|
||||
*/
|
||||
private String renderTemplateToString(String key, Object model) throws IOException, TemplateException {
|
||||
StringWriter result = new StringWriter();
|
||||
Template template = configuration.getTemplate(key, null, serverContext.getServerId(), null, true, false);
|
||||
template.process(model, result);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a simple template identified by key without any model. This will cause exceptions in case there are references to a model in the provided template.
|
||||
*
|
||||
* @param key The key of the template to be rendered
|
||||
* @return The rendered template as a string
|
||||
*/
|
||||
@Override
|
||||
public String renderSimpleTemplate(String key) {
|
||||
return renderTemplate(key, new Object());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderSimpleTemplate(String key, Long serverId) {
|
||||
try {
|
||||
serverContext.setServerId(serverId);
|
||||
return renderSimpleTemplate(key, serverId);
|
||||
} finally {
|
||||
serverContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the {@link Templatable} object using the template key and the model and returns it as a string.
|
||||
*
|
||||
* @param templatable The {@link Templatable} object to be rendered
|
||||
* @return The rendered {@link Templatable} as a string
|
||||
*/
|
||||
@Override
|
||||
public String renderTemplatable(Templatable templatable) {
|
||||
return renderTemplate(templatable.getTemplateName(), templatable.getTemplateModel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderTemplatable(Templatable templatable, Long serverId) {
|
||||
try {
|
||||
serverContext.setServerId(serverId);
|
||||
return renderTemplatable(templatable);
|
||||
} finally {
|
||||
serverContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCache() {
|
||||
configuration.getCacheStorage().clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.abstracto.core.templating.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.templating.model.database.AutoLoadMacro;
|
||||
import dev.sheldan.abstracto.core.templating.repository.AutoLoadMacroRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Component
|
||||
public class AutoLoadMacroManagementServiceBean implements AutoLoadMacroManagementService {
|
||||
|
||||
@Autowired
|
||||
private AutoLoadMacroRepository repository;
|
||||
|
||||
@Override
|
||||
public List<AutoLoadMacro> loadAllMacros() {
|
||||
return repository.findAll();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package dev.sheldan.abstracto.core.templating.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.TemplateNotFoundException;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.database.CustomTemplate;
|
||||
import dev.sheldan.abstracto.core.templating.repository.CustomTemplateRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class CustomTemplateManagementServiceBean implements CustomTemplateManagementService {
|
||||
|
||||
@Autowired
|
||||
private CustomTemplateRepository customTemplateRepository;
|
||||
|
||||
@Autowired
|
||||
private TemplateManagementService templateManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public CustomTemplate createOrUpdateCustomTemplate(String templateKey, String templateContent, Long serverId) {
|
||||
if(!templateManagementService.templateExists(templateKey)) {
|
||||
throw new TemplateNotFoundException(templateKey);
|
||||
}
|
||||
Optional<CustomTemplate> customTemplateOptional = getCustomTemplate(templateKey, serverId);
|
||||
customTemplateOptional.ifPresent(customTemplate -> customTemplate.setContent(templateContent));
|
||||
return customTemplateOptional.orElseGet(() -> createCustomTemplate(templateKey, templateContent, serverId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomTemplate createCustomTemplate(String templateKey, String templateContent, Long serverId) {
|
||||
CustomTemplate template = CustomTemplate
|
||||
.builder()
|
||||
.server(serverManagementService.loadServer(serverId))
|
||||
.content(templateContent)
|
||||
.key(templateKey)
|
||||
.build();
|
||||
customTemplateRepository.save(template);
|
||||
return template;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CustomTemplate> getCustomTemplate(String templateKey, Long serverId) {
|
||||
return customTemplateRepository.findByKeyAndServerId(templateKey, serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesCustomTemplateExist(String templateKey, Long serverId) {
|
||||
return getCustomTemplate(templateKey, serverId).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCustomTemplateByKey(String templateKey, Long serverId) {
|
||||
Optional<CustomTemplate> customTemplateOptional = getCustomTemplate(templateKey, serverId);
|
||||
customTemplateOptional.ifPresent(this::deleteCustomTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCustomTemplate(CustomTemplate customTemplate) {
|
||||
customTemplateRepository.delete(customTemplate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sheldan.abstracto.core.templating.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.templating.model.EffectiveTemplate;
|
||||
import dev.sheldan.abstracto.core.templating.repository.EffectiveTemplateRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class EffectiveTemplateManagementServiceBean implements EffectiveTemplateManagementService {
|
||||
|
||||
@Autowired
|
||||
private EffectiveTemplateRepository effectiveTemplateRepository;
|
||||
|
||||
@Override
|
||||
public Optional<EffectiveTemplate> getTemplateByKeyAndServer(String key, Long server) {
|
||||
return effectiveTemplateRepository.findByKeyAndServerId(key, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<EffectiveTemplate> getTemplateByKey(String key) {
|
||||
return effectiveTemplateRepository.findByKey(key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package dev.sheldan.abstracto.core.templating.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.templating.model.database.Template;
|
||||
import dev.sheldan.abstracto.core.templating.repository.TemplateRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* ManagementService bean used to retrieve the templates by key from the database.
|
||||
* This class uses the {@link TemplateRepository} bean to load the {@link Template} objects.
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class TemplateManagementServiceBean implements TemplateManagementService {
|
||||
|
||||
@Autowired
|
||||
private TemplateRepository repository;
|
||||
|
||||
/**
|
||||
* Returns the template from the database by key
|
||||
* @param key They template key to search for
|
||||
* @return An {@link Optional} containing the {@link Template} if any was found.
|
||||
*/
|
||||
@Override
|
||||
public Optional<Template> getTemplateByKey(String key) {
|
||||
return repository.findById(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the template identified by the key exists in the database
|
||||
* @param key They key of the template to search for
|
||||
* @return Whether or not the template exists in the database
|
||||
*/
|
||||
@Override
|
||||
public boolean templateExists(String key) {
|
||||
return repository.existsById(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Template} object and stores it in the database. Returns the newly created object.
|
||||
* @param key They key of the template to create.
|
||||
* @param content The content the template should have
|
||||
* @return The {@link Template} which was created
|
||||
*/
|
||||
@Override
|
||||
public Template createTemplate(String key, String content) {
|
||||
Template build = Template.builder().key(key).content(content).lastModified(Instant.now()).build();
|
||||
repository.save(build);
|
||||
return build;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -103,6 +103,30 @@
|
||||
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="setTemplate"/>
|
||||
<column name="module_id" valueComputed="${configModule}"/>
|
||||
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="getTemplate"/>
|
||||
<column name="module_id" valueComputed="${configModule}"/>
|
||||
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="resetTemplate"/>
|
||||
<column name="module_id" valueComputed="${configModule}"/>
|
||||
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="getCustomTemplate"/>
|
||||
<column name="module_id" valueComputed="${configModule}"/>
|
||||
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="setupFeature"/>
|
||||
<column name="module_id" valueComputed="${configModule}"/>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../dbchangelog-3.8.xsd" >
|
||||
<include file="templating-tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="templating-seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="templates-auto_load_macro">
|
||||
<insert tableName="auto_load_macro">
|
||||
<column name="key" value="safe_macro"/>
|
||||
</insert>
|
||||
<insert tableName="auto_load_macro">
|
||||
<column name="key" value="member_user_name"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<include file="auto_load_macro.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="auto_load_macro-table">
|
||||
<createTable tableName="auto_load_macro">
|
||||
<column name="key" type="VARCHAR(255)">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="auto_load_macro_pkey"/>
|
||||
</column>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
<!-- TODO doesnt work for initial config, because auto load macros are defined, but templates not present yet
|
||||
<changeSet author="Sheldan" id="auto_load_macro-fk_assignable_role_emote">
|
||||
<addForeignKeyConstraint baseColumnNames="key" baseTableName="auto_load_macro" constraintName="fk_auto_load_macro_template" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="key" referencedTableName="template" validate="true"/>
|
||||
</changeSet>
|
||||
-->
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="custom_template-table">
|
||||
<createTable tableName="custom_template">
|
||||
<column name="key" type="VARCHAR(255)">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="section" type="VARCHAR(255)"/>
|
||||
<column name="last_modified" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="content" type="VARCHAR(4000)"/>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addPrimaryKey columnNames="server_id, key" tableName="custom_template" constraintName="pk_custom_template" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS custom_template_update_trigger ON custom_template;
|
||||
CREATE TRIGGER custom_template_update_trigger BEFORE UPDATE ON custom_template FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS custom_template_insert_trigger ON custom_template;
|
||||
CREATE TRIGGER custom_template_insert_trigger BEFORE INSERT ON custom_template FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS custom_template_last_modified_trigger ON custom_template;
|
||||
CREATE TRIGGER custom_template_last_modified_trigger BEFORE UPDATE ON custom_template FOR EACH ROW EXECUTE PROCEDURE last_modified_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS custom_template_last_modified_insert_trigger ON custom_template;
|
||||
CREATE TRIGGER custom_template_last_modified_insert_trigger BEFORE INSERT ON custom_template FOR EACH ROW EXECUTE PROCEDURE last_modified_trigger_procedure();
|
||||
</sql>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="custom_template" constraintName="fk_custom_template_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="key" baseTableName="custom_template" constraintName="fk_custom_template_template" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="key" referencedTableName="template" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,8 @@
|
||||
CREATE OR REPLACE FUNCTION last_modified_trigger_procedure() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW.last_modified := CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<include file="trigger_functions.xml" relativeToChangelogFile="true"/>
|
||||
<include file="template.xml" relativeToChangelogFile="true"/>
|
||||
<include file="custom_template.xml" relativeToChangelogFile="true"/>
|
||||
<include file="auto_load_macro.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="template-table">
|
||||
<createTable tableName="template">
|
||||
<column name="key" type="VARCHAR(255)">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="template_pkey"/>
|
||||
</column>
|
||||
<column name="section" type="VARCHAR(255)"/>
|
||||
<column name="last_modified" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="content" type="VARCHAR(4000)"/>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS template_update_trigger ON template;
|
||||
CREATE TRIGGER template_update_trigger BEFORE UPDATE ON template FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS template_insert_trigger ON template;
|
||||
CREATE TRIGGER template_insert_trigger BEFORE INSERT ON template FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS template_last_modified_trigger ON template;
|
||||
CREATE TRIGGER template_last_modified_trigger BEFORE UPDATE ON template FOR EACH ROW EXECUTE PROCEDURE last_modified_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS template_last_modified_insert_trigger ON template;
|
||||
CREATE TRIGGER template_last_modified_insert_trigger BEFORE INSERT ON template FOR EACH ROW EXECUTE PROCEDURE last_modified_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="last_modified_trigger" dbms="postgresql">
|
||||
<sqlFile encoding="utf8" path="sql/last_modified_trigger.sql"
|
||||
relativeToChangelogFile="true"
|
||||
splitStatements="false"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -7,4 +7,5 @@
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog-3.8.xsd" >
|
||||
<include file="1.0-core/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.0-templating/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
@@ -14,7 +15,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AChannelParameterHandlerImplTest {
|
||||
public class AChannelParameterHandlerImplTest extends AbstractParameterHandlerTest {
|
||||
|
||||
@InjectMocks
|
||||
private AChannelParameterHandlerImpl testUnit;
|
||||
@@ -49,10 +50,10 @@ public class AChannelParameterHandlerImplTest {
|
||||
|
||||
@Test
|
||||
public void testProperChannelMention() {
|
||||
String input = "test";
|
||||
when(textChannelParameterHandler.handle(input, iterators, TextChannel.class, message)).thenReturn(channel);
|
||||
UnparsedCommandParameterPiece piece = getPieceWithValue("input");
|
||||
when(textChannelParameterHandler.handle(piece, iterators, TextChannel.class, message)).thenReturn(channel);
|
||||
when(channelService.getFakeChannelFromTextChannel(channel)).thenReturn(aChannel);
|
||||
AChannel parsed = (AChannel) testUnit.handle(input, iterators, TextChannel.class, message);
|
||||
AChannel parsed = (AChannel) testUnit.handle(piece, iterators, TextChannel.class, message);
|
||||
Assert.assertEquals(aChannel, parsed);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
@@ -14,8 +15,9 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AEmoteParameterHandlerImplImplTest {
|
||||
public class AEmoteParameterHandlerImplImplTest extends AbstractParameterHandlerTest {
|
||||
|
||||
public static final String INPUT = "input";
|
||||
@InjectMocks
|
||||
private AEmoteParameterHandlerImpl testUnit;
|
||||
|
||||
@@ -49,19 +51,19 @@ public class AEmoteParameterHandlerImplImplTest {
|
||||
|
||||
@Test
|
||||
public void testProperEmoteMention() {
|
||||
String input = "test";
|
||||
when(emoteParameterHandler.handle(input, iterators, Emote.class, message)).thenReturn(emote);
|
||||
UnparsedCommandParameterPiece piece = getPieceWithValue(INPUT);
|
||||
when(emoteParameterHandler.handle(piece, iterators, Emote.class, message)).thenReturn(emote);
|
||||
when(emoteService.getFakeEmoteFromEmote(emote)).thenReturn(aEmote);
|
||||
AEmote parsed = (AEmote) testUnit.handle(input, iterators, AEmote.class, message);
|
||||
AEmote parsed = (AEmote) testUnit.handle(piece, iterators, AEmote.class, message);
|
||||
Assert.assertEquals(aEmote, parsed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultEmoteHandling() {
|
||||
String input = "test";
|
||||
when(emoteParameterHandler.handle(input, iterators, Emote.class, message)).thenReturn(null);
|
||||
when(emoteService.getFakeEmote(input)).thenReturn(aEmote);
|
||||
AEmote parsed = (AEmote) testUnit.handle(input, iterators, AEmote.class, message);
|
||||
UnparsedCommandParameterPiece piece = getPieceWithValue(INPUT);
|
||||
when(emoteParameterHandler.handle(piece, iterators, Emote.class, message)).thenReturn(null);
|
||||
when(emoteService.getFakeEmote(INPUT)).thenReturn(aEmote);
|
||||
AEmote parsed = (AEmote) testUnit.handle(piece, iterators, AEmote.class, message);
|
||||
Assert.assertEquals(aEmote, parsed);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.service.RoleService;
|
||||
@@ -15,7 +16,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ARoleParameterHandlerImplImplTest {
|
||||
public class ARoleParameterHandlerImplImplTest extends AbstractParameterHandlerTest {
|
||||
|
||||
@InjectMocks
|
||||
private ARoleParameterHandlerImpl testUnit;
|
||||
@@ -50,10 +51,10 @@ public class ARoleParameterHandlerImplImplTest {
|
||||
|
||||
@Test
|
||||
public void testProperRoleMention() {
|
||||
String input = "test";
|
||||
when(roleParameterHandler.handle(input, iterators, Role.class, message)).thenReturn(role);
|
||||
UnparsedCommandParameterPiece piece = getPieceWithValue("test");
|
||||
when(roleParameterHandler.handle(piece, iterators, Role.class, message)).thenReturn(role);
|
||||
when(roleService.getFakeRoleFromRole(role)).thenReturn(aRole);
|
||||
ARole parsed = (ARole) testUnit.handle(input, iterators, AEmote.class, message);
|
||||
ARole parsed = (ARole) testUnit.handle(piece, iterators, AEmote.class, message);
|
||||
Assert.assertEquals(aRole, parsed);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
|
||||
public abstract class AbstractParameterHandlerTest {
|
||||
protected UnparsedCommandParameterPiece getPieceWithValue(String value) {
|
||||
return UnparsedCommandParameterPiece.builder().value(value).build();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -7,7 +8,7 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BooleanParameterHandlerImplTest {
|
||||
public class BooleanParameterHandlerImplTest extends AbstractParameterHandlerTest {
|
||||
|
||||
@InjectMocks
|
||||
private BooleanParameterHandlerImpl testUnit;
|
||||
@@ -24,22 +25,26 @@ public class BooleanParameterHandlerImplTest {
|
||||
|
||||
@Test
|
||||
public void testTrueParsing() {
|
||||
Assert.assertTrue((Boolean)testUnit.handle("true", null, null, null));
|
||||
UnparsedCommandParameterPiece piece = getPieceWithValue("true");
|
||||
Assert.assertTrue((Boolean)testUnit.handle(piece, null, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnyOtherText() {
|
||||
Assert.assertFalse((Boolean)testUnit.handle("test", null, null, null));
|
||||
UnparsedCommandParameterPiece piece = getPieceWithValue("test");
|
||||
Assert.assertFalse((Boolean)testUnit.handle(piece, null, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullInput() {
|
||||
Assert.assertFalse((Boolean)testUnit.handle(null, null, null, null));
|
||||
UnparsedCommandParameterPiece piece = getPieceWithValue(null);
|
||||
Assert.assertFalse((Boolean)testUnit.handle(piece, null, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyStringAsInput() {
|
||||
Assert.assertFalse((Boolean)testUnit.handle("", null, null, null));
|
||||
UnparsedCommandParameterPiece piece = getPieceWithValue("");
|
||||
Assert.assertFalse((Boolean)testUnit.handle(piece, null, null, null));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DoubleParameterHandlerImplTest {
|
||||
public class DoubleParameterHandlerImplTest extends AbstractParameterHandlerTest {
|
||||
|
||||
@InjectMocks
|
||||
private DoubleParameterHandlerImpl testUnit;
|
||||
@@ -24,32 +24,32 @@ public class DoubleParameterHandlerImplTest {
|
||||
|
||||
@Test
|
||||
public void testSuccessfulParse() {
|
||||
Assert.assertEquals(5D, testUnit.handle("5", null, null, null));
|
||||
Assert.assertEquals(5D, testUnit.handle(getPieceWithValue("5"), null, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativeNumber() {
|
||||
Assert.assertEquals(-5D, testUnit.handle("-5", null, null, null));
|
||||
Assert.assertEquals(-5D, testUnit.handle(getPieceWithValue("-5"), null, null, null));
|
||||
}
|
||||
|
||||
|
||||
public void testDecimal() {
|
||||
Assert.assertEquals(3.14D, testUnit.handle("3.14", null, null, null));
|
||||
Assert.assertEquals(3.14D, testUnit.handle(getPieceWithValue("3.14"), null, null, null));
|
||||
}
|
||||
|
||||
@Test(expected = NumberFormatException.class)
|
||||
public void testTextAsInput() {
|
||||
testUnit.handle("someText", null, null, null);
|
||||
testUnit.handle(getPieceWithValue("someText"), null, null, null);
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testNullInput() {
|
||||
testUnit.handle(null, null, null, null);
|
||||
testUnit.handle(getPieceWithValue(null), null, null, null);
|
||||
}
|
||||
|
||||
@Test(expected = NumberFormatException.class)
|
||||
public void testEmptyStringAsInput() {
|
||||
testUnit.handle("", null, null, null);
|
||||
testUnit.handle(getPieceWithValue(""), null, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DurationParameterHandlerImplTest {
|
||||
public class DurationParameterHandlerImplTest extends AbstractParameterHandlerTest {
|
||||
|
||||
@InjectMocks
|
||||
private DurationParameterHandlerImpl testUnit;
|
||||
@@ -28,23 +28,23 @@ public class DurationParameterHandlerImplTest {
|
||||
|
||||
@Test
|
||||
public void testSimpleParsing() {
|
||||
Assert.assertEquals(Duration.ofMinutes(1), testUnit.handle("1m", null, null, null));
|
||||
Assert.assertEquals(Duration.ofMinutes(1), testUnit.handle(getPieceWithValue("1m"), null, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoreComplicatedParsing() {
|
||||
Duration targetDuration = Duration.ofDays(4).plus(5, ChronoUnit.HOURS).plus(5, ChronoUnit.MINUTES);
|
||||
Assert.assertEquals(targetDuration, testUnit.handle("5m5h4d", null, null, null));
|
||||
Assert.assertEquals(targetDuration, testUnit.handle(getPieceWithValue("5h5m4d"), null, null, null));
|
||||
}
|
||||
|
||||
@Test(expected = DurationFormatException.class)
|
||||
public void testNullInput() {
|
||||
testUnit.handle(null, null, null, null);
|
||||
testUnit.handle(getPieceWithValue(null), null, null, null);
|
||||
}
|
||||
|
||||
@Test(expected = DurationFormatException.class)
|
||||
public void testEmptyStringAsInput() {
|
||||
testUnit.handle("", null, null, null);
|
||||
testUnit.handle(getPieceWithValue(""), null, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user