[AB-xxx] do not delete embedding message if the message embedding fails

fixing code for top level container config (not sure how that worked before)
This commit is contained in:
Sheldan
2026-01-25 00:02:30 +01:00
parent 4dc92fe49b
commit 2f125d0101
2 changed files with 34 additions and 17 deletions

View File

@@ -13,9 +13,13 @@ import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.MessageCache; import dev.sheldan.abstracto.core.service.MessageCache;
import dev.sheldan.abstracto.core.service.MessageService; import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.abstracto.linkembed.config.LinkEmbedFeatureDefinition; import dev.sheldan.abstracto.linkembed.config.LinkEmbedFeatureDefinition;
import dev.sheldan.abstracto.linkembed.model.MessageEmbedLink; import dev.sheldan.abstracto.linkembed.model.MessageEmbedLink;
import dev.sheldan.abstracto.linkembed.service.MessageEmbedService; import dev.sheldan.abstracto.linkembed.service.MessageEmbedService;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.Event; import net.dv8tion.jda.api.events.Event;
@@ -27,7 +31,6 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
@Component @Component
@Slf4j @Slf4j
@@ -67,37 +70,51 @@ public class MessageEmbedListener implements MessageReceivedListener {
} }
String messageRaw = message.getContentRaw(); String messageRaw = message.getContentRaw();
List<MessageEmbedLink> links = messageEmbedService.getLinksInMessage(messageRaw); List<MessageEmbedLink> links = messageEmbedService.getLinksInMessage(messageRaw);
for (MessageEmbedLink messageEmbedLink : links) {
messageRaw = messageRaw.replace(messageEmbedLink.getWholeUrl(), "");
}
boolean deleteMessage = StringUtils.isBlank(messageRaw) && !links.isEmpty() && message.getAttachments().isEmpty();
if(!links.isEmpty()) { if(!links.isEmpty()) {
Long messageId = message.getIdLong();
Long channelId = message.getChannelIdLong();
Long serverId = message.getGuildIdLong();
log.debug("We found {} links to embed in message {} in channel {} in guild {}.", links.size(), message.getId(), message.getChannel().getId(), message.getGuild().getId()); log.debug("We found {} links to embed in message {} in channel {} in guild {}.", links.size(), message.getId(), message.getChannel().getId(), message.getGuild().getId());
Long userEmbeddingUserInServerId = userInServerManagementService.loadOrCreateUser(message.getMember()).getUserInServerId(); Long userEmbeddingUserInServerId = userInServerManagementService.loadOrCreateUser(message.getMember()).getUserInServerId();
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (MessageEmbedLink messageEmbedLink : links) { for (MessageEmbedLink messageEmbedLink : links) {
// potentially support foreign linked servers // potentially support foreign linked servers?
if(!messageEmbedLink.getServerId().equals(message.getGuild().getIdLong())) { if(!messageEmbedLink.getServerId().equals(message.getGuild().getIdLong())) {
log.info("Link for message {} was from a foreign server {}. Do not embed.", messageEmbedLink.getMessageId(), messageEmbedLink.getServerId()); log.info("Link for message {} was from a foreign server {}. Do not embed.", messageEmbedLink.getMessageId(), messageEmbedLink.getServerId());
continue; continue;
} }
messageRaw = messageRaw.replace(messageEmbedLink.getWholeUrl(), ""); Function<CachedMessage, CompletableFuture<Void>> cachedMessageConsumer = cachedMessage -> self.embedSingleLink(message, userEmbeddingUserInServerId, cachedMessage);
Consumer<CachedMessage> cachedMessageConsumer = cachedMessage -> self.embedSingleLink(message, userEmbeddingUserInServerId, cachedMessage); futures.add(messageCache.getMessageFromCache(messageEmbedLink.getServerId(), messageEmbedLink.getChannelId(), messageEmbedLink.getMessageId())
messageCache.getMessageFromCache(messageEmbedLink.getServerId(), messageEmbedLink.getChannelId(), messageEmbedLink.getMessageId()) .thenCompose(cachedMessageConsumer));
.thenAccept(cachedMessageConsumer) }
.exceptionally(throwable -> { if(!futures.isEmpty()) {
log.error("Error when embedding link for message {}", message.getId(), throwable); // only delete the message if all futures go through
return null; new CompletableFutureList<>(futures).getMainFuture().thenAccept(unused -> {
}); if(deleteMessage) {
messageService.deleteMessageInChannelInServer(serverId, channelId, messageId);
}
}).thenAccept(unused -> {
log.info("Deleted embedding message server {} channel {} message {}.", serverId, channelId, messageId);
}).exceptionally(throwable -> {
log.info("Failed to delete embedding message or to embed message server {} channel {} message {}.", serverId, channelId, messageId, throwable);
return null;
});
} }
} }
if(StringUtils.isBlank(messageRaw) && !links.isEmpty() && message.getAttachments().isEmpty()) { if(deleteMessage) {
messageService.deleteMessage(message);
return ConsumableListenerResult.DELETED; return ConsumableListenerResult.DELETED;
} } else if(!links.isEmpty()) {
if(!links.isEmpty()) {
return ConsumableListenerResult.PROCESSED; return ConsumableListenerResult.PROCESSED;
} }
return ConsumableListenerResult.IGNORED; return ConsumableListenerResult.IGNORED;
} }
@Transactional @Transactional
public void embedSingleLink(Message message, Long cause, CachedMessage cachedMessage) { public CompletableFuture<Void> embedSingleLink(Message message, Long cause, CachedMessage cachedMessage) {
GuildMemberMessageChannel context = GuildMemberMessageChannel GuildMemberMessageChannel context = GuildMemberMessageChannel
.builder() .builder()
.guildChannel(message.getGuildChannel()) .guildChannel(message.getGuildChannel())
@@ -107,7 +124,7 @@ public class MessageEmbedListener implements MessageReceivedListener {
.build(); .build();
log.info("Embedding link to message {} in channel {} in server {} to channel {} and server {}.", log.info("Embedding link to message {} in channel {} in server {} to channel {} and server {}.",
cachedMessage.getMessageId(), cachedMessage.getChannelId(), cachedMessage.getServerId(), message.getChannel().getId(), message.getGuild().getId()); cachedMessage.getMessageId(), cachedMessage.getChannelId(), cachedMessage.getServerId(), message.getChannel().getId(), message.getGuild().getId());
messageEmbedService.embedLink(cachedMessage, message.getGuildChannel(), cause , context).thenAccept(unused -> return messageEmbedService.embedLink(cachedMessage, message.getGuildChannel(), cause , context).thenAccept(unused ->
metricService.incrementCounter(MESSAGE_EMBED_CREATED) metricService.incrementCounter(MESSAGE_EMBED_CREATED)
).exceptionally(throwable -> { ).exceptionally(throwable -> {
log.error("Failed to embed link towards message {} in channel {} in sever {} linked from message {} in channel {} in server {}.", cachedMessage.getMessageId(), cachedMessage.getChannelId(), cachedMessage.getServerId(), log.error("Failed to embed link towards message {} in channel {} in sever {} linked from message {} in channel {} in server {}.", cachedMessage.getMessageId(), cachedMessage.getChannelId(), cachedMessage.getServerId(),

View File

@@ -8,6 +8,6 @@ import lombok.experimental.SuperBuilder;
public class TopLevelContainerConfig extends ContainerConfig implements ComponentConfig { public class TopLevelContainerConfig extends ContainerConfig implements ComponentConfig {
@Override @Override
public ComponentTypeConfig getType() { public ComponentTypeConfig getType() {
return ComponentTypeConfig.SECTION; return ComponentTypeConfig.CONTAINER;
} }
} }