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

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

View File

@@ -0,0 +1,31 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.sync.entity.AsyncChannelGroupCreatedListener;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.listener.ChannelGroupCreatedListenerModel;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class RepostCheckAsyncChannelGroupCreatedListener implements AsyncChannelGroupCreatedListener {
@Autowired
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
@Autowired
private ChannelGroupManagementService channelGroupManagementService;
@Override
public DefaultListenerResult execute(ChannelGroupCreatedListenerModel model) {
AChannelGroup channelGroup = channelGroupManagementService.findChannelGroupById(model.getChannelGroupId());
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
checkChannelGroupManagement.createRepostCheckChannelGroup(channelGroup);
return DefaultListenerResult.PROCESSED;
}
return DefaultListenerResult.IGNORED;
}
}

View File

@@ -0,0 +1,31 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.sync.entity.AsyncChannelGroupDeletedListener;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.listener.ChannelGroupDeletedListenerModel;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class RepostCheckAsyncChannelGroupDeletedListener implements AsyncChannelGroupDeletedListener {
@Autowired
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
@Autowired
private ChannelGroupManagementService channelGroupManagementService;
@Override
public DefaultListenerResult execute(ChannelGroupDeletedListenerModel model) {
AChannelGroup channelGroup = channelGroupManagementService.findChannelGroupById(model.getChannelGroupId());
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
checkChannelGroupManagement.deleteRepostCheckChannelGroup(channelGroup);
return DefaultListenerResult.PROCESSED;
}
return DefaultListenerResult.IGNORED;
}
}

View File

@@ -1,22 +0,0 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.listener.sync.entity.ChannelGroupCreatedListener;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class RepostCheckChannelGroupCreatedListener implements ChannelGroupCreatedListener {
@Autowired
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
@Override
public void channelGroupCreated(AChannelGroup channelGroup) {
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
checkChannelGroupManagement.createRepostCheckChannelGroup(channelGroup);
}
}
}

View File

@@ -1,22 +0,0 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.listener.sync.entity.ChannelGroupDeletedListener;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class RepostCheckChannelGroupDeletedListener implements ChannelGroupDeletedListener {
@Autowired
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
@Override
public void channelGroupDeleted(AChannelGroup channelGroup) {
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
checkChannelGroupManagement.deleteRepostCheckChannelGroup(channelGroup);
}
}
}

View File

@@ -1,6 +1,7 @@
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;
@@ -39,13 +40,13 @@ public class RepostEmbedListener implements AsyncMessageEmbeddedListener {
private ChannelService channelService;
@Override
public void execute(GuildMessageEmbedEventModel eventModel) {
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;
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());
@@ -54,6 +55,7 @@ public class RepostEmbedListener implements AsyncMessageEmbeddedListener {
}
});
}
return DefaultListenerResult.PROCESSED;
}
@Override

View File

@@ -1,16 +1,18 @@
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.AsyncMessageReceivedListener;
import dev.sheldan.abstracto.core.models.cache.CachedEmbed;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
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 lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.EmbedType;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -32,13 +34,16 @@ public class RepostMessageReceivedListener implements AsyncMessageReceivedListen
private ChannelManagementService channelManagementService;
@Override
public void execute(CachedMessage message) {
AChannel channel = channelManagementService.loadChannel(message.getChannelId());
public DefaultListenerResult execute(MessageReceivedModel model) {
Message message = model.getMessage();
AChannel channel = channelManagementService.loadChannel(message.getTextChannel().getIdLong());
if(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)) {
repostService.processMessageAttachmentRepostCheck(message);
List<CachedEmbed> imageEmbeds = message.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
List<MessageEmbed> imageEmbeds = message.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
repostService.processMessageEmbedsRepostCheck(imageEmbeds, message);
return DefaultListenerResult.PROCESSED;
}
return DefaultListenerResult.IGNORED;
}
@Override

View File

