[AB-150] creating repost detection feature including configuration and documentation

adding http and hash service
adding ability to add default emotes to a message to message service
adding message embedded listener to wrap the embedded event
adding custom channel groups which can be defined by modules, in case a change on a channel group (only created and updated) happens a listener is available in order to sync the state in dependant areas
changing command receiver re-throwing abstracto runtime exceptions in order to display them better
changing channel group parameter handler to throw an exception in case the channel group was not found
adding User in a server parameter handler
split channel not found exception to be able to differentiate between not found in database and not found in guild
changing exception handling in command received handler to handle the case for only one parameter handler future which failed (the whole single future failed, which was not reported)
changing parameter type of `removeFromChannelGroup` to AChannel in order to be able to delete channels in the database via ID
moving method to mock utils for mocking consumer
removing parameter validation from commands, as it should be done in the command received handler and parameter handlers anyway
This commit is contained in:
Sheldan
2020-12-04 00:38:18 +01:00
parent e966c710ce
commit 325264a325
249 changed files with 5310 additions and 686 deletions

View File

@@ -32,7 +32,6 @@ public class ShowAvatar extends AbstractConditionableCommand {
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Member memberToShow = parameters.size() == 1 ? (Member) parameters.get(0) : commandContext.getUserInitiatedContext().getMember();
ShowAvatarModel model = (ShowAvatarModel) ContextConverter.fromCommandContext(commandContext, ShowAvatarModel.class);

View File

@@ -29,7 +29,6 @@ public class ShowEmote extends AbstractConditionableCommand {
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Emote emoteParameter = (Emote) parameters.get(0);
ShowEmoteLog emoteLog = (ShowEmoteLog) ContextConverter.fromCommandContext(commandContext, ShowEmoteLog.class);

View File

@@ -39,7 +39,6 @@ public class UserInfo extends AbstractConditionableCommand {
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Member memberToShow = parameters.size() == 1 ? (Member) parameters.get(0) : commandContext.getAuthor();
UserInfoModel model = (UserInfoModel) ContextConverter.slimFromCommandContext(commandContext, UserInfoModel.class);

View File

@@ -37,7 +37,6 @@ public class Remind extends AbstractConditionableCommand {
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Duration remindTime = (Duration) parameters.get(0);
String text = (String) parameters.get(1);

View File

@@ -29,7 +29,6 @@ public class UnRemind extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
Long reminderId = (Long) commandContext.getParameters().getParameters().get(0);
reminderService.unRemind(reminderId, commandContext.getUserInitiatedContext().getAUserInAServer());
return CommandResult.fromSuccess();

View File

@@ -0,0 +1,67 @@
package dev.sheldan.abstracto.utility.commands.repost;
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.FeatureEnum;
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.utility.config.RepostDetectionModuleInterface;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.service.RepostCheckChannelService;
import dev.sheldan.abstracto.utility.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(RepostDetectionModuleInterface.REPOST_DETECTION)
.templated(true)
.async(false)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return UtilityFeature.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,67 @@
package dev.sheldan.abstracto.utility.commands.repost;
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.FeatureEnum;
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.utility.config.RepostDetectionModuleInterface;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.service.RepostCheckChannelService;
import dev.sheldan.abstracto.utility.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(RepostDetectionModuleInterface.REPOST_DETECTION)
.templated(true)
.async(false)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return UtilityFeature.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,64 @@
package dev.sheldan.abstracto.utility.commands.repost;
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.FeatureEnum;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.utility.config.RepostDetectionModuleInterface;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.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.loadUser(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(RepostDetectionModuleInterface.REPOST_DETECTION)
.templated(true)
.async(false)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return UtilityFeature.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,64 @@
package dev.sheldan.abstracto.utility.commands.repost;
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.FeatureEnum;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.utility.config.RepostDetectionModuleInterface;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.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.loadUser(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(RepostDetectionModuleInterface.REPOST_DETECTION)
.templated(true)
.async(false)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return UtilityFeature.REPOST_DETECTION;
}
}

View File

@@ -0,0 +1,102 @@
package dev.sheldan.abstracto.utility.commands.repost;
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.FeatureEnum;
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.templating.service.TemplateService;
import dev.sheldan.abstracto.utility.config.RepostDetectionModuleInterface;
import dev.sheldan.abstracto.utility.config.features.RepostDetectionFeatureMode;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.converter.RepostLeaderBoardConverter;
import dev.sheldan.abstracto.utility.models.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.utility.models.RepostLeaderboardModel;
import dev.sheldan.abstracto.utility.models.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.utility.service.RepostService;
import dev.sheldan.abstracto.utility.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.loadUser(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.sendEmbedTemplateInChannel(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(RepostDetectionModuleInterface.REPOST_DETECTION)
.templated(true)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return UtilityFeature.REPOST_DETECTION;
}
@Override
public List<FeatureMode> getFeatureModeLimitations() {
return Arrays.asList(RepostDetectionFeatureMode.LEADERBOARD);
}
}

View File

@@ -0,0 +1,62 @@
package dev.sheldan.abstracto.utility.commands.repost;
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.FeatureEnum;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.utility.config.RepostDetectionModuleInterface;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.converter.RepostCheckChannelModelConverter;
import dev.sheldan.abstracto.utility.models.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.utility.models.template.commands.RepostCheckChannelsModel;
import dev.sheldan.abstracto.utility.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.sendEmbedTemplateInChannel(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(RepostDetectionModuleInterface.REPOST_DETECTION)
.templated(true)
.async(true)
.supportsEmbedException(true)
.causesReaction(false)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return UtilityFeature.REPOST_DETECTION;
}
}

View File

@@ -30,7 +30,6 @@ public class Accept extends AbstractConditionableCommand {
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Long suggestionId = (Long) parameters.get(0);
String text = parameters.size() == 2 ? (String) parameters.get(1) : "";

View File

@@ -30,7 +30,6 @@ public class Reject extends AbstractConditionableCommand {
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Long suggestionId = (Long) parameters.get(0);
String text = parameters.size() == 2 ? (String) parameters.get(1) : "";

View File

@@ -25,7 +25,6 @@ public class Suggest extends AbstractConditionableCommand {
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String text = (String) parameters.get(0);
SuggestionLog suggestLogModel = (SuggestionLog) ContextConverter.fromCommandContext(commandContext, SuggestionLog.class);

View File

@@ -0,0 +1,42 @@
package dev.sheldan.abstracto.utility.converter;
import dev.sheldan.abstracto.core.models.FullChannel;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.utility.models.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.utility.models.template.commands.RepostCheckChannelGroupDisplayModel;
import dev.sheldan.abstracto.utility.models.template.commands.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 BotService botService;
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(botService.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.utility.converter;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.utility.models.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.utility.models.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 BotService botService;
@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.loadUser(result.getUserInServerId());
Integer count = result.getRepostCount();
Long userInServerId = result.getUserInServerId();
Integer rank = result.getRank();
return botService.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.loadUser(userInServerId))
.count(count)
.rank(rank)
.build();
}
}

View File

@@ -0,0 +1,22 @@
package dev.sheldan.abstracto.utility.listener.repost;
import dev.sheldan.abstracto.core.listener.entity.ChannelGroupCreatedListener;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.utility.service.RepostServiceBean;
import dev.sheldan.abstracto.utility.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.utility.listener.repost;
import dev.sheldan.abstracto.core.listener.entity.ChannelGroupDeletedListener;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.utility.service.RepostServiceBean;
import dev.sheldan.abstracto.utility.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,58 @@
package dev.sheldan.abstracto.utility.listener.repost;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.config.ListenerPriority;
import dev.sheldan.abstracto.core.listener.MessageEmbeddedListener;
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.service.RepostCheckChannelService;
import dev.sheldan.abstracto.utility.service.RepostService;
import dev.sheldan.abstracto.utility.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 MessageEmbeddedListener {
@Autowired
private RepostCheckChannelService repostCheckChannelService;
@Autowired
private RepostService repostService;
@Autowired
private PostedImageManagement repostManagement;
@Override
public void execute(GuildMessageEmbedEventModel eventModel) {
if(repostCheckChannelService.duplicateCheckEnabledForChannel(eventModel.getChannel())) {
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.getChannel().getIdLong(), eventModel.getChannel().getGuild().getIdLong());
return;
}
eventModel.getChannel().retrieveMessageById(eventModel.getMessageId()).queue(message -> {
List<MessageEmbed> imageEmbeds = eventModel.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
repostService.processMessageEmbedsRepostCheck(imageEmbeds, message);
});
}
}
@Override
public FeatureEnum getFeature() {
return UtilityFeature.REPOST_DETECTION;
}
@Override
public Integer getPriority() {
return ListenerPriority.MEDIUM;
}
}

View File

@@ -0,0 +1,48 @@
package dev.sheldan.abstracto.utility.listener.repost;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.config.ListenerPriority;
import dev.sheldan.abstracto.core.listener.MessageReceivedListener;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.service.RepostCheckChannelService;
import dev.sheldan.abstracto.utility.service.RepostService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.EmbedType;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
@Component
@Slf4j
public class RepostMessageReceivedListener implements MessageReceivedListener {
@Autowired
private RepostCheckChannelService repostCheckChannelService;
@Autowired
private RepostService repostService;
@Override
public void execute(Message message) {
if(repostCheckChannelService.duplicateCheckEnabledForChannel(message.getTextChannel())) {
repostService.processMessageAttachmentRepostCheck(message);
List<MessageEmbed> imageEmbeds = message.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
repostService.processMessageEmbedsRepostCheck(imageEmbeds, message);
}
}
@Override
public FeatureEnum getFeature() {
return UtilityFeature.REPOST_DETECTION;
}
@Override
public Integer getPriority() {
return ListenerPriority.MEDIUM;
}
}

View File

@@ -0,0 +1,22 @@
package dev.sheldan.abstracto.utility.repository;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.utility.models.database.PostedImage;
import dev.sheldan.abstracto.utility.models.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.utility.repository;
import dev.sheldan.abstracto.utility.models.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.utility.repository;
import dev.sheldan.abstracto.utility.models.database.Repost;
import dev.sheldan.abstracto.utility.models.database.embed.RepostIdentifier;
import dev.sheldan.abstracto.utility.models.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

@@ -37,6 +37,7 @@ public class StarStatsUserConverter {
.builder()
.starCount(starStatsUserResult.getStarCount())
.member(member)
// TODO properly load this instance instead of just building one
.user(AUser.builder().id(starStatsUserResult.getUserId()).build())
.build()
);

View File

@@ -0,0 +1,30 @@
package dev.sheldan.abstracto.utility.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.utility.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.utility.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.utility.models.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.utility.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.utility.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,235 @@
package dev.sheldan.abstracto.utility.service;
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.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.service.HashService;
import dev.sheldan.abstracto.core.service.HttpService;
import dev.sheldan.abstracto.core.service.MessageService;
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.FileUtils;
import dev.sheldan.abstracto.utility.config.features.RepostDetectionFeatureMode;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.converter.RepostLeaderBoardConverter;
import dev.sheldan.abstracto.utility.models.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.utility.models.database.PostedImage;
import dev.sheldan.abstracto.utility.models.database.Repost;
import dev.sheldan.abstracto.utility.models.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.utility.service.management.PostedImageManagement;
import dev.sheldan.abstracto.utility.service.management.RepostManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.*;
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 FileUtils fileUtils;
@Autowired
private PostedImageManagement postedImageManagement;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private MessageService messageService;
@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(Message message, MessageEmbed messageEmbed, Integer index) {
return getRepostFor(message, messageEmbed, index).isPresent();
}
@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();
}
return checkForDuplicates(message, EMBEDDED_LINK_POSITION_START_INDEX + embedIndex, urlToUse);
}
private Optional<PostedImage> checkForDuplicates(Message message, Integer index, String fileUrl) {
String fileHash = calculateHashForPost(fileUrl, message.getGuild().getIdLong());
AServer aServer = serverManagementService.loadServer(message.getGuild().getIdLong());
Optional<PostedImage> potentialRepost = postedImageManagement.getPostWithHash(fileHash, aServer);
if(potentialRepost.isPresent()) {
PostedImage existingRepost = potentialRepost.get();
return existingRepost.getPostId().getMessageId() != message.getIdLong() ? Optional.of(existingRepost) : Optional.empty();
} else {
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(message.getMember());
AServerAChannelAUser cause = AServerAChannelAUser
.builder()
.aUserInAServer(aUserInAServer)
.channel(channelManagementService.loadChannel(message.getTextChannel().getIdLong()))
.guild(aServer)
.user(aUserInAServer.getUserReference())
.build();
postedImageManagement.createPost(cause, message, fileHash, index);
return Optional.empty();
}
}
@Override
public boolean isRepost(Message message, Message.Attachment attachment, Integer index) {
return getRepostFor(message, attachment, index).isPresent();
}
@Override
public Optional<PostedImage> getRepostFor(Message message, Message.Attachment attachment, Integer index) {
return checkForDuplicates(message, index, attachment.getProxyUrl());
}
@Override
public String calculateHashForPost(String url, Long serverId) {
File downloadedFile = null;
try {
if(featureModeService.featureModeActive(UtilityFeature.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 {
fileUtils.safeDelete(downloadedFile);
} catch (IOException e) {
log.error("Failed to delete downloaded repost check file.", e);
}
}
}
return null;
}
@Override
public void processMessageAttachmentRepostCheck(Message message) {
boolean canThereBeMultipleReposts = message.getAttachments().size() > 1;
for (int imageIndex = 0; imageIndex < message.getAttachments().size(); imageIndex++) {
executeRepostCheckForAttachment(message, message.getAttachments().get(imageIndex), imageIndex, canThereBeMultipleReposts);
}
}
private void executeRepostCheckForAttachment(Message message, Message.Attachment attachment, Integer index, boolean moreRepostsPossible) {
Optional<PostedImage> originalPostOptional = getRepostFor(message, attachment, index);
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(message, index, moreRepostsPossible, postedImage));
}
private void markMessageAndPersist(Message message, Integer index, boolean moreRepostsPossible, PostedImage originalPost) {
log.info("Detected repost in message embed {} of message {} in channel {} in server {}.", index, message.getIdLong(), message.getTextChannel().getIdLong(), message.getGuild().getIdLong());
CompletableFuture<Void> markerFuture = messageService.addReactionToMessageWithFuture(REPOST_MARKER_EMOTE_KEY, message.getGuild().getIdLong(), message);
CompletableFuture<Void> counterFuture;
if (moreRepostsPossible) {
counterFuture = messageService.addDefaultReactionToMessageAsync(NUMBER_EMOJI.get(index), message);
} else {
counterFuture = CompletableFuture.completedFuture(null);
}
Long messageId = originalPost.getPostId().getMessageId();
Integer position = originalPost.getPostId().getPosition();
Long serverId = message.getGuild().getIdLong();
Long userId = message.getAuthor().getIdLong();
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.loadUser(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<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(Message message, MessageEmbed messageEmbed, Integer index, boolean moreRepostsPossible) {
Optional<PostedImage> originalPostOptional = getRepostFor(message, messageEmbed, index);
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(message, index, moreRepostsPossible, postedImage));
}
}

