[AB-xxx] more instrumenting changes

This commit is contained in:
Sheldan
2025-11-28 20:31:28 +01:00
parent 0d5b7c5855
commit bd00f6d248
4 changed files with 362 additions and 333 deletions

View File

@@ -314,9 +314,9 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
AServer server = serverManagementService.loadOrCreate(serverId); AServer server = serverManagementService.loadOrCreate(serverId);
List<ADisabledExpRole> disabledExpRoles = disabledExpRoleManagementService.getDisabledRolesForServer(server); List<ADisabledExpRole> disabledExpRoles = disabledExpRoleManagementService.getDisabledRolesForServer(server);
List<ARole> disabledRoles = disabledExpRoles List<ARole> disabledRoles = disabledExpRoles
.stream() .stream()
.map(ADisabledExpRole::getRole) .map(ADisabledExpRole::getRole)
.collect(Collectors.toList()); .collect(Collectors.toList());
if (roleService.hasAnyOfTheRoles(member, disabledRoles)) { if (roleService.hasAnyOfTheRoles(member, disabledRoles)) {
log.debug("User {} has a experience disable role in server {} - not giving any experience.", member.getIdLong(), serverId); log.debug("User {} has a experience disable role in server {} - not giving any experience.", member.getIdLong(), serverId);
newSpan.end(); newSpan.end();
@@ -342,29 +342,31 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
log.debug("Handling {}. The user gains {}.", userInServerId, gainedExperience); log.debug("Handling {}. The user gains {}.", userInServerId, gainedExperience);
Long oldExperience = aUserExperience.getExperience(); Long oldExperience = aUserExperience.getExperience();
Long newExperienceCount = oldExperience + gainedExperience; Long newExperienceCount = oldExperience + gainedExperience;
aUserExperience.setExperience(newExperienceCount); aUserExperience.setExperience(newExperienceCount);
AExperienceLevel newLevel = calculateLevel(levels, newExperienceCount); AExperienceLevel newLevel = calculateLevel(levels, newExperienceCount);
RoleCalculationResult result = RoleCalculationResult RoleCalculationResult result = RoleCalculationResult
.builder() .builder()
.build(); .build();
boolean userChangesLevel = !Objects.equals(newLevel.getLevel(), aUserExperience.getCurrentLevel().getLevel()); boolean userChangesLevel = !Objects.equals(newLevel.getLevel(), aUserExperience.getCurrentLevel().getLevel());
Integer oldLevel = aUserExperience.getCurrentLevel() != null ? aUserExperience.getCurrentLevel().getLevel() : 0; Integer oldLevel = aUserExperience.getCurrentLevel() != null ? aUserExperience.getCurrentLevel().getLevel() : 0;
if(userChangesLevel) { if (userChangesLevel) {
log.info("User {} in server {} changed level. New {}, Old {}.", member.getIdLong(), log.info("User {} in server {} changed level. New {}, Old {}.", member.getIdLong(),
member.getGuild().getIdLong(), newLevel.getLevel(), member.getGuild().getIdLong(), newLevel.getLevel(),
oldLevel); oldLevel);
aUserExperience.setCurrentLevel(newLevel); aUserExperience.setCurrentLevel(newLevel);
AExperienceRole calculatedNewRole = experienceRoleService.calculateRole(roles, newLevel.getLevel()); AExperienceRole calculatedNewRole = experienceRoleService.calculateRole(roles, newLevel.getLevel());
Long oldRoleId = aUserExperience.getCurrentExperienceRole() != null && aUserExperience.getCurrentExperienceRole().getRole() != null ? aUserExperience.getCurrentExperienceRole().getRole().getId() : null; Long oldRoleId = aUserExperience.getCurrentExperienceRole() != null && aUserExperience.getCurrentExperienceRole().getRole() != null ?
Long newRoleId = calculatedNewRole != null && calculatedNewRole.getRole() != null ? calculatedNewRole.getRole().getId() : null; aUserExperience.getCurrentExperienceRole().getRole().getId() : null;
result.setOldRoleId(oldRoleId); Long newRoleId = calculatedNewRole != null && calculatedNewRole.getRole() != null ? calculatedNewRole.getRole().getId() : null;
result.setNewRoleId(newRoleId); result.setOldRoleId(oldRoleId);
if(message != null result.setNewRoleId(newRoleId);
if (message != null
&& aUserExperience.getLevelUpNotification() && aUserExperience.getLevelUpNotification()
&& featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, serverId, ExperienceFeatureMode.LEVEL_UP_NOTIFICATION)) { &&
LevelUpNotificationModel model = LevelUpNotificationModel featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, serverId, ExperienceFeatureMode.LEVEL_UP_NOTIFICATION)) {
LevelUpNotificationModel model = LevelUpNotificationModel
.builder() .builder()
.memberDisplay(MemberDisplay.fromMember(member)) .memberDisplay(MemberDisplay.fromMember(member))
.oldExperience(oldExperience) .oldExperience(oldExperience)
@@ -374,63 +376,72 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
.newRole(oldRoleId != null ? RoleDisplay.fromRole(oldRoleId) : null) .newRole(oldRoleId != null ? RoleDisplay.fromRole(oldRoleId) : null)
.newRole(newRoleId != null ? RoleDisplay.fromRole(newRoleId) : null) .newRole(newRoleId != null ? RoleDisplay.fromRole(newRoleId) : null)
.build(); .build();
MessageToSend messageToSend = templateService.renderEmbedTemplate("experience_level_up_notification", model, serverId); MessageToSend messageToSend = templateService.renderEmbedTemplate("experience_level_up_notification", model, serverId);
FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, message.getChannel())).thenAccept(unused -> { FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, message.getChannel())).thenAccept(unused -> {
log.info("Sent level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId, message.getChannel().getIdLong()); log.info("Sent level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId,
}).exceptionally(throwable -> { message.getChannel().getIdLong());
log.warn("Failed to send level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId, message.getChannel().getIdLong());
return null;
});
}
aUserExperience.setCurrentExperienceRole(calculatedNewRole);
}
aUserExperience.setMessageCount(aUserExperience.getMessageCount() + 1L);
if(userChangesLevel && featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, server, ExperienceFeatureMode.LEVEL_ACTION)) {
levelActionService.applyLevelActionsToUser(aUserExperience, oldLevel)
.thenAccept(unused -> {
log.info("Executed level actions for user {}.", userInServerId);
})
.exceptionally(throwable -> {
log.warn("Failed to execute level actions for user {}.", userInServerId, throwable);
return null;
});
}
if(aUserExperienceOptional.isEmpty()) {
userExperienceManagementService.saveUser(aUserExperience);
}
if(!Objects.equals(result.getOldRoleId(), result.getNewRoleId())) {
if(result.getOldRoleId() != null && result.getNewRoleId() != null) {
roleService.updateRolesIds(member, Arrays.asList(result.getOldRoleId()), Arrays.asList(result.getNewRoleId())).thenAccept(unused -> {
log.debug("Removed role {} from and added role {} to member {} in server {}.", result.getOldRoleId(), result.getNewRoleId(), member.getIdLong(), member.getGuild().getIdLong());
}).exceptionally(throwable -> {
log.warn("Failed to remove role {} from and add role {} to member {} in server {}.", result.getOldRoleId(), result.getNewRoleId(), member.getIdLong(), member.getGuild().getIdLong(), throwable);
return null;
});
} else {
if(result.getOldRoleId() != null) {
roleService.removeRoleFromMemberAsync(member, result.getOldRoleId()).thenAccept(unused -> {
log.debug("Removed role {} from member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong());
}).exceptionally(throwable -> { }).exceptionally(throwable -> {
log.warn("Failed to remove role {} from member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong(), throwable); log.warn("Failed to send level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId,
message.getChannel().getIdLong());
return null; return null;
}); });
} }
if(result.getNewRoleId() != null) { aUserExperience.setCurrentExperienceRole(calculatedNewRole);
roleService.addRoleToMemberAsync(member, result.getNewRoleId()).thenAccept(unused -> { }
log.debug("Added role {} to member {} in server {}.", result.getNewRoleId(), member.getIdLong(), member.getGuild().getIdLong()); aUserExperience.setMessageCount(aUserExperience.getMessageCount() + 1L);
}).exceptionally(throwable -> { if (userChangesLevel &&
log.warn("Failed to add role {} to member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong(), throwable); featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, server, ExperienceFeatureMode.LEVEL_ACTION)) {
levelActionService.applyLevelActionsToUser(aUserExperience, oldLevel)
.thenAccept(unused -> {
log.info("Executed level actions for user {}.", userInServerId);
})
.exceptionally(throwable -> {
log.warn("Failed to execute level actions for user {}.", userInServerId, throwable);
return null; return null;
}); });
}
if (aUserExperienceOptional.isEmpty()) {
userExperienceManagementService.saveUser(aUserExperience);
}
if (!Objects.equals(result.getOldRoleId(), result.getNewRoleId())) {
if (result.getOldRoleId() != null && result.getNewRoleId() != null) {
roleService.updateRolesIds(member, Arrays.asList(result.getOldRoleId()), Arrays.asList(result.getNewRoleId())).thenAccept(unused -> {
log.debug("Removed role {} from and added role {} to member {} in server {}.", result.getOldRoleId(), result.getNewRoleId(),
member.getIdLong(), member.getGuild().getIdLong());
}).exceptionally(throwable -> {
log.warn("Failed to remove role {} from and add role {} to member {} in server {}.", result.getOldRoleId(), result.getNewRoleId(),
member.getIdLong(), member.getGuild().getIdLong(), throwable);
return null;
});
} else {
if (result.getOldRoleId() != null) {
roleService.removeRoleFromMemberAsync(member, result.getOldRoleId()).thenAccept(unused -> {
log.debug("Removed role {} from member {} in server {}.", result.getOldRoleId(), member.getIdLong(),
member.getGuild().getIdLong());
}).exceptionally(throwable -> {
log.warn("Failed to remove role {} from member {} in server {}.", result.getOldRoleId(), member.getIdLong(),
member.getGuild().getIdLong(), throwable);
return null;
});
}
if (result.getNewRoleId() != null) {
roleService.addRoleToMemberAsync(member, result.getNewRoleId()).thenAccept(unused -> {
log.debug("Added role {} to member {} in server {}.", result.getNewRoleId(), member.getIdLong(), member.getGuild().getIdLong());
}).exceptionally(throwable -> {
log.warn("Failed to add role {} to member {} in server {}.", result.getOldRoleId(), member.getIdLong(),
member.getGuild().getIdLong(), throwable);
return null;
});
}
} }
} }
} else {
log.debug("Experience gain was disabled. User did not gain any experience.");
} }
} else { return CompletableFuture.allOf(notificationFuture, levelActionFuture, roleFuture).whenComplete((unused, throwable) -> {
log.debug("Experience gain was disabled. User did not gain any experience."); newSpan.end();
});
} }
return CompletableFuture.allOf(notificationFuture, levelActionFuture, roleFuture).whenComplete((unused, throwable) -> {
newSpan.end();
});
} }
@Override @Override

