added templating support

changed ping command to use templates
added userjoin/userleave event
added guild to command context
refactored post target service
added logging output to initial loading
added server_id to postTarget
added leave log postTarget
This commit is contained in:
Sheldan
2020-03-16 01:28:17 +01:00
parent 5c6b7b9a78
commit 0521a1ab44
30 changed files with 491 additions and 34 deletions

View File

@@ -5,31 +5,31 @@ import dev.sheldan.abstracto.command.execution.Configuration;
import dev.sheldan.abstracto.command.execution.Context;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.core.models.AChannel;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.PostTargetService;
import net.dv8tion.jda.api.entities.GuildChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
@Service
public class PostTarget implements Command {
public class SetPostTargetCommand implements Command {
@Autowired
private PostTargetService service;
private PostTargetService postTargetService;
@Autowired
private ChannelService channelService;
@Override
@Transactional
public Result execute(Context context) {
GuildChannel channel = (GuildChannel) context.getParameters().getParameters().get(1);
String targetName = (String) context.getParameters().getParameters().get(0);
AChannel dbChannel = channelService.loadChannel(channel.getIdLong());
service.createOrUpdate(targetName, dbChannel);
postTargetService.createOrUpdate(targetName, channel.getIdLong(), channel.getGuild().getIdLong());
return Result.fromSuccess();
}

View File

@@ -1,20 +1,32 @@
package dev.sheldan.abstracto.command.utility;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.Module;
import dev.sheldan.abstracto.command.execution.Configuration;
import dev.sheldan.abstracto.command.execution.Context;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.templating.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
@Service
public class Ping implements Command {
public static final String PING_TEMPLATE = "ping";
@Autowired
private TemplateService templateService;
@Override
@Transactional
public Result execute(Context context) {
long ping = context.getJda().getGatewayPing();
context.getChannel().sendMessage("Latency: " + ping + " ms.").queue();
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("latency", ping);
String text = templateService.renderTemplate(PING_TEMPLATE, parameters);
context.getChannel().sendMessage(text).queue();
return Result.fromSuccess();
}

View File

@@ -29,6 +29,12 @@
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.templating</groupId>
<artifactId>templating-interface</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

View File

@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.command.execution;
import lombok.Builder;
import lombok.Getter;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
@@ -11,6 +12,7 @@ import net.dv8tion.jda.api.entities.User;
@Getter
public class Context {
private TextChannel channel;
private Guild guild;
private User author;
private Message message;
private Parameters parameters;

View File

@@ -42,6 +42,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
Parameters parsedParameters = getParsedParameters(unparsedParameter, foundCommand, event.getMessage());
Context context = Context.builder()
.author(event.getAuthor())
.guild(event.getGuild())
.channel(event.getTextChannel())
.message(event.getMessage())
.parameters(parsedParameters)

View File

@@ -24,10 +24,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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-oauth2-client</artifactId>
@@ -90,6 +86,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.templating</groupId>
<artifactId>templating-interface</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -2,46 +2,69 @@ package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.commands.management.PostTargetException;
import dev.sheldan.abstracto.core.models.AChannel;
import dev.sheldan.abstracto.core.models.AServer;
import dev.sheldan.abstracto.core.models.PostTarget;
import dev.sheldan.abstracto.repository.ChannelRepository;
import dev.sheldan.abstracto.repository.PostTargetRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
@Service
@Slf4j
public class PostTargetServiceServiceBean implements PostTargetService {
@Autowired
private PostTargetRepository postTargetRepository;
@Autowired
private ChannelRepository channelRepository;
private ChannelService channelService;
@Autowired
private ServerService serverService;
@Override
@Transactional
public void createPostTarget(String name, AChannel targetChannel) {
public void createPostTarget(String name, AChannel targetChannel, AServer server) {
if(!PostTarget.AVAILABLE_POST_TARGETS.contains(name)) {
throw new PostTargetException("PostTarget not found");
}
postTargetRepository.save(PostTarget.builder().name(name).AChannel(targetChannel).build());
log.info("Creating post target {} pointing towards {}", name, targetChannel);
postTargetRepository.save(PostTarget.builder().name(name).channelReference(targetChannel).serverReference(server).build());
}
@Override
@Transactional
public void createOrUpdate(String name, AChannel targetChannel) {
public void createOrUpdate(String name, AChannel targetChannel, AServer server) {
PostTarget existing = postTargetRepository.findPostTargetByName(name);
if(existing == null){
this.createPostTarget(name, targetChannel);
this.createPostTarget(name, targetChannel, server);
} else {
this.updatePostTarget(existing, targetChannel);
this.updatePostTarget(existing, targetChannel, server);
}
}
@Override
@Transactional
public void updatePostTarget(PostTarget target, AChannel newTargetChannel) {
postTargetRepository.getOne(target.getId()).setAChannel(newTargetChannel);
public void createOrUpdate(String name, Long channelId, AServer server) {
AChannel dbChannel = channelService.loadChannel(channelId);
createOrUpdate(name, dbChannel, server);
}
@Override
public void createOrUpdate(String name, Long channelId, Long serverId) {
AChannel dbChannel = channelService.loadChannel(channelId);
AServer dbServer = serverService.loadServer(serverId);
createOrUpdate(name, dbChannel, dbServer);
}
@Override
@Cacheable("posttargets")
public PostTarget getPostTarget(String name, AServer server) {
return postTargetRepository.findPostTargetByName(name);
}
@Override
public void updatePostTarget(PostTarget target, AChannel newTargetChannel, AServer server) {
postTargetRepository.getOne(target.getId()).setChannelReference(newTargetChannel);
}
}

View File

@@ -15,11 +15,19 @@ public class ServerServiceBean implements ServerService {
private ServerRepository repository;
@Override
@Transactional
public AServer createServer(Long id) {
return repository.save(AServer.builder().id(id).build());
}
@Override
@Transactional
public AServer loadServer(Long id) {
return repository.getOne(id);
}
@Override
@Transactional
public void addChannelToServer(AServer server, AChannel channel) {
server.getChannels().add(channel);
}

View File

@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.models.AChannel;
import dev.sheldan.abstracto.core.models.AChannelType;
import dev.sheldan.abstracto.core.models.ARole;
import dev.sheldan.abstracto.core.models.AServer;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildChannel;
@@ -19,6 +20,7 @@ import javax.transaction.Transactional;
import java.util.List;
import java.util.Set;
@Slf4j
@Service
public class StartupManager implements Startup {
@@ -47,7 +49,9 @@ public class StartupManager implements Startup {
@Override
@Transactional
public void synchronize() {
log.info("Synchronizing servers.");
synchronizeServers();
log.info("Done synchronizing servers");
}
private void synchronizeServers(){
@@ -57,6 +61,7 @@ public class StartupManager implements Startup {
availableServers.forEach(aLong -> {
AServer newAServer = serverService.createServer(aLong);
Guild newGuild = instance.getGuildById(aLong);
log.debug("Synchronizing server: {}", aLong);
if(newGuild != null){
synchronizeRolesOf(newGuild, newAServer);
synchronizeChannelsOf(newGuild, newAServer);
@@ -73,6 +78,7 @@ public class StartupManager implements Startup {
Set<Long> newRoles = SetUtils.disjunction(availableRoles, knownRolesId);
newRoles.forEach(aLong -> {
ARole newRole = roleService.createRole(aLong);
log.debug("Adding new role: {}", aLong);
existingAServer.getRoles().add(newRole);
});
}
@@ -85,6 +91,7 @@ public class StartupManager implements Startup {
Set<Long> newChannels = SetUtils.disjunction(existingChannelsIds, knownChannelsIds);
newChannels.forEach(aLong -> {
GuildChannel channel1 = available.stream().filter(channel -> channel.getIdLong() == aLong).findFirst().get();
log.debug("Adding new channel: {}", aLong);
AChannelType type = AChannel.getAChannelType(channel1.getType());
AChannel newChannel = channelService.createChannel(channel1.getIdLong(), type);
serverService.addChannelToServer(existingServer, newChannel);

View File

@@ -0,0 +1,74 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.models.AServer;
import dev.sheldan.abstracto.core.models.PostTarget;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.service.ServerService;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.HashMap;
@Service
@Slf4j
public class JoinLeaveListener extends ListenerAdapter {
public static final String USER_JOIN_TEMPLATE = "user_join";
public static final String USER_LEAVE_TEMPLATE = "user_leave";
@Autowired
private PostTargetService postTargetService;
@Autowired
private ServerService serverService;
@Autowired
private TemplateService templateService;
@Override
@Transactional
public void onGuildMemberJoin(@Nonnull GuildMemberJoinEvent event) {
AServer server = serverService.loadServer(event.getGuild().getIdLong());
PostTarget target = postTargetService.getPostTarget(PostTarget.JOIN_LOG, server);
TextChannel textChannelById = event.getGuild().getTextChannelById(target.getChannelReference().getId());
if(textChannelById != null){
HashMap<String, Object> parameters = getUserParameter(event.getUser());
String text = templateService.renderTemplate(USER_JOIN_TEMPLATE, parameters);
textChannelById.sendMessage(text).queue();
} else {
log.warn("{} post target is not defined for server {}", PostTarget.JOIN_LOG, server.getId());
}
}
@NotNull
private HashMap<String, Object> getUserParameter(@Nonnull User user) {
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("user", user);
parameters.put("userMention", user.getAsMention());
return parameters;
}
@Override
@Transactional
public void onGuildMemberLeave(@Nonnull GuildMemberLeaveEvent event) {
AServer server = serverService.loadServer(event.getGuild().getIdLong());
PostTarget target = postTargetService.getPostTarget(PostTarget.LEAVE_LOG, server);
TextChannel textChannelById = event.getGuild().getTextChannelById(target.getChannelReference().getId());
if(textChannelById != null){
HashMap<String, Object> parameters = getUserParameter(event.getUser());
String text = templateService.renderTemplate(USER_LEAVE_TEMPLATE, parameters);
textChannelById.sendMessage(text).queue();
} else {
log.warn("{} post target is not defined for server {}", PostTarget.LEAVE_LOG, server.getId());
}
}
}

View File

@@ -0,0 +1 @@
User ${user.name}#${user.discriminator} (${userMention}) has joined the guild.

View File

@@ -0,0 +1 @@
User ${user.name}#${user.discriminator} (${userMention}) has left the guild.

View File

@@ -23,12 +23,18 @@ public class PostTarget {
@Getter
private String name;
@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "id", nullable = false)
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "channel_id", nullable = false)
@Getter @Setter
private AChannel AChannel;
private AChannel channelReference;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="server_id", nullable = false)
@Getter @Setter
private AServer serverReference;
public static String JOIN_LOG = "joinlog";
public static String LEAVE_LOG = "leavelog";
public static List<String> AVAILABLE_POST_TARGETS = Arrays.asList(JOIN_LOG);
public static List<String> AVAILABLE_POST_TARGETS = Arrays.asList(JOIN_LOG, LEAVE_LOG);
}

View File

@@ -1,10 +1,14 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.models.AChannel;
import dev.sheldan.abstracto.core.models.AServer;
import dev.sheldan.abstracto.core.models.PostTarget;
public interface PostTargetService {
void createPostTarget(String name, AChannel targetChanel);
void createOrUpdate(String name, AChannel targetChannel);
void updatePostTarget(PostTarget target, AChannel newTargetChannel);
void createPostTarget(String name, AChannel targetChanel, AServer server);
void createOrUpdate(String name, AChannel targetChannel, AServer server);
void createOrUpdate(String name, Long channelId, AServer server);
void createOrUpdate(String name, Long channelId, Long serverId);
PostTarget getPostTarget(String name, AServer server);
void updatePostTarget(PostTarget target, AChannel newTargetChannel, AServer server);
}

View File

@@ -5,5 +5,6 @@ import dev.sheldan.abstracto.core.models.AServer;
public interface ServerService {
AServer createServer(Long id);
AServer loadServer(Long id);
void addChannelToServer(AServer server, AChannel channel);
}

View File

@@ -39,6 +39,12 @@
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.templating</groupId>
<artifactId>templating-impl</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<!-- modules containing commands -->

View File

@@ -4,11 +4,14 @@ import dev.sheldan.abstracto.core.service.Startup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableAutoConfiguration(exclude = { FreeMarkerAutoConfiguration.class })
@ComponentScan(basePackages = {"dev.sheldan.abstracto"})
@EnableCaching
public class Application implements CommandLineRunner {

View File

@@ -1,11 +1,17 @@
spring.datasource.url=jdbc:postgresql://localhost:5432/abstracto
spring.datasource.username= abstracto
spring.datasource.password= abstracto
spring.jpa.properties.hibernate.default_schema=abstracto
spring.jpa.hibernate.default_schema=abstracto
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = create-drop
spring.jpa.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.naming_strategy = org.hibernate.cfg.ImprovedNamingStrategy
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type.descriptor.sql=trace
log4j.logger.org.hibernate.type=trace
abstracto.startup.synchronize=true
abstracto.startup.synchronize=true
logging.level.dev.sheldan=DEBUG

View File

@@ -18,6 +18,7 @@
<module>command</module>
<module>core</module>
<module>executable</module>
<module>templating</module>
</modules>
@@ -39,6 +40,11 @@
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>abstracto-application</artifactId>
<groupId>dev.sheldan.abstracto</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>dev.sheldan.abstracto.templating</groupId>
<artifactId>templating</artifactId>
<packaging>pom</packaging>
<modules>
<module>templating-interface</module>
<module>templating-impl</module>
</modules>
</project>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>templating</artifactId>
<groupId>dev.sheldan.abstracto.templating</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>templating-impl</artifactId>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.templating</groupId>
<artifactId>templating-interface</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,24 @@
package dev.sheldan.abstracto.templating.config;
import dev.sheldan.abstracto.templating.loading.DatabaseTemplateLoader;
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;
@org.springframework.context.annotation.Configuration
public class FreemarkerConfiguration {
@Autowired
private DatabaseTemplateLoader templateLoader;
@Bean
public Configuration freeMarkerConfiguration() throws IOException, TemplateException {
FreeMarkerConfigurationFactory factory = new FreeMarkerConfigurationFactory();
factory.setPreTemplateLoaders(templateLoader);
return factory.createConfiguration();
}
}

View File

@@ -0,0 +1,49 @@
package dev.sheldan.abstracto.templating.loading;
import dev.sheldan.abstracto.templating.TemplateDto;
import dev.sheldan.abstracto.templating.TemplateService;
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;
@Component
public class DatabaseTemplateLoader implements TemplateLoader {
@Autowired
private TemplateService templateService;
@Override
public Object findTemplateSource(String s) throws IOException {
TemplateDto templateDtoByKey = templateService.getTemplateByKey(s);
if(templateDtoByKey != null){
return templateDtoByKey;
} else {
return null;
}
}
@Override
public long getLastModified(Object o) {
TemplateDto casted = (TemplateDto) o;
TemplateDto templateDtoByKey = templateService.getTemplateByKey(casted.getKey());
if(templateDtoByKey != null){
return templateDtoByKey.getLastModified().getEpochSecond();
} else {
return Long.MAX_VALUE;
}
}
@Override
public Reader getReader(Object o, String s) throws IOException {
return new StringReader(((TemplateDto) o).getContent());
}
@Override
public void closeTemplateSource(Object o) throws IOException {
}
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.templating.loading;
import dev.sheldan.abstracto.templating.TemplateDto;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TemplateRepository extends JpaRepository<TemplateDto, String> {
}

View File

@@ -0,0 +1,52 @@
package dev.sheldan.abstracto.templating.loading;
import dev.sheldan.abstracto.templating.TemplateDto;
import dev.sheldan.abstracto.templating.TemplateService;
import freemarker.template.Configuration;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import java.io.IOException;
import java.time.Instant;
import java.util.HashMap;
@Component
public class TemplateServiceBean implements TemplateService {
@Autowired
private TemplateRepository repository;
@Autowired
private Configuration configuration;
@Override
@Cacheable("template")
public TemplateDto getTemplateByKey(String key) {
return repository.getOne(key);
}
@Override
public String renderTemplate(TemplateDto templateDto) {
return null;
}
@Override
public String renderTemplate(String key, HashMap<String, Object> parameters) {
try {
return FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate(key), parameters);
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
return "";
}
@Override
public void createTemplate(String key, String content) {
repository.save(TemplateDto.builder().key(key).content(content).lastModified(Instant.now()).build());
}
}

View File

@@ -0,0 +1,40 @@
package dev.sheldan.abstracto.templating.seeddata;
import dev.sheldan.abstracto.templating.TemplateService;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
@Component
public class TemplateSeedDataLoader {
@Value("classpath*:**/templates/**/*.ftl")
private Resource[] resources;
@Autowired
private TemplateService service;
@EventListener
public void handleContextRefreshEvent(ContextRefreshedEvent ctxStartEvt) {
List<Resource> templatesToLoad = Arrays.asList(resources);
templatesToLoad.forEach(resource -> {
try {
String templateKey = FilenameUtils.getBaseName(resource.getFilename());
String templateContent = IOUtils.toString(resource.getURI(), Charset.defaultCharset());
service.createTemplate(templateKey, templateContent);
} catch (IOException e) {
e.printStackTrace();
}
});
}
}

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto.templating</groupId>
<artifactId>templating</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>templating-interface</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,32 @@
package dev.sheldan.abstracto.templating;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.Instant;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "template")
public class TemplateDto {
@Id
@Getter
private String key;
@Getter
private String content;
@Getter
private String section;
@Getter
private Instant lastModified;
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.templating;
import java.util.HashMap;
public interface TemplateService {
TemplateDto getTemplateByKey(String key);
String renderTemplate(TemplateDto templateDto);
String renderTemplate(String key, HashMap<String, Object> parameters);
void createTemplate(String key, String content);
}