[AB-203] restructuring listeners to use more common code and common interfaces for listeners and models

restructuring entity listener to be async and added models
fixing usage of repository save method
adding interface dependencies to bundle dependency management
This commit is contained in:
Sheldan
2021-03-21 10:58:31 +01:00
parent cfe7786d4d
commit b4e36efafb
241 changed files with 3521 additions and 2049 deletions

View File

@@ -4,8 +4,11 @@ import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.models.database.ACommand;
import dev.sheldan.abstracto.core.command.service.management.CommandInServerManagementService;
import dev.sheldan.abstracto.core.command.service.management.CommandManagementService;
import dev.sheldan.abstracto.core.listener.sync.entity.ServerConfigListener;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.entity.AsyncServerCreatedListener;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.listener.ServerCreatedListenerModel;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -14,7 +17,7 @@ import java.util.List;
@Component
@Slf4j
public class CommandConfigListener implements ServerConfigListener {
public class CommandConfigListenerAsync implements AsyncServerCreatedListener {
@Autowired
private List<Command> commandList;
@@ -25,9 +28,13 @@ public class CommandConfigListener implements ServerConfigListener {
@Autowired
private CommandManagementService commandManagementService;
@Autowired
private ServerManagementService serverManagementService;
@Override
public void updateServerConfig(AServer server) {
log.info("Creating command instances for server {}.", server.getId());
public DefaultListenerResult execute(ServerCreatedListenerModel model) {
AServer server = serverManagementService.loadServer(model.getServerId());
log.info("Creating command instances for server {}.", model.getServerId());
commandList.forEach(command -> {
if(command.getConfiguration() != null) {
ACommand aCommand = commandManagementService.findCommandByName(command.getConfiguration().getName());
@@ -36,5 +43,6 @@ public class CommandConfigListener implements ServerConfigListener {
}
}
});
return DefaultListenerResult.PROCESSED;
}
}

View File

@@ -40,8 +40,7 @@ public class ChannelGroupCommandManagementServiceBean implements ChannelGroupCom
log.info("Creating command {} in group {}.", command.getName(), group.getId());
groupCommandRepository.save(channelGroupCommand);
return channelGroupCommand;
return groupCommandRepository.save(channelGroupCommand);
}
@Override

View File

@@ -24,9 +24,8 @@ public class CommandInServerManagementServiceBean implements CommandInServerMana
.serverReference(server)
.restricted(false)
.build();
repository.save(commandInAServer);
log.info("Creating command {} in server {}.", command.getName(), server.getId());
return commandInAServer;
return repository.save(commandInAServer);
}
@Override

View File

@@ -40,8 +40,7 @@ public class CommandManagementServiceBean implements CommandManagementService {
.feature(feature)
.build();
log.info("Creating creating command {} in module {} with feature {}.", name, module.getName(), feature.getKey());
commandRepository.save(command);
return command;
return commandRepository.save(command);
}
@Override

View File

@@ -19,9 +19,8 @@ public class ModuleManagementServiceBean implements ModuleManagementService {
builder()
.name(name)
.build();
moduleRepository.save(module);
log.info("Creating module {}.", name);
return module;
return moduleRepository.save(module);
}
@Override

View File

@@ -1,117 +1,82 @@
package dev.sheldan.abstracto.core.config;
import dev.sheldan.abstracto.core.service.ExecutorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
public class ListenerExecutorConfig {
@Value("${abstracto.listener.default.maxPoolSize}")
private Integer defaultMaxPoolSize;
@Value("${abstracto.listener.default.corePoolSize}")
private Integer defaultCorePoolSize;
@Value("${abstracto.listener.default.keepAliveSeconds}")
private Integer defaultKeepAliveSeconds;
@Autowired
private Environment environment;
private static final String LISTENER_PREFIX = "abstracto.listener.";
private static final String LISTENER_MAX_POOL_SIZE = "maxPoolSize";
private static final String LISTENER_CORE_POOL_SIZE = "corePoolSize";
private static final String LISTENER_KEEP_ALIVE_SECONDS = "keepAliveSeconds";
private ExecutorService executorService;
@Bean(name = "joinListenerExecutor")
public TaskExecutor joinListenerExecutor() {
return setupExecutorFor("joinListener");
return executorService.setupExecutorFor("joinListener");
}
@Bean(name = "leaveListenerExecutor")
public TaskExecutor leaveListenerExecutor() {
return setupExecutorFor("leaveListener");
return executorService.setupExecutorFor("leaveListener");
}
@Bean(name = "messageReceivedExecutor")
public TaskExecutor messageReceivedExecutor() {
return setupExecutorFor("messageReceivedListener");
return executorService.setupExecutorFor("messageReceivedListener");
}
@Bean(name = "messageDeletedExecutor")
public TaskExecutor messageDeletedExecutor() {
return setupExecutorFor("messageReceivedListener");
return executorService.setupExecutorFor("messageReceivedListener");
}
@Bean(name = "messageEmbeddedExecutor")
public TaskExecutor messageEmbeddedExecutor() {
return setupExecutorFor("messageEmbeddedListener");
return executorService.setupExecutorFor("messageEmbeddedListener");
}
@Bean(name = "messageUpdatedExecutor")
public TaskExecutor messageUpdatedExecutor() {
return setupExecutorFor("messageUpdatedListener");
return executorService.setupExecutorFor("messageUpdatedListener");
}
@Bean(name = "privateMessageReceivedExecutor")
public TaskExecutor privateMessageReceivedExecutor() {
return setupExecutorFor("privateMessageReceivedListener");
return executorService.setupExecutorFor("privateMessageReceivedListener");
}
@Bean(name = "emoteCreatedExecutor")
public TaskExecutor emoteCreatedExecutor() {
return setupExecutorFor("emoteCreatedListener");
return executorService.setupExecutorFor("emoteCreatedListener");
}
@Bean(name = "emoteDeletedExecutor")
public TaskExecutor emoteDeletedExecutor() {
return setupExecutorFor("emoteDeletedListener");
return executorService.setupExecutorFor("emoteDeletedListener");
}
@Bean(name = "emoteUpdatedExecutor")
public TaskExecutor emoteUpdatedExecutor() {
return setupExecutorFor("emoteUpdatedListener");
return executorService.setupExecutorFor("emoteUpdatedListener");
}
@Bean(name = "reactionAddedExecutor")
public TaskExecutor reactionAddedExecutor() {
return setupExecutorFor("reactionAddedListener");
return executorService.setupExecutorFor("reactionAddedListener");
}
@Bean(name = "reactionRemovedExecutor")
public TaskExecutor reactionRemovedExecutor() {
return setupExecutorFor("reactionRemovedListener");
return executorService.setupExecutorFor("reactionRemovedListener");
}
@Bean(name = "reactionClearedExecutor")
public TaskExecutor reactionClearedExecutor() {
return setupExecutorFor("reactionClearedListener");
return executorService.setupExecutorFor("reactionClearedListener");
}
public ThreadPoolTaskExecutor setupExecutorFor(String listenerName) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
Integer maxPoolSize = getPropertyValueInteger(listenerName, LISTENER_MAX_POOL_SIZE, defaultMaxPoolSize.toString());
Integer corePoolSize = getPropertyValueInteger(listenerName, LISTENER_CORE_POOL_SIZE, defaultCorePoolSize.toString());
Integer keepAliveSeconds = getPropertyValueInteger(listenerName, LISTENER_KEEP_ALIVE_SECONDS, defaultKeepAliveSeconds.toString());
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setThreadNamePrefix(listenerName + "-task-executor-thread");
executor.initialize();
return executor;
}
public String getPropertyValue(String listenerName, String key, String defaultValue) {
return environment.getProperty(LISTENER_PREFIX + listenerName + "." + key, defaultValue);
}
public Integer getPropertyValueInteger(String listenerName, String key, String defaultValue) {
return Integer.parseInt(getPropertyValue(listenerName, key, defaultValue));
}
}

View File

@@ -1,47 +1,51 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
package dev.sheldan.abstracto.core.listener.async.entity;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.database.AChannelType;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.listener.AChannelCreatedListenerModel;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.events.channel.text.TextChannelCreateEvent;
import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
import javax.annotation.Nonnull;
import java.util.List;
@Service
@Component
@Slf4j
public class ChannelListener extends ListenerAdapter {
public class AsyncAChannelCreatedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncAChannelCreatedListener> channelListener;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private ListenerService listenerService;
@Autowired
private ChannelManagementService channelManagementService;
// TODO move this to a separate sync listener, which implements a a generic channel listener, in order to provide
// the channel listener for other implementations
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public void onTextChannelDelete(@Nonnull TextChannelDeleteEvent event) {
log.info("Handling channel delete event. Marking channel {} as deleted in server {}", event.getChannel().getIdLong(), event.getGuild().getIdLong());
channelManagementService.markAsDeleted(event.getChannel().getIdLong());
}
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public void onTextChannelCreate(@Nonnull TextChannelCreateEvent event) {
log.info("Handling channel created event. Creating channel {} in server {}", event.getChannel().getIdLong(), event.getGuild().getIdLong());
AServer serverObject = serverManagementService.loadOrCreate(event.getGuild().getIdLong());
log.info("Creating text channel with ID {}.", event.getChannel().getIdLong());
AServer serverObject = serverManagementService.loadOrCreate(event.getChannel().getGuild().getIdLong());
TextChannel createdChannel = event.getChannel();
AChannelType type = AChannelType.getAChannelType(createdChannel.getType());
channelManagementService.createChannel(createdChannel.getIdLong(), type, serverObject);
}
@TransactionalEventListener
public void executeServerCreationListener(AChannelCreatedListenerModel model) {
if(channelListener == null) return;
channelListener.forEach(serverCreatedListener -> listenerService.executeListener(serverCreatedListener, model));
}
}

View File

@@ -0,0 +1,40 @@
package dev.sheldan.abstracto.core.listener.async.entity;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.AChannelDeletedListenerModel;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@Slf4j
public class AsyncAChannelDeletedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncAChannelDeletedListener> channelDeletedListeners;
@Autowired
private ListenerService listenerService;
@Autowired
private ChannelManagementService channelManagementService;
@Override
public void onTextChannelDelete(@Nonnull TextChannelDeleteEvent event) {
channelManagementService.markAsDeleted(event.getChannel().getIdLong());
}
@TransactionalEventListener
public void executeServerCreationListener(AChannelDeletedListenerModel model) {
if(channelDeletedListeners == null) return;
channelDeletedListeners.forEach(serverCreatedListener -> listenerService.executeListener(serverCreatedListener, model));
}
}

View File

@@ -0,0 +1,46 @@
package dev.sheldan.abstracto.core.listener.async.entity;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.listener.ARoleCreatedListenerModel;
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.role.RoleCreateEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@Slf4j
public class AsyncARoleCreatedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncARoleCreatedListener> roleCreatedListeners;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private ListenerService listenerService;
@Autowired
private RoleManagementService roleManagementService;
@Override
public void onRoleCreate(@Nonnull RoleCreateEvent event) {
AServer server = serverManagementService.loadServer(event.getGuild());
roleManagementService.createRole(event.getRole().getIdLong(), server);
}
@TransactionalEventListener
public void executeServerCreationListener(ARoleCreatedListenerModel model) {
if(roleCreatedListeners == null) return;
roleCreatedListeners.forEach(asyncServerCreatedListener -> listenerService.executeListener(asyncServerCreatedListener, model));
}
}

View File

@@ -0,0 +1,40 @@
package dev.sheldan.abstracto.core.listener.async.entity;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.ARoleDeletedListenerModel;
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.role.RoleDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@Slf4j
public class AsyncARoleDeletedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncARoleDeletedListener> roleDeletedListeners;
@Autowired
private RoleManagementService roleManagementService;
@Autowired
private ListenerService listenerService;
@Override
public void onRoleDelete(@Nonnull RoleDeleteEvent event) {
roleManagementService.markDeleted(event.getRole().getIdLong());
}
@TransactionalEventListener
public void executeServerCreationListener(ARoleDeletedListenerModel model) {
if(roleDeletedListeners == null) return;
roleDeletedListeners.forEach(serverCreatedListener -> listenerService.executeListener(serverCreatedListener, model));
}
}

