mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-01 15:28:35 +00:00
Compare commits
2 Commits
feature/us
...
release-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58632bcf9d | ||
|
|
592ac01bfa |
2
.env
2
.env
@@ -1,2 +1,2 @@
|
||||
REGISTRY_PREFIX=harbor.sheldan.dev/abstracto/
|
||||
VERSION=1.5.60
|
||||
VERSION=1.6.0
|
||||
1
.github/workflows/release_manual.yml
vendored
1
.github/workflows/release_manual.yml
vendored
@@ -39,6 +39,7 @@ jobs:
|
||||
git-release-bot-name: "release-bot"
|
||||
git-release-bot-email: "release-bot@sheldan.dev"
|
||||
release-branch-name: master
|
||||
version-minor: true
|
||||
maven-args: "-Dmaven.javadoc.skip=true -s settings.xml -DskipTests"
|
||||
access-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Install node dependencies and build
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageEmbeddedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.PostedImageManagement;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.EmbedType;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RepostEmbedListener implements AsyncMessageEmbeddedListener {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelService repostCheckChannelService;
|
||||
|
||||
@Autowired
|
||||
private RepostService repostService;
|
||||
|
||||
@Autowired
|
||||
private PostedImageManagement repostManagement;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(GuildMessageEmbedEventModel eventModel) {
|
||||
AChannel channel = channelManagementService.loadChannel(eventModel.getChannelId());
|
||||
if(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)) {
|
||||
if(repostManagement.messageEmbedsHaveBeenCovered(eventModel.getMessageId())) {
|
||||
log.info("The embeds of the message {} in channel {} in server {} have already been covered by repost check -- ignoring.",
|
||||
eventModel.getMessageId(), eventModel.getChannelId(), eventModel.getServerId());
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
channelService.retrieveMessageInChannel(eventModel.getServerId(), eventModel.getChannelId(), eventModel.getMessageId()).thenAccept(message -> {
|
||||
List<MessageEmbed> imageEmbeds = eventModel.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
|
||||
if(!imageEmbeds.isEmpty()) {
|
||||
repostService.processMessageEmbedsRepostCheck(imageEmbeds, message);
|
||||
}
|
||||
});
|
||||
}
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.PostedImageManagement;
|
||||
import net.dv8tion.jda.api.entities.EmbedType;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RepostEmbedListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private RepostEmbedListener testUnit;
|
||||
|
||||
@Mock
|
||||
private RepostCheckChannelService repostCheckChannelService;
|
||||
|
||||
@Mock
|
||||
private RepostService repostService;
|
||||
|
||||
@Mock
|
||||
private PostedImageManagement repostManagement;
|
||||
|
||||
@Mock
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Mock
|
||||
private ChannelService channelService;
|
||||
|
||||
@Mock
|
||||
private GuildMessageEmbedEventModel model;
|
||||
|
||||
@Mock
|
||||
private TextChannel textChannel;
|
||||
|
||||
@Mock
|
||||
private Message message;
|
||||
|
||||
@Mock
|
||||
private AChannel channel;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<List<MessageEmbed>> embedListsParameterCaptor;
|
||||
|
||||
private static final Long MESSAGE_ID = 1L;
|
||||
private static final Long CHANNEL_ID = 2L;
|
||||
private static final Long SERVER_ID = 3L;
|
||||
|
||||
@Test
|
||||
public void testExecuteCheckDisabled() {
|
||||
when(model.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
testUnit.execute(model);
|
||||
verify(repostManagement, times(0)).messageEmbedsHaveBeenCovered(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteEmbedsHaveBeenCovered() {
|
||||
channelSetup();
|
||||
setupMessageHasBeenCovered(true);
|
||||
testUnit.execute(model);
|
||||
verify(repostService, times(0)).processMessageEmbedsRepostCheck(anyList(), any(Message.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteNoEmbeds() {
|
||||
channelSetup();
|
||||
setupMessageHasBeenCovered(false);
|
||||
when(channelService.retrieveMessageInChannel(SERVER_ID, CHANNEL_ID, MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(message));
|
||||
testUnit.execute(model);
|
||||
verify(repostService, times(0)).processMessageEmbedsRepostCheck(anyList(), any(Message.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteOneImageEmbed() {
|
||||
channelSetup();
|
||||
setupMessageHasBeenCovered(false);
|
||||
MessageEmbed imageEmbed = Mockito.mock(MessageEmbed.class);
|
||||
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
|
||||
when(model.getEmbeds()).thenReturn(Arrays.asList(imageEmbed));
|
||||
when(channelService.retrieveMessageInChannel(SERVER_ID, CHANNEL_ID, MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(message));
|
||||
testUnit.execute(model);
|
||||
verifySingleEmbedProcessed(imageEmbed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteMultipleEmbedsOneImage() {
|
||||
channelSetup();
|
||||
setupMessageHasBeenCovered(false);
|
||||
MessageEmbed imageEmbed = Mockito.mock(MessageEmbed.class);
|
||||
MessageEmbed nonImageEmbed = Mockito.mock(MessageEmbed.class);
|
||||
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
|
||||
when(nonImageEmbed.getType()).thenReturn(EmbedType.LINK);
|
||||
when(model.getEmbeds()).thenReturn(Arrays.asList(imageEmbed, nonImageEmbed));
|
||||
when(channelService.retrieveMessageInChannel(SERVER_ID, CHANNEL_ID, MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(message));
|
||||
testUnit.execute(model);
|
||||
verifySingleEmbedProcessed(imageEmbed);
|
||||
}
|
||||
|
||||
private void setupMessageHasBeenCovered(boolean covered) {
|
||||
when(model.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(repostManagement.messageEmbedsHaveBeenCovered(MESSAGE_ID)).thenReturn(covered);
|
||||
}
|
||||
|
||||
private void verifySingleEmbedProcessed(MessageEmbed imageEmbed) {
|
||||
verify(repostService, times(1)).processMessageEmbedsRepostCheck(embedListsParameterCaptor.capture(), eq(message));
|
||||
List<MessageEmbed> embeds = embedListsParameterCaptor.getValue();
|
||||
Assert.assertEquals(1, embeds.size());
|
||||
Assert.assertEquals(imageEmbed, embeds.get(0));
|
||||
}
|
||||
|
||||
|
||||
private void channelSetup() {
|
||||
when(model.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(channel);
|
||||
when(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)).thenReturn(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -52,11 +52,6 @@ public class ListenerExecutorConfig {
|
||||
return executorService.setupExecutorFor("messageReceivedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "messageEmbeddedExecutor")
|
||||
public TaskExecutor messageEmbeddedExecutor() {
|
||||
return executorService.setupExecutorFor("messageEmbeddedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "messageUpdatedExecutor")
|
||||
public TaskExecutor messageUpdatedExecutor() {
|
||||
return executorService.setupExecutorFor("messageUpdatedListener");
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
package dev.sheldan.abstracto.core.listener.async.jda;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.message.MessageEmbedEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
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.Transactional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AsyncMessageEmbeddedListenerBean extends ListenerAdapter {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<AsyncMessageEmbeddedListener> listenerList;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("messageEmbeddedExecutor")
|
||||
private TaskExecutor messageEmbeddedListener;
|
||||
|
||||
@Autowired
|
||||
private AsyncMessageEmbeddedListenerBean self;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onMessageEmbed(@Nonnull MessageEmbedEvent event) {
|
||||
if(listenerList == null) return;
|
||||
GuildMessageEmbedEventModel model = getModel(event);
|
||||
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, messageEmbeddedListener));
|
||||
}
|
||||
|
||||
private GuildMessageEmbedEventModel getModel(MessageEmbedEvent event) {
|
||||
return GuildMessageEmbedEventModel
|
||||
.builder()
|
||||
.channelId(event.getChannel().getIdLong())
|
||||
.serverId(event.getGuild().getIdLong())
|
||||
.embeds(event.getMessageEmbeds())
|
||||
.messageId(event.getMessageIdLong())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package dev.sheldan.abstracto.core.listener.sync.jda;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.MessageCache;
|
||||
import dev.sheldan.abstracto.core.utils.BeanUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.message.MessageEmbedEvent;
|
||||
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.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MessageEmbeddedListenerBean extends ListenerAdapter {
|
||||
|
||||
@Autowired
|
||||
private MessageCache messageCache;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<MessageEmbeddedListener> listenerList;
|
||||
|
||||
@Autowired
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private ExceptionService exceptionService;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onMessageEmbed(@Nonnull MessageEmbedEvent event) {
|
||||
if(listenerList == null) return;
|
||||
GuildMessageEmbedEventModel model = buildModel(event);
|
||||
listenerList.forEach(messageReceivedListener -> listenerService.executeFeatureAwareListener(messageReceivedListener, model));
|
||||
}
|
||||
|
||||
private GuildMessageEmbedEventModel buildModel(MessageEmbedEvent event) {
|
||||
return GuildMessageEmbedEventModel
|
||||
.builder()
|
||||
.channelId(event.getChannel().getIdLong())
|
||||
.serverId(event.getGuild().getIdLong())
|
||||
.embeds(event.getMessageEmbeds())
|
||||
.messageId(event.getMessageIdLong())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
|
||||
public void executeIndividualGuildMessageReceivedListener(GuildMessageEmbedEventModel model, MessageEmbeddedListener messageReceivedListener) {
|
||||
messageReceivedListener.execute(model);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
BeanUtils.sortPrioritizedListeners(listenerList);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package dev.sheldan.abstracto.core.listener.async.jda;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.FeatureAwareListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
|
||||
|
||||
public interface AsyncMessageEmbeddedListener extends FeatureAwareListener<GuildMessageEmbedEventModel, DefaultListenerResult> {
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package dev.sheldan.abstracto.core.listener.sync.jda;
|
||||
|
||||
import dev.sheldan.abstracto.core.Prioritized;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.FeatureAwareListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
|
||||
|
||||
public interface MessageEmbeddedListener extends FeatureAwareListener<GuildMessageEmbedEventModel, DefaultListenerResult>, Prioritized {
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package dev.sheldan.abstracto.core.models.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.FeatureAwareListenerModel;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class GuildMessageEmbedEventModel implements FeatureAwareListenerModel {
|
||||
@Builder.Default
|
||||
private List<MessageEmbed> embeds = new ArrayList<>();
|
||||
private Long messageId;
|
||||
private Long channelId;
|
||||
private Long serverId;
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
public class ContextUtils {
|
||||
|
||||
public static boolean isGuildKnown(Interaction interaction) {
|
||||
return interaction.hasFullGuild();
|
||||
return interaction.isFromAttachedGuild();
|
||||
}
|
||||
|
||||
public static boolean isGuildNotKnown(Interaction interaction) {
|
||||
@@ -25,7 +25,7 @@ public class ContextUtils {
|
||||
}
|
||||
|
||||
public static boolean isUserCommand(Interaction interaction) {
|
||||
return interaction.getIntegrationOwners().getUserIntegration() != null && interaction.getIntegrationOwners().getGuildIntegration() == null;
|
||||
return interaction.getIntegrationOwners().isUserIntegration();
|
||||
}
|
||||
|
||||
public static boolean isNotUserCommand(Interaction interaction) {
|
||||
|
||||
Reference in New Issue
Block a user