[AB-197] splitting utility maven module into separate maven modules

aligning some package names
removing some unnecessary computed values from liquibase
This commit is contained in:
Sheldan
2021-03-12 17:29:49 +01:00
parent e2da800d84
commit 2ed456c164
835 changed files with 12790 additions and 3310 deletions

View File

@@ -0,0 +1,18 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
<id>liquibase</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<outputDirectory>.</outputDirectory>
<directory>${project.basedir}/src/main/resources/migrations</directory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,67 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class DisableRepostCheck extends AbstractConditionableCommand {
@Autowired
private RepostCheckChannelService repostCheckChannelService;
@Autowired
private ChannelGroupManagementService channelGroupManagementService;
@Autowired
private ServerManagementService serverManagementService;
@Override
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
AChannelGroup fakeChannelGroup = (AChannelGroup) parameters.get(0);
AServer actualServer = serverManagementService.loadServer(commandContext.getGuild().getIdLong());
AChannelGroup actualChannelGroup = channelGroupManagementService.findByNameAndServerAndType(fakeChannelGroup.getGroupName(), actualServer, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
repostCheckChannelService.setRepostCheckDisabledForChannelGroup(actualChannelGroup);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter channelToSet = Parameter.builder().name("channelGroup").type(AChannelGroup.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(channelToSet);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("disableRepostCheck")
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
.templated(true)
.async(false)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,67 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class EnableRepostCheck extends AbstractConditionableCommand {
@Autowired
private RepostCheckChannelService repostCheckChannelService;
@Autowired
private ChannelGroupManagementService channelGroupManagementService;
@Autowired
private ServerManagementService serverManagementService;
@Override
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
AChannelGroup fakeChannelGroup = (AChannelGroup) parameters.get(0);
AServer actualServer = serverManagementService.loadServer(commandContext.getGuild().getIdLong());
AChannelGroup actualChannelGroup = channelGroupManagementService.findByNameAndServerAndType(fakeChannelGroup.getGroupName(), actualServer, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
repostCheckChannelService.setRepostCheckEnabledForChannelGroup(actualChannelGroup);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter channelToSet = Parameter.builder().name("channelGroup").type(AChannelGroup.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(channelToSet);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("enableRepostCheck")
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
.templated(true)
.async(false)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,64 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
import dev.sheldan.abstracto.repostdetection.service.PostedImageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class PurgeImagePosts extends AbstractConditionableCommand {
@Autowired
private PostedImageService postedImageService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Override
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
if(!parameters.isEmpty()) {
AUserInAServer fakeUser = (AUserInAServer) parameters.get(0);
AUserInAServer actualUser = userInServerManagementService.loadOrCreateUser(fakeUser.getUserInServerId());
postedImageService.purgePostedImages(actualUser);
} else {
postedImageService.purgePostedImages(commandContext.getGuild());
}
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter channelToSet = Parameter.builder().name("member").type(AUserInAServer.class).templated(true).optional(true).build();
List<Parameter> parameters = Arrays.asList(channelToSet);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("purgeImagePosts")
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
.templated(true)
.async(false)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,64 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
import dev.sheldan.abstracto.repostdetection.service.RepostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class PurgeReposts extends AbstractConditionableCommand {
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private RepostService repostService;
@Override
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
if(!parameters.isEmpty()) {
AUserInAServer fakeUser = (AUserInAServer) parameters.get(0);
AUserInAServer actualUser = userInServerManagementService.loadOrCreateUser(fakeUser.getUserInServerId());
repostService.purgeReposts(actualUser);
} else {
repostService.purgeReposts(commandContext.getGuild());
}
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter channelToSet = Parameter.builder().name("member").type(AUserInAServer.class).templated(true).optional(true).build();
List<Parameter> parameters = Arrays.asList(channelToSet);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("purgeReposts")
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
.templated(true)
.async(false)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,102 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureMode;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
import dev.sheldan.abstracto.repostdetection.converter.RepostLeaderBoardConverter;
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardModel;
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.repostdetection.service.RepostService;
import dev.sheldan.abstracto.repostdetection.service.management.RepostManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class RepostLeaderboard extends AbstractConditionableCommand {
public static final String REPOST_LEADERBOARD_RESPONSE_TEMPLATE_KEY = "repostLeaderboard_response";
@Autowired
private RepostService repostService;
@Autowired
private RepostManagementService repostManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Autowired
private RepostLeaderBoardConverter converter;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Integer page = !parameters.isEmpty() ? (Integer) parameters.get(0) : 1;
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
List<RepostLeaderboardResult> topRepostingUsersOfServer = repostManagementService.findTopRepostingUsersOfServer(commandContext.getGuild().getIdLong(), page, 5);
RepostLeaderboardResult resultOfUser = repostManagementService.getRepostRankOfUser(aUserInAServer);
CompletableFuture<List<RepostLeaderboardEntryModel>> leaderBoardFuture = converter.fromLeaderBoardResults(topRepostingUsersOfServer);
CompletableFuture<RepostLeaderboardEntryModel> userFuture = converter.convertSingleUser(resultOfUser);
return CompletableFuture.allOf(leaderBoardFuture, userFuture).thenCompose(unused -> {
List<RepostLeaderboardEntryModel> entries = leaderBoardFuture.join();
RepostLeaderboardModel model = RepostLeaderboardModel
.builder()
.guild(commandContext.getGuild())
.entries(entries)
.userExecuting(userFuture.join())
.member(commandContext.getAuthor())
.build();
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(REPOST_LEADERBOARD_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()));
}).thenApply(o -> CommandResult.fromIgnored());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter channelToSet = Parameter.builder().name("page").type(Integer.class).templated(true).optional(true).build();
List<Parameter> parameters = Arrays.asList(channelToSet);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("repostLeaderboard")
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
.templated(true)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
}
@Override
public List<FeatureMode> getFeatureModeLimitations() {
return Arrays.asList(RepostDetectionFeatureMode.LEADERBOARD);
}
}

View File

@@ -0,0 +1,62 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
import dev.sheldan.abstracto.repostdetection.converter.RepostCheckChannelModelConverter;
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.repostdetection.model.template.RepostCheckChannelsModel;
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class ShowRepostCheckChannels extends AbstractConditionableCommand {
public static final String SHOW_REPOST_CHECK_CHANNELS_RESPONSE_TEMPLATE_KEY = "showRepostCheckChannels_response";
@Autowired
private RepostCheckChannelModelConverter converter;
@Autowired
private RepostCheckChannelService checkChannelService;
@Autowired
private ChannelService channelService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<RepostCheckChannelGroup> channelGroups = checkChannelService.getChannelGroupsWithEnabledCheck(commandContext.getGuild().getIdLong());
RepostCheckChannelsModel model = converter.fromRepostCheckChannelGroups(channelGroups, commandContext.getGuild());
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(SHOW_REPOST_CHECK_CHANNELS_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CommandConfiguration getConfiguration() {
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("showRepostCheckChannels")
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
.templated(true)
.async(true)
.supportsEmbedException(true)
.causesReaction(false)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.repostdetection.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:repost-detection-config.properties")
public class RepostDetectionConfig {
}

View File

@@ -0,0 +1,42 @@
package dev.sheldan.abstracto.repostdetection.converter;
import dev.sheldan.abstracto.core.models.FullChannel;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.repostdetection.model.template.RepostCheckChannelGroupDisplayModel;
import dev.sheldan.abstracto.repostdetection.model.template.RepostCheckChannelsModel;
import net.dv8tion.jda.api.entities.Guild;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class RepostCheckChannelModelConverter {
@Autowired
private ChannelService channelService;
public RepostCheckChannelsModel fromRepostCheckChannelGroups(List<RepostCheckChannelGroup> channelGroups, Guild guild) {
List<RepostCheckChannelGroupDisplayModel> repostCheckChannelGroups = new ArrayList<>();
channelGroups.forEach(repostCheckChannelGroup -> {
List<FullChannel> fullChannels = repostCheckChannelGroup.getChannelGroup().getChannels().stream().map(channel ->
FullChannel
.builder()
.channel(channel)
.serverChannel(channelService.getTextChannelFromServerNullable(guild, channel.getId()))
.build()
).collect(Collectors.toList());
repostCheckChannelGroups.add(
RepostCheckChannelGroupDisplayModel
.builder()
.channelGroup(repostCheckChannelGroup)
.channels(fullChannels)
.build());
});
return RepostCheckChannelsModel.builder().repostCheckChannelGroups(repostCheckChannelGroups).build();
}
}

View File

@@ -0,0 +1,62 @@
package dev.sheldan.abstracto.repostdetection.converter;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Component
public class RepostLeaderBoardConverter {
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private MemberService memberService;
@Autowired
private RepostLeaderBoardConverter self;
public CompletableFuture<List<RepostLeaderboardEntryModel>> fromLeaderBoardResults(List<RepostLeaderboardResult> results) {
if(results.isEmpty()) {
return CompletableFuture.completedFuture(new ArrayList<>());
}
List<CompletableFuture<RepostLeaderboardEntryModel>> modelFutures =
results.stream().map(this::convertSingleUser).collect(Collectors.toList());
return FutureUtils.toSingleFutureGeneric(modelFutures).thenApply(unused ->
modelFutures.stream().map(CompletableFuture::join).collect(Collectors.toList())
);
}
public CompletableFuture<RepostLeaderboardEntryModel> convertSingleUser(RepostLeaderboardResult result) {
AUserInAServer user = userInServerManagementService.loadOrCreateUser(result.getUserInServerId());
Integer count = result.getRepostCount();
Long userInServerId = result.getUserInServerId();
Integer rank = result.getRank();
return memberService.getMemberInServerAsync(user).thenApply(member ->
self.loadUserFromDatabase(member, count, userInServerId, rank)
);
}
@Transactional
public RepostLeaderboardEntryModel loadUserFromDatabase(Member member, Integer count, Long userInServerId, Integer rank) {
return RepostLeaderboardEntryModel
.builder()
.member(member)
.user(userInServerManagementService.loadOrCreateUser(userInServerId))
.count(count)
.rank(rank)
.build();
}
}

View File

@@ -0,0 +1,22 @@
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

@@ -0,0 +1,22 @@
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

@@ -0,0 +1,64 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
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 void 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;
}
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);
}
});
}
}
@Override
public FeatureDefinition getFeature() {
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,49 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
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.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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
@Component
@Slf4j
public class RepostMessageReceivedListener implements AsyncMessageReceivedListener {
@Autowired
private RepostCheckChannelService repostCheckChannelService;
@Autowired
private RepostService repostService;
@Autowired
private ChannelManagementService channelManagementService;
@Override
public void execute(CachedMessage message) {
AChannel channel = channelManagementService.loadChannel(message.getChannelId());
if(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)) {
repostService.processMessageAttachmentRepostCheck(message);
List<CachedEmbed> imageEmbeds = message.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
repostService.processMessageEmbedsRepostCheck(imageEmbeds, message);
}
}
@Override
public FeatureDefinition getFeature() {
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,22 @@
package dev.sheldan.abstracto.repostdetection.repository;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
import dev.sheldan.abstracto.repostdetection.model.database.embed.PostIdentifier;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface PostedImageRepository extends JpaRepository<PostedImage, PostIdentifier> {
boolean existsByImageHashAndServerId(String hash, Long serverId);
Optional<PostedImage> findByImageHashAndServerId(String hash, Long serverId);
boolean existsByPostId_MessageId(Long messageId);
boolean existsByPostId_MessageIdAndPostId_PositionGreaterThan(Long messageId, Integer position);
List<PostedImage> findByPostId_MessageId(Long messageId);
void deleteByServer(AServer server);
void deleteByPoster(AUserInAServer aUserInAServer);
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.repostdetection.repository;
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface RepostCheckChannelRepository extends JpaRepository<RepostCheckChannelGroup, Long> {
}

View File

@@ -0,0 +1,55 @@
package dev.sheldan.abstracto.repostdetection.repository;
import dev.sheldan.abstracto.repostdetection.model.database.Repost;
import dev.sheldan.abstracto.repostdetection.model.database.embed.RepostIdentifier;
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface RepostRepository extends JpaRepository<Repost, RepostIdentifier> {
@Query(value = "WITH repost_rank AS " +
"( " +
"SELECT user_in_server_id as user_in_server_id, SUM(count) as repost_count, ROW_NUMBER() OVER ( ORDER BY SUM(count) DESC ) \n" +
"FROM repost \n" +
"WHERE server_id = :server_id " +
"GROUP BY user_in_server_id \n" +
"ORDER BY SUM(count) DESC \n" +
" )" +
"SELECT rank.user_in_server_id as userInServerId, rank.repost_count as repostCount, rank.row_number as rank " +
"FROM repost_rank rank ",
countQuery = "SELECT COUNT(1) FROM repost WHERE server_id = :server_id GROUP BY user_in_server_id",
nativeQuery = true)
List<RepostLeaderboardResult> findTopRepostingUsers(@Param("server_id") Long serverId, Pageable pageable);
@Query(value = "WITH repost_rank AS " +
"( " +
"SELECT user_in_server_id as user_in_server_id, SUM(count) as repost_count, ROW_NUMBER() OVER ( ORDER BY SUM(count) DESC ) \n" +
"FROM repost \n" +
"WHERE server_id = :server_id " +
"GROUP BY user_in_server_id \n" +
"ORDER BY SUM(count) DESC \n" +
" )" +
"SELECT rank.user_in_server_id as userInServerId, rank.repost_count as repostCount, rank.row_number as rank " +
"FROM repost_rank rank " +
"WHERE rank.user_in_server_id = :user_in_server_id " +
"UNION ALL " +
"SELECT :user_in_server_id as userInServerId, 0 as repostCount, 0 as rank " +
"WHERE NOT EXISTS " +
"(SELECT 1 " +
"FROM repost_rank rank WHERE rank.user_in_server_id = :user_in_server_id" +
")",
nativeQuery = true)
RepostLeaderboardResult getRepostRankOfUserInServer(@Param("user_in_server_id") Long useInServerId, @Param("server_id") Long serverId);
void deleteByServerId(Long serverId);
void deleteByRepostId_UserInServerIdAndServerId(Long userInServerId, Long serverId);
}

View File

@@ -0,0 +1,30 @@
package dev.sheldan.abstracto.repostdetection.service;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.repostdetection.service.management.PostedImageManagement;
import net.dv8tion.jda.api.entities.Guild;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PostedImageServiceBean implements PostedImageService {
@Autowired
private PostedImageManagement postedImageManagement;
@Autowired
private ServerManagementService serverManagementService;
@Override
public void purgePostedImages(AUserInAServer aUserInAServer) {
postedImageManagement.removePostedImagesOf(aUserInAServer);
}
@Override
public void purgePostedImages(Guild guild) {
AServer server = serverManagementService.loadServer(guild.getIdLong());
postedImageManagement.removedPostedImagesIn(server);
}
}

View File

@@ -0,0 +1,104 @@
package dev.sheldan.abstracto.repostdetection.service;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.ChannelGroupService;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static dev.sheldan.abstracto.repostdetection.service.RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE;
@Component
public class RepostCheckChannelServiceBean implements RepostCheckChannelService {
@Autowired
private RepostCheckChannelGroupManagement repostCheckChannelManagement;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private ChannelGroupService channelGroupService;
@Autowired
private ChannelGroupManagementService channelGroupManagementService;
@Override
public void setRepostCheckEnabledForChannelGroup(AChannelGroup channelGroup) {
RepostCheckChannelGroup group = repostCheckChannelManagement.loadRepostChannelGroupByChannelGroup(channelGroup);
setRepostCheckEnabledForChannelGroup(group);
}
@Override
public void setRepostCheckEnabledForChannelGroup(RepostCheckChannelGroup channelGroup) {
channelGroup.setCheckEnabled(true);
}
@Override
public void setRepostCheckDisabledForChannelGroup(AChannelGroup channelGroup) {
RepostCheckChannelGroup group = repostCheckChannelManagement.loadRepostChannelGroupByChannelGroup(channelGroup);
setRepostCheckDisabledForChannelGroup(group);
}
@Override
public void setRepostCheckDisabledForChannelGroup(RepostCheckChannelGroup channelGroup) {
channelGroup.setCheckEnabled(false);
}
@Override
public boolean duplicateCheckEnabledForChannel(TextChannel textChannel) {
AChannel channel = channelManagementService.loadChannel(textChannel.getIdLong());
return duplicateCheckEnabledForChannel(channel);
}
@Override
public boolean duplicateCheckEnabledForChannel(AChannel channel) {
List<AChannelGroup> channelGroups = channelGroupService.getChannelGroupsOfChannelWithType(channel, REPOST_CHECK_CHANNEL_GROUP_TYPE);
if(!channelGroups.isEmpty()) {
List<RepostCheckChannelGroup> repostChannelGroups = channelGroups.stream().map(aChannelGroup ->
repostCheckChannelManagement.loadRepostChannelGroupById(aChannelGroup.getId())
).collect(Collectors.toList());
return repostChannelGroups.stream().anyMatch(RepostCheckChannelGroup::getCheckEnabled);
}
return false;
}
@Override
public List<RepostCheckChannelGroup> getRepostCheckChannelGroupsForServer(AServer server) {
return getRepostCheckChannelGroupsForServer(server.getId());
}
@Override
public List<RepostCheckChannelGroup> getRepostCheckChannelGroupsForServer(Long serverId) {
List<AChannelGroup> channelGroups = channelGroupManagementService.findAllInServerWithType(serverId, REPOST_CHECK_CHANNEL_GROUP_TYPE);
if(!channelGroups.isEmpty()) {
return channelGroups.stream().map(aChannelGroup ->
repostCheckChannelManagement.loadRepostChannelGroupById(aChannelGroup.getId())
).collect(Collectors.toList());
}
return new ArrayList<>();
}
@Override
public List<RepostCheckChannelGroup> getChannelGroupsWithEnabledCheck(AServer server) {
return getChannelGroupsWithEnabledCheck(server.getId());
}
@Override
public List<RepostCheckChannelGroup> getChannelGroupsWithEnabledCheck(Long serverId) {
return getRepostCheckChannelGroupsForServer(serverId)
.stream()
.filter(RepostCheckChannelGroup::getCheckEnabled)
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,307 @@
package dev.sheldan.abstracto.repostdetection.service;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.core.models.ServerChannelMessageUser;
import dev.sheldan.abstracto.core.models.cache.CachedAttachment;
import dev.sheldan.abstracto.core.models.cache.CachedEmbed;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.FileService;
import dev.sheldan.abstracto.repostdetection.converter.RepostLeaderBoardConverter;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureMode;
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
import dev.sheldan.abstracto.repostdetection.model.database.Repost;
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.repostdetection.service.management.PostedImageManagement;
import dev.sheldan.abstracto.repostdetection.service.management.RepostManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
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;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
public class RepostServiceBean implements RepostService {
public static final Integer LEADER_BOARD_PAGE_SIZE = 5;
@Autowired
private HttpService httpService;
@Autowired
private HashService hashService;
@Autowired
private FileService fileService;
@Autowired
private PostedImageManagement postedImageManagement;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private ReactionService reactionService;
@Autowired
private FeatureModeService featureModeService;
@Autowired
private RepostManagementService repostManagementService;
@Autowired
private RepostLeaderBoardConverter leaderBoardConverter;
@Autowired
private RepostServiceBean self;
public static final List<String> NUMBER_EMOJI = Arrays.asList("\u0031\u20e3", "\u0032\u20e3", "\u0033\u20e3",
"\u0034\u20e3", "\u0035\u20e3", "\u0036\u20e3",
"\u0037\u20e3", "\u0038\u20e3", "\u0039\u20e3");
public static final String REPOST_CHECK_CHANNEL_GROUP_TYPE = "repostDetection";
// any embedded post will create an repost instance with a position higher than this
public static final Integer EMBEDDED_LINK_POSITION_START_INDEX = 1000;
public static final String REPOST_MARKER_EMOTE_KEY = "repostMarker";
@Override
public boolean isRepost(CachedMessage message, CachedEmbed messageEmbed, Integer index) {
return getRepostFor(message, messageEmbed, index).isPresent();
}
@Override
public Optional<PostedImage> getRepostFor(CachedMessage message, CachedEmbed messageEmbed, Integer embedIndex) {
if(messageEmbed.getCachedThumbnail() == null && messageEmbed.getCachedImageInfo() == null) {
return Optional.empty();
}
String urlToUse = null;
if(messageEmbed.getCachedThumbnail() != null) {
urlToUse = messageEmbed.getCachedThumbnail().getProxyUrl();
} else if (messageEmbed.getCachedImageInfo() != null) {
urlToUse = messageEmbed.getCachedImageInfo().getProxyUrl();
}
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
.builder()
.serverId(message.getServerId())
.channelId(message.getChannelId())
.userId(message.getAuthor().getAuthorId())
.messageId(message.getMessageId())
.build();
return checkForDuplicates(serverChannelMessageUser, EMBEDDED_LINK_POSITION_START_INDEX + embedIndex, urlToUse);
}
@Override
public Optional<PostedImage> getRepostFor(Message message, MessageEmbed messageEmbed, Integer embedIndex) {
if(messageEmbed.getThumbnail() == null && messageEmbed.getImage() == null) {
return Optional.empty();
}
String urlToUse = null;
if(messageEmbed.getThumbnail() != null) {
urlToUse = messageEmbed.getThumbnail().getProxyUrl();
} else if (messageEmbed.getImage() != null) {
urlToUse = messageEmbed.getImage().getProxyUrl();
}
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
.builder()
.serverId(message.getGuild().getIdLong())
.channelId(message.getChannel().getIdLong())
.userId(message.getAuthor().getIdLong())
.messageId(message.getIdLong())
.build();
return checkForDuplicates(serverChannelMessageUser, EMBEDDED_LINK_POSITION_START_INDEX + embedIndex, urlToUse);
}
private Optional<PostedImage> checkForDuplicates(ServerChannelMessageUser serverChannelMessageUser, Integer index, String fileUrl) {
String fileHash = calculateHashForPost(fileUrl, serverChannelMessageUser.getServerId());
AServer aServer = serverManagementService.loadServer(serverChannelMessageUser.getServerId());
Optional<PostedImage> potentialRepost = postedImageManagement.getPostWithHash(fileHash, aServer);
if(potentialRepost.isPresent()) {
PostedImage existingRepost = potentialRepost.get();
return !existingRepost.getPostId().getMessageId().equals(serverChannelMessageUser.getMessageId()) ? Optional.of(existingRepost) : Optional.empty();
} else {
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(serverChannelMessageUser.getServerId(), serverChannelMessageUser.getUserId());
AServerAChannelAUser cause = AServerAChannelAUser
.builder()
.aUserInAServer(aUserInAServer)
.channel(channelManagementService.loadChannel(serverChannelMessageUser.getChannelId()))
.guild(aServer)
.user(aUserInAServer.getUserReference())
.build();
postedImageManagement.createPost(cause, serverChannelMessageUser.getMessageId(), fileHash, index);
return Optional.empty();
}
}
@Override
public boolean isRepost(CachedMessage message, CachedAttachment attachment, Integer index) {
return getRepostFor(message, attachment, index).isPresent();
}
@Override
public Optional<PostedImage> getRepostFor(CachedMessage message, CachedAttachment attachment, Integer index) {
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
.builder()
.serverId(message.getServerId())
.channelId(message.getChannelId())
.userId(message.getAuthor().getAuthorId())
.messageId(message.getMessageId())
.build();
return checkForDuplicates(serverChannelMessageUser, index, attachment.getProxyUrl());
}
@Override
public String calculateHashForPost(String url, Long serverId) {
File downloadedFile = null;
try {
if(featureModeService.featureModeActive(RepostDetectionFeatureDefinition.REPOST_DETECTION, serverId, RepostDetectionFeatureMode.DOWNLOAD)) {
downloadedFile = httpService.downloadFileToTempFile(url);
return hashService.sha256HashFileContent(downloadedFile);
} else {
return hashService.sha256HashString(url);
}
} catch (IOException e) {
log.error("Failed to download attachment for repost check.", e);
} finally {
if(downloadedFile != null) {
try {
fileService.safeDelete(downloadedFile);
} catch (IOException e) {
log.error("Failed to delete downloaded repost check file.", e);
}
}
}
return null;
}
@Override
public void processMessageAttachmentRepostCheck(CachedMessage 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
.builder()
.serverId(message.getServerId())
.channelId(message.getChannelId())
.userId(message.getAuthor().getAuthorId())
.messageId(message.getMessageId())
.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());
CompletableFuture<Void> counterFuture;
if (moreRepostsPossible) {
counterFuture = reactionService.addDefaultReactionToMessageAsync(NUMBER_EMOJI.get(index), messageUser.getServerId(), messageUser.getChannelId(), messageUser.getMessageId());
} else {
counterFuture = CompletableFuture.completedFuture(null);
}
Long messageId = originalPost.getPostId().getMessageId();
Integer position = originalPost.getPostId().getPosition();
Long serverId = messageUser.getServerId();
Long userId = messageUser.getUserId();
CompletableFuture.allOf(markerFuture, counterFuture).thenAccept(unused ->
self.persistRepost(messageId, position, serverId, userId)
);
}
@Transactional
public void persistRepost(Long messageId, Integer position, Long serverId, Long userId) {
PostedImage postedImage = postedImageManagement.getPostFromMessageAndPosition(messageId, position);
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(serverId, userId);
Optional<Repost> existingPost = repostManagementService.findRepostOptional(postedImage, userInAServer);
if(existingPost.isPresent()) {
Repost previousRepost = existingPost.get();
existingPost.get().setCount(previousRepost.getCount() + 1);
} else {
repostManagementService.createRepost(postedImage, userInAServer);
}
}
@Override
public void processMessageEmbedsRepostCheck(List<CachedEmbed> embeds, CachedMessage message) {
boolean canThereBeMultipleReposts = embeds.size() > 1 || !message.getAttachments().isEmpty();
for (int imageIndex = 0; imageIndex < embeds.size(); imageIndex++) {
executeRepostCheckForMessageEmbed(message, embeds.get(imageIndex), imageIndex + message.getAttachments().size(), canThereBeMultipleReposts);
}
}
@Override
public void processMessageEmbedsRepostCheck(List<MessageEmbed> embeds, Message message) {
boolean canThereBeMultipleReposts = embeds.size() > 1 || !message.getAttachments().isEmpty();
for (int imageIndex = 0; imageIndex < embeds.size(); imageIndex++) {
executeRepostCheckForMessageEmbed(message, embeds.get(imageIndex), imageIndex + message.getAttachments().size(), canThereBeMultipleReposts);
}
}
@Override
public CompletableFuture<List<RepostLeaderboardEntryModel>> retrieveRepostLeaderboard(Guild guild, Integer page) {
AServer server = serverManagementService.loadServer(guild.getIdLong());
List<RepostLeaderboardResult> topRepostingUsersOfServer = repostManagementService.findTopRepostingUsersOfServer(server, page, LEADER_BOARD_PAGE_SIZE);
return leaderBoardConverter.fromLeaderBoardResults(topRepostingUsersOfServer);
}
@Override
public void purgeReposts(AUserInAServer userInAServer) {
repostManagementService.deleteRepostsFromUser(userInAServer);
}
@Override
public void purgeReposts(Guild guild) {
AServer server = serverManagementService.loadServer(guild.getIdLong());
repostManagementService.deleteRepostsFromServer(server);
}
private void executeRepostCheckForMessageEmbed(CachedMessage message, CachedEmbed messageEmbed, Integer index, boolean moreRepostsPossible) {
Optional<PostedImage> originalPostOptional = getRepostFor(message, messageEmbed, index);
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
.builder()
.serverId(message.getServerId())
.channelId(message.getChannelId())
.userId(message.getAuthor().getAuthorId())
.messageId(message.getMessageId())
.build();
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(serverChannelMessageUser, index, moreRepostsPossible, postedImage));
}
private void executeRepostCheckForMessageEmbed(Message message, MessageEmbed messageEmbed, Integer index, boolean moreRepostsPossible) {
Optional<PostedImage> originalPostOptional = getRepostFor(message, messageEmbed, 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));
}
}

View File

@@ -0,0 +1,85 @@
package dev.sheldan.abstracto.repostdetection.service.management;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.repostdetection.exception.PostedImageNotFoundException;
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
import dev.sheldan.abstracto.repostdetection.model.database.embed.PostIdentifier;
import dev.sheldan.abstracto.repostdetection.repository.PostedImageRepository;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
public class PostedImageManagementBean implements PostedImageManagement {
@Autowired
private PostedImageRepository postedImageRepository;
@Autowired
private RepostCheckChannelGroupManagement checkChannelBean;
@Override
public PostedImage createPost(AServerAChannelAUser creation, Long messageId, String hash, Integer index) {
PostedImage post = PostedImage
.builder()
.imageHash(hash)
.postId(new PostIdentifier(messageId, index))
.poster(creation.getAUserInAServer())
.server(creation.getGuild())
.postedChannel(creation.getChannel())
.build();
postedImageRepository.save(post);
return post;
}
@Override
public boolean postWitHashExists(String hash, AServer server) {
return postedImageRepository.existsByImageHashAndServerId(hash, server.getId());
}
@Override
public Optional<PostedImage> getPostWithHash(String hash, AServer server) {
return postedImageRepository.findByImageHashAndServerId(hash, server.getId());
}
@Override
public boolean messageHasBeenCovered(Long messageId) {
return postedImageRepository.existsByPostId_MessageId(messageId);
}
@Override
public boolean messageEmbedsHaveBeenCovered(Long messageId) {
return postedImageRepository.existsByPostId_MessageIdAndPostId_PositionGreaterThan(messageId, RepostServiceBean.EMBEDDED_LINK_POSITION_START_INDEX - 1);
}
@Override
public List<PostedImage> getAllFromMessage(Long messageId) {
return postedImageRepository.findByPostId_MessageId(messageId);
}
@Override
public Optional<PostedImage> getPostFromMessageAndPositionOptional(Long messageId, Integer position) {
return postedImageRepository.findById(new PostIdentifier(messageId, position));
}
@Override
public PostedImage getPostFromMessageAndPosition(Long messageId, Integer position) {
return getPostFromMessageAndPositionOptional(messageId, position).orElseThrow(() -> new PostedImageNotFoundException(messageId, position));
}
@Override
public void removePostedImagesOf(AUserInAServer poster) {
postedImageRepository.deleteByPoster(poster);
}
@Override
public void removedPostedImagesIn(AServer aServer) {
postedImageRepository.deleteByServer(aServer);
}
}

View File

@@ -0,0 +1,61 @@
package dev.sheldan.abstracto.repostdetection.service.management;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.repostdetection.exception.RepostCheckChannelGroupNotFoundException;
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.repostdetection.repository.RepostCheckChannelRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class RepostCheckChannelGroupManagementBean implements RepostCheckChannelGroupManagement {
@Autowired
private RepostCheckChannelRepository repository;
@Override
public RepostCheckChannelGroup loadRepostChannelGroupById(Long channelGroupId) {
return loadRepostChanelGroupByIdOptional(channelGroupId).orElseThrow(() -> new RepostCheckChannelGroupNotFoundException(channelGroupId));
}
@Override
public Optional<RepostCheckChannelGroup> loadRepostChanelGroupByIdOptional(Long channelGroupId) {
return repository.findById(channelGroupId);
}
@Override
public boolean repostCheckChannelGroupExists(Long channelGroupId) {
return loadRepostChanelGroupByIdOptional(channelGroupId).isPresent();
}
@Override
public Optional<RepostCheckChannelGroup> loadRepostChannelGroupByChannelGroupOptional(AChannelGroup channelGroup) {
return loadRepostChanelGroupByIdOptional(channelGroup.getId());
}
@Override
public RepostCheckChannelGroup loadRepostChannelGroupByChannelGroup(AChannelGroup channelGroup) {
return loadRepostChannelGroupById(channelGroup.getId());
}
@Override
public RepostCheckChannelGroup createRepostCheckChannelGroup(AChannelGroup channelGroup) {
RepostCheckChannelGroup repostCheckChannelGroup = RepostCheckChannelGroup
.builder()
.checkEnabled(true)
.channelGroup(channelGroup)
.id(channelGroup.getId())
.build();
repository.save(repostCheckChannelGroup);
return repostCheckChannelGroup;
}
@Override
public void deleteRepostCheckChannelGroup(AChannelGroup channelGroup) {
RepostCheckChannelGroup repostCheckChannelGroup = loadRepostChannelGroupByChannelGroup(channelGroup);
repository.delete(repostCheckChannelGroup);
}
}

View File

@@ -0,0 +1,85 @@
package dev.sheldan.abstracto.repostdetection.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.repostdetection.exception.RepostNotFoundException;
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
import dev.sheldan.abstracto.repostdetection.model.database.Repost;
import dev.sheldan.abstracto.repostdetection.model.database.embed.RepostIdentifier;
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.repostdetection.repository.RepostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
public class RepostManagementServiceBean implements RepostManagementService {
@Autowired
private RepostRepository repostRepository;
@Override
public Repost createRepost(PostedImage postedImage, AUserInAServer poster) {
Repost repost = Repost
.builder()
.originalPost(postedImage)
.poster(poster)
.repostId(buildRepostIdentifier(postedImage, poster))
.server(postedImage.getServer())
.count(1)
.build();
repostRepository.save(repost);
return repost;
}
@Override
public Repost setRepostCount(PostedImage postedImage, AUserInAServer poster, Integer newCount) {
Repost repost = findRepost(postedImage, poster);
repost.setCount(newCount);
return repost;
}
@Override
public Repost findRepost(PostedImage postedImage, AUserInAServer poster) {
return findRepostOptional(postedImage, poster)
.orElseThrow(() -> new RepostNotFoundException(postedImage.getPostId().getMessageId(), postedImage.getPostId().getPosition(), poster.getUserInServerId()));
}
@Override
public Optional<Repost> findRepostOptional(PostedImage postedImage, AUserInAServer poster) {
return repostRepository.findById(buildRepostIdentifier(postedImage, poster));
}
@Override
public List<RepostLeaderboardResult> findTopRepostingUsersOfServer(AServer server, Integer page, Integer pageSize) {
return findTopRepostingUsersOfServer(server.getId(), page, pageSize);
}
@Override
public List<RepostLeaderboardResult> findTopRepostingUsersOfServer(Long serverId, Integer page, Integer pageSize) {
return repostRepository.findTopRepostingUsers(serverId, PageRequest.of(page - 1, pageSize));
}
@Override
public RepostLeaderboardResult getRepostRankOfUser(AUserInAServer aUserInAServer) {
return repostRepository.getRepostRankOfUserInServer(aUserInAServer.getUserInServerId(), aUserInAServer.getServerReference().getId());
}
@Override
public void deleteRepostsFromUser(AUserInAServer aUserInAServer) {
repostRepository.deleteByRepostId_UserInServerIdAndServerId(aUserInAServer.getUserInServerId(), aUserInAServer.getServerReference().getId());
}
@Override
public void deleteRepostsFromServer(AServer server) {
repostRepository.deleteByServerId(server.getId());
}
private RepostIdentifier buildRepostIdentifier(PostedImage postedImage, AUserInAServer poster) {
return new RepostIdentifier(postedImage.getPostId().getMessageId(), postedImage.getPostId().getPosition(), poster.getUserInServerId());
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../dbchangelog-3.8.xsd" >
<include file="repost-detection-tables/tables.xml" relativeToChangelogFile="true"/>
<include file="repost-detection-seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,14 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="repost_channel_group_type-insertion">
<insert tableName="channel_group_type">
<column name="group_type_key" value="repostDetection"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,51 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="repostDetectionModule" value="(SELECT id FROM module WHERE name = 'repostDetection')"/>
<property name="repostDetectionFeature" value="(SELECT id FROM feature WHERE key = 'repostDetection')"/>
<changeSet author="Sheldan" id="repostDetection-commands">
<insert tableName="command">
<column name="name" value="disableRepostCheck"/>
<column name="module_id" valueComputed="${repostDetectionModule}"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="enableRepostCheck"/>
<column name="module_id" valueComputed="${repostDetectionModule}"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="purgeImagePosts"/>
<column name="module_id" valueComputed="${repostDetectionModule}"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="purgeReposts"/>
<column name="module_id" valueComputed="${repostDetectionModule}"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="repostLeaderboard"/>
<column name="module_id" valueComputed="${repostDetectionModule}"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="showRepostCheckChannels"/>
<column name="module_id" valueComputed="${repostDetectionModule}"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,14 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="default_emote.xml" relativeToChangelogFile="true"/>
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="module.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="channel_group_types.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,15 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="repost-detection_default_emote-insert">
<insert tableName="default_emote">
<column name="emote_key" value="repostMarker"/>
<column name="name" value="♻️"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,14 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="repost-detection_feature-insertion">
<insert tableName="feature">
<column name="key" value="repostDetection"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,14 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="repost-detection-module-insertion">
<insert tableName="module">
<column name="name" value="repostDetection"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,58 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="posted_image-table">
<createTable tableName="posted_image">
<column name="message_id" type="BIGINT" >
<constraints nullable="true"/>
</column>
<column name="position" type="INTEGER" >
<constraints nullable="true"/>
</column>
<column name="author_user_in_server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="posted_channel_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="image_hash" type="VARCHAR(512)">
<constraints nullable="false"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
<createIndex indexName="idx_posted_image_hash_server" tableName="posted_image">
<column name="image_hash"/>
<column name="server_id"/>
</createIndex>
<addPrimaryKey columnNames="message_id, position" tableName="posted_image" constraintName="pk_posted_image" validate="true"/>
<addForeignKeyConstraint baseColumnNames="author_user_in_server_id" baseTableName="posted_image" constraintName="fk_posted_image_user"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
<addForeignKeyConstraint baseColumnNames="posted_channel_id" baseTableName="posted_image" constraintName="fk_posted_image_channel"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
referencedTableName="channel" validate="true"/>
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="posted_image" constraintName="fk_posted_image_server"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
referencedTableName="server" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS posted_image_update_trigger ON posted_image;
CREATE TRIGGER posted_image_update_trigger BEFORE UPDATE ON posted_image FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS posted_image_insert_trigger ON posted_image;
CREATE TRIGGER posted_image_insert_trigger BEFORE INSERT ON posted_image FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,51 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="repost-table">
<createTable tableName="repost">
<column name="message_id" type="BIGINT" >
<constraints nullable="true"/>
</column>
<column name="position" type="INTEGER" >
<constraints nullable="true"/>
</column>
<column name="user_in_server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="count" type="INTEGER">
<constraints nullable="false"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
<addPrimaryKey columnNames="message_id, position, user_in_server_id" tableName="repost" constraintName="pk_repost" validate="true"/>
<addForeignKeyConstraint baseColumnNames="user_in_server_id" baseTableName="repost" constraintName="fk_repost_server"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
referencedColumnNames="id" referencedTableName="server" validate="true"/>
<addForeignKeyConstraint baseColumnNames="message_id, position" baseTableName="repost" constraintName="fk_repost_posted_image"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="message_id, position"
referencedTableName="posted_image" validate="true"/>
<addForeignKeyConstraint baseColumnNames="user_in_server_id" baseTableName="repost" constraintName="fk_repost_user_in_server"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id"
referencedTableName="user_in_server" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS repost_update_trigger ON repost;
CREATE TRIGGER repost_update_trigger BEFORE UPDATE ON repost FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS repost_insert_trigger ON repost;
CREATE TRIGGER repost_insert_trigger BEFORE INSERT ON repost FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,35 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="repost_check_channel_group-table">
<createTable tableName="repost_check_channel_group">
<column name="id" type="BIGINT">
<constraints nullable="true"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="enabled" type="BOOLEAN">
<constraints nullable="true"/>
</column>
</createTable>
<addForeignKeyConstraint baseColumnNames="id" baseTableName="repost_check_channel_group" constraintName="fk_repost_check_channel_group_group"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="channel_group" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS repost_check_channel_group_update_trigger ON repost_check_channel_group;
CREATE TRIGGER repost_check_channel_group_update_trigger BEFORE UPDATE ON repost_check_channel_group FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS repost_check_channel_group_insert_trigger ON repost_check_channel_group;
CREATE TRIGGER repost_check_channel_group_insert_trigger BEFORE INSERT ON repost_check_channel_group FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,12 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="repost_check_channel_group.xml" relativeToChangelogFile="true"/>
<include file="posted_image.xml" relativeToChangelogFile="true"/>
<include file="repost.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog-3.8.xsd" >
<include file="1.0-repost-detection/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
abstracto.featureFlags.repostDetection.featureName=repostDetection
abstracto.featureFlags.repostDetection.enabled=false
abstracto.featureModes.download.featureName=repostDetection
abstracto.featureModes.download.mode=download
abstracto.featureModes.download.enabled=true
abstracto.featureModes.leaderboard.featureName=repostDetection
abstracto.featureModes.leaderboard.mode=leaderboard
abstracto.featureModes.leaderboard.enabled=true

View File

@@ -0,0 +1,61 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class DisableRepostCheckTest {
@InjectMocks
private DisableRepostCheck testUnit;
@Mock
private ServerManagementService serverManagementService;
@Mock
private ChannelGroupManagementService channelGroupManagementService;
@Mock
private RepostCheckChannelService repostCheckChannelService;
@Test
public void executeCommandWithChannelGroupParameter() {
AChannelGroup channelGroup = Mockito.mock(AChannelGroup.class);
AChannelGroup actualChannelGroup = Mockito.mock(AChannelGroup.class);
Long serverId = 2L;
AServer server = Mockito.mock(AServer.class);
String channelGroupName = "test";
when(channelGroup.getGroupName()).thenReturn(channelGroupName);
when(serverManagementService.loadServer(serverId)).thenReturn(server);
when(channelGroupManagementService.findByNameAndServerAndType(channelGroupName, server, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(actualChannelGroup);
CommandContext channelGroupParameters = CommandTestUtilities.getWithParameters(Arrays.asList(channelGroup));
when(channelGroupParameters.getGuild().getIdLong()).thenReturn(serverId);
CommandResult result = testUnit.execute(channelGroupParameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(repostCheckChannelService, times(1)).setRepostCheckDisabledForChannelGroup(actualChannelGroup);
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -0,0 +1,61 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class EnableRepostCheckTest {
@InjectMocks
private EnableRepostCheck testUnit;
@Mock
private ServerManagementService serverManagementService;
@Mock
private ChannelGroupManagementService channelGroupManagementService;
@Mock
private RepostCheckChannelService repostCheckChannelService;
@Test
public void executeCommandWithChannelGroupParameter() {
AChannelGroup channelGroup = Mockito.mock(AChannelGroup.class);
AChannelGroup actualChannelGroup = Mockito.mock(AChannelGroup.class);
Long serverId = 2L;
AServer server = Mockito.mock(AServer.class);
String channelGroupName = "test";
when(channelGroup.getGroupName()).thenReturn(channelGroupName);
when(serverManagementService.loadServer(serverId)).thenReturn(server);
when(channelGroupManagementService.findByNameAndServerAndType(channelGroupName, server, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(actualChannelGroup);
CommandContext channelGroupParameters = CommandTestUtilities.getWithParameters(Arrays.asList(channelGroup));
when(channelGroupParameters.getGuild().getIdLong()).thenReturn(serverId);
CommandResult result = testUnit.execute(channelGroupParameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(repostCheckChannelService, times(1)).setRepostCheckEnabledForChannelGroup(actualChannelGroup);
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -0,0 +1,58 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.repostdetection.service.PostedImageService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class PurgeImagePostsTest {
@InjectMocks
private PurgeImagePosts testUnit;
@Mock
private UserInServerManagementService userInServerManagementService;
@Mock
private PostedImageService postedImageService;
@Test
public void testPurgeImagePostsFromMember(){
AUserInAServer fakeUser = Mockito.mock(AUserInAServer.class);
AUserInAServer actualUser = Mockito.mock(AUserInAServer.class);
Long userInServerId = 1L;
when(fakeUser.getUserInServerId()).thenReturn(userInServerId);
CommandContext purgeImagePostsParameters = CommandTestUtilities.getWithParameters(Arrays.asList(fakeUser));
when(userInServerManagementService.loadOrCreateUser(userInServerId)).thenReturn(actualUser);
CommandResult result = testUnit.execute(purgeImagePostsParameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(postedImageService, times(1)).purgePostedImages(actualUser);
}
@Test
public void testPurgeImagePostsFromServer(){
CommandContext noParameters = CommandTestUtilities.getNoParameters();
CommandResult result = testUnit.execute(noParameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(postedImageService, times(1)).purgePostedImages(noParameters.getGuild());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -0,0 +1,58 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.repostdetection.service.RepostService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class PurgeRepostsTest {
@InjectMocks
private PurgeReposts testUnit;
@Mock
private UserInServerManagementService userInServerManagementService;
@Mock
private RepostService repostService;
@Test
public void testPurgeImagePostsFromMember(){
AUserInAServer fakeUser = Mockito.mock(AUserInAServer.class);
AUserInAServer actualUser = Mockito.mock(AUserInAServer.class);
Long userInServerId = 1L;
when(fakeUser.getUserInServerId()).thenReturn(userInServerId);
CommandContext purgeImagePostsParameters = CommandTestUtilities.getWithParameters(Arrays.asList(fakeUser));
when(userInServerManagementService.loadOrCreateUser(userInServerId)).thenReturn(actualUser);
CommandResult result = testUnit.execute(purgeImagePostsParameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(repostService, times(1)).purgeReposts(actualUser);
}
@Test
public void testPurgeImagePostsFromServer(){
CommandContext noParameters = CommandTestUtilities.getNoParameters();
CommandResult result = testUnit.execute(noParameters);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(repostService, times(1)).purgeReposts(noParameters.getGuild());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -0,0 +1,108 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.repostdetection.converter.RepostLeaderBoardConverter;
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardModel;
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.repostdetection.service.management.RepostManagementService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
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 RepostLeaderboardTest {
@InjectMocks
private RepostLeaderboard testUnit;
@Mock
private RepostManagementService repostManagementService;
@Mock
private TemplateService templateService;
@Mock
private ChannelService channelService;
@Mock
private RepostLeaderBoardConverter converter;
@Mock
private UserInServerManagementService userInServerManagementService;
@Mock
private AUserInAServer aUserInAServer;
@Mock
private RepostLeaderboardResult result;
@Mock
private RepostLeaderboardResult userResult;
@Mock
private RepostLeaderboardEntryModel convertedResult;
@Mock
private RepostLeaderboardEntryModel convertedUserResult;
private static final Long SERVER_ID = 1L;
@Captor
private ArgumentCaptor<RepostLeaderboardModel> modelCaptor;
@Test
public void testExecuteWithoutParameter() {
executeRepostLeaderboardTest(1, CommandTestUtilities.getNoParameters());
}
@Test
public void testExecuteWithPageParameter() {
Integer page = 2;
CommandContext noParameters = CommandTestUtilities.getWithParameters(Arrays.asList(page));
executeRepostLeaderboardTest(page, noParameters);
}
public void executeRepostLeaderboardTest(Integer page, CommandContext noParameters) {
when(noParameters.getGuild().getIdLong()).thenReturn(SERVER_ID);
when(userInServerManagementService.loadOrCreateUser(noParameters.getAuthor())).thenReturn(aUserInAServer);
when(repostManagementService.getRepostRankOfUser(aUserInAServer)).thenReturn(userResult);
List<RepostLeaderboardResult> resultList = Arrays.asList(result);
when(repostManagementService.findTopRepostingUsersOfServer(SERVER_ID, page, 5)).thenReturn(resultList);
List<RepostLeaderboardEntryModel> convertedList = Arrays.asList(convertedResult);
when(converter.fromLeaderBoardResults(resultList)).thenReturn(CompletableFuture.completedFuture(convertedList));
when(converter.convertSingleUser(userResult)).thenReturn(CompletableFuture.completedFuture(convertedUserResult));
CompletableFuture<CommandResult> resultFuture = testUnit.executeAsync(noParameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(resultFuture);
verify(channelService, times(1)).sendEmbedTemplateInTextChannelList(eq(RepostLeaderboard.REPOST_LEADERBOARD_RESPONSE_TEMPLATE_KEY), modelCaptor.capture(), eq(noParameters.getChannel()));
RepostLeaderboardModel model = modelCaptor.getValue();
Assert.assertEquals(noParameters.getGuild(), model.getGuild());
Assert.assertEquals(convertedList, model.getEntries());
Assert.assertEquals(convertedUserResult, model.getUserExecuting());
Assert.assertEquals(noParameters.getAuthor(), model.getMember());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -0,0 +1,61 @@
package dev.sheldan.abstracto.repostdetection.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.repostdetection.converter.RepostCheckChannelModelConverter;
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.repostdetection.model.template.RepostCheckChannelsModel;
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.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 ShowRepostCheckChannelsTest {
@InjectMocks
private ShowRepostCheckChannels testUnit;
@Mock
private RepostCheckChannelModelConverter converter;
@Mock
private RepostCheckChannelService checkChannelService;
@Mock
private ChannelService channelService;
@Test
public void testExecuteCommand() {
Long serverId = 1L;
CommandContext noParameters = CommandTestUtilities.getNoParameters();
when(noParameters.getGuild().getIdLong()).thenReturn(serverId);
RepostCheckChannelGroup group = Mockito.mock(RepostCheckChannelGroup.class);
List<RepostCheckChannelGroup> groupList = Arrays.asList(group);
when(checkChannelService.getChannelGroupsWithEnabledCheck(serverId)).thenReturn(groupList);
RepostCheckChannelsModel model = Mockito.mock(RepostCheckChannelsModel.class);
when(converter.fromRepostCheckChannelGroups(groupList, noParameters.getGuild())).thenReturn(model);
CompletableFuture<CommandResult> futureResult = testUnit.executeAsync(noParameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(futureResult);
verify(channelService, times(1)).sendEmbedTemplateInTextChannelList(ShowRepostCheckChannels.SHOW_REPOST_CHECK_CHANNELS_RESPONSE_TEMPLATE_KEY, model, noParameters.getChannel());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -0,0 +1,83 @@
package dev.sheldan.abstracto.repostdetection.converter;
import dev.sheldan.abstracto.core.models.FullChannel;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.repostdetection.model.template.RepostCheckChannelGroupDisplayModel;
import dev.sheldan.abstracto.repostdetection.model.template.RepostCheckChannelsModel;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.TextChannel;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class RepostCheckChannelModelConverterTest {
@InjectMocks
private RepostCheckChannelModelConverter testUnit;
@Mock
private ChannelService channelService;
@Mock
private Guild guild;
@Test
public void testConvertEmptyList() {
RepostCheckChannelsModel model = testUnit.fromRepostCheckChannelGroups(new ArrayList<>(), guild);
Assert.assertEquals(0, model.getRepostCheckChannelGroups().size());
}
@Test
public void testConvertChannelGroupNoChannels() {
RepostCheckChannelGroup element = Mockito.mock(RepostCheckChannelGroup.class);
AChannelGroup group = Mockito.mock(AChannelGroup.class);
when(element.getChannelGroup()).thenReturn(group);
when(group.getChannels()).thenReturn(new ArrayList<>());
RepostCheckChannelsModel model = testUnit.fromRepostCheckChannelGroups(Arrays.asList(element), guild);
Assert.assertEquals(1, model.getRepostCheckChannelGroups().size());
RepostCheckChannelGroupDisplayModel displayModel = model.getRepostCheckChannelGroups().get(0);
Assert.assertEquals(element, displayModel.getChannelGroup());
Assert.assertEquals(0, displayModel.getChannels().size());
}
@Test
public void testConvertChannelGroupWithChannelsOneDeleted() {
RepostCheckChannelGroup element = Mockito.mock(RepostCheckChannelGroup.class);
AChannelGroup group = Mockito.mock(AChannelGroup.class);
when(element.getChannelGroup()).thenReturn(group);
Long channelId1 = 1L;
AChannel channel1 = Mockito.mock(AChannel.class);
when(channel1.getId()).thenReturn(channelId1);
TextChannel textChannel = Mockito.mock(TextChannel.class);
when(channelService.getTextChannelFromServerNullable(guild, channelId1)).thenReturn(textChannel);
Long channelId2 = 2L;
AChannel channel2 = Mockito.mock(AChannel.class);
when(channel2.getId()).thenReturn(channelId2);
when(channelService.getTextChannelFromServerNullable(guild, channelId2)).thenReturn(null);
when(group.getChannels()).thenReturn(Arrays.asList(channel1, channel2));
RepostCheckChannelsModel model = testUnit.fromRepostCheckChannelGroups(Arrays.asList(element), guild);
Assert.assertEquals(1, model.getRepostCheckChannelGroups().size());
RepostCheckChannelGroupDisplayModel displayModel = model.getRepostCheckChannelGroups().get(0);
Assert.assertEquals(element, displayModel.getChannelGroup());
Assert.assertEquals(2, displayModel.getChannels().size());
FullChannel firstFullChannel = displayModel.getChannels().get(0);
Assert.assertEquals(channel1, firstFullChannel.getChannel());
Assert.assertEquals(textChannel, firstFullChannel.getServerChannel());
FullChannel secondFullChannel = displayModel.getChannels().get(1);
Assert.assertEquals(channel2, secondFullChannel.getChannel());
Assert.assertNull(secondFullChannel.getServerChannel());
}
}

View File

@@ -0,0 +1,110 @@
package dev.sheldan.abstracto.repostdetection.converter;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
import net.dv8tion.jda.api.entities.Member;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostLeaderBoardConverterTest {
@InjectMocks
private RepostLeaderBoardConverter testUnit;
@Mock
private UserInServerManagementService userInServerManagementService;
@Mock
private MemberService memberService;
@Mock
private RepostLeaderBoardConverter self;
@Mock
private AUserInAServer aUserInAServer;
@Mock
private Member member;
private static final Long USER_IN_SERVER_ID = 1L;
private static final Integer REPOST_COUNT = 1;
private static final Integer RANK = 2;
@Test
public void testConvertEmptyList() {
CompletableFuture<List<RepostLeaderboardEntryModel>> future = testUnit.fromLeaderBoardResults(new ArrayList<>());
Assert.assertTrue(future.isDone());
Assert.assertEquals(0, future.join().size());
}
@Test
public void testConvertOneResult() {
RepostLeaderboardResult result = setupFirstResult();
CompletableFuture<List<RepostLeaderboardEntryModel>> future = testUnit.fromLeaderBoardResults(Arrays.asList(result));
Assert.assertTrue(future.isDone());
Assert.assertEquals(1, future.join().size());
verifyFirstResultConversion();
}
@Test
public void testConvertTwoResults() {
RepostLeaderboardResult result = setupFirstResult();
RepostLeaderboardResult result2 = Mockito.mock(RepostLeaderboardResult.class);
Long secondUserInServerId = USER_IN_SERVER_ID + 1;
when(result2.getUserInServerId()).thenReturn(secondUserInServerId);
Integer secondRepostCount = REPOST_COUNT + 1;
when(result2.getRepostCount()).thenReturn(secondRepostCount);
Integer secondRank = RANK + 1;
when(result2.getRank()).thenReturn(secondRank);
AUserInAServer secondAUserInAServer = Mockito.mock(AUserInAServer.class);
when(userInServerManagementService.loadOrCreateUser(secondUserInServerId)).thenReturn(secondAUserInAServer);
Member secondMember = Mockito.mock(Member.class);
when(memberService.getMemberInServerAsync(secondAUserInAServer)).thenReturn(CompletableFuture.completedFuture(secondMember));
CompletableFuture<List<RepostLeaderboardEntryModel>> future = testUnit.fromLeaderBoardResults(Arrays.asList(result, result2));
Assert.assertTrue(future.isDone());
Assert.assertEquals(2, future.join().size());
verifyFirstResultConversion();
verify(self, times(1)).loadUserFromDatabase(secondMember, secondRepostCount, secondUserInServerId, secondRank);
}
private void verifyFirstResultConversion() {
verify(self, times(1)).loadUserFromDatabase(member, REPOST_COUNT, USER_IN_SERVER_ID, RANK);
}
private RepostLeaderboardResult setupFirstResult() {
RepostLeaderboardResult result = Mockito.mock(RepostLeaderboardResult.class);
when(result.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
when(result.getRepostCount()).thenReturn(REPOST_COUNT);
when(result.getRank()).thenReturn(RANK);
when(userInServerManagementService.loadOrCreateUser(USER_IN_SERVER_ID)).thenReturn(aUserInAServer);
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(member));
return result;
}
@Test
public void testLoadUserFromDatabase() {
when(userInServerManagementService.loadOrCreateUser(USER_IN_SERVER_ID)).thenReturn(aUserInAServer);
RepostLeaderboardEntryModel loadedModel = testUnit.loadUserFromDatabase(member, REPOST_COUNT, USER_IN_SERVER_ID, RANK);
Assert.assertEquals(REPOST_COUNT, loadedModel.getCount());
Assert.assertEquals(RANK, loadedModel.getRank());
Assert.assertEquals(member, loadedModel.getMember());
Assert.assertEquals(aUserInAServer, loadedModel.getUser());
}
}

View File

@@ -0,0 +1,47 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostCheckChannelGroupCreatedListenerTest {
@InjectMocks
private RepostCheckChannelGroupCreatedListener testUnit;
@Mock
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
@Mock
private AChannelGroup channelGroup;
@Mock
private ChannelGroupType channelGroupType;
private static final String INCORRECT_TYPE = "incorrectType";
@Test
public void testChannelGroupCreated() {
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
when(channelGroupType.getGroupTypeKey()).thenReturn(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
testUnit.channelGroupCreated(channelGroup);
verify(checkChannelGroupManagement, times(1)).createRepostCheckChannelGroup(channelGroup);
}
@Test
public void testChannelGroupCreatedIncorrectType() {
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
when(channelGroupType.getGroupTypeKey()).thenReturn(INCORRECT_TYPE);
testUnit.channelGroupCreated(channelGroup);
verify(checkChannelGroupManagement, times(0)).createRepostCheckChannelGroup(channelGroup);
}
}

View File

@@ -0,0 +1,47 @@
package dev.sheldan.abstracto.repostdetection.listener;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostCheckChannelGroupDeletedListenerTest {
@InjectMocks
private RepostCheckChannelGroupDeletedListener testUnit;
@Mock
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
@Mock
private AChannelGroup channelGroup;
@Mock
private ChannelGroupType channelGroupType;
private static final String INCORRECT_TYPE = "incorrectType";
@Test
public void testChannelGroupDeleted() {
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
when(channelGroupType.getGroupTypeKey()).thenReturn(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
testUnit.channelGroupDeleted(channelGroup);
verify(checkChannelGroupManagement, times(1)).deleteRepostCheckChannelGroup(channelGroup);
}
@Test
public void testChannelGroupDeletedIncorrectType() {
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
when(channelGroupType.getGroupTypeKey()).thenReturn(INCORRECT_TYPE);
testUnit.channelGroupDeleted(channelGroup);
verify(checkChannelGroupManagement, times(0)).deleteRepostCheckChannelGroup(channelGroup);
}
}

View File

@@ -0,0 +1,137 @@
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.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);
}
}

View File

@@ -0,0 +1,99 @@
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.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 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 static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostMessageReceivedListenerTest {
@InjectMocks
private RepostMessageReceivedListener testUnit;
@Mock
private RepostCheckChannelService repostCheckChannelService;
@Mock
private ChannelManagementService channelManagementService;
@Mock
private RepostService repostService;
@Mock
private CachedMessage message;
@Mock
private AChannel channel;
@Captor
private ArgumentCaptor<List<CachedEmbed>> embedListCaptor;
private static final Long CHANNEL_ID = 4L;
@Test
public void testExecuteCheckDisabled() {
setupRepostCheckEnabled(false);
testUnit.execute(message);
verify(repostService, times(0)).processMessageAttachmentRepostCheck(message);
}
@Test
public void testExecuteOnlyMessage() {
setupRepostCheckEnabled(true);
testUnit.execute(message);
verify(repostService, times(1)).processMessageAttachmentRepostCheck(message);
verify(repostService, times(1)).processMessageEmbedsRepostCheck(embedListCaptor.capture(), eq(message));
Assert.assertEquals(0, embedListCaptor.getValue().size());
}
@Test
public void testExecuteOnlyMessageOneImageAttachment() {
setupRepostCheckEnabled(true);
CachedEmbed imageEmbed = Mockito.mock(CachedEmbed.class);
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
when(message.getEmbeds()).thenReturn(Arrays.asList(imageEmbed));
testUnit.execute(message);
verifySingleEmbed(imageEmbed);
}
@Test
public void testExecuteOnlyMessageTwoEmbedsOneImageAttachment() {
setupRepostCheckEnabled(true);
CachedEmbed imageEmbed = Mockito.mock(CachedEmbed.class);
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
CachedEmbed nonImageEmbed = Mockito.mock(CachedEmbed.class);
when(nonImageEmbed.getType()).thenReturn(EmbedType.LINK);
when(message.getEmbeds()).thenReturn(Arrays.asList(imageEmbed, nonImageEmbed));
testUnit.execute(message);
verifySingleEmbed(imageEmbed);
}
private void setupRepostCheckEnabled(boolean b) {
when(message.getChannelId()).thenReturn(CHANNEL_ID);
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(channel);
when(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)).thenReturn(b);
}
private void verifySingleEmbed(CachedEmbed imageEmbed) {
verify(repostService, times(1)).processMessageAttachmentRepostCheck(message);
verify(repostService, times(1)).processMessageEmbedsRepostCheck(embedListCaptor.capture(), eq(message));
List<CachedEmbed> processedEmbeds = embedListCaptor.getValue();
Assert.assertEquals(1, processedEmbeds.size());
Assert.assertEquals(imageEmbed, processedEmbeds.get(0));
}
}

View File

@@ -0,0 +1,57 @@
package dev.sheldan.abstracto.repostdetection.service;
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.repostdetection.service.management.PostedImageManagement;
import net.dv8tion.jda.api.entities.Guild;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class PostedImageServiceBeanTest {
@InjectMocks
private PostedImageServiceBean testUnit;
@Mock
private PostedImageManagement postedImageManagement;
@Mock
private ServerManagementService serverManagementService;
@Test
public void testPurgePostedImagesOfAUserInAServer() {
AUserInAServer aUserInAServer = Mockito.mock(AUserInAServer.class);
testUnit.purgePostedImages(aUserInAServer);
verify(postedImageManagement, times(1)).removePostedImagesOf(aUserInAServer);
}
@Test
public void testPurgePostedImagesInGuild() {
Guild guild = Mockito.mock(Guild.class);
Long serverId = 5L;
when(guild.getIdLong()).thenReturn(serverId);
AServer server = Mockito.mock(AServer.class);
when(serverManagementService.loadServer(serverId)).thenReturn(server);
testUnit.purgePostedImages(guild);
verify(postedImageManagement, times(1)).removedPostedImagesIn(server);
}
@Test(expected = GuildNotFoundException.class)
public void testPurgePostedImagesNotExistingServer() {
Guild guild = Mockito.mock(Guild.class);
Long serverId = 5L;
when(guild.getIdLong()).thenReturn(serverId);
when(serverManagementService.loadServer(serverId)).thenThrow(new GuildNotFoundException(serverId));
testUnit.purgePostedImages(guild);
}
}

View File

@@ -0,0 +1,256 @@
package dev.sheldan.abstracto.repostdetection.service;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.ChannelGroupService;
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.repostdetection.exception.RepostCheckChannelGroupNotFoundException;
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
import net.dv8tion.jda.api.entities.TextChannel;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostCheckChannelServiceBeanTest {
public static final long SERVER_ID = 1L;
@InjectMocks
private RepostCheckChannelServiceBean testUnit;
@Mock
private RepostCheckChannelGroupManagement repostCheckChannelManagement;
@Mock
private ChannelManagementService channelManagementService;
@Mock
private ChannelGroupService channelGroupService;
@Mock
private ChannelGroupManagementService channelGroupManagementService;
@Test
public void testSetCheckEnabledForCheckGroup() {
RepostCheckChannelGroup group = Mockito.mock(RepostCheckChannelGroup.class);
testUnit.setRepostCheckEnabledForChannelGroup(group);
verify(group, times(1)).setCheckEnabled(true);
}
@Test
public void testSetCheckEnabledForChannelGroup() {
AChannelGroup channelGroup = Mockito.mock(AChannelGroup.class);
RepostCheckChannelGroup group = Mockito.mock(RepostCheckChannelGroup.class);
when(repostCheckChannelManagement.loadRepostChannelGroupByChannelGroup(channelGroup)).thenReturn(group);
testUnit.setRepostCheckEnabledForChannelGroup(channelGroup);
verify(group, times(1)).setCheckEnabled(true);
}
@Test
public void testSetCheckDisabledForCheckGroup() {
RepostCheckChannelGroup group = Mockito.mock(RepostCheckChannelGroup.class);
testUnit.setRepostCheckDisabledForChannelGroup(group);
verify(group, times(1)).setCheckEnabled(false);
}
@Test
public void testSetCheckDisabledForChannelGroup() {
AChannelGroup channelGroup = Mockito.mock(AChannelGroup.class);
RepostCheckChannelGroup group = Mockito.mock(RepostCheckChannelGroup.class);
when(repostCheckChannelManagement.loadRepostChannelGroupByChannelGroup(channelGroup)).thenReturn(group);
testUnit.setRepostCheckDisabledForChannelGroup(channelGroup);
verify(group, times(1)).setCheckEnabled(false);
}
@Test
public void testCheckDuplicateCheckEnabledAChannel() {
AChannel channel = mock(AChannel.class);
setupEnabledCheck(channel);
boolean enabled = testUnit.duplicateCheckEnabledForChannel(channel);
Assert.assertTrue(enabled);
}
@Test
public void testCheckDuplicateCheckDisabledAChannel() {
AChannel channel = mock(AChannel.class);
setupDisabledCheck(channel);
boolean enabled = testUnit.duplicateCheckEnabledForChannel(channel);
Assert.assertFalse(enabled);
}
@Test
public void testCheckDuplicateCheckEnabledTextChannel() {
TextChannel textChannel = Mockito.mock(TextChannel.class);
AChannel channel = Mockito.mock(AChannel.class);
Long channelID = 3L;
when(textChannel.getIdLong()).thenReturn(channelID);
when(channelManagementService.loadChannel(channelID)).thenReturn(channel);
setupEnabledCheck(channel);
boolean enabled = testUnit.duplicateCheckEnabledForChannel(textChannel);
Assert.assertTrue(enabled);
}
@Test
public void testCheckDuplicateCheckDisabledTextChannel() {
TextChannel textChannel = Mockito.mock(TextChannel.class);
AChannel channel = Mockito.mock(AChannel.class);
Long channelID = 3L;
when(textChannel.getIdLong()).thenReturn(channelID);
when(channelManagementService.loadChannel(channelID)).thenReturn(channel);
setupDisabledCheck(channel);
boolean enabled = testUnit.duplicateCheckEnabledForChannel(textChannel);
Assert.assertFalse(enabled);
}
@Test
public void testCheckDuplicateCheckNoChannelGroupsChannel() {
AChannel channel = Mockito.mock(AChannel.class);
when(channelGroupService.getChannelGroupsOfChannelWithType(channel, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(new ArrayList<>());
boolean enabled = testUnit.duplicateCheckEnabledForChannel(channel);
Assert.assertFalse(enabled);
}
@Test
public void testCheckDuplicateCheckNoChannelGroupsTextChannel() {
TextChannel textChannel = Mockito.mock(TextChannel.class);
AChannel channel = Mockito.mock(AChannel.class);
Long channelID = 3L;
when(textChannel.getIdLong()).thenReturn(channelID);
when(channelManagementService.loadChannel(channelID)).thenReturn(channel);
when(channelGroupService.getChannelGroupsOfChannelWithType(channel, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(new ArrayList<>());
boolean enabled = testUnit.duplicateCheckEnabledForChannel(textChannel);
Assert.assertFalse(enabled);
}
public void setupEnabledCheck(AChannel channel) {
setupRepostEnabledTest(channel, true, false);
}
public void setupDisabledCheck(AChannel channel) {
setupRepostEnabledTest(channel, false, false);
}
public void setupRepostEnabledTest(AChannel channel, boolean firstGroupState, boolean secondGroupSate) {
AChannelGroup firstGroup = Mockito.mock(AChannelGroup.class);
Long firstChannelGroupId = 1L;
Long secondChannelGroupId = 2L;
when(firstGroup.getId()).thenReturn(firstChannelGroupId);
AChannelGroup secondGroup = Mockito.mock(AChannelGroup.class);
when(secondGroup.getId()).thenReturn(secondChannelGroupId);
RepostCheckChannelGroup firstRepostCheckChannelGroup = Mockito.mock(RepostCheckChannelGroup.class);
when(firstRepostCheckChannelGroup.getCheckEnabled()).thenReturn(secondGroupSate);
RepostCheckChannelGroup secondRepostCheckChannelGroup = Mockito.mock(RepostCheckChannelGroup.class);
when(secondRepostCheckChannelGroup.getCheckEnabled()).thenReturn(firstGroupState);
when(repostCheckChannelManagement.loadRepostChannelGroupById(firstChannelGroupId)).thenReturn(firstRepostCheckChannelGroup);
when(repostCheckChannelManagement.loadRepostChannelGroupById(secondChannelGroupId)).thenReturn(secondRepostCheckChannelGroup);
when(channelGroupService.getChannelGroupsOfChannelWithType(channel, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(Arrays.asList(firstGroup, secondGroup));
}
@Test
public void testGetRepostCheckChannelGroupsForServerNoChannelGroups() {
when(channelGroupManagementService.findAllInServerWithType(SERVER_ID, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(new ArrayList<>());
List<RepostCheckChannelGroup> groups = testUnit.getRepostCheckChannelGroupsForServer(SERVER_ID);
Assert.assertEquals(0, groups.size());
}
@Test
public void testGetRepostCheckChannelGroupsForServerTwoChannelGroups() {
List<RepostCheckChannelGroup> mockedGroups = setupGetRepostCheckChannelGroupsTest();
List<RepostCheckChannelGroup> groups = testUnit.getRepostCheckChannelGroupsForServer(SERVER_ID);
Assert.assertEquals(2, groups.size());
Assert.assertEquals(mockedGroups.get(0), groups.get(0));
Assert.assertEquals(mockedGroups.get(1), groups.get(1));
}
@Test
public void testGetRepostCheckChannelGroupsForServerTwoChannelGroupsAServer() {
AServer server = Mockito.mock(AServer.class);
when(server.getId()).thenReturn(SERVER_ID);
List<RepostCheckChannelGroup> mockedGroups = setupGetRepostCheckChannelGroupsTest();
List<RepostCheckChannelGroup> groups = testUnit.getRepostCheckChannelGroupsForServer(server);
Assert.assertEquals(2, groups.size());
Assert.assertEquals(mockedGroups.get(0), groups.get(0));
Assert.assertEquals(mockedGroups.get(1), groups.get(1));
}
public List<RepostCheckChannelGroup> setupGetRepostCheckChannelGroupsTest() {
Long firstChannelGroupId = 1L;
Long secondChannelGroupId = 2L;
AChannelGroup firstGroup = Mockito.mock(AChannelGroup.class);
when(firstGroup.getId()).thenReturn(firstChannelGroupId);
AChannelGroup secondGroup = Mockito.mock(AChannelGroup.class);
when(secondGroup.getId()).thenReturn(secondChannelGroupId);
when(channelGroupManagementService.findAllInServerWithType(SERVER_ID, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(Arrays.asList(firstGroup, secondGroup));
RepostCheckChannelGroup firstRepostCheckChannelGroup = Mockito.mock(RepostCheckChannelGroup.class);
RepostCheckChannelGroup secondRepostCheckChannelGroup = Mockito.mock(RepostCheckChannelGroup.class);
when(repostCheckChannelManagement.loadRepostChannelGroupById(firstChannelGroupId)).thenReturn(firstRepostCheckChannelGroup);
when(repostCheckChannelManagement.loadRepostChannelGroupById(secondChannelGroupId)).thenReturn(secondRepostCheckChannelGroup);
return Arrays.asList(firstRepostCheckChannelGroup, secondRepostCheckChannelGroup);
}
@Test(expected = RepostCheckChannelGroupNotFoundException.class)
public void testGetRepostCheckChannelGroupsNotExisting() {
Long channelGroupId = 1L;
AChannelGroup firstGroup = Mockito.mock(AChannelGroup.class);
when(firstGroup.getId()).thenReturn(channelGroupId);
when(channelGroupManagementService.findAllInServerWithType(SERVER_ID, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(Arrays.asList(firstGroup));
when(repostCheckChannelManagement.loadRepostChannelGroupById(channelGroupId)).thenThrow(new RepostCheckChannelGroupNotFoundException(channelGroupId));
testUnit.getRepostCheckChannelGroupsForServer(SERVER_ID);
}
@Test
public void testGetChannelGroupsWithEnabledCheckNoGroups() {
when(channelGroupManagementService.findAllInServerWithType(SERVER_ID, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(new ArrayList<>());
List<RepostCheckChannelGroup> groups = testUnit.getChannelGroupsWithEnabledCheck(SERVER_ID);
Assert.assertEquals(0, groups.size());
}
@Test
public void testGetChannelGroupsWithEnabledCheckAServer() {
AServer server = Mockito.mock(AServer.class);
when(server.getId()).thenReturn(SERVER_ID);
List<RepostCheckChannelGroup> checkGroups = setupGetChannelGroupsTest();
List<RepostCheckChannelGroup> groups = testUnit.getChannelGroupsWithEnabledCheck(server);
Assert.assertEquals(1, groups.size());
Assert.assertEquals(checkGroups.get(0), groups.get(0));
}
@Test
public void testGetChannelGroupsWithEnabledCheck() {
List<RepostCheckChannelGroup> checkGroups = setupGetChannelGroupsTest();
List<RepostCheckChannelGroup> groups = testUnit.getChannelGroupsWithEnabledCheck(SERVER_ID);
Assert.assertEquals(1, groups.size());
Assert.assertEquals(checkGroups.get(0), groups.get(0));
}
public List<RepostCheckChannelGroup> setupGetChannelGroupsTest() {
Long firstChannelGroupId = 1L;
Long secondChannelGroupId = 2L;
AChannelGroup firstGroup = Mockito.mock(AChannelGroup.class);
when(firstGroup.getId()).thenReturn(firstChannelGroupId);
AChannelGroup secondGroup = Mockito.mock(AChannelGroup.class);
when(secondGroup.getId()).thenReturn(secondChannelGroupId);
when(channelGroupManagementService.findAllInServerWithType(SERVER_ID, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(Arrays.asList(firstGroup, secondGroup));
RepostCheckChannelGroup firstRepostCheckChannelGroup = Mockito.mock(RepostCheckChannelGroup.class);
when(firstRepostCheckChannelGroup.getCheckEnabled()).thenReturn(true);
RepostCheckChannelGroup secondRepostCheckChannelGroup = Mockito.mock(RepostCheckChannelGroup.class);
when(secondRepostCheckChannelGroup.getCheckEnabled()).thenReturn(false);
when(repostCheckChannelManagement.loadRepostChannelGroupById(firstChannelGroupId)).thenReturn(firstRepostCheckChannelGroup);
when(repostCheckChannelManagement.loadRepostChannelGroupById(secondChannelGroupId)).thenReturn(secondRepostCheckChannelGroup);
return Arrays.asList(firstRepostCheckChannelGroup, secondRepostCheckChannelGroup);
}
}

View File

@@ -0,0 +1,467 @@
package dev.sheldan.abstracto.repostdetection.service;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.core.models.cache.*;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.FileService;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureMode;
import dev.sheldan.abstracto.repostdetection.converter.RepostLeaderBoardConverter;
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
import dev.sheldan.abstracto.repostdetection.model.database.Repost;
import dev.sheldan.abstracto.repostdetection.model.database.embed.PostIdentifier;
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.repostdetection.service.management.PostedImageManagement;
import dev.sheldan.abstracto.repostdetection.service.management.RepostManagementService;
import net.dv8tion.jda.api.entities.*;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostServiceBeanTest {
@InjectMocks
private RepostServiceBean testUnit;
@Mock
private HttpService httpService;
@Mock
private HashService hashService;
@Mock
private FileService fileService;
@Mock
private PostedImageManagement postedImageManagement;
@Mock
private ServerManagementService serverManagementService;
@Mock
private ChannelManagementService channelManagementService;
@Mock
private UserInServerManagementService userInServerManagementService;
@Mock
private ReactionService reactionService;
@Mock
private FeatureModeService featureModeService;
@Mock
private RepostManagementService repostManagementService;
@Mock
private RepostLeaderBoardConverter leaderBoardConverter;
@Mock
private RepostServiceBean self;
@Mock
private AUserInAServer userInAServer;
@Mock
private AUser user;
@Mock
private Guild guild;
@Mock
private AServer server;
@Mock
private AChannel channel;
@Mock
private PostedImage postedImage;
@Mock
private Repost repost;
@Mock
private CachedMessage cachedMessage;
@Mock
private Message message;
@Mock
private MessageChannel messageChannel;
@Mock
private CachedAuthor author;
private static final Long SERVER_ID = 4L;
private static final Long CHANNEL_ID = 8L;
private static final Long MESSAGE_ID = 5L;
private static final Integer POSITION = 6;
private static final Long USER_ID = 7L;
private static final String URL = "url";
private static final String HASH = "hash";
@Test
public void testPurgeRepostsForUser() {
testUnit.purgeReposts(userInAServer);
verify(repostManagementService, times(1)).deleteRepostsFromUser(userInAServer);
}
@Test
public void testPurgeRepostsForServer() {
when(guild.getIdLong()).thenReturn(SERVER_ID);
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
testUnit.purgeReposts(guild);
verify(repostManagementService, times(1)).deleteRepostsFromServer(server);
}
@Test
public void testRetrieveRepostLeaderboard() {
Integer page = 4;
when(guild.getIdLong()).thenReturn(SERVER_ID);
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
RepostLeaderboardResult result = Mockito.mock(RepostLeaderboardResult.class);
List<RepostLeaderboardResult> resultList = Arrays.asList(result);
when(repostManagementService.findTopRepostingUsersOfServer(server, page, RepostServiceBean.LEADER_BOARD_PAGE_SIZE)).thenReturn(resultList);
RepostLeaderboardEntryModel firstModel = Mockito.mock(RepostLeaderboardEntryModel.class);
RepostLeaderboardEntryModel secondModel = Mockito.mock(RepostLeaderboardEntryModel.class);
List<RepostLeaderboardEntryModel> entries = Arrays.asList(firstModel, secondModel);
when(leaderBoardConverter.fromLeaderBoardResults(resultList)).thenReturn(CompletableFuture.completedFuture(entries));
CompletableFuture<List<RepostLeaderboardEntryModel>> future = testUnit.retrieveRepostLeaderboard(guild, page);
Assert.assertTrue(future.isDone());
List<RepostLeaderboardEntryModel> futureList = future.join();
Assert.assertEquals(2, futureList.size());
Assert.assertEquals(firstModel, futureList.get(0));
Assert.assertEquals(secondModel, futureList.get(1));
}
@Test
public void testPersistRepostWithExisting() {
Integer count = 4;
when(postedImageManagement.getPostFromMessageAndPosition(MESSAGE_ID, POSITION)).thenReturn(postedImage);
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(userInAServer);
when(repost.getCount()).thenReturn(count);
when(repostManagementService.findRepostOptional(postedImage, userInAServer)).thenReturn(Optional.of(repost));
testUnit.persistRepost(MESSAGE_ID, POSITION, SERVER_ID, USER_ID);
verify(repost, times(1)).setCount(count + 1);
}
@Test
public void testPersistRepostWithoutExisting() {
when(postedImageManagement.getPostFromMessageAndPosition(MESSAGE_ID, POSITION)).thenReturn(postedImage);
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(userInAServer);
when(repostManagementService.findRepostOptional(postedImage, userInAServer)).thenReturn(Optional.empty());
testUnit.persistRepost(MESSAGE_ID, POSITION, SERVER_ID, USER_ID);
verify(repostManagementService, times(1)).createRepost(postedImage, userInAServer);
}
@Test
public void testCalculateHashForPostWithImage() throws IOException {
File file = Mockito.mock(File.class);
when(featureModeService.featureModeActive(RepostDetectionFeatureDefinition.REPOST_DETECTION, SERVER_ID, RepostDetectionFeatureMode.DOWNLOAD)).thenReturn(true);
when(httpService.downloadFileToTempFile(URL)).thenReturn(file);
when(hashService.sha256HashFileContent(file)).thenReturn(HASH);
String calculatedHash = testUnit.calculateHashForPost(URL, SERVER_ID);
Assert.assertEquals(HASH, calculatedHash);
verify(fileService, times(1)).safeDelete(file);
}
@Test
public void testCalculateHashForPostWithImageException() throws IOException {
File file = Mockito.mock(File.class);
when(featureModeService.featureModeActive(RepostDetectionFeatureDefinition.REPOST_DETECTION, SERVER_ID, RepostDetectionFeatureMode.DOWNLOAD)).thenReturn(true);
when(httpService.downloadFileToTempFile(URL)).thenReturn(file);
when(hashService.sha256HashFileContent(file)).thenThrow(new IOException());
testUnit.calculateHashForPost(URL, SERVER_ID);
verify(fileService, times(1)).safeDelete(file);
}
@Test
public void testCalculateHashForPostWithUrl() {
when(featureModeService.featureModeActive(RepostDetectionFeatureDefinition.REPOST_DETECTION, SERVER_ID, RepostDetectionFeatureMode.DOWNLOAD)).thenReturn(false);
when(hashService.sha256HashString(URL)).thenReturn(HASH);
String calculatedHash = testUnit.calculateHashForPost(URL, SERVER_ID);
Assert.assertEquals(HASH, calculatedHash);
}
@Test
public void testProcessMessageAttachmentRepostCheckNoAttachment() {
when(cachedMessage.getAttachments()).thenReturn(new ArrayList<>());
testUnit.processMessageAttachmentRepostCheck(cachedMessage);
verify(cachedMessage, times(0)).getChannelId();
}
@Test
public void testProcessMessageAttachmentRepostCheckOneAttachmentNotExistingPost() {
generalSetupForRepostTest();
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
when(author.getAuthorId()).thenReturn(USER_ID);
when(cachedMessage.getAuthor()).thenReturn(author);
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
CachedAttachment attachment = Mockito.mock(CachedAttachment.class);
when(cachedMessage.getAttachments()).thenReturn(Arrays.asList(attachment));
when(attachment.getProxyUrl()).thenReturn(URL);
setupSingleRepost();
testUnit.processMessageAttachmentRepostCheck(cachedMessage);
verify(postedImageManagement, times(1)).createPost(any(AServerAChannelAUser.class), eq(MESSAGE_ID), eq(HASH), eq(0));
verify(reactionService, times(0)).addReactionToMessageAsync(RepostServiceBean.REPOST_MARKER_EMOTE_KEY, SERVER_ID, CHANNEL_ID, MESSAGE_ID);
}
@Test
public void testProcessMessageAttachmentRepostCheckOneAttachmentIsRepost() {
generalSetupForRepostTest();
setupForRepostCreation();
CachedAttachment attachment = Mockito.mock(CachedAttachment.class);
when(cachedMessage.getAttachments()).thenReturn(Arrays.asList(attachment));
when(attachment.getProxyUrl()).thenReturn(URL);
setupSingleHash(postedImage);
Long originalPostMessageId = MESSAGE_ID + 1;
when(postedImage.getPostId()).thenReturn(new PostIdentifier(originalPostMessageId, POSITION));
when(reactionService.addReactionToMessageAsync(RepostServiceBean.REPOST_MARKER_EMOTE_KEY, SERVER_ID, CHANNEL_ID, MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(null));
testUnit.processMessageAttachmentRepostCheck(cachedMessage);
verify(reactionService, times(0)).addDefaultReactionToMessageAsync(anyString(), eq(SERVER_ID), eq(CHANNEL_ID), eq(MESSAGE_ID));
verify(self, times(1)).persistRepost(originalPostMessageId, POSITION, SERVER_ID, USER_ID);
}
@Test
public void testProcessMessageAttachmentRepostCheckTwoAttachmentsOneIsRepost() {
generalSetupForRepostTest();
setupForRepostCreation();
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
when(cachedMessage.getAuthor().getAuthorId()).thenReturn(USER_ID);
CachedAttachment attachment = Mockito.mock(CachedAttachment.class);
CachedAttachment attachment2 = Mockito.mock(CachedAttachment.class);
when(cachedMessage.getAttachments()).thenReturn(Arrays.asList(attachment, attachment2));
when(attachment.getProxyUrl()).thenReturn(URL);
setupSingleRepost();
String secondAttachmentUrl = URL + "2";
when(attachment2.getProxyUrl()).thenReturn(secondAttachmentUrl);
String secondAttachmentHash = HASH + "2";
when(hashService.sha256HashString(secondAttachmentUrl)).thenReturn(secondAttachmentHash);
when(postedImageManagement.getPostWithHash(secondAttachmentHash, server)).thenReturn(Optional.of(postedImage));
Long originalPostMessageId = MESSAGE_ID + 1;
when(postedImage.getPostId()).thenReturn(new PostIdentifier(originalPostMessageId, POSITION));
when(reactionService.addReactionToMessageAsync(RepostServiceBean.REPOST_MARKER_EMOTE_KEY, SERVER_ID, CHANNEL_ID, MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(null));
when(reactionService.addDefaultReactionToMessageAsync(anyString(), eq(SERVER_ID), eq(CHANNEL_ID), eq(MESSAGE_ID))).thenReturn(CompletableFuture.completedFuture(null));
testUnit.processMessageAttachmentRepostCheck(cachedMessage);
verify(postedImageManagement, times(1)).createPost(any(AServerAChannelAUser.class), eq(MESSAGE_ID), eq(HASH), eq(0));
verify(self, times(1)).persistRepost(originalPostMessageId, POSITION, SERVER_ID, USER_ID);
}
private void setupForRepostCreation() {
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
when(cachedMessage.getAuthor()).thenReturn(author);
when(author.getAuthorId()).thenReturn(USER_ID);
when(cachedMessage.getChannelId()).thenReturn(CHANNEL_ID);
}
private void generalSetupForRepostTest() {
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(userInAServer);
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
}
private void setupSingleRepost() {
setupSingleHash(null);
when(userInAServer.getUserReference()).thenReturn(user);
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(channel);
}
private void setupSingleHash(PostedImage postedImage) {
when(featureModeService.featureModeActive(RepostDetectionFeatureDefinition.REPOST_DETECTION, SERVER_ID, RepostDetectionFeatureMode.DOWNLOAD)).thenReturn(false);
when(hashService.sha256HashString(URL)).thenReturn(HASH);
when(postedImageManagement.getPostWithHash(HASH, server)).thenReturn(Optional.ofNullable(postedImage));
}
@Test
public void testProcessMessageEmbedsRepostCheckWithNotRepostedThumbnailNoAttachments() {
generalSetupForRepostTest();
CachedEmbed firstEmbed = Mockito.mock(CachedEmbed.class);
CachedThumbnail thumbnail = Mockito.mock(CachedThumbnail.class);
when(thumbnail.getProxyUrl()).thenReturn(URL);
when(firstEmbed.getCachedThumbnail()).thenReturn(thumbnail);
List<CachedEmbed> messageEmbeds = Arrays.asList(firstEmbed);
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
when(cachedMessage.getAuthor()).thenReturn(author);
when(author.getAuthorId()).thenReturn(USER_ID);
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
when(cachedMessage.getAttachments()).thenReturn(new ArrayList<>());
setupSingleRepost();
testUnit.processMessageEmbedsRepostCheck(messageEmbeds, cachedMessage);
verify(postedImageManagement, times(1)).createPost(any(AServerAChannelAUser.class), eq(MESSAGE_ID), eq(HASH), eq(RepostServiceBean.EMBEDDED_LINK_POSITION_START_INDEX));
verify(reactionService, times(0)).addReactionToMessageAsync(RepostServiceBean.REPOST_MARKER_EMOTE_KEY, SERVER_ID, CHANNEL_ID, MESSAGE_ID);
}
@Test
public void testProcessMessageEmbedsRepostCheckWithNotRepostedEmbedImageNoAttachments() {
generalSetupForRepostTest();
CachedEmbed firstEmbed = Mockito.mock(CachedEmbed.class);
CachedImageInfo image = Mockito.mock(CachedImageInfo.class);
when(image.getProxyUrl()).thenReturn(URL);
when(firstEmbed.getCachedImageInfo()).thenReturn(image);
List<CachedEmbed> messageEmbeds = Arrays.asList(firstEmbed);
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
when(author.getAuthorId()).thenReturn(USER_ID);
when(cachedMessage.getAuthor()).thenReturn(author);
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
when(cachedMessage.getAttachments()).thenReturn(new ArrayList<>());
setupSingleRepost();
testUnit.processMessageEmbedsRepostCheck(messageEmbeds, cachedMessage);
verify(postedImageManagement, times(1)).createPost(any(AServerAChannelAUser.class), eq(MESSAGE_ID), eq(HASH), eq(RepostServiceBean.EMBEDDED_LINK_POSITION_START_INDEX));
verify(reactionService, times(0)).addReactionToMessageAsync(RepostServiceBean.REPOST_MARKER_EMOTE_KEY, SERVER_ID, CHANNEL_ID, MESSAGE_ID);
}
@Test
public void testProcessMessageEmbedsRepostCheckWithRepostedThumbnailNoAttachments() {
generalSetupForRepostTest();
setupForRepostCreation();
CachedEmbed firstEmbed = Mockito.mock(CachedEmbed.class);
CachedThumbnail thumbnail = Mockito.mock(CachedThumbnail.class);
when(thumbnail.getProxyUrl()).thenReturn(URL);
when(firstEmbed.getCachedThumbnail()).thenReturn(thumbnail);
List<CachedEmbed> messageEmbeds = Arrays.asList(firstEmbed);
when(cachedMessage.getAttachments()).thenReturn(new ArrayList<>());
setupSingleHash(postedImage);
Long originalPostMessageId = MESSAGE_ID + 1;
when(postedImage.getPostId()).thenReturn(new PostIdentifier(originalPostMessageId, POSITION));
when(reactionService.addReactionToMessageAsync(RepostServiceBean.REPOST_MARKER_EMOTE_KEY, SERVER_ID, CHANNEL_ID, MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(null));
testUnit.processMessageEmbedsRepostCheck(messageEmbeds, cachedMessage);
verify(self, times(1)).persistRepost(originalPostMessageId, POSITION, SERVER_ID, USER_ID);
}
@Test
public void testIsRepostEmptyEmbedMessage() {
CachedEmbed messageEmbed = Mockito.mock(CachedEmbed.class);
Optional<PostedImage> emptyOptional = testUnit.getRepostFor(cachedMessage, messageEmbed, POSITION);
Assert.assertFalse(emptyOptional.isPresent());
}
@Test
public void testGetRepostForWithRepostSameMessage() {
executeGetRepostForWithMessageId(MESSAGE_ID, false);
}
@Test
public void testGetRepostForWithRepost() {
executeGetRepostForWithMessageId(MESSAGE_ID + 1, true);
}
private void executeGetRepostForWithMessageId(Long originalPostMessageId, boolean shouldBePresent) {
CachedEmbed messageEmbed = setupSimpleRepostCheck(originalPostMessageId);
Optional<PostedImage> optional = testUnit.getRepostFor(cachedMessage, messageEmbed, POSITION);
Assert.assertEquals(shouldBePresent, optional.isPresent());
if(shouldBePresent && optional.isPresent()) {
Assert.assertEquals(postedImage, optional.get());
}
}
private CachedEmbed setupSimpleRepostCheck(Long originalPostMessageId) {
generalSetupForRepostTest();
setupForRepostCreation();
setupSingleHash(postedImage);
when(postedImage.getPostId()).thenReturn(new PostIdentifier(originalPostMessageId, POSITION));
CachedEmbed messageEmbed = Mockito.mock(CachedEmbed.class);
CachedThumbnail thumbnail = Mockito.mock(CachedThumbnail.class);
when(thumbnail.getProxyUrl()).thenReturn(URL);
when(messageEmbed.getCachedThumbnail()).thenReturn(thumbnail);
return messageEmbed;
}
@Test
public void testIsRepostWithRepost() {
CachedEmbed messageEmbed = setupSimpleRepostCheck(MESSAGE_ID + 1);
Assert.assertTrue(testUnit.isRepost(cachedMessage, messageEmbed, POSITION));
}
@Test
public void testIsRepostWithSameMessage() {
CachedEmbed messageEmbed = setupSimpleRepostCheck(MESSAGE_ID);
Assert.assertFalse(testUnit.isRepost(cachedMessage, messageEmbed, POSITION));
}
@Test
public void testIsRepostWithRepostInAttachment() {
generalSetupForRepostTest();
setupSingleRepost();
setupSingleHash(postedImage);
when(postedImage.getPostId()).thenReturn(new PostIdentifier(MESSAGE_ID + 1, POSITION));
CachedAttachment attachment = Mockito.mock(CachedAttachment.class);
when(attachment.getProxyUrl()).thenReturn(URL);
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
when(author.getAuthorId()).thenReturn(USER_ID);
when(cachedMessage.getAuthor()).thenReturn(author);
Assert.assertTrue(testUnit.isRepost(cachedMessage, attachment, POSITION));
}
@Test
public void testGetRepostForEmpty() {
Optional<PostedImage> repost = testUnit.getRepostFor(message, Mockito.mock(MessageEmbed.class), 1);
Assert.assertFalse(repost.isPresent());
}
@Test
public void testGetRepostForMessageThumbnail() {
MessageEmbed messageEmbed = Mockito.mock(MessageEmbed.class);
MessageEmbed.Thumbnail thumbnail = Mockito.mock(MessageEmbed.Thumbnail.class);
when(thumbnail.getProxyUrl()).thenReturn(URL);
when(messageEmbed.getThumbnail()).thenReturn(thumbnail);
generalSetupForRepostTest();
setupForRepostCreation();
setupSingleHash(postedImage);
when(postedImage.getPostId()).thenReturn(new PostIdentifier(2L, POSITION));
when(message.getGuild()).thenReturn(guild);
when(guild.getIdLong()).thenReturn(SERVER_ID);
User author = Mockito.mock(User.class);
when(author.getIdLong()).thenReturn(USER_ID);
when(message.getAuthor()).thenReturn(author);
when(message.getChannel()).thenReturn(messageChannel);
when(messageChannel.getIdLong()).thenReturn(CHANNEL_ID);
Optional<PostedImage> repost = testUnit.getRepostFor(message, messageEmbed, 1);
Assert.assertTrue(repost.isPresent());
repost.ifPresent(postedImage1 -> Assert.assertEquals(postedImage, postedImage1));
}
@Test
public void testProcessMessageEmbedsRepostCheck() {
MessageEmbed messageEmbed = Mockito.mock(MessageEmbed.class);
MessageEmbed.ImageInfo imageInfo = Mockito.mock(MessageEmbed.ImageInfo.class);
when(imageInfo.getProxyUrl()).thenReturn(URL);
when(messageEmbed.getImage()).thenReturn(imageInfo);
generalSetupForRepostTest();
setupForRepostCreation();
setupSingleHash(postedImage);
when(postedImage.getPostId()).thenReturn(new PostIdentifier(2L, POSITION));
when(message.getGuild()).thenReturn(guild);
when(message.getIdLong()).thenReturn(MESSAGE_ID);
when(guild.getIdLong()).thenReturn(SERVER_ID);
User author = Mockito.mock(User.class);
when(author.getIdLong()).thenReturn(USER_ID);
when(message.getAuthor()).thenReturn(author);
when(message.getChannel()).thenReturn(messageChannel);
when(messageChannel.getIdLong()).thenReturn(CHANNEL_ID);
when(reactionService.addReactionToMessageAsync(RepostServiceBean.REPOST_MARKER_EMOTE_KEY, SERVER_ID, CHANNEL_ID, MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(null));
testUnit.processMessageEmbedsRepostCheck(Collections.singletonList(messageEmbed), message);
verify(self, times(1)).persistRepost(2L, POSITION, SERVER_ID, USER_ID);
}
}

View File

@@ -0,0 +1,145 @@
package dev.sheldan.abstracto.repostdetection.service.management;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.repostdetection.exception.PostedImageNotFoundException;
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
import dev.sheldan.abstracto.repostdetection.model.database.embed.PostIdentifier;
import dev.sheldan.abstracto.repostdetection.repository.PostedImageRepository;
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class PostedImageManagementBeanTest {
@InjectMocks
private PostedImageManagementBean testUnit;
@Mock
private PostedImageRepository postedImageRepository;
@Mock
private AUserInAServer aUserInAServer;
@Mock
private AServer server;
@Mock
private PostedImage postedImage;
private static final String HASH = "hash";
private static final Integer INDEX = 1;
private static final Long MESSAGE_ID = 4L;
private static final Long SERVER_ID = 3L;
private static final Integer POSITION = 5;
@Test
public void testCreatePost() {
AServerAChannelAUser serverAChannelAUser = Mockito.mock(AServerAChannelAUser.class);
AChannel channel = Mockito.mock(AChannel.class);
when(serverAChannelAUser.getGuild()).thenReturn(server);
when(serverAChannelAUser.getChannel()).thenReturn(channel);
when(serverAChannelAUser.getAUserInAServer()).thenReturn(aUserInAServer);
PostedImage createdPost = testUnit.createPost(serverAChannelAUser, MESSAGE_ID, HASH, INDEX);
Assert.assertEquals(HASH, createdPost.getImageHash());
Assert.assertEquals(INDEX, createdPost.getPostId().getPosition());
Assert.assertEquals(MESSAGE_ID, createdPost.getPostId().getMessageId());
verify(postedImageRepository, times(1)).save(createdPost);
}
@Test
public void testPostWitHashExists() {
when(server.getId()).thenReturn(SERVER_ID);
when(postedImageRepository.existsByImageHashAndServerId(HASH, SERVER_ID)).thenReturn(true);
Assert.assertTrue(testUnit.postWitHashExists(HASH, server));
}
@Test
public void testGetPostWithHash() {
when(server.getId()).thenReturn(SERVER_ID);
when(postedImageRepository.findByImageHashAndServerId(HASH, SERVER_ID)).thenReturn(Optional.of(postedImage));
java.util.Optional<PostedImage> optionalPostedImage = testUnit.getPostWithHash(HASH, server);
Assert.assertTrue(optionalPostedImage.isPresent());
optionalPostedImage.ifPresent(optionalPostedImageObj ->
Assert.assertEquals(postedImage, optionalPostedImageObj)
);
}
@Test
public void testMessageHasBeenCovered() {
when(postedImageRepository.existsByPostId_MessageId(MESSAGE_ID)).thenReturn(true);
Assert.assertTrue(testUnit.messageHasBeenCovered(MESSAGE_ID));
}
@Test
public void testMessageEmbedsHaveBeenCovered() {
when(postedImageRepository.existsByPostId_MessageIdAndPostId_PositionGreaterThan(MESSAGE_ID, RepostServiceBean.EMBEDDED_LINK_POSITION_START_INDEX - 1)).thenReturn(true);
Assert.assertTrue(testUnit.messageEmbedsHaveBeenCovered(MESSAGE_ID));
}
@Test
public void testGetAllFromMessage() {
when(postedImageRepository.findByPostId_MessageId(MESSAGE_ID)).thenReturn(Arrays.asList(postedImage));
List<PostedImage> foundPosts = testUnit.getAllFromMessage(MESSAGE_ID);
Assert.assertEquals(1, foundPosts.size());
Assert.assertEquals(postedImage, foundPosts.get(0));
}
@Test
public void testGetAllFromMessageEmpty() {
when(postedImageRepository.findByPostId_MessageId(MESSAGE_ID)).thenReturn(new ArrayList<>());
List<PostedImage> foundPosts = testUnit.getAllFromMessage(MESSAGE_ID);
Assert.assertEquals(0, foundPosts.size());
}
@Test
public void testGetPostFromMessageAndPositionOptional() {
when(postedImageRepository.findById(new PostIdentifier(MESSAGE_ID, POSITION))).thenReturn(Optional.of(postedImage));
Optional<PostedImage> foundPostedImage = testUnit.getPostFromMessageAndPositionOptional(MESSAGE_ID, POSITION);
Assert.assertTrue(foundPostedImage.isPresent());
foundPostedImage.ifPresent(optionalPostedImageObj ->
Assert.assertEquals(postedImage, optionalPostedImageObj)
);
}
@Test(expected = PostedImageNotFoundException.class)
public void testGetPostFromMessageAndPositionNotFound() {
when(postedImageRepository.findById(new PostIdentifier(MESSAGE_ID, POSITION))).thenReturn(Optional.empty());
testUnit.getPostFromMessageAndPosition(MESSAGE_ID, POSITION);
}
@Test
public void testGetPostFromMessageAndPositionFound() {
when(postedImageRepository.findById(new PostIdentifier(MESSAGE_ID, POSITION))).thenReturn(Optional.of(postedImage));
PostedImage foundPostedImage = testUnit.getPostFromMessageAndPosition(MESSAGE_ID, POSITION);
Assert.assertEquals(postedImage, foundPostedImage);
}
@Test
public void testRemovePostedImagesOf() {
testUnit.removePostedImagesOf(aUserInAServer);
verify(postedImageRepository, times(1)).deleteByPoster(aUserInAServer);
}
@Test
public void testRemovePostedImagesIn() {
testUnit.removedPostedImagesIn(server);
verify(postedImageRepository, times(1)).deleteByServer(server);
}
}

View File

@@ -0,0 +1,130 @@
package dev.sheldan.abstracto.repostdetection.service.management;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.repostdetection.exception.RepostCheckChannelGroupNotFoundException;
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.repostdetection.repository.RepostCheckChannelRepository;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Optional;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostCheckChannelGroupManagementBeanTest {
@InjectMocks
private RepostCheckChannelGroupManagementBean testUnit;
@Mock
private RepostCheckChannelRepository repository;
@Mock
private RepostCheckChannelGroup checkChannelGroup;
@Mock
private AChannelGroup aChannelGroup;
@Captor
private ArgumentCaptor<RepostCheckChannelGroup> checkChannelGroupArgumentCaptor;
private static final Long CHANNEL_GROUP_ID = 1L;
@Test(expected = RepostCheckChannelGroupNotFoundException.class)
public void testLoadRepostChannelGroupByIdNotFound() {
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.empty());
testUnit.loadRepostChannelGroupById(CHANNEL_GROUP_ID);
}
@Test
public void testLoadRepostChannelGroupById() {
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.of(checkChannelGroup));
RepostCheckChannelGroup resultChannelGroup = testUnit.loadRepostChannelGroupById(CHANNEL_GROUP_ID);
Assert.assertEquals(checkChannelGroup, resultChannelGroup);
}
@Test
public void testLoadRepostChannelGroupByIdOptional() {
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.of(checkChannelGroup));
Optional<RepostCheckChannelGroup> resultChannelGroupOptional = testUnit.loadRepostChanelGroupByIdOptional(CHANNEL_GROUP_ID);
Assert.assertTrue(resultChannelGroupOptional.isPresent());
resultChannelGroupOptional.ifPresent(repostCheckChannelGroup -> Assert.assertEquals(checkChannelGroup, repostCheckChannelGroup));
}
@Test
public void testRepostCheckChannelGroupExistsNot() {
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.empty());
Assert.assertFalse(testUnit.repostCheckChannelGroupExists(CHANNEL_GROUP_ID));
}
@Test
public void testRepostCheckChannelGroupExists() {
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.of(checkChannelGroup));
Assert.assertTrue(testUnit.repostCheckChannelGroupExists(CHANNEL_GROUP_ID));
}
@Test
public void testLoadRepostChannelGroupByChannelGroupOptionalPresent() {
when(aChannelGroup.getId()).thenReturn(CHANNEL_GROUP_ID);
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.of(checkChannelGroup));
Optional<RepostCheckChannelGroup> resultChannelGroupOptional = testUnit.loadRepostChannelGroupByChannelGroupOptional(aChannelGroup);
Assert.assertTrue(resultChannelGroupOptional.isPresent());
resultChannelGroupOptional.ifPresent(repostCheckChannelGroup -> Assert.assertEquals(checkChannelGroup, repostCheckChannelGroup));
}
@Test
public void testLoadRepostChannelGroupByChannelGroupOptionalNotPresent() {
when(aChannelGroup.getId()).thenReturn(CHANNEL_GROUP_ID);
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.empty());
Optional<RepostCheckChannelGroup> resultChannelGroupOptional = testUnit.loadRepostChannelGroupByChannelGroupOptional(aChannelGroup);
Assert.assertFalse(resultChannelGroupOptional.isPresent());
}
@Test
public void testLoadRepostChannelGroupByChannelGroup() {
when(aChannelGroup.getId()).thenReturn(CHANNEL_GROUP_ID);
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.of(checkChannelGroup));
RepostCheckChannelGroup repostCheckChannelGroup = testUnit.loadRepostChannelGroupByChannelGroup(aChannelGroup);
Assert.assertEquals(checkChannelGroup, repostCheckChannelGroup);
}
@Test(expected = RepostCheckChannelGroupNotFoundException.class)
public void testLoadRepostChannelGroupByChannelGroupNotFound() {
when(aChannelGroup.getId()).thenReturn(CHANNEL_GROUP_ID);
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.empty());
testUnit.loadRepostChannelGroupByChannelGroup(aChannelGroup);
}
@Test
public void testCreateRepostCheckChannelGroup() {
when(aChannelGroup.getId()).thenReturn(CHANNEL_GROUP_ID);
RepostCheckChannelGroup createdCheckChannelGroup = testUnit.createRepostCheckChannelGroup(aChannelGroup);
verify(repository, times(1)).save(checkChannelGroupArgumentCaptor.capture());
Assert.assertEquals(checkChannelGroupArgumentCaptor.getValue(), createdCheckChannelGroup);
Assert.assertTrue(createdCheckChannelGroup.getCheckEnabled());
Assert.assertEquals(CHANNEL_GROUP_ID, createdCheckChannelGroup.getId());
Assert.assertEquals(aChannelGroup, createdCheckChannelGroup.getChannelGroup());
}
@Test(expected = RepostCheckChannelGroupNotFoundException.class)
public void testDeleteRepostCheckChannelGroupNotExisting(){
when(aChannelGroup.getId()).thenReturn(CHANNEL_GROUP_ID);
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.empty());
testUnit.deleteRepostCheckChannelGroup(aChannelGroup);
}
@Test
public void testDeleteRepostCheckChannelGroup(){
when(aChannelGroup.getId()).thenReturn(CHANNEL_GROUP_ID);
when(repository.findById(CHANNEL_GROUP_ID)).thenReturn(Optional.of(checkChannelGroup));
testUnit.deleteRepostCheckChannelGroup(aChannelGroup);
verify(repository, times(1)).delete(checkChannelGroup);
}
}

View File

@@ -0,0 +1,185 @@
package dev.sheldan.abstracto.repostdetection.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.repostdetection.exception.RepostNotFoundException;
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
import dev.sheldan.abstracto.repostdetection.model.database.Repost;
import dev.sheldan.abstracto.repostdetection.model.database.embed.PostIdentifier;
import dev.sheldan.abstracto.repostdetection.model.database.embed.RepostIdentifier;
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.repostdetection.repository.RepostRepository;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Pageable;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RepostManagementServiceBeanTest {
@InjectMocks
private RepostManagementServiceBean testUnit;
@Mock
private RepostRepository repostRepository;
@Mock
private PostedImage postedImage;
@Mock
private AUserInAServer poster;
@Mock
private PostIdentifier postIdentifier;
@Mock
private Repost repost;
@Mock
private AServer server;
@Captor
private ArgumentCaptor<Repost> repostArgumentCaptor;
@Captor
private ArgumentCaptor<Pageable> pageableArgumentCaptor;
private static final Long MESSAGE_ID = 1L;
private static final Integer POSITION = 2;
private static final Long USER_IN_SERVER_ID = 3L;
private static final Integer COUNT = 4;
private static final Long SERVER_ID = 5L;
private static final Integer PAGE = 6;
private static final Integer PAGE_SIZE = 7;
@Test
public void testCreateRepost() {
setupPostIdentifier();
testUnit.createRepost(postedImage, poster);
verify(repostRepository, times(1)).save(repostArgumentCaptor.capture());
Repost capturedRepost = repostArgumentCaptor.getValue();
Assert.assertEquals(poster, capturedRepost.getPoster());
Assert.assertEquals(postedImage, capturedRepost.getOriginalPost());
Assert.assertEquals(MESSAGE_ID, capturedRepost.getRepostId().getMessageId());
Assert.assertEquals(POSITION, capturedRepost.getRepostId().getPosition());
Assert.assertEquals(USER_IN_SERVER_ID, capturedRepost.getRepostId().getUserInServerId());
}
@Test
public void testFindRepostOptional() {
setupPostIdentifier();
when(repostRepository.findById(any(RepostIdentifier.class))).thenReturn(Optional.of(repost));
Optional<Repost> repostOptional = testUnit.findRepostOptional(postedImage, poster);
Assert.assertTrue(repostOptional.isPresent());
repostOptional.ifPresent(foundRepost -> Assert.assertEquals(repost, foundRepost));
}
@Test
public void testFindRepostOptionalNotPresent() {
setupPostIdentifier();
when(repostRepository.findById(any(RepostIdentifier.class))).thenReturn(Optional.empty());
Optional<Repost> repostOptional = testUnit.findRepostOptional(postedImage, poster);
Assert.assertFalse(repostOptional.isPresent());
}
@Test
public void testSetRepostCount() {
setupPostIdentifier();
when(repostRepository.findById(any(RepostIdentifier.class))).thenReturn(Optional.of(repost));
Repost updatedRepost = testUnit.setRepostCount(postedImage, poster, COUNT);
verify(repost, times(1)).setCount(4);
Assert.assertEquals(repost, updatedRepost);
}
@Test(expected = RepostNotFoundException.class)
public void testSetRepostCountNotFound() {
setupPostIdentifier();
when(repostRepository.findById(any(RepostIdentifier.class))).thenReturn(Optional.empty());
testUnit.setRepostCount(postedImage, poster, COUNT);
}
@Test(expected = RepostNotFoundException.class)
public void testFindRepostNotFound() {
setupPostIdentifier();
when(repostRepository.findById(any(RepostIdentifier.class))).thenReturn(Optional.empty());
testUnit.findRepost(postedImage, poster);
}
@Test
public void testFindRepost() {
setupPostIdentifier();
when(repostRepository.findById(any(RepostIdentifier.class))).thenReturn(Optional.of(repost));
Repost foundRepost = testUnit.findRepost(postedImage, poster);
Assert.assertEquals(repost, foundRepost);
}
@Test
public void testFindTopRepostingUsersOfServer() {
RepostLeaderboardResult singleResult = Mockito.mock(RepostLeaderboardResult.class);
when(repostRepository.findTopRepostingUsers(eq(SERVER_ID), pageableArgumentCaptor.capture())).thenReturn(Arrays.asList(singleResult));
List<RepostLeaderboardResult> foundResult = testUnit.findTopRepostingUsersOfServer(SERVER_ID, PAGE, PAGE_SIZE);
checkLeaderboardResult(singleResult, foundResult);
}
@Test
public void testFindTopRepostingUsersOfServerAServer() {
when(server.getId()).thenReturn(SERVER_ID);
RepostLeaderboardResult singleResult = Mockito.mock(RepostLeaderboardResult.class);
when(repostRepository.findTopRepostingUsers(eq(SERVER_ID), pageableArgumentCaptor.capture())).thenReturn(Arrays.asList(singleResult));
List<RepostLeaderboardResult> foundResult = testUnit.findTopRepostingUsersOfServer(server, PAGE, PAGE_SIZE);
checkLeaderboardResult(singleResult, foundResult);
}
@Test
public void testGetRepostRankOfUser() {
setupPoster();
RepostLeaderboardResult singleResult = Mockito.mock(RepostLeaderboardResult.class);
when(repostRepository.getRepostRankOfUserInServer(USER_IN_SERVER_ID, SERVER_ID)).thenReturn(singleResult);
RepostLeaderboardResult foundRank = testUnit.getRepostRankOfUser(poster);
Assert.assertEquals(singleResult, foundRank);
}
@Test
public void testDeleteRepostsFromUser() {
setupPoster();
testUnit.deleteRepostsFromUser(poster);
verify(repostRepository, times(1)).deleteByRepostId_UserInServerIdAndServerId(USER_IN_SERVER_ID, SERVER_ID);
}
@Test
public void testDeleteRepostsFromServer() {
when(server.getId()).thenReturn(SERVER_ID);
testUnit.deleteRepostsFromServer(server);
verify(repostRepository, times(1)).deleteByServerId(SERVER_ID);
}
private void setupPoster() {
when(poster.getServerReference()).thenReturn(server);
when(server.getId()).thenReturn(SERVER_ID);
when(poster.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
}
private void checkLeaderboardResult(RepostLeaderboardResult singleResult, List<RepostLeaderboardResult> foundResult) {
Pageable usedPaging = pageableArgumentCaptor.getValue();
Assert.assertEquals(PAGE - 1, usedPaging.getPageNumber());
Assert.assertEquals(PAGE_SIZE.intValue(), usedPaging.getPageSize());
Assert.assertEquals(1, foundResult.size());
Assert.assertEquals(singleResult, foundResult.get(0));
}
private void setupPostIdentifier() {
when(postedImage.getPostId()).thenReturn(postIdentifier);
when(postIdentifier.getMessageId()).thenReturn(MESSAGE_ID);
when(postIdentifier.getPosition()).thenReturn(POSITION);
when(poster.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
}
}