mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-16 04:21:49 +00:00
[AB-197] splitting utility maven module into separate maven modules
aligning some package names removing some unnecessary computed values from liquibase
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
|
||||
<id>liquibase</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<outputDirectory>.</outputDirectory>
|
||||
<directory>${project.basedir}/src/main/resources/migrations</directory>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
@@ -0,0 +1,67 @@
|
||||
package dev.sheldan.abstracto.repostdetection.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class DisableRepostCheck extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelService repostCheckChannelService;
|
||||
|
||||
@Autowired
|
||||
private ChannelGroupManagementService channelGroupManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
AChannelGroup fakeChannelGroup = (AChannelGroup) parameters.get(0);
|
||||
AServer actualServer = serverManagementService.loadServer(commandContext.getGuild().getIdLong());
|
||||
AChannelGroup actualChannelGroup = channelGroupManagementService.findByNameAndServerAndType(fakeChannelGroup.getGroupName(), actualServer, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
|
||||
repostCheckChannelService.setRepostCheckDisabledForChannelGroup(actualChannelGroup);
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter channelToSet = Parameter.builder().name("channelGroup").type(AChannelGroup.class).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(channelToSet);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("disableRepostCheck")
|
||||
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
|
||||
.templated(true)
|
||||
.async(false)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package dev.sheldan.abstracto.repostdetection.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class EnableRepostCheck extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelService repostCheckChannelService;
|
||||
|
||||
@Autowired
|
||||
private ChannelGroupManagementService channelGroupManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
AChannelGroup fakeChannelGroup = (AChannelGroup) parameters.get(0);
|
||||
AServer actualServer = serverManagementService.loadServer(commandContext.getGuild().getIdLong());
|
||||
AChannelGroup actualChannelGroup = channelGroupManagementService.findByNameAndServerAndType(fakeChannelGroup.getGroupName(), actualServer, RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
|
||||
repostCheckChannelService.setRepostCheckEnabledForChannelGroup(actualChannelGroup);
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter channelToSet = Parameter.builder().name("channelGroup").type(AChannelGroup.class).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(channelToSet);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("enableRepostCheck")
|
||||
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
|
||||
.templated(true)
|
||||
.async(false)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package dev.sheldan.abstracto.repostdetection.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.service.PostedImageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class PurgeImagePosts extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private PostedImageService postedImageService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
if(!parameters.isEmpty()) {
|
||||
AUserInAServer fakeUser = (AUserInAServer) parameters.get(0);
|
||||
AUserInAServer actualUser = userInServerManagementService.loadOrCreateUser(fakeUser.getUserInServerId());
|
||||
postedImageService.purgePostedImages(actualUser);
|
||||
} else {
|
||||
postedImageService.purgePostedImages(commandContext.getGuild());
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter channelToSet = Parameter.builder().name("member").type(AUserInAServer.class).templated(true).optional(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(channelToSet);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("purgeImagePosts")
|
||||
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
|
||||
.templated(true)
|
||||
.async(false)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package dev.sheldan.abstracto.repostdetection.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class PurgeReposts extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private RepostService repostService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
if(!parameters.isEmpty()) {
|
||||
AUserInAServer fakeUser = (AUserInAServer) parameters.get(0);
|
||||
AUserInAServer actualUser = userInServerManagementService.loadOrCreateUser(fakeUser.getUserInServerId());
|
||||
repostService.purgeReposts(actualUser);
|
||||
} else {
|
||||
repostService.purgeReposts(commandContext.getGuild());
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter channelToSet = Parameter.builder().name("member").type(AUserInAServer.class).templated(true).optional(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(channelToSet);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("purgeReposts")
|
||||
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
|
||||
.templated(true)
|
||||
.async(false)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package dev.sheldan.abstracto.repostdetection.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureMode;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.converter.RepostLeaderBoardConverter;
|
||||
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardEntryModel;
|
||||
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardModel;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class RepostLeaderboard extends AbstractConditionableCommand {
|
||||
|
||||
public static final String REPOST_LEADERBOARD_RESPONSE_TEMPLATE_KEY = "repostLeaderboard_response";
|
||||
@Autowired
|
||||
private RepostService repostService;
|
||||
|
||||
@Autowired
|
||||
private RepostManagementService repostManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private RepostLeaderBoardConverter converter;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
Integer page = !parameters.isEmpty() ? (Integer) parameters.get(0) : 1;
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
|
||||
List<RepostLeaderboardResult> topRepostingUsersOfServer = repostManagementService.findTopRepostingUsersOfServer(commandContext.getGuild().getIdLong(), page, 5);
|
||||
RepostLeaderboardResult resultOfUser = repostManagementService.getRepostRankOfUser(aUserInAServer);
|
||||
CompletableFuture<List<RepostLeaderboardEntryModel>> leaderBoardFuture = converter.fromLeaderBoardResults(topRepostingUsersOfServer);
|
||||
CompletableFuture<RepostLeaderboardEntryModel> userFuture = converter.convertSingleUser(resultOfUser);
|
||||
return CompletableFuture.allOf(leaderBoardFuture, userFuture).thenCompose(unused -> {
|
||||
List<RepostLeaderboardEntryModel> entries = leaderBoardFuture.join();
|
||||
RepostLeaderboardModel model = RepostLeaderboardModel
|
||||
.builder()
|
||||
.guild(commandContext.getGuild())
|
||||
.entries(entries)
|
||||
.userExecuting(userFuture.join())
|
||||
.member(commandContext.getAuthor())
|
||||
.build();
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(REPOST_LEADERBOARD_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()));
|
||||
}).thenApply(o -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter channelToSet = Parameter.builder().name("page").type(Integer.class).templated(true).optional(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(channelToSet);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("repostLeaderboard")
|
||||
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(RepostDetectionFeatureMode.LEADERBOARD);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package dev.sheldan.abstracto.repostdetection.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionModuleDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.converter.RepostCheckChannelModelConverter;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
|
||||
import dev.sheldan.abstracto.repostdetection.model.template.RepostCheckChannelsModel;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class ShowRepostCheckChannels extends AbstractConditionableCommand {
|
||||
|
||||
public static final String SHOW_REPOST_CHECK_CHANNELS_RESPONSE_TEMPLATE_KEY = "showRepostCheckChannels_response";
|
||||
@Autowired
|
||||
private RepostCheckChannelModelConverter converter;
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelService checkChannelService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<RepostCheckChannelGroup> channelGroups = checkChannelService.getChannelGroupsWithEnabledCheck(commandContext.getGuild().getIdLong());
|
||||
RepostCheckChannelsModel model = converter.fromRepostCheckChannelGroups(channelGroups, commandContext.getGuild());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(SHOW_REPOST_CHECK_CHANNELS_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("showRepostCheckChannels")
|
||||
.module(RepostDetectionModuleDefinition.REPOST_DETECTION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.abstracto.repostdetection.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:repost-detection-config.properties")
|
||||
public class RepostDetectionConfig {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package dev.sheldan.abstracto.repostdetection.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.FullChannel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
|
||||
import dev.sheldan.abstracto.repostdetection.model.template.RepostCheckChannelGroupDisplayModel;
|
||||
import dev.sheldan.abstracto.repostdetection.model.template.RepostCheckChannelsModel;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class RepostCheckChannelModelConverter {
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
public RepostCheckChannelsModel fromRepostCheckChannelGroups(List<RepostCheckChannelGroup> channelGroups, Guild guild) {
|
||||
List<RepostCheckChannelGroupDisplayModel> repostCheckChannelGroups = new ArrayList<>();
|
||||
channelGroups.forEach(repostCheckChannelGroup -> {
|
||||
List<FullChannel> fullChannels = repostCheckChannelGroup.getChannelGroup().getChannels().stream().map(channel ->
|
||||
FullChannel
|
||||
.builder()
|
||||
.channel(channel)
|
||||
.serverChannel(channelService.getTextChannelFromServerNullable(guild, channel.getId()))
|
||||
.build()
|
||||
).collect(Collectors.toList());
|
||||
repostCheckChannelGroups.add(
|
||||
RepostCheckChannelGroupDisplayModel
|
||||
.builder()
|
||||
.channelGroup(repostCheckChannelGroup)
|
||||
.channels(fullChannels)
|
||||
.build());
|
||||
});
|
||||
return RepostCheckChannelsModel.builder().repostCheckChannelGroups(repostCheckChannelGroups).build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package dev.sheldan.abstracto.repostdetection.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardEntryModel;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class RepostLeaderBoardConverter {
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private RepostLeaderBoardConverter self;
|
||||
|
||||
public CompletableFuture<List<RepostLeaderboardEntryModel>> fromLeaderBoardResults(List<RepostLeaderboardResult> results) {
|
||||
if(results.isEmpty()) {
|
||||
return CompletableFuture.completedFuture(new ArrayList<>());
|
||||
}
|
||||
List<CompletableFuture<RepostLeaderboardEntryModel>> modelFutures =
|
||||
results.stream().map(this::convertSingleUser).collect(Collectors.toList());
|
||||
return FutureUtils.toSingleFutureGeneric(modelFutures).thenApply(unused ->
|
||||
modelFutures.stream().map(CompletableFuture::join).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
public CompletableFuture<RepostLeaderboardEntryModel> convertSingleUser(RepostLeaderboardResult result) {
|
||||
AUserInAServer user = userInServerManagementService.loadOrCreateUser(result.getUserInServerId());
|
||||
Integer count = result.getRepostCount();
|
||||
Long userInServerId = result.getUserInServerId();
|
||||
Integer rank = result.getRank();
|
||||
return memberService.getMemberInServerAsync(user).thenApply(member ->
|
||||
self.loadUserFromDatabase(member, count, userInServerId, rank)
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public RepostLeaderboardEntryModel loadUserFromDatabase(Member member, Integer count, Long userInServerId, Integer rank) {
|
||||
return RepostLeaderboardEntryModel
|
||||
.builder()
|
||||
.member(member)
|
||||
.user(userInServerManagementService.loadOrCreateUser(userInServerId))
|
||||
.count(count)
|
||||
.rank(rank)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.ChannelGroupCreatedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class RepostCheckChannelGroupCreatedListener implements ChannelGroupCreatedListener {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
|
||||
|
||||
@Override
|
||||
public void channelGroupCreated(AChannelGroup channelGroup) {
|
||||
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
|
||||
checkChannelGroupManagement.createRepostCheckChannelGroup(channelGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.ChannelGroupDeletedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class RepostCheckChannelGroupDeletedListener implements ChannelGroupDeletedListener {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
|
||||
|
||||
@Override
|
||||
public void channelGroupDeleted(AChannelGroup channelGroup) {
|
||||
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
|
||||
checkChannelGroupManagement.deleteRepostCheckChannelGroup(channelGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageEmbeddedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.PostedImageManagement;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.EmbedType;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RepostEmbedListener implements AsyncMessageEmbeddedListener {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelService repostCheckChannelService;
|
||||
|
||||
@Autowired
|
||||
private RepostService repostService;
|
||||
|
||||
@Autowired
|
||||
private PostedImageManagement repostManagement;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public void execute(GuildMessageEmbedEventModel eventModel) {
|
||||
AChannel channel = channelManagementService.loadChannel(eventModel.getChannelId());
|
||||
if(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)) {
|
||||
if(repostManagement.messageEmbedsHaveBeenCovered(eventModel.getMessageId())) {
|
||||
log.info("The embeds of the message {} in channel {} in server {} have already been covered by repost check -- ignoring.",
|
||||
eventModel.getMessageId(), eventModel.getChannelId(), eventModel.getServerId());
|
||||
return;
|
||||
}
|
||||
channelService.retrieveMessageInChannel(eventModel.getServerId(), eventModel.getChannelId(), eventModel.getMessageId()).thenAccept(message -> {
|
||||
List<MessageEmbed> imageEmbeds = eventModel.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
|
||||
if(!imageEmbeds.isEmpty()) {
|
||||
repostService.processMessageEmbedsRepostCheck(imageEmbeds, message);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmbed;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.EmbedType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RepostMessageReceivedListener implements AsyncMessageReceivedListener {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelService repostCheckChannelService;
|
||||
|
||||
@Autowired
|
||||
private RepostService repostService;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage message) {
|
||||
AChannel channel = channelManagementService.loadChannel(message.getChannelId());
|
||||
if(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)) {
|
||||
repostService.processMessageAttachmentRepostCheck(message);
|
||||
List<CachedEmbed> imageEmbeds = message.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
|
||||
repostService.processMessageEmbedsRepostCheck(imageEmbeds, message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RepostDetectionFeatureDefinition.REPOST_DETECTION;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.abstracto.repostdetection.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.embed.PostIdentifier;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface PostedImageRepository extends JpaRepository<PostedImage, PostIdentifier> {
|
||||
boolean existsByImageHashAndServerId(String hash, Long serverId);
|
||||
Optional<PostedImage> findByImageHashAndServerId(String hash, Long serverId);
|
||||
boolean existsByPostId_MessageId(Long messageId);
|
||||
boolean existsByPostId_MessageIdAndPostId_PositionGreaterThan(Long messageId, Integer position);
|
||||
List<PostedImage> findByPostId_MessageId(Long messageId);
|
||||
void deleteByServer(AServer server);
|
||||
void deleteByPoster(AUserInAServer aUserInAServer);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.abstracto.repostdetection.repository;
|
||||
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface RepostCheckChannelRepository extends JpaRepository<RepostCheckChannelGroup, Long> {
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.sheldan.abstracto.repostdetection.repository;
|
||||
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.Repost;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.embed.RepostIdentifier;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface RepostRepository extends JpaRepository<Repost, RepostIdentifier> {
|
||||
|
||||
@Query(value = "WITH repost_rank AS " +
|
||||
"( " +
|
||||
"SELECT user_in_server_id as user_in_server_id, SUM(count) as repost_count, ROW_NUMBER() OVER ( ORDER BY SUM(count) DESC ) \n" +
|
||||
"FROM repost \n" +
|
||||
"WHERE server_id = :server_id " +
|
||||
"GROUP BY user_in_server_id \n" +
|
||||
"ORDER BY SUM(count) DESC \n" +
|
||||
" )" +
|
||||
"SELECT rank.user_in_server_id as userInServerId, rank.repost_count as repostCount, rank.row_number as rank " +
|
||||
"FROM repost_rank rank ",
|
||||
countQuery = "SELECT COUNT(1) FROM repost WHERE server_id = :server_id GROUP BY user_in_server_id",
|
||||
nativeQuery = true)
|
||||
List<RepostLeaderboardResult> findTopRepostingUsers(@Param("server_id") Long serverId, Pageable pageable);
|
||||
|
||||
@Query(value = "WITH repost_rank AS " +
|
||||
"( " +
|
||||
"SELECT user_in_server_id as user_in_server_id, SUM(count) as repost_count, ROW_NUMBER() OVER ( ORDER BY SUM(count) DESC ) \n" +
|
||||
"FROM repost \n" +
|
||||
"WHERE server_id = :server_id " +
|
||||
"GROUP BY user_in_server_id \n" +
|
||||
"ORDER BY SUM(count) DESC \n" +
|
||||
" )" +
|
||||
"SELECT rank.user_in_server_id as userInServerId, rank.repost_count as repostCount, rank.row_number as rank " +
|
||||
"FROM repost_rank rank " +
|
||||
"WHERE rank.user_in_server_id = :user_in_server_id " +
|
||||
"UNION ALL " +
|
||||
"SELECT :user_in_server_id as userInServerId, 0 as repostCount, 0 as rank " +
|
||||
"WHERE NOT EXISTS " +
|
||||
"(SELECT 1 " +
|
||||
"FROM repost_rank rank WHERE rank.user_in_server_id = :user_in_server_id" +
|
||||
")",
|
||||
nativeQuery = true)
|
||||
RepostLeaderboardResult getRepostRankOfUserInServer(@Param("user_in_server_id") Long useInServerId, @Param("server_id") Long serverId);
|
||||
|
||||
void deleteByServerId(Long serverId);
|
||||
|
||||
void deleteByRepostId_UserInServerIdAndServerId(Long userInServerId, Long serverId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package dev.sheldan.abstracto.repostdetection.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.PostedImageManagement;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class PostedImageServiceBean implements PostedImageService {
|
||||
|
||||
@Autowired
|
||||
private PostedImageManagement postedImageManagement;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public void purgePostedImages(AUserInAServer aUserInAServer) {
|
||||
postedImageManagement.removePostedImagesOf(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgePostedImages(Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
postedImageManagement.removedPostedImagesIn(server);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package dev.sheldan.abstracto.repostdetection.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelGroupService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.sheldan.abstracto.repostdetection.service.RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE;
|
||||
|
||||
@Component
|
||||
public class RepostCheckChannelServiceBean implements RepostCheckChannelService {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelGroupManagement repostCheckChannelManagement;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelGroupService channelGroupService;
|
||||
|
||||
@Autowired
|
||||
private ChannelGroupManagementService channelGroupManagementService;
|
||||
|
||||
@Override
|
||||
public void setRepostCheckEnabledForChannelGroup(AChannelGroup channelGroup) {
|
||||
RepostCheckChannelGroup group = repostCheckChannelManagement.loadRepostChannelGroupByChannelGroup(channelGroup);
|
||||
setRepostCheckEnabledForChannelGroup(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRepostCheckEnabledForChannelGroup(RepostCheckChannelGroup channelGroup) {
|
||||
channelGroup.setCheckEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRepostCheckDisabledForChannelGroup(AChannelGroup channelGroup) {
|
||||
RepostCheckChannelGroup group = repostCheckChannelManagement.loadRepostChannelGroupByChannelGroup(channelGroup);
|
||||
setRepostCheckDisabledForChannelGroup(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRepostCheckDisabledForChannelGroup(RepostCheckChannelGroup channelGroup) {
|
||||
channelGroup.setCheckEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean duplicateCheckEnabledForChannel(TextChannel textChannel) {
|
||||
AChannel channel = channelManagementService.loadChannel(textChannel.getIdLong());
|
||||
return duplicateCheckEnabledForChannel(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean duplicateCheckEnabledForChannel(AChannel channel) {
|
||||
List<AChannelGroup> channelGroups = channelGroupService.getChannelGroupsOfChannelWithType(channel, REPOST_CHECK_CHANNEL_GROUP_TYPE);
|
||||
if(!channelGroups.isEmpty()) {
|
||||
List<RepostCheckChannelGroup> repostChannelGroups = channelGroups.stream().map(aChannelGroup ->
|
||||
repostCheckChannelManagement.loadRepostChannelGroupById(aChannelGroup.getId())
|
||||
).collect(Collectors.toList());
|
||||
return repostChannelGroups.stream().anyMatch(RepostCheckChannelGroup::getCheckEnabled);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepostCheckChannelGroup> getRepostCheckChannelGroupsForServer(AServer server) {
|
||||
return getRepostCheckChannelGroupsForServer(server.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepostCheckChannelGroup> getRepostCheckChannelGroupsForServer(Long serverId) {
|
||||
List<AChannelGroup> channelGroups = channelGroupManagementService.findAllInServerWithType(serverId, REPOST_CHECK_CHANNEL_GROUP_TYPE);
|
||||
if(!channelGroups.isEmpty()) {
|
||||
return channelGroups.stream().map(aChannelGroup ->
|
||||
repostCheckChannelManagement.loadRepostChannelGroupById(aChannelGroup.getId())
|
||||
).collect(Collectors.toList());
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepostCheckChannelGroup> getChannelGroupsWithEnabledCheck(AServer server) {
|
||||
return getChannelGroupsWithEnabledCheck(server.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepostCheckChannelGroup> getChannelGroupsWithEnabledCheck(Long serverId) {
|
||||
return getRepostCheckChannelGroupsForServer(serverId)
|
||||
.stream()
|
||||
.filter(RepostCheckChannelGroup::getCheckEnabled)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
package dev.sheldan.abstracto.repostdetection.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessageUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedAttachment;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmbed;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import dev.sheldan.abstracto.repostdetection.converter.RepostLeaderBoardConverter;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureMode;
|
||||
import dev.sheldan.abstracto.repostdetection.model.RepostLeaderboardEntryModel;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.Repost;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.PostedImageManagement;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RepostServiceBean implements RepostService {
|
||||
|
||||
public static final Integer LEADER_BOARD_PAGE_SIZE = 5;
|
||||
@Autowired
|
||||
private HttpService httpService;
|
||||
|
||||
@Autowired
|
||||
private HashService hashService;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Autowired
|
||||
private PostedImageManagement postedImageManagement;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private ReactionService reactionService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private RepostManagementService repostManagementService;
|
||||
|
||||
@Autowired
|
||||
private RepostLeaderBoardConverter leaderBoardConverter;
|
||||
|
||||
@Autowired
|
||||
private RepostServiceBean self;
|
||||
|
||||
public static final List<String> NUMBER_EMOJI = Arrays.asList("\u0031\u20e3", "\u0032\u20e3", "\u0033\u20e3",
|
||||
"\u0034\u20e3", "\u0035\u20e3", "\u0036\u20e3",
|
||||
"\u0037\u20e3", "\u0038\u20e3", "\u0039\u20e3");
|
||||
|
||||
public static final String REPOST_CHECK_CHANNEL_GROUP_TYPE = "repostDetection";
|
||||
|
||||
// any embedded post will create an repost instance with a position higher than this
|
||||
public static final Integer EMBEDDED_LINK_POSITION_START_INDEX = 1000;
|
||||
public static final String REPOST_MARKER_EMOTE_KEY = "repostMarker";
|
||||
|
||||
@Override
|
||||
public boolean isRepost(CachedMessage message, CachedEmbed messageEmbed, Integer index) {
|
||||
return getRepostFor(message, messageEmbed, index).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PostedImage> getRepostFor(CachedMessage message, CachedEmbed messageEmbed, Integer embedIndex) {
|
||||
if(messageEmbed.getCachedThumbnail() == null && messageEmbed.getCachedImageInfo() == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
String urlToUse = null;
|
||||
if(messageEmbed.getCachedThumbnail() != null) {
|
||||
urlToUse = messageEmbed.getCachedThumbnail().getProxyUrl();
|
||||
} else if (messageEmbed.getCachedImageInfo() != null) {
|
||||
urlToUse = messageEmbed.getCachedImageInfo().getProxyUrl();
|
||||
}
|
||||
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
|
||||
.builder()
|
||||
.serverId(message.getServerId())
|
||||
.channelId(message.getChannelId())
|
||||
.userId(message.getAuthor().getAuthorId())
|
||||
.messageId(message.getMessageId())
|
||||
.build();
|
||||
return checkForDuplicates(serverChannelMessageUser, EMBEDDED_LINK_POSITION_START_INDEX + embedIndex, urlToUse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PostedImage> getRepostFor(Message message, MessageEmbed messageEmbed, Integer embedIndex) {
|
||||
if(messageEmbed.getThumbnail() == null && messageEmbed.getImage() == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
String urlToUse = null;
|
||||
if(messageEmbed.getThumbnail() != null) {
|
||||
urlToUse = messageEmbed.getThumbnail().getProxyUrl();
|
||||
} else if (messageEmbed.getImage() != null) {
|
||||
urlToUse = messageEmbed.getImage().getProxyUrl();
|
||||
}
|
||||
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
|
||||
.builder()
|
||||
.serverId(message.getGuild().getIdLong())
|
||||
.channelId(message.getChannel().getIdLong())
|
||||
.userId(message.getAuthor().getIdLong())
|
||||
.messageId(message.getIdLong())
|
||||
.build();
|
||||
return checkForDuplicates(serverChannelMessageUser, EMBEDDED_LINK_POSITION_START_INDEX + embedIndex, urlToUse);
|
||||
}
|
||||
|
||||
private Optional<PostedImage> checkForDuplicates(ServerChannelMessageUser serverChannelMessageUser, Integer index, String fileUrl) {
|
||||
String fileHash = calculateHashForPost(fileUrl, serverChannelMessageUser.getServerId());
|
||||
AServer aServer = serverManagementService.loadServer(serverChannelMessageUser.getServerId());
|
||||
Optional<PostedImage> potentialRepost = postedImageManagement.getPostWithHash(fileHash, aServer);
|
||||
if(potentialRepost.isPresent()) {
|
||||
PostedImage existingRepost = potentialRepost.get();
|
||||
return !existingRepost.getPostId().getMessageId().equals(serverChannelMessageUser.getMessageId()) ? Optional.of(existingRepost) : Optional.empty();
|
||||
} else {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(serverChannelMessageUser.getServerId(), serverChannelMessageUser.getUserId());
|
||||
AServerAChannelAUser cause = AServerAChannelAUser
|
||||
.builder()
|
||||
.aUserInAServer(aUserInAServer)
|
||||
.channel(channelManagementService.loadChannel(serverChannelMessageUser.getChannelId()))
|
||||
.guild(aServer)
|
||||
.user(aUserInAServer.getUserReference())
|
||||
.build();
|
||||
postedImageManagement.createPost(cause, serverChannelMessageUser.getMessageId(), fileHash, index);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRepost(CachedMessage message, CachedAttachment attachment, Integer index) {
|
||||
return getRepostFor(message, attachment, index).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PostedImage> getRepostFor(CachedMessage message, CachedAttachment attachment, Integer index) {
|
||||
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
|
||||
.builder()
|
||||
.serverId(message.getServerId())
|
||||
.channelId(message.getChannelId())
|
||||
.userId(message.getAuthor().getAuthorId())
|
||||
.messageId(message.getMessageId())
|
||||
.build();
|
||||
return checkForDuplicates(serverChannelMessageUser, index, attachment.getProxyUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String calculateHashForPost(String url, Long serverId) {
|
||||
File downloadedFile = null;
|
||||
try {
|
||||
if(featureModeService.featureModeActive(RepostDetectionFeatureDefinition.REPOST_DETECTION, serverId, RepostDetectionFeatureMode.DOWNLOAD)) {
|
||||
downloadedFile = httpService.downloadFileToTempFile(url);
|
||||
return hashService.sha256HashFileContent(downloadedFile);
|
||||
} else {
|
||||
return hashService.sha256HashString(url);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to download attachment for repost check.", e);
|
||||
} finally {
|
||||
if(downloadedFile != null) {
|
||||
try {
|
||||
fileService.safeDelete(downloadedFile);
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to delete downloaded repost check file.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessageAttachmentRepostCheck(CachedMessage message) {
|
||||
boolean canThereBeMultipleReposts = message.getAttachments().size() > 1;
|
||||
for (int imageIndex = 0; imageIndex < message.getAttachments().size(); imageIndex++) {
|
||||
executeRepostCheckForAttachment(message, message.getAttachments().get(imageIndex), imageIndex, canThereBeMultipleReposts);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeRepostCheckForAttachment(CachedMessage message, CachedAttachment attachment, Integer index, boolean moreRepostsPossible) {
|
||||
Optional<PostedImage> originalPostOptional = getRepostFor(message, attachment, index);
|
||||
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
|
||||
.builder()
|
||||
.serverId(message.getServerId())
|
||||
.channelId(message.getChannelId())
|
||||
.userId(message.getAuthor().getAuthorId())
|
||||
.messageId(message.getMessageId())
|
||||
.build();
|
||||
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(serverChannelMessageUser, index, moreRepostsPossible, postedImage));
|
||||
}
|
||||
|
||||
private void markMessageAndPersist(ServerChannelMessageUser messageUser, Integer index, boolean moreRepostsPossible, PostedImage originalPost) {
|
||||
log.info("Detected repost in message embed {} of message {} in channel {} in server {}.", index, messageUser.getMessageId(), messageUser.getChannelId(), messageUser.getServerId());
|
||||
CompletableFuture<Void> markerFuture = reactionService.addReactionToMessageAsync(REPOST_MARKER_EMOTE_KEY, messageUser.getServerId(), messageUser.getChannelId(), messageUser.getMessageId());
|
||||
CompletableFuture<Void> counterFuture;
|
||||
if (moreRepostsPossible) {
|
||||
counterFuture = reactionService.addDefaultReactionToMessageAsync(NUMBER_EMOJI.get(index), messageUser.getServerId(), messageUser.getChannelId(), messageUser.getMessageId());
|
||||
} else {
|
||||
counterFuture = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
Long messageId = originalPost.getPostId().getMessageId();
|
||||
Integer position = originalPost.getPostId().getPosition();
|
||||
Long serverId = messageUser.getServerId();
|
||||
Long userId = messageUser.getUserId();
|
||||
CompletableFuture.allOf(markerFuture, counterFuture).thenAccept(unused ->
|
||||
self.persistRepost(messageId, position, serverId, userId)
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void persistRepost(Long messageId, Integer position, Long serverId, Long userId) {
|
||||
PostedImage postedImage = postedImageManagement.getPostFromMessageAndPosition(messageId, position);
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(serverId, userId);
|
||||
Optional<Repost> existingPost = repostManagementService.findRepostOptional(postedImage, userInAServer);
|
||||
if(existingPost.isPresent()) {
|
||||
Repost previousRepost = existingPost.get();
|
||||
existingPost.get().setCount(previousRepost.getCount() + 1);
|
||||
} else {
|
||||
repostManagementService.createRepost(postedImage, userInAServer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessageEmbedsRepostCheck(List<CachedEmbed> embeds, CachedMessage message) {
|
||||
boolean canThereBeMultipleReposts = embeds.size() > 1 || !message.getAttachments().isEmpty();
|
||||
for (int imageIndex = 0; imageIndex < embeds.size(); imageIndex++) {
|
||||
executeRepostCheckForMessageEmbed(message, embeds.get(imageIndex), imageIndex + message.getAttachments().size(), canThereBeMultipleReposts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessageEmbedsRepostCheck(List<MessageEmbed> embeds, Message message) {
|
||||
boolean canThereBeMultipleReposts = embeds.size() > 1 || !message.getAttachments().isEmpty();
|
||||
for (int imageIndex = 0; imageIndex < embeds.size(); imageIndex++) {
|
||||
executeRepostCheckForMessageEmbed(message, embeds.get(imageIndex), imageIndex + message.getAttachments().size(), canThereBeMultipleReposts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<RepostLeaderboardEntryModel>> retrieveRepostLeaderboard(Guild guild, Integer page) {
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
List<RepostLeaderboardResult> topRepostingUsersOfServer = repostManagementService.findTopRepostingUsersOfServer(server, page, LEADER_BOARD_PAGE_SIZE);
|
||||
return leaderBoardConverter.fromLeaderBoardResults(topRepostingUsersOfServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeReposts(AUserInAServer userInAServer) {
|
||||
repostManagementService.deleteRepostsFromUser(userInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeReposts(Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
repostManagementService.deleteRepostsFromServer(server);
|
||||
}
|
||||
|
||||
private void executeRepostCheckForMessageEmbed(CachedMessage message, CachedEmbed messageEmbed, Integer index, boolean moreRepostsPossible) {
|
||||
Optional<PostedImage> originalPostOptional = getRepostFor(message, messageEmbed, index);
|
||||
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
|
||||
.builder()
|
||||
.serverId(message.getServerId())
|
||||
.channelId(message.getChannelId())
|
||||
.userId(message.getAuthor().getAuthorId())
|
||||
.messageId(message.getMessageId())
|
||||
.build();
|
||||
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(serverChannelMessageUser, index, moreRepostsPossible, postedImage));
|
||||
}
|
||||
|
||||
private void executeRepostCheckForMessageEmbed(Message message, MessageEmbed messageEmbed, Integer index, boolean moreRepostsPossible) {
|
||||
Optional<PostedImage> originalPostOptional = getRepostFor(message, messageEmbed, index);
|
||||
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
|
||||
.builder()
|
||||
.serverId(message.getGuild().getIdLong())
|
||||
.channelId(message.getChannel().getIdLong())
|
||||
.userId(message.getAuthor().getIdLong())
|
||||
.messageId(message.getIdLong())
|
||||
.build();
|
||||
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(serverChannelMessageUser, index, moreRepostsPossible, postedImage));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package dev.sheldan.abstracto.repostdetection.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.repostdetection.exception.PostedImageNotFoundException;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.embed.PostIdentifier;
|
||||
import dev.sheldan.abstracto.repostdetection.repository.PostedImageRepository;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class PostedImageManagementBean implements PostedImageManagement {
|
||||
|
||||
@Autowired
|
||||
private PostedImageRepository postedImageRepository;
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelGroupManagement checkChannelBean;
|
||||
|
||||
@Override
|
||||
public PostedImage createPost(AServerAChannelAUser creation, Long messageId, String hash, Integer index) {
|
||||
PostedImage post = PostedImage
|
||||
.builder()
|
||||
.imageHash(hash)
|
||||
.postId(new PostIdentifier(messageId, index))
|
||||
.poster(creation.getAUserInAServer())
|
||||
.server(creation.getGuild())
|
||||
.postedChannel(creation.getChannel())
|
||||
.build();
|
||||
|
||||
postedImageRepository.save(post);
|
||||
return post;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postWitHashExists(String hash, AServer server) {
|
||||
return postedImageRepository.existsByImageHashAndServerId(hash, server.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PostedImage> getPostWithHash(String hash, AServer server) {
|
||||
return postedImageRepository.findByImageHashAndServerId(hash, server.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean messageHasBeenCovered(Long messageId) {
|
||||
return postedImageRepository.existsByPostId_MessageId(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean messageEmbedsHaveBeenCovered(Long messageId) {
|
||||
return postedImageRepository.existsByPostId_MessageIdAndPostId_PositionGreaterThan(messageId, RepostServiceBean.EMBEDDED_LINK_POSITION_START_INDEX - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PostedImage> getAllFromMessage(Long messageId) {
|
||||
return postedImageRepository.findByPostId_MessageId(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PostedImage> getPostFromMessageAndPositionOptional(Long messageId, Integer position) {
|
||||
return postedImageRepository.findById(new PostIdentifier(messageId, position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PostedImage getPostFromMessageAndPosition(Long messageId, Integer position) {
|
||||
return getPostFromMessageAndPositionOptional(messageId, position).orElseThrow(() -> new PostedImageNotFoundException(messageId, position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePostedImagesOf(AUserInAServer poster) {
|
||||
postedImageRepository.deleteByPoster(poster);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removedPostedImagesIn(AServer aServer) {
|
||||
postedImageRepository.deleteByServer(aServer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package dev.sheldan.abstracto.repostdetection.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.repostdetection.exception.RepostCheckChannelGroupNotFoundException;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.RepostCheckChannelGroup;
|
||||
import dev.sheldan.abstracto.repostdetection.repository.RepostCheckChannelRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class RepostCheckChannelGroupManagementBean implements RepostCheckChannelGroupManagement {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelRepository repository;
|
||||
|
||||
@Override
|
||||
public RepostCheckChannelGroup loadRepostChannelGroupById(Long channelGroupId) {
|
||||
return loadRepostChanelGroupByIdOptional(channelGroupId).orElseThrow(() -> new RepostCheckChannelGroupNotFoundException(channelGroupId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<RepostCheckChannelGroup> loadRepostChanelGroupByIdOptional(Long channelGroupId) {
|
||||
return repository.findById(channelGroupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean repostCheckChannelGroupExists(Long channelGroupId) {
|
||||
return loadRepostChanelGroupByIdOptional(channelGroupId).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<RepostCheckChannelGroup> loadRepostChannelGroupByChannelGroupOptional(AChannelGroup channelGroup) {
|
||||
return loadRepostChanelGroupByIdOptional(channelGroup.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepostCheckChannelGroup loadRepostChannelGroupByChannelGroup(AChannelGroup channelGroup) {
|
||||
return loadRepostChannelGroupById(channelGroup.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepostCheckChannelGroup createRepostCheckChannelGroup(AChannelGroup channelGroup) {
|
||||
RepostCheckChannelGroup repostCheckChannelGroup = RepostCheckChannelGroup
|
||||
.builder()
|
||||
.checkEnabled(true)
|
||||
.channelGroup(channelGroup)
|
||||
.id(channelGroup.getId())
|
||||
.build();
|
||||
|
||||
repository.save(repostCheckChannelGroup);
|
||||
return repostCheckChannelGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRepostCheckChannelGroup(AChannelGroup channelGroup) {
|
||||
RepostCheckChannelGroup repostCheckChannelGroup = loadRepostChannelGroupByChannelGroup(channelGroup);
|
||||
repository.delete(repostCheckChannelGroup);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package dev.sheldan.abstracto.repostdetection.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.repostdetection.exception.RepostNotFoundException;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.PostedImage;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.Repost;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.embed.RepostIdentifier;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.result.RepostLeaderboardResult;
|
||||
import dev.sheldan.abstracto.repostdetection.repository.RepostRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class RepostManagementServiceBean implements RepostManagementService {
|
||||
|
||||
@Autowired
|
||||
private RepostRepository repostRepository;
|
||||
|
||||
@Override
|
||||
public Repost createRepost(PostedImage postedImage, AUserInAServer poster) {
|
||||
Repost repost = Repost
|
||||
.builder()
|
||||
.originalPost(postedImage)
|
||||
.poster(poster)
|
||||
.repostId(buildRepostIdentifier(postedImage, poster))
|
||||
.server(postedImage.getServer())
|
||||
.count(1)
|
||||
.build();
|
||||
|
||||
repostRepository.save(repost);
|
||||
return repost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Repost setRepostCount(PostedImage postedImage, AUserInAServer poster, Integer newCount) {
|
||||
Repost repost = findRepost(postedImage, poster);
|
||||
repost.setCount(newCount);
|
||||
return repost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Repost findRepost(PostedImage postedImage, AUserInAServer poster) {
|
||||
return findRepostOptional(postedImage, poster)
|
||||
.orElseThrow(() -> new RepostNotFoundException(postedImage.getPostId().getMessageId(), postedImage.getPostId().getPosition(), poster.getUserInServerId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Repost> findRepostOptional(PostedImage postedImage, AUserInAServer poster) {
|
||||
return repostRepository.findById(buildRepostIdentifier(postedImage, poster));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepostLeaderboardResult> findTopRepostingUsersOfServer(AServer server, Integer page, Integer pageSize) {
|
||||
return findTopRepostingUsersOfServer(server.getId(), page, pageSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepostLeaderboardResult> findTopRepostingUsersOfServer(Long serverId, Integer page, Integer pageSize) {
|
||||
return repostRepository.findTopRepostingUsers(serverId, PageRequest.of(page - 1, pageSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepostLeaderboardResult getRepostRankOfUser(AUserInAServer aUserInAServer) {
|
||||
return repostRepository.getRepostRankOfUserInServer(aUserInAServer.getUserInServerId(), aUserInAServer.getServerReference().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRepostsFromUser(AUserInAServer aUserInAServer) {
|
||||
repostRepository.deleteByRepostId_UserInServerIdAndServerId(aUserInAServer.getUserInServerId(), aUserInAServer.getServerReference().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRepostsFromServer(AServer server) {
|
||||
repostRepository.deleteByServerId(server.getId());
|
||||
}
|
||||
|
||||
private RepostIdentifier buildRepostIdentifier(PostedImage postedImage, AUserInAServer poster) {
|
||||
return new RepostIdentifier(postedImage.getPostId().getMessageId(), postedImage.getPostId().getPosition(), poster.getUserInServerId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../dbchangelog-3.8.xsd" >
|
||||
<include file="repost-detection-tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="repost-detection-seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<property name="repostDetectionModule" value="(SELECT id FROM module WHERE name = 'repostDetection')"/>
|
||||
<property name="repostDetectionFeature" value="(SELECT id FROM feature WHERE key = 'repostDetection')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="repostDetection-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="disableRepostCheck"/>
|
||||
<column name="module_id" valueComputed="${repostDetectionModule}"/>
|
||||
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="enableRepostCheck"/>
|
||||
<column name="module_id" valueComputed="${repostDetectionModule}"/>
|
||||
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="purgeImagePosts"/>
|
||||
<column name="module_id" valueComputed="${repostDetectionModule}"/>
|
||||
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="purgeReposts"/>
|
||||
<column name="module_id" valueComputed="${repostDetectionModule}"/>
|
||||
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="repostLeaderboard"/>
|
||||
<column name="module_id" valueComputed="${repostDetectionModule}"/>
|
||||
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="showRepostCheckChannels"/>
|
||||
<column name="module_id" valueComputed="${repostDetectionModule}"/>
|
||||
<column name="feature_id" valueComputed="${repostDetectionFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<include file="default_emote.xml" relativeToChangelogFile="true"/>
|
||||
<include file="feature.xml" relativeToChangelogFile="true"/>
|
||||
<include file="module.xml" relativeToChangelogFile="true"/>
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
<include file="channel_group_types.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="repost-detection_default_emote-insert">
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="repostMarker"/>
|
||||
<column name="name" value="♻️"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="repost-detection_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="repostDetection"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="repost-detection-module-insertion">
|
||||
<insert tableName="module">
|
||||
<column name="name" value="repostDetection"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="posted_image-table">
|
||||
<createTable tableName="posted_image">
|
||||
<column name="message_id" type="BIGINT" >
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="position" type="INTEGER" >
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="author_user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="posted_channel_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="image_hash" type="VARCHAR(512)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<createIndex indexName="idx_posted_image_hash_server" tableName="posted_image">
|
||||
<column name="image_hash"/>
|
||||
<column name="server_id"/>
|
||||
</createIndex>
|
||||
<addPrimaryKey columnNames="message_id, position" tableName="posted_image" constraintName="pk_posted_image" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="author_user_in_server_id" baseTableName="posted_image" constraintName="fk_posted_image_user"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="posted_channel_id" baseTableName="posted_image" constraintName="fk_posted_image_channel"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
|
||||
referencedTableName="channel" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="posted_image" constraintName="fk_posted_image_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
|
||||
referencedTableName="server" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS posted_image_update_trigger ON posted_image;
|
||||
CREATE TRIGGER posted_image_update_trigger BEFORE UPDATE ON posted_image FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS posted_image_insert_trigger ON posted_image;
|
||||
CREATE TRIGGER posted_image_insert_trigger BEFORE INSERT ON posted_image FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="repost-table">
|
||||
<createTable tableName="repost">
|
||||
<column name="message_id" type="BIGINT" >
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="position" type="INTEGER" >
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="count" type="INTEGER">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<addPrimaryKey columnNames="message_id, position, user_in_server_id" tableName="repost" constraintName="pk_repost" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="user_in_server_id" baseTableName="repost" constraintName="fk_repost_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="message_id, position" baseTableName="repost" constraintName="fk_repost_posted_image"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="message_id, position"
|
||||
referencedTableName="posted_image" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="user_in_server_id" baseTableName="repost" constraintName="fk_repost_user_in_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id"
|
||||
referencedTableName="user_in_server" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS repost_update_trigger ON repost;
|
||||
CREATE TRIGGER repost_update_trigger BEFORE UPDATE ON repost FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS repost_insert_trigger ON repost;
|
||||
CREATE TRIGGER repost_insert_trigger BEFORE INSERT ON repost FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="repost_check_channel_group-table">
|
||||
<createTable tableName="repost_check_channel_group">
|
||||
<column name="id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="enabled" type="BOOLEAN">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="id" baseTableName="repost_check_channel_group" constraintName="fk_repost_check_channel_group_group"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="channel_group" validate="true"/>
|
||||
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS repost_check_channel_group_update_trigger ON repost_check_channel_group;
|
||||
CREATE TRIGGER repost_check_channel_group_update_trigger BEFORE UPDATE ON repost_check_channel_group FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS repost_check_channel_group_insert_trigger ON repost_check_channel_group;
|
||||
CREATE TRIGGER repost_check_channel_group_insert_trigger BEFORE INSERT ON repost_check_channel_group FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<include file="repost_check_channel_group.xml" relativeToChangelogFile="true"/>
|
||||
<include file="posted_image.xml" relativeToChangelogFile="true"/>
|
||||
<include file="repost.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog-3.8.xsd" >
|
||||
<include file="1.0-repost-detection/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,10 @@
|
||||
abstracto.featureFlags.repostDetection.featureName=repostDetection
|
||||
abstracto.featureFlags.repostDetection.enabled=false
|
||||
|
||||
abstracto.featureModes.download.featureName=repostDetection
|
||||
abstracto.featureModes.download.mode=download
|
||||
abstracto.featureModes.download.enabled=true
|
||||
|
||||
abstracto.featureModes.leaderboard.featureName=repostDetection
|
||||
abstracto.featureModes.leaderboard.mode=leaderboard
|
||||
abstracto.featureModes.leaderboard.enabled=true
|
||||
Reference in New Issue
Block a user