View File

@@ -0,0 +1,86 @@
package dev.sheldan.abstracto.utility.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.utility.exception.PostedImageNotFoundException;
import dev.sheldan.abstracto.utility.models.database.PostedImage;
import dev.sheldan.abstracto.utility.models.database.embed.PostIdentifier;
import dev.sheldan.abstracto.utility.repository.PostedImageRepository;
import dev.sheldan.abstracto.utility.service.RepostServiceBean;
import net.dv8tion.jda.api.entities.Message;
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, Message source, String hash, Integer index) {
PostedImage post = PostedImage
.builder()
.imageHash(hash)
.postId(new PostIdentifier(source.getIdLong(), 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.utility.service.management;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.utility.exception.RepostCheckChannelGroupNotFoundException;
import dev.sheldan.abstracto.utility.models.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.utility.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.utility.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.utility.exception.RepostNotFoundException;
import dev.sheldan.abstracto.utility.models.database.PostedImage;
import dev.sheldan.abstracto.utility.models.database.Repost;
import dev.sheldan.abstracto.utility.models.database.embed.RepostIdentifier;
import dev.sheldan.abstracto.utility.models.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.utility.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,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

@@ -7,10 +7,12 @@
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="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
<property name="repostDetectionModule" value="(SELECT id FROM module WHERE name = 'repostDetection')"/>
<property name="remindFeature" value="(SELECT id FROM feature WHERE key = 'remind')"/>
<property name="starboardFeature" value="(SELECT id FROM feature WHERE key = 'starboard')"/>
<property name="suggestionFeature" value="(SELECT id FROM feature WHERE key = 'suggestion')"/>
<property name="utilityFeature" value="(SELECT id FROM feature WHERE key = 'utility')"/>
<property name="repostDetectionFeature" value="(SELECT id FROM feature WHERE key = 'repostDetection')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="utility_remind-commands">
@@ -87,6 +89,43 @@
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
<changeSet author="Sheldan" id="utility_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="${remindFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -13,4 +13,6 @@
<include file="default_posttarget.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="reminder_job.xml" relativeToChangelogFile="true"/>
<include file="default_feature_mode.xml" relativeToChangelogFile="true"/>
<include file="channel_group_types.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -63,5 +63,10 @@
<column name="name" value="🗑"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_emote">
<column name="emote_key" value="repostMarker"/>
<column name="name" value="♻️"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -11,6 +11,7 @@
<property name="suggestionFeature" value="(SELECT id FROM feature WHERE key = 'suggestion')"/>
<property name="utilityFeature" value="(SELECT id FROM feature WHERE key = 'utility')"/>
<property name="linkEmbedFeature" value="(SELECT id FROM feature WHERE key = 'link_embeds')"/>
<property name="repostDetectionFeature" value="(SELECT id FROM feature WHERE key = 'repostDetection')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="utility_default_feature_flag-insertion">
<insert tableName="default_feature_flag">
@@ -38,5 +39,10 @@
<column name="feature_id" valueComputed="${linkEmbedFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_flag">
<column name="enabled" value="false"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,25 @@
<?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="repostDetectionFeature" value="(SELECT id FROM feature WHERE key = 'repostDetection')"/>
<property name="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="utilities_default_feature_mode-insertion">
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="download"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="default_feature_mode">
<column name="enabled" value="true"/>
<column name="mode" value="leaderboard"/>
<column name="feature_id" valueComputed="${repostDetectionFeature}" />
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -28,5 +28,9 @@
<column name="key" value="link_embeds"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="feature">
<column name="key" value="repostDetection"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,16 @@
<?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="today" value="(SELECT NOW())"/>
<changeSet author="Sheldan" id="utility-module-insertion">
<insert tableName="module">
<column name="name" value="repostDetection"/>
<column name="created" valueComputed="${today}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,46 @@
<?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" />
<column name="position" type="INTEGER" />
<column name="posting_user_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"/>
</createTable>
<addPrimaryKey columnNames="message_id, position" tableName="posted_image" constraintName="pk_posted_image" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="posted_image-fk_posted_image_user">
<addForeignKeyConstraint baseColumnNames="posting_user_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"/>
</changeSet>
<changeSet author="Sheldan" id="posted_image-fk_posted_image_channel">
<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"/>
</changeSet>
<changeSet author="Sheldan" id="posted_image-fk_posted_image_server">
<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"/>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,44 @@
<?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" />
<column name="position" type="INTEGER" />
<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"/>
<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"/>
</changeSet>
<changeSet author="Sheldan" id="repost-fk_repost_server">
<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"/>
</changeSet>
<changeSet author="Sheldan" id="repost-fk_repost_posted_image">
<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"/>
</changeSet>
<changeSet author="Sheldan" id="repost-fk_repost_user_in_server">
<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"/>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,23 @@
<?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" />
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="enabled" type="BOOLEAN"/>
</createTable>
</changeSet>
<changeSet author="Sheldan" id="repost_check_channel_group-fk_repost_check_channel_group_group">
<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"/>
</changeSet>
</databaseChangeLog>

View File

@@ -1,42 +0,0 @@
<?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="starboard-table">
<createTable tableName="starboard_post">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="starboard_post_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="ignored" type="BOOLEAN"/>
<column name="post_message_id" type="BIGINT"/>
<column name="starboard_message_id" type="BIGINT"/>
<column name="starred_date" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="poster" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="source_channel_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="channel_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<changeSet author="Sheldan" id="starboard-fk_starboard_post_poster">
<addForeignKeyConstraint baseColumnNames="poster" baseTableName="starboard_post" constraintName="fk_starboard_post_poster" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="starboard-fk_starboard_post_channel">
<addForeignKeyConstraint baseColumnNames="channel_id" baseTableName="starboard_post" constraintName="fk_starboard_post_channel" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="channel" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="starboard-fk_starboard_post_source_channel">
<addForeignKeyConstraint baseColumnNames="source_channel_id" baseTableName="starboard_post" constraintName="fk_starboard_post_source_channel" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="channel" validate="true"/>
</changeSet>
</databaseChangeLog>

View File

@@ -6,23 +6,37 @@
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="starboard_post_reaction-table">
<createTable tableName="starboard_post_reaction">
<changeSet author="Sheldan" id="starboard-table">
<createTable tableName="starboard_post">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="starboard_post_reaction_pkey"/>
<constraints nullable="false" primaryKey="true" primaryKeyName="starboard_post_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="reactor_id" type="BIGINT">
<column name="ignored" type="BOOLEAN"/>
<column name="post_message_id" type="BIGINT"/>
<column name="starboard_message_id" type="BIGINT"/>
<column name="starred_date" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="poster" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="source_channel_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="channel_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="post_id" type="BIGINT"/>
</createTable>
</changeSet>
<changeSet author="Sheldan" id="starboard_post_reaction-fk_starboard_post_reaction_reactor">
<addForeignKeyConstraint baseColumnNames="reactor_id" baseTableName="starboard_post_reaction" constraintName="fk_starboard_post_reaction_reactor" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
<changeSet author="Sheldan" id="starboard-fk_starboard_post_poster">
<addForeignKeyConstraint baseColumnNames="poster" baseTableName="starboard_post" constraintName="fk_starboard_post_poster" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="starboard_post_reaction-fk_starboard_post_reaction_post">
<addForeignKeyConstraint baseColumnNames="post_id" baseTableName="starboard_post_reaction" constraintName="fk_starboard_post_reaction_post" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="starboard_post" validate="true"/>
<changeSet author="Sheldan" id="starboard-fk_starboard_post_channel">
<addForeignKeyConstraint baseColumnNames="channel_id" baseTableName="starboard_post" constraintName="fk_starboard_post_channel" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="channel" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="starboard-fk_starboard_post_source_channel">
<addForeignKeyConstraint baseColumnNames="source_channel_id" baseTableName="starboard_post" constraintName="fk_starboard_post_source_channel" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="channel" validate="true"/>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,28 @@
<?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="starboard_post_reaction-table">
<createTable tableName="starboard_post_reaction">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="starboard_post_reaction_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="reactor_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="post_id" type="BIGINT"/>
</createTable>
</changeSet>
<changeSet author="Sheldan" id="starboard_post_reaction-fk_starboard_post_reaction_reactor">
<addForeignKeyConstraint baseColumnNames="reactor_id" baseTableName="starboard_post_reaction" constraintName="fk_starboard_post_reaction_reactor" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
</changeSet>
<changeSet author="Sheldan" id="starboard_post_reaction-fk_starboard_post_reaction_post">
<addForeignKeyConstraint baseColumnNames="post_id" baseTableName="starboard_post_reaction" constraintName="fk_starboard_post_reaction_post" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="starboard_post" validate="true"/>
</changeSet>
</databaseChangeLog>

View File

@@ -8,7 +8,10 @@
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="embedded_message.xml" relativeToChangelogFile="true"/>
<include file="reminder.xml" relativeToChangelogFile="true"/>
<include file="starboard.xml" relativeToChangelogFile="true"/>
<include file="starboard_post.xml" relativeToChangelogFile="true"/>
<include file="starboard_post_reaction.xml" relativeToChangelogFile="true"/>
<include file="suggestion.xml" relativeToChangelogFile="true"/>
<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

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.utility.commands;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
@@ -31,11 +30,6 @@ public class ShowAvatarTest {
@Captor
private ArgumentCaptor<ShowAvatarModel> argumentCaptor;
@Test(expected = IncorrectParameterTypeException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test
public void executeWithoutParameter() {
CommandContext noParameters = CommandTestUtilities.getNoParameters();

View File

@@ -1,7 +1,5 @@
package dev.sheldan.abstracto.utility.commands;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
@@ -32,16 +30,6 @@ public class ShowEmoteTest {
@Captor
private ArgumentCaptor<ShowEmoteLog> emoteLogArgumentCaptor;
@Test(expected = IncorrectParameterTypeException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test(expected = InsufficientParametersException.class)
public void testTooLittleParameters() {
CommandTestUtilities.executeNoParametersTestAsync(testUnit);
}
@Test
public void executeCommandWithOneEmote() {
Emote emote = Mockito.mock(Emote.class);

View File

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.utility.commands;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.BotService;
@@ -39,11 +38,6 @@ public class UserInfoTest {
@Captor
private ArgumentCaptor<UserInfoModel> modelArgumentCaptor;
@Test(expected = IncorrectParameterTypeException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test
public void executeWithoutParameterAndLoadedMember() {
CommandContext noParameters = CommandTestUtilities.getNoParameters();

View File

@@ -1,7 +1,5 @@
package dev.sheldan.abstracto.utility.commands.remind;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
@@ -39,22 +37,6 @@ public class RemindTest {
@Captor
private ArgumentCaptor<ReminderModel> captor;
@Test(expected = InsufficientParametersException.class)
public void testTooLittleParameters() {
CommandTestUtilities.executeNoParametersTestAsync(testUnit);
}
@Test(expected = IncorrectParameterTypeException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test(expected = InsufficientParametersException.class)
public void testOnlyRemindDateParameter() {
CommandContext durationParameter = CommandTestUtilities.getWithParameters(Arrays.asList(Duration.ofDays(4)));
testUnit.executeAsync(durationParameter);
}
@Test
public void executeCommand() {
String reminderText = "text";

View File

@@ -1,7 +1,5 @@
package dev.sheldan.abstracto.utility.commands.remind;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
@@ -26,16 +24,6 @@ public class UnRemindTest {
@Mock
private ReminderService reminderService;
@Test(expected = IncorrectParameterTypeException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTest(testUnit);
}
@Test(expected = InsufficientParametersException.class)
public void testTooLittleParameters() {
CommandTestUtilities.executeNoParametersTest(testUnit);
}
@Test
public void testExecuteCommand() {
Long reminderId = 6L;

View File

@@ -0,0 +1,61 @@
package dev.sheldan.abstracto.utility.commands.repost;
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.utility.service.RepostCheckChannelService;
import dev.sheldan.abstracto.utility.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.utility.commands.repost;
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.utility.service.RepostCheckChannelService;
import dev.sheldan.abstracto.utility.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.utility.commands.repost;
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.utility.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.loadUser(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.utility.commands.repost;
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.utility.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.loadUser(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,109 @@
package dev.sheldan.abstracto.utility.commands.repost;
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.templating.service.TemplateService;
import dev.sheldan.abstracto.utility.converter.RepostLeaderBoardConverter;
import dev.sheldan.abstracto.utility.models.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.utility.models.RepostLeaderboardModel;
import dev.sheldan.abstracto.utility.models.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.utility.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 dev.sheldan.abstracto.utility.commands.repost.RepostLeaderboard.REPOST_LEADERBOARD_RESPONSE_TEMPLATE_KEY;
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.loadUser(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)).sendEmbedTemplateInChannel(eq(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,62 @@
package dev.sheldan.abstracto.utility.commands.repost;
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.utility.converter.RepostCheckChannelModelConverter;
import dev.sheldan.abstracto.utility.models.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.utility.models.template.commands.RepostCheckChannelsModel;
import dev.sheldan.abstracto.utility.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 dev.sheldan.abstracto.utility.commands.repost.ShowRepostCheckChannels.SHOW_REPOST_CHECK_CHANNELS_RESPONSE_TEMPLATE_KEY;
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)).sendEmbedTemplateInChannel(SHOW_REPOST_CHECK_CHANNELS_RESPONSE_TEMPLATE_KEY, model, noParameters.getChannel());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -1,7 +1,5 @@
package dev.sheldan.abstracto.utility.commands.suggest;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
@@ -31,16 +29,6 @@ public class AcceptTest {
@Mock
private SuggestionService suggestionService;
@Test(expected = InsufficientParametersException.class)
public void testTooLittleParameters() {
CommandTestUtilities.executeNoParametersTestAsync(testUnit);
}
@Test(expected = IncorrectParameterTypeException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test
public void testExecuteCommand() throws ExecutionException, InterruptedException {
String text = "text";

View File

@@ -1,7 +1,5 @@
package dev.sheldan.abstracto.utility.commands.suggest;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
@@ -31,15 +29,6 @@ public class RejectTest {
@Mock
private SuggestionService suggestionService;
@Test(expected = InsufficientParametersException.class)
public void testTooLittleParameters() {
CommandTestUtilities.executeNoParametersTestAsync(testUnit);
}
@Test(expected = IncorrectParameterTypeException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test
public void testExecuteCommand() throws ExecutionException, InterruptedException {
String text = "text";

View File

@@ -1,7 +1,5 @@
package dev.sheldan.abstracto.utility.commands.suggest;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
@@ -29,16 +27,6 @@ public class SuggestTest {
@Mock
private SuggestionService suggestionService;
@Test(expected = InsufficientParametersException.class)
public void testTooLittleParameters() {
CommandTestUtilities.executeNoParametersTestAsync(testUnit);
}
@Test(expected = IncorrectParameterTypeException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test
public void testExecuteCommand() throws ExecutionException, InterruptedException {
String text = "text";

View File

@@ -0,0 +1,83 @@
package dev.sheldan.abstracto.utility.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.BotService;
import dev.sheldan.abstracto.utility.models.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.utility.models.template.commands.RepostCheckChannelGroupDisplayModel;
import dev.sheldan.abstracto.utility.models.template.commands.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 BotService botService;
@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(botService.getTextChannelFromServerNullable(guild, channelId1)).thenReturn(textChannel);
Long channelId2 = 2L;
AChannel channel2 = Mockito.mock(AChannel.class);
when(channel2.getId()).thenReturn(channelId2);
when(botService.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.utility.converter;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.utility.models.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.utility.models.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 BotService botService;
@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.loadUser(secondUserInServerId)).thenReturn(secondAUserInAServer);
Member secondMember = Mockito.mock(Member.class);
when(botService.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.loadUser(USER_IN_SERVER_ID)).thenReturn(aUserInAServer);
when(botService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(member));
return result;
}
@Test
public void testLoadUserFromDatabase() {
when(userInServerManagementService.loadUser(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.utility.listener.repost;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
import dev.sheldan.abstracto.utility.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 dev.sheldan.abstracto.utility.service.RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE;
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(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.utility.listener.repost;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
import dev.sheldan.abstracto.utility.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 dev.sheldan.abstracto.utility.service.RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE;
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(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,141 @@
package dev.sheldan.abstracto.utility.listener.repost;
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
import dev.sheldan.abstracto.utility.service.RepostCheckChannelService;
import dev.sheldan.abstracto.utility.service.RepostService;
import dev.sheldan.abstracto.utility.service.management.PostedImageManagement;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.requests.RestAction;
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.function.Consumer;
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 GuildMessageEmbedEventModel model;
@Mock
private TextChannel textChannel;
@Mock
private Message message;
@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.getChannel()).thenReturn(textChannel);
when(repostCheckChannelService.duplicateCheckEnabledForChannel(textChannel)).thenReturn(false);
testUnit.execute(model);
verify(repostManagement, times(0)).messageEmbedsHaveBeenCovered(anyLong());
}
@Test
public void testExecuteEmbedsHaveBeenCovered() {
channelSetup();
setupMessageHasBeenCovered(true);
Guild guild = Mockito.mock(Guild.class);
when(guild.getIdLong()).thenReturn(SERVER_ID);
when(textChannel.getGuild()).thenReturn(guild);
testUnit.execute(model);
verify(repostService, times(0)).processMessageEmbedsRepostCheck(any(), any());
}
@Test
public void testExecuteNoEmbeds() {
channelSetup();
setupMessageHasBeenCovered(false);
RestAction messageRestAction = Mockito.mock(RestAction.class);
when(textChannel.retrieveMessageById(MESSAGE_ID)).thenReturn(messageRestAction);
testUnit.execute(model);
verify(repostService, times(0)).processMessageEmbedsRepostCheck(any(), any());
}
@Test
public void testExecuteOneImageEmbed() {
channelSetup();
setupMessageHasBeenCovered(false);
RestAction<Message> messageRestAction = Mockito.mock(RestAction.class);
MessageEmbed imageEmbed = Mockito.mock(MessageEmbed.class);
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
when(model.getEmbeds()).thenReturn(Arrays.asList(imageEmbed));
mockMessageConsumer(messageRestAction, message);
when(textChannel.retrieveMessageById(MESSAGE_ID)).thenReturn(messageRestAction);
testUnit.execute(model);
verifySingleEmbedProcessed(imageEmbed);
}
@Test
public void testExecuteMultipleEmbedsOneImage() {
channelSetup();
setupMessageHasBeenCovered(false);
RestAction<Message> messageRestAction = Mockito.mock(RestAction.class);
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));
mockMessageConsumer(messageRestAction, message);
when(textChannel.retrieveMessageById(MESSAGE_ID)).thenReturn(messageRestAction);
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 mockMessageConsumer(RestAction<Message> action, Message message) {
doAnswer(invocationOnMock -> {
Object consumerObj = invocationOnMock.getArguments()[0];
if(consumerObj instanceof Consumer) {
Consumer<Message> consumer = (Consumer<Message>) consumerObj;
consumer.accept(message);
}
return null;
}).when(action).queue(any(Consumer.class));
}
private void channelSetup() {
when(model.getChannel()).thenReturn(textChannel);
when(textChannel.getIdLong()).thenReturn(CHANNEL_ID);
when(repostCheckChannelService.duplicateCheckEnabledForChannel(textChannel)).thenReturn(true);
}
}

View File

@@ -0,0 +1,92 @@
package dev.sheldan.abstracto.utility.listener.repost;
import dev.sheldan.abstracto.utility.service.RepostCheckChannelService;
import dev.sheldan.abstracto.utility.service.RepostService;
import net.dv8tion.jda.api.entities.EmbedType;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.TextChannel;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
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 RepostService repostService;
@Mock
private Message message;
@Mock
private TextChannel textChannel;
@Captor
private ArgumentCaptor<List<MessageEmbed>> embedListCaptor;
@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);
MessageEmbed imageEmbed = Mockito.mock(MessageEmbed.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);
MessageEmbed imageEmbed = Mockito.mock(MessageEmbed.class);
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
MessageEmbed nonImageEmbed = Mockito.mock(MessageEmbed.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.getTextChannel()).thenReturn(textChannel);
when(repostCheckChannelService.duplicateCheckEnabledForChannel(textChannel)).thenReturn(b);
}
private void verifySingleEmbed(MessageEmbed imageEmbed) {
verify(repostService, times(1)).processMessageAttachmentRepostCheck(message);
verify(repostService, times(1)).processMessageEmbedsRepostCheck(embedListCaptor.capture(), eq(message));
List<MessageEmbed> processedEmbeds = embedListCaptor.getValue();
Assert.assertEquals(1, processedEmbeds.size());
Assert.assertEquals(imageEmbed, processedEmbeds.get(0));
}
}

View File

@@ -0,0 +1,57 @@
package dev.sheldan.abstracto.utility.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.utility.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,257 @@
package dev.sheldan.abstracto.utility.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.utility.exception.RepostCheckChannelGroupNotFoundException;
import dev.sheldan.abstracto.utility.models.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.utility.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 dev.sheldan.abstracto.utility.service.RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE;
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, 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, 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, REPOST_CHECK_CHANNEL_GROUP_TYPE)).thenReturn(Arrays.asList(firstGroup, secondGroup));
}
@Test
public void testGetRepostCheckChannelGroupsForServerNoChannelGroups() {
when(channelGroupManagementService.findAllInServerWithType(SERVER_ID, 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, 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, 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, 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, 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,411 @@
package dev.sheldan.abstracto.utility.service;
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.AUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.FeatureModeService;
import dev.sheldan.abstracto.core.service.HashService;
import dev.sheldan.abstracto.core.service.HttpService;
import dev.sheldan.abstracto.core.service.MessageService;
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.FileUtils;
import dev.sheldan.abstracto.utility.config.features.RepostDetectionFeatureMode;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
import dev.sheldan.abstracto.utility.converter.RepostLeaderBoardConverter;
import dev.sheldan.abstracto.utility.models.RepostLeaderboardEntryModel;
import dev.sheldan.abstracto.utility.models.database.PostedImage;
import dev.sheldan.abstracto.utility.models.database.Repost;
import dev.sheldan.abstracto.utility.models.database.embed.PostIdentifier;
import dev.sheldan.abstracto.utility.models.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.utility.service.management.PostedImageManagement;
import dev.sheldan.abstracto.utility.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.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.utility.service.RepostServiceBean.*;
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 FileUtils fileUtils;
@Mock
private PostedImageManagement postedImageManagement;
@Mock
private ServerManagementService serverManagementService;
@Mock
private ChannelManagementService channelManagementService;
@Mock
private UserInServerManagementService userInServerManagementService;
@Mock
private MessageService messageService;
@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 Message message;
@Mock
private TextChannel textChannel;
@Mock
private Member member;
@Mock
private User jdaUser;
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, 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.loadUser(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.loadUser(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(UtilityFeature.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(fileUtils, times(1)).safeDelete(file);
}
@Test
public void testCalculateHashForPostWithImageException() throws IOException {
File file = Mockito.mock(File.class);
when(featureModeService.featureModeActive(UtilityFeature.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(fileUtils, times(1)).safeDelete(file);
}
@Test
public void testCalculateHashForPostWithUrl() {
when(featureModeService.featureModeActive(UtilityFeature.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(message.getAttachments()).thenReturn(new ArrayList<>());
testUnit.processMessageAttachmentRepostCheck(message);
verify(message, times(0)).getTextChannel();
}
@Test
public void testProcessMessageAttachmentRepostCheckOneAttachmentNotExistingPost() {
generalSetupForRepostTest();
when(message.getMember()).thenReturn(member);
Message.Attachment attachment = Mockito.mock(Message.Attachment.class);
when(message.getAttachments()).thenReturn(Arrays.asList(attachment));
when(attachment.getProxyUrl()).thenReturn(URL);
setupSingleRepost();
testUnit.processMessageAttachmentRepostCheck(message);
verify(postedImageManagement, times(1)).createPost(any(AServerAChannelAUser.class), eq(message), eq(HASH), eq(0));
verify(messageService, times(0)).addReactionToMessageWithFuture(REPOST_MARKER_EMOTE_KEY, SERVER_ID, message);
}
@Test
public void testProcessMessageAttachmentRepostCheckOneAttachmentIsRepost() {
generalSetupForRepostTest();
setupForRepostCreation();
Message.Attachment attachment = Mockito.mock(Message.Attachment.class);
when(message.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(messageService.addReactionToMessageWithFuture(REPOST_MARKER_EMOTE_KEY, SERVER_ID, message)).thenReturn(CompletableFuture.completedFuture(null));
testUnit.processMessageAttachmentRepostCheck(message);
verify(messageService, times(0)).addDefaultReactionToMessageAsync(anyString(), eq(message));
verify(self, times(1)).persistRepost(originalPostMessageId, POSITION, SERVER_ID, USER_ID);
}
@Test
public void testProcessMessageAttachmentRepostCheckTwoAttachmentsOneIsRepost() {
generalSetupForRepostTest();
setupForRepostCreation();
when(message.getMember()).thenReturn(member);
Message.Attachment attachment = Mockito.mock(Message.Attachment.class);
Message.Attachment attachment2 = Mockito.mock(Message.Attachment.class);
when(message.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(messageService.addReactionToMessageWithFuture(REPOST_MARKER_EMOTE_KEY, SERVER_ID, message)).thenReturn(CompletableFuture.completedFuture(null));
when(messageService.addDefaultReactionToMessageAsync(anyString(), eq(message))).thenReturn(CompletableFuture.completedFuture(null));
testUnit.processMessageAttachmentRepostCheck(message);
verify(postedImageManagement, times(1)).createPost(any(AServerAChannelAUser.class), eq(message), eq(HASH), eq(0));
verify(self, times(1)).persistRepost(originalPostMessageId, POSITION, SERVER_ID, USER_ID);
}
private void setupForRepostCreation() {
when(message.getIdLong()).thenReturn(MESSAGE_ID);
when(message.getAuthor()).thenReturn(jdaUser);
when(jdaUser.getIdLong()).thenReturn(USER_ID);
}
private void generalSetupForRepostTest() {
when(message.getTextChannel()).thenReturn(textChannel);
when(textChannel.getIdLong()).thenReturn(CHANNEL_ID);
when(message.getGuild()).thenReturn(guild);
when(guild.getIdLong()).thenReturn(SERVER_ID);
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
}
private void setupSingleRepost() {
setupSingleHash(null);
when(userInServerManagementService.loadUser(member)).thenReturn(userInAServer);
when(userInAServer.getUserReference()).thenReturn(user);
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(channel);
}
private void setupSingleHash(PostedImage postedImage) {
when(featureModeService.featureModeActive(UtilityFeature.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();
MessageEmbed firstEmbed = Mockito.mock(MessageEmbed.class);
MessageEmbed.Thumbnail thumbnail = Mockito.mock(MessageEmbed.Thumbnail.class);
when(thumbnail.getProxyUrl()).thenReturn(URL);
when(firstEmbed.getThumbnail()).thenReturn(thumbnail);
List<MessageEmbed> messageEmbeds = Arrays.asList(firstEmbed);
when(message.getMember()).thenReturn(member);
when(message.getAttachments()).thenReturn(new ArrayList<>());
setupSingleRepost();
testUnit.processMessageEmbedsRepostCheck(messageEmbeds, message);
verify(postedImageManagement, times(1)).createPost(any(AServerAChannelAUser.class), eq(message), eq(HASH), eq(EMBEDDED_LINK_POSITION_START_INDEX));
verify(messageService, times(0)).addReactionToMessageWithFuture(REPOST_MARKER_EMOTE_KEY, SERVER_ID, message);
}
@Test
public void testProcessMessageEmbedsRepostCheckWithNotRepostedEmbedImageNoAttachments() {
generalSetupForRepostTest();
MessageEmbed firstEmbed = Mockito.mock(MessageEmbed.class);
MessageEmbed.ImageInfo thumbnail = Mockito.mock(MessageEmbed.ImageInfo.class);
when(thumbnail.getProxyUrl()).thenReturn(URL);
when(firstEmbed.getImage()).thenReturn(thumbnail);
List<MessageEmbed> messageEmbeds = Arrays.asList(firstEmbed);
when(message.getMember()).thenReturn(member);
when(message.getAttachments()).thenReturn(new ArrayList<>());
setupSingleRepost();
testUnit.processMessageEmbedsRepostCheck(messageEmbeds, message);
verify(postedImageManagement, times(1)).createPost(any(AServerAChannelAUser.class), eq(message), eq(HASH), eq(EMBEDDED_LINK_POSITION_START_INDEX));
verify(messageService, times(0)).addReactionToMessageWithFuture(REPOST_MARKER_EMOTE_KEY, SERVER_ID, message);
}
@Test
public void testProcessMessageEmbedsRepostCheckWithRepostedThumbnailNoAttachments() {
generalSetupForRepostTest();
setupForRepostCreation();
MessageEmbed firstEmbed = Mockito.mock(MessageEmbed.class);
MessageEmbed.Thumbnail thumbnail = Mockito.mock(MessageEmbed.Thumbnail.class);
when(thumbnail.getProxyUrl()).thenReturn(URL);
when(firstEmbed.getThumbnail()).thenReturn(thumbnail);
List<MessageEmbed> messageEmbeds = Arrays.asList(firstEmbed);
when(message.getAttachments()).thenReturn(new ArrayList<>());
setupSingleHash(postedImage);
Long originalPostMessageId = MESSAGE_ID + 1;
when(postedImage.getPostId()).thenReturn(new PostIdentifier(originalPostMessageId, POSITION));
when(messageService.addReactionToMessageWithFuture(REPOST_MARKER_EMOTE_KEY, SERVER_ID, message)).thenReturn(CompletableFuture.completedFuture(null));
testUnit.processMessageEmbedsRepostCheck(messageEmbeds, message);
verify(self, times(1)).persistRepost(originalPostMessageId, POSITION, SERVER_ID, USER_ID);
}
@Test
public void testIsRepostEmptyEmbedMessage() {
MessageEmbed messageEmbed = Mockito.mock(MessageEmbed.class);
Optional<PostedImage> emptyOptional = testUnit.getRepostFor(message, 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) {
MessageEmbed messageEmbed = setupSimpleRepostCheck(originalPostMessageId);
Optional<PostedImage> optional = testUnit.getRepostFor(message, messageEmbed, POSITION);
Assert.assertEquals(shouldBePresent, optional.isPresent());
if(shouldBePresent && optional.isPresent()) {
Assert.assertEquals(postedImage, optional.get());
}
}
private MessageEmbed setupSimpleRepostCheck(Long originalPostMessageId) {
generalSetupForRepostTest();
setupForRepostCreation();
setupSingleHash(postedImage);
when(postedImage.getPostId()).thenReturn(new PostIdentifier(originalPostMessageId, POSITION));
MessageEmbed messageEmbed = Mockito.mock(MessageEmbed.class);
MessageEmbed.Thumbnail thumbnail = Mockito.mock(MessageEmbed.Thumbnail.class);
when(thumbnail.getProxyUrl()).thenReturn(URL);
when(messageEmbed.getThumbnail()).thenReturn(thumbnail);
return messageEmbed;
}
@Test
public void testIsRepostWithRepost() {
MessageEmbed messageEmbed = setupSimpleRepostCheck(MESSAGE_ID + 1);
Assert.assertTrue(testUnit.isRepost(message, messageEmbed, POSITION));
}
@Test
public void testIsRepostWithSameMessage() {
MessageEmbed messageEmbed = setupSimpleRepostCheck(MESSAGE_ID);
Assert.assertFalse(testUnit.isRepost(message, messageEmbed, POSITION));
}
@Test
public void testIsRepostWithRepostInAttachment() {
generalSetupForRepostTest();
setupSingleRepost();
setupSingleHash(postedImage);
when(postedImage.getPostId()).thenReturn(new PostIdentifier(MESSAGE_ID + 1, POSITION));
Message.Attachment attachment = Mockito.mock(Message.Attachment.class);
when(attachment.getProxyUrl()).thenReturn(URL);
Assert.assertTrue(testUnit.isRepost(message, attachment, POSITION));
}
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
import dev.sheldan.abstracto.core.models.ServerSpecificId;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
@@ -139,7 +139,7 @@ public class SuggestionServiceBeanTest {
executeAcceptWithMember(null);
}
@Test(expected = ChannelNotFoundException.class)
@Test(expected = ChannelNotInGuildException.class)
public void testAcceptSuggestionInNoTextChannel() {
setupForNoTextChannel();
testUnit.acceptSuggestion(SUGGESTION_ID, CLOSING_TEXT, SuggestionLog.builder().build());
@@ -157,7 +157,7 @@ public class SuggestionServiceBeanTest {
.build();
when(server.getId()).thenReturn(SERVER_ID);
when(channel.getId()).thenReturn(CHANNEL_ID);
when(botService.getTextChannelFromServer(SERVER_ID, CHANNEL_ID)).thenThrow(new ChannelNotFoundException(CHANNEL_ID));
when(botService.getTextChannelFromServer(SERVER_ID, CHANNEL_ID)).thenThrow(new ChannelNotInGuildException(CHANNEL_ID));
when(suggestionManagementService.getSuggestion(SUGGESTION_ID)).thenReturn(Optional.of(suggestionToAccept));
}
@@ -199,7 +199,7 @@ public class SuggestionServiceBeanTest {
executeRejectWithMember(null);
}
@Test(expected = ChannelNotFoundException.class)
@Test(expected = ChannelNotInGuildException.class)
public void testRejectSuggestionInNoTextChannel() {
setupForNoTextChannel();
testUnit.rejectSuggestion(SUGGESTION_ID, CLOSING_TEXT, SuggestionLog.builder().build());

View File

@@ -0,0 +1,148 @@
package dev.sheldan.abstracto.utility.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.utility.exception.PostedImageNotFoundException;
import dev.sheldan.abstracto.utility.models.database.PostedImage;
import dev.sheldan.abstracto.utility.models.database.embed.PostIdentifier;
import dev.sheldan.abstracto.utility.repository.PostedImageRepository;
import dev.sheldan.abstracto.utility.service.RepostServiceBean;
import net.dv8tion.jda.api.entities.Message;
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);
Message message = Mockito.mock(Message.class);
when(message.getIdLong()).thenReturn(MESSAGE_ID);
when(serverAChannelAUser.getGuild()).thenReturn(server);
when(serverAChannelAUser.getChannel()).thenReturn(channel);
when(serverAChannelAUser.getAUserInAServer()).thenReturn(aUserInAServer);
PostedImage createdPost = testUnit.createPost(serverAChannelAUser, message, 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.utility.service.management;
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
import dev.sheldan.abstracto.utility.exception.RepostCheckChannelGroupNotFoundException;
import dev.sheldan.abstracto.utility.models.database.RepostCheckChannelGroup;
import dev.sheldan.abstracto.utility.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.utility.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.utility.exception.RepostNotFoundException;
import dev.sheldan.abstracto.utility.models.database.PostedImage;
import dev.sheldan.abstracto.utility.models.database.Repost;
import dev.sheldan.abstracto.utility.models.database.embed.PostIdentifier;
import dev.sheldan.abstracto.utility.models.database.embed.RepostIdentifier;
import dev.sheldan.abstracto.utility.models.database.result.RepostLeaderboardResult;
import dev.sheldan.abstracto.utility.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);
}
}