mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-08 02:17:43 +00:00
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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Latency: ${latency} ms.
|
||||
@@ -0,0 +1 @@
|
||||
User ${user.name}#${user.discriminator} (${userMention}) has joined the guild.
|
||||
@@ -0,0 +1 @@
|
||||
User ${user.name}#${user.discriminator} (${userMention}) has left the guild.
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
21
abstracto-application/templating/pom.xml
Normal file
21
abstracto-application/templating/pom.xml
Normal 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>
|
||||
31
abstracto-application/templating/templating-impl/pom.xml
Normal file
31
abstracto-application/templating/templating-impl/pom.xml
Normal 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>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user