mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-15 20:16:34 +00:00
[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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) : "";
|
||||
|
||||
@@ -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) : "";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user