@@ -172,6 +172,18 @@ public class RepostServiceBean implements RepostService {
return checkForDuplicates(serverChannelMessageUser, index, attachment.getProxyUrl());
}
@Override
public Optional<PostedImage> getRepostFor(Message message, Message.Attachment attachment, Integer index) {
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
.builder()
.serverId(message.getGuild().getIdLong())
.channelId(message.getChannel().getIdLong())
.userId(message.getAuthor().getIdLong())
.messageId(message.getIdLong())
.build();
return checkForDuplicates(serverChannelMessageUser, index, attachment.getProxyUrl());
}
@Override
public String calculateHashForPost(String url, Long serverId) {
File downloadedFile = null;
@@ -204,6 +216,14 @@ public class RepostServiceBean implements RepostService {
}
}
@Override
public void processMessageAttachmentRepostCheck(Message message) {
boolean canThereBeMultipleReposts = message.getAttachments().size() > 1;
for (int imageIndex = 0; imageIndex < message.getAttachments().size(); imageIndex++) {
executeRepostCheckForAttachment(message, message.getAttachments().get(imageIndex), imageIndex, canThereBeMultipleReposts);
}
}
private void executeRepostCheckForAttachment(CachedMessage message, CachedAttachment attachment, Integer index, boolean moreRepostsPossible) {
Optional<PostedImage> originalPostOptional = getRepostFor(message, attachment, index);
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
@@ -216,6 +236,18 @@ public class RepostServiceBean implements RepostService {
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(serverChannelMessageUser, index, moreRepostsPossible, postedImage));
}
private void executeRepostCheckForAttachment(Message message, Message.Attachment attachment, Integer index, boolean moreRepostsPossible) {
Optional<PostedImage> originalPostOptional = getRepostFor(message, attachment, index);
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
.builder()
.serverId(message.getGuild().getIdLong())
.channelId(message.getChannel().getIdLong())
.userId(message.getAuthor().getIdLong())
.messageId(message.getIdLong())
.build();
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(serverChannelMessageUser, index, moreRepostsPossible, postedImage));
}
private void markMessageAndPersist(ServerChannelMessageUser messageUser, Integer index, boolean moreRepostsPossible, PostedImage originalPost) {
log.info("Detected repost in message embed {} of message {} in channel {} in server {}.", index, messageUser.getMessageId(), messageUser.getChannelId(), messageUser.getServerId());
CompletableFuture<Void> markerFuture = reactionService.addReactionToMessageAsync(REPOST_MARKER_EMOTE_KEY, messageUser.getServerId(), messageUser.getChannelId(), messageUser.getMessageId());

View File

@@ -34,8 +34,7 @@ public class PostedImageManagementBean implements PostedImageManagement {
.postedChannel(creation.getChannel())
.build();
postedImageRepository.save(post);
return post;
return postedImageRepository.save(post);
}
@Override

View File

@@ -49,8 +49,7 @@ public class RepostCheckChannelGroupManagementBean implements RepostCheckChannel
.id(channelGroup.getId())
.build();
repository.save(repostCheckChannelGroup);
return repostCheckChannelGroup;
return repository.save(repostCheckChannelGroup);
}
@Override

View File

@@ -32,8 +32,7 @@ public class RepostManagementServiceBean implements RepostManagementService {
.count(1)
.build();
repostRepository.save(repost);
return repost;
return repostRepository.save(repost);
}
@Override

View File