View File

@@ -0,0 +1,27 @@
package dev.sheldan.abstracto.core.listener.async.entity;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.listener.sync.entity.AsyncChannelGroupCreatedListener;
import dev.sheldan.abstracto.core.models.listener.ChannelGroupCreatedListenerModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
import java.util.List;
@Component
public class AsyncChannelGroupCreatedListenerManager {
@Autowired(required = false)
private List<AsyncChannelGroupCreatedListener> listener;
@Autowired
private ListenerService listenerService;
@TransactionalEventListener
public void executeListener(ChannelGroupCreatedListenerModel createdGroup){
listener.forEach(asyncChannelGroupCreatedListener ->
listenerService.executeListener(asyncChannelGroupCreatedListener, createdGroup)
);
}
}

View File

@@ -0,0 +1,27 @@
package dev.sheldan.abstracto.core.listener.async.entity;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.listener.sync.entity.AsyncChannelGroupDeletedListener;
import dev.sheldan.abstracto.core.models.listener.ChannelGroupDeletedListenerModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
import java.util.List;
@Component
public class AsyncChannelGroupDeletedListenerManager {
@Autowired(required = false)
private List<AsyncChannelGroupDeletedListener> listener;
@Autowired
private ListenerService listenerService;
@TransactionalEventListener
public void executeListener(ChannelGroupDeletedListenerModel model){
listener.forEach(channelGroupCreatedListener ->
listenerService.executeListener(channelGroupCreatedListener, model)
);
}
}

View File

@@ -0,0 +1,44 @@
package dev.sheldan.abstracto.core.listener.async.entity;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.ServerCreatedListenerModel;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.guild.GuildJoinEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@Slf4j
public class AsyncServerJoinListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncServerCreatedListener> serverCreatedListeners;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private ListenerService listenerService;
@Override
@Transactional
public void onGuildJoin(@Nonnull GuildJoinEvent event) {
if(serverCreatedListeners == null) return;
log.info("Joining guild {}, creating server.", event.getGuild().getId());
serverManagementService.loadOrCreate(event.getGuild().getIdLong());
}
@TransactionalEventListener
public void executeServerCreationListener(ServerCreatedListenerModel model) {
if(serverCreatedListeners == null) return;
serverCreatedListeners.forEach(asyncServerCreatedListener -> listenerService.executeListener(asyncServerCreatedListener, model));
}
}

View File

@@ -1,11 +1,7 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
import dev.sheldan.abstracto.core.service.CacheEntityService;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.EmoteCreatedModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.emote.EmoteAddedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -14,64 +10,33 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Service
@Slf4j
public class AsyncEmoteCreatedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncEmoteCreatedListener> createdListeners;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureModeService featureModeService;
@Autowired
private AsyncEmoteCreatedListenerBean self;
private List<AsyncEmoteCreatedListener> listenerList;
@Autowired
@Qualifier("emoteCreatedExecutor")
private TaskExecutor emoteCreatedExecutor;
private TaskExecutor emoteCreatedListenerExecutor;
@Autowired
private CacheEntityService cacheEntityService;
private ListenerService listenerService;
@Override
@Transactional
public void onEmoteAdded(@NotNull EmoteAddedEvent event) {
if(createdListeners == null) return;
CachedEmote cachedEmote = cacheEntityService.getCachedEmoteFromEmote(event.getEmote(), event.getGuild());
createdListeners.forEach(emoteUpdatedListener ->
CompletableFuture.runAsync(() ->
self.executeCreatedListener(emoteUpdatedListener, cachedEmote, event.getGuild().getIdLong())
, emoteCreatedExecutor)
.exceptionally(throwable -> {
log.error("Async join listener {} failed with exception.", emoteUpdatedListener, throwable);
return null;
})
);
if(listenerList == null) return;
EmoteCreatedModel model = getModel(event);
listenerList.forEach(joinListener -> listenerService.executeFeatureAwareListener(joinListener, model, emoteCreatedListenerExecutor));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeCreatedListener(AsyncEmoteCreatedListener listener, CachedEmote createDdEmote, Long serverId) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(listener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, serverId)) {
return;
}
if(!featureModeService.necessaryFeatureModesMet(listener, serverId)) {
return;
}
listener.emoteCreated(createDdEmote);
private EmoteCreatedModel getModel(EmoteAddedEvent event) {
return EmoteCreatedModel.builder().emote(event.getEmote()).build();
}
}

View File

@@ -1,11 +1,7 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
import dev.sheldan.abstracto.core.service.CacheEntityService;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.EmoteDeletedModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.emote.EmoteRemovedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -14,65 +10,33 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Service
@Slf4j
public class AsyncEmoteDeletedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncEmoteDeletedListener> deletedListeners;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureModeService featureModeService;
@Autowired
private AsyncEmoteDeletedListenerBean self;
private List<AsyncEmoteDeletedListener> listenerList;
@Autowired
@Qualifier("emoteDeletedExecutor")
private TaskExecutor emoteCreatedExecutor;
private TaskExecutor emoteDeletedListenerExecutor;
@Autowired
private CacheEntityService cacheEntityService;
private ListenerService listenerService;
@Override
@Transactional
public void onEmoteRemoved(@NotNull EmoteRemovedEvent event) {
if(deletedListeners == null) return;
CachedEmote cachedEmote = cacheEntityService.getCachedEmoteFromEmote(event.getEmote(), event.getGuild());
deletedListeners.forEach(emoteUpdatedListener ->
CompletableFuture.runAsync(() ->
self.executeDeletedListener(emoteUpdatedListener, cachedEmote, event.getGuild().getIdLong())
, emoteCreatedExecutor)
.exceptionally(throwable -> {
log.error("Async join listener {} failed with exception.", emoteUpdatedListener, throwable);
return null;
})
);
if(listenerList == null) return;
EmoteDeletedModel model = getModel(event);
listenerList.forEach(deletedListener -> listenerService.executeFeatureAwareListener(deletedListener, model, emoteDeletedListenerExecutor));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeDeletedListener(AsyncEmoteDeletedListener listener, CachedEmote deletedEmote, Long serverId) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(listener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, serverId)) {
return;
}
if(!featureModeService.necessaryFeatureModesMet(listener, serverId)) {
return;
}
listener.emoteDeleted(deletedEmote);
private EmoteDeletedModel getModel(EmoteRemovedEvent event) {
return EmoteDeletedModel.builder().emote(event.getEmote()).build();
}
}

View File

@@ -1,11 +1,7 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
import dev.sheldan.abstracto.core.service.CacheEntityService;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.EmoteNameUpdatedModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.emote.update.EmoteUpdateNameEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -14,65 +10,34 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Service
@Slf4j
public class AsyncEmoteUpdatedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncEmoteUpdatedListener> updatedListeners;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureModeService featureModeService;
@Autowired
private AsyncEmoteUpdatedListenerBean self;
private List<AsyncEmoteNameUpdatedListener> listenerList;
@Autowired
@Qualifier("emoteUpdatedExecutor")
private TaskExecutor emoteUpdatedExecutor;
private TaskExecutor emoteDeletedListenerExecutor;
@Autowired
private CacheEntityService cacheEntityService;
private ListenerService listenerService;
@Override
@Transactional
public void onEmoteUpdateName(@NotNull EmoteUpdateNameEvent event) {
if(updatedListeners == null) return;
CachedEmote cachedEmote = cacheEntityService.getCachedEmoteFromEmote(event.getEmote(), event.getGuild());
updatedListeners.forEach(emoteUpdatedListener ->
CompletableFuture.runAsync(() ->
self.executeUpdatedListener(emoteUpdatedListener, cachedEmote, event.getOldName(), event.getNewName(), event.getGuild().getIdLong())
, emoteUpdatedExecutor)
.exceptionally(throwable -> {
log.error("Async join listener {} failed with exception.", emoteUpdatedListener, throwable);
return null;
})
);
if(listenerList == null) return;
EmoteNameUpdatedModel model = getModel(event);
listenerList.forEach(deletedListener -> listenerService.executeFeatureAwareListener(deletedListener, model, emoteDeletedListenerExecutor));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeUpdatedListener(AsyncEmoteUpdatedListener listener, CachedEmote updatedEmote, String oldName, String newName, Long serverId) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(listener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, serverId)) {
return;
}
if(!featureModeService.necessaryFeatureModesMet(listener, serverId)) {
return;
}
listener.emoteUpdated(updatedEmote, oldName, newName);
private EmoteNameUpdatedModel getModel(EmoteUpdateNameEvent event) {
return EmoteNameUpdatedModel.builder().emote(event.getEmote()).newValue(event.getNewValue()).oldValue(event.getOldValue()).build();
}
}

View File

@@ -1,10 +1,8 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -12,13 +10,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
@@ -27,53 +22,31 @@ public class AsyncJoinListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncJoinListener> listenerList;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private AsyncJoinListenerBean self;
@Autowired
@Qualifier("joinListenerExecutor")
private TaskExecutor joinListenerExecutor;
@Autowired
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMemberJoin(@Nonnull GuildMemberJoinEvent event) {
if(listenerList == null) return;
listenerList.forEach(joinListener -> {
ServerUser serverUser = ServerUser
.builder()
.serverId(event.getGuild().getIdLong())
.userId(event.getUser().getIdLong())
.build();
CompletableFuture.runAsync(() ->
self.executeIndividualJoinListener(joinListener, serverUser)
, joinListenerExecutor).exceptionally(throwable -> {
log.error("Async join listener {} failed with exception.", joinListener, throwable);
return null;
});
});
MemberJoinModel model = getModel(event);
listenerList.forEach(joinListener -> listenerService.executeFeatureAwareListener(joinListener, model, joinListenerExecutor));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualJoinListener(AsyncJoinListener joinListener, ServerUser serverUser) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(joinListener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, serverUser.getServerId())) {
return;
}
log.trace("Executing async join listener {} for user {} in server {}.", joinListener, serverUser.getServerId(), serverUser.getUserId());
try {
joinListener.execute(serverUser);
} catch (Exception e) {
log.error("Listener {} failed with exception:", joinListener.getClass().getName(), e);
}
private MemberJoinModel getModel(GuildMemberJoinEvent event) {
ServerUser serverUser = ServerUser
.builder()
.serverId(event.getGuild().getIdLong())
.userId(event.getUser().getIdLong())
.build();
return MemberJoinModel
.builder()
.joiningUser(serverUser)
.member(event.getMember())
.build();
}
}

View File

@@ -1,10 +1,8 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.models.listener.MemberLeaveModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -12,65 +10,44 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
public class AsyncLeaveListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncLeaveListener> listenerList;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
@Qualifier("leaveListenerExecutor")
private TaskExecutor leaveListenerExecutor;
@Autowired
private AsyncLeaveListenerBean self;
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMemberRemove(@Nonnull GuildMemberRemoveEvent event) {
if(listenerList == null) return;
listenerList.forEach(leaveListener -> {
ServerUser serverUser = ServerUser
.builder()
.userId(event.getUser().getIdLong())
.serverId(event.getGuild().getIdLong())
.build();
CompletableFuture.runAsync(() ->
self.executeIndividualLeaveListener(serverUser, leaveListener)
, leaveListenerExecutor).exceptionally(throwable -> {
log.error("Async leave listener {} threw exception.", leaveListener, throwable);
return null;
});
});
MemberLeaveModel model = getModel(event);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, leaveListenerExecutor));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualLeaveListener(ServerUser user, AsyncLeaveListener leaveListener) {
log.trace("Executing leave listener {} for member {} in guild {}.", leaveListener.getClass().getName(), user.getUserId(), user.getServerId());
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(leaveListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, user.getServerId())) {
return;
}
try {
leaveListener.execute(user);
} catch (AbstractoRunTimeException e) {
log.error("Listener {} failed with exception:", leaveListener.getClass().getName(), e);
}
private MemberLeaveModel getModel(GuildMemberRemoveEvent event) {
ServerUser serverUser = ServerUser
.builder()
.serverId(event.getGuild().getIdLong())
.userId(event.getUser().getIdLong())
.build();
return MemberLeaveModel
.builder()
.leavingUser(serverUser)
.member(event.getMember())
.build();
}
}