View File

@@ -266,86 +266,86 @@ public class InteractionServiceBean implements InteractionService {
public CompletableFuture<InteractionHook> replyMessageToSend(MessageToSend messageToSend, IReplyCallback callback) { public CompletableFuture<InteractionHook> replyMessageToSend(MessageToSend messageToSend, IReplyCallback callback) {
Span newSpan = tracer.nextSpan().name("send-message-to-interaction"); Span newSpan = tracer.nextSpan().name("send-message-to-interaction");
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) { try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
ReplyCallbackAction action = null; ReplyCallbackAction action = null;
if(messageToSend.getUseComponentsV2()) { if (messageToSend.getUseComponentsV2()) {
action = callback.replyComponents(messageToSend.getComponents()).useComponentsV2(); action = callback.replyComponents(messageToSend.getComponents()).useComponentsV2();
} else { } else {
if(messageToSend.getMessages() != null && !messageToSend.getMessages().isEmpty()) { if (messageToSend.getMessages() != null && !messageToSend.getMessages().isEmpty()) {
metricService.incrementCounter(MESSAGE_SEND_METRIC);
action = callback.reply(messageToSend.getMessages().get(0));
}
if(messageToSend.getEmbeds() != null && !messageToSend.getEmbeds().isEmpty()) {
if(action != null) {
action = action.addEmbeds(messageToSend.getEmbeds().subList(0, Math.min(10, messageToSend.getEmbeds().size())));
} else {
action = callback.replyEmbeds(messageToSend.getEmbeds());
}
}
if(messageToSend.hasFilesToSend()) {
List<FileUpload> attachedFiles = messageToSend
.getAttachedFiles()
.stream()
.map(AttachedFile::convertToFileUpload)
.collect(Collectors.toList());
if(action != null) {
action.setFiles(attachedFiles);
} else {
metricService.incrementCounter(MESSAGE_SEND_METRIC); metricService.incrementCounter(MESSAGE_SEND_METRIC);
action = callback.replyFiles(attachedFiles); action = callback.reply(messageToSend.getMessages().get(0));
} }
} if (messageToSend.getEmbeds() != null && !messageToSend.getEmbeds().isEmpty()) {
// this should be last, because we are "faking" a message, by inserting a ., in case there has not been a reply yet if (action != null) {
// we could also throw an exception, but we are allowing this to go through action = action.addEmbeds(messageToSend.getEmbeds().subList(0, Math.min(10, messageToSend.getEmbeds().size())));
List<ActionRow> actionRows = messageToSend.getActionRows(); } else {
if(actionRows != null && !actionRows.isEmpty()) { action = callback.replyEmbeds(messageToSend.getEmbeds());
if(action == null) {
action = callback.reply(".");
}
action = action.setComponents(actionRows);
AServer server;
if(ContextUtils.isGuildKnown(callback)) {
server = serverManagementService.loadServer(callback.getGuild().getIdLong());
} else {
server = null;
}
actionRows.forEach(components -> components.forEach(component -> {
if(component instanceof ActionComponent) {
String id = ((ActionComponent)component).getId();
MessageToSend.ComponentConfig payload = messageToSend.getComponentPayloads().get(id);
if(payload != null && payload.getPersistCallback()) {
componentPayloadManagementService.createPayload(id, payload.getPayload(), payload.getPayloadType(), payload.getComponentOrigin(), server, payload.getComponentType());
}
} }
})); }
if (messageToSend.hasFilesToSend()) {
List<FileUpload> attachedFiles = messageToSend
.getAttachedFiles()
.stream()
.map(AttachedFile::convertToFileUpload)
.collect(Collectors.toList());
if (action != null) {
action.setFiles(attachedFiles);
} else {
metricService.incrementCounter(MESSAGE_SEND_METRIC);
action = callback.replyFiles(attachedFiles);
}
}
// this should be last, because we are "faking" a message, by inserting a ., in case there has not been a reply yet
// we could also throw an exception, but we are allowing this to go through
List<ActionRow> actionRows = messageToSend.getActionRows();
if (actionRows != null && !actionRows.isEmpty()) {
if (action == null) {
action = callback.reply(".");
}
action = action.setComponents(actionRows);
AServer server;
if (ContextUtils.isGuildKnown(callback)) {
server = serverManagementService.loadServer(callback.getGuild().getIdLong());
} else {
server = null;
}
actionRows.forEach(components -> components.forEach(component -> {
if (component instanceof ActionComponent) {
String id = ((ActionComponent) component).getId();
MessageToSend.ComponentConfig payload = messageToSend.getComponentPayloads().get(id);
if (payload != null && payload.getPersistCallback()) {
componentPayloadManagementService.createPayload(id, payload.getPayload(), payload.getPayloadType(),
payload.getComponentOrigin(), server, payload.getComponentType());
}
}
}));
}
} }
}
if(messageToSend.getEphemeral()) { if (messageToSend.getEphemeral()) {
if(ContextUtils.hasGuild(callback)) { if (ContextUtils.hasGuild(callback)) {
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.", log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
callback.getGuild().getIdLong(), callback.getChannel().getId(), callback.getGuild().getIdLong(), callback.getChannel().getId(),
callback.getUser().getIdLong()); callback.getUser().getIdLong());
} else { } else {
log.info("Sending ephemeral message to user {}.", callback.getUser().getIdLong()); log.info("Sending ephemeral message to user {}.", callback.getUser().getIdLong());
}
metricService.incrementCounter(EPHEMERAL_MESSAGES_SEND);
if (action != null) {
action = action.setEphemeral(messageToSend.getEphemeral());
}
} }
metricService.incrementCounter(EPHEMERAL_MESSAGES_SEND); if (ContextUtils.isGuildKnown(callback)) {
if(action != null) { Set<Message.MentionType> allowedMentions = allowedMentionService.getAllowedMentionsFor(callback.getMessageChannel(), messageToSend);
action = action.setEphemeral(messageToSend.getEphemeral()); if (action != null) {
action = action.setAllowedMentions(allowedMentions);
}
} }
}
if(ContextUtils.isGuildKnown(callback)) {
Set<Message.MentionType> allowedMentions = allowedMentionService.getAllowedMentionsFor(callback.getMessageChannel(), messageToSend);
if (action != null) {
action = action.setAllowedMentions(allowedMentions);
}
}
if (action == null) { if (action == null) {
throw new AbstractoRunTimeException("The callback did not result in any message."); throw new AbstractoRunTimeException("The callback did not result in any message.");
} }
return action.submit(); return action.submit();
} }
}
} }
@Override @Override