@@ -1,7 +1,10 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.command.exception.ChannelGroupNotFoundByIdException;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
import dev.sheldan.abstracto.core.models.listener.ChannelGroupCreatedListenerModel;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import org.junit.Test;
@@ -13,35 +16,53 @@ import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostCheckChannelGroupCreatedListenerTest {
public class RepostCheckAsyncChannelGroupCreatedListenerTest {
@InjectMocks
private RepostCheckChannelGroupCreatedListener testUnit;
private RepostCheckAsyncChannelGroupCreatedListener testUnit;
@Mock
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
@Mock
private ChannelGroupManagementService channelGroupManagementService;
@Mock
private AChannelGroup channelGroup;
@Mock
private ChannelGroupCreatedListenerModel model;
@Mock
private ChannelGroupType channelGroupType;
private static final String INCORRECT_TYPE = "incorrectType";
private static final Long CHANNEL_GROUP_ID = 1L;
@Test
public void testChannelGroupCreated() {
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
when(channelGroupType.getGroupTypeKey()).thenReturn(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
testUnit.channelGroupCreated(channelGroup);
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenReturn(channelGroup);
testUnit.execute(model);
verify(checkChannelGroupManagement, times(1)).createRepostCheckChannelGroup(channelGroup);
}
@Test(expected = ChannelGroupNotFoundByIdException.class)
public void testChannelGroupNotExisting() {
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenThrow(new ChannelGroupNotFoundByIdException());
testUnit.execute(model);
}
@Test
public void testChannelGroupCreatedIncorrectType() {
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
when(channelGroupType.getGroupTypeKey()).thenReturn(INCORRECT_TYPE);
testUnit.channelGroupCreated(channelGroup);
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenReturn(channelGroup);
testUnit.execute(model);
verify(checkChannelGroupManagement, times(0)).createRepostCheckChannelGroup(channelGroup);
}
}

View File

@@ -1,7 +1,10 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.command.exception.ChannelGroupNotFoundByIdException;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
import dev.sheldan.abstracto.core.models.listener.ChannelGroupDeletedListenerModel;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import org.junit.Test;
@@ -13,35 +16,53 @@ import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostCheckChannelGroupDeletedListenerTest {
public class RepostCheckAsyncChannelGroupDeletedListenerTest {
@InjectMocks
private RepostCheckChannelGroupDeletedListener testUnit;
private RepostCheckAsyncChannelGroupDeletedListener testUnit;
@Mock
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
@Mock
private ChannelGroupManagementService channelGroupManagementService;
@Mock
private AChannelGroup channelGroup;
@Mock
private ChannelGroupType channelGroupType;
@Mock
private ChannelGroupDeletedListenerModel model;
private static final String INCORRECT_TYPE = "incorrectType";
private static final Long CHANNEL_GROUP_ID = 1L;
@Test
public void testChannelGroupDeleted() {
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
when(channelGroupType.getGroupTypeKey()).thenReturn(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
testUnit.channelGroupDeleted(channelGroup);
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenReturn(channelGroup);
testUnit.execute(model);
verify(checkChannelGroupManagement, times(1)).deleteRepostCheckChannelGroup(channelGroup);
}
@Test(expected = ChannelGroupNotFoundByIdException.class)
public void testChannelGroupNotExisting() {
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenThrow(new ChannelGroupNotFoundByIdException());
testUnit.execute(model);
}
@Test
public void testChannelGroupDeletedIncorrectType() {
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
when(channelGroupType.getGroupTypeKey()).thenReturn(INCORRECT_TYPE);
testUnit.channelGroupDeleted(channelGroup);
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenReturn(channelGroup);
testUnit.execute(model);
verify(checkChannelGroupManagement, times(0)).deleteRepostCheckChannelGroup(channelGroup);
}
}

View File

@@ -1,12 +1,14 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.models.cache.CachedEmbed;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
import dev.sheldan.abstracto.repostdetection.service.RepostService;
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.TextChannel;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,27 +36,33 @@ public class RepostMessageReceivedListenerTest {
private RepostService repostService;
@Mock
private CachedMessage message;
private Message message;
@Mock
private AChannel channel;
@Mock
private MessageReceivedModel model;
@Mock
private TextChannel textChannel;
@Captor
private ArgumentCaptor<List<CachedEmbed>> embedListCaptor;
private ArgumentCaptor<List<MessageEmbed>> embedListCaptor;
private static final Long CHANNEL_ID = 4L;
@Test
public void testExecuteCheckDisabled() {
setupRepostCheckEnabled(false);
testUnit.execute(message);
testUnit.execute(model);
verify(repostService, times(0)).processMessageAttachmentRepostCheck(message);
}
@Test
public void testExecuteOnlyMessage() {
setupRepostCheckEnabled(true);
testUnit.execute(message);
testUnit.execute(model);
verify(repostService, times(1)).processMessageAttachmentRepostCheck(message);
verify(repostService, times(1)).processMessageEmbedsRepostCheck(embedListCaptor.capture(), eq(message));
Assert.assertEquals(0, embedListCaptor.getValue().size());
@@ -63,35 +71,38 @@ public class RepostMessageReceivedListenerTest {
@Test
public void testExecuteOnlyMessageOneImageAttachment() {
setupRepostCheckEnabled(true);
CachedEmbed imageEmbed = Mockito.mock(CachedEmbed.class);
MessageEmbed imageEmbed = Mockito.mock(MessageEmbed.class);
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
when(message.getEmbeds()).thenReturn(Arrays.asList(imageEmbed));
testUnit.execute(message);
testUnit.execute(model);
verifySingleEmbed(imageEmbed);
}
@Test
public void testExecuteOnlyMessageTwoEmbedsOneImageAttachment() {
setupRepostCheckEnabled(true);
CachedEmbed imageEmbed = Mockito.mock(CachedEmbed.class);
MessageEmbed imageEmbed = Mockito.mock(MessageEmbed.class);
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
CachedEmbed nonImageEmbed = Mockito.mock(CachedEmbed.class);
MessageEmbed nonImageEmbed = Mockito.mock(MessageEmbed.class);
when(nonImageEmbed.getType()).thenReturn(EmbedType.LINK);
when(message.getEmbeds()).thenReturn(Arrays.asList(imageEmbed, nonImageEmbed));
testUnit.execute(message);
when(model.getMessage()).thenReturn(message);
testUnit.execute(model);
verifySingleEmbed(imageEmbed);
}
private void setupRepostCheckEnabled(boolean b) {
when(message.getChannelId()).thenReturn(CHANNEL_ID);
when(message.getTextChannel()).thenReturn(textChannel);
when(model.getMessage()).thenReturn(message);
when(textChannel.getIdLong()).thenReturn(CHANNEL_ID);
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(channel);
when(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)).thenReturn(b);
}
private void verifySingleEmbed(CachedEmbed imageEmbed) {
private void verifySingleEmbed(MessageEmbed imageEmbed) {
verify(repostService, times(1)).processMessageAttachmentRepostCheck(message);
verify(repostService, times(1)).processMessageEmbedsRepostCheck(embedListCaptor.capture(), eq(message));
List<CachedEmbed> processedEmbeds = embedListCaptor.getValue();
List<MessageEmbed> processedEmbeds = embedListCaptor.getValue();
Assert.assertEquals(1, processedEmbeds.size());
Assert.assertEquals(imageEmbed, processedEmbeds.get(0));
}

View File

@@ -20,8 +20,10 @@ public interface RepostService {
Optional<PostedImage> getRepostFor(Message message, MessageEmbed messageEmbed, Integer embedIndex);
boolean isRepost(CachedMessage message, CachedAttachment attachment, Integer index);
Optional<PostedImage> getRepostFor(CachedMessage message, CachedAttachment attachment, Integer index);
Optional<PostedImage> getRepostFor(Message message, Message.Attachment attachment, Integer index);
String calculateHashForPost(String url, Long serverId);
void processMessageAttachmentRepostCheck(CachedMessage message);
void processMessageAttachmentRepostCheck(Message message);
void processMessageEmbedsRepostCheck(List<CachedEmbed> embeds, CachedMessage message);
void processMessageEmbedsRepostCheck(List<MessageEmbed> embeds, Message message);
CompletableFuture<List<RepostLeaderboardEntryModel>> retrieveRepostLeaderboard(Guild guild, Integer page);