View File

@@ -1,15 +1,9 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.models.listener.MessageDeletedModel;
import dev.sheldan.abstracto.core.service.MessageCache;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -17,54 +11,36 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
@Component
@Slf4j
public class AsyncMessageDeletedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncMessageDeletedListener> listener;
private List<AsyncMessageDeletedListener> listenerList;
@Autowired
private MessageCache messageCache;
@Autowired
private AsyncMessageDeletedListenerBean self;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private BotService botService;
@Autowired
@Qualifier("messageDeletedExecutor")
private TaskExecutor messageDeletedListenerExecutor;
@Autowired
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMessageDelete(@Nonnull GuildMessageDeleteEvent event) {
if(listener == null) return;
Consumer<CachedMessage> cachedMessageConsumer = cachedMessage -> self.executeListener(cachedMessage);
if(listenerList == null) return;
Consumer<CachedMessage> cachedMessageConsumer = cachedMessage -> {
MessageDeletedModel model = getModel(cachedMessage);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, messageDeletedListenerExecutor));
};
messageCache.getMessageFromCache(event.getGuild().getIdLong(), event.getChannel().getIdLong(), event.getMessageIdLong())
.thenAccept(cachedMessageConsumer)
.exceptionally(throwable -> {
@@ -73,30 +49,8 @@ public class AsyncMessageDeletedListenerBean extends ListenerAdapter {
});
}
@Transactional
public void executeListener(CachedMessage cachedMessage) {
listener.forEach(messageDeletedListener ->
CompletableFuture.runAsync(() ->
self.executeIndividualMessageDeletedListener(cachedMessage, messageDeletedListener)
, messageDeletedListenerExecutor).exceptionally(throwable -> {
log.error("Async message deleted {} failed with exception.", messageDeletedListener, throwable);
return null;
})
);
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualMessageDeletedListener(CachedMessage cachedMessage, AsyncMessageDeletedListener messageDeletedListener) {
log.trace("Executing message deleted listener {} for message {} in guild {}.", messageDeletedListener.getClass().getName(), cachedMessage.getMessageId(), cachedMessage.getMessageId());
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(messageDeletedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, cachedMessage.getServerId())) {
return;
}
try {
messageDeletedListener.execute(cachedMessage);
} catch (AbstractoRunTimeException e) {
log.error("Listener {} failed with exception:", messageDeletedListener.getClass().getName(), e);
}
private MessageDeletedModel getModel(CachedMessage cachedMessage) {
return MessageDeletedModel.builder().cachedMessage(cachedMessage).build();
}
}

View File

@@ -1,12 +1,7 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.command.service.ExceptionService;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.MessageCache;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.guild.GuildMessageEmbedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -15,35 +10,17 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
public class AsyncMessageEmbeddedListenerBean extends ListenerAdapter {
@Autowired
private MessageCache messageCache;
@Autowired(required = false)
private List<AsyncMessageEmbeddedListener> listenerList;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private BotService botService;
@Autowired
private ExceptionService exceptionService;
@Autowired
@Qualifier("messageEmbeddedExecutor")
private TaskExecutor messageEmbeddedListener;
@@ -51,22 +28,18 @@ public class AsyncMessageEmbeddedListenerBean extends ListenerAdapter {
@Autowired
private AsyncMessageEmbeddedListenerBean self;
@Autowired
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMessageEmbed(@NotNull GuildMessageEmbedEvent event) {
if(listenerList == null) return;
GuildMessageEmbedEventModel model = buildModel(event);
listenerList.forEach(messageReceivedListener ->
CompletableFuture.runAsync(() ->
self.executeIndividualGuildMessageReceivedListener(model, messageReceivedListener)
, messageEmbeddedListener).exceptionally(throwable -> {
log.error("Async message embedded listener {} failed with exception.", messageReceivedListener, throwable);
return null;
})
);
GuildMessageEmbedEventModel model = getModel(event);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, messageEmbeddedListener));
}
private GuildMessageEmbedEventModel buildModel(GuildMessageEmbedEvent event) {
private GuildMessageEmbedEventModel getModel(GuildMessageEmbedEvent event) {
return GuildMessageEmbedEventModel
.builder()
.channelId(event.getChannel().getIdLong())
@@ -76,17 +49,4 @@ public class AsyncMessageEmbeddedListenerBean extends ListenerAdapter {
.build();
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualGuildMessageReceivedListener(GuildMessageEmbedEventModel model, AsyncMessageEmbeddedListener messageReceivedListener) {
try {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(messageReceivedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, model.getServerId())) {
return;
}
messageReceivedListener.execute(model);
} catch (Exception e) {
log.error("Listener {} had exception when executing.", messageReceivedListener, e);
}
}
}

View File

@@ -1,8 +1,8 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.command.service.ExceptionService;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
@@ -14,13 +14,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
@@ -48,33 +45,21 @@ public class AsyncMessageReceivedListenerBean extends ListenerAdapter {
private TaskExecutor messageReceivedExecutor;
@Autowired
private AsyncMessageReceivedListenerBean self;
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) {
if(listenerList == null) return;
messageCache.putMessageInCache(event.getMessage()).thenAccept(message -> {
for (AsyncMessageReceivedListener messageReceivedListener : listenerList) {
CompletableFuture.runAsync(() -> self.executeIndividualGuildMessageReceivedListener(message, messageReceivedListener), messageReceivedExecutor)
.exceptionally(throwable -> {
log.error("Async message received listener {} failed.", messageReceivedListener, throwable);
return null;
});
}
});
messageCache.putMessageInCache(event.getMessage());
MessageReceivedModel model = getModel(event);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, messageReceivedExecutor));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualGuildMessageReceivedListener(CachedMessage cachedMessage, AsyncMessageReceivedListener messageReceivedListener) {
try {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(messageReceivedListener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, cachedMessage.getServerId())) {
return;
}
messageReceivedListener.execute(cachedMessage);
} catch (Exception e) {
log.error("Async listener {} had exception when executing.", messageReceivedListener, e);
}
private MessageReceivedModel getModel(GuildMessageReceivedEvent event) {
return MessageReceivedModel
.builder()
.message(event.getMessage())
.build();
}
}

View File