View File

@@ -19,23 +19,31 @@ import dev.sheldan.abstracto.core.interaction.slash.payload.SlashCommandConfirma
import dev.sheldan.abstracto.core.metric.service.CounterMetric; import dev.sheldan.abstracto.core.metric.service.CounterMetric;
import dev.sheldan.abstracto.core.metric.service.MetricService; import dev.sheldan.abstracto.core.metric.service.MetricService;
import dev.sheldan.abstracto.core.metric.service.MetricTag; import dev.sheldan.abstracto.core.metric.service.MetricTag;
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
import dev.sheldan.abstracto.core.models.database.AServer; import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.ConfigService; import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService; import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.utils.ContextUtils;
import dev.sheldan.abstracto.scheduling.model.JobParameters; import dev.sheldan.abstracto.scheduling.model.JobParameters;
import dev.sheldan.abstracto.scheduling.service.SchedulerService; import dev.sheldan.abstracto.scheduling.service.SchedulerService;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import dev.sheldan.abstracto.core.utils.ContextUtils;
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
import io.micrometer.observation.Observation; import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry; import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Span; import io.micrometer.tracing.Span;
import io.micrometer.tracing.Tracer; import io.micrometer.tracing.Tracer;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
@@ -50,15 +58,6 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
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 java.util.stream.Collectors;
@Component @Component
@Slf4j @Slf4j
public class SlashCommandListenerBean extends ListenerAdapter { public class SlashCommandListenerBean extends ListenerAdapter {
@@ -118,46 +117,49 @@ public class SlashCommandListenerBean extends ListenerAdapter {
public static final String SLASH_COMMAND_CONFIRMATION_ORIGIN = "SLASH_COMMAND_CONFIRMATION"; public static final String SLASH_COMMAND_CONFIRMATION_ORIGIN = "SLASH_COMMAND_CONFIRMATION";
public static final CounterMetric SLASH_COMMANDS_PROCESSED_COUNTER = CounterMetric public static final CounterMetric SLASH_COMMANDS_PROCESSED_COUNTER = CounterMetric
.builder() .builder()
.name(CommandReceivedHandler.COMMAND_PROCESSED) .name(CommandReceivedHandler.COMMAND_PROCESSED)
.tagList(Arrays.asList(MetricTag.getTag(CommandReceivedHandler.STATUS_TAG, "processed"), MetricTag.getTag(CommandReceivedHandler.TYPE_TAG, "slash"))) .tagList(Arrays.asList(MetricTag.getTag(CommandReceivedHandler.STATUS_TAG, "processed"), MetricTag.getTag(CommandReceivedHandler.TYPE_TAG, "slash")))
.build(); .build();
public List<Command> getSlashCommands() { public List<Command> getSlashCommands() {
if(commands == null || commands.isEmpty()) { if (commands == null || commands.isEmpty()) {
return new ArrayList<>(); return new ArrayList<>();
} }
return commands.stream() return commands.stream()
.filter(command -> command.getConfiguration() .filter(command -> command.getConfiguration()
.getSlashCommandConfig().isEnabled()) .getSlashCommandConfig().isEnabled())
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Override @Override
public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
Observation observation = Observation.createNotStarted("slash-command-received", this.observationRegistry); Observation observation = Observation.createNotStarted("slash-command-received", this.observationRegistry);
observation.observe(() -> { observation.observe(() -> {
try { try {
if(commands == null || commands.isEmpty()) return; if (commands == null || commands.isEmpty()) {
if(ContextUtils.hasGuild(event.getInteraction())) { return;
log.debug("Executing slash command in guild {} from user {}.", event.getGuild().getIdLong(), event.getUser().getIdLong());
} else {
log.debug("Executing slash command by user {}", event.getUser().getIdLong());
}
Span span = tracer.currentSpan();
CompletableFuture.runAsync(() -> {
try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
self.executeListenerLogic(event).whenComplete((unused, throwable) -> {
span.end();
});
} }
if (ContextUtils.hasGuild(event.getInteraction())) {
}, slashCommandExecutor).exceptionally(throwable -> { log.debug("Executing slash command in guild {} from user {}.", event.getGuild().getIdLong(), event.getUser().getIdLong());
log.error("Failed to execute listener logic in async slash command event.", throwable); } else {
return null; log.debug("Executing slash command by user {}", event.getUser().getIdLong());
}); }
} catch (Exception exception) { Span span = tracer.currentSpan();
log.error("Failed to process slash command interaction event.", exception); CompletableFuture.runAsync(() -> {
try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
self.executeListenerLogic(event).whenComplete((unused, throwable) -> {
span.end();
});
}
}, slashCommandExecutor).exceptionally(throwable -> {
log.error("Failed to execute listener logic in async slash command event.", throwable);
return null;
});
} catch (Exception exception) {
log.error("Failed to process slash command interaction event.", exception);
}
}); });
} }
@@ -165,28 +167,28 @@ public class SlashCommandListenerBean extends ListenerAdapter {
@Transactional @Transactional
public CompletableFuture<Void> executeListenerLogic(SlashCommandInteractionEvent event) { public CompletableFuture<Void> executeListenerLogic(SlashCommandInteractionEvent event) {
Optional<Command> potentialCommand = findCommand(event); Optional<Command> potentialCommand = findCommand(event);
if(potentialCommand.isPresent()) { if (potentialCommand.isPresent()) {
Command command = potentialCommand.get(); Command command = potentialCommand.get();
metricService.incrementCounter(SLASH_COMMANDS_PROCESSED_COUNTER); metricService.incrementCounter(SLASH_COMMANDS_PROCESSED_COUNTER);
try { try {
Span span = tracer.currentSpan(); Span span = tracer.currentSpan();
span.tag("command-name", command.getConfiguration().getName()); span.tag("command-name", command.getConfiguration().getName());
return commandService.isCommandExecutable(command, event).thenCompose(conditionResult -> { return commandService.isCommandExecutable(command, event).thenCompose(conditionResult -> {
try (Tracer.SpanInScope ws = tracer.withSpan(span)) { try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
return self.executeCommand(event, command, conditionResult); return self.executeCommand(event, command, conditionResult);
} }
}).exceptionally(throwable -> { }).exceptionally(throwable -> {
log.error("Error while executing command {}", command.getConfiguration().getName(), throwable); log.error("Error while executing command {}", command.getConfiguration().getName(), throwable);
CommandResult commandResult = CommandResult.fromError(throwable.getMessage(), throwable); CommandResult commandResult = CommandResult.fromError(throwable.getMessage(), throwable);
self.executePostCommandListener(command, event, commandResult);
return null;
});
} catch (Exception exception) {
log.error("Error while checking if command {} is executable.", command.getConfiguration().getName(), exception);
CommandResult commandResult = CommandResult.fromError(exception.getMessage(), exception);
self.executePostCommandListener(command, event, commandResult); self.executePostCommandListener(command, event, commandResult);
return CompletableFuture.completedFuture(null); return null;
} });
} catch (Exception exception) {
log.error("Error while checking if command {} is executable.", command.getConfiguration().getName(), exception);
CommandResult commandResult = CommandResult.fromError(exception.getMessage(), exception);
self.executePostCommandListener(command, event, commandResult);
return CompletableFuture.completedFuture(null);
}
} else { } else {
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
@@ -195,11 +197,14 @@ public class SlashCommandListenerBean extends ListenerAdapter {
@Override @Override
public void onCommandAutoCompleteInteraction(@Nonnull CommandAutoCompleteInteractionEvent event) { public void onCommandAutoCompleteInteraction(@Nonnull CommandAutoCompleteInteractionEvent event) {
try { try {
if(commands == null || commands.isEmpty()) return; if (commands == null || commands.isEmpty()) {
CompletableFuture.runAsync(() -> self.executeAutCompleteListenerLogic(event), MetricUtils.wrapExecutor(slashCommandAutoCompleteExecutor)).exceptionally(throwable -> { return;
log.error("Failed to execute listener logic in async auto complete interaction event.", throwable); }
return null; CompletableFuture.runAsync(() -> self.executeAutCompleteListenerLogic(event), MetricUtils.wrapExecutor(slashCommandAutoCompleteExecutor))
}); .exceptionally(throwable -> {
log.error("Failed to execute listener logic in async auto complete interaction event.", throwable);
return null;
});
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to process slash command auto complete interaction.", e); log.error("Failed to process slash command auto complete interaction.", e);
} }
@@ -212,15 +217,17 @@ public class SlashCommandListenerBean extends ListenerAdapter {
try { try {
List<String> fullRepliesList = command.performAutoComplete(event); List<String> fullRepliesList = command.performAutoComplete(event);
List<String> replies = fullRepliesList.subList(0, Math.min(fullRepliesList.size(), OptionData.MAX_CHOICES)); List<String> replies = fullRepliesList.subList(0, Math.min(fullRepliesList.size(), OptionData.MAX_CHOICES));
event.replyChoiceStrings(replies).queue(unused -> {}, event.replyChoiceStrings(replies).queue(unused -> {
throwable -> { },
if(ContextUtils.hasGuild(event)) { throwable -> {
log.error("Failed to respond to complete of command {} in guild {} by user {}.", if (ContextUtils.hasGuild(event)) {
command.getConfiguration().getName(), event.getGuild().getIdLong(), event.getUser().getIdLong()); log.error("Failed to respond to complete of command {} in guild {} by user {}.",
} else { command.getConfiguration().getName(), event.getGuild().getIdLong(), event.getUser().getIdLong());
log.error("Failed to resp ond to complete of command {} for user {}.", command.getConfiguration().getName(), event.getUser().getIdLong()); } else {
} log.error("Failed to resp ond to complete of command {} for user {}.", command.getConfiguration().getName(),
}); event.getUser().getIdLong());
}
});
} catch (Exception exception) { } catch (Exception exception) {
log.error("Error while executing autocomplete of command {}.", command.getConfiguration().getName(), exception); log.error("Error while executing autocomplete of command {}.", command.getConfiguration().getName(), exception);
} }
@@ -228,8 +235,9 @@ public class SlashCommandListenerBean extends ListenerAdapter {
} }
@Transactional @Transactional
public void continueSlashCommand(Long interactionId, ButtonInteractionEvent buttonInteractionEvent, SlashCommandConfirmationPayload slashCommandConfirmationPayload) { public void continueSlashCommand(Long interactionId, ButtonInteractionEvent buttonInteractionEvent,
if(COMMANDS_WAITING_FOR_CONFIRMATION.containsKey(interactionId)) { SlashCommandConfirmationPayload slashCommandConfirmationPayload) {
if (COMMANDS_WAITING_FOR_CONFIRMATION.containsKey(interactionId)) {
DriedSlashCommand driedSlashCommand = COMMANDS_WAITING_FOR_CONFIRMATION.get(interactionId); DriedSlashCommand driedSlashCommand = COMMANDS_WAITING_FOR_CONFIRMATION.get(interactionId);
Command commandInstance = driedSlashCommand.getCommand(); Command commandInstance = driedSlashCommand.getCommand();
String commandName = commandInstance.getConfiguration().getName(); String commandName = commandInstance.getConfiguration().getName();
@@ -250,23 +258,28 @@ public class SlashCommandListenerBean extends ListenerAdapter {
return null; return null;
}); });
} else { } else {
log.warn("Interaction was not found in internal map - not continuing interaction from user {} in server {}.", buttonInteractionEvent.getUser().getIdLong(), buttonInteractionEvent.getGuild().getIdLong()); log.warn("Interaction was not found in internal map - not continuing interaction from user {} in server {}.",
buttonInteractionEvent.getUser().getIdLong(), buttonInteractionEvent.getGuild().getIdLong());
} }
} }
@Transactional @Transactional
public void cleanupSlashCommandConfirmation(SlashCommandConfirmationPayload slashCommandConfirmationPayload, ButtonInteractionEvent buttonInteractionEvent) { public void cleanupSlashCommandConfirmation(SlashCommandConfirmationPayload slashCommandConfirmationPayload,
log.debug("Cleaning up component {} and {}.", slashCommandConfirmationPayload.getConfirmationPayloadId(), slashCommandConfirmationPayload.getAbortPayloadId()); ButtonInteractionEvent buttonInteractionEvent) {
componentPayloadManagementService.deletePayloads(Arrays.asList(slashCommandConfirmationPayload.getAbortPayloadId(), slashCommandConfirmationPayload.getConfirmationPayloadId())); log.debug("Cleaning up component {} and {}.", slashCommandConfirmationPayload.getConfirmationPayloadId(),
slashCommandConfirmationPayload.getAbortPayloadId());
componentPayloadManagementService.deletePayloads(
Arrays.asList(slashCommandConfirmationPayload.getAbortPayloadId(), slashCommandConfirmationPayload.getConfirmationPayloadId()));
} }
@Transactional @Transactional
public void removeSlashCommandConfirmationInteraction(Long interactionId, String confirmationPayload, String abortPayload) { public void removeSlashCommandConfirmationInteraction(Long interactionId, String confirmationPayload, String abortPayload) {
if(COMMANDS_WAITING_FOR_CONFIRMATION.containsKey(interactionId)) { if (COMMANDS_WAITING_FOR_CONFIRMATION.containsKey(interactionId)) {
DriedSlashCommand removedSlashCommand = COMMANDS_WAITING_FOR_CONFIRMATION.remove(interactionId); DriedSlashCommand removedSlashCommand = COMMANDS_WAITING_FOR_CONFIRMATION.remove(interactionId);
SlashCommandInteractionEvent event = removedSlashCommand.getEvent(); SlashCommandInteractionEvent event = removedSlashCommand.getEvent();
event.getInteraction().getHook().deleteOriginal().queue(); event.getInteraction().getHook().deleteOriginal().queue();
log.info("Remove interaction for command {} in server {} from user {}.", removedSlashCommand.getCommand().getConfiguration().getName(), event.getGuild().getIdLong(), event.getUser().getIdLong()); log.info("Remove interaction for command {} in server {} from user {}.", removedSlashCommand.getCommand().getConfiguration().getName(),
event.getGuild().getIdLong(), event.getUser().getIdLong());
} else { } else {
log.info("Did not find interaction to clean up."); log.info("Did not find interaction to clean up.");
} }
@@ -274,9 +287,9 @@ public class SlashCommandListenerBean extends ListenerAdapter {
} }
@Transactional(rollbackFor = AbstractoRunTimeException.class) @Transactional(rollbackFor = AbstractoRunTimeException.class)
public void executeCommand(SlashCommandInteractionEvent event, Command command, ConditionResult conditionResult) { public CompletableFuture<Void> executeCommand(SlashCommandInteractionEvent event, Command command, ConditionResult conditionResult) {
String commandName = command.getConfiguration().getName(); String commandName = command.getConfiguration().getName();
if(command.getConfiguration().isRequiresConfirmation() && conditionResult.isResult()) { if (command.getConfiguration().isRequiresConfirmation() && conditionResult.isResult()) {
DriedSlashCommand slashCommand = DriedSlashCommand DriedSlashCommand slashCommand = DriedSlashCommand
.builder() .builder()
.command(command) .command(command)
@@ -310,19 +323,22 @@ public class SlashCommandListenerBean extends ListenerAdapter {
.commandName(commandName) .commandName(commandName)
.build(); .build();
Long userId = event.getUser().getIdLong(); Long userId = event.getUser().getIdLong();
interactionService.replyEmbed(COMMAND_CONFIRMATION_MESSAGE_TEMPLATE_KEY, model, event).thenAccept(interactionHook -> { CompletableFuture<Void> replyFuture =
log.info("Sent confirmation for command {} in server {} for user {}.", commandName, serverId, userId); interactionService.replyEmbed(COMMAND_CONFIRMATION_MESSAGE_TEMPLATE_KEY, model, event).thenAccept(interactionHook -> {
}).exceptionally(throwable -> { log.info("Sent confirmation for command {} in server {} for user {}.", commandName, serverId, userId);
log.warn("Failed to send confirmation for command {} in server {} for user {}.", commandName, serverId, userId); }).exceptionally(throwable -> {
return null; log.warn("Failed to send confirmation for command {} in server {} for user {}.", commandName, serverId, userId);
}); return null;
});
scheduleConfirmationDeletion(event.getIdLong(), confirmationId, abortId, serverId); scheduleConfirmationDeletion(event.getIdLong(), confirmationId, abortId, serverId);
return replyFuture;
} else { } else {
CompletableFuture<CommandResult> commandOutput; CompletableFuture<CommandResult> commandOutput;
if(conditionResult.isResult()) { if (conditionResult.isResult()) {
commandOutput = command.executeSlash(event).thenApply(commandResult -> { commandOutput = command.executeSlash(event).thenApply(commandResult -> {
if(ContextUtils.hasGuild(event)) { if (ContextUtils.hasGuild(event)) {
log.info("Command {} in server {} was executed by user {}.", command.getConfiguration().getName(), event.getGuild().getIdLong(), event.getUser().getIdLong()); log.info("Command {} in server {} was executed by user {}.", command.getConfiguration().getName(), event.getGuild().getIdLong(),
event.getUser().getIdLong());
} else { } else {
log.info("Command {} was executed by user {}.", command.getConfiguration().getName(), event.getUser().getId()); log.info("Command {} was executed by user {}.", command.getConfiguration().getName(), event.getUser().getId());
} }
@@ -331,7 +347,7 @@ public class SlashCommandListenerBean extends ListenerAdapter {
} else { } else {
commandOutput = CompletableFuture.completedFuture(CommandResult.fromCondition(conditionResult)); commandOutput = CompletableFuture.completedFuture(CommandResult.fromCondition(conditionResult));
} }
commandOutput.thenAccept(commandResult -> { return commandOutput.thenAccept(commandResult -> {
self.executePostCommandListener(command, event, commandResult); self.executePostCommandListener(command, event, commandResult);
}).exceptionally(throwable -> { }).exceptionally(throwable -> {
log.error("Error while handling post execution of command {}", commandName, throwable); log.error("Error while handling post execution of command {}", commandName, throwable);
@@ -366,26 +382,26 @@ public class SlashCommandListenerBean extends ListenerAdapter {
private Optional<Command> findCommand(SlashCommandInteractionEvent event) { private Optional<Command> findCommand(SlashCommandInteractionEvent event) {
return commands return commands
.stream() .stream()
.filter(command -> command.getConfiguration().getSlashCommandConfig().isEnabled()) .filter(command -> command.getConfiguration().getSlashCommandConfig().isEnabled())
.filter(command -> command.getConfiguration().getSlashCommandConfig().matchesInteraction(event.getInteraction())) .filter(command -> command.getConfiguration().getSlashCommandConfig().matchesInteraction(event.getInteraction()))
.findAny(); .findAny();
} }
private Optional<Command> findCommand(CommandAutoCompleteInteractionEvent event) { private Optional<Command> findCommand(CommandAutoCompleteInteractionEvent event) {
return commands return commands
.stream() .stream()
.filter(command -> command.getConfiguration().getSlashCommandConfig().isEnabled()) .filter(command -> command.getConfiguration().getSlashCommandConfig().isEnabled())
.filter(command -> command.getConfiguration().getSlashCommandConfig().matchesInteraction(event.getInteraction())) .filter(command -> command.getConfiguration().getSlashCommandConfig().matchesInteraction(event.getInteraction()))
.findAny(); .findAny();
} }
@PostConstruct @PostConstruct
public void filterPostProcessors() { public void filterPostProcessors() {
metricService.registerCounter(SLASH_COMMANDS_PROCESSED_COUNTER, "Slash Commands processed"); metricService.registerCounter(SLASH_COMMANDS_PROCESSED_COUNTER, "Slash Commands processed");
executions = executions executions = executions
.stream() .stream()
.filter(PostCommandExecution::supportsSlash) .filter(PostCommandExecution::supportsSlash)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
} }

View File

@@ -218,114 +218,116 @@ public class ChannelServiceBean implements ChannelService {
Span newSpan = tracer.nextSpan().name("send-message"); Span newSpan = tracer.nextSpan().name("send-message");
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) { try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
newSpan.tag("channel.id", textChannel.getIdLong()); newSpan.tag("channel.id", textChannel.getIdLong());
messageToSend.setEphemeral(false); messageToSend.setEphemeral(false);
if(textChannel instanceof GuildMessageChannel guildMessageChannel) { if (textChannel instanceof GuildMessageChannel guildMessageChannel) {
long maxFileSize = guildMessageChannel.getGuild().getMaxFileSize(); long maxFileSize = guildMessageChannel.getGuild().getMaxFileSize();
// in this case, we cannot upload the file, so we need to fail // in this case, we cannot upload the file, so we need to fail
messageToSend.getAttachedFiles().forEach(attachedFile -> { messageToSend.getAttachedFiles().forEach(attachedFile -> {
if(attachedFile.getFile().length() > maxFileSize) { if (attachedFile.getFile().length() > maxFileSize) {
throw new UploadFileTooLargeException(attachedFile.getFile().length(), maxFileSize); throw new UploadFileTooLargeException(attachedFile.getFile().length(), maxFileSize);
} }
}); });
} }
List<CompletableFuture<Message>> futures = new ArrayList<>(); List<CompletableFuture<Message>> futures = new ArrayList<>();
List<MessageCreateAction> allMessageActions = new ArrayList<>(); List<MessageCreateAction> allMessageActions = new ArrayList<>();
if(messageToSend.getUseComponentsV2() && messageToSend.getComponents() != null && !messageToSend.getComponents().isEmpty()) { if (messageToSend.getUseComponentsV2() && messageToSend.getComponents() != null && !messageToSend.getComponents().isEmpty()) {
metricService.incrementCounter(MESSAGE_SEND_METRIC);
allMessageActions.add(textChannel.sendMessageComponents(messageToSend.getComponents()).useComponentsV2());
} else {
Iterator<MessageEmbed> embedIterator = messageToSend.getEmbeds().iterator();
for (int i = 0; i < messageToSend.getMessages().size(); i++) {
metricService.incrementCounter(MESSAGE_SEND_METRIC); metricService.incrementCounter(MESSAGE_SEND_METRIC);
String text = messageToSend.getMessages().get(i); allMessageActions.add(textChannel.sendMessageComponents(messageToSend.getComponents()).useComponentsV2());
} else {
Iterator<MessageEmbed> embedIterator = messageToSend.getEmbeds().iterator();
for (int i = 0; i < messageToSend.getMessages().size(); i++) {
metricService.incrementCounter(MESSAGE_SEND_METRIC);
String text = messageToSend.getMessages().get(i);
List<MessageEmbed> messageEmbeds = new ArrayList<>();
while (embedIterator.hasNext()) {
MessageEmbed embedToAdd = embedIterator.next();
if ((currentEmbedLength(messageEmbeds) + embedToAdd.getLength()) >= MessageEmbed.EMBED_MAX_LENGTH_BOT) {
break;
}
messageEmbeds.add(embedToAdd);
embedIterator.remove();
}
MessageCreateAction messageAction = textChannel.sendMessage(text);
if (!messageEmbeds.isEmpty()) {
messageAction.setEmbeds(messageEmbeds);
}
allMessageActions.add(messageAction);
}
List<MessageEmbed> messageEmbeds = new ArrayList<>(); List<MessageEmbed> messageEmbeds = new ArrayList<>();
while(embedIterator.hasNext()) { // reset the iterator, because if the if in the above while iterator loop applied, we already took it out from the iterator
// but we didnt add it yet, so it would be lost
embedIterator = messageToSend.getEmbeds().iterator();
while (embedIterator.hasNext()) {
MessageEmbed embedToAdd = embedIterator.next(); MessageEmbed embedToAdd = embedIterator.next();
if((currentEmbedLength(messageEmbeds) + embedToAdd.getLength()) >= MessageEmbed.EMBED_MAX_LENGTH_BOT) { if ((currentEmbedLength(messageEmbeds) + embedToAdd.getLength()) >= MessageEmbed.EMBED_MAX_LENGTH_BOT && !messageEmbeds.isEmpty()) {
break; allMessageActions.add(textChannel.sendMessageEmbeds(messageEmbeds));
metricService.incrementCounter(MESSAGE_SEND_METRIC);
messageEmbeds = new ArrayList<>();
} }
messageEmbeds.add(embedToAdd); messageEmbeds.add(embedToAdd);
embedIterator.remove();
} }
MessageCreateAction messageAction = textChannel.sendMessage(text);
if(!messageEmbeds.isEmpty()) { if (!messageEmbeds.isEmpty()) {
messageAction.setEmbeds(messageEmbeds);
}
allMessageActions.add(messageAction);
}
List<MessageEmbed> messageEmbeds = new ArrayList<>();
// reset the iterator, because if the if in the above while iterator loop applied, we already took it out from the iterator
// but we didnt add it yet, so it would be lost
embedIterator = messageToSend.getEmbeds().iterator();
while(embedIterator.hasNext()) {
MessageEmbed embedToAdd = embedIterator.next();
if((currentEmbedLength(messageEmbeds) + embedToAdd.getLength()) >= MessageEmbed.EMBED_MAX_LENGTH_BOT && !messageEmbeds.isEmpty()) {
allMessageActions.add(textChannel.sendMessageEmbeds(messageEmbeds)); allMessageActions.add(textChannel.sendMessageEmbeds(messageEmbeds));
metricService.incrementCounter(MESSAGE_SEND_METRIC); metricService.incrementCounter(MESSAGE_SEND_METRIC);
messageEmbeds = new ArrayList<>();
} }
messageEmbeds.add(embedToAdd);
}
if(!messageEmbeds.isEmpty()) { List<ActionRow> actionRows = messageToSend.getActionRows();
allMessageActions.add(textChannel.sendMessageEmbeds(messageEmbeds)); if (!actionRows.isEmpty()) {
metricService.incrementCounter(MESSAGE_SEND_METRIC); List<List<ActionRow>> groupedActionRows = ListUtils.partition(actionRows, ComponentService.MAX_BUTTONS_PER_ROW);
} for (int i = 0; i < allMessageActions.size(); i++) {
allMessageActions.set(i, allMessageActions.get(i).setComponents(groupedActionRows.get(i)));
List<ActionRow> actionRows = messageToSend.getActionRows(); }
if(!actionRows.isEmpty()) { for (int i = allMessageActions.size(); i < groupedActionRows.size(); i++) {
List<List<ActionRow>> groupedActionRows = ListUtils.partition(actionRows, ComponentService.MAX_BUTTONS_PER_ROW); // TODO maybe possible nicer
for (int i = 0; i < allMessageActions.size(); i++) { allMessageActions.add(textChannel.sendMessage(".").setComponents(groupedActionRows.get(i)));
allMessageActions.set(i, allMessageActions.get(i).setComponents(groupedActionRows.get(i))); }
} AServer server = null;
for (int i = allMessageActions.size(); i < groupedActionRows.size(); i++) { if (textChannel instanceof GuildChannel) {
// TODO maybe possible nicer GuildChannel channel = (GuildChannel) textChannel;
allMessageActions.add(textChannel.sendMessage(".").setComponents(groupedActionRows.get(i))); server = serverManagementService.loadServer(channel.getGuild());
} }
AServer server = null; for (ActionRow row : actionRows) {
if(textChannel instanceof GuildChannel) { for (ActionRowChildComponent component : row) {
GuildChannel channel = (GuildChannel) textChannel; if (component instanceof ActionComponent) {
server = serverManagementService.loadServer(channel.getGuild()); String id = ((ActionComponent) component).getId();
} MessageToSend.ComponentConfig payload = messageToSend.getComponentPayloads().get(id);
for (ActionRow row : actionRows) { if (payload != null && payload.getPersistCallback()) {
for (ActionRowChildComponent component : row) { componentPayloadManagementService.createPayload(id, payload.getPayload(), payload.getPayloadType(),
if (component instanceof ActionComponent) { payload.getComponentOrigin(), server, payload.getComponentType());
String id = ((ActionComponent) component).getId(); }
MessageToSend.ComponentConfig payload = messageToSend.getComponentPayloads().get(id);
if (payload != null && payload.getPersistCallback()) {
componentPayloadManagementService.createPayload(id, payload.getPayload(), payload.getPayloadType(), payload.getComponentOrigin(), server, payload.getComponentType());
} }
} }
} }
} }
}
if(messageToSend.hasFilesToSend()) { if (messageToSend.hasFilesToSend()) {
List<FileUpload> attachedFiles = messageToSend List<FileUpload> attachedFiles = messageToSend
.getAttachedFiles() .getAttachedFiles()
.stream() .stream()
.map(AttachedFile::convertToFileUpload) .map(AttachedFile::convertToFileUpload)
.collect(Collectors.toList()); .collect(Collectors.toList());
if(!allMessageActions.isEmpty()) { if (!allMessageActions.isEmpty()) {
// in case there has not been a message, we need to increment it // in case there has not been a message, we need to increment it
allMessageActions.set(0, allMessageActions.get(0).addFiles(attachedFiles)); allMessageActions.set(0, allMessageActions.get(0).addFiles(attachedFiles));
} else { } else {
metricService.incrementCounter(MESSAGE_SEND_METRIC); metricService.incrementCounter(MESSAGE_SEND_METRIC);
allMessageActions.add(textChannel.sendFiles(attachedFiles)); allMessageActions.add(textChannel.sendFiles(attachedFiles));
}
} }
Set<Message.MentionType> allowedMentions = allowedMentionService.getAllowedMentionsFor(textChannel, messageToSend);
allMessageActions.forEach(messageAction -> {
if (messageToSend.getReferencedMessageId() != null) {
messageAction = messageAction.setMessageReference(messageToSend.getReferencedMessageId());
if (messageToSend.getMessageConfig() != null && !messageToSend.getMessageConfig().getMentionsReferencedMessage()) {
messageAction = messageAction.mentionRepliedUser(false);
}
}
futures.add(messageAction.setAllowedMentions(allowedMentions).submit());
});
} }
return futures;
} }
Set<Message.MentionType> allowedMentions = allowedMentionService.getAllowedMentionsFor(textChannel, messageToSend);
allMessageActions.forEach(messageAction -> {
if(messageToSend.getReferencedMessageId() != null) {
messageAction = messageAction.setMessageReference(messageToSend.getReferencedMessageId());
if(messageToSend.getMessageConfig() != null && !messageToSend.getMessageConfig().getMentionsReferencedMessage()) {
messageAction = messageAction.mentionRepliedUser(false);
}
}
futures.add(messageAction.setAllowedMentions(allowedMentions).submit());
});
return futures;
} }
private Integer currentEmbedLength(List<MessageEmbed> messageEmbeds) { private Integer currentEmbedLength(List<MessageEmbed> messageEmbeds) {