mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-07-06 12:41:42 +00:00
[AB-184] adding various metrics to the system, organizing imports, changing some transactional behaviour
adding okhttp metrics, split bot service into multiple services (guild, message), unified some places that services are used in order to interact with the api, and not directly the objects (this is to make it easier for metric to be accurate)
This commit is contained in:
@@ -139,7 +139,11 @@
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>metrics-interface</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -6,20 +6,23 @@ import dev.sheldan.abstracto.core.command.config.ParameterValidator;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameters;
|
||||
import dev.sheldan.abstracto.core.command.exception.CommandParameterValidationException;
|
||||
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterException;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
|
||||
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandManager;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandService;
|
||||
import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.core.command.execution.*;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.RoleService;
|
||||
import dev.sheldan.abstracto.core.service.management.*;
|
||||
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
@@ -28,9 +31,14 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
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.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -80,6 +88,14 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
@Autowired
|
||||
private List<CommandParameterHandler> parameterHandlers;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
public static final String COMMAND_PROCESSED = "command.processed";
|
||||
public static final String STATUS_TAG = "status";
|
||||
public static final CounterMetric COMMANDS_PROCESSED_COUNTER = CounterMetric.builder().name(COMMAND_PROCESSED).tagList(Arrays.asList(MetricTag.getTag(STATUS_TAG, "processed"))).build();
|
||||
public static final CounterMetric COMMANDS_WRONG_PARAMETER_COUNTER = CounterMetric.builder().name(COMMAND_PROCESSED).tagList(Arrays.asList(MetricTag.getTag(STATUS_TAG, "parameter.wrong"))).build();
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onMessageReceived(MessageReceivedEvent event) {
|
||||
@@ -89,7 +105,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
if(!commandManager.isCommand(event.getMessage())) {
|
||||
return;
|
||||
}
|
||||
|
||||
metricService.incrementCounter(COMMANDS_PROCESSED_COUNTER);
|
||||
final Command foundCommand;
|
||||
try {
|
||||
String contentStripped = event.getMessage().getContentRaw();
|
||||
@@ -134,9 +150,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
log.info("Executing async command {} for server {} in channel {} based on message {} by user {}.",
|
||||
foundCommand.getConfiguration().getName(), commandContext.getGuild().getId(), commandContext.getChannel().getId(), commandContext.getMessage().getId(), commandContext.getAuthor().getId());
|
||||
|
||||
foundCommand.executeAsync(commandContext).thenAccept(result ->
|
||||
executePostCommandListener(foundCommand, commandContext, result)
|
||||
).exceptionally(throwable -> {
|
||||
self.executeAsyncCommand(foundCommand, commandContext).exceptionally(throwable -> {
|
||||
log.error("Asynchronous command {} failed.", foundCommand.getConfiguration().getName(), throwable);
|
||||
UserInitiatedServerContext rebuildUserContext = buildTemplateParameter(event);
|
||||
CommandContext rebuildContext = CommandContext.builder()
|
||||
@@ -163,6 +177,13 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(isolation = Isolation.SERIALIZABLE)
|
||||
public CompletableFuture<Void> executeAsyncCommand(Command foundCommand, CommandContext commandContext) {
|
||||
return foundCommand.executeAsync(commandContext).thenAccept(result ->
|
||||
executePostCommandListener(foundCommand, commandContext, result)
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void reportException(MessageReceivedEvent event, Command foundCommand, Throwable throwable, String s) {
|
||||
UserInitiatedServerContext userInitiatedContext = buildTemplateParameter(event);
|
||||
@@ -204,7 +225,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Transactional(isolation = Isolation.SERIALIZABLE)
|
||||
public CommandResult executeCommand(Command foundCommand, CommandContext commandContext) {
|
||||
log.info("Executing sync command {} for server {} in channel {} based on message {} by user {}.",
|
||||
foundCommand.getConfiguration().getName(), commandContext.getGuild().getId(), commandContext.getChannel().getId(), commandContext.getMessage().getId(), commandContext.getAuthor().getId());
|
||||
@@ -260,6 +281,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
throw abstractoRunTimeException;
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to parse parameter with exception.", e);
|
||||
metricService.incrementCounter(COMMANDS_WRONG_PARAMETER_COUNTER);
|
||||
throw new IncorrectParameterException(command, param.getName());
|
||||
}
|
||||
}
|
||||
@@ -312,4 +334,10 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
return CompletableFuture.completedFuture(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(COMMANDS_PROCESSED_COUNTER, "Commands processed");
|
||||
metricService.registerCounter(COMMANDS_WRONG_PARAMETER_COUNTER, "Commands with incorrect parameter");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public class AUserInAServerParameterHandlerImpl implements AUserInAServerParamet
|
||||
AUserInAServer actualInstance;
|
||||
if (throwable == null) {
|
||||
Member member = (Member) o;
|
||||
actualInstance = userInServerManagementService.loadUser(member);
|
||||
actualInstance = userInServerManagementService.loadOrCreateUser(member);
|
||||
} else {
|
||||
Long userId = Long.parseLong(input);
|
||||
actualInstance = userInServerManagementService.loadAUserInAServerOptional(context.getGuild().getIdLong(), userId).orElseThrow(() -> new UserInServerNotFoundException(0L));
|
||||
|
||||
@@ -8,7 +8,7 @@ import dev.sheldan.abstracto.core.command.models.condition.GenericConditionModel
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.core.models.GuildChannelMember;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.ReactionService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class ConditionPostExecution implements PostCommandExecution {
|
||||
public static final String GENERIC_COMMAND_EXCEPTION_MODEL_KEY = "generic_condition_notification";
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
private ReactionService reactionService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
@@ -26,7 +26,7 @@ public class ConditionPostExecution implements PostCommandExecution {
|
||||
@Override
|
||||
public void execute(CommandContext commandContext, CommandResult commandResult, Command command) {
|
||||
if(commandResult.getResult().equals(ResultState.CONDITION) && commandResult.getConditionResult() != null && !commandResult.getConditionResult().isResult() && commandResult.getConditionResult().getConditionDetail() != null) {
|
||||
messageService.addReactionToMessage(WARN_REACTION_EMOTE, commandContext.getGuild().getIdLong(), commandContext.getMessage());
|
||||
reactionService.addReactionToMessage(WARN_REACTION_EMOTE, commandContext.getGuild().getIdLong(), commandContext.getMessage());
|
||||
GenericConditionModel conditionModel = GenericConditionModel
|
||||
.builder()
|
||||
.conditionDetail(commandResult.getConditionResult().getConditionDetail())
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package dev.sheldan.abstracto.core.command.post;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ResultState;
|
||||
import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package dev.sheldan.abstracto.core.command.post;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ResultState;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.ReactionService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -15,18 +16,21 @@ public class ReactionPostExecution implements PostCommandExecution {
|
||||
public static final String WARN_REACTION_EMOTE = "warnReaction";
|
||||
public static final String SUCCESS_REACTION_EMOTE = "successReaction";
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
private ReactionService reactionService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext commandContext, CommandResult commandResult, Command command) {
|
||||
ResultState result = commandResult.getResult();
|
||||
if(result.equals(ResultState.ERROR) || result.equals(ResultState.REPORTED_ERROR)) {
|
||||
messageService.addReactionToMessage(WARN_REACTION_EMOTE, commandContext.getGuild().getIdLong(), commandContext.getMessage());
|
||||
reactionService.addReactionToMessage(WARN_REACTION_EMOTE, commandContext.getGuild().getIdLong(), commandContext.getMessage());
|
||||
if(commandResult.getMessage() != null && commandResult.getThrowable() == null){
|
||||
commandContext.getChannel().sendMessage(commandResult.getMessage()).queue();
|
||||
channelService.sendTextToChannel(commandResult.getMessage(), commandContext.getChannel());
|
||||
}
|
||||
} else if(result.equals(ResultState.SUCCESSFUL) && command.getConfiguration().isCausesReaction()) {
|
||||
messageService.addReactionToMessage(SUCCESS_REACTION_EMOTE, commandContext.getGuild().getIdLong(), commandContext.getMessage());
|
||||
reactionService.addReactionToMessage(SUCCESS_REACTION_EMOTE, commandContext.getGuild().getIdLong(), commandContext.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,20 +5,26 @@ import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ResultState;
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SelfDestructPostExecution implements PostCommandExecution {
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext commandContext, CommandResult commandResult, Command command) {
|
||||
if(commandResult.getResult().equals(ResultState.SELF_DESTRUCT)) {
|
||||
Message message = commandContext.getMessage();
|
||||
log.trace("Command {} is of type self destruct. Deleting message {} in channel {} in server {}.",
|
||||
command.getConfiguration().getName(), message.getId(), message.getChannel().getId(), message.getGuild().getId());
|
||||
message.delete().queue();
|
||||
messageService.deleteMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package dev.sheldan.abstracto.core.command.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
|
||||
import dev.sheldan.abstracto.core.command.exception.CommandNotFoundException;
|
||||
import dev.sheldan.abstracto.core.command.CommandReceivedHandler;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.exception.CommandNotFoundException;
|
||||
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
@@ -30,6 +32,9 @@ public class CommandManager implements CommandRegistry {
|
||||
@Autowired
|
||||
private DefaultConfigManagementService defaultConfigManagementService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
@Override
|
||||
public Command findCommandByParameters(String name, UnParsedCommandParameter unParsedCommandParameter) {
|
||||
Optional<Command> commandOptional = commands.stream().filter((Command o )-> {
|
||||
@@ -46,6 +51,7 @@ public class CommandManager implements CommandRegistry {
|
||||
boolean hasRemainderParameter = commandConfiguration.getParameters().stream().anyMatch(Parameter::isRemainder);
|
||||
if(unParsedCommandParameter.getParameters().size() < commandConfiguration.getNecessaryParameterCount()) {
|
||||
String nextParameterName = commandConfiguration.getParameters().get(commandConfiguration.getNecessaryParameterCount() - 1).getName();
|
||||
metricService.incrementCounter(CommandReceivedHandler.COMMANDS_WRONG_PARAMETER_COUNTER);
|
||||
throw new InsufficientParametersException(o, nextParameterName);
|
||||
}
|
||||
parameterFit = paramCountFits || hasRemainderParameter;
|
||||
|
||||
@@ -94,7 +94,7 @@ public class ExceptionServiceBean implements ExceptionService {
|
||||
}
|
||||
|
||||
private GenericExceptionModel buildCommandModel(Throwable throwable, CommandContext context) {
|
||||
FullUserInServer fullUser = FullUserInServer.builder().member(context.getAuthor()).aUserInAServer(userInServerManagementService.loadUser(context.getAuthor())).build();
|
||||
FullUserInServer fullUser = FullUserInServer.builder().member(context.getAuthor()).aUserInAServer(userInServerManagementService.loadUserOptional(context.getGuild().getIdLong(), context.getAuthor().getIdLong()).orElse(null)).build();
|
||||
return GenericExceptionModel
|
||||
.builder()
|
||||
.user(fullUser)
|
||||
@@ -103,7 +103,7 @@ public class ExceptionServiceBean implements ExceptionService {
|
||||
}
|
||||
|
||||
private GenericExceptionModel buildMemberContext(Throwable throwable, Member member) {
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadUser(member);
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(member);
|
||||
FullUserInServer fullUser = FullUserInServer
|
||||
.builder()
|
||||
.aUserInAServer(userInAServer)
|
||||
@@ -117,7 +117,7 @@ public class ExceptionServiceBean implements ExceptionService {
|
||||
}
|
||||
|
||||
private GenericExceptionModel buildPrivateMessageReceivedModel(Throwable throwable, User user) {
|
||||
AUser aUser = userManagementService.loadUser(user.getIdLong());
|
||||
AUser aUser = userManagementService.loadOrCreateUser(user.getIdLong());
|
||||
FullUser fullUser = FullUser
|
||||
.builder()
|
||||
.user(user)
|
||||
|
||||
@@ -6,7 +6,7 @@ import dev.sheldan.abstracto.core.command.config.SingleLevelPackedModule;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
||||
@@ -15,6 +15,7 @@ public class CommandInServerManagementServiceBean implements CommandInServerMana
|
||||
@Autowired
|
||||
private CommandInServerRepository repository;
|
||||
|
||||
|
||||
@Override
|
||||
public ACommandInAServer crateCommandInServer(ACommand command, AServer server) {
|
||||
ACommandInAServer commandInAServer = ACommandInAServer
|
||||
@@ -40,6 +41,6 @@ public class CommandInServerManagementServiceBean implements CommandInServerMana
|
||||
|
||||
@Override
|
||||
public ACommandInAServer getCommandForServer(ACommand command, Long serverId) {
|
||||
return null;
|
||||
return repository.findByServerReference_IdAndCommandReference(serverId, command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ package dev.sheldan.abstracto.core.commands.channels;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.service.ChannelGroupService;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.commands.channels;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
|
||||
@@ -3,11 +3,11 @@ package dev.sheldan.abstracto.core.commands.channels;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
|
||||
import dev.sheldan.abstracto.core.service.ChannelGroupService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupTypeManagementService;
|
||||
|
||||
@@ -3,11 +3,11 @@ package dev.sheldan.abstracto.core.commands.channels;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.service.ChannelGroupService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -4,11 +4,11 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.service.ChannelGroupService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -4,11 +4,11 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.service.ChannelGroupService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -3,20 +3,20 @@ package dev.sheldan.abstracto.core.commands.channels;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.ChannelGroupChannelModel;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.ChannelGroupModel;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.ListChannelGroupsModel;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -58,7 +58,7 @@ public class ListChannelGroups extends AbstractConditionableCommand {
|
||||
channelGroups.forEach(group -> {
|
||||
List<ChannelGroupChannelModel> convertedChannels = new ArrayList<>();
|
||||
group.getChannels().forEach(channel -> {
|
||||
Optional<TextChannel> textChannelInGuild = channelService.getTextChannelInGuild(channel.getServer().getId(), channel.getId());
|
||||
Optional<TextChannel> textChannelInGuild = channelService.getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
|
||||
if(textChannelInGuild.isPresent()) {
|
||||
ChannelGroupChannelModel convertedChannel = ChannelGroupChannelModel
|
||||
.builder()
|
||||
|
||||
@@ -4,9 +4,11 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.*;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.exception.PostTargetNotValidException;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||
|
||||
@@ -3,11 +3,11 @@ package dev.sheldan.abstracto.core.commands.channels;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelGroupService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.service.CacheServiceBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -5,11 +5,11 @@ import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.config.validator.MaxStringLengthValidator;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.models.database.ACommand;
|
||||
@@ -13,7 +14,6 @@ import dev.sheldan.abstracto.core.command.service.management.CommandManagementSe
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.models.database.ACommand;
|
||||
@@ -13,7 +14,6 @@ import dev.sheldan.abstracto.core.command.service.management.CommandManagementSe
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
|
||||
@@ -4,14 +4,14 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.EnableModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
|
||||
@@ -4,14 +4,14 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.FeatureValidationResult;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.EnableModel;
|
||||
|
||||
@@ -3,12 +3,12 @@ package dev.sheldan.abstracto.core.commands.config.features;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.converter.FeatureFlagConverter;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.models.database.ACommand;
|
||||
@@ -13,7 +14,6 @@ import dev.sheldan.abstracto.core.command.service.management.CommandManagementSe
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.models.database.ACommand;
|
||||
@@ -13,7 +14,6 @@ import dev.sheldan.abstracto.core.command.service.management.CommandManagementSe
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.models.database.ACommand;
|
||||
@@ -13,7 +14,6 @@ import dev.sheldan.abstracto.core.command.service.management.CommandManagementSe
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package dev.sheldan.abstracto.core.commands.help;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.*;
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.config.*;
|
||||
import dev.sheldan.abstracto.core.command.execution.*;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.command.models.database.ACommand;
|
||||
import dev.sheldan.abstracto.core.command.models.database.ACommandInAServer;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandRegistry;
|
||||
@@ -11,7 +14,9 @@ import dev.sheldan.abstracto.core.command.service.ModuleRegistry;
|
||||
import dev.sheldan.abstracto.core.command.service.management.CommandInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.command.service.management.CommandManagementService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.help.HelpCommandDetailsModel;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.help.HelpModuleDetailsModel;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.help.HelpModuleOverviewModel;
|
||||
@@ -24,7 +29,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -59,14 +66,49 @@ public class Help implements Command {
|
||||
@Autowired
|
||||
private CommandService commandService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
public static final String HELP_COMMAND_EXECUTED_METRIC = "help.executions";
|
||||
public static final String CATEGORY = "category";
|
||||
private static final CounterMetric HELP_COMMAND_NO_PARAMETER_METRIC =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.name(HELP_COMMAND_EXECUTED_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(CATEGORY, "no.parmeter")))
|
||||
.build();
|
||||
|
||||
private static final CounterMetric HELP_COMMAND_MODULE_METRIC =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.name(HELP_COMMAND_EXECUTED_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(CATEGORY, "module")))
|
||||
.build();
|
||||
|
||||
private static final CounterMetric HELP_COMMAND_COMMAND_METRIC =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.name(HELP_COMMAND_EXECUTED_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(CATEGORY, "command")))
|
||||
.build();
|
||||
|
||||
private static final CounterMetric HELP_COMMAND_WRONG_PARAM_METRIC =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.name(HELP_COMMAND_EXECUTED_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(CATEGORY, "wrong.argument")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
if(parameters.isEmpty()) {
|
||||
metricService.incrementCounter(HELP_COMMAND_NO_PARAMETER_METRIC);
|
||||
return displayHelpOverview(commandContext);
|
||||
} else {
|
||||
String parameter = (String) parameters.get(0);
|
||||
if(moduleService.moduleExists(parameter)){
|
||||
metricService.incrementCounter(HELP_COMMAND_MODULE_METRIC);
|
||||
ModuleInterface moduleInterface = moduleService.getModuleByName(parameter);
|
||||
log.trace("Displaying help for module {}.", moduleInterface.getInfo().getName());
|
||||
SingleLevelPackedModule module = moduleService.getPackedModule(moduleInterface);
|
||||
@@ -86,6 +128,7 @@ public class Help implements Command {
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
} else if(commandRegistry.commandExists(parameter)) {
|
||||
metricService.incrementCounter(HELP_COMMAND_COMMAND_METRIC);
|
||||
Command command = commandRegistry.getCommandByName(parameter);
|
||||
log.trace("Displaying help for command {}.", command.getConfiguration().getName());
|
||||
ACommand aCommand = commandManagementService.findCommandByName(parameter);
|
||||
@@ -102,6 +145,7 @@ public class Help implements Command {
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
} else {
|
||||
metricService.incrementCounter(HELP_COMMAND_WRONG_PARAM_METRIC);
|
||||
return displayHelpOverview(commandContext);
|
||||
}
|
||||
}
|
||||
@@ -142,4 +186,12 @@ public class Help implements Command {
|
||||
public FeatureEnum getFeature() {
|
||||
return CoreFeatures.CORE_FEATURE;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(HELP_COMMAND_NO_PARAMETER_METRIC, "Help command executions without argument.");
|
||||
metricService.registerCounter(HELP_COMMAND_MODULE_METRIC, "Help command executions with a module as argument.");
|
||||
metricService.registerCounter(HELP_COMMAND_COMMAND_METRIC, "Help command executions with a command as argument.");
|
||||
metricService.registerCounter(HELP_COMMAND_WRONG_PARAM_METRIC, "Help command executions with a parameter not matching.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.commands.help;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
|
||||
@@ -2,14 +2,15 @@ package dev.sheldan.abstracto.core.commands.utility;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleInterface;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.EchoModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -25,6 +26,9 @@ public class Echo extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -32,7 +36,8 @@ public class Echo extends AbstractConditionableCommand {
|
||||
sb.append(o.toString())
|
||||
);
|
||||
EchoModel model = EchoModel.builder().text(sb.toString()).build();
|
||||
commandContext.getChannel().sendMessage(templateService.renderTemplate(TEMPLATE_NAME, model)).queue();
|
||||
String textToSend = templateService.renderTemplate(TEMPLATE_NAME, model);
|
||||
channelService.sendTextToChannel(textToSend, commandContext.getChannel());
|
||||
return CommandResult.fromIgnored();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleInterface;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.PingModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
|
||||
@@ -4,13 +4,13 @@ import dev.sheldan.abstracto.core.command.UtilityModuleInterface;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.config.validator.MaxStringLengthValidator;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
|
||||
|
||||
@@ -4,6 +4,7 @@ import ch.qos.logback.core.net.ssl.SecureRandomFactoryBean;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
|
||||
import dev.sheldan.abstracto.core.metrics.OkHttpMetrics;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -27,6 +28,9 @@ public class CoreConfig {
|
||||
@Value("${abstracto.eventWaiter.threads}")
|
||||
private Integer threadCount;
|
||||
|
||||
@Autowired
|
||||
private OkHttpMetrics okHttpMetrics;
|
||||
|
||||
@Bean
|
||||
public Gson gson() {
|
||||
return new GsonBuilder()
|
||||
@@ -44,7 +48,7 @@ public class CoreConfig {
|
||||
|
||||
@Bean
|
||||
public OkHttpClient client() {
|
||||
return new OkHttpClient();
|
||||
return new OkHttpClient.Builder().addInterceptor(okHttpMetrics).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.abstracto.core.config;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class MetricConstants {
|
||||
public static final String DISCORD_API_INTERACTION_METRIC = "discord.api.interactions";
|
||||
public static final String INTERACTION_TYPE = "action";
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package dev.sheldan.abstracto.core.config;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Instant;
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.jagrosh.jdautilities.menu.ButtonMenu;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
@@ -42,9 +41,6 @@ public class InteractiveServiceBean implements InteractiveService {
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Override
|
||||
public void createMessageWithResponse(String messageText, AUserInAServer responder, AChannel channel, Long messageId, Consumer<MessageReceivedEvent> action, Runnable finalAction) {
|
||||
channelService.sendTextToAChannel(messageText, channel);
|
||||
@@ -90,14 +86,14 @@ public class InteractiveServiceBean implements InteractiveService {
|
||||
}
|
||||
})
|
||||
.build();
|
||||
Optional<TextChannel> textChannelInGuild = channelService.getTextChannelInGuild(serverId, channel.getId());
|
||||
Optional<TextChannel> textChannelInGuild = channelService.getTextChannelFromServerOptional(serverId, channel.getId());
|
||||
textChannelInGuild.ifPresent(menu::display);
|
||||
}
|
||||
|
||||
private void addEmoteToBuilder(String key, Consumer<Void> consumer, Long serverId, ButtonMenu.Builder builder, HashMap<String, Consumer<Void>> actions) {
|
||||
AEmote emoteOrFakeEmote = emoteService.getEmoteOrDefaultEmote(key, serverId);
|
||||
if(Boolean.TRUE.equals(emoteOrFakeEmote.getCustom())){
|
||||
Optional<Emote> emote = botService.getEmote(serverId, emoteOrFakeEmote);
|
||||
Optional<Emote> emote = emoteService.getEmote(serverId, emoteOrFakeEmote);
|
||||
emote.ifPresent(emote1 -> {
|
||||
builder.addChoice(emote1);
|
||||
actions.put(emote1.getId(), consumer);
|
||||
|
||||
@@ -5,7 +5,7 @@ import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.SetupPostTargetMessageModel;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
|
||||
@@ -47,7 +47,7 @@ public class PostTargetSetupStep extends AbstractConfigSetupStep {
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private PostTargetManagement postTargetManagement;
|
||||
@@ -58,7 +58,7 @@ public class PostTargetSetupStep extends AbstractConfigSetupStep {
|
||||
TextChannel currentTextChannel;
|
||||
if(postTargetManagement.postTargetExists(postTargetStepParameter.getPostTargetKey(), user.getGuildId())) {
|
||||
PostTarget postTarget = postTargetManagement.getPostTarget(postTargetStepParameter.getPostTargetKey(), user.getGuildId());
|
||||
currentTextChannel = botService.getTextChannelFromServerOptional(user.getGuildId(), postTarget.getChannelReference().getId()).orElse(null);
|
||||
currentTextChannel = channelService.getTextChannelFromServerOptional(user.getGuildId(), postTarget.getChannelReference().getId()).orElse(null);
|
||||
} else {
|
||||
currentTextChannel = null;
|
||||
}
|
||||
@@ -70,7 +70,7 @@ public class PostTargetSetupStep extends AbstractConfigSetupStep {
|
||||
String messageText = templateService.renderTemplate(FEATURE_SETUP_POST_TARGET_MESSAGE_TEMPLATE_KEY, model);
|
||||
AChannel channel = channelManagementService.loadChannel(user.getChannelId());
|
||||
CompletableFuture<SetupStepResult> future = new CompletableFuture<>();
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId());
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(user.getGuildId(), user.getUserId());
|
||||
Runnable finalAction = super.getTimeoutRunnable(user.getGuildId(), user.getChannelId());
|
||||
log.trace("Executing setup for post target {} in server {} for user {}.", postTargetStepParameter.getPostTargetKey(), user.getGuildId(), user.getUserId());
|
||||
Consumer<MessageReceivedEvent> configAction = (MessageReceivedEvent event) -> {
|
||||
|
||||
@@ -49,7 +49,7 @@ public class SetupSummaryStep extends AbstractConfigSetupStep {
|
||||
String messageToSend = templateService.renderTemplate(FEATURE_SETUP_CONFIRMATION_TEMPLATE_KEY, model);
|
||||
AChannel channel = channelManagementService.loadChannel(user.getChannelId());
|
||||
CompletableFuture<SetupStepResult> future = new CompletableFuture<>();
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId());
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(user.getGuildId(), user.getUserId());
|
||||
Runnable finalAction = super.getTimeoutRunnable(user.getGuildId(), user.getChannelId());
|
||||
log.info("Executing setup summary question step in server {} in channel {} from user {}.", user.getGuildId(), user.getChannelId(), user.getUserId());
|
||||
Consumer<Void> confirmation = (Void none) -> {
|
||||
|
||||
@@ -61,7 +61,7 @@ public class SystemConfigSetupStep extends AbstractConfigSetupStep {
|
||||
String messageText = templateService.renderTemplate(SETUP_SYSTEM_CONFIG_MESSAGE_TEMPLATE_KEY, model);
|
||||
AChannel channel = channelManagementService.loadChannel(user.getChannelId());
|
||||
CompletableFuture<SetupStepResult> future = new CompletableFuture<>();
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId());
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(user.getGuildId(), user.getUserId());
|
||||
log.trace("Executing setup for system config {} in server {} for user {}.", systemConfigStepParameter.getConfigKey(), user.getGuildId(), user.getUserId());
|
||||
|
||||
Runnable finalAction = super.getTimeoutRunnable(user.getGuildId(), user.getChannelId());
|
||||
|
||||
@@ -14,6 +14,7 @@ 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;
|
||||
|
||||
@@ -62,7 +63,7 @@ public class AsyncEmoteCreatedListenerBean extends ListenerAdapter {
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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)) {
|
||||
|
||||
@@ -14,6 +14,7 @@ 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;
|
||||
|
||||
@@ -47,6 +48,7 @@ public class AsyncEmoteDeletedListenerBean extends ListenerAdapter {
|
||||
private CacheEntityService cacheEntityService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onEmoteRemoved(@NotNull EmoteRemovedEvent event) {
|
||||
if(deletedListeners == null) return;
|
||||
CachedEmote cachedEmote = cacheEntityService.getCachedEmoteFromEmote(event.getEmote(), event.getGuild());
|
||||
@@ -62,7 +64,7 @@ public class AsyncEmoteDeletedListenerBean extends ListenerAdapter {
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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)) {
|
||||
|
||||
@@ -14,6 +14,7 @@ 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;
|
||||
|
||||
@@ -47,6 +48,7 @@ public class AsyncEmoteUpdatedListenerBean extends ListenerAdapter {
|
||||
private CacheEntityService cacheEntityService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onEmoteUpdateName(@NotNull EmoteUpdateNameEvent event) {
|
||||
if(updatedListeners == null) return;
|
||||
CachedEmote cachedEmote = cacheEntityService.getCachedEmoteFromEmote(event.getEmote(), event.getGuild());
|
||||
@@ -61,7 +63,7 @@ public class AsyncEmoteUpdatedListenerBean extends ListenerAdapter {
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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)) {
|
||||
|
||||
@@ -12,6 +12,7 @@ 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;
|
||||
|
||||
@@ -61,7 +62,7 @@ public class AsyncJoinListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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())) {
|
||||
|
||||
@@ -12,6 +12,7 @@ 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;
|
||||
|
||||
@@ -58,7 +59,7 @@ public class AsyncLeaveListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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());
|
||||
|
||||
@@ -17,6 +17,7 @@ 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;
|
||||
|
||||
@@ -84,7 +85,7 @@ public class AsyncMessageDeletedListenerBean extends ListenerAdapter {
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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());
|
||||
|
||||
@@ -52,6 +52,7 @@ public class AsyncMessageEmbeddedListenerBean extends ListenerAdapter {
|
||||
private AsyncMessageEmbeddedListenerBean self;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onGuildMessageEmbed(@NotNull GuildMessageEmbedEvent event) {
|
||||
if(listenerList == null) return;
|
||||
GuildMessageEmbedEventModel model = buildModel(event);
|
||||
|
||||
@@ -14,6 +14,7 @@ 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;
|
||||
|
||||
@@ -50,6 +51,7 @@ public class AsyncMessageReceivedListenerBean extends ListenerAdapter {
|
||||
private AsyncMessageReceivedListenerBean self;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) {
|
||||
if(listenerList == null) return;
|
||||
messageCache.putMessageInCache(event.getMessage()).thenAccept(message -> {
|
||||
@@ -63,7 +65,7 @@ public class AsyncMessageReceivedListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||
public void executeIndividualGuildMessageReceivedListener(CachedMessage cachedMessage, AsyncMessageReceivedListener messageReceivedListener) {
|
||||
try {
|
||||
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(messageReceivedListener.getFeature());
|
||||
|
||||
@@ -14,6 +14,7 @@ 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;
|
||||
|
||||
@@ -44,11 +45,12 @@ public class AsyncMessageUpdatedListenerBean extends ListenerAdapter {
|
||||
private TaskExecutor messageUpdatedExecutor;
|
||||
|
||||
@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.executeListener(newCache, oldCache))
|
||||
.thenAcceptBoth(messageCache.putMessageInCache(message), (oldCache, newCache) -> self.executeListeners(newCache, oldCache))
|
||||
.exceptionally(throwable -> {
|
||||
log.error("Message retrieval {} from cache failed. ", event.getMessage().getId(), throwable);
|
||||
return null;
|
||||
@@ -56,7 +58,7 @@ public class AsyncMessageUpdatedListenerBean extends ListenerAdapter {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void executeListener(CachedMessage updatedMessage, CachedMessage oldMessage) {
|
||||
public void executeListeners(CachedMessage updatedMessage, CachedMessage oldMessage) {
|
||||
listener.forEach(messageTextUpdatedListener ->
|
||||
CompletableFuture
|
||||
.runAsync(() -> self.executeIndividualMessageUpdatedListener(updatedMessage, oldMessage, messageTextUpdatedListener), messageUpdatedExecutor)
|
||||
@@ -67,7 +69,7 @@ public class AsyncMessageUpdatedListenerBean extends ListenerAdapter {
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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())) {
|
||||
|
||||
@@ -11,6 +11,7 @@ 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;
|
||||
|
||||
@@ -42,6 +43,7 @@ public class AsyncPrivateMessageReceivedListenerBean extends ListenerAdapter {
|
||||
private TaskExecutor privateMessageReceivedExecutor;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onPrivateMessageReceived(@Nonnull PrivateMessageReceivedEvent event) {
|
||||
if(privateMessageReceivedListeners == null) return;
|
||||
if(event.getAuthor().getId().equals(botService.getInstance().getSelfUser().getId())) {
|
||||
@@ -65,7 +67,7 @@ public class AsyncPrivateMessageReceivedListenerBean extends ListenerAdapter {
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||
public void executeIndividualPrivateMessageReceivedListener(CachedMessage cachedMessage, AsyncPrivateMessageReceivedListener messageReceivedListener) {
|
||||
log.trace("Executing private message listener {} for member {}.", messageReceivedListener.getClass().getName(), cachedMessage.getAuthor().getAuthorId());
|
||||
messageReceivedListener.execute(cachedMessage);
|
||||
|
||||
@@ -13,6 +13,7 @@ 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;
|
||||
|
||||
@@ -108,7 +109,7 @@ public class AsyncReactionAddedListenerBean extends ListenerAdapter {
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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())) {
|
||||
|
||||
@@ -12,6 +12,7 @@ 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;
|
||||
|
||||
@@ -59,7 +60,7 @@ public class AsyncReactionClearedListenerBean extends ListenerAdapter {
|
||||
if(clearedListenerList == null) return;
|
||||
clearedListenerList.forEach(reactionRemovedListener ->
|
||||
CompletableFuture.runAsync(() ->
|
||||
self.callConcreteListener(cachedMessage, reactionRemovedListener)
|
||||
self.executeIndividualListener(cachedMessage, reactionRemovedListener)
|
||||
, reactionClearedExecutor)
|
||||
.exceptionally(throwable -> {
|
||||
log.error("Async reaction cleared listener {} failed with exception.", reactionRemovedListener, throwable);
|
||||
@@ -68,8 +69,8 @@ public class AsyncReactionClearedListenerBean extends ListenerAdapter {
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void callConcreteListener(CachedMessage cachedMessage, AsyncReactionClearedListener reactionRemovedListener) {
|
||||
@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;
|
||||
|
||||
@@ -14,6 +14,7 @@ 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;
|
||||
|
||||
@@ -109,7 +110,7 @@ public class AsyncReactionRemovedListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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())) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package dev.sheldan.abstracto.core.listener.sync.jda;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelType;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
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;
|
||||
@@ -11,6 +11,7 @@ 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 javax.annotation.Nonnull;
|
||||
@@ -28,14 +29,14 @@ public class ChannelListener extends ListenerAdapter {
|
||||
// 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
|
||||
@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
|
||||
@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());
|
||||
|
||||
@@ -13,6 +13,7 @@ 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;
|
||||
|
||||
@@ -55,7 +56,7 @@ public class EmoteCreatedListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||
public void executeCreatedListener(EmoteCreatedListener listener, Emote createDdEmote) {
|
||||
listener.emoteCreated(createDdEmote);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ 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;
|
||||
|
||||
@@ -54,7 +55,7 @@ public class EmoteDeletedListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||
public void executeDeletedListener(EmoteDeletedListener listener, Emote createDdEmote) {
|
||||
listener.emoteDeleted(createDdEmote);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ 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;
|
||||
|
||||
@@ -40,6 +41,7 @@ public class EmoteUpdatedListenerBean extends ListenerAdapter {
|
||||
private EmoteUpdatedListenerBean self;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onEmoteUpdateName(@NotNull EmoteUpdateNameEvent event) {
|
||||
if(updatedListeners == null) return;
|
||||
updatedListeners.forEach(emoteUpdatedListener -> {
|
||||
@@ -54,7 +56,7 @@ public class EmoteUpdatedListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||
public void executeUpdatedListener(EmoteUpdatedListener listener, Emote updatedEmote, String oldName, String newName) {
|
||||
listener.emoteUpdated(updatedEmote, oldName, newName);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ 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;
|
||||
|
||||
@@ -47,7 +48,7 @@ public class JoinListenerBean extends ListenerAdapter {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(event.getMember());
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(event.getMember());
|
||||
self.executeIndividualJoinListener(event, joinListener, aUserInAServer);
|
||||
} catch (Exception e) {
|
||||
log.error("Listener {} failed with exception:", joinListener.getClass().getName(), e);
|
||||
@@ -55,7 +56,7 @@ public class JoinListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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);
|
||||
|
||||
@@ -10,6 +10,7 @@ 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;
|
||||
|
||||
@@ -50,7 +51,7 @@ public class LeaveListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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());
|
||||
|
||||
@@ -3,13 +3,13 @@ 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.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
|
||||
import dev.sheldan.abstracto.core.models.GuildChannelMember;
|
||||
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.service.MessageCache;
|
||||
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;
|
||||
@@ -19,14 +19,19 @@ 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;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListenerBean.ACTION;
|
||||
import static dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListenerBean.MESSAGE_METRIC;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MessageDeletedListenerBean extends ListenerAdapter {
|
||||
@@ -55,11 +60,27 @@ public class MessageDeletedListenerBean extends ListenerAdapter {
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
private static final CounterMetric MESSAGE_DELETED_COUNTER =
|
||||
CounterMetric
|
||||
.builder().name(MESSAGE_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(ACTION, "deleted")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onGuildMessageDelete(@Nonnull GuildMessageDeleteEvent event) {
|
||||
metricService.incrementCounter(MESSAGE_DELETED_COUNTER);
|
||||
if(listener == null) return;
|
||||
Consumer<CachedMessage> cachedMessageConsumer = cachedMessage -> self.executeListener(cachedMessage);
|
||||
messageCache.getMessageFromCache(event.getGuild().getIdLong(), event.getChannel().getIdLong(), event.getMessageIdLong())
|
||||
@@ -77,14 +98,14 @@ public class MessageDeletedListenerBean extends ListenerAdapter {
|
||||
.builder()
|
||||
.guild(serverManagementService.loadOrCreate(cachedMessage.getServerId()))
|
||||
.channel(channelManagementService.loadChannel(cachedMessage.getChannelId()))
|
||||
.aUserInAServer(userInServerManagementService.loadUser(cachedMessage.getServerId(), cachedMessage.getAuthor().getAuthorId()))
|
||||
.aUserInAServer(userInServerManagementService.loadOrCreateUser(cachedMessage.getServerId(), cachedMessage.getAuthor().getAuthorId()))
|
||||
.build();
|
||||
botService.getMemberInServerAsync(cachedMessage.getServerId(), cachedMessage.getAuthor().getAuthorId()).thenAccept(member -> {
|
||||
memberService.getMemberInServerAsync(cachedMessage.getServerId(), cachedMessage.getAuthor().getAuthorId()).thenAccept(member -> {
|
||||
GuildChannelMember authorMember = GuildChannelMember
|
||||
.builder()
|
||||
.guild(botService.getGuildById(cachedMessage.getServerId()))
|
||||
.textChannel(botService.getTextChannelFromServerOptional(cachedMessage.getServerId(), cachedMessage.getChannelId()).orElseThrow(() -> new ChannelNotInGuildException(cachedMessage.getChannelId())))
|
||||
.member(botService.getMemberInServer(cachedMessage.getServerId(), cachedMessage.getAuthor().getAuthorId()))
|
||||
.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());
|
||||
@@ -104,7 +125,7 @@ public class MessageDeletedListenerBean extends ListenerAdapter {
|
||||
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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);
|
||||
@@ -112,6 +133,7 @@ public class MessageDeletedListenerBean extends ListenerAdapter {
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(MESSAGE_DELETED_COUNTER, "Messages deleted");
|
||||
BeanUtils.sortPrioritizedListeners(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public class MessageEmbeddedListenerBean extends ListenerAdapter {
|
||||
private MessageEmbeddedListenerBean self;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onGuildMessageEmbed(@NotNull GuildMessageEmbedEvent event) {
|
||||
if(listenerList == null) return;
|
||||
GuildMessageEmbedEventModel model = buildModel(event);
|
||||
|
||||
@@ -3,6 +3,9 @@ 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.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
@@ -13,11 +16,13 @@ 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;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@@ -45,8 +50,17 @@ public class MessageReceivedListenerBean extends ListenerAdapter {
|
||||
@Autowired
|
||||
private MessageReceivedListenerBean self;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
public static final String MESSAGE_METRIC = "message";
|
||||
public static final String ACTION = "action";
|
||||
private static final CounterMetric MESSAGE_RECEIVED_COUNTER = CounterMetric.builder().name(MESSAGE_METRIC).tagList(Arrays.asList(MetricTag.getTag(ACTION, "received"))).build();
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) {
|
||||
metricService.incrementCounter(MESSAGE_RECEIVED_COUNTER);
|
||||
messageCache.putMessageInCache(event.getMessage());
|
||||
if(listenerList == null) return;
|
||||
for (MessageReceivedListener messageReceivedListener : listenerList) {
|
||||
@@ -66,13 +80,14 @@ public class MessageReceivedListenerBean extends ListenerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||
public MessageReceivedListenerResult executeIndividualGuildMessageReceivedListener(@Nonnull GuildMessageReceivedEvent event, MessageReceivedListener messageReceivedListener) {
|
||||
return messageReceivedListener.execute(event.getMessage());
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(MESSAGE_RECEIVED_COUNTER, "Message received");
|
||||
BeanUtils.sortPrioritizedListeners(listenerList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ 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.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
@@ -13,13 +16,18 @@ 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;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListenerBean.ACTION;
|
||||
import static dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListenerBean.MESSAGE_METRIC;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MessageUpdatedListenerBean extends ListenerAdapter {
|
||||
@@ -39,8 +47,15 @@ public class MessageUpdatedListenerBean extends ListenerAdapter {
|
||||
@Autowired
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
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;
|
||||
Message message = event.getMessage();
|
||||
messageCache.getMessageFromCache(message.getGuild().getIdLong(), message.getTextChannel().getIdLong(), event.getMessageIdLong()).thenAccept(cachedMessage -> {
|
||||
@@ -68,13 +83,14 @@ public class MessageUpdatedListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||
public void executeIndividualMessageUpdatedListener(Message message, CachedMessage cachedMessage, MessageTextUpdatedListener messageTextUpdatedListener) {
|
||||
messageTextUpdatedListener.execute(cachedMessage, message);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(MESSAGE_UPDATED_COUNTER, "Messages updated");
|
||||
BeanUtils.sortPrioritizedListeners(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent;
|
||||
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;
|
||||
|
||||
@@ -32,6 +33,7 @@ public class PrivateMessageReceivedListenerBean extends ListenerAdapter {
|
||||
private PrivateMessageReceivedListenerBean self;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onPrivateMessageReceived(@Nonnull PrivateMessageReceivedEvent event) {
|
||||
if(privateMessageReceivedListeners == null) return;
|
||||
if(event.getAuthor().getId().equals(botService.getInstance().getSelfUser().getId())) {
|
||||
@@ -47,7 +49,7 @@ public class PrivateMessageReceivedListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||
public void executeIndividualPrivateMessageReceivedListener(@Nonnull PrivateMessageReceivedEvent event, PrivateMessageReceivedListener messageReceivedListener) {
|
||||
// no feature flag check, because we are in no server context
|
||||
log.trace("Executing private message listener {} for member {}.", messageReceivedListener.getClass().getName(), event.getAuthor().getId());
|
||||
|
||||
@@ -12,6 +12,7 @@ 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;
|
||||
|
||||
@@ -106,7 +107,7 @@ public class ReactionAddedListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ 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;
|
||||
|
||||
@@ -50,20 +52,24 @@ public class ReactionClearedListenerBean extends ListenerAdapter {
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void callClearListeners(@Nonnull GuildMessageReactionRemoveAllEvent event, CachedMessage cachedMessage) {
|
||||
if(clearedListenerList == null) return;
|
||||
clearedListenerList.forEach(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);
|
||||
}
|
||||
});
|
||||
clearedListenerList.forEach(reactionRemovedListener ->
|
||||
self.executeIndividualListener(event, cachedMessage, reactionRemovedListener)
|
||||
);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,7 @@ 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;
|
||||
|
||||
@@ -103,7 +104,7 @@ public class ReactionRemovedListenerBean extends ListenerAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ 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;
|
||||
@@ -28,7 +29,7 @@ public class RoleListener extends ListenerAdapter {
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@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());
|
||||
@@ -36,7 +37,7 @@ public class RoleListener extends ListenerAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@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());
|
||||
|
||||
@@ -8,6 +8,7 @@ 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;
|
||||
|
||||
@@ -36,7 +37,7 @@ public class ServerJoinListener extends ListenerAdapter {
|
||||
configListeners.forEach(serverConfigListener -> self.executingIndividualServerConfigListener(server, serverConfigListener));
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@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);
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
package dev.sheldan.abstracto.core.metrics;
|
||||
|
||||
import dev.sheldan.abstracto.core.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class OkHttpMetrics implements Interceptor {
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
public static final String MODERATION_PURGE_METRIC = "okhttp.request";
|
||||
public static final String HTTP_CODE = "http.code";
|
||||
|
||||
private static final CounterMetric OKTTHP_200_RESPONSE =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.tagList(Arrays.asList(MetricTag.getTag(HTTP_CODE, "200")))
|
||||
.name(MODERATION_PURGE_METRIC)
|
||||
.build();
|
||||
|
||||
private static final CounterMetric OKTTHP_201_RESPONSE =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.tagList(Arrays.asList(MetricTag.getTag(HTTP_CODE, "201")))
|
||||
.name(MODERATION_PURGE_METRIC)
|
||||
.build();
|
||||
|
||||
private static final CounterMetric OKTTHP_204_RESPONSE =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.tagList(Arrays.asList(MetricTag.getTag(HTTP_CODE, "204")))
|
||||
.name(MODERATION_PURGE_METRIC)
|
||||
.build();
|
||||
|
||||
private static final CounterMetric OKTTHP_202_RESPONSE =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.tagList(Arrays.asList(MetricTag.getTag(HTTP_CODE, "202")))
|
||||
.name(MODERATION_PURGE_METRIC)
|
||||
.build();
|
||||
|
||||
private static final CounterMetric OKTTHP_401_RESPONSE =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.tagList(Arrays.asList(MetricTag.getTag(HTTP_CODE, "401")))
|
||||
.name(MODERATION_PURGE_METRIC)
|
||||
.build();
|
||||
|
||||
private static final CounterMetric OKTTHP_403_RESPONSE =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.tagList(Arrays.asList(MetricTag.getTag(HTTP_CODE, "403")))
|
||||
.name(MODERATION_PURGE_METRIC)
|
||||
.build();
|
||||
|
||||
private static final CounterMetric OKTTHP_404_RESPONSE =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.tagList(Arrays.asList(MetricTag.getTag(HTTP_CODE, "404")))
|
||||
.name(MODERATION_PURGE_METRIC)
|
||||
.build();
|
||||
|
||||
private static final CounterMetric OKTTHP_429_RESPONSE =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.tagList(Arrays.asList(MetricTag.getTag(HTTP_CODE, "429")))
|
||||
.name(MODERATION_PURGE_METRIC)
|
||||
.build();
|
||||
|
||||
private static final CounterMetric OKTTHP_500_RESPONSE =
|
||||
CounterMetric
|
||||
.builder()
|
||||
.tagList(Arrays.asList(MetricTag.getTag(HTTP_CODE, "500")))
|
||||
.name(MODERATION_PURGE_METRIC)
|
||||
.build();
|
||||
|
||||
private static final HashMap<Integer, CounterMetric> METRICS = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Request request = chain.request();
|
||||
Response response = chain.proceed(request);
|
||||
incrementCounter(response.code());
|
||||
return response;
|
||||
}
|
||||
|
||||
private void incrementCounter(Integer code) {
|
||||
if(METRICS.containsKey(code)) {
|
||||
metricService.incrementCounter(METRICS.get(code));
|
||||
} else {
|
||||
log.warn("Unmapped response code from server {}.", code);
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(OKTTHP_200_RESPONSE, "Amount of HTTP 200 responses in okhttp");
|
||||
metricService.registerCounter(OKTTHP_201_RESPONSE, "Amount of HTTP 201 responses in okhttp");
|
||||
metricService.registerCounter(OKTTHP_202_RESPONSE, "Amount of HTTP 202 responses in okhttp");
|
||||
metricService.registerCounter(OKTTHP_204_RESPONSE, "Amount of HTTP 204 responses in okhttp");
|
||||
metricService.registerCounter(OKTTHP_401_RESPONSE, "Amount of HTTP 401 responses in okhttp");
|
||||
metricService.registerCounter(OKTTHP_403_RESPONSE, "Amount of HTTP 403 responses in okhttp");
|
||||
metricService.registerCounter(OKTTHP_404_RESPONSE, "Amount of HTTP 404 responses in okhttp");
|
||||
metricService.registerCounter(OKTTHP_429_RESPONSE, "Amount of HTTP 429 responses in okhttp");
|
||||
metricService.registerCounter(OKTTHP_500_RESPONSE, "Amount of HTTP 500 responses in okhttp");
|
||||
METRICS.put(200, OKTTHP_200_RESPONSE);
|
||||
METRICS.put(201, OKTTHP_201_RESPONSE);
|
||||
METRICS.put(202, OKTTHP_202_RESPONSE);
|
||||
METRICS.put(204, OKTTHP_204_RESPONSE);
|
||||
METRICS.put(401, OKTTHP_401_RESPONSE);
|
||||
METRICS.put(403, OKTTHP_403_RESPONSE);
|
||||
METRICS.put(404, OKTTHP_404_RESPONSE);
|
||||
METRICS.put(429, OKTTHP_429_RESPONSE);
|
||||
METRICS.put(500, OKTTHP_500_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,10 @@ import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.GuildChannelMember;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.metrics.OkHttpMetrics;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||
import net.dv8tion.jda.api.utils.MemberCachePolicy;
|
||||
import net.dv8tion.jda.internal.utils.IOUtil;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static net.dv8tion.jda.api.requests.GatewayIntent.*;
|
||||
|
||||
@@ -28,6 +21,9 @@ public class BotServiceBean implements BotService {
|
||||
|
||||
private JDA instance;
|
||||
|
||||
@Autowired
|
||||
private OkHttpMetrics okHttpMetrics;
|
||||
|
||||
@Override
|
||||
public void login() throws LoginException {
|
||||
JDABuilder builder = JDABuilder.create(System.getenv("TOKEN"), GatewayIntent.GUILD_MEMBERS, GUILD_VOICE_STATES,
|
||||
@@ -35,7 +31,10 @@ public class BotServiceBean implements BotService {
|
||||
GUILD_MESSAGE_REACTIONS, DIRECT_MESSAGE_REACTIONS, DIRECT_MESSAGES, GUILD_PRESENCES);
|
||||
|
||||
builder.setBulkDeleteSplittingEnabled(false);
|
||||
builder.setMemberCachePolicy(MemberCachePolicy.ALL);
|
||||
builder.setMemberCachePolicy(MemberCachePolicy.DEFAULT);
|
||||
OkHttpClient.Builder defaultBuilder = IOUtil.newHttpClientBuilder();
|
||||
defaultBuilder.addInterceptor(okHttpMetrics);
|
||||
builder.setHttpClientBuilder(defaultBuilder);
|
||||
|
||||
this.instance = builder.build();
|
||||
}
|
||||
@@ -45,201 +44,5 @@ public class BotServiceBean implements BotService {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuildChannelMember getServerChannelUser(Long serverId, Long channelId, Long userId) {
|
||||
log.trace("Trying to retrieve member {}, channel {} in server {} from cache.", userId, channelId, serverId);
|
||||
Guild guild = getGuildById(serverId);
|
||||
Optional<TextChannel> textChannelOptional = this.getTextChannelFromServerOptional(guild, channelId);
|
||||
if(textChannelOptional.isPresent()) {
|
||||
TextChannel textChannel = textChannelOptional.get();
|
||||
Member member = guild.getMemberById(userId);
|
||||
return GuildChannelMember.builder().guild(guild).textChannel(textChannel).member(member).build();
|
||||
} else {
|
||||
throw new ChannelNotInGuildException(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<GuildChannelMember> getServerChannelUserAsync(Long serverId, Long channelId, Long userId) {
|
||||
log.trace("Trying to retrieve member {}, channel {} in server {} async.", userId, channelId, serverId);
|
||||
CompletableFuture<Member> memberFuture = getMemberInServerAsync(serverId, userId);
|
||||
|
||||
Guild guild = getGuildById(serverId);
|
||||
TextChannel textChannel = this.getTextChannelFromServer(guild, channelId);
|
||||
return memberFuture.thenApply(member ->
|
||||
GuildChannelMember.builder().guild(guild).textChannel(textChannel).member(member).build()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getMemberInServer(Long serverId, Long memberId) {
|
||||
log.trace("Retrieving member {} in server {} from cache.", memberId, serverId);
|
||||
Guild guildById = instance.getGuildById(serverId);
|
||||
if(guildById != null) {
|
||||
return guildById.getMemberById(memberId);
|
||||
} else {
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Member> getMemberInServerAsync(Long serverId, Long memberId) {
|
||||
log.trace("Retrieving member {} in server {} from cache.", memberId, serverId);
|
||||
Guild guildById = instance.getGuildById(serverId);
|
||||
if(guildById != null) {
|
||||
return guildById.retrieveMemberById(memberId).submit();
|
||||
} else {
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Member> retrieveMemberInServer(ServerUser serverUser) {
|
||||
return getMemberInServerAsync(serverUser.getServerId(), serverUser.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<User> retrieveUserById(Long userId) {
|
||||
return instance.retrieveUserById(userId).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInGuild(AUserInAServer aUserInAServer) {
|
||||
Guild guildById = instance.getGuildById(aUserInAServer.getServerReference().getId());
|
||||
if(guildById != null) {
|
||||
return isUserInGuild(guildById, aUserInAServer);
|
||||
} else {
|
||||
throw new GuildNotFoundException(aUserInAServer.getServerReference().getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInGuild(Guild guild, AUserInAServer aUserInAServer) {
|
||||
return guild.getMemberById(aUserInAServer.getUserReference().getId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getMemberInServer(AUserInAServer aUserInAServer) {
|
||||
return getMemberInServer(aUserInAServer.getServerReference().getId(), aUserInAServer.getUserReference().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Member> getMemberInServerAsync(AUserInAServer aUserInAServer) {
|
||||
return getMemberInServerAsync(aUserInAServer.getServerReference().getId(), aUserInAServer.getUserReference().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getMemberInServer(AServer server, AUser member) {
|
||||
return getMemberInServer(server.getId(), member.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteMessage(Long serverId, Long channelId, Long messageId) {
|
||||
Optional<TextChannel> textChannelOptional = getTextChannelFromServerOptional(serverId, channelId);
|
||||
if(textChannelOptional.isPresent()) {
|
||||
TextChannel textChannel = textChannelOptional.get();
|
||||
return textChannel.deleteMessageById(messageId).submit();
|
||||
} else {
|
||||
log.warn("Could not find channel {} in guild {} to delete message {} in.", channelId, serverId, messageId);
|
||||
}
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteMessage(Long channelId, Long messageId) {
|
||||
TextChannel textChannel = getInstance().getTextChannelById(channelId);
|
||||
if(textChannel != null) {
|
||||
return textChannel.deleteMessageById(messageId).submit();
|
||||
} else {
|
||||
log.warn("Could not find channel {} to delete message {} in.", channelId, messageId);
|
||||
}
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Member> forceReloadMember(Member member) {
|
||||
return member.getGuild().retrieveMember(member.getUser()).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Emote> getEmote(Long serverId, AEmote emote) {
|
||||
if(Boolean.FALSE.equals(emote.getCustom())) {
|
||||
return Optional.empty();
|
||||
}
|
||||
Optional<Guild> guildById = getGuildByIdOptional(serverId);
|
||||
if(guildById.isPresent()) {
|
||||
Guild guild = guildById.get();
|
||||
Emote emoteById = guild.getEmoteById(emote.getEmoteId());
|
||||
return Optional.ofNullable(emoteById);
|
||||
}
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Emote> getEmote(AEmote emote) {
|
||||
if(Boolean.FALSE.equals(emote.getCustom())) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.ofNullable(instance.getEmoteById(emote.getEmoteId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TextChannel> getTextChannelFromServerOptional(Guild guild, Long textChannelId) {
|
||||
return Optional.ofNullable(guild.getTextChannelById(textChannelId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextChannel getTextChannelFromServer(Guild guild, Long textChannelId) {
|
||||
return getTextChannelFromServerOptional(guild, textChannelId).orElseThrow(() -> new ChannelNotInGuildException(textChannelId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextChannel getTextChannelFromServerNullable(Guild guild, Long textChannelId) {
|
||||
return getTextChannelFromServerOptional(guild, textChannelId).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TextChannel> getTextChannelFromServerOptional(Long serverId, Long textChannelId) {
|
||||
Optional<Guild> guildOptional = getGuildByIdOptional(serverId);
|
||||
if(guildOptional.isPresent()) {
|
||||
Guild guild = guildOptional.get();
|
||||
return Optional.ofNullable(guild.getTextChannelById(textChannelId));
|
||||
}
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextChannel getTextChannelFromServer(Long serverId, Long textChannelId) {
|
||||
return getTextChannelFromServerOptional(serverId, textChannelId).orElseThrow(() -> new ChannelNotInGuildException(textChannelId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Guild> getGuildByIdOptional(Long serverId) {
|
||||
return Optional.ofNullable(instance.getGuildById(serverId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Guild getGuildById(Long serverId) {
|
||||
Guild guildById = instance.getGuildById(serverId);
|
||||
if(guildById == null) {
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
return guildById;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Guild> retrieveGuildById(Long serverId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getBotInGuild(AServer server) {
|
||||
Guild guild = getGuildById(server.getId());
|
||||
return guild.getSelfMember();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<User> getUserViaId(Long userId) {
|
||||
return instance.retrieveUserById(userId).submit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,34 +3,80 @@ package dev.sheldan.abstracto.core.service;
|
||||
import dev.sheldan.abstracto.core.exception.CategoryNotFoundException;
|
||||
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||
import dev.sheldan.abstracto.core.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static dev.sheldan.abstracto.core.config.MetricConstants.DISCORD_API_INTERACTION_METRIC;
|
||||
import static dev.sheldan.abstracto.core.config.MetricConstants.INTERACTION_TYPE;
|
||||
import static dev.sheldan.abstracto.core.service.MessageServiceBean.*;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ChannelServiceBean implements ChannelService {
|
||||
|
||||
@Autowired
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
public static final CounterMetric CHANNEL_CREATE_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "channel.create")))
|
||||
.build();
|
||||
|
||||
public static final CounterMetric CHANNEL_DELETE_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "channel.delete")))
|
||||
.build();
|
||||
|
||||
public static final CounterMetric CHANNEL_MESSAGE_BULK_DELETE_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "channel.message.bulk.delete")))
|
||||
.build();
|
||||
|
||||
public static final CounterMetric CHANNEL_RETRIEVE_HISTORY = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "channel.load.history")))
|
||||
.build();
|
||||
|
||||
public static final CounterMetric CHANNEL_CHANGE_SLOW_MODE = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "channel.slowmode")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void sendTextToAChannelNotAsync(String text, AChannel channel) {
|
||||
sendTextToAChannel(text, channel);
|
||||
@@ -60,7 +106,7 @@ public class ChannelServiceBean implements ChannelService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> sendMessageToAChannel(Message message, AChannel channel) {
|
||||
Optional<TextChannel> textChannelOpt = botService.getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
|
||||
Optional<TextChannel> textChannelOpt = getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
|
||||
if(textChannelOpt.isPresent()) {
|
||||
TextChannel textChannel = textChannelOpt.get();
|
||||
return sendMessageToChannel(message, textChannel);
|
||||
@@ -72,12 +118,14 @@ public class ChannelServiceBean implements ChannelService {
|
||||
public CompletableFuture<Message> sendMessageToChannel(Message message, MessageChannel channel) {
|
||||
log.trace("Sending message {} from channel {} and server {} to channel {}.",
|
||||
message.getId(), message.getChannel().getId(), message.getGuild().getId(), channel.getId());
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
return channel.sendMessage(message).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> sendTextToChannel(String text, MessageChannel channel) {
|
||||
log.trace("Sending text to channel {}.", channel.getId());
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
return channel.sendMessage(text).submit();
|
||||
}
|
||||
|
||||
@@ -106,12 +154,13 @@ public class ChannelServiceBean implements ChannelService {
|
||||
|
||||
@Override
|
||||
public MessageAction sendEmbedToChannelInComplete(MessageEmbed embed, MessageChannel channel) {
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
return channel.sendMessage(embed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Message>> sendMessageToSendToAChannel(MessageToSend messageToSend, AChannel channel) {
|
||||
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
|
||||
Optional<TextChannel> textChannelFromServer = getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
|
||||
if(textChannelFromServer.isPresent()) {
|
||||
return sendMessageToSendToChannel(messageToSend, textChannelFromServer.get());
|
||||
}
|
||||
@@ -123,6 +172,18 @@ public class ChannelServiceBean implements ChannelService {
|
||||
return sendEmbedToAChannel(messageToSend.getEmbeds().get(embedIndex), channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> retrieveMessageInChannel(Long serverId, Long channelId, Long messageId) {
|
||||
TextChannel channel = getTextChannelFromServer(serverId, channelId);
|
||||
return retrieveMessageInChannel(channel, messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> retrieveMessageInChannel(MessageChannel channel, Long messageId) {
|
||||
metricService.incrementCounter(MESSAGE_LOAD_METRIC);
|
||||
return channel.retrieveMessageById(messageId).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Message>> sendMessageToSendToChannel(MessageToSend messageToSend, MessageChannel textChannel) {
|
||||
String messageText = messageToSend.getMessage();
|
||||
@@ -130,10 +191,12 @@ public class ChannelServiceBean implements ChannelService {
|
||||
MessageAction firstMessageAction = null;
|
||||
List<MessageAction> allMessageActions = new ArrayList<>();
|
||||
if(!StringUtils.isBlank(messageText)) {
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
firstMessageAction = textChannel.sendMessage(messageText);
|
||||
}
|
||||
if(!messageToSend.getEmbeds().isEmpty()) {
|
||||
if(firstMessageAction != null) {
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
firstMessageAction.embed(messageToSend.getEmbeds().get(0));
|
||||
} else {
|
||||
firstMessageAction = textChannel.sendMessage(messageToSend.getEmbeds().get(0));
|
||||
@@ -142,6 +205,8 @@ public class ChannelServiceBean implements ChannelService {
|
||||
}
|
||||
if(messageToSend.hasFileToSend()) {
|
||||
if(firstMessageAction != null) {
|
||||
// in case there has not been a message, we need to increment it
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
firstMessageAction.addFile(messageToSend.getFileToSend());
|
||||
} else {
|
||||
firstMessageAction = textChannel.sendFile(messageToSend.getFileToSend());
|
||||
@@ -154,14 +219,9 @@ public class ChannelServiceBean implements ChannelService {
|
||||
return futures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TextChannel> getTextChannelInGuild(Long serverId, Long channelId) {
|
||||
return botService.getTextChannelFromServerOptional(serverId, channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editMessageInAChannel(MessageToSend messageToSend, AChannel channel, Long messageId) {
|
||||
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
|
||||
Optional<TextChannel> textChannelFromServer = getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
|
||||
if(textChannelFromServer.isPresent()) {
|
||||
TextChannel textChannel = textChannelFromServer.get();
|
||||
editMessageInAChannel(messageToSend, textChannel, messageId);
|
||||
@@ -193,26 +253,35 @@ public class ChannelServiceBean implements ChannelService {
|
||||
throw new IllegalArgumentException("Message to send did not contain anything to send.");
|
||||
}
|
||||
}
|
||||
metricService.incrementCounter(MESSAGE_EDIT_METRIC);
|
||||
return messageAction.submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> editEmbedMessageInAChannel(MessageEmbed embedToSend, MessageChannel channel, Long messageId) {
|
||||
metricService.incrementCounter(MESSAGE_EDIT_METRIC);
|
||||
return channel.editMessageById(messageId, embedToSend).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> editTextMessageInAChannel(String text, MessageChannel channel, Long messageId) {
|
||||
metricService.incrementCounter(MESSAGE_EDIT_METRIC);
|
||||
return channel.editMessageById(messageId, text).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> editTextMessageInAChannel(String text, MessageEmbed messageEmbed, MessageChannel channel, Long messageId) {
|
||||
metricService.incrementCounter(MESSAGE_EDIT_METRIC);
|
||||
return channel.editMessageById(messageId, text).embed(messageEmbed).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Message>> editMessagesInAChannelFuture(MessageToSend messageToSend, MessageChannel channel, List<Long> messageIds) {
|
||||
List<CompletableFuture<Message>> futures = new ArrayList<>();
|
||||
futures.add(editMessageInAChannelFuture(messageToSend, channel ,messageIds.get(0)));
|
||||
for (int i = 1; i < messageIds.size(); i++) {
|
||||
Long messageIdToUpdate = messageIds.get(i);
|
||||
futures.add(channel.editMessageById(messageIdToUpdate, messageToSend.getEmbeds().get(i)).submit());
|
||||
futures.add(editEmbedMessageInAChannel(messageToSend.getEmbeds().get(i), channel, messageIdToUpdate));
|
||||
}
|
||||
return futures;
|
||||
}
|
||||
@@ -224,11 +293,11 @@ public class ChannelServiceBean implements ChannelService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> removeFieldFromMessage(MessageChannel channel, Long messageId, Integer index, Integer embedIndex) {
|
||||
return channel.retrieveMessageById(messageId).submit().thenCompose(message -> {
|
||||
return retrieveMessageInChannel(channel, messageId).thenCompose(message -> {
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder(message.getEmbeds().get(embedIndex));
|
||||
embedBuilder.getFields().remove(index.intValue());
|
||||
log.trace("Removing field with index {} from message {}.", index, messageId);
|
||||
return channel.editMessageById(messageId, embedBuilder.build()).submit();
|
||||
return editEmbedMessageInAChannel(embedBuilder.build(), channel, messageId);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -242,6 +311,7 @@ public class ChannelServiceBean implements ChannelService {
|
||||
TextChannel textChannelById = botService.getInstance().getTextChannelById(channelId);
|
||||
if(textChannelById != null) {
|
||||
log.info("Deleting channel {} on server {}.", channelId, serverId);
|
||||
metricService.incrementCounter(CHANNEL_DELETE_METRIC);
|
||||
return textChannelById.delete().submit();
|
||||
}
|
||||
throw new ChannelNotInGuildException(channelId);
|
||||
@@ -260,13 +330,20 @@ public class ChannelServiceBean implements ChannelService {
|
||||
return sendTextToChannel(text, channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestAction<Void> deleteMessagesInChannel(TextChannel textChannel, List<Message> messages) {
|
||||
metricService.incrementCounter(CHANNEL_MESSAGE_BULK_DELETE_METRIC);
|
||||
return textChannel.deleteMessages(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<TextChannel> createTextChannel(String name, AServer server, Long categoryId) {
|
||||
Optional<Guild> guildById = botService.getGuildByIdOptional(server.getId());
|
||||
Optional<Guild> guildById = guildService.getGuildByIdOptional(server.getId());
|
||||
if(guildById.isPresent()) {
|
||||
Guild guild = guildById.get();
|
||||
Category categoryById = guild.getCategoryById(categoryId);
|
||||
if(categoryById != null) {
|
||||
metricService.incrementCounter(CHANNEL_CREATE_METRIC);
|
||||
log.info("Creating channel on server {} in category {}.", server.getId(), categoryById);
|
||||
return categoryById.createTextChannel(name).submit();
|
||||
}
|
||||
@@ -277,7 +354,7 @@ public class ChannelServiceBean implements ChannelService {
|
||||
|
||||
@Override
|
||||
public Optional<TextChannel> getChannelFromAChannel(AChannel channel) {
|
||||
return botService.getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
|
||||
return getTextChannelFromServerOptional(channel.getServer().getId(), channel.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -297,12 +374,58 @@ public class ChannelServiceBean implements ChannelService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> sendSimpleTemplateToChannel(Long serverId, Long channelId, String template) {
|
||||
TextChannel textChannel = getTextChannel(serverId, channelId);
|
||||
TextChannel textChannel = getTextChannelFromServer(serverId, channelId);
|
||||
return sendTextTemplateInChannel(template, new Object(), textChannel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextChannel getTextChannel(Long serverId, Long channelId) {
|
||||
return botService.getTextChannelFromServer(serverId, channelId);
|
||||
public CompletableFuture<MessageHistory> getHistoryOfChannel(TextChannel channel, Long startMessageId, Integer amount) {
|
||||
return channel.getHistoryBefore(startMessageId, amount).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TextChannel> getTextChannelFromServerOptional(Guild guild, Long textChannelId) {
|
||||
return Optional.ofNullable(guild.getTextChannelById(textChannelId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextChannel getTextChannelFromServer(Guild guild, Long textChannelId) {
|
||||
return getTextChannelFromServerOptional(guild, textChannelId).orElseThrow(() -> new ChannelNotInGuildException(textChannelId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextChannel getTextChannelFromServerNullable(Guild guild, Long textChannelId) {
|
||||
return getTextChannelFromServerOptional(guild, textChannelId).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TextChannel> getTextChannelFromServerOptional(Long serverId, Long textChannelId) {
|
||||
Optional<Guild> guildOptional = guildService.getGuildByIdOptional(serverId);
|
||||
if(guildOptional.isPresent()) {
|
||||
Guild guild = guildOptional.get();
|
||||
return Optional.ofNullable(guild.getTextChannelById(textChannelId));
|
||||
}
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextChannel getTextChannelFromServer(Long serverId, Long textChannelId) {
|
||||
return getTextChannelFromServerOptional(serverId, textChannelId).orElseThrow(() -> new ChannelNotInGuildException(textChannelId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> setSlowModeInChannel(TextChannel textChannel, Integer seconds) {
|
||||
metricService.incrementCounter(CHANNEL_CHANGE_SLOW_MODE);
|
||||
return textChannel.getManager().setSlowmode(seconds).submit();
|
||||
}
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(CHANNEL_CREATE_METRIC, "Amount of channels created");
|
||||
metricService.registerCounter(CHANNEL_DELETE_METRIC, "Amount of channels deleted");
|
||||
metricService.registerCounter(CHANNEL_MESSAGE_BULK_DELETE_METRIC, "Amount of channel bulk message delete");
|
||||
metricService.registerCounter(CHANNEL_RETRIEVE_HISTORY, "Amount of retrievals of message history in a channel");
|
||||
metricService.registerCounter(CHANNEL_CHANGE_SLOW_MODE, "Amount of times slowmode has been changed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.ConfigurationKeyNotFoundException;
|
||||
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.models.database.AConfig;
|
||||
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.EmoteNotDefinedException;
|
||||
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
|
||||
@@ -26,6 +27,9 @@ public class EmoteServiceBean implements EmoteService {
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private EmoteManagementService emoteManagementService;
|
||||
|
||||
@@ -58,7 +62,7 @@ public class EmoteServiceBean implements EmoteService {
|
||||
@Override
|
||||
public String getEmoteAsMention(AEmote emote, Long serverId, String defaultText) {
|
||||
if(emote != null && emote.getCustom()) {
|
||||
Optional<Emote> emoteOptional = botService.getEmote(serverId, emote);
|
||||
Optional<Emote> emoteOptional = getEmote(serverId, emote);
|
||||
if (emoteOptional.isPresent()) {
|
||||
return emoteOptional.get().getAsMention();
|
||||
} else {
|
||||
@@ -183,9 +187,30 @@ public class EmoteServiceBean implements EmoteService {
|
||||
if(!cachedEmote.getCustom()) {
|
||||
throw new IllegalArgumentException("Given Emote was not a custom emote.");
|
||||
}
|
||||
return botService.retrieveGuildById(cachedEmote.getServerId()).thenCompose(guild ->
|
||||
guild.retrieveEmoteById(cachedEmote.getEmoteId()).submit().thenApply(listedEmote -> listedEmote)
|
||||
);
|
||||
Guild guild = guildService.getGuildById(cachedEmote.getServerId());
|
||||
return guild.retrieveEmoteById(cachedEmote.getEmoteId()).submit().thenApply(listedEmote -> listedEmote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Emote> getEmote(Long serverId, AEmote emote) {
|
||||
if(Boolean.FALSE.equals(emote.getCustom())) {
|
||||
return Optional.empty();
|
||||
}
|
||||
Optional<Guild> guildById = guildService.getGuildByIdOptional(serverId);
|
||||
if(guildById.isPresent()) {
|
||||
Guild guild = guildById.get();
|
||||
Emote emoteById = guild.getEmoteById(emote.getEmoteId());
|
||||
return Optional.ofNullable(emoteById);
|
||||
}
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Emote> getEmote(AEmote emote) {
|
||||
if(Boolean.FALSE.equals(emote.getCustom())) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.ofNullable(botService.getInstance().getEmoteById(emote.getEmoteId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.FeatureAware;
|
||||
import dev.sheldan.abstracto.core.command.exception.IncorrectFeatureModeException;
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
|
||||
import dev.sheldan.abstracto.core.FeatureAware;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.FeatureModeDisplay;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultFeatureModeManagement;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||
import dev.sheldan.abstracto.core.interactive.DelayedActionConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||
import dev.sheldan.abstracto.core.interactive.*;
|
||||
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.SetupCompletedNotificationModel;
|
||||
@@ -48,6 +47,9 @@ public class FeatureSetupServiceBean implements FeatureSetupService {
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@@ -58,7 +60,7 @@ public class FeatureSetupServiceBean implements FeatureSetupService {
|
||||
public CompletableFuture<Void> performFeatureSetup(FeatureConfig featureConfig, AServerChannelUserId user, Long initialMessageId) {
|
||||
log.info("Performing setup of feature {} for user {} in channel {} in server {}.",
|
||||
featureConfig.getFeature().getKey(), user.getUserId(), user.getChannelId(), user.getGuildId());
|
||||
Optional<TextChannel> textChannelInGuild = channelService.getTextChannelInGuild(user.getGuildId(), user.getChannelId());
|
||||
Optional<TextChannel> textChannelInGuild = channelService.getTextChannelFromServerOptional(user.getGuildId(), user.getChannelId());
|
||||
if(textChannelInGuild.isPresent()) {
|
||||
List<String> requiredSystemConfigKeys = featureConfig.getRequiredSystemConfigKeys();
|
||||
List<SetupExecution> steps = new ArrayList<>();
|
||||
@@ -142,8 +144,8 @@ public class FeatureSetupServiceBean implements FeatureSetupService {
|
||||
|
||||
@Transactional
|
||||
public void showExceptionMessage(Throwable throwable, AServerChannelUserId aServerChannelUserId) {
|
||||
Optional<TextChannel> channelOptional = botService.getTextChannelFromServerOptional(aServerChannelUserId.getGuildId(), aServerChannelUserId.getChannelId());
|
||||
botService.getMemberInServerAsync(aServerChannelUserId.getGuildId(), aServerChannelUserId.getUserId()).thenAccept(member ->
|
||||
Optional<TextChannel> channelOptional = channelService.getTextChannelFromServerOptional(aServerChannelUserId.getGuildId(), aServerChannelUserId.getChannelId());
|
||||
memberService.getMemberInServerAsync(aServerChannelUserId.getGuildId(), aServerChannelUserId.getUserId()).thenAccept(member ->
|
||||
channelOptional.ifPresent(textChannel -> exceptionService.reportExceptionToChannel(throwable, textChannel, member))
|
||||
).exceptionally(innserThrowable -> {
|
||||
log.error("Failed to report exception message for exception {} for user {} in channel {} in server {}.", throwable, aServerChannelUserId.getUserId(), aServerChannelUserId.getChannelId(), aServerChannelUserId.getGuildId(), innserThrowable);
|
||||
@@ -174,7 +176,7 @@ public class FeatureSetupServiceBean implements FeatureSetupService {
|
||||
.featureConfig(featureConfig)
|
||||
.build();
|
||||
String text = templateService.renderTemplate(templateName, model);
|
||||
Optional<TextChannel> textChannel = channelService.getTextChannelInGuild(aServerChannelUserId.getGuildId(), aServerChannelUserId.getChannelId());
|
||||
Optional<TextChannel> textChannel = channelService.getTextChannelFromServerOptional(aServerChannelUserId.getGuildId(), aServerChannelUserId.getChannelId());
|
||||
textChannel.ifPresent(channel -> channelService.sendTextToChannel(text, channel));
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ public class FeatureValidationServiceBean implements FeatureValidatorService {
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Override
|
||||
public void checkPostTarget(PostTargetEnum name, AServer server, FeatureValidationResult featureValidationResult) {
|
||||
if(!postTargetManagement.postTargetExists(name.getKey(), server)) {
|
||||
@@ -73,7 +76,7 @@ public class FeatureValidationServiceBean implements FeatureValidatorService {
|
||||
if(emoteById == null) {
|
||||
rejectEmote(emoteKey, featureValidationResult);
|
||||
} else {
|
||||
Member selfMember = botService.getMemberInServer(server.getId(), botService.getInstance().getSelfUser().getIdLong());
|
||||
Member selfMember = memberService.getMemberInServer(server.getId(), botService.getInstance().getSelfUser().getIdLong());
|
||||
if(!emoteById.canInteract(selfMember)) {
|
||||
rejectEmote(emoteKey, featureValidationResult);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class GuildServiceBean implements GuildService {
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Override
|
||||
public Optional<Guild> getGuildByIdOptional(Long serverId) {
|
||||
return Optional.ofNullable(botService.getInstance().getGuildById(serverId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Guild getGuildById(Long serverId) {
|
||||
Guild guildById = botService.getInstance().getGuildById(serverId);
|
||||
if(guildById == null) {
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
return guildById;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.GuildChannelMember;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MemberServiceBean implements MemberService {
|
||||
|
||||
@Autowired
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public GuildChannelMember getServerChannelUser(Long serverId, Long channelId, Long userId) {
|
||||
log.trace("Trying to retrieve member {}, channel {} in server {} from cache.", userId, channelId, serverId);
|
||||
Guild guild = guildService.getGuildById(serverId);
|
||||
Optional<TextChannel> textChannelOptional = channelService.getTextChannelFromServerOptional(guild, channelId);
|
||||
if(textChannelOptional.isPresent()) {
|
||||
TextChannel textChannel = textChannelOptional.get();
|
||||
Member member = guild.getMemberById(userId);
|
||||
return GuildChannelMember.builder().guild(guild).textChannel(textChannel).member(member).build();
|
||||
} else {
|
||||
throw new ChannelNotInGuildException(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<GuildChannelMember> getServerChannelUserAsync(Long serverId, Long channelId, Long userId) {
|
||||
log.trace("Trying to retrieve member {}, channel {} in server {} async.", userId, channelId, serverId);
|
||||
CompletableFuture<Member> memberFuture = getMemberInServerAsync(serverId, userId);
|
||||
|
||||
Guild guild = guildService.getGuildById(serverId);
|
||||
TextChannel textChannel = channelService.getTextChannelFromServer(guild, channelId);
|
||||
return memberFuture.thenApply(member ->
|
||||
GuildChannelMember.builder().guild(guild).textChannel(textChannel).member(member).build()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getMemberInServer(Long serverId, Long memberId) {
|
||||
log.trace("Retrieving member {} in server {} from cache.", memberId, serverId);
|
||||
Guild guildById = guildService.getGuildById(serverId);
|
||||
if(guildById != null) {
|
||||
return guildById.getMemberById(memberId);
|
||||
} else {
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Member> getMemberInServerAsync(Long serverId, Long memberId) {
|
||||
log.trace("Retrieving member {} in server {} from cache.", memberId, serverId);
|
||||
Guild guildById = guildService.getGuildById(serverId);
|
||||
if(guildById != null) {
|
||||
return guildById.retrieveMemberById(memberId).submit();
|
||||
} else {
|
||||
throw new GuildNotFoundException(serverId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Member> retrieveMemberInServer(ServerUser serverUser) {
|
||||
return getMemberInServerAsync(serverUser.getServerId(), serverUser.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<User> retrieveUserById(Long userId) {
|
||||
return botService.getInstance().retrieveUserById(userId).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInGuild(AUserInAServer aUserInAServer) {
|
||||
Guild guildById = guildService.getGuildById(aUserInAServer.getServerReference().getId());
|
||||
if(guildById != null) {
|
||||
return isUserInGuild(guildById, aUserInAServer);
|
||||
} else {
|
||||
throw new GuildNotFoundException(aUserInAServer.getServerReference().getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInGuild(Guild guild, AUserInAServer aUserInAServer) {
|
||||
return guild.getMemberById(aUserInAServer.getUserReference().getId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getMemberInServer(AUserInAServer aUserInAServer) {
|
||||
return getMemberInServer(aUserInAServer.getServerReference().getId(), aUserInAServer.getUserReference().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Member> getMemberInServerAsync(AUserInAServer aUserInAServer) {
|
||||
return getMemberInServerAsync(aUserInAServer.getServerReference().getId(), aUserInAServer.getUserReference().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getMemberInServer(AServer server, AUser member) {
|
||||
return getMemberInServer(server.getId(), member.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Member> forceReloadMember(Member member) {
|
||||
return member.getGuild().retrieveMember(member.getUser()).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getBotInGuild(AServer server) {
|
||||
Guild guild = guildService.getGuildById(server.getId());
|
||||
return guild.getSelfMember();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<User> getUserViaId(Long userId) {
|
||||
return botService.getInstance().retrieveUserById(userId).submit();
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,9 @@ import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
@@ -21,7 +23,10 @@ import java.util.concurrent.CompletableFuture;
|
||||
public class MessageCacheBean implements MessageCache {
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
@@ -66,13 +71,13 @@ public class MessageCacheBean implements MessageCache {
|
||||
@Override
|
||||
public CompletableFuture<CachedMessage> loadMessage(Long guildId, Long textChannelId, Long messageId) {
|
||||
CompletableFuture<CachedMessage> future = new CompletableFuture<>();
|
||||
Optional<Guild> guildOptional = botService.getGuildByIdOptional(guildId);
|
||||
Optional<Guild> guildOptional = guildService.getGuildByIdOptional(guildId);
|
||||
if(guildOptional.isPresent()) {
|
||||
Optional<TextChannel> textChannelByIdOptional = botService.getTextChannelFromServerOptional(guildOptional.get(), textChannelId);
|
||||
Optional<TextChannel> textChannelByIdOptional = channelService.getTextChannelFromServerOptional(guildOptional.get(), textChannelId);
|
||||
if(textChannelByIdOptional.isPresent()) {
|
||||
TextChannel textChannel = textChannelByIdOptional.get();
|
||||
textChannel.retrieveMessageById(messageId).queue(message ->
|
||||
|
||||
channelService.retrieveMessageInChannel(textChannel, messageId)
|
||||
.thenAccept(message ->
|
||||
cacheEntityService.buildCachedMessageFromMessage(message)
|
||||
.thenAccept(future::complete)
|
||||
.exceptionally(throwable -> {
|
||||
@@ -80,8 +85,7 @@ public class MessageCacheBean implements MessageCache {
|
||||
future.completeExceptionally(throwable);
|
||||
return null;
|
||||
})
|
||||
|
||||
);
|
||||
);
|
||||
} else {
|
||||
log.error("Not able to load message {} in channel {} in guild {}. Text channel not found.", messageId, textChannelId, guildId);
|
||||
future.completeExceptionally(new ChannelNotInGuildException(textChannelId));
|
||||
|
||||
@@ -1,253 +1,73 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.ConfiguredEmoteNotUsableException;
|
||||
import dev.sheldan.abstracto.core.exception.EmoteNotInServerException;
|
||||
import dev.sheldan.abstracto.core.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.requests.restaction.AuditableRestAction;
|
||||
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static dev.sheldan.abstracto.core.config.MetricConstants.DISCORD_API_INTERACTION_METRIC;
|
||||
import static dev.sheldan.abstracto.core.config.MetricConstants.INTERACTION_TYPE;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MessageServiceBean implements MessageService {
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private EmoteManagementService emoteManagementService;
|
||||
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private MessageServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Override
|
||||
public void addReactionToMessage(String emoteKey, Long serverId, Message message) {
|
||||
addReactionToMessageWithFuture(emoteKey, serverId, message);
|
||||
}
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Override
|
||||
public void addDefaultReactionToMessage(String unicode, Message message) {
|
||||
addDefaultReactionToMessageAsync(unicode, message);
|
||||
}
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addDefaultReactionToMessageAsync(String unicode, Message message) {
|
||||
return message.addReaction(unicode).submit();
|
||||
}
|
||||
public static final CounterMetric MESSAGE_SEND_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "message.send")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addDefaultReactionToMessageAsync(String unicode, Long serverId, Long channelId, Long messageId) {
|
||||
TextChannel channel = botService.getTextChannelFromServer(serverId, channelId);
|
||||
return channel.retrieveMessageById(messageId).submit()
|
||||
.thenCompose(message -> self.addDefaultReactionToMessageAsync(unicode, message));
|
||||
}
|
||||
public static final CounterMetric MESSAGE_EDIT_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "message.edit")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageWithFuture(String emoteKey, Long serverId, Message message) {
|
||||
Guild guild = botService.getGuildById(serverId);
|
||||
return addReactionToMessageWithFuture(emoteKey, guild, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageWithFuture(String emoteKey, Guild guild, Message message) {
|
||||
AEmote emote = emoteService.getEmoteOrDefaultEmote(emoteKey, guild.getIdLong());
|
||||
return addReactionToMessageWithFuture(emote, guild, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageWithFuture(AEmote emote, Long serverId, Message message) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
return addReactionToMessageWithFuture(emote.getEmoteId(), serverId, message);
|
||||
} else {
|
||||
return message.addReaction(emote.getEmoteKey()).submit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageWithFuture(AEmote emote, Guild guild, Message message) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
|
||||
if(emoteById != null) {
|
||||
log.trace("Adding custom emote {} as reaction to message {}.", emoteById.getId(), message.getId());
|
||||
return message.addReaction(emoteById).submit();
|
||||
} else {
|
||||
log.error("Emote with key {} and id {} for guild {} was not found.", emote.getName() , emote.getEmoteId(), guild.getId());
|
||||
throw new ConfiguredEmoteNotUsableException(emote);
|
||||
}
|
||||
} else {
|
||||
log.trace("Adding default emote {} as reaction to message {}.", emote.getEmoteKey(), message.getId());
|
||||
return message.addReaction(emote.getEmoteKey()).submit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageWithFuture(Long emoteId, Long serverId, Message message) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emoteId);
|
||||
if(emoteById == null) {
|
||||
throw new EmoteNotInServerException(emoteId);
|
||||
}
|
||||
return message.addReaction(emoteById).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageWithFuture(String emoteKey, Long serverId, Long channelId, Long messageId) {
|
||||
TextChannel channel = botService.getTextChannelFromServer(serverId, channelId);
|
||||
return channel.retrieveMessageById(messageId).submit()
|
||||
.thenCompose(message -> self.addReactionToMessageWithFuture(emoteKey, serverId, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionFromMessageWithFuture(AEmote emote, Message message) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
|
||||
if(emoteById == null) {
|
||||
throw new EmoteNotInServerException(emote.getEmoteId());
|
||||
}
|
||||
log.trace("Removing single custom reaction for emote {} on message {}.", emoteById.getId(), message.getId());
|
||||
return message.removeReaction(emoteById).submit();
|
||||
} else {
|
||||
log.trace("Removing single default emote {} reaction from message {}.", emote.getEmoteKey(), message.getId());
|
||||
return message.removeReaction(emote.getEmoteKey()).submit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> clearReactionFromMessageWithFuture(AEmote emote, Message message) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
|
||||
if(emoteById == null) {
|
||||
throw new EmoteNotInServerException(emote.getEmoteId());
|
||||
}
|
||||
log.trace("Clearing reactions for custom emote {} on message {}.", emoteById.getId(), message.getId());
|
||||
return message.clearReactions(emoteById).submit();
|
||||
} else {
|
||||
log.trace("Clearing reactions for default emote {} on message {}.", emote.getEmoteKey(), message.getId());
|
||||
return message.clearReactions(emote.getEmoteKey()).submit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionFromMessageWithFuture(Integer emoteId, Message message) {
|
||||
AEmote emote = emoteManagementService.loadEmote(emoteId);
|
||||
return removeReactionFromMessageWithFuture(emote, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> clearReactionFromMessageWithFuture(Integer emoteId, Message message) {
|
||||
AEmote emote = emoteManagementService.loadEmote(emoteId);
|
||||
return clearReactionFromMessageWithFuture(emote, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId) {
|
||||
TextChannel channel = botService.getTextChannelFromServer(serverId, channelId);
|
||||
Integer emoteId = emote.getId();
|
||||
return channel.retrieveMessageById(messageId).submit()
|
||||
.thenCompose(message -> self.removeReactionFromMessageWithFuture(emoteId, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId, Long userId) {
|
||||
Guild guild = botService.getGuildById(serverId);
|
||||
Integer emoteId = emote.getId();
|
||||
TextChannel textChannel = botService.getTextChannelFromServer(serverId, channelId);
|
||||
CompletableFuture<Member> memberFuture = guild.retrieveMemberById(userId).submit();
|
||||
CompletableFuture<Message> messageFuture = textChannel.retrieveMessageById(messageId).submit();
|
||||
|
||||
return CompletableFuture.allOf(memberFuture, messageFuture).thenCompose(aVoid ->
|
||||
memberFuture.thenCompose(member ->
|
||||
self.removeReactionOfUserFromMessageWithFuture(emoteId, messageFuture.join(), memberFuture.join())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId, Member member) {
|
||||
TextChannel channel = botService.getTextChannelFromServer(serverId, channelId);
|
||||
Integer emoteId = emote.getId();
|
||||
return channel.retrieveMessageById(messageId).submit()
|
||||
.thenCompose(message -> self.removeReactionOfUserFromMessageWithFuture(emoteId, message, member));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Message message, Member member) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
|
||||
if(emoteById == null) {
|
||||
throw new EmoteNotInServerException(emote.getEmoteId());
|
||||
}
|
||||
log.trace("Removing reaction for custom emote {} from user {} on message {}.", emoteById.getId(), member.getId(), member.getId());
|
||||
return message.removeReaction(emoteById, member.getUser()).submit();
|
||||
} else {
|
||||
log.trace("Removing reaction for default emote {} from user {} on message {}.", emote.getEmoteKey(), member.getId(), member.getId());
|
||||
return message.removeReaction(emote.getEmoteKey(), member.getUser()).submit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(Integer emoteId, Message message, Member member) {
|
||||
AEmote emote = emoteManagementService.loadEmote(emoteId);
|
||||
return removeReactionOfUserFromMessageWithFuture(emote, message, member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Message message, Long userId) {
|
||||
Integer emoteId = emote.getId();
|
||||
return message.getGuild().retrieveMemberById(userId).submit().thenCompose(member ->
|
||||
self.removeReactionOfUserFromMessageWithFuture(emoteId, message, member)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(Integer emoteId, Message message, Long userId) {
|
||||
return message.getGuild().retrieveMemberById(userId).submit().thenCompose(member ->
|
||||
self.removeReactionOfUserFromMessageWithFuture(emoteId, message, member)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> clearReactionFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId) {
|
||||
TextChannel channel = botService.getTextChannelFromServer(serverId, channelId);
|
||||
Integer emoteId = emote.getId();
|
||||
return channel.retrieveMessageById(messageId).submit()
|
||||
.thenCompose(message1 -> clearReactionFromMessageWithFuture(emoteId, message1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Void>> addReactionsToMessageWithFuture(List<String> emoteKeys, Long serverId, Message message) {
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
emoteKeys.forEach(s -> futures.add(addReactionToMessageWithFuture(s, serverId, message)));
|
||||
return futures;
|
||||
}
|
||||
public static final CounterMetric MESSAGE_LOAD_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "message.load")))
|
||||
.build();
|
||||
|
||||
public static final CounterMetric MESSAGE_DELETE_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "message.delete")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteMessageInChannelInServer(Long serverId, Long channelId, Long messageId) {
|
||||
return botService.deleteMessage(serverId, channelId, messageId);
|
||||
metricService.incrementCounter(MESSAGE_DELETE_METRIC);
|
||||
return channelService.getTextChannelFromServer(serverId, channelId).deleteMessageById(messageId).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -277,7 +97,7 @@ public class MessageServiceBean implements MessageService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> sendMessageToUser(AUserInAServer userInAServer, String text) {
|
||||
return botService.getMemberInServerAsync(userInAServer).thenCompose(member ->
|
||||
return memberService.getMemberInServerAsync(userInAServer).thenCompose(member ->
|
||||
sendMessageToUser(member.getUser(), text)
|
||||
);
|
||||
}
|
||||
@@ -285,7 +105,7 @@ public class MessageServiceBean implements MessageService {
|
||||
@Override
|
||||
public CompletableFuture<Message> sendSimpleTemplateToUser(Long userId, String templateKey) {
|
||||
String text = templateService.renderSimpleTemplate(templateKey);
|
||||
return botService.getUserViaId(userId)
|
||||
return memberService.getUserViaId(userId)
|
||||
.thenCompose(this::openPrivateChannelForUser)
|
||||
.thenCompose(o -> channelService.sendTextToChannel(text, o));
|
||||
}
|
||||
@@ -343,6 +163,32 @@ public class MessageServiceBean implements MessageService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> loadMessage(Long serverId, Long channelId, Long messageId) {
|
||||
return channelService.getTextChannel(serverId, channelId).retrieveMessageById(messageId).submit();
|
||||
return channelService.retrieveMessageInChannel(serverId, channelId, messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageAction editMessage(Message message, MessageEmbed messageEmbed) {
|
||||
metricService.incrementCounter(MESSAGE_EDIT_METRIC);
|
||||
return message.editMessage(messageEmbed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageAction editMessage(Message message, String text, MessageEmbed messageEmbed) {
|
||||
metricService.incrementCounter(MESSAGE_EDIT_METRIC);
|
||||
return message.editMessage(text).embed(messageEmbed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuditableRestAction<Void> deleteMessage(Message message) {
|
||||
metricService.incrementCounter(MESSAGE_DELETE_METRIC);
|
||||
return message.delete();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(MESSAGE_SEND_METRIC, "Messages send to discord");
|
||||
metricService.registerCounter(MESSAGE_EDIT_METRIC, "Messages edited in discord");
|
||||
metricService.registerCounter(MESSAGE_LOAD_METRIC, "Messages loaded from discord");
|
||||
metricService.registerCounter(MESSAGE_DELETE_METRIC, "Messages deleted from discord");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ public class PaginatorServiceBean implements PaginatorService {
|
||||
@Autowired
|
||||
private Gson gson;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Override
|
||||
public Paginator createPaginatorFromTemplate(String templateKey, Object model, EventWaiter waiter) {
|
||||
@@ -42,7 +44,7 @@ public class PaginatorServiceBean implements PaginatorService {
|
||||
.setEventWaiter(waiter)
|
||||
.waitOnSinglePage(true)
|
||||
.setTimeout(ObjectUtils.defaultIfNull(configuration.getTimeoutSeconds(), 120L), TimeUnit.SECONDS)
|
||||
.setFinalAction(message -> message.delete().queue())
|
||||
.setFinalAction(message -> messageService.deleteMessage(message))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,14 @@ package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import dev.sheldan.abstracto.core.exception.*;
|
||||
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||
import dev.sheldan.abstracto.core.exception.PostTargetNotFoundException;
|
||||
import dev.sheldan.abstracto.core.exception.PostTargetNotValidException;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultPostTargetManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
|
||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
@@ -45,6 +48,9 @@ public class PostTargetServiceBean implements PostTargetService {
|
||||
@Autowired
|
||||
private DefaultPostTargetManagementService defaultPostTargetManagementService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> sendTextInPostTarget(String text, PostTarget target) {
|
||||
log.trace("Sending text to post target {}.", target.getName());
|
||||
@@ -55,7 +61,7 @@ public class PostTargetServiceBean implements PostTargetService {
|
||||
public CompletableFuture<Message> sendEmbedInPostTarget(MessageEmbed embed, PostTarget target) {
|
||||
TextChannel textChannelForPostTarget = getTextChannelForPostTarget(target);
|
||||
log.trace("Sending message embed to post target {}.", target.getName());
|
||||
return textChannelForPostTarget.sendMessage(embed).submit();
|
||||
return channelService.sendEmbedToChannel(embed, textChannelForPostTarget);
|
||||
}
|
||||
|
||||
private TextChannel getTextChannelForPostTarget(PostTarget target) {
|
||||
@@ -127,10 +133,10 @@ public class PostTargetServiceBean implements PostTargetService {
|
||||
String messageText = message.getMessage();
|
||||
if(StringUtils.isBlank(messageText)) {
|
||||
log.trace("Editing embeds of message {} in post target {}.", messageId, target.getName());
|
||||
return Arrays.asList(textChannelForPostTarget.editMessageById(messageId, message.getEmbeds().get(0)).submit());
|
||||
return Arrays.asList(channelService.editEmbedMessageInAChannel(message.getEmbeds().get(0), textChannelForPostTarget, messageId));
|
||||
} else {
|
||||
log.trace("Editing message text and potentially text for message {} in post target {}.", messageId, target.getName());
|
||||
return Arrays.asList(textChannelForPostTarget.editMessageById(messageId, messageText).embed(message.getEmbeds().get(0)).submit());
|
||||
return Arrays.asList(channelService.editTextMessageInAChannel(messageText, message.getEmbeds().get(0), textChannelForPostTarget, messageId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,48 +147,39 @@ public class PostTargetServiceBean implements PostTargetService {
|
||||
CompletableFuture<Message> messageEditFuture = new CompletableFuture<>();
|
||||
futures.add(messageEditFuture);
|
||||
if(StringUtils.isBlank(messageToSend.getMessage().trim())) {
|
||||
textChannelForPostTarget
|
||||
.retrieveMessageById(messageId)
|
||||
.queue(
|
||||
existingMessage -> {
|
||||
log.trace("Editing existing message {} when upserting message embeds in channel {} in server {}.",
|
||||
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
||||
existingMessage
|
||||
.editMessage(messageToSend.getEmbeds().get(0))
|
||||
.queue(messageEditFuture::complete, messageEditFuture::completeExceptionally);
|
||||
},
|
||||
throwable -> {
|
||||
log.trace("Creating new message when upserting message embeds for message {} in channel {} in server {}.",
|
||||
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
||||
sendEmbedInPostTarget(messageToSend, target).get(0)
|
||||
.thenAccept(messageEditFuture::complete).exceptionally(innerThrowable -> {
|
||||
log.error("Failed to send message to create a message.", innerThrowable);
|
||||
messageEditFuture.completeExceptionally(innerThrowable);
|
||||
return null;
|
||||
});
|
||||
});
|
||||
channelService.retrieveMessageInChannel(textChannelForPostTarget, messageId).thenAccept(message -> {
|
||||
log.trace("Editing existing message {} when upserting message embeds in channel {} in server {}.",
|
||||
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
||||
messageService.editMessage(message, messageToSend.getEmbeds().get(0))
|
||||
.queue(messageEditFuture::complete, messageEditFuture::completeExceptionally);
|
||||
}).exceptionally(throwable -> {
|
||||
log.trace("Creating new message when upserting message embeds for message {} in channel {} in server {}.",
|
||||
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
||||
sendEmbedInPostTarget(messageToSend, target).get(0)
|
||||
.thenAccept(messageEditFuture::complete).exceptionally(innerThrowable -> {
|
||||
log.error("Failed to send message to create a message.", innerThrowable);
|
||||
messageEditFuture.completeExceptionally(innerThrowable);
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
textChannelForPostTarget
|
||||
.retrieveMessageById(messageId)
|
||||
.queue(
|
||||
existingMessage -> {
|
||||
log.trace("Editing existing message {} when upserting message in channel {} in server {}.",
|
||||
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
||||
existingMessage
|
||||
.editMessage(messageToSend.getMessage())
|
||||
.embed(messageToSend.getEmbeds().get(0))
|
||||
.queue(messageEditFuture::complete, messageEditFuture::completeExceptionally);
|
||||
},
|
||||
throwable -> {
|
||||
log.trace("Creating new message when trying to upsert a message {} in channel {} in server {}.",
|
||||
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
||||
sendEmbedInPostTarget(messageToSend, target).get(0)
|
||||
.thenAccept(messageEditFuture::complete).exceptionally(innerThrowable -> {
|
||||
log.error("Failed to send message to create a message.", innerThrowable);
|
||||
messageEditFuture.completeExceptionally(innerThrowable);
|
||||
return null;
|
||||
});
|
||||
});
|
||||
channelService.retrieveMessageInChannel(textChannelForPostTarget, messageId).thenAccept(message -> {
|
||||
log.trace("Editing existing message {} when upserting message in channel {} in server {}.",
|
||||
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
||||
messageService.editMessage(message, messageToSend.getMessage(), messageToSend.getEmbeds().get(0))
|
||||
.queue(messageEditFuture::complete, messageEditFuture::completeExceptionally);
|
||||
}).exceptionally(throwable -> {
|
||||
log.trace("Creating new message when trying to upsert a message {} in channel {} in server {}.",
|
||||
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
||||
sendEmbedInPostTarget(messageToSend, target).get(0)
|
||||
.thenAccept(messageEditFuture::complete).exceptionally(innerThrowable -> {
|
||||
log.error("Failed to send message to create a message.", innerThrowable);
|
||||
messageEditFuture.completeExceptionally(innerThrowable);
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
return futures;
|
||||
|
||||
@@ -1,14 +1,31 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.ConfiguredEmoteNotUsableException;
|
||||
import dev.sheldan.abstracto.core.exception.EmoteNotInServerException;
|
||||
import dev.sheldan.abstracto.core.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedReaction;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static dev.sheldan.abstracto.core.config.MetricConstants.DISCORD_API_INTERACTION_METRIC;
|
||||
import static dev.sheldan.abstracto.core.config.MetricConstants.INTERACTION_TYPE;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ReactionServiceBean implements ReactionService {
|
||||
|
||||
@Autowired
|
||||
@@ -17,9 +34,45 @@ public class ReactionServiceBean implements ReactionService {
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private EmoteManagementService emoteManagementService;
|
||||
|
||||
@Autowired
|
||||
private ReactionService self;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
public static final CounterMetric REACTION_ADDED_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "reaction.added")))
|
||||
.build();
|
||||
|
||||
public static final CounterMetric REACTION_REMOVED_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "reaction.removed")))
|
||||
.build();
|
||||
|
||||
public static final CounterMetric REACTION_CLEARED_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "reaction.cleared")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionFromMessage(CachedReaction reaction, CachedMessage cachedMessage) {
|
||||
return messageService.loadMessageFromCachedMessage(cachedMessage).thenCompose(message -> removeReactionFromMessage(reaction, message));
|
||||
@@ -27,14 +80,257 @@ public class ReactionServiceBean implements ReactionService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionFromMessage(CachedReaction reaction, Message message) {
|
||||
return botService.retrieveUserById(reaction.getUser().getUserId()).thenCompose(user -> {
|
||||
return memberService.retrieveUserById(reaction.getUser().getUserId()).thenCompose(user -> {
|
||||
if(reaction.getEmote().getCustom()) {
|
||||
return emoteService.getEmoteFromCachedEmote(reaction.getEmote()).thenCompose(emote ->
|
||||
message.removeReaction(emote, user).submit()
|
||||
removeReaction(message, emote, user)
|
||||
);
|
||||
} else {
|
||||
return message.removeReaction(reaction.getEmote().getEmoteName(), user).submit();
|
||||
return removeReaction(message, reaction.getEmote().getEmoteName(), user);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addReactionToMessage(String emoteKey, Long serverId, Message message) {
|
||||
addReactionToMessageAsync(emoteKey, serverId, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDefaultReactionToMessage(String unicode, Message message) {
|
||||
addDefaultReactionToMessageAsync(unicode, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addDefaultReactionToMessageAsync(String unicode, Message message) {
|
||||
metricService.incrementCounter(REACTION_ADDED_METRIC);
|
||||
return message.addReaction(unicode).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addDefaultReactionToMessageAsync(String unicode, Long serverId, Long channelId, Long messageId) {
|
||||
return channelService.retrieveMessageInChannel(serverId, channelId, messageId)
|
||||
.thenCompose(message -> self.addDefaultReactionToMessageAsync(unicode, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageAsync(String emoteKey, Long serverId, Message message) {
|
||||
Guild guild = guildService.getGuildById(serverId);
|
||||
return addReactionToMessageAsync(emoteKey, guild, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageAsync(String emoteKey, Guild guild, Message message) {
|
||||
AEmote emote = emoteService.getEmoteOrDefaultEmote(emoteKey, guild.getIdLong());
|
||||
return addReactionToMessageAsync(emote, guild, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageAsync(AEmote emote, Long serverId, Message message) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
return addReactionToMessageAsync(emote.getEmoteId(), serverId, message);
|
||||
} else {
|
||||
return addDefaultReactionToMessageAsync(emote.getEmoteKey(), message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageAsync(AEmote emote, Guild guild, Message message) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
|
||||
if(emoteById != null) {
|
||||
log.trace("Adding custom emote {} as reaction to message {}.", emoteById.getId(), message.getId());
|
||||
return addReactionToMessageAsync(emoteById, message);
|
||||
} else {
|
||||
log.error("Emote with key {} and id {} for guild {} was not found.", emote.getName() , emote.getEmoteId(), guild.getId());
|
||||
throw new ConfiguredEmoteNotUsableException(emote);
|
||||
}
|
||||
} else {
|
||||
log.trace("Adding default emote {} as reaction to message {}.", emote.getEmoteKey(), message.getId());
|
||||
return addDefaultReactionToMessageAsync(emote.getEmoteKey(), message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageAsync(Emote emote, Message message) {
|
||||
metricService.incrementCounter(REACTION_ADDED_METRIC);
|
||||
return message.addReaction(emote).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageAsync(Long emoteId, Long serverId, Message message) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emoteId);
|
||||
if(emoteById == null) {
|
||||
throw new EmoteNotInServerException(emoteId);
|
||||
}
|
||||
return addReactionToMessageAsync(emoteById, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addReactionToMessageAsync(String emoteKey, Long serverId, Long channelId, Long messageId) {
|
||||
return channelService.retrieveMessageInChannel(serverId, channelId, messageId)
|
||||
.thenCompose(message -> self.addReactionToMessageAsync(emoteKey, serverId, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionFromMessageWithFuture(AEmote emote, Message message) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
|
||||
if(emoteById == null) {
|
||||
throw new EmoteNotInServerException(emote.getEmoteId());
|
||||
}
|
||||
log.trace("Removing single custom reaction for emote {} on message {}.", emoteById.getId(), message.getId());
|
||||
return removeReaction(message, emoteById);
|
||||
} else {
|
||||
log.trace("Removing single default emote {} reaction from message {}.", emote.getEmoteKey(), message.getId());
|
||||
return removeReaction(message, emote.getEmoteKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReaction(Message message, String key) {
|
||||
metricService.incrementCounter(REACTION_REMOVED_METRIC);
|
||||
return message.removeReaction(key).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReaction(Message message, String key, User user) {
|
||||
metricService.incrementCounter(REACTION_REMOVED_METRIC);
|
||||
return message.removeReaction(key, user).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReaction(Message message, Emote emoteById) {
|
||||
metricService.incrementCounter(REACTION_REMOVED_METRIC);
|
||||
return message.removeReaction(emoteById).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReaction(Message message, Emote emoteById, User user) {
|
||||
metricService.incrementCounter(REACTION_REMOVED_METRIC);
|
||||
return message.removeReaction(emoteById, user).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> clearReactionFromMessageWithFuture(AEmote emote, Message message) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
|
||||
if(emoteById == null) {
|
||||
throw new EmoteNotInServerException(emote.getEmoteId());
|
||||
}
|
||||
log.trace("Clearing reactions for custom emote {} on message {}.", emoteById.getId(), message.getId());
|
||||
return clearReaction(message, emoteById);
|
||||
} else {
|
||||
log.trace("Clearing reactions for default emote {} on message {}.", emote.getEmoteKey(), message.getId());
|
||||
return clearReaction(message, emote.getEmoteKey());
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> clearReaction(Message message, String key) {
|
||||
metricService.incrementCounter(REACTION_CLEARED_METRIC);
|
||||
return message.clearReactions(key).submit();
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> clearReaction(Message message, Emote emoteById) {
|
||||
metricService.incrementCounter(REACTION_CLEARED_METRIC);
|
||||
return message.clearReactions(emoteById).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionFromMessageWithFuture(Integer emoteId, Message message) {
|
||||
AEmote emote = emoteManagementService.loadEmote(emoteId);
|
||||
return removeReactionFromMessageWithFuture(emote, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> clearReactionFromMessageWithFuture(Integer emoteId, Message message) {
|
||||
AEmote emote = emoteManagementService.loadEmote(emoteId);
|
||||
return clearReactionFromMessageWithFuture(emote, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId) {
|
||||
Integer emoteId = emote.getId();
|
||||
return channelService.retrieveMessageInChannel(serverId, channelId, messageId)
|
||||
.thenCompose(message -> self.removeReactionFromMessageWithFuture(emoteId, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId, Long userId) {
|
||||
Guild guild = guildService.getGuildById(serverId);
|
||||
Integer emoteId = emote.getId();
|
||||
CompletableFuture<Member> memberFuture = guild.retrieveMemberById(userId).submit();
|
||||
CompletableFuture<Message> messageFuture = channelService.retrieveMessageInChannel(serverId, channelId, messageId);
|
||||
|
||||
return CompletableFuture.allOf(memberFuture, messageFuture).thenCompose(aVoid ->
|
||||
memberFuture.thenCompose(member ->
|
||||
self.removeReactionOfUserFromMessageWithFuture(emoteId, messageFuture.join(), memberFuture.join())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId, Member member) {
|
||||
Integer emoteId = emote.getId();
|
||||
return channelService.retrieveMessageInChannel(serverId, channelId, messageId)
|
||||
.thenCompose(message -> self.removeReactionOfUserFromMessageWithFuture(emoteId, message, member));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Message message, Member member) {
|
||||
if(Boolean.TRUE.equals(emote.getCustom())) {
|
||||
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
|
||||
if(emoteById == null) {
|
||||
throw new EmoteNotInServerException(emote.getEmoteId());
|
||||
}
|
||||
log.trace("Removing reaction for custom emote {} from user {} on message {}.", emoteById.getId(), member.getId(), member.getId());
|
||||
return removeReaction(message, emoteById, member.getUser());
|
||||
} else {
|
||||
log.trace("Removing reaction for default emote {} from user {} on message {}.", emote.getEmoteKey(), member.getId(), member.getId());
|
||||
return removeReaction(message, emote.getEmoteKey(), member.getUser());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(Integer emoteId, Message message, Member member) {
|
||||
AEmote emote = emoteManagementService.loadEmote(emoteId);
|
||||
return removeReactionOfUserFromMessageWithFuture(emote, message, member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Message message, Long userId) {
|
||||
Integer emoteId = emote.getId();
|
||||
return message.getGuild().retrieveMemberById(userId).submit().thenCompose(member ->
|
||||
self.removeReactionOfUserFromMessageWithFuture(emoteId, message, member)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(Integer emoteId, Message message, Long userId) {
|
||||
return message.getGuild().retrieveMemberById(userId).submit().thenCompose(member ->
|
||||
self.removeReactionOfUserFromMessageWithFuture(emoteId, message, member)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> clearReactionFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId) {
|
||||
Integer emoteId = emote.getId();
|
||||
return channelService.retrieveMessageInChannel(serverId, channelId, messageId)
|
||||
.thenCompose(message1 -> clearReactionFromMessageWithFuture(emoteId, message1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Void>> addReactionsToMessageWithFuture(List<String> emoteKeys, Long serverId, Message message) {
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
emoteKeys.forEach(s -> futures.add(addReactionToMessageAsync(s, serverId, message)));
|
||||
return futures;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(REACTION_ADDED_METRIC, "Reactions added");
|
||||
metricService.registerCounter(REACTION_REMOVED_METRIC, "Reactions removed");
|
||||
metricService.registerCounter(REACTION_CLEARED_METRIC, "Reactions cleared");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||
import dev.sheldan.abstracto.core.exception.RoleDeletedException;
|
||||
import dev.sheldan.abstracto.core.exception.RoleNotFoundInDBException;
|
||||
import dev.sheldan.abstracto.core.exception.RoleNotFoundInGuildException;
|
||||
import dev.sheldan.abstracto.core.metrics.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
@@ -15,24 +18,45 @@ import net.dv8tion.jda.api.entities.Role;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.sheldan.abstracto.core.config.MetricConstants.DISCORD_API_INTERACTION_METRIC;
|
||||
import static dev.sheldan.abstracto.core.config.MetricConstants.INTERACTION_TYPE;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RoleServiceBean implements RoleService {
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
public static final CounterMetric ROLE_ASSIGNED_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "role.assigned")))
|
||||
.build();
|
||||
|
||||
|
||||
public static final CounterMetric ROLE_REMOVED_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(INTERACTION_TYPE, "role.removed")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void addRoleToUser(AUserInAServer aUserInAServer, ARole role) {
|
||||
Optional<Guild> guildById = botService.getGuildByIdOptional(aUserInAServer.getServerReference().getId());
|
||||
Optional<Guild> guildById = guildService.getGuildByIdOptional(aUserInAServer.getServerReference().getId());
|
||||
if(guildById.isPresent()) {
|
||||
addRoleToUser(guildById.get(), role, aUserInAServer.getUserReference().getId());
|
||||
} else {
|
||||
@@ -42,9 +66,9 @@ public class RoleServiceBean implements RoleService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addRoleToUserFuture(AUserInAServer aUserInAServer, ARole role) {
|
||||
Optional<Guild> guildById = botService.getGuildByIdOptional(aUserInAServer.getServerReference().getId());
|
||||
Optional<Guild> guildById = guildService.getGuildByIdOptional(aUserInAServer.getServerReference().getId());
|
||||
if(guildById.isPresent()) {
|
||||
return addRoleToUserFuture(guildById.get(), role, aUserInAServer.getUserReference().getId());
|
||||
return addRoleToUserFuture(guildById.get(), aUserInAServer.getUserReference().getId(), role);
|
||||
} else {
|
||||
throw new GuildNotFoundException(aUserInAServer.getServerReference().getId());
|
||||
}
|
||||
@@ -56,7 +80,7 @@ public class RoleServiceBean implements RoleService {
|
||||
if(role == null) {
|
||||
throw new RoleNotFoundInGuildException(roleId, member.getGuild().getIdLong());
|
||||
}
|
||||
return member.getGuild().addRoleToMember(member, role).submit();
|
||||
return addRoleToUser(member.getGuild(), member.getIdLong(), role);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +114,7 @@ public class RoleServiceBean implements RoleService {
|
||||
return member.getGuild().removeRoleFromMember(member, role).submit();
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> addRoleToUserFuture(Guild guild, ARole role, Long userId) {
|
||||
private CompletableFuture<Void> addRoleToUserFuture(Guild guild, Long userId, ARole role) {
|
||||
if(role.getDeleted()) {
|
||||
log.warn("Not possible to add role to user. Role {} was marked as deleted.", role.getId());
|
||||
throw new RoleDeletedException(role);
|
||||
@@ -98,15 +122,27 @@ public class RoleServiceBean implements RoleService {
|
||||
Role roleById = guild.getRoleById(role.getId());
|
||||
if(roleById != null) {
|
||||
log.info("Adding role {} to user {} in server {}.", role.getId(), userId, guild.getId());
|
||||
return guild.addRoleToMember(userId, roleById).submit();
|
||||
return addRoleToUser(guild, userId, roleById);
|
||||
} else {
|
||||
throw new RoleNotFoundInGuildException(role.getId(), guild.getIdLong());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addRoleToUser(Guild guild, Long userId, Role roleById) {
|
||||
metricService.incrementCounter(ROLE_ASSIGNED_METRIC);
|
||||
return guild.addRoleToMember(userId, roleById).submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeRoleFromUser(Guild guild, Long userId, Role roleById) {
|
||||
metricService.incrementCounter(ROLE_REMOVED_METRIC);
|
||||
return guild.removeRoleFromMember(userId, roleById).submit();
|
||||
}
|
||||
|
||||
|
||||
private void addRoleToUser(Guild guild, ARole role, Long userId) {
|
||||
addRoleToUserFuture(guild, role, userId);
|
||||
addRoleToUserFuture(guild, userId, role);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> removeRoleFromUserFuture(Guild guild, ARole role, Long userId) {
|
||||
@@ -117,7 +153,7 @@ public class RoleServiceBean implements RoleService {
|
||||
Role roleById = guild.getRoleById(role.getId());
|
||||
if(roleById != null) {
|
||||
log.info("Removing role {} from user {} in server {}.", role.getId(), userId, guild.getId());
|
||||
return guild.removeRoleFromMember(userId, roleById).submit();
|
||||
return removeRoleFromUser(guild, userId, roleById);
|
||||
} else {
|
||||
throw new RoleNotFoundInGuildException(role.getId(), guild.getIdLong());
|
||||
}
|
||||
@@ -130,7 +166,7 @@ public class RoleServiceBean implements RoleService {
|
||||
|
||||
@Override
|
||||
public void removeRoleFromUser(AUserInAServer aUserInAServer, ARole role) {
|
||||
Optional<Guild> guildById = botService.getGuildByIdOptional(aUserInAServer.getServerReference().getId());
|
||||
Optional<Guild> guildById = guildService.getGuildByIdOptional(aUserInAServer.getServerReference().getId());
|
||||
if(guildById.isPresent()) {
|
||||
removeRoleFromUser(guildById.get(), role, aUserInAServer.getUserReference().getId());
|
||||
} else {
|
||||
@@ -140,7 +176,7 @@ public class RoleServiceBean implements RoleService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> removeRoleFromUserFuture(AUserInAServer aUserInAServer, ARole role) {
|
||||
Optional<Guild> guildById = botService.getGuildByIdOptional(aUserInAServer.getServerReference().getId());
|
||||
Optional<Guild> guildById = guildService.getGuildByIdOptional(aUserInAServer.getServerReference().getId());
|
||||
if(guildById.isPresent()) {
|
||||
return removeRoleFromUserFuture(guildById.get(), role, aUserInAServer.getUserReference().getId());
|
||||
} else {
|
||||
@@ -166,7 +202,7 @@ public class RoleServiceBean implements RoleService {
|
||||
log.warn("Trying to load role {} which is marked as deleted.", role.getId());
|
||||
throw new RoleDeletedException(role);
|
||||
}
|
||||
Optional<Guild> guildById = botService.getGuildByIdOptional(role.getServer().getId());
|
||||
Optional<Guild> guildById = guildService.getGuildByIdOptional(role.getServer().getId());
|
||||
if(guildById.isPresent()) {
|
||||
log.trace("Loading role {} from server {}.", role.getId(), role.getServer().getId());
|
||||
return guildById.get().getRoleById(role.getId());
|
||||
@@ -227,4 +263,10 @@ public class RoleServiceBean implements RoleService {
|
||||
.server(server)
|
||||
.build();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(ROLE_ASSIGNED_METRIC, "Amount of roles assigned");
|
||||
metricService.registerCounter(ROLE_REMOVED_METRIC, "Amount of roles removed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.ServerConfigListener;
|
||||
import dev.sheldan.abstracto.core.utils.SnowflakeUtils;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelType;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.SnowflakeUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
@@ -18,9 +18,10 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import org.apache.commons.collections4.SetUtils;
|
||||
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 javax.security.auth.login.LoginException;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -55,7 +56,7 @@ public class StartupServiceBean implements Startup {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Transactional(isolation = Isolation.SERIALIZABLE)
|
||||
public void synchronize() {
|
||||
log.info("Synchronizing servers.");
|
||||
synchronizeServers();
|
||||
|
||||
@@ -21,6 +21,9 @@ public class UndoActionServiceBean implements UndoActionService {
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Override
|
||||
public void performActions(List<UndoActionInstance> actionsToPerform) {
|
||||
performActionsFuture(actionsToPerform);
|
||||
@@ -41,12 +44,12 @@ public class UndoActionServiceBean implements UndoActionService {
|
||||
log.info("Deleting channel {} in guild {} because of an UNDO action.", ids.get(1), ids.get(0));
|
||||
futures.add(deleteChannel(ids.get(0), ids.get(1)));
|
||||
} else if(action.equals(UndoAction.DELETE_MESSAGE)) {
|
||||
if(ids.size() != 2) {
|
||||
if(ids.size() != 3) {
|
||||
log.error("Not the correct amount of ids provided for the message deletion undo action.");
|
||||
return;
|
||||
}
|
||||
log.info("Deleting message {} in channel {} because of an UNDO action.", ids.get(1), ids.get(0));
|
||||
futures.add(botService.deleteMessage(ids.get(0), ids.get(1)));
|
||||
log.info("Deleting message {} in channel {} in server {} because of an UNDO action.", ids.get(2), ids.get(1), ids.get(0));
|
||||
futures.add(messageService.deleteMessageInChannelInServer(ids.get(0), ids.get(1), ids.get(2)));
|
||||
}
|
||||
});
|
||||
return FutureUtils.toSingleFutureGeneric(futures);
|
||||
|
||||
@@ -5,8 +5,8 @@ import dev.sheldan.abstracto.core.exception.ServerChannelConflictException;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.repository.PostTargetRepository;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -67,6 +67,10 @@ public class ServerManagementServiceBean implements ServerManagementService {
|
||||
@Override
|
||||
public AUserInAServer addUserToServer(Long serverId, Long userId) {
|
||||
log.info("Adding user {} to server {}", userId, serverId);
|
||||
// we need to reload the user, because the user already got persisted within this transaction (if the user didnt exist)
|
||||
// but it seems the current transaction is not aware that it is already persisted, it tries to create again
|
||||
// but fails with integrity constraint violation
|
||||
userManagementService.loadOrCreateUser(userId);
|
||||
AUser user = userManagementService.loadUser(userId);
|
||||
AServer serverReference = loadServer(serverId);
|
||||
AUserInAServer aUserInAServer = AUserInAServer.builder().serverReference(serverReference).userReference(user).build();
|
||||
|
||||
@@ -9,7 +9,10 @@ import dev.sheldan.abstracto.core.repository.UserInServerRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -27,9 +30,11 @@ public class UserInServerManagementServiceBean implements UserInServerManagement
|
||||
@Autowired
|
||||
private UserManagementService userManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementServiceBean self;
|
||||
|
||||
@Override
|
||||
public AUserInAServer loadUser(Long serverId, Long userId) {
|
||||
public AUserInAServer loadOrCreateUser(Long serverId, Long userId) {
|
||||
if(userInServerRepository.existsByServerReference_IdAndUserReference_Id(serverId, userId)) {
|
||||
return userInServerRepository.findByServerReference_IdAndUserReference_Id(serverId, userId).orElseThrow(() -> new UserInServerNotFoundException(0L));
|
||||
} else {
|
||||
@@ -38,8 +43,13 @@ public class UserInServerManagementServiceBean implements UserInServerManagement
|
||||
}
|
||||
|
||||
@Override
|
||||
public AUserInAServer loadUser(ServerUser serverUser) {
|
||||
return loadUser(serverUser.getServerId(), serverUser.getUserId());
|
||||
public AUserInAServer onlyLoadUser(Long serverId, Long userId) {
|
||||
return userInServerRepository.findByServerReference_IdAndUserReference_Id(serverId, userId).orElseThrow(() -> new UserInServerNotFoundException(0L));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AUserInAServer loadOrCreateUser(ServerUser serverUser) {
|
||||
return loadOrCreateUser(serverUser.getServerId(), serverUser.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,7 +58,7 @@ public class UserInServerManagementServiceBean implements UserInServerManagement
|
||||
}
|
||||
|
||||
@Override
|
||||
public AUserInAServer loadUser(AServer server, AUser user) {
|
||||
public AUserInAServer loadOrCreateUser(AServer server, AUser user) {
|
||||
if(userInServerRepository.existsByServerReferenceAndUserReference(server, user)) {
|
||||
return userInServerRepository.findByServerReferenceAndUserReference(server, user).orElseThrow(() -> new UserInServerNotFoundException(0L));
|
||||
} else {
|
||||
@@ -57,8 +67,8 @@ public class UserInServerManagementServiceBean implements UserInServerManagement
|
||||
}
|
||||
|
||||
@Override
|
||||
public AUserInAServer loadUser(Member member) {
|
||||
return this.loadUser(member.getGuild().getIdLong(), member.getIdLong());
|
||||
public AUserInAServer loadOrCreateUser(Member member) {
|
||||
return this.loadOrCreateUser(member.getGuild().getIdLong(), member.getIdLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,7 +77,7 @@ public class UserInServerManagementServiceBean implements UserInServerManagement
|
||||
}
|
||||
|
||||
@Override
|
||||
public AUserInAServer loadUser(Long userInServerId) {
|
||||
public AUserInAServer loadOrCreateUser(Long userInServerId) {
|
||||
return loadUserOptional(userInServerId).orElseThrow(() -> new UserInServerNotFoundException(userInServerId));
|
||||
}
|
||||
|
||||
@@ -77,8 +87,21 @@ public class UserInServerManagementServiceBean implements UserInServerManagement
|
||||
}
|
||||
|
||||
@Override
|
||||
public AUserInAServer createUserInServer(Long guildId, Long userId) {
|
||||
log.info("Creating user {} in server {}.", userId, guildId);
|
||||
public AUserInAServer createUserInServer(Long serverId, Long userId) {
|
||||
log.info("Creating user {} in server {}.", userId, serverId);
|
||||
AUserInAServer aUserInAServer;
|
||||
try {
|
||||
// TODO there seems to be an issue, of trying to create the user a second time
|
||||
aUserInAServer = self.tryToCreateAUserInAServer(serverId, userId);
|
||||
} catch (DataIntegrityViolationException ex) {
|
||||
log.info("Concurrency exception creating user - retrieving.");
|
||||
aUserInAServer = onlyLoadUser(serverId, userId);
|
||||
}
|
||||
return aUserInAServer;
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public AUserInAServer tryToCreateAUserInAServer(Long guildId, Long userId) {
|
||||
AUserInAServer aUserInAServer = serverManagementService.addUserToServer(guildId, userId);
|
||||
userInServerRepository.save(aUserInAServer);
|
||||
return aUserInAServer;
|
||||
@@ -86,13 +109,13 @@ public class UserInServerManagementServiceBean implements UserInServerManagement
|
||||
|
||||
@Override
|
||||
public List<AUserInAServer> getUserInAllServers(Long userId) {
|
||||
AUser user = userManagementService.loadUser(userId);
|
||||
AUser user = userManagementService.loadOrCreateUser(userId);
|
||||
return userInServerRepository.findByUserReference(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AUserInAServer> loadAUserInAServerOptional(Long serverId, Long userId) {
|
||||
AUser user = userManagementService.loadUser(userId);
|
||||
AUser user = userManagementService.loadOrCreateUser(userId);
|
||||
AServer server = serverManagementService.loadServer(serverId);
|
||||
return userInServerRepository.findByServerReferenceAndUserReference(server, user);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ import dev.sheldan.abstracto.core.repository.UserRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -16,6 +19,9 @@ public class UserManagementServiceBean implements UserManagementService {
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private UserManagementServiceBean self;
|
||||
|
||||
@Override
|
||||
public AUser createUser(Member member) {
|
||||
return createUser(member.getIdLong());
|
||||
@@ -23,14 +29,30 @@ public class UserManagementServiceBean implements UserManagementService {
|
||||
|
||||
@Override
|
||||
public AUser createUser(Long userId) {
|
||||
AUser user;
|
||||
try {
|
||||
user = self.tryCreateUser(userId);
|
||||
} catch (DataIntegrityViolationException ex) {
|
||||
log.info("Concurrency exception creating user - retrieving.");
|
||||
user = loadUser(userId);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AUser loadUser(Long userId) {
|
||||
return userRepository.getOne(userId);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public AUser tryCreateUser(Long userId) {
|
||||
AUser aUser = AUser.builder().id(userId).build();
|
||||
log.info("Creating user {}.", userId);
|
||||
userRepository.save(aUser);
|
||||
return aUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AUser loadUser(Long userId) {
|
||||
public AUser loadOrCreateUser(Long userId) {
|
||||
Optional<AUser> optional = loadUserOptional(userId);
|
||||
return optional.orElseGet(() -> this.createUser(userId));
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
abstracto.startup.synchronize=true
|
||||
|
||||
abstracto.eventWaiter.threads=10
|
||||
server.port=8080
|
||||
@@ -1,6 +1,8 @@
|
||||
package dev.sheldan.abstracto.core.command.handler;
|
||||
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CommandServiceBeanTest {
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FeatureFlagListenerTest {
|
||||
|
||||
Reference in New Issue
Block a user