@@ -1,10 +1,8 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.models.listener.MessageTextUpdatedModel;
import dev.sheldan.abstracto.core.service.MessageCache;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
@@ -14,12 +12,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
@@ -34,52 +29,39 @@ public class AsyncMessageUpdatedListenerBean extends ListenerAdapter {
@Autowired
private AsyncMessageUpdatedListenerBean self;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
@Qualifier("messageUpdatedExecutor")
private TaskExecutor messageUpdatedExecutor;
@Autowired
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMessageUpdate(GuildMessageUpdateEvent event) {
if(listener == null) return;
Message message = event.getMessage();
messageCache.getMessageFromCache(message.getGuild().getIdLong(), message.getTextChannel().getIdLong(), event.getMessageIdLong())
.thenAcceptBoth(messageCache.putMessageInCache(message), (oldCache, newCache) -> self.executeListeners(newCache, oldCache))
.thenAcceptBoth(messageCache.putMessageInCache(message), (oldCache, newCache) -> self.executeListeners(event, oldCache))
.exceptionally(throwable -> {
log.error("Message retrieval {} from cache failed. ", event.getMessage().getId(), throwable);
return null;
});
}
@Transactional
public void executeListeners(CachedMessage updatedMessage, CachedMessage oldMessage) {
public void executeListeners(GuildMessageUpdateEvent event, CachedMessage oldMessage) {
MessageTextUpdatedModel model = getModel(event, oldMessage);
listener.forEach(messageTextUpdatedListener ->
CompletableFuture
.runAsync(() -> self.executeIndividualMessageUpdatedListener(updatedMessage, oldMessage, messageTextUpdatedListener), messageUpdatedExecutor)
.exceptionally(throwable -> {
log.error("Async message receiver listener {} failed.", messageTextUpdatedListener, throwable);
return null;
})
listenerService.executeFeatureAwareListener(messageTextUpdatedListener, model, messageUpdatedExecutor)
);
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualMessageUpdatedListener(CachedMessage updatedMessage, CachedMessage cachedMessage, AsyncMessageTextUpdatedListener messageTextUpdatedListener) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(messageTextUpdatedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, cachedMessage.getServerId())) {
return;
}
try {
messageTextUpdatedListener.execute(cachedMessage, updatedMessage);
} catch (AbstractoRunTimeException e) {
log.error(String.format("Failed to execute listener. %s", messageTextUpdatedListener.getClass().getName()), e);
}
private MessageTextUpdatedModel getModel(GuildMessageUpdateEvent event, CachedMessage oldMessage) {
return MessageTextUpdatedModel
.builder()
.after(event.getMessage())
.before(oldMessage)
.build();
}
}

View File

@@ -1,11 +1,11 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
import dev.sheldan.abstracto.core.models.listener.ReactionAddedModel;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -13,8 +13,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -32,24 +30,12 @@ public class AsyncReactionAddedListenerBean extends ListenerAdapter {
@Autowired
private MessageCache messageCache;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired(required = false)
private List<AsyncReactionAddedListener> addedListenerList;
private List<AsyncReactionAddedListener> listenerList;
@Autowired
private AsyncReactionAddedListenerBean self;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private BotService botService;
@Autowired
private EmoteService emoteService;
@@ -57,11 +43,14 @@ public class AsyncReactionAddedListenerBean extends ListenerAdapter {
@Qualifier("reactionAddedExecutor")
private TaskExecutor reactionAddedTaskExecutor;
@Autowired
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMessageReactionAdd(@Nonnull GuildMessageReactionAddEvent event) {
if(addedListenerList == null) return;
if(event.getUserIdLong() == botService.getInstance().getSelfUser().getIdLong()) {
if(listenerList == null) return;
if(event.getUserIdLong() == event.getJDA().getSelfUser().getIdLong()) {
return;
}
CompletableFuture<CachedMessage> asyncMessageFromCache = messageCache.getMessageFromCache(event.getGuild().getIdLong(), event.getChannel().getIdLong(), event.getMessageIdLong());
@@ -94,31 +83,21 @@ public class AsyncReactionAddedListenerBean extends ListenerAdapter {
}
@Transactional
public void callAddedListeners(@Nonnull GuildMessageReactionAddEvent event, CachedMessage cachedMessage, CachedReactions reaction) {
public void callAddedListeners(GuildMessageReactionAddEvent event, CachedMessage cachedMessage, CachedReactions reaction) {
ServerUser serverUser = ServerUser.builder().serverId(event.getGuild().getIdLong()).userId(event.getUserIdLong()).build();
addReactionIfNotThere(cachedMessage, reaction, serverUser);
ReactionAddedModel model = getModel(event, cachedMessage, serverUser);
messageCache.putMessageInCache(cachedMessage);
addedListenerList.forEach(reactedAddedListener ->
CompletableFuture.runAsync(() ->
self.executeIndividualReactionAddedListener(reaction, cachedMessage, serverUser, reactedAddedListener)
, reactionAddedTaskExecutor)
.exceptionally(throwable -> {
log.error("Async reaction added listener {} failed with exception.", reactedAddedListener, throwable);
return null;
})
);
listenerList.forEach(asyncReactionAddedListener -> listenerService.executeFeatureAwareListener(asyncReactionAddedListener, model, reactionAddedTaskExecutor));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualReactionAddedListener(@Nonnull CachedReactions reaction, CachedMessage cachedMessage, ServerUser serverUser, AsyncReactionAddedListener reactedAddedListener) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(reactedAddedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, serverUser.getServerId())) {
return;
}
try {
reactedAddedListener.executeReactionAdded(cachedMessage, reaction, serverUser);
} catch (Exception e) {
log.warn(String.format("Failed to execute reaction added listener %s.", reactedAddedListener.getClass().getName()), e);
}
private ReactionAddedModel getModel(GuildMessageReactionAddEvent event, CachedMessage cachedMessage, ServerUser userReacting) {
return ReactionAddedModel
.builder()
.reaction(event.getReaction())
.message(cachedMessage)
.memberReacting(event.getMember())
.userReacting(userReacting)
.build();
}
}

View File

@@ -1,10 +1,9 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.models.listener.ReactionClearedModel;
import dev.sheldan.abstracto.core.service.MessageCache;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionRemoveAllEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -12,8 +11,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -24,63 +21,18 @@ import java.util.concurrent.CompletableFuture;
@Slf4j
public class AsyncReactionClearedListenerBean extends ListenerAdapter {
@Autowired
private CacheEntityService cacheEntityService;
@Autowired
private MessageCache messageCache;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired(required = false)
private List<AsyncReactionClearedListener> clearedListenerList;
@Autowired
private AsyncReactionClearedListenerBean self;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private BotService botService;
@Autowired
private EmoteService emoteService;
@Autowired
@Qualifier("reactionClearedExecutor")
private TaskExecutor reactionClearedExecutor;
@Transactional
public void callClearListeners(CachedMessage cachedMessage) {
if(clearedListenerList == null) return;
clearedListenerList.forEach(reactionRemovedListener ->
CompletableFuture.runAsync(() ->
self.executeIndividualListener(cachedMessage, reactionRemovedListener)
, reactionClearedExecutor)
.exceptionally(throwable -> {
log.error("Async reaction cleared listener {} failed with exception.", reactionRemovedListener, throwable);
return null;
})
);
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualListener(CachedMessage cachedMessage, AsyncReactionClearedListener reactionRemovedListener) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(reactionRemovedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, cachedMessage.getServerId())) {
return;
}
try {
reactionRemovedListener.executeReactionCleared(cachedMessage);
} catch (AbstractoRunTimeException e) {
log.warn(String.format("Failed to execute reaction clear listener %s.", reactionRemovedListener.getClass().getName()), e);
}
}
@Autowired
private ListenerService listenerServiceBean;
@Override
@Transactional
@@ -89,11 +41,23 @@ public class AsyncReactionClearedListenerBean extends ListenerAdapter {
asyncMessageFromCache.thenAccept(cachedMessage -> {
cachedMessage.getReactions().clear();
messageCache.putMessageInCache(cachedMessage);
self.callClearListeners(cachedMessage);
}) .exceptionally(throwable -> {
ReactionClearedModel model = getModel(event, cachedMessage);
if(clearedListenerList == null) {
return;
}
clearedListenerList.forEach(asyncReactionClearedListener -> listenerServiceBean.executeFeatureAwareListener(asyncReactionClearedListener, model, reactionClearedExecutor));
}).exceptionally(throwable -> {
log.error("Message retrieval from cache failed for message {}", event.getMessageIdLong(), throwable);
return null;
});
}
private ReactionClearedModel getModel(GuildMessageReactionRemoveAllEvent event, CachedMessage message) {
return ReactionClearedModel
.builder()
.message(message)
.channel(event.getChannel())
.build();
}
}

View File

@@ -1,10 +1,10 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
import dev.sheldan.abstracto.core.models.listener.ReactionRemovedModel;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import lombok.extern.slf4j.Slf4j;
@@ -14,8 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -58,16 +56,8 @@ public class AsyncReactionRemovedListenerBean extends ListenerAdapter {
@Qualifier("reactionRemovedExecutor")
private TaskExecutor reactionRemovedExecutor;
private void removeReactionIfThere(CachedMessage message, CachedReactions reaction, ServerUser serverUser) {
Optional<CachedReactions> existingReaction = message.getReactions().stream().filter(reaction1 ->
reaction1.getEmote().equals(reaction.getEmote())
).findAny();
if(existingReaction.isPresent()) {
CachedReactions cachedReaction = existingReaction.get();
cachedReaction.getUsers().removeIf(user -> user.getUserId().equals(serverUser.getUserId()) && user.getServerId().equals(serverUser.getServerId()));
message.getReactions().removeIf(reaction1 -> reaction1.getUsers().isEmpty());
}
}
@Autowired
private ListenerService listenerServiceBean;
@Override
@Transactional
@@ -92,31 +82,32 @@ public class AsyncReactionRemovedListenerBean extends ListenerAdapter {
}
@Transactional
public void callRemoveListeners(@Nonnull GuildMessageReactionRemoveEvent event, CachedMessage cachedMessage, CachedReactions reaction) {
public void callRemoveListeners(GuildMessageReactionRemoveEvent event, CachedMessage cachedMessage, CachedReactions reaction) {
ServerUser serverUser = ServerUser.builder().serverId(cachedMessage.getServerId()).userId(event.getUserIdLong()).build();
removeReactionIfThere(cachedMessage, reaction, serverUser);
reactionRemovedListeners.forEach(reactionRemovedListener -> {
try {
CompletableFuture.runAsync(() ->
self.executeIndividualReactionRemovedListener(reaction, cachedMessage, serverUser, reactionRemovedListener)
, reactionRemovedExecutor)
.exceptionally(throwable -> {
log.error("Async reaction removed listener {} failed with exception.", reactionRemovedListener, throwable);
return null;
});
} catch (AbstractoRunTimeException e) {
log.warn(String.format("Failed to execute reaction removed listener %s.", reactionRemovedListener.getClass().getName()), e);
}
});
ReactionRemovedModel model = getModel(event, cachedMessage, serverUser);
reactionRemovedListeners.forEach(asyncReactionRemovedListener -> listenerServiceBean.executeFeatureAwareListener(asyncReactionRemovedListener, model, reactionRemovedExecutor));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualReactionRemovedListener(@Nonnull CachedReactions reaction, CachedMessage cachedMessage, ServerUser userRemoving, AsyncReactionRemovedListener reactionRemovedListener) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(reactionRemovedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, cachedMessage.getServerId())) {
return;
private ReactionRemovedModel getModel(GuildMessageReactionRemoveEvent event, CachedMessage cachedMessage, ServerUser userRemoving) {
return ReactionRemovedModel
.builder()
.memberRemoving(event.getMember())
.reaction(event.getReaction())
.userRemoving(userRemoving)
.message(cachedMessage)
.build();
}
private void removeReactionIfThere(CachedMessage message, CachedReactions reaction, ServerUser serverUser) {
Optional<CachedReactions> existingReaction = message.getReactions().stream().filter(reaction1 ->
reaction1.getEmote().equals(reaction.getEmote())
).findAny();
if(existingReaction.isPresent()) {
CachedReactions cachedReaction = existingReaction.get();
cachedReaction.getUsers().removeIf(user -> user.getUserId().equals(serverUser.getUserId()) && user.getServerId().equals(serverUser.getServerId()));
message.getReactions().removeIf(reaction1 -> reaction1.getUsers().isEmpty());
}
reactionRemovedListener.executeReactionRemoved(cachedMessage, reaction, userRemoving);
}
}

View File

@@ -0,0 +1,39 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.RoleCreatedModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.role.RoleCreateEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@Slf4j
public class AsyncRoleCreatedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncRoleCreatedListener> listenerList;
@Autowired
private ListenerService listenerService;
@Override
public void onRoleCreate(@Nonnull RoleCreateEvent event) {
if(listenerList == null) return;
RoleCreatedModel model = getModel(event);
listenerList.forEach(roleCreatedListener -> listenerService.executeFeatureAwareListener(roleCreatedListener, model));
}
private RoleCreatedModel getModel(RoleCreateEvent event) {
return RoleCreatedModel
.builder()
.role(event.getRole())
.build();
}
}

View File

@@ -0,0 +1,38 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.RoleDeletedModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.role.RoleDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@Slf4j
public class AsyncRoleDeletedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncRoleDeletedListener> listenerList;
@Autowired
private ListenerService listenerService;
@Override
public void onRoleDelete(@Nonnull RoleDeleteEvent event) {
if(listenerList == null) return;
RoleDeletedModel model = getModel(event);
listenerList.forEach(roleCreatedListener -> listenerService.executeFeatureAwareListener(roleCreatedListener, model));
}
private RoleDeletedModel getModel(RoleDeleteEvent event) {
return RoleDeletedModel
.builder()
.role(event.getRole())
.build();
}
}

View File

@@ -0,0 +1,38 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.TextChannelCreatedModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.channel.text.TextChannelCreateEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Nonnull;
import java.util.List;
@Service
@Slf4j
public class AsyncTextChannelCreatedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncTextChannelCreatedListener> listenerList;
@Autowired
private ListenerService listenerService;
@Override
public void onTextChannelCreate(@Nonnull TextChannelCreateEvent event) {
if(listenerList == null) return;
TextChannelCreatedModel model = getModel(event);
listenerList.forEach(textChannelCreatedListener -> listenerService.executeFeatureAwareListener(textChannelCreatedListener, model));
}
private TextChannelCreatedModel getModel(TextChannelCreateEvent event) {
return TextChannelCreatedModel
.builder()
.channel(event.getChannel())
.build();
}
}

View File

@@ -0,0 +1,38 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.TextChannelDeletedModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Nonnull;
import java.util.List;
@Service
@Slf4j
public class AsyncTextChannelDeletedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncTextChannelDeletedListener> listenerList;
@Autowired
private ListenerService listenerService;
@Override
public void onTextChannelDelete(@Nonnull TextChannelDeleteEvent event) {
if(listenerList == null) return;
TextChannelDeletedModel model = getModel(event);
listenerList.forEach(textChannelCreatedListener -> listenerService.executeFeatureAwareListener(textChannelCreatedListener, model));
}
private TextChannelDeletedModel getModel(TextChannelDeleteEvent event) {
return TextChannelDeletedModel
.builder()
.channel(event.getChannel())
.build();
}
}

View File

@@ -1,23 +0,0 @@
package dev.sheldan.abstracto.core.listener.sync.entity;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ChannelGroupCreatedListenerManager {
@Autowired(required = false)
private List<ChannelGroupCreatedListener> listener;
@Autowired
private ChannelGroupCreatedListenerManager self;
public void executeListener(AChannelGroup createdGroup){
listener.forEach(channelGroupCreatedListener ->
channelGroupCreatedListener.channelGroupCreated(createdGroup)
);
}
}

View File

@@ -1,20 +0,0 @@
package dev.sheldan.abstracto.core.listener.sync.entity;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ChannelGroupDeletedListenerManager {
@Autowired(required = false)
private List<ChannelGroupDeletedListener> listener;
public void executeListener(AChannelGroup createdGroup){
listener.forEach(channelGroupCreatedListener ->
channelGroupCreatedListener.channelGroupDeleted(createdGroup)
);
}
}

View File

@@ -1,20 +1,14 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.EmoteCreatedModel;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.events.emote.EmoteAddedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
@@ -28,37 +22,18 @@ public class EmoteCreatedListenerBean extends ListenerAdapter {
private List<EmoteCreatedListener> createdListeners;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureModeService featureModeService;
@Autowired
@Lazy
private EmoteCreatedListenerBean self;
private ListenerService listenerService;
@Override
@Transactional
public void onEmoteAdded(@NotNull EmoteAddedEvent event) {
if(createdListeners == null) return;
createdListeners.forEach(listener -> {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(listener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
return;
}
if(!featureModeService.necessaryFeatureModesMet(listener, event.getGuild().getIdLong())) {
return;
}
self.executeCreatedListener(listener, event.getEmote());
});
EmoteCreatedModel model = getModel(event);
createdListeners.forEach(listener -> listenerService.executeFeatureAwareListener(listener, model));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeCreatedListener(EmoteCreatedListener listener, Emote createDdEmote) {
listener.emoteCreated(createDdEmote);
private EmoteCreatedModel getModel(EmoteAddedEvent event) {
return EmoteCreatedModel.builder().emote(event.getEmote()).build();
}
@PostConstruct

View File

@@ -1,21 +1,18 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.EmoteDeletedModel;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.events.emote.EmoteRemovedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.List;
@@ -38,26 +35,17 @@ public class EmoteDeletedListenerBean extends ListenerAdapter {
@Autowired
@Lazy
private EmoteDeletedListenerBean self;
private ListenerService listenerService;
@Override
public void onEmoteRemoved(@NotNull EmoteRemovedEvent event) {
if(deletedListeners == null) return;
deletedListeners.forEach(listener -> {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(listener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
return;
}
if(!featureModeService.necessaryFeatureModesMet(listener, event.getGuild().getIdLong())) {
return;
}
self.executeDeletedListener(listener, event.getEmote());
});
EmoteDeletedModel model = getModel(event);
deletedListeners.forEach(listener -> listenerService.executeFeatureAwareListener(listener, model));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeDeletedListener(EmoteDeletedListener listener, Emote createDdEmote) {
listener.emoteDeleted(createDdEmote);
private EmoteDeletedModel getModel(EmoteRemovedEvent event) {
return EmoteDeletedModel.builder().emote(event.getEmote()).build();
}
@PostConstruct

View File

@@ -1,20 +1,18 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.EmoteNameUpdatedModel;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.events.emote.update.EmoteUpdateNameEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
@@ -38,27 +36,18 @@ public class EmoteUpdatedListenerBean extends ListenerAdapter {
@Autowired
@Lazy
private EmoteUpdatedListenerBean self;
private ListenerService listenerService;
@Override
@Transactional
public void onEmoteUpdateName(@NotNull EmoteUpdateNameEvent event) {
if(updatedListeners == null) return;
updatedListeners.forEach(emoteUpdatedListener -> {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(emoteUpdatedListener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
return;
}
if(!featureModeService.necessaryFeatureModesMet(emoteUpdatedListener, event.getGuild().getIdLong())) {
return;
}
self.executeUpdatedListener(emoteUpdatedListener, event.getEmote(), event.getOldName(), event.getNewName());
});
EmoteNameUpdatedModel model = getModel(event);
updatedListeners.forEach(emoteUpdatedListener -> listenerService.executeFeatureAwareListener(emoteUpdatedListener, model));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeUpdatedListener(EmoteUpdatedListener listener, Emote updatedEmote, String oldName, String newName) {
listener.emoteUpdated(updatedEmote, oldName, newName);
private EmoteNameUpdatedModel getModel(EmoteUpdateNameEvent event) {
return EmoteNameUpdatedModel.builder().emote(event.getEmote()).newValue(event.getNewValue()).oldValue(event.getOldValue()).build();
}
@PostConstruct

View File

@@ -1,7 +1,8 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
@@ -11,8 +12,6 @@ import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -36,30 +35,27 @@ public class JoinListenerBean extends ListenerAdapter {
private UserInServerManagementService userInServerManagementService;
@Autowired
private JoinListenerBean self;
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMemberJoin(@Nonnull GuildMemberJoinEvent event) {
if(listenerList == null) return;
listenerList.forEach(joinListener -> {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(joinListener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
return;
}
try {
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(event.getMember());
self.executeIndividualJoinListener(event, joinListener, aUserInAServer);
} catch (Exception e) {
log.error("Listener {} failed with exception:", joinListener.getClass().getName(), e);
}
});
MemberJoinModel model = getModel(event);
listenerList.forEach(joinListener -> listenerService.executeFeatureAwareListener(joinListener, model));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualJoinListener(@Nonnull GuildMemberJoinEvent event, JoinListener joinListener, AUserInAServer aUserInAServer) {
log.trace("Executing join listener {} for member {} in guild {}.", joinListener.getClass().getName(), event.getMember().getId(), event.getGuild().getId());
joinListener.execute(event.getMember(), event.getGuild(), aUserInAServer);
private MemberJoinModel getModel(GuildMemberJoinEvent event) {
ServerUser serverUser = ServerUser
.builder()
.serverId(event.getGuild().getIdLong())
.userId(event.getUser().getIdLong())
.build();
return MemberJoinModel
.builder()
.joiningUser(serverUser)
.member(event.getMember())
.build();
}
@PostConstruct

View File

@@ -1,7 +1,8 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.listener.MemberLeaveModel;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.utils.BeanUtils;
@@ -10,8 +11,6 @@ import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -32,29 +31,27 @@ public class LeaveListenerBean extends ListenerAdapter {
private FeatureFlagService featureFlagService;
@Autowired
private LeaveListenerBean self;
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMemberRemove(@Nonnull GuildMemberRemoveEvent event) {
if(listenerList == null) return;
listenerList.forEach(leaveListener -> {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(leaveListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
return;
}
try {
self.executeIndividualLeaveListener(event, leaveListener);
} catch (AbstractoRunTimeException e) {
log.error("Listener {} failed with exception:", leaveListener.getClass().getName(), e);
}
});
MemberLeaveModel model = getModel(event);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualLeaveListener(@Nonnull GuildMemberRemoveEvent event, LeaveListener leaveListener) {
log.trace("Executing leave listener {} for member {} in guild {}.", leaveListener.getClass().getName(), event.getMember().getId(), event.getGuild().getId());
leaveListener.execute(event.getMember(), event.getGuild());
private MemberLeaveModel getModel(GuildMemberRemoveEvent event) {
ServerUser serverUser = ServerUser
.builder()
.serverId(event.getGuild().getIdLong())
.userId(event.getUser().getIdLong())
.build();
return MemberLeaveModel
.builder()
.leavingUser(serverUser)
.member(event.getMember())
.build();
}
@PostConstruct

View File

@@ -1,26 +1,18 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
import dev.sheldan.abstracto.core.metric.service.MetricService;
import dev.sheldan.abstracto.core.metric.service.MetricTag;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.core.models.GuildChannelMember;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.models.listener.MessageDeletedModel;
import dev.sheldan.abstracto.core.service.MessageCache;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -36,41 +28,17 @@ import static dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListen
@Slf4j
public class MessageDeletedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<MessageDeletedListener> listener;
private List<MessageDeletedListener> listenerList;
@Autowired
private MessageCache messageCache;
@Autowired
private MessageDeletedListenerBean self;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private GuildService guildService;
@Autowired
private ChannelService channelService;
@Autowired
private MemberService memberService;
@Autowired
private MetricService metricService;
@Autowired
private ListenerService listenerService;
private static final CounterMetric MESSAGE_DELETED_COUNTER =
CounterMetric
.builder().name(MESSAGE_METRIC)
@@ -81,8 +49,11 @@ public class MessageDeletedListenerBean extends ListenerAdapter {
@Transactional
public void onGuildMessageDelete(@Nonnull GuildMessageDeleteEvent event) {
metricService.incrementCounter(MESSAGE_DELETED_COUNTER);
if(listener == null) return;
Consumer<CachedMessage> cachedMessageConsumer = cachedMessage -> self.executeListener(cachedMessage);
if(listenerList == null) return;
Consumer<CachedMessage> cachedMessageConsumer = cachedMessage -> {
MessageDeletedModel model = getModel(cachedMessage);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model));
};
messageCache.getMessageFromCache(event.getGuild().getIdLong(), event.getChannel().getIdLong(), event.getMessageIdLong())
.thenAccept(cachedMessageConsumer)
.exceptionally(throwable -> {
@@ -91,49 +62,13 @@ public class MessageDeletedListenerBean extends ListenerAdapter {
});
}
@Transactional
public void executeListener(CachedMessage cachedMessage) {
// TODO maybe lazy load, when there is actually a listener which has its feature enabled
AServerAChannelAUser authorUser = AServerAChannelAUser
.builder()
.guild(serverManagementService.loadOrCreate(cachedMessage.getServerId()))
.channel(channelManagementService.loadChannel(cachedMessage.getChannelId()))
.aUserInAServer(userInServerManagementService.loadOrCreateUser(cachedMessage.getServerId(), cachedMessage.getAuthor().getAuthorId()))
.build();
memberService.getMemberInServerAsync(cachedMessage.getServerId(), cachedMessage.getAuthor().getAuthorId()).thenAccept(member -> {
GuildChannelMember authorMember = GuildChannelMember
.builder()
.guild(guildService.getGuildById(cachedMessage.getServerId()))
.textChannel(channelService.getTextChannelFromServerOptional(cachedMessage.getServerId(), cachedMessage.getChannelId()).orElseThrow(() -> new ChannelNotInGuildException(cachedMessage.getChannelId())))
.member(memberService.getMemberInServer(cachedMessage.getServerId(), cachedMessage.getAuthor().getAuthorId()))
.build();
listener.forEach(messageDeletedListener -> {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(messageDeletedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, cachedMessage.getServerId())) {
return;
}
try {
self.executeIndividualMessageDeletedListener(cachedMessage, authorUser, authorMember, messageDeletedListener);
} catch (AbstractoRunTimeException e) {
log.error("Listener {} failed with exception:", messageDeletedListener.getClass().getName(), e);
}
});
}).exceptionally(throwable -> {
log.error("Message deleted listener failed.", throwable);
return null;
});
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualMessageDeletedListener(CachedMessage cachedMessage, AServerAChannelAUser authorUser, GuildChannelMember authorMember, MessageDeletedListener messageDeletedListener) {
log.trace("Executing message deleted listener {} for message {} in guild {}.", messageDeletedListener.getClass().getName(), cachedMessage.getMessageId(), cachedMessage.getMessageId());
messageDeletedListener.execute(cachedMessage, authorUser, authorMember);
private MessageDeletedModel getModel(CachedMessage cachedMessage) {
return MessageDeletedModel.builder().cachedMessage(cachedMessage).build();
}
@PostConstruct
public void postConstruct() {
metricService.registerCounter(MESSAGE_DELETED_COUNTER, "Messages deleted");
BeanUtils.sortPrioritizedListeners(listener);
BeanUtils.sortPrioritizedListeners(listenerList);
}
}

View File

@@ -1,7 +1,7 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.command.service.ExceptionService;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
@@ -44,24 +44,14 @@ public class MessageEmbeddedListenerBean extends ListenerAdapter {
private ExceptionService exceptionService;
@Autowired
private MessageEmbeddedListenerBean self;
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMessageEmbed(@NotNull GuildMessageEmbedEvent event) {
if(listenerList == null) return;
GuildMessageEmbedEventModel model = buildModel(event);
listenerList.forEach(messageReceivedListener -> {
try {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(messageReceivedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
return;
}
self.executeIndividualGuildMessageReceivedListener(model, messageReceivedListener);
} catch (Exception e) {
log.error("Listener {} had exception when executing.", messageReceivedListener, e);
}
});
listenerList.forEach(messageReceivedListener -> listenerService.executeFeatureAwareListener(messageReceivedListener, model));
}
private GuildMessageEmbedEventModel buildModel(GuildMessageEmbedEvent event) {

View File

@@ -1,11 +1,11 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.command.service.ExceptionService;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.execution.result.MessageReceivedListenerResult;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
import dev.sheldan.abstracto.core.metric.service.MetricService;
import dev.sheldan.abstracto.core.metric.service.MetricTag;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
@@ -16,8 +16,6 @@ import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -48,7 +46,7 @@ public class MessageReceivedListenerBean extends ListenerAdapter {
private ExceptionService exceptionService;
@Autowired
private MessageReceivedListenerBean self;
private ListenerService listenerService;
@Autowired
private MetricService metricService;
@@ -63,26 +61,16 @@ public class MessageReceivedListenerBean extends ListenerAdapter {
metricService.incrementCounter(MESSAGE_RECEIVED_COUNTER);
messageCache.putMessageInCache(event.getMessage());
if(listenerList == null) return;
for (MessageReceivedListener messageReceivedListener : listenerList) {
try {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(messageReceivedListener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
continue;
}
MessageReceivedListenerResult result = self.executeIndividualGuildMessageReceivedListener(event, messageReceivedListener);
if (messageReceivedListener.shouldConsume(event, result)) {
break;
}
} catch (Exception e) {
log.error("Listener {} had exception when executing.", messageReceivedListener, e);
exceptionService.reportExceptionToGuildMessageReceivedContext(e, event);
}
}
MessageReceivedModel model = getModel(event);
listenerList.forEach(messageReceivedListener -> listenerService.executeFeatureAwareListener(messageReceivedListener, model));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public MessageReceivedListenerResult executeIndividualGuildMessageReceivedListener(@Nonnull GuildMessageReceivedEvent event, MessageReceivedListener messageReceivedListener) {
return messageReceivedListener.execute(event.getMessage());
private MessageReceivedModel getModel(GuildMessageReceivedEvent event) {
return MessageReceivedModel
.builder()
.message(event.getMessage())
.build();
}
@PostConstruct

View File

@@ -1,13 +1,11 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
import dev.sheldan.abstracto.core.metric.service.MetricService;
import dev.sheldan.abstracto.core.metric.service.MetricTag;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.models.listener.MessageTextUpdatedModel;
import dev.sheldan.abstracto.core.service.MessageCache;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
@@ -16,8 +14,6 @@ import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -33,7 +29,7 @@ import static dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListen
public class MessageUpdatedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<MessageTextUpdatedListener> listener;
private List<MessageTextUpdatedListener> listenerList;
@Autowired
private MessageCache messageCache;
@@ -42,24 +38,25 @@ public class MessageUpdatedListenerBean extends ListenerAdapter {
private MessageUpdatedListenerBean self;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private FeatureConfigService featureConfigService;
private ListenerService listenerService;
@Autowired
private MetricService metricService;
private static final CounterMetric MESSAGE_UPDATED_COUNTER = CounterMetric.builder().name(MESSAGE_METRIC).tagList(Arrays.asList(MetricTag.getTag(ACTION, "updated"))).build();
private static final CounterMetric MESSAGE_UPDATED_COUNTER = CounterMetric
.builder()
.name(MESSAGE_METRIC)
.tagList(Arrays.asList(MetricTag.getTag(ACTION, "updated")))
.build();
@Override
@Transactional
public void onGuildMessageUpdate(@Nonnull GuildMessageUpdateEvent event) {
metricService.incrementCounter(MESSAGE_UPDATED_COUNTER);
if(listener == null) return;
if(listenerList == null) return;
Message message = event.getMessage();
messageCache.getMessageFromCache(message.getGuild().getIdLong(), message.getTextChannel().getIdLong(), event.getMessageIdLong()).thenAccept(cachedMessage -> {
self.executeListener(message, cachedMessage);
self.executeListener(cachedMessage, event);
messageCache.putMessageInCache(message);
}).exceptionally(throwable -> {
log.error("Message retrieval {} from cache failed. ", event.getMessage().getId(), throwable);
@@ -69,28 +66,22 @@ public class MessageUpdatedListenerBean extends ListenerAdapter {
}
@Transactional
public void executeListener(Message message, CachedMessage cachedMessage) {
listener.forEach(messageTextUpdatedListener -> {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(messageTextUpdatedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, message.getGuild().getIdLong())) {
return;
}
try {
self.executeIndividualMessageUpdatedListener(message, cachedMessage, messageTextUpdatedListener);
} catch (AbstractoRunTimeException e) {
log.error(String.format("Failed to execute listener. %s", messageTextUpdatedListener.getClass().getName()), e);
}
});
public void executeListener(CachedMessage cachedMessage, GuildMessageUpdateEvent event) {
MessageTextUpdatedModel model = getModel(event, cachedMessage);
listenerList.forEach(messageTextUpdatedListener -> listenerService.executeFeatureAwareListener(messageTextUpdatedListener, model));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualMessageUpdatedListener(Message message, CachedMessage cachedMessage, MessageTextUpdatedListener messageTextUpdatedListener) {
messageTextUpdatedListener.execute(cachedMessage, message);
private MessageTextUpdatedModel getModel(GuildMessageUpdateEvent event, CachedMessage oldMessage) {
return MessageTextUpdatedModel
.builder()
.after(event.getMessage())
.before(oldMessage)
.build();
}
@PostConstruct
public void postConstruct() {
metricService.registerCounter(MESSAGE_UPDATED_COUNTER, "Messages updated");
BeanUtils.sortPrioritizedListeners(listener);
BeanUtils.sortPrioritizedListeners(listenerList);
}
}

View File

@@ -1,9 +1,10 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
import dev.sheldan.abstracto.core.models.listener.ReactionAddedModel;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.BeanUtils;
@@ -12,8 +13,6 @@ import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEve
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -51,7 +50,7 @@ public class ReactionAddedListenerBean extends ListenerAdapter {
private BotService botService;
@Autowired
private EmoteService emoteService;
private ListenerService listenerService;
@Override
@Transactional
@@ -94,22 +93,18 @@ public class ReactionAddedListenerBean extends ListenerAdapter {
public void callAddedListeners(@Nonnull GuildMessageReactionAddEvent event, CachedMessage cachedMessage, CachedReactions reaction) {
ServerUser serverUser = ServerUser.builder().serverId(cachedMessage.getServerId()).userId(event.getUserIdLong()).build();
addReactionIfNotThere(cachedMessage, reaction, serverUser);
addedListenerList.forEach(reactedAddedListener -> {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(reactedAddedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
return;
}
try {
self.executeIndividualReactionAddedListener(event, cachedMessage, serverUser, reactedAddedListener);
} catch (Exception e) {
log.warn(String.format("Failed to execute reaction added listener %s.", reactedAddedListener.getClass().getName()), e);
}
});
ReactionAddedModel model = getModel(event, cachedMessage, serverUser);
addedListenerList.forEach(reactedAddedListener -> listenerService.executeFeatureAwareListener(reactedAddedListener, model));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualReactionAddedListener(@Nonnull GuildMessageReactionAddEvent event, CachedMessage cachedMessage, ServerUser serverUser, ReactionAddedListener reactedAddedListener) {
reactedAddedListener.executeReactionAdded(cachedMessage, event, serverUser);
private ReactionAddedModel getModel(GuildMessageReactionAddEvent event, CachedMessage cachedMessage, ServerUser userReacting) {
return ReactionAddedModel
.builder()
.reaction(event.getReaction())
.message(cachedMessage)
.memberReacting(event.getMember())
.userReacting(userReacting)
.build();
}
@PostConstruct

View File

@@ -1,19 +1,16 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.listener.ReactionClearedModel;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionRemoveAllEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -50,26 +47,22 @@ public class ReactionClearedListenerBean extends ListenerAdapter {
private BotService botService;
@Autowired
private EmoteService emoteService;
private ListenerService listenerService;
public void callClearListeners(@Nonnull GuildMessageReactionRemoveAllEvent event, CachedMessage cachedMessage) {
if(clearedListenerList == null) return;
ReactionClearedModel model = getModel(event, cachedMessage);
clearedListenerList.forEach(reactionRemovedListener ->
self.executeIndividualListener(event, cachedMessage, reactionRemovedListener)
listenerService.executeFeatureAwareListener(reactionRemovedListener, model)
);
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualListener(@NotNull GuildMessageReactionRemoveAllEvent event, CachedMessage cachedMessage, ReactionClearedListener reactionRemovedListener) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(reactionRemovedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
return;
}
try {
reactionRemovedListener.executeReactionCleared(cachedMessage);
} catch (AbstractoRunTimeException e) {
log.warn(String.format("Failed to execute reaction clear listener %s.", reactionRemovedListener.getClass().getName()), e);
}
private ReactionClearedModel getModel(GuildMessageReactionRemoveAllEvent event, CachedMessage message) {
return ReactionClearedModel
.builder()
.message(message)
.channel(event.getChannel())
.build();
}
@Override

View File

@@ -1,10 +1,10 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
import dev.sheldan.abstracto.core.models.listener.ReactionRemovedModel;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.BeanUtils;
@@ -13,8 +13,6 @@ import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionRemove
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@@ -52,7 +50,7 @@ public class ReactionRemovedListenerBean extends ListenerAdapter {
private BotService botService;
@Autowired
private EmoteService emoteService;
private ListenerService listenerService;
private void removeReactionIfThere(CachedMessage message, CachedReactions reaction, ServerUser userReacting) {
Optional<CachedReactions> existingReaction = message.getReactions().stream().filter(reaction1 ->
@@ -91,24 +89,21 @@ public class ReactionRemovedListenerBean extends ListenerAdapter {
public void callRemoveListeners(@Nonnull GuildMessageReactionRemoveEvent event, CachedMessage cachedMessage, CachedReactions reaction) {
ServerUser serverUser = ServerUser.builder().serverId(event.getGuild().getIdLong()).userId(event.getUserIdLong()).build();
removeReactionIfThere(cachedMessage, reaction, serverUser);
reactionRemovedListeners.forEach(reactionRemovedListener -> {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(reactionRemovedListener.getFeature());
if(!featureFlagService.isFeatureEnabled(feature, event.getGuild().getIdLong())) {
return;
}
try {
self.executeIndividualReactionRemovedListener(event, cachedMessage, serverUser, reactionRemovedListener);
} catch (AbstractoRunTimeException e) {
log.warn(String.format("Failed to execute reaction removed listener %s.", reactionRemovedListener.getClass().getName()), e);
}
});
ReactionRemovedModel model = getModel(event, cachedMessage, serverUser);
reactionRemovedListeners.forEach(reactionRemovedListener -> listenerService.executeFeatureAwareListener(reactionRemovedListener, model));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executeIndividualReactionRemovedListener(@Nonnull GuildMessageReactionRemoveEvent event, CachedMessage cachedMessage, ServerUser serverUser, ReactionRemovedListener reactionRemovedListener) {
reactionRemovedListener.executeReactionRemoved(cachedMessage, event, serverUser);
private ReactionRemovedModel getModel(GuildMessageReactionRemoveEvent event, CachedMessage cachedMessage, ServerUser userRemoving) {
return ReactionRemovedModel
.builder()
.memberRemoving(event.getMember())
.reaction(event.getReaction())
.userRemoving(userRemoving)
.message(cachedMessage)
.build();
}
@PostConstruct
public void postConstruct() {
BeanUtils.sortPrioritizedListeners(reactionRemovedListeners);

View File

@@ -0,0 +1,45 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.RoleCreatedModel;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.role.RoleCreateEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import java.util.List;
@Component
@Slf4j
public class RoleCreatedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<RoleCreatedListener> listenerList;
@Autowired
private ListenerService listenerService;
@Override
public void onRoleCreate(@Nonnull RoleCreateEvent event) {
if(listenerList == null) return;
RoleCreatedModel model = getModel(event);
listenerList.forEach(roleCreatedListener -> listenerService.executeFeatureAwareListener(roleCreatedListener, model));
}
private RoleCreatedModel getModel(RoleCreateEvent event) {
return RoleCreatedModel
.builder()
.role(event.getRole())
.build();
}
@PostConstruct
public void postConstruct() {
BeanUtils.sortPrioritizedListeners(listenerList);
}
}

View File

@@ -0,0 +1,44 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.RoleDeletedModel;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.role.RoleDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import java.util.List;
@Component
@Slf4j
public class RoleDeletedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<RoleDeletedListener> listenerList;
@Autowired
private ListenerService listenerService;
@Override
public void onRoleDelete(@Nonnull RoleDeleteEvent event) {
if(listenerList == null) return;
RoleDeletedModel model = getModel(event);
listenerList.forEach(roleCreatedListener -> listenerService.executeFeatureAwareListener(roleCreatedListener, model));
}
private RoleDeletedModel getModel(RoleDeleteEvent event) {
return RoleDeletedModel
.builder()
.role(event.getRole())
.build();
}
@PostConstruct
public void postConstruct() {
BeanUtils.sortPrioritizedListeners(listenerList);
}
}

View File

@@ -1,46 +0,0 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.RoleService;
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.role.RoleCreateEvent;
import net.dv8tion.jda.api.events.role.RoleDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
@Component
@Slf4j
public class RoleListener extends ListenerAdapter {
@Autowired
private RoleManagementService service;
@Autowired
private RoleService roleService;
@Autowired
private ServerManagementService serverManagementService;
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public void onRoleCreate(@Nonnull RoleCreateEvent event) {
log.info("Creating role {} in server {}.", event.getRole().getId(), event.getGuild().getId());
AServer server = serverManagementService.loadOrCreate(event.getGuild().getIdLong());
service.createRole(event.getRole().getIdLong(), server);
}
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public void onRoleDelete(@Nonnull RoleDeleteEvent event) {
log.info("Marking role {} as deleted in server {}.", event.getRole().getId(), event.getGuild().getId());
AServer server = serverManagementService.loadOrCreate(event.getGuild().getIdLong());
roleService.markDeleted(event.getRole(), server);
}
}

View File

@@ -1,45 +0,0 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.listener.sync.entity.ServerConfigListener;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.guild.GuildJoinEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@Slf4j
public class ServerJoinListener extends ListenerAdapter {
@Autowired(required = false)
private List<ServerConfigListener> configListeners;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private ServerJoinListener self;
@Override
@Transactional
public void onGuildJoin(@Nonnull GuildJoinEvent event) {
if(configListeners == null) return;
log.info("Joining guild {}, executing server config listener.", event.getGuild().getId());
AServer server = serverManagementService.loadOrCreate(event.getGuild().getIdLong());
configListeners.forEach(serverConfigListener -> self.executingIndividualServerConfigListener(server, serverConfigListener));
}
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void executingIndividualServerConfigListener(AServer server, ServerConfigListener serverConfigListener) {
log.trace("Executing server config listener for server {}.", server.getId());
serverConfigListener.updateServerConfig(server);
}
}

View File

@@ -0,0 +1,44 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.TextChannelCreatedModel;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.channel.text.TextChannelCreateEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import java.util.List;
@Service
@Slf4j
public class TextChannelCreatedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<TextChannelCreatedListener> listenerList;
@Autowired
private ListenerService listenerService;
@Override
public void onTextChannelCreate(@Nonnull TextChannelCreateEvent event) {
if(listenerList == null) return;
TextChannelCreatedModel model = getModel(event);
listenerList.forEach(textChannelCreatedListener -> listenerService.executeFeatureAwareListener(textChannelCreatedListener, model));
}
private TextChannelCreatedModel getModel(TextChannelCreateEvent event) {
return TextChannelCreatedModel
.builder()
.channel(event.getChannel())
.build();
}
@PostConstruct
public void postConstruct() {
BeanUtils.sortPrioritizedListeners(listenerList);
}
}

View File

@@ -0,0 +1,44 @@
package dev.sheldan.abstracto.core.listener.sync.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.listener.TextChannelDeletedModel;
import dev.sheldan.abstracto.core.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import java.util.List;
@Service
@Slf4j
public class TextChannelDeletedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<TextChannelDeletedListener> listenerList;
@Autowired
private ListenerService listenerService;
@Override
public void onTextChannelDelete(@Nonnull TextChannelDeleteEvent event) {
if(listenerList == null) return;
TextChannelDeletedModel model = getModel(event);
listenerList.forEach(textChannelCreatedListener -> listenerService.executeFeatureAwareListener(textChannelCreatedListener, model));
}
private TextChannelDeletedModel getModel(TextChannelDeleteEvent event) {
return TextChannelDeletedModel
.builder()
.channel(event.getChannel())
.build();
}
@PostConstruct
public void postConstruct() {
BeanUtils.sortPrioritizedListeners(listenerList);
}
}

View File

@@ -0,0 +1,50 @@
package dev.sheldan.abstracto.core.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
@Component
public class ExecutorServiceBean implements ExecutorService {
@Autowired
private Environment environment;
@Value("${abstracto.listener.default.maxPoolSize}")
private Integer defaultMaxPoolSize;
@Value("${abstracto.listener.default.corePoolSize}")
private Integer defaultCorePoolSize;
@Value("${abstracto.listener.default.keepAliveSeconds}")
private Integer defaultKeepAliveSeconds;
private static final String LISTENER_PREFIX = "abstracto.listener.";
private static final String LISTENER_MAX_POOL_SIZE = "maxPoolSize";
private static final String LISTENER_CORE_POOL_SIZE = "corePoolSize";
private static final String LISTENER_KEEP_ALIVE_SECONDS = "keepAliveSeconds";
private String getPropertyValue(String listenerName, String key, String defaultValue) {
return environment.getProperty(LISTENER_PREFIX + listenerName + "." + key, defaultValue);
}
private Integer getPropertyValueInteger(String listenerName, String key, String defaultValue) {
return Integer.parseInt(getPropertyValue(listenerName, key, defaultValue));
}
@Override
public ThreadPoolTaskExecutor setupExecutorFor(String listenerName) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
Integer maxPoolSize = getPropertyValueInteger(listenerName, LISTENER_MAX_POOL_SIZE, defaultMaxPoolSize.toString());
Integer corePoolSize = getPropertyValueInteger(listenerName, LISTENER_CORE_POOL_SIZE, defaultCorePoolSize.toString());
Integer keepAliveSeconds = getPropertyValueInteger(listenerName, LISTENER_KEEP_ALIVE_SECONDS, defaultKeepAliveSeconds.toString());
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setThreadNamePrefix(listenerName + "-task-executor-thread");
executor.initialize();
return executor;
}
}

View File

@@ -0,0 +1,87 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.listener.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
public class ListenerServiceBean implements ListenerService {
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private FeatureModeService featureModeService;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public <T extends FeatureAwareListenerModel, R extends ListenerExecutionResult> void executeFeatureAwareListener(FeatureAwareListener<T, R> listener, T model) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(listener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, model.getServerId())) {
return;
}
if(!featureModeService.necessaryFeatureModesMet(listener, model.getServerId())) {
return;
}
try {
listener.execute(model);
} catch (Exception e) {
log.error("Feature aware listener {} failed with exception:", listener.getClass().getName(), e);
}
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public <T extends FeatureAwareListenerModel, R extends ListenerExecutionResult> void executeFeatureAwareListener(FeatureAwareListener<T, R> listener, T model, TaskExecutor executor) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(listener.getFeature());
if (!featureFlagService.isFeatureEnabled(feature, model.getServerId())) {
return;
}
if(!featureModeService.necessaryFeatureModesMet(listener, model.getServerId())) {
return;
}
try {
CompletableFuture.runAsync(() -> listener.execute(model), executor).exceptionally(throwable -> {
log.error("Feature aware async Listener {} failed with async exception:", listener.getClass().getName(), throwable);
return null;
});
} catch (Exception e) {
log.error("Feature aware listener {} failed with exception:", listener.getClass().getName(), e);
}
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public <T extends ListenerModel, R extends ListenerExecutionResult> void executeListener(AbstractoListener<T, R> listener, T model) {
try {
listener.execute(model);
} catch (Exception e) {
log.error("Listener {} failed with exception:", listener.getClass().getName(), e);
}
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public <T extends ListenerModel, R extends ListenerExecutionResult> void executeListener(AbstractoListener<T, R> listener, T model, TaskExecutor executor) {
try {
CompletableFuture.runAsync(() -> listener.execute(model), executor).exceptionally(throwable -> {
log.error("Async Listener {} failed with async exception:", listener.getClass().getName(), throwable);
return null;
});
} catch (Exception e) {
log.error("Async listener {} failed with exception:", listener.getClass().getName(), e);
}
}
}

View File

@@ -81,6 +81,16 @@ public class ReactionServiceBean implements ReactionService {
return messageService.loadMessageFromCachedMessage(cachedMessage).thenCompose(message -> removeReactionFromMessage(reaction, message));
}
@Override
public CompletableFuture<Void> removeReactionFromMessage(MessageReaction reaction, CachedMessage cachedMessage, User user) {
return messageService.loadMessageFromCachedMessage(cachedMessage).thenCompose(message -> removeReactionFromMessageWithFuture(reaction.getReactionEmote(), message, user));
}
@Override
public CompletableFuture<Void> removeReactionFromMessage(MessageReaction reaction, CachedMessage cachedMessage) {
return messageService.loadMessageFromCachedMessage(cachedMessage).thenCompose(message -> removeReactionFromMessageWithFuture(reaction.getReactionEmote(), message));
}
@Override
public CompletableFuture<Void> removeReactionFromMessage(CachedReaction reaction, Message message) {
return memberService.retrieveUserById(reaction.getUser().getUserId()).thenCompose(user -> {
@@ -190,6 +200,24 @@ public class ReactionServiceBean implements ReactionService {
}
}
@Override
public CompletableFuture<Void> removeReactionFromMessageWithFuture(MessageReaction.ReactionEmote emote, Message message) {
if(emote.isEmote()) {
return removeReaction(message, emote.getEmote());
} else {
return removeReaction(message, emote.getEmoji());
}
}
@Override
public CompletableFuture<Void> removeReactionFromMessageWithFuture(MessageReaction.ReactionEmote emote, Message message, User user) {
if(emote.isEmote()) {
return removeReaction(message, emote.getEmote(), user);
} else {
return removeReaction(message, emote.getEmoji(), user);
}
}
@Override
public CompletableFuture<Void> removeReaction(Message message, String key) {
metricService.incrementCounter(REACTION_REMOVED_METRIC);

View File

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.listener.sync.entity.ServerConfigListener;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelType;
import dev.sheldan.abstracto.core.models.database.ARole;
@@ -44,9 +43,6 @@ public class StartupServiceBean implements Startup {
@Autowired
private RoleManagementService roleManagementService;
@Autowired
private List<ServerConfigListener> configListeners;
@Override
public void startBot() throws LoginException {
@@ -73,24 +69,20 @@ public class StartupServiceBean implements Startup {
if(newGuild != null){
synchronizeRolesOf(newGuild, newAServer);
synchronizeChannelsOf(newGuild, newAServer);
configListeners.forEach(serverConfigListener ->
serverConfigListener.updateServerConfig(newAServer)
);
}
});
}
// TODO mark deleted roles ad deleted, use intersect for that
private void synchronizeRolesOf(Guild guild, AServer existingAServer){
List<Role> existingRoles = guild.getRoles();
List<ARole> knownARoles = existingAServer.getRoles();
Set<Long> knownRolesId = SnowflakeUtils.getOwnItemsIds(knownARoles);
Set<Long> availableRoles = SnowflakeUtils.getSnowflakeIds(existingRoles);
Set<Long> newRoles = SetUtils.difference(availableRoles, knownRolesId);
newRoles.forEach(aLong ->
roleManagementService.createRole(aLong, existingAServer)
);
List<Role> guildRoles = guild.getRoles();
List<ARole> existingRoles = existingAServer.getRoles();
Set<Long> existingRoleIds = SnowflakeUtils.getOwnItemsIds(existingRoles);
Set<Long> guildRoleIds = SnowflakeUtils.getSnowflakeIds(guildRoles);
Set<Long> newRoles = SetUtils.difference(guildRoleIds, existingRoleIds);
newRoles.forEach(aLong -> roleManagementService.createRole(aLong, existingAServer));
Set<Long> deletedRoles = SetUtils.difference(existingRoleIds, guildRoleIds);
deletedRoles.forEach(aLong -> roleManagementService.markDeleted(aLong));
}
private void synchronizeChannelsOf(Guild guild, AServer existingServer){

View File

@@ -44,8 +44,7 @@ public class AllowedMentionManagementServiceBean implements AllowedMentionManage
.role(base.getRole())
.user(base.getUser())
.server(server).build();
allowedMentionRepository.save(allowedMention);
return allowedMention;
return allowedMentionRepository.save(allowedMention);
}
@Override

View File

@@ -1,18 +1,18 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.command.exception.ChannelAlreadyInChannelGroupException;
import dev.sheldan.abstracto.core.command.exception.ChannelGroupExistsException;
import dev.sheldan.abstracto.core.command.exception.ChannelGroupNotFoundException;
import dev.sheldan.abstracto.core.command.exception.ChannelNotInChannelGroupException;
import dev.sheldan.abstracto.core.listener.sync.entity.ChannelGroupCreatedListenerManager;
import dev.sheldan.abstracto.core.listener.sync.entity.ChannelGroupDeletedListenerManager;
import dev.sheldan.abstracto.core.command.exception.*;
import dev.sheldan.abstracto.core.listener.async.entity.AsyncChannelGroupCreatedListenerManager;
import dev.sheldan.abstracto.core.listener.async.entity.AsyncChannelGroupDeletedListenerManager;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
import dev.sheldan.abstracto.core.models.listener.ChannelGroupCreatedListenerModel;
import dev.sheldan.abstracto.core.models.listener.ChannelGroupDeletedListenerModel;
import dev.sheldan.abstracto.core.repository.ChannelGroupRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import java.util.List;
@@ -31,10 +31,13 @@ public class ChannelGroupManagementServiceBean implements ChannelGroupManagement
private ServerManagementService serverManagementService;
@Autowired
private ChannelGroupDeletedListenerManager deletedListenerManager;
private AsyncChannelGroupDeletedListenerManager deletedListenerManager;
@Autowired
private ChannelGroupCreatedListenerManager createdListenerManager;
private AsyncChannelGroupCreatedListenerManager createdListenerManager;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Override
public AChannelGroup createChannelGroup(String name, AServer server, ChannelGroupType channelGroupType) {
@@ -49,11 +52,26 @@ public class ChannelGroupManagementServiceBean implements ChannelGroupManagement
.server(server)
.build();
log.info("Creating new channel group in server {}.", server.getId());
channelGroupRepository.save(channelGroup);
createdListenerManager.executeListener(channelGroup);
channelGroup = channelGroupRepository.save(channelGroup);
ChannelGroupCreatedListenerModel model = getCreatedModel(channelGroup);
applicationEventPublisher.publishEvent(model);
return channelGroup;
}
private ChannelGroupCreatedListenerModel getCreatedModel(AChannelGroup channelGroup) {
return ChannelGroupCreatedListenerModel
.builder()
.channelGroupId(channelGroup.getId())
.build();
}
private ChannelGroupDeletedListenerModel getDeletionModel(AChannelGroup channelGroup) {
return ChannelGroupDeletedListenerModel
.builder()
.channelGroupId(channelGroup.getId())
.build();
}
@Override
public boolean doesChannelGroupExist(String name, AServer server) {
return channelGroupRepository.existsByGroupNameAndServer(name, server);
@@ -67,8 +85,9 @@ public class ChannelGroupManagementServiceBean implements ChannelGroupManagement
throw new ChannelGroupNotFoundException(name, getAllAvailableAsString(server));
}
log.info("Deleting channel group {} in server {}.", existing.getId(), server.getId());
deletedListenerManager.executeListener(existing);
channelGroupRepository.delete(existing);
ChannelGroupDeletedListenerModel model = getDeletionModel(existing);
applicationEventPublisher.publishEvent(model);
}
@Override
@@ -83,6 +102,16 @@ public class ChannelGroupManagementServiceBean implements ChannelGroupManagement
return channelGroup;
}
@Override
public Optional<AChannelGroup> findChannelGroupByIdOptional(Long channelGroupId) {
return channelGroupRepository.findById(channelGroupId);
}
@Override
public AChannelGroup findChannelGroupById(Long channelGroupId) {
return findChannelGroupByIdOptional(channelGroupId).orElseThrow(ChannelGroupNotFoundByIdException::new);
}
@Override
public void removeChannelFromChannelGroup(AChannelGroup channelGroup, AChannel channel) {
Predicate<AChannel> channelInGroupPredicate = channel1 -> channel1.getId().equals(channel.getId());

View File

@@ -5,11 +5,14 @@ import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelType;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.listener.AChannelCreatedListenerModel;
import dev.sheldan.abstracto.core.models.listener.AChannelDeletedListenerModel;
import dev.sheldan.abstracto.core.repository.ChannelRepository;
import dev.sheldan.abstracto.core.service.LockService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import java.util.Optional;
@@ -24,6 +27,9 @@ public class ChannelManagementServiceBean implements ChannelManagementService {
@Autowired
private LockService lockService;
@Autowired
private ApplicationEventPublisher eventPublisher;
@Override
public Optional<AChannel> loadChannelOptional(Long id) {
return repository.findById(id);
@@ -51,17 +57,37 @@ public class ChannelManagementServiceBean implements ChannelManagementService {
.server(server)
.deleted(false)
.build();
return repository.save(build);
AChannel createdChannel = repository.save(build);
AChannelCreatedListenerModel model = getCreationModel(createdChannel);
eventPublisher.publishEvent(model);
return createdChannel;
} else {
Optional<AChannel> channelOptional = loadChannelOptional(id);
return channelOptional.orElse(null);
}
}
private AChannelCreatedListenerModel getCreationModel(AChannel channel) {
return AChannelCreatedListenerModel
.builder()
.channelId(channel.getId())
.build();
}
private AChannelDeletedListenerModel getDeletionModel(AChannel channel) {
return AChannelDeletedListenerModel
.builder()
.channelId(channel.getId())
.build();
}
@Override
public AChannel markAsDeleted(Long id) {
AChannel channel = loadChannel(id);
channel.setDeleted(true);
AChannelDeletedListenerModel model = getDeletionModel(channel);
eventPublisher.publishEvent(model);
log.info("Marking channel {} as deleted.", id);
return channel;
}

View File

@@ -60,8 +60,7 @@ public class ConfigManagementServiceBean implements ConfigManagementService {
.name(name)
.build();
log.trace("Creating config entry for type string in server {} and key {}", serverId, name);
configRepository.save(config);
return config;
return configRepository.save(config);
}
@Override
@@ -74,8 +73,7 @@ public class ConfigManagementServiceBean implements ConfigManagementService {
.name(name)
.build();
log.trace("Creating config entry for type double in server {} and key {}", serverId, name);
configRepository.save(config);
return config;
return configRepository.save(config);
}
@Override
@@ -87,9 +85,8 @@ public class ConfigManagementServiceBean implements ConfigManagementService {
.server(server)
.name(name)
.build();
configRepository.save(config);
log.trace("Creating config entry for type long in server {} and key {}", serverId, name);
return config;
return configRepository.save(config);
}
@Override

View File

@@ -69,8 +69,7 @@ public class EmoteManagementServiceBean implements EmoteManagementService {
.emoteKey(emoteKey)
.serverRef(server)
.build();
repository.save(emoteToCreate);
return emoteToCreate;
return repository.save(emoteToCreate);
}
@Override
@@ -93,8 +92,7 @@ public class EmoteManagementServiceBean implements EmoteManagementService {
.emoteKey(emoteKey)
.serverRef(server)
.build();
repository.save(emoteToCreate);
return emoteToCreate;
return repository.save(emoteToCreate);
}
@Override
@@ -123,7 +121,7 @@ public class EmoteManagementServiceBean implements EmoteManagementService {
emote.setEmoteId(emoteId);
emote.setAnimated(animated);
emote.setCustom(true);
repository.save(emote);
return repository.save(emote);
}
return emote;
}
@@ -147,7 +145,7 @@ public class EmoteManagementServiceBean implements EmoteManagementService {
emoteBeingSet.setEmoteKey(emoteKey);
emoteBeingSet.setCustom(false);
emoteBeingSet.setAnimated(false);
repository.save(emoteBeingSet);
return repository.save(emoteBeingSet);
}
return emoteBeingSet;
}

View File

@@ -40,8 +40,7 @@ public class FeatureFlagManagementServiceBean implements FeatureFlagManagementSe
.server(server)
.build();
log.info("Creating new feature flag for feature {} in server {} with value {}.", feature.getKey(), server.getId(), newValue);
repository.save(featureFlag);
return featureFlag;
return repository.save(featureFlag);
}

View File

@@ -20,9 +20,8 @@ public class FeatureManagementServiceBean implements FeatureManagementService {
.builder()
.key(key)
.build();
featureRepository.save(feature);
log.info("Creating new feature {}.", key);
return feature;
return featureRepository.save(feature);
}
@Override

View File

@@ -33,8 +33,7 @@ public class FeatureModeManagementServiceBean implements FeatureModeManagementSe
.featureMode(mode)
.build();
featureModeRepository.save(aFeatureMode);
return aFeatureMode;
return featureModeRepository.save(aFeatureMode);
}
@Override

View File

@@ -38,9 +38,8 @@ public class PostTargetManagementBean implements PostTargetManagement {
throw new PostTargetNotValidException(name, defaultPostTargetManagementService.getDefaultPostTargetKeys());
}
log.info("Creating post target {} pointing towards {} on server {}.", name, targetChannel.getId(), targetChannel.getServer().getId());
PostTarget build = PostTarget.builder().name(name).channelReference(targetChannel).serverReference(targetChannel.getServer()).build();
postTargetRepository.save(build);
return build;
PostTarget createdPostTarget = PostTarget.builder().name(name).channelReference(targetChannel).serverReference(targetChannel.getServer()).build();
return postTargetRepository.save(createdPostTarget);
}
@Override

View File

@@ -3,9 +3,12 @@ package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.exception.RoleNotFoundInDBException;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.listener.ARoleCreatedListenerModel;
import dev.sheldan.abstracto.core.models.listener.ARoleDeletedListenerModel;
import dev.sheldan.abstracto.core.repository.RoleRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import java.util.Optional;
@@ -17,6 +20,9 @@ public class RoleManagementServiceBean implements RoleManagementService {
@Autowired
private RoleRepository repository;
@Autowired
private ApplicationEventPublisher eventPublisher;
@Override
public ARole createRole(Long id, AServer server) {
ARole build = ARole
@@ -26,7 +32,10 @@ public class RoleManagementServiceBean implements RoleManagementService {
.deleted(false)
.build();
log.info("Creating role {} in server {}.", id, server.getId());
return repository.save(build);
ARole createdRole = repository.save(build);
ARoleCreatedListenerModel model = getCreationModel(createdRole);
eventPublisher.publishEvent(model);
return createdRole;
}
@Override
@@ -34,6 +43,20 @@ public class RoleManagementServiceBean implements RoleManagementService {
return repository.findById(id);
}
private ARoleCreatedListenerModel getCreationModel(ARole createdRole) {
return ARoleCreatedListenerModel
.builder()
.roleId(createdRole.getId())
.build();
}
private ARoleDeletedListenerModel getDeletionModel(ARole deletedRole) {
return ARoleDeletedListenerModel
.builder()
.roleId(deletedRole.getId())
.build();
}
@Override
public ARole findRole(Long id) {
return findRoleOptional(id).orElseThrow(() -> new RoleNotFoundInDBException(id));
@@ -42,6 +65,13 @@ public class RoleManagementServiceBean implements RoleManagementService {
@Override
public void markDeleted(ARole role) {
log.info("Marking role {} in server {} as deleted.", role.getId(), role.getServer().getId());
ARoleDeletedListenerModel model = getDeletionModel(role);
eventPublisher.publishEvent(model);
role.setDeleted(true);
}
@Override
public void markDeleted(Long roleId) {
markDeleted(findRole(roleId));
}
}

View File

@@ -2,10 +2,12 @@ package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
import dev.sheldan.abstracto.core.models.database.*;
import dev.sheldan.abstracto.core.models.listener.ServerCreatedListenerModel;
import dev.sheldan.abstracto.core.repository.ServerRepository;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -24,11 +26,24 @@ public class ServerManagementServiceBean implements ServerManagementService {
@Autowired
private UserManagementService userManagementService;
@Autowired
private ApplicationEventPublisher eventPublisher;
@Override
public AServer createServer(Long id) {
AServer newServer = AServer.builder().id(id).adminMode(false).build();
log.info("Creating server with id {}.", id);
return repository.save(newServer);
AServer server = repository.save(newServer);
ServerCreatedListenerModel model = getModel(server);
eventPublisher.publishEvent(model);
return server;
}
private ServerCreatedListenerModel getModel(AServer server) {
return ServerCreatedListenerModel
.builder()
.serverId(server.getId())
.build();
}
@Override

View File

@@ -108,8 +108,7 @@ public class UserInServerManagementServiceBean implements UserInServerManagement
public AUserInAServer tryToCreateAUserInAServer(Long guildId, Long userId) {
lockService.lockTable(TableLocks.USER_IN_SERVER);
AUserInAServer aUserInAServer = serverManagementService.addUserToServer(guildId, userId);
userInServerRepository.save(aUserInAServer);
return aUserInAServer;
return userInServerRepository.save(aUserInAServer);
}
@Override

View File

@@ -53,8 +53,7 @@ public class UserManagementServiceBean implements UserManagementService {
public AUser tryCreateUser(Long userId) {
lockService.lockTable(TableLocks.USER);
AUser aUser = AUser.builder().id(userId).build();
userRepository.save(aUser);
return aUser;
return userRepository.save(aUser);
}
@Override

View File

@@ -42,8 +42,7 @@ public class CustomTemplateManagementServiceBean implements CustomTemplateManage
.content(templateContent)
.key(templateKey)
.build();
customTemplateRepository.save(template);
return template;
return customTemplateRepository.save(template);
}
@Override

View File

@@ -48,9 +48,8 @@ public class TemplateManagementServiceBean implements TemplateManagementService
*/
@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;
Template template = Template.builder().key(key).content(content).lastModified(Instant.now()).build();
return repository.save(template);
}
}