mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-16 20:29:08 +00:00
[AB-197] splitting utility maven module into separate maven modules
aligning some package names removing some unnecessary computed values from liquibase
This commit is contained in:
33
abstracto-application/abstracto-modules/starboard/pom.xml
Normal file
33
abstracto-application/abstracto-modules/starboard/pom.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>starboard</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>starboard-int</module>
|
||||
<module>starboard-impl</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>starboard</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>starboard-impl</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/liquibase.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>starboard-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>metrics-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
|
||||
<id>liquibase</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<outputDirectory>.</outputDirectory>
|
||||
<directory>${project.basedir}/src/main/resources/migrations</directory>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
@@ -0,0 +1,73 @@
|
||||
package dev.sheldan.abstracto.starboard.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeatureDefinition;
|
||||
import dev.sheldan.abstracto.starboard.model.template.MemberStarStatsModel;
|
||||
import dev.sheldan.abstracto.starboard.service.StarboardService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class StarStats extends AbstractConditionableCommand {
|
||||
|
||||
public static final String STARSTATS_RESPONSE_TEMPLATE = "starStats_response";
|
||||
public static final String STARSTATS_SINGLE_MEMBER_RESPONSE_TEMPLATE = "starStats_single_member_response";
|
||||
|
||||
@Autowired
|
||||
private StarboardService starboardService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
if(parameters.isEmpty()) {
|
||||
return starboardService.retrieveStarStats(commandContext.getGuild().getIdLong())
|
||||
.thenCompose(starStatsModel ->
|
||||
FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(STARSTATS_RESPONSE_TEMPLATE, starStatsModel, commandContext.getChannel()))
|
||||
).thenApply(o -> CommandResult.fromIgnored());
|
||||
} else {
|
||||
Member targetMember = (Member) parameters.get(0);
|
||||
MemberStarStatsModel memberStarStatsModel = starboardService.retrieveStarStatsForMember(targetMember);
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(STARSTATS_SINGLE_MEMBER_RESPONSE_TEMPLATE, memberStarStatsModel, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter memberParameter = Parameter.builder().templated(true).name("member").type(Member.class).optional(true).build();
|
||||
List<Parameter> parameters = Collections.singletonList(memberParameter);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("starStats")
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StarboardFeatureDefinition.STARBOARD;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.abstracto.starboard.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:starboard-config.properties")
|
||||
public class StarboardConfig {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package dev.sheldan.abstracto.starboard.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserManagementService;
|
||||
import dev.sheldan.abstracto.starboard.model.template.StarStatsUser;
|
||||
import dev.sheldan.abstracto.starboard.repository.result.StarStatsGuildUserResult;
|
||||
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;
|
||||
|
||||
@Component
|
||||
public class StarStatsUserConverter {
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserManagementService userManagementService;
|
||||
|
||||
@Autowired
|
||||
private StarStatsUserConverter self;
|
||||
|
||||
public List<CompletableFuture<StarStatsUser>> convertToStarStatsUser(List<StarStatsGuildUserResult> users, Long serverId) {
|
||||
List<CompletableFuture<StarStatsUser>> result = new ArrayList<>();
|
||||
users.forEach(starStatsUserResult ->
|
||||
result.add(createStarStatsUser(serverId, starStatsUserResult))
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
private CompletableFuture<StarStatsUser> createStarStatsUser(Long serverId, StarStatsGuildUserResult starStatsGuildUserResult) {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(starStatsGuildUserResult.getUserId());
|
||||
return memberService.getMemberInServerAsync(serverId, aUserInAServer.getUserReference().getId())
|
||||
.thenApply(member -> self.loadStarStatsUser(starStatsGuildUserResult, member))
|
||||
.exceptionally(throwable -> self.loadStarStatsUser(starStatsGuildUserResult, null));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public StarStatsUser loadStarStatsUser(StarStatsGuildUserResult starStatsGuildUserResult, net.dv8tion.jda.api.entities.Member member) {
|
||||
return StarStatsUser
|
||||
.builder()
|
||||
.starCount(starStatsGuildUserResult.getStarCount())
|
||||
.member(member)
|
||||
.user(userInServerManagementService.loadOrCreateUser(starStatsGuildUserResult.getUserId()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncReactionAddedListener;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncReactionClearedListener;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncReactionRemovedListener;
|
||||
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeature;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeatureDefinition;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.StarboardService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarboardListener implements AsyncReactionAddedListener, AsyncReactionRemovedListener, AsyncReactionClearedListener {
|
||||
|
||||
public static final String FIRST_LEVEL_THRESHOLD_KEY = "starLvl1";
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private ConfigManagementService configManagementService;
|
||||
|
||||
@Autowired
|
||||
private StarboardService starboardService;
|
||||
|
||||
@Autowired
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Autowired
|
||||
private StarboardPostReactorManagementService starboardPostReactorManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
public static final String STARBOARD_STARS = "starboard.stars";
|
||||
public static final String STARBOARD_POSTS = "starboard.posts";
|
||||
public static final String STAR_ACTION = "action";
|
||||
private static final CounterMetric STARBOARD_STARS_ADDED = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_STARS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "added")))
|
||||
.build();
|
||||
|
||||
private static final CounterMetric STARBOARD_STARS_REMOVED = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_STARS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "removed")))
|
||||
.build();
|
||||
|
||||
private static final CounterMetric STARBOARD_STARS_THRESHOLD_REACHED = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_POSTS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "threshold.reached")))
|
||||
.build();
|
||||
|
||||
private static final CounterMetric STARBOARD_STARS_THRESHOLD_FELL = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_POSTS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "threshold.below")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void executeReactionAdded(CachedMessage message, CachedReactions cachedReaction, ServerUser serverUser) {
|
||||
if(serverUser.getUserId().equals(message.getAuthor().getAuthorId())) {
|
||||
return;
|
||||
}
|
||||
Long guildId = message.getServerId();
|
||||
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, guildId);
|
||||
if(emoteService.compareCachedEmoteWithAEmote(cachedReaction.getEmote(), aEmote)) {
|
||||
metricService.incrementCounter(STARBOARD_STARS_ADDED);
|
||||
log.info("User {} in server {} reacted with star to put a message {} from channel {} on starboard.", serverUser.getUserId(), message.getServerId(), message.getMessageId(), message.getChannelId());
|
||||
Optional<CachedReactions> reactionOptional = emoteService.getReactionFromMessageByEmote(message, aEmote);
|
||||
handleStarboardPostChange(message, reactionOptional.orElse(null), serverUser, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStarboardPostChange(CachedMessage message, CachedReactions reaction, ServerUser serverUser, boolean adding) {
|
||||
Optional<StarboardPost> starboardPostOptional = starboardPostManagementService.findByMessageId(message.getMessageId());
|
||||
if(reaction != null) {
|
||||
AUserInAServer author = userInServerManagementService.loadOrCreateUser(message.getServerId(), message.getAuthor().getAuthorId());
|
||||
List<AUserInAServer> userExceptAuthor = getUsersExcept(reaction.getUsers(), author);
|
||||
Long starMinimum = getFromConfig(FIRST_LEVEL_THRESHOLD_KEY, message.getServerId());
|
||||
AUserInAServer userAddingReaction = userInServerManagementService.loadOrCreateUser(serverUser);
|
||||
if (userExceptAuthor.size() >= starMinimum) {
|
||||
log.info("Post reached starboard minimum. Message {} in channel {} in server {} will be starred/updated.",
|
||||
message.getMessageId(), message.getChannelId(), message.getServerId());
|
||||
if(starboardPostOptional.isPresent()) {
|
||||
updateStarboardPost(message, userAddingReaction, adding, starboardPostOptional.get(), userExceptAuthor);
|
||||
} else {
|
||||
metricService.incrementCounter(STARBOARD_STARS_THRESHOLD_REACHED);
|
||||
log.info("Creating starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
|
||||
starboardService.createStarboardPost(message, userExceptAuthor, userAddingReaction, author);
|
||||
}
|
||||
} else {
|
||||
if(starboardPostOptional.isPresent()) {
|
||||
metricService.incrementCounter(STARBOARD_STARS_THRESHOLD_FELL);
|
||||
log.info("Removing starboard post for message {} in channel {} in server {}. It fell under the threshold {}", message.getMessageId(), message.getChannelId(), message.getServerId(), starMinimum);
|
||||
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(starboardPostOptional.isPresent()) {
|
||||
log.info("Removing starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
|
||||
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStarboardPost(CachedMessage message, AUserInAServer userReacting, boolean adding, StarboardPost starboardPost, List<AUserInAServer> userExceptAuthor) {
|
||||
starboardPost.setIgnored(false);
|
||||
// TODO handle futures correctly
|
||||
starboardService.updateStarboardPost(starboardPost, message, userExceptAuthor);
|
||||
if(adding) {
|
||||
log.trace("Adding reactor {} from message {}", userReacting.getUserReference().getId(), message.getMessageId());
|
||||
starboardPostReactorManagementService.addReactor(starboardPost, userReacting);
|
||||
} else {
|
||||
log.trace("Removing reactor {} from message {}", userReacting.getUserReference().getId(), message.getMessageId());
|
||||
starboardPostReactorManagementService.removeReactor(starboardPost, userReacting);
|
||||
}
|
||||
}
|
||||
|
||||
private void completelyRemoveStarboardPost(StarboardPost starboardPost) {
|
||||
starboardService.deleteStarboardMessagePost(starboardPost);
|
||||
starboardPostManagementService.removePost(starboardPost);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void executeReactionRemoved(CachedMessage message, CachedReactions removedReaction, ServerUser userRemoving) {
|
||||
if(message.getAuthor().getAuthorId().equals(userRemoving.getUserId())) {
|
||||
return;
|
||||
}
|
||||
Long guildId = message.getServerId();
|
||||
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, guildId);
|
||||
if(emoteService.compareCachedEmoteWithAEmote(removedReaction.getEmote(), aEmote)) {
|
||||
metricService.incrementCounter(STARBOARD_STARS_REMOVED);
|
||||
log.info("User {} in server {} removed star reaction from message {} on starboard.",
|
||||
userRemoving.getUserId(), message.getServerId(), message.getMessageId());
|
||||
Optional<CachedReactions> reactionOptional = emoteService.getReactionFromMessageByEmote(message, aEmote);
|
||||
handleStarboardPostChange(message, reactionOptional.orElse(null), userRemoving, false);
|
||||
}
|
||||
}
|
||||
|
||||
private Long getFromConfig(String key, Long guildId) {
|
||||
return configManagementService.loadConfig(guildId, key).getLongValue();
|
||||
}
|
||||
|
||||
private List<AUserInAServer> getUsersExcept(List<ServerUser> users, AUserInAServer author) {
|
||||
return users.stream().filter(user -> !(user.getServerId().equals(author.getServerReference().getId()) && user.getUserId().equals(author.getUserReference().getId()))).map(serverUser -> {
|
||||
Optional<AUserInAServer> aUserInAServer = userInServerManagementService.loadUserOptional(serverUser.getServerId(), serverUser.getUserId());
|
||||
return aUserInAServer.orElse(null);
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StarboardFeatureDefinition.STARBOARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeReactionCleared(CachedMessage message) {
|
||||
Optional<StarboardPost> starboardPostOptional = starboardPostManagementService.findByMessageId(message.getMessageId());
|
||||
|
||||
starboardPostOptional.ifPresent(starboardPost -> {
|
||||
log.info("Reactions on message {} in channel {} in server {} were cleared. Completely deleting the starboard post {}.",
|
||||
message.getMessageId(), message.getChannelId(), message.getServerId(), starboardPost.getId());
|
||||
starboardPostReactorManagementService.removeReactors(starboardPost);
|
||||
completelyRemoveStarboardPost(starboardPost);
|
||||
});
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(STARBOARD_STARS_ADDED, "Star reaction added");
|
||||
metricService.registerCounter(STARBOARD_STARS_REMOVED, "Star reaction removed");
|
||||
metricService.registerCounter(STARBOARD_STARS_THRESHOLD_REACHED, "Starboard posts reaching threshold");
|
||||
metricService.registerCounter(STARBOARD_STARS_THRESHOLD_FELL, "Starboard posts falling below threshold");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageDeletedListener;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeatureDefinition;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarboardPostDeletedListener implements AsyncMessageDeletedListener {
|
||||
|
||||
@Autowired
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage messageBefore) {
|
||||
Optional<StarboardPost> byStarboardPostId = starboardPostManagementService.findByStarboardPostId(messageBefore.getMessageId());
|
||||
if(byStarboardPostId.isPresent()) {
|
||||
StarboardPost post = byStarboardPostId.get();
|
||||
log.info("Removing starboard post: message {}, channel {}, server {}, because the message was deleted",
|
||||
post.getPostMessageId(), post.getSourceChannel().getId(), messageBefore.getServerId());
|
||||
starboardPostManagementService.setStarboardPostIgnored(messageBefore.getMessageId(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StarboardFeatureDefinition.STARBOARD;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.sheldan.abstracto.starboard.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPostReaction;
|
||||
import dev.sheldan.abstracto.starboard.repository.result.StarStatsGuildUserResult;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface StarboardPostReactionRepository extends JpaRepository<StarboardPostReaction, Long> {
|
||||
|
||||
void deleteByReactorAndStarboardPost(AUserInAServer user, StarboardPost post);
|
||||
|
||||
void deleteByStarboardPost(StarboardPost post);
|
||||
|
||||
@Query(value = "SELECT r.reactor_user_in_server_id as userId, COUNT(*) AS starCount \n" +
|
||||
"FROM starboard_post_reaction r \n" +
|
||||
"INNER JOIN starboard_post p ON p.id = r.post_id\n" +
|
||||
"WHERE p.server_id = :serverId\n" +
|
||||
" AND p.ignored = false\n" +
|
||||
"GROUP BY r.reactor_user_in_server_id \n" +
|
||||
"ORDER BY starCount DESC \n" +
|
||||
"LIMIT :count", nativeQuery = true)
|
||||
List<StarStatsGuildUserResult> findTopStarGiverInServer(Long serverId, Integer count);
|
||||
|
||||
@Query(value = "SELECT COUNT(*) \n" +
|
||||
"FROM starboard_post_reaction r \n" +
|
||||
"INNER JOIN starboard_post p ON p.id = r.post_id\n" +
|
||||
"WHERE p.server_id = :serverId\n"
|
||||
, nativeQuery = true)
|
||||
Integer getReactionCountByServer(Long serverId);
|
||||
|
||||
@Query(value = "SELECT p.author_user_in_server_id as userId, COUNT(*) AS starCount \n" +
|
||||
"FROM starboard_post_reaction r \n" +
|
||||
"INNER JOIN starboard_post p ON p.id = r.post_id\n" +
|
||||
"WHERE p.server_id = :serverId\n" +
|
||||
" AND p.ignored = false\n" +
|
||||
"GROUP BY p.author_user_in_server_id \n" +
|
||||
"ORDER BY starCount DESC \n" +
|
||||
"LIMIT :count", nativeQuery = true)
|
||||
List<StarStatsGuildUserResult> retrieveTopStarReceiverInServer(Long serverId, Integer count);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dev.sheldan.abstracto.starboard.repository;
|
||||
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface StarboardPostRepository extends JpaRepository<StarboardPost, Long> {
|
||||
|
||||
StarboardPost findByPostMessageId(Long messageId);
|
||||
|
||||
StarboardPost findByStarboardMessageId(Long messageId);
|
||||
|
||||
boolean existsByStarboardMessageId(Long messageId);
|
||||
|
||||
List<StarboardPost> findByServer_Id(Long serverId);
|
||||
|
||||
@Query(value = "SELECT p.id, COUNT(*) AS starCount \n" +
|
||||
" FROM starboard_post p \n" +
|
||||
" INNER JOIN starboard_post_reaction r ON p.id = r.post_id\n" +
|
||||
" INNER JOIN user_in_server usi ON usi.user_in_server_id = p.author_user_in_server_id\n" +
|
||||
" WHERE p.server_id = :serverId\n" +
|
||||
" AND p.ignored = false\n" +
|
||||
" AND usi.user_id = :userId\n" +
|
||||
" GROUP BY p.id \n" +
|
||||
" ORDER BY starCount DESC \n" +
|
||||
" LIMIT :count", nativeQuery = true)
|
||||
List<Long> getTopStarboardPostsForUser(Long serverId, Long userId, Integer count);
|
||||
|
||||
@Query(value = "SELECT COUNT(*) AS starCount\n" +
|
||||
"FROM starboard_post_reaction r \n" +
|
||||
" INNER JOIN starboard_post p ON p.id = r.post_id \n" +
|
||||
" INNER JOIN user_in_server usi ON usi.user_in_server_id = r.reactor_user_in_server_id \n" +
|
||||
" WHERE usi.user_id = :userId \n" +
|
||||
" AND p.ignored = false\n" +
|
||||
" AND r.server_id = :serverId", nativeQuery = true)
|
||||
Long getGivenStarsOfUserInServer(Long serverId, Long userId);
|
||||
|
||||
@Query(value = "SELECT COUNT(*) AS starCount\n" +
|
||||
" FROM starboard_post_reaction r \n" +
|
||||
" INNER JOIN starboard_post p ON p.id = r.post_id \n" +
|
||||
" INNER JOIN user_in_server usi ON usi.user_in_server_id = p.author_user_in_server_id \n" +
|
||||
" WHERE p.author_user_in_server_id = usi.user_in_server_id \n" +
|
||||
" AND usi.user_id = :userId \n" +
|
||||
" AND p.ignored = false\n" +
|
||||
" AND r.server_id = :serverId", nativeQuery = true)
|
||||
Long getReceivedStarsOfUserInServer(Long serverId, Long userId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.sheldan.abstracto.starboard.repository.result;
|
||||
|
||||
public interface StarStatsGuildUserResult {
|
||||
// this is the User in Server Id
|
||||
Long getUserId();
|
||||
Integer getStarCount();
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
package dev.sheldan.abstracto.starboard.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.UserInServerNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeature;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardPostTarget;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.model.template.*;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
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.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarboardServiceBean implements StarboardService {
|
||||
|
||||
public static final String STARBOARD_POST_TEMPLATE = "starboard_post";
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Autowired
|
||||
private StarboardPostReactorManagementService starboardPostReactorManagementService;
|
||||
|
||||
@Autowired
|
||||
private PostTargetManagement postTargetManagement;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Autowired
|
||||
private DefaultConfigManagementService defaultConfigManagementService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private StarboardServiceBean self;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createStarboardPost(CachedMessage message, List<AUserInAServer> userExceptAuthor, AUserInAServer userReacting, AUserInAServer starredUser) {
|
||||
Long starredUserId = starredUser.getUserInServerId();
|
||||
List<Long> userExceptAuthorIds = userExceptAuthor.stream().map(AUserInAServer::getUserInServerId).collect(Collectors.toList());
|
||||
return buildStarboardPostModel(message, userExceptAuthor.size()).thenCompose(starboardPostModel ->
|
||||
self.sendStarboardPostAndStore(message, starredUserId, userExceptAuthorIds, starboardPostModel)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletionStage<Void> sendStarboardPostAndStore(CachedMessage message, Long starredUserId, List<Long> userExceptAuthorIds, StarboardPostModel starboardPostModel) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(STARBOARD_POST_TEMPLATE, starboardPostModel);
|
||||
PostTarget starboard = postTargetManagement.getPostTarget(StarboardPostTarget.STARBOARD.getKey(), message.getServerId());
|
||||
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(messageToSend, StarboardPostTarget.STARBOARD, message.getServerId());
|
||||
Long starboardChannelId = starboard.getChannelReference().getId();
|
||||
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).thenAccept(aVoid ->
|
||||
self.persistPost(message, userExceptAuthorIds, completableFutures, starboardChannelId, starredUserId)
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void persistPost(CachedMessage message, List<Long> userExceptAuthorIds, List<CompletableFuture<Message>> completableFutures, Long starboardChannelId, Long starredUserId) {
|
||||
AUserInAServer innerStarredUser = userInServerManagementService.loadUserOptional(starredUserId).orElseThrow(() -> new UserInServerNotFoundException(starredUserId));
|
||||
AChannel starboardChannel = channelManagementService.loadChannel(starboardChannelId);
|
||||
Message message1 = completableFutures.get(0).join();
|
||||
AServerAChannelMessage aServerAChannelMessage = AServerAChannelMessage
|
||||
.builder()
|
||||
.messageId(message1.getIdLong())
|
||||
.channel(starboardChannel)
|
||||
.server(starboardChannel.getServer())
|
||||
.build();
|
||||
StarboardPost starboardPost = starboardPostManagementService.createStarboardPost(message, innerStarredUser, aServerAChannelMessage);
|
||||
log.info("Persisting starboard post in channel {} with message {} with {} reactors.", message1.getId(),starboardChannelId, userExceptAuthorIds.size());
|
||||
if(userExceptAuthorIds.isEmpty()) {
|
||||
log.warn("There are no user ids except the author for the reactions in post {} in guild {} for message {} in channel {}.", starboardPost.getId(), message.getChannelId(), message.getMessageId(), message.getChannelId());
|
||||
}
|
||||
userExceptAuthorIds.forEach(aLong -> {
|
||||
AUserInAServer user = userInServerManagementService.loadUserOptional(aLong).orElseThrow(() -> new UserInServerNotFoundException(aLong));
|
||||
starboardPostReactorManagementService.addReactor(starboardPost, user);
|
||||
});
|
||||
}
|
||||
|
||||
private CompletableFuture<StarboardPostModel> buildStarboardPostModel(CachedMessage message, Integer starCount) {
|
||||
return memberService.getMemberInServerAsync(message.getServerId(), message.getAuthor().getAuthorId()).thenApply(member -> {
|
||||
Optional<TextChannel> channel = channelService.getTextChannelFromServerOptional(message.getServerId(), message.getChannelId());
|
||||
Optional<Guild> guild = guildService.getGuildByIdOptional(message.getServerId());
|
||||
// TODO use model objects instead of building entity models
|
||||
AChannel aChannel = AChannel.builder().id(message.getChannelId()).build();
|
||||
AUser user = AUser.builder().id(message.getAuthor().getAuthorId()).build();
|
||||
String starLevelEmote = getAppropriateEmote(message.getServerId(), starCount);
|
||||
return StarboardPostModel
|
||||
.builder()
|
||||
.message(message)
|
||||
.author(member)
|
||||
.channel(channel.orElse(null))
|
||||
.aChannel(aChannel)
|
||||
.starCount(starCount)
|
||||
.guild(guild.orElse(null))
|
||||
.user(user)
|
||||
.starLevelEmote(starLevelEmote)
|
||||
.build();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> updateStarboardPost(StarboardPost post, CachedMessage message, List<AUserInAServer> userExceptAuthor) {
|
||||
int starCount = userExceptAuthor.size();
|
||||
log.info("Updating starboard post {} in server {} with reactors {}.", post.getId(), post.getSourceChannel().getServer().getId(), starCount);
|
||||
return buildStarboardPostModel(message, starCount).thenCompose(starboardPostModel -> {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(STARBOARD_POST_TEMPLATE, starboardPostModel);
|
||||
List<CompletableFuture<Message>> futures = postTargetService.editOrCreatedInPostTarget(post.getStarboardMessageId(), messageToSend, StarboardPostTarget.STARBOARD, message.getServerId());
|
||||
Long starboardPostId = post.getId();
|
||||
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(aVoid -> {
|
||||
Optional<StarboardPost> innerPost = starboardPostManagementService.findByStarboardPostId(starboardPostId);
|
||||
innerPost.ifPresent(starboardPost -> starboardPostManagementService.setStarboardPostMessageId(starboardPost, futures.get(0).join().getIdLong()));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteStarboardMessagePost(StarboardPost message) {
|
||||
AChannel starboardChannel = message.getStarboardChannel();
|
||||
log.info("Deleting starboard post {} in server {}", message.getId(), message.getSourceChannel().getServer().getId());
|
||||
messageService.deleteMessageInChannelInServer(starboardChannel.getServer().getId(), starboardChannel.getId(), message.getStarboardMessageId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<GuildStarStatsModel> retrieveStarStats(Long serverId) {
|
||||
int count = 3;
|
||||
List<CompletableFuture<StarStatsUser>> topStarGiverFutures = starboardPostReactorManagementService.retrieveTopStarGiver(serverId, count);
|
||||
List<CompletableFuture<StarStatsUser>> topStarReceiverFutures = starboardPostReactorManagementService.retrieveTopStarReceiver(serverId, count);
|
||||
List<CompletableFuture> allFutures = new ArrayList<>();
|
||||
allFutures.addAll(topStarGiverFutures);
|
||||
allFutures.addAll(topStarReceiverFutures);
|
||||
return FutureUtils.toSingleFuture(allFutures).thenApply(aVoid -> {
|
||||
List<StarboardPost> starboardPosts = starboardPostManagementService.retrieveTopPosts(serverId, count);
|
||||
List<StarStatsPost> starStatsPosts = starboardPosts.stream().map(this::fromStarboardPost).collect(Collectors.toList());
|
||||
Integer postCount = starboardPostManagementService.getPostCount(serverId);
|
||||
Integer reactionCount = starboardPostReactorManagementService.getStarCount(serverId);
|
||||
List<String> emotes = new ArrayList<>();
|
||||
for (int i = 1; i < count + 1; i++) {
|
||||
emotes.add(getStarboardRankingEmote(serverId, i));
|
||||
}
|
||||
List<StarStatsUser> topStarGivers = topStarGiverFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
|
||||
List<StarStatsUser> topStarReceiver = topStarReceiverFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
|
||||
return GuildStarStatsModel
|
||||
.builder()
|
||||
.badgeEmotes(emotes)
|
||||
.starGiver(topStarGivers)
|
||||
.starReceiver(topStarReceiver)
|
||||
.topPosts(starStatsPosts)
|
||||
.starredMessages(postCount)
|
||||
.totalStars(reactionCount)
|
||||
.build();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemberStarStatsModel retrieveStarStatsForMember(Member member) {
|
||||
int count = 3;
|
||||
Long receivedStars = starboardPostManagementService.retrieveReceivedStarsOfUserInServer(member.getGuild().getIdLong(), member.getIdLong());
|
||||
Long givenStars = starboardPostManagementService.retrieveGivenStarsOfUserInServer(member.getGuild().getIdLong(), member.getIdLong());
|
||||
List<StarboardPost> topPosts = starboardPostManagementService.retrieveTopPostsForUserInServer(member.getGuild().getIdLong(), member.getIdLong(), count);
|
||||
List<StarStatsPost> starStatsPosts = topPosts.stream().map(this::fromStarboardPost).collect(Collectors.toList());
|
||||
List<String> emotes = new ArrayList<>();
|
||||
for (int i = 1; i < count + 1; i++) {
|
||||
emotes.add(getStarboardRankingEmote(member.getGuild().getIdLong(), i));
|
||||
}
|
||||
return MemberStarStatsModel
|
||||
.builder()
|
||||
.member(member)
|
||||
.topPosts(starStatsPosts)
|
||||
.badgeEmotes(emotes)
|
||||
.receivedStars(receivedStars)
|
||||
.givenStars(givenStars)
|
||||
.build();
|
||||
}
|
||||
|
||||
public StarStatsPost fromStarboardPost(StarboardPost starboardPost) {
|
||||
AChannel channel = starboardPost.getStarboardChannel();
|
||||
return StarStatsPost
|
||||
.builder()
|
||||
.serverId(starboardPost.getServer().getId())
|
||||
.channelId(channel.getId())
|
||||
.messageId(starboardPost.getPostMessageId())
|
||||
.starCount(starboardPost.getReactions().size())
|
||||
.build();
|
||||
}
|
||||
|
||||
private String getStarboardRankingEmote(Long serverId, Integer position) {
|
||||
return emoteService.getUsableEmoteOrDefault(serverId, buildBadgeName(position));
|
||||
}
|
||||
|
||||
private String buildBadgeName(Integer position) {
|
||||
return StarboardFeature.STAR_BADGE_EMOTE_PREFIX + position;
|
||||
}
|
||||
|
||||
private String getAppropriateEmote(Long serverId, Integer starCount) {
|
||||
int maxLevels = defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LEVELS_CONFIG_KEY).getLongValue().intValue();
|
||||
for(int i = maxLevels; i > 0; i--) {
|
||||
String key = StarboardFeature.STAR_LVL_CONFIG_PREFIX + i;
|
||||
SystemConfigProperty defaultStars = defaultConfigManagementService.getDefaultConfig(key);
|
||||
Long starMinimum = configService.getLongValue(key, serverId, defaultStars.getLongValue());
|
||||
if(starCount >= starMinimum) {
|
||||
return emoteService.getUsableEmoteOrDefault(serverId, StarboardFeature.STAR_EMOTE_PREFIX + i);
|
||||
}
|
||||
}
|
||||
return emoteService.getUsableEmoteOrDefault(serverId, StarboardFeature.STAR_EMOTE_PREFIX);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package dev.sheldan.abstracto.starboard.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.repository.StarboardPostRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarboardPostManagementServiceBean implements StarboardPostManagementService {
|
||||
|
||||
@Autowired
|
||||
private StarboardPostRepository repository;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Override
|
||||
public StarboardPost createStarboardPost(CachedMessage starredMessage, AUserInAServer starredUser, AServerAChannelMessage starboardPost) {
|
||||
AChannel build = channelManagementService.loadChannel(starredMessage.getChannelId());
|
||||
StarboardPost post = StarboardPost
|
||||
.builder()
|
||||
.author(starredUser)
|
||||
.postMessageId(starredMessage.getMessageId())
|
||||
.sourceChannel(build)
|
||||
.ignored(false)
|
||||
.server(starboardPost.getServer())
|
||||
.starboardMessageId(starboardPost.getMessageId())
|
||||
.starboardChannel(starboardPost.getChannel())
|
||||
.starredDate(Instant.now())
|
||||
.build();
|
||||
log.info("Persisting starboard post for message {} in channel {} in server {} on starboard at message {} in channel {} and server {} of user {}.",
|
||||
starredMessage.getMessageId(), starredMessage.getChannelId(), starredMessage.getServerId(),
|
||||
starboardPost.getMessageId(), starboardPost.getChannel().getId(), starboardPost.getServer().getId(),
|
||||
starredUser.getUserReference().getId());
|
||||
repository.save(post);
|
||||
return post;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StarboardPost createStarboardPost(StarboardPost post) {
|
||||
return repository.save(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStarboardPostMessageId(StarboardPost post, Long messageId) {
|
||||
post.setStarboardMessageId(messageId);
|
||||
repository.save(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StarboardPost> retrieveTopPosts(Long serverId, Integer count) {
|
||||
List<StarboardPost> posts = retrieveAllPosts(serverId);
|
||||
posts.sort(Comparator.comparingInt(o -> o.getReactions().size()));
|
||||
Collections.reverse(posts);
|
||||
return posts.subList(0, Math.min(count, posts.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StarboardPost> retrieveTopPostsForUserInServer(Long serverId, Long userId, Integer count) {
|
||||
List<Long> topPostIds = repository.getTopStarboardPostsForUser(serverId, userId, count);
|
||||
return repository.findAllById(topPostIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long retrieveGivenStarsOfUserInServer(Long serverId, Long userId) {
|
||||
return repository.getGivenStarsOfUserInServer(serverId, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long retrieveReceivedStarsOfUserInServer(Long serverId, Long userId) {
|
||||
return repository.getReceivedStarsOfUserInServer(serverId, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StarboardPost> retrieveAllPosts(Long serverId) {
|
||||
return repository.findByServer_Id(serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPostCount(Long serverId) {
|
||||
return retrieveAllPosts(serverId).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<StarboardPost> findByMessageId(Long messageId) {
|
||||
return Optional.ofNullable(repository.findByPostMessageId(messageId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<StarboardPost> findByStarboardPostId(Long postId) {
|
||||
return Optional.ofNullable(repository.findByStarboardMessageId(postId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStarboardPostIgnored(Long messageId, Boolean newValue) {
|
||||
StarboardPost post = repository.findByStarboardMessageId(messageId);
|
||||
post.setIgnored(newValue);
|
||||
repository.save(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStarboardPost(Long messageId) {
|
||||
return repository.existsByStarboardMessageId(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePost(StarboardPost starboardPost) {
|
||||
starboardPost.getReactions().clear();
|
||||
repository.delete(starboardPost);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package dev.sheldan.abstracto.starboard.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.starboard.converter.StarStatsUserConverter;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPostReaction;
|
||||
import dev.sheldan.abstracto.starboard.model.template.StarStatsUser;
|
||||
import dev.sheldan.abstracto.starboard.repository.result.StarStatsGuildUserResult;
|
||||
import dev.sheldan.abstracto.starboard.repository.StarboardPostReactionRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarboardPostReactorManagementServiceBean implements StarboardPostReactorManagementService {
|
||||
|
||||
@Autowired
|
||||
private StarboardPostReactionRepository repository;
|
||||
|
||||
@Autowired
|
||||
private StarStatsUserConverter converter;
|
||||
|
||||
@Override
|
||||
public StarboardPostReaction addReactor(StarboardPost post, AUserInAServer user) {
|
||||
StarboardPostReaction reactor = StarboardPostReaction
|
||||
.builder()
|
||||
.starboardPost(post)
|
||||
.reactor(user)
|
||||
.server(user.getServerReference())
|
||||
.build();
|
||||
log.info("Persisting the reactor {} for starboard post {} in server {}.", user.getUserReference().getId(), post.getId(), user.getServerReference().getId());
|
||||
repository.save(reactor);
|
||||
return reactor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeReactor(StarboardPost post, AUserInAServer user) {
|
||||
log.info("Removing reactor {} from post {} in server {}.", user.getUserReference().getId(), post.getId(), user.getServerReference().getId());
|
||||
repository.deleteByReactorAndStarboardPost(user, post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeReactors(StarboardPost post) {
|
||||
log.info("Removing all {} reactors from starboard post {}", post.getReactions().size(), post.getId());
|
||||
repository.deleteByStarboardPost(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getStarCount(Long serverId) {
|
||||
return repository.getReactionCountByServer(serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<StarStatsUser>> retrieveTopStarGiver(Long serverId, Integer count) {
|
||||
List<StarStatsGuildUserResult> starGivers = repository.findTopStarGiverInServer(serverId, count);
|
||||
return converter.convertToStarStatsUser(starGivers, serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<StarStatsUser>> retrieveTopStarReceiver(Long serverId, Integer count) {
|
||||
List<StarStatsGuildUserResult> starReceivers = repository.retrieveTopStarReceiverInServer(serverId, count);
|
||||
return converter.convertToStarStatsUser(starReceivers, serverId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../dbchangelog-3.8.xsd" >
|
||||
<include file="starboard-tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="starboard-seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<property name="starboardFeature" value="(SELECT id FROM feature WHERE key = 'starboard')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="starboard-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="starStats"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${starboardFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<include file="default_emote.xml" relativeToChangelogFile="true"/>
|
||||
<include file="feature.xml" relativeToChangelogFile="true"/>
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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_default_emote-insert">
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="star"/>
|
||||
<column name="name" value="⭐"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="star1"/>
|
||||
<column name="name" value="⭐"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="star2"/>
|
||||
<column name="name" value="🌟"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="star3"/>
|
||||
<column name="name" value="💫"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="star4"/>
|
||||
<column name="name" value="🌠"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="starboardBadge1"/>
|
||||
<column name="name" value="🥇"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="starboardBadge2"/>
|
||||
<column name="name" value="🥈"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="starboardBadge3"/>
|
||||
<column name="name" value="🥉"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="starboard_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="starboard"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,69 @@
|
||||
<?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="ignored" type="BOOLEAN">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="post_message_id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="starboard_message_id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="starred_date" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="author_user_in_server_id" 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="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<createIndex indexName="idx_starboard_post_message" tableName="starboard_post">
|
||||
<column name="post_message_id"/>
|
||||
</createIndex>
|
||||
<createIndex indexName="idx_starboard_starboard_message" tableName="starboard_post">
|
||||
<column name="starboard_message_id"/>
|
||||
</createIndex>
|
||||
<createIndex indexName="idx_starboard_server" tableName="starboard_post">
|
||||
<column name="server_id"/>
|
||||
</createIndex>
|
||||
<addForeignKeyConstraint baseColumnNames="author_user_in_server_id" baseTableName="starboard_post" constraintName="fk_starboard_post_author_user_in_server_id" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<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"/>
|
||||
<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"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="starboard_post" constraintName="fk_starboard_post_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
|
||||
referencedTableName="server" validate="true"/>
|
||||
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS starboard_post_update_trigger ON starboard_post;
|
||||
CREATE TRIGGER starboard_post_update_trigger BEFORE UPDATE ON starboard_post FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS starboard_insert_trigger ON starboard_post;
|
||||
CREATE TRIGGER starboard_post_insert_trigger BEFORE INSERT ON starboard_post FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?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">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="reactor_user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="post_id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="reactor_user_in_server_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"/>
|
||||
<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"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="starboard_post_reaction" constraintName="fk_starboard_post_reaction_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS starboard_post_reaction_update_trigger ON starboard_post_reaction;
|
||||
CREATE TRIGGER starboard_post_reaction_update_trigger BEFORE UPDATE ON starboard_post_reaction FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS starboard_post_reaction_insert_trigger ON starboard_post_reaction;
|
||||
CREATE TRIGGER starboard_post_reaction_insert_trigger BEFORE INSERT ON starboard_post_reaction FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<include file="starboard_post.xml" relativeToChangelogFile="true"/>
|
||||
<include file="starboard_post_reaction.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog-3.8.xsd" >
|
||||
<include file="1.0-starboard/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,19 @@
|
||||
abstracto.systemConfigs.starLvl1.name=starLvl1
|
||||
abstracto.systemConfigs.starLvl1.longValue=5
|
||||
|
||||
abstracto.systemConfigs.starLvl2.name=starLvl2
|
||||
abstracto.systemConfigs.starLvl2.longValue=8
|
||||
|
||||
abstracto.systemConfigs.starLvl3.name=starLvl3
|
||||
abstracto.systemConfigs.starLvl3.longValue=13
|
||||
|
||||
abstracto.systemConfigs.starLvl4.name=starLvl4
|
||||
abstracto.systemConfigs.starLvl4.longValue=17
|
||||
|
||||
abstracto.systemConfigs.starLvls.name=starLvls
|
||||
abstracto.systemConfigs.starLvls.longValue=4
|
||||
|
||||
abstracto.featureFlags.starboard.featureName=starboard
|
||||
abstracto.featureFlags.starboard.enabled=false
|
||||
|
||||
abstracto.postTargets.starboard.name=starboard
|
||||
@@ -0,0 +1,63 @@
|
||||
package dev.sheldan.abstracto.starboard.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import dev.sheldan.abstracto.starboard.model.template.GuildStarStatsModel;
|
||||
import dev.sheldan.abstracto.starboard.model.template.MemberStarStatsModel;
|
||||
import dev.sheldan.abstracto.starboard.service.StarboardService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarStatsTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarStats testUnit;
|
||||
|
||||
@Mock
|
||||
private StarboardService starboardService;
|
||||
|
||||
@Mock
|
||||
private ChannelService channelService;
|
||||
|
||||
@Test
|
||||
public void executeCommand() {
|
||||
CommandContext noParameters = CommandTestUtilities.getNoParameters();
|
||||
GuildStarStatsModel guildStarStatsModel = Mockito.mock(GuildStarStatsModel.class);
|
||||
when(starboardService.retrieveStarStats(noParameters.getGuild().getIdLong())).thenReturn(CompletableFuture.completedFuture(guildStarStatsModel));
|
||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(noParameters);
|
||||
verify(channelService, times(1)).sendEmbedTemplateInTextChannelList(StarStats.STARSTATS_RESPONSE_TEMPLATE, guildStarStatsModel, noParameters.getChannel());
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeCommandForMember() {
|
||||
Member member = Mockito.mock(Member.class);
|
||||
CommandContext memberParameter = CommandTestUtilities.getWithParameters(Arrays.asList(member));
|
||||
MemberStarStatsModel model = Mockito.mock(MemberStarStatsModel.class);
|
||||
when(starboardService.retrieveStarStatsForMember(member)).thenReturn(model);
|
||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(memberParameter);
|
||||
verify(channelService, times(1)).sendEmbedTemplateInTextChannelList(StarStats.STARSTATS_SINGLE_MEMBER_RESPONSE_TEMPLATE, model, memberParameter.getChannel());
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void validateCommand() {
|
||||
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package dev.sheldan.abstracto.starboard.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.starboard.model.template.StarStatsUser;
|
||||
import dev.sheldan.abstracto.starboard.repository.result.StarStatsGuildUserResult;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarStatsUserConverterTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarStatsUserConverter testUnit;
|
||||
|
||||
@Mock
|
||||
private MemberService memberService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private StarStatsUserConverter self;
|
||||
|
||||
@Test
|
||||
public void testConversionOfMultipleItems() {
|
||||
Long serverId = 5L;
|
||||
Long firstUserId = 5L;
|
||||
Long secondUserId = 9L;
|
||||
List<StarStatsGuildUserResult> results = new ArrayList<>();
|
||||
StarStatsGuildUserResult firstResult = Mockito.mock(StarStatsGuildUserResult.class);
|
||||
Member firstMember = Mockito.mock(Member.class);
|
||||
AUserInAServer firstUser = Mockito.mock(AUserInAServer.class);
|
||||
AUser firstAUser = Mockito.mock(AUser.class);
|
||||
when(firstAUser.getId()).thenReturn(firstUserId);
|
||||
when(firstUser.getUserReference()).thenReturn(firstAUser);
|
||||
when(userInServerManagementService.loadOrCreateUser(firstUserId)).thenReturn(firstUser);
|
||||
when(memberService.getMemberInServerAsync(serverId, firstUserId)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
when(firstResult.getUserId()).thenReturn(firstUserId);
|
||||
results.add(firstResult);
|
||||
StarStatsGuildUserResult secondResult = Mockito.mock(StarStatsGuildUserResult.class);
|
||||
Member secondMember = Mockito.mock(Member.class);
|
||||
AUserInAServer secondUser = Mockito.mock(AUserInAServer.class);
|
||||
AUser secondAUser = Mockito.mock(AUser.class);
|
||||
when(secondAUser.getId()).thenReturn(secondUserId);
|
||||
when(secondUser.getUserReference()).thenReturn(secondAUser);
|
||||
when(userInServerManagementService.loadOrCreateUser(secondUserId)).thenReturn(secondUser);
|
||||
when(memberService.getMemberInServerAsync(serverId, secondUserId)).thenReturn(CompletableFuture.completedFuture(secondMember));
|
||||
|
||||
when(secondResult.getUserId()).thenReturn(secondUserId);
|
||||
results.add(secondResult);
|
||||
|
||||
testUnit.convertToStarStatsUser(results, serverId);
|
||||
ArgumentCaptor<StarStatsGuildUserResult> resultArgumentCaptor = ArgumentCaptor.forClass(StarStatsGuildUserResult.class);
|
||||
ArgumentCaptor<Member> memberArgumentCaptor = ArgumentCaptor.forClass(Member.class);
|
||||
verify(self, times(2)).loadStarStatsUser(resultArgumentCaptor.capture(), memberArgumentCaptor.capture());
|
||||
List<StarStatsGuildUserResult> resultCaptorValues = resultArgumentCaptor.getAllValues();
|
||||
Assert.assertEquals(2, resultCaptorValues.size());
|
||||
Assert.assertEquals(firstResult, resultCaptorValues.get(0));
|
||||
Assert.assertEquals(secondResult, resultCaptorValues.get(1));
|
||||
List<Member> memberCaptorValues = memberArgumentCaptor.getAllValues();
|
||||
Assert.assertEquals(2, memberCaptorValues.size());
|
||||
Assert.assertEquals(firstMember, memberCaptorValues.get(0));
|
||||
Assert.assertEquals(secondMember, memberCaptorValues.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConversionOfEmptyList() {
|
||||
Long serverId = 5L;
|
||||
List<StarStatsGuildUserResult> results = new ArrayList<>();
|
||||
|
||||
List<CompletableFuture<StarStatsUser>> starStatsUsers = testUnit.convertToStarStatsUser(results, serverId);
|
||||
verify(memberService, times(0)).getMemberInServer(eq(serverId), anyLong());
|
||||
Assert.assertEquals(0, starStatsUsers.size());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedAuthor;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeature;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.StarboardService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarboardListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarboardListener testUnit;
|
||||
|
||||
@Mock
|
||||
private ConfigManagementService configManagementService;
|
||||
|
||||
@Mock
|
||||
private StarboardService starboardService;
|
||||
|
||||
@Mock
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Mock
|
||||
private StarboardPostReactorManagementService starboardPostReactorManagementService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Mock
|
||||
private MetricService metricService;
|
||||
|
||||
@Mock
|
||||
private CachedReactions cachedReaction;
|
||||
|
||||
@Mock
|
||||
private CachedMessage cachedMessage;
|
||||
|
||||
@Mock
|
||||
private ServerUser serverUserActing;
|
||||
|
||||
@Mock
|
||||
private CachedAuthor cachedAuthor;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer userInServerActing;
|
||||
|
||||
@Mock
|
||||
private AUser userActing;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer userInAServer;
|
||||
|
||||
@Mock
|
||||
private AUser aUser;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private StarboardPost post;
|
||||
|
||||
@Mock
|
||||
private CachedEmote cachedEmote;
|
||||
|
||||
@Mock
|
||||
private AEmote starEmote;
|
||||
|
||||
private static final Long MESSAGE_ID = 5L;
|
||||
private static final Long SERVER_ID = 6L;
|
||||
private static final Long AUTHOR_ID = 4L;
|
||||
private static final Long USER_ACTING_ID = 7L;
|
||||
|
||||
@Test
|
||||
public void testAuthorAddingStar() {
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(serverUserActing.getUserId()).thenReturn(AUTHOR_ID);
|
||||
testUnit.executeReactionAdded(cachedMessage, cachedReaction, serverUserActing);
|
||||
verify(emoteService, times(0)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingWrongEmote() {
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
setupWrongEmote(SERVER_ID, AUTHOR_ID, starEmote);
|
||||
when(cachedReaction.getEmote()).thenReturn(cachedEmote);
|
||||
when(emoteService.compareCachedEmoteWithAEmote(cachedEmote, starEmote)).thenReturn(false);
|
||||
testUnit.executeReactionAdded(cachedMessage, cachedReaction, serverUserActing);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(0)).getReactionFromMessageByEmote(any(CachedMessage.class), eq(starEmote));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingEmoteToExistingPostButNowBelowThreshold() {
|
||||
Long requiredStars = 5L;
|
||||
setupActingAndAuthor();
|
||||
executeAddingTest(requiredStars, post);
|
||||
verify(starboardService, times(1)).deleteStarboardMessagePost(post);
|
||||
verify(starboardPostManagementService, times(1)).removePost(post);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingEmoteBelowThreshold() {
|
||||
Long requiredStars = 5L;
|
||||
setupActingAndAuthor();
|
||||
executeAddingTest(requiredStars, null);
|
||||
verify(starboardService, times(0)).deleteStarboardMessagePost(any(StarboardPost.class));
|
||||
verify(starboardPostManagementService, times(0)).removePost(any(StarboardPost.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingEmoteReachingThreshold() {
|
||||
Long requiredStars = 1L;
|
||||
setupActingAndAuthor();
|
||||
executeAddingTest(requiredStars, null);
|
||||
verify(metricService, times(2)).incrementCounter(any());
|
||||
verify(starboardService, times(1)).createStarboardPost(any(CachedMessage.class), anyList(), eq(userInServerActing), eq(userInAServer));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingEmoteToExistingPost() {
|
||||
Long requiredStars = 1L;
|
||||
setupActingAndAuthor();
|
||||
executeAddingTest(requiredStars, post);
|
||||
verify(metricService, times(1)).incrementCounter(any());
|
||||
verify(starboardService, times(1)).updateStarboardPost(eq(post), any(CachedMessage.class), anyList());
|
||||
verify(starboardPostReactorManagementService, times(1)).addReactor(post, userInServerActing);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthorRemovingReaction() {
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(serverUserActing.getUserId()).thenReturn(AUTHOR_ID);
|
||||
testUnit.executeReactionRemoved(cachedMessage, cachedReaction, serverUserActing);
|
||||
verify(emoteService, times(0)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovingWrongEmote() {
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
setupWrongEmote(SERVER_ID, AUTHOR_ID, starEmote);
|
||||
testUnit.executeReactionRemoved(cachedMessage, cachedReaction, serverUserActing);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(0)).getReactionFromMessageByEmote(any(CachedMessage.class), eq(starEmote));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactionFromExistingPostBelowThreshold() {
|
||||
Long requiredStars = 5L;
|
||||
List<ServerUser> remainingUsers = Arrays.asList(serverUserActing);
|
||||
setupActingAndAuthor();
|
||||
executeRemovalTest(requiredStars, remainingUsers);
|
||||
verify(starboardService, times(1)).deleteStarboardMessagePost(eq(post));
|
||||
verify(starboardPostManagementService, times(1)).removePost(eq(post));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactionFromExistingPostAboveThreshold() {
|
||||
Long requiredStars = 0L;
|
||||
List<ServerUser> remainingUsers = Arrays.asList(serverUserActing);
|
||||
setupActingAndAuthor();
|
||||
when(userInServerManagementService.loadOrCreateUser(serverUserActing)).thenReturn(userInServerActing);
|
||||
executeRemovalTest(requiredStars, remainingUsers);
|
||||
verify(metricService, times(1)).incrementCounter(any());
|
||||
verify(starboardService, times(0)).deleteStarboardMessagePost(eq(post));
|
||||
verify(starboardPostManagementService, times(0)).removePost(eq(post));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactionFromExistingPostTriggeringThreshold() {
|
||||
Long requiredStars = 1L;
|
||||
ArrayList<ServerUser> usersRemaining = new ArrayList<>();
|
||||
setupActingAndAuthor();
|
||||
executeRemovalTest(requiredStars, usersRemaining);
|
||||
verify(metricService, times(2)).incrementCounter(any());
|
||||
verify(starboardService, times(1)).deleteStarboardMessagePost(eq(post));
|
||||
verify(starboardPostManagementService, times(1)).removePost(eq(post));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReactionsClearedOnStarredMessage() {
|
||||
executeClearingTest(Mockito.mock(StarboardPost.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReactionsClearedOnNotStarredMessage() {
|
||||
executeClearingTest(null);
|
||||
}
|
||||
|
||||
private void setupActingAndAuthor() {
|
||||
when(userInServerActing.getUserReference()).thenReturn(userActing);
|
||||
when(userActing.getId()).thenReturn(USER_ACTING_ID);
|
||||
when(userInAServer.getServerReference()).thenReturn(server);
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
when(userInAServer.getUserReference()).thenReturn(aUser);
|
||||
when(aUser.getId()).thenReturn(AUTHOR_ID);
|
||||
}
|
||||
|
||||
|
||||
private void executeClearingTest(StarboardPost post) {
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(starboardPostManagementService.findByMessageId(MESSAGE_ID)).thenReturn(Optional.ofNullable(post));
|
||||
testUnit.executeReactionCleared(cachedMessage);
|
||||
int callCount = post != null ? 1 : 0;
|
||||
verify(starboardPostReactorManagementService, times(callCount)).removeReactors(post);
|
||||
verify(starboardService, times(callCount)).deleteStarboardMessagePost(eq(post));
|
||||
verify(starboardPostManagementService, times(callCount)).removePost(eq(post));
|
||||
}
|
||||
|
||||
|
||||
private void executeRemovalTest(Long requiredStars, List<ServerUser> remainingUsers) {
|
||||
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(cachedReaction.getEmote()).thenReturn(cachedEmote);
|
||||
when(emoteService.compareCachedEmoteWithAEmote(cachedEmote, starEmote)).thenReturn(true);
|
||||
when(emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID)).thenReturn(starEmote);
|
||||
CachedReactions reaction = Mockito.mock(CachedReactions.class);
|
||||
when(reaction.getUsers()).thenReturn(remainingUsers);
|
||||
when(emoteService.getReactionFromMessageByEmote(cachedMessage, starEmote)).thenReturn(Optional.of(reaction));
|
||||
when(starboardPostManagementService.findByMessageId(MESSAGE_ID)).thenReturn(Optional.ofNullable(post));
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, AUTHOR_ID)).thenReturn(userInAServer);
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
when(serverUserActing.getServerId()).thenReturn(SERVER_ID);
|
||||
if(!remainingUsers.isEmpty()) {
|
||||
when(userInServerManagementService.loadUserOptional(SERVER_ID, USER_ACTING_ID)).thenReturn(Optional.of(userInServerActing));
|
||||
}
|
||||
AConfig starRequirementConfig = Mockito.mock(AConfig.class);
|
||||
when(starRequirementConfig.getLongValue()).thenReturn(requiredStars);
|
||||
when(configManagementService.loadConfig(SERVER_ID, StarboardListener.FIRST_LEVEL_THRESHOLD_KEY)).thenReturn(starRequirementConfig);
|
||||
testUnit.executeReactionRemoved(cachedMessage, cachedReaction, serverUserActing);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(1)).getReactionFromMessageByEmote(cachedMessage, starEmote);
|
||||
}
|
||||
|
||||
private void executeAddingTest(Long requiredStars, StarboardPost postToUse) {
|
||||
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(cachedReaction.getEmote()).thenReturn(cachedEmote);
|
||||
when(emoteService.compareCachedEmoteWithAEmote(cachedEmote, starEmote)).thenReturn(true);
|
||||
when(emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID)).thenReturn(starEmote);
|
||||
CachedReactions reaction = Mockito.mock(CachedReactions.class);
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
when(serverUserActing.getServerId()).thenReturn(SERVER_ID);
|
||||
when(reaction.getUsers()).thenReturn(Arrays.asList(serverUserActing));
|
||||
when(emoteService.getReactionFromMessageByEmote(cachedMessage, starEmote)).thenReturn(Optional.of(reaction));
|
||||
when(starboardPostManagementService.findByMessageId(MESSAGE_ID)).thenReturn(Optional.ofNullable(postToUse));
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, AUTHOR_ID)).thenReturn(userInAServer);
|
||||
when(userInServerManagementService.loadOrCreateUser(serverUserActing)).thenReturn(userInServerActing);
|
||||
when(userInServerManagementService.loadUserOptional(SERVER_ID, USER_ACTING_ID)).thenReturn(Optional.of(userInServerActing));
|
||||
AConfig starRequirementConfig = Mockito.mock(AConfig.class);
|
||||
when(starRequirementConfig.getLongValue()).thenReturn(requiredStars);
|
||||
when(configManagementService.loadConfig(SERVER_ID, StarboardListener.FIRST_LEVEL_THRESHOLD_KEY)).thenReturn(starRequirementConfig);
|
||||
testUnit.executeReactionAdded(cachedMessage, cachedReaction, serverUserActing);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(1)).getReactionFromMessageByEmote(cachedMessage, starEmote);
|
||||
}
|
||||
|
||||
private void setupWrongEmote(Long serverId, Long authorId, AEmote starEmote) {
|
||||
when(cachedMessage.getServerId()).thenReturn(serverId);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(authorId);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(cachedReaction.getEmote()).thenReturn(cachedEmote);
|
||||
when(emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, serverId)).thenReturn(starEmote);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarboardPostDeletedListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarboardPostDeletedListener testUnit;
|
||||
|
||||
@Mock
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Test
|
||||
public void deleteNonStarboardPost() {
|
||||
Long messageId = 4L;
|
||||
when(starboardPostManagementService.findByStarboardPostId(messageId)).thenReturn(Optional.empty());
|
||||
CachedMessage cachedMessage = Mockito.mock(CachedMessage.class);
|
||||
when(cachedMessage.getMessageId()).thenReturn(messageId);
|
||||
testUnit.execute(cachedMessage);
|
||||
verify( starboardPostManagementService, times(0)).setStarboardPostIgnored(messageId, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteStarboardPost() {
|
||||
Long messageId = 4L;
|
||||
Long postMessageId = 5L;
|
||||
Long serverId = 3L;
|
||||
AChannel sourceChannel = Mockito.mock(AChannel.class);
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
when(post.getSourceChannel()) .thenReturn(sourceChannel);
|
||||
when(post.getPostMessageId()).thenReturn(postMessageId);
|
||||
when(starboardPostManagementService.findByStarboardPostId(messageId)).thenReturn(Optional.of(post));
|
||||
CachedMessage cachedMessage = Mockito.mock(CachedMessage.class);
|
||||
when(cachedMessage.getServerId()).thenReturn(serverId);
|
||||
when(cachedMessage.getMessageId()).thenReturn(messageId);
|
||||
testUnit.execute(cachedMessage);
|
||||
verify( starboardPostManagementService, times(1)).setStarboardPostIgnored(messageId, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
package dev.sheldan.abstracto.starboard.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.UserInServerNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedAuthor;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeature;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardPostTarget;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPostReaction;
|
||||
import dev.sheldan.abstracto.starboard.model.template.*;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarboardServiceBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarboardServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private GuildService guildService;
|
||||
|
||||
@Mock
|
||||
private ChannelService channelService;
|
||||
|
||||
@Mock
|
||||
private MemberService memberService;
|
||||
|
||||
@Mock
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Mock
|
||||
private TemplateService templateService;
|
||||
|
||||
@Mock
|
||||
private ConfigService configService;
|
||||
|
||||
@Mock
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Mock
|
||||
private StarboardPostReactorManagementService starboardPostReactorManagementService;
|
||||
|
||||
@Mock
|
||||
private DefaultConfigManagementService defaultConfigManagementService;
|
||||
|
||||
@Mock
|
||||
private PostTargetManagement postTargetManagement;
|
||||
|
||||
@Mock
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private MessageService messageService;
|
||||
|
||||
@Mock
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Mock
|
||||
private StarboardServiceBean self;
|
||||
|
||||
@Mock
|
||||
private Guild guild;
|
||||
|
||||
@Mock
|
||||
private Message sendPost;
|
||||
|
||||
@Mock
|
||||
private TextChannel mockedTextChannel;
|
||||
|
||||
@Mock
|
||||
private Member starredMember;
|
||||
|
||||
@Mock
|
||||
private AChannel starboardChannel;
|
||||
|
||||
@Mock
|
||||
private MessageToSend messageToSend;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
private static final Long STARRED_USER_ID = 5L;
|
||||
private static final Long STARRED_SERVER_USER_ID = 2L;
|
||||
private static final Long SERVER_ID = 6L;
|
||||
private static final Long STARBOARD_CHANNEL_ID = 8L;
|
||||
private static final Long FIRST_USER_IN_SERVER_ID = 3L;
|
||||
private static final Long SECOND_USER_IN_SERVER_ID = 9L;
|
||||
private static final Long CHANNEL_ID = 10L;
|
||||
private static final Long MESSAGE_ID = 11L;
|
||||
private static final Long SECOND_MESSAGE_ID = 12L;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<AUserInAServer> userInAServerArgumentCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<StarboardPostModel> starboardPostModelArgumentCaptor;
|
||||
|
||||
@Test
|
||||
public void testCreateStarboardPost() {
|
||||
List<AUserInAServer> userExceptAuthor = new ArrayList<>();
|
||||
AUserInAServer firstUserExceptAuthor = Mockito.mock(AUserInAServer.class);
|
||||
userExceptAuthor.add(firstUserExceptAuthor);
|
||||
AUserInAServer secondUserExceptAuthor = Mockito.mock(AUserInAServer.class);
|
||||
userExceptAuthor.add(secondUserExceptAuthor);
|
||||
AUserInAServer userReacting = Mockito.mock(AUserInAServer.class);
|
||||
AUserInAServer starredUser = Mockito.mock(AUserInAServer.class);
|
||||
when(starredUser.getUserInServerId()).thenReturn(STARRED_SERVER_USER_ID);
|
||||
CachedAuthor cachedAuthor = Mockito.mock(CachedAuthor.class);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(STARRED_USER_ID);
|
||||
CachedMessage message = Mockito.mock(CachedMessage.class);
|
||||
when(message.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(message.getServerId()).thenReturn(SERVER_ID);
|
||||
when(message.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
Member authorMember = Mockito.mock(Member.class);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, STARRED_USER_ID)).thenReturn(CompletableFuture.completedFuture(authorMember));
|
||||
when(channelService.getTextChannelFromServerOptional(SERVER_ID, CHANNEL_ID)).thenReturn(Optional.of(mockedTextChannel));
|
||||
when(guildService.getGuildByIdOptional(SERVER_ID)).thenReturn(Optional.of(guild));
|
||||
SystemConfigProperty config = Mockito.mock(SystemConfigProperty.class);
|
||||
Long defaultValue = 3L;
|
||||
when(config.getLongValue()).thenReturn(defaultValue);
|
||||
when(defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LEVELS_CONFIG_KEY)).thenReturn(config);
|
||||
when(configService.getLongValue(StarboardFeature.STAR_LVL_CONFIG_PREFIX + "2", SERVER_ID, defaultValue)).thenReturn(2L);
|
||||
when(configService.getLongValue(StarboardFeature.STAR_LVL_CONFIG_PREFIX + "3", SERVER_ID, defaultValue)).thenReturn(3L);
|
||||
when(defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LVL_CONFIG_PREFIX + "2")).thenReturn(config);
|
||||
when(defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LVL_CONFIG_PREFIX + "3")).thenReturn(config);
|
||||
when(emoteService.getUsableEmoteOrDefault(SERVER_ID, StarboardFeature.STAR_EMOTE_PREFIX + "2")).thenReturn("b");
|
||||
when(self.sendStarboardPostAndStore(eq(message), eq(STARRED_SERVER_USER_ID), anyList(), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<Void> createPostFuture = testUnit.createStarboardPost(message, userExceptAuthor, userReacting, starredUser);
|
||||
createPostFuture.join();
|
||||
Assert.assertFalse(createPostFuture.isCompletedExceptionally());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendStarboard() {
|
||||
CachedMessage message = Mockito.mock(CachedMessage.class);
|
||||
when(message.getServerId()).thenReturn(SERVER_ID);
|
||||
StarboardPostModel model = Mockito.mock(StarboardPostModel.class);
|
||||
when(templateService.renderEmbedTemplate(StarboardServiceBean.STARBOARD_POST_TEMPLATE, model)).thenReturn(messageToSend);
|
||||
PostTarget postTarget = Mockito.mock(PostTarget.class);
|
||||
when(postTarget.getChannelReference()).thenReturn(starboardChannel);
|
||||
when(starboardChannel.getId()).thenReturn(STARBOARD_CHANNEL_ID);
|
||||
when(postTargetManagement.getPostTarget(StarboardPostTarget.STARBOARD.getKey(), SERVER_ID)).thenReturn(postTarget);
|
||||
when(postTargetService.sendEmbedInPostTarget(messageToSend, StarboardPostTarget.STARBOARD, SERVER_ID)).thenReturn(Arrays.asList(CompletableFuture.completedFuture(null)));
|
||||
ArrayList<Long> userExceptAuthorIds = new ArrayList<>();
|
||||
testUnit.sendStarboardPostAndStore(message, STARRED_USER_ID, userExceptAuthorIds, model);
|
||||
verify(self, times(1)).persistPost(eq(message), eq(userExceptAuthorIds), any(), eq(STARBOARD_CHANNEL_ID), eq(STARRED_USER_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistPostWithTwoReactors() {
|
||||
AUserInAServer userReacting = Mockito.mock(AUserInAServer.class);
|
||||
AUserInAServer starredUser = Mockito.mock(AUserInAServer.class);
|
||||
CachedMessage message = Mockito.mock(CachedMessage.class);
|
||||
List<Long> userExceptAuthorIds = Arrays.asList(FIRST_USER_IN_SERVER_ID, SECOND_USER_IN_SERVER_ID);
|
||||
List<CompletableFuture<Message>> futures = Arrays.asList(CompletableFuture.completedFuture(sendPost));
|
||||
when(userInServerManagementService.loadUserOptional(STARRED_SERVER_USER_ID)).thenReturn(Optional.of(starredUser));
|
||||
when(userInServerManagementService.loadUserOptional(FIRST_USER_IN_SERVER_ID)).thenReturn(Optional.of(userReacting));
|
||||
when(userReacting.getUserInServerId()).thenReturn(FIRST_USER_IN_SERVER_ID);
|
||||
AChannel channel = Mockito.mock(AChannel.class);
|
||||
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(channel);
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
when(starboardPostManagementService.createStarboardPost(eq(message), eq(starredUser), any(AServerAChannelMessage.class))).thenReturn(post);
|
||||
AUserInAServer secondStarrerUserObj = Mockito.mock(AUserInAServer.class);
|
||||
when(userInServerManagementService.loadUserOptional(SECOND_USER_IN_SERVER_ID)).thenReturn(Optional.of(secondStarrerUserObj));
|
||||
when(secondStarrerUserObj.getUserInServerId()).thenReturn(SECOND_USER_IN_SERVER_ID);
|
||||
testUnit.persistPost(message, userExceptAuthorIds, futures, CHANNEL_ID, STARRED_SERVER_USER_ID);
|
||||
verify(starboardPostReactorManagementService, times(2)).addReactor(eq(post), userInAServerArgumentCaptor.capture());
|
||||
List<AUserInAServer> addedReactors = userInAServerArgumentCaptor.getAllValues();
|
||||
Assert.assertEquals(FIRST_USER_IN_SERVER_ID, addedReactors.get(0).getUserInServerId());
|
||||
Assert.assertEquals(SECOND_USER_IN_SERVER_ID, addedReactors.get(1).getUserInServerId());
|
||||
Assert.assertEquals(2, addedReactors.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateStarboardPost() {
|
||||
Long newPostId = 37L;
|
||||
Long oldPostId = 36L;
|
||||
AChannel sourceChannel = Mockito.mock(AChannel.class);
|
||||
when(sourceChannel.getServer()).thenReturn(server);
|
||||
CachedMessage message = Mockito.mock(CachedMessage.class);
|
||||
when(message.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(message.getServerId()).thenReturn(SERVER_ID);
|
||||
CachedAuthor author = Mockito.mock(CachedAuthor.class);
|
||||
when(author.getAuthorId()).thenReturn(STARRED_USER_ID);
|
||||
when(message.getAuthor()).thenReturn(author);
|
||||
Long starboardPostId = 47L;
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
when(post.getStarboardMessageId()).thenReturn(oldPostId);
|
||||
when(post.getSourceChannel()).thenReturn(sourceChannel);
|
||||
when(post.getId()).thenReturn(starboardPostId);
|
||||
MessageToSend postMessage = Mockito.mock(MessageToSend.class);
|
||||
when(templateService.renderEmbedTemplate(eq(StarboardServiceBean.STARBOARD_POST_TEMPLATE), starboardPostModelArgumentCaptor.capture())).thenReturn(postMessage);
|
||||
when(postTargetService.editOrCreatedInPostTarget(oldPostId, postMessage, StarboardPostTarget.STARBOARD, SERVER_ID)).thenReturn(Arrays.asList(CompletableFuture.completedFuture(sendPost)));
|
||||
when(sendPost.getIdLong()).thenReturn(newPostId);
|
||||
SystemConfigProperty config = Mockito.mock(SystemConfigProperty.class);
|
||||
when(config.getLongValue()).thenReturn(1L);
|
||||
when(defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LEVELS_CONFIG_KEY)).thenReturn(config);
|
||||
when(defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LVL_CONFIG_PREFIX + 1)).thenReturn(config);
|
||||
when(starboardPostManagementService.findByStarboardPostId(starboardPostId)).thenReturn(Optional.of(post));
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, STARRED_USER_ID)).thenReturn(CompletableFuture.completedFuture(starredMember));
|
||||
List<AUserInAServer > userExceptAuthor = new ArrayList<>();
|
||||
CompletableFuture<Void> future = testUnit.updateStarboardPost(post, message, userExceptAuthor);
|
||||
future.join();
|
||||
Assert.assertFalse(future.isCompletedExceptionally());
|
||||
verify(postTargetService, times(1)).editOrCreatedInPostTarget(oldPostId, postMessage, StarboardPostTarget.STARBOARD, SERVER_ID);
|
||||
verify(starboardPostManagementService, times(1)).setStarboardPostMessageId(post, newPostId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteStarboardMessagePost() {
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
when(post.getStarboardMessageId()).thenReturn(MESSAGE_ID);
|
||||
AChannel channel = Mockito.mock(AChannel.class);
|
||||
when(channel.getServer()).thenReturn(server);
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
when(channel.getId()).thenReturn(CHANNEL_ID);
|
||||
when(post.getSourceChannel()).thenReturn(channel);
|
||||
when(post.getStarboardChannel()).thenReturn(channel);
|
||||
testUnit.deleteStarboardMessagePost(post);
|
||||
verify(messageService, times(1)).deleteMessageInChannelInServer(SERVER_ID, CHANNEL_ID, MESSAGE_ID);
|
||||
}
|
||||
|
||||
@Test(expected = UserInServerNotFoundException.class)
|
||||
public void testPersistingOfNotFoundStarredUser() {
|
||||
when(userInServerManagementService.loadUserOptional(SECOND_USER_IN_SERVER_ID)).thenReturn(Optional.empty());
|
||||
CachedMessage message = Mockito.mock(CachedMessage.class);
|
||||
List<Long> userExceptAuthorIds = Arrays.asList(FIRST_USER_IN_SERVER_ID);
|
||||
List<CompletableFuture<Message>> futures = Arrays.asList(CompletableFuture.completedFuture(sendPost));
|
||||
testUnit.persistPost(message, userExceptAuthorIds, futures, CHANNEL_ID, SECOND_USER_IN_SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveStarStats() {
|
||||
Integer limit = 3;
|
||||
AChannel channel = Mockito.mock(AChannel.class);
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
StarboardPostReaction reaction = Mockito.mock(StarboardPostReaction.class);
|
||||
StarboardPost post1 = Mockito.mock(StarboardPost.class);
|
||||
when(post1.getReactions()).thenReturn(Arrays.asList(reaction));
|
||||
when(post1.getPostMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(post1.getServer()).thenReturn(server);
|
||||
when(post1.getStarboardChannel()).thenReturn(channel);
|
||||
StarboardPost post2 = Mockito.mock(StarboardPost.class);
|
||||
when(post2.getPostMessageId()).thenReturn(SECOND_MESSAGE_ID);
|
||||
when(post2.getReactions()).thenReturn(new ArrayList<>());
|
||||
when(post2.getServer()).thenReturn(server);
|
||||
when(post2.getStarboardChannel()).thenReturn(channel);
|
||||
List<StarboardPost> topPosts = Arrays.asList(post1, post2);
|
||||
when(starboardPostManagementService.retrieveTopPosts(SERVER_ID, limit)).thenReturn(topPosts);
|
||||
CompletableFuture<StarStatsUser> statsUser = CompletableFuture.completedFuture(Mockito.mock(StarStatsUser.class));
|
||||
CompletableFuture<StarStatsUser> statsUser2 = CompletableFuture.completedFuture(Mockito.mock(StarStatsUser.class));
|
||||
List<CompletableFuture<StarStatsUser>> topGiver = Arrays.asList(statsUser, statsUser2);
|
||||
when(starboardPostReactorManagementService.retrieveTopStarGiver(SERVER_ID, limit)).thenReturn(topGiver);
|
||||
when(starboardPostReactorManagementService.retrieveTopStarReceiver(SERVER_ID, limit)).thenReturn(topGiver);
|
||||
when(starboardPostManagementService.getPostCount(SERVER_ID)).thenReturn(50);
|
||||
when(starboardPostReactorManagementService.getStarCount(SERVER_ID)).thenReturn(500);
|
||||
when(emoteService.getUsableEmoteOrDefault(SERVER_ID, "starboardBadge1")).thenReturn("1");
|
||||
when(emoteService.getUsableEmoteOrDefault(SERVER_ID, "starboardBadge2")).thenReturn("2");
|
||||
when(emoteService.getUsableEmoteOrDefault(SERVER_ID, "starboardBadge3")).thenReturn("3");
|
||||
CompletableFuture<GuildStarStatsModel> modelFuture = testUnit.retrieveStarStats(SERVER_ID);
|
||||
GuildStarStatsModel model = modelFuture.join();
|
||||
List<String> badgeEmotes = model.getBadgeEmotes();
|
||||
Assert.assertEquals(limit.intValue(), badgeEmotes.size());
|
||||
Assert.assertEquals("1", badgeEmotes.get(0));
|
||||
Assert.assertEquals("2", badgeEmotes.get(1));
|
||||
Assert.assertEquals("3", badgeEmotes.get(2));
|
||||
Assert.assertEquals(500, model.getTotalStars().intValue());
|
||||
Assert.assertEquals(50, model.getStarredMessages().intValue());
|
||||
StarStatsPost topPost = model.getTopPosts().get(0);
|
||||
Assert.assertEquals(SERVER_ID, topPost.getServerId());
|
||||
Assert.assertEquals(channel.getId(), topPost.getChannelId());
|
||||
Assert.assertEquals(MESSAGE_ID, topPost.getMessageId());
|
||||
Assert.assertEquals(1, topPost.getStarCount().intValue());
|
||||
StarStatsPost secondTopPost = model.getTopPosts().get(1);
|
||||
Assert.assertEquals(SERVER_ID, secondTopPost.getServerId());
|
||||
Assert.assertEquals(channel.getId(), secondTopPost.getChannelId());
|
||||
Assert.assertEquals(SECOND_MESSAGE_ID, secondTopPost.getMessageId());
|
||||
Assert.assertEquals(0, secondTopPost.getStarCount().intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveStarStatsForMember() {
|
||||
when(starredMember.getGuild()).thenReturn(guild);
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
when(starredMember.getIdLong()).thenReturn(STARRED_USER_ID);
|
||||
Long receivedStars = 3L;
|
||||
Long givenStars = 3L;
|
||||
when(starboardPostManagementService.retrieveReceivedStarsOfUserInServer(SERVER_ID, STARRED_USER_ID)).thenReturn(receivedStars);
|
||||
when(starboardPostManagementService.retrieveGivenStarsOfUserInServer(SERVER_ID, STARRED_USER_ID)).thenReturn(givenStars);
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
AChannel starboardChannel = Mockito.mock(AChannel.class);
|
||||
when(post.getStarboardChannel()).thenReturn(starboardChannel);
|
||||
AServer server = Mockito.mock(AServer.class);
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
when(post.getServer()).thenReturn(server);
|
||||
StarboardPostReaction reaction = Mockito.mock(StarboardPostReaction.class);
|
||||
when(post.getReactions()).thenReturn(Collections.singletonList(reaction));
|
||||
when(starboardChannel.getId()).thenReturn(STARBOARD_CHANNEL_ID);
|
||||
when(post.getPostMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(starboardPostManagementService.retrieveTopPostsForUserInServer(SERVER_ID, STARRED_USER_ID, 3)).thenReturn(Collections.singletonList(post));
|
||||
MemberStarStatsModel returnedModel = testUnit.retrieveStarStatsForMember(starredMember);
|
||||
Assert.assertEquals(receivedStars, returnedModel.getReceivedStars());
|
||||
Assert.assertEquals(givenStars, returnedModel.getGivenStars());
|
||||
Assert.assertEquals(starredMember, returnedModel.getMember());
|
||||
Assert.assertEquals(3, returnedModel.getBadgeEmotes().size());
|
||||
Assert.assertEquals(1, returnedModel.getTopPosts().size());
|
||||
StarStatsPost starStatsPost = returnedModel.getTopPosts().get(0);
|
||||
Assert.assertEquals(STARBOARD_CHANNEL_ID, starStatsPost.getChannelId());
|
||||
Assert.assertEquals(SERVER_ID, starStatsPost.getServerId());
|
||||
Assert.assertEquals(1, starStatsPost.getStarCount().longValue());
|
||||
Assert.assertEquals(MESSAGE_ID, starStatsPost.getMessageId());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package dev.sheldan.abstracto.starboard.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPostReaction;
|
||||
import dev.sheldan.abstracto.starboard.repository.StarboardPostRepository;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarboardPostManagementServiceBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarboardPostManagementServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private StarboardPostRepository repository;
|
||||
|
||||
@Mock
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer aUserInAServer;
|
||||
|
||||
@Mock
|
||||
private AChannel sourceChannel;
|
||||
|
||||
@Mock
|
||||
private AChannel starboardChannel;
|
||||
|
||||
private static final Long SOURCE_CHANNEL_ID = 5L;
|
||||
private static final Long SERVER_ID = 7L;
|
||||
|
||||
@Test
|
||||
public void testCreateStarboardPost() {
|
||||
Long starboardPostId = 5L;
|
||||
Long starredMessageId = 8L;
|
||||
CachedMessage starredMessage = Mockito.mock(CachedMessage.class);
|
||||
when(starredMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(starredMessage.getChannelId()).thenReturn(SOURCE_CHANNEL_ID);
|
||||
when(starredMessage.getMessageId()).thenReturn(starredMessageId);
|
||||
AServerAChannelMessage postInStarboard = Mockito.mock(AServerAChannelMessage.class);
|
||||
when(postInStarboard.getServer()).thenReturn(server);
|
||||
when(postInStarboard.getChannel()).thenReturn(starboardChannel);
|
||||
when(postInStarboard.getMessageId()).thenReturn(starboardPostId);
|
||||
when(channelManagementService.loadChannel(SOURCE_CHANNEL_ID)).thenReturn(sourceChannel);
|
||||
AUser aUser = Mockito.mock(AUser.class);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(aUser);
|
||||
StarboardPost createdStarboardPost = testUnit.createStarboardPost(starredMessage, aUserInAServer, postInStarboard);
|
||||
verify(repository, times(1)).save(createdStarboardPost);
|
||||
Assert.assertEquals(starboardChannel, createdStarboardPost.getStarboardChannel());
|
||||
Assert.assertEquals(starboardPostId, createdStarboardPost.getStarboardMessageId());
|
||||
Assert.assertEquals(starredMessageId, createdStarboardPost.getPostMessageId());
|
||||
Assert.assertEquals(aUserInAServer, createdStarboardPost.getAuthor());
|
||||
Assert.assertEquals(sourceChannel, createdStarboardPost.getSourceChannel());
|
||||
Assert.assertFalse(createdStarboardPost.isIgnored());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setStarboardMessageId(){
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
Long messageId = 6L;
|
||||
testUnit.setStarboardPostMessageId(post, messageId);
|
||||
verify(post, times(1)).setStarboardMessageId(messageId);
|
||||
verify(repository, times(1)).save(post);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveTopPosts() {
|
||||
Integer count = 2;
|
||||
StarboardPost starboardPost1 = Mockito.mock(StarboardPost.class);
|
||||
when(starboardPost1.getReactions()).thenReturn(Arrays.asList(Mockito.mock(StarboardPostReaction.class), Mockito.mock(StarboardPostReaction.class)));
|
||||
StarboardPost starboardPost2 = Mockito.mock(StarboardPost.class);
|
||||
when(starboardPost2.getReactions()).thenReturn(Arrays.asList(Mockito.mock(StarboardPostReaction.class)));
|
||||
StarboardPost starboardPost3 = Mockito.mock(StarboardPost.class);
|
||||
when(starboardPost3.getReactions()).thenReturn(new ArrayList<>());
|
||||
List<StarboardPost> posts = Arrays.asList(starboardPost1, starboardPost2, starboardPost3);
|
||||
when(repository.findByServer_Id(SERVER_ID)).thenReturn(posts);
|
||||
List<StarboardPost> topPosts = testUnit.retrieveTopPosts(SERVER_ID, count);
|
||||
Assert.assertEquals(count.intValue(), topPosts.size());
|
||||
StarboardPost topMostPost = topPosts.get(0);
|
||||
StarboardPost secondTop = topPosts.get(1);
|
||||
Assert.assertEquals(starboardPost1, topPosts.get(0));
|
||||
Assert.assertEquals(starboardPost2, secondTop);
|
||||
Assert.assertTrue(topMostPost.getReactions().size() > secondTop.getReactions().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveMoreThanAvailable() {
|
||||
Integer count = 5;
|
||||
StarboardPost starboardPost1 = Mockito.mock(StarboardPost.class);
|
||||
when(starboardPost1.getReactions()).thenReturn(Arrays.asList(Mockito.mock(StarboardPostReaction.class), Mockito.mock(StarboardPostReaction.class)));
|
||||
StarboardPost starboardPost2 = Mockito.mock(StarboardPost.class);
|
||||
when(starboardPost2.getReactions()).thenReturn(Arrays.asList(Mockito.mock(StarboardPostReaction.class)));
|
||||
StarboardPost starboardPost3 = Mockito.mock(StarboardPost.class);
|
||||
when(starboardPost3.getReactions()).thenReturn(new ArrayList<>());
|
||||
List<StarboardPost> posts = Arrays.asList(starboardPost1, starboardPost2, starboardPost3);
|
||||
when(repository.findByServer_Id(SERVER_ID)).thenReturn(posts);
|
||||
List<StarboardPost> topPosts = testUnit.retrieveTopPosts(SERVER_ID, count);
|
||||
StarboardPost topMostPost = topPosts.get(0);
|
||||
StarboardPost secondTop = topPosts.get(1);
|
||||
StarboardPost thirdTopMostPost = topPosts.get(2);
|
||||
Assert.assertEquals(3, topPosts.size());
|
||||
Assert.assertEquals(starboardPost1, topPosts.get(0));
|
||||
Assert.assertEquals(starboardPost2, secondTop);
|
||||
Assert.assertEquals(starboardPost3, thirdTopMostPost);
|
||||
Assert.assertTrue(topMostPost.getReactions().size() > secondTop.getReactions().size());
|
||||
Assert.assertTrue(secondTop.getReactions().size() > thirdTopMostPost.getReactions().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovePost() {
|
||||
StarboardPost starboardPost1 = Mockito.mock(StarboardPost.class);
|
||||
when(starboardPost1.getReactions()).thenReturn(new ArrayList<>(Arrays.asList(Mockito.mock(StarboardPostReaction.class), Mockito.mock(StarboardPostReaction.class))));
|
||||
testUnit.removePost(starboardPost1);
|
||||
verify(repository, times(1)).delete(any(StarboardPost.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetStarboardPostIgnored() {
|
||||
Long messageId = 5L;
|
||||
Boolean ignoredValue = true;
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
when(repository.findByStarboardMessageId(messageId)).thenReturn(post);
|
||||
testUnit.setStarboardPostIgnored(messageId, ignoredValue);
|
||||
verify(post, times(1)).setIgnored(true);
|
||||
verify(repository, times(1)).save(post);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsStarboardPost() {
|
||||
Long starboardPostId = 5L;
|
||||
when(repository.existsByStarboardMessageId(starboardPostId)).thenReturn(true);
|
||||
boolean starboardPost = testUnit.isStarboardPost(starboardPostId);
|
||||
Assert.assertTrue(starboardPost);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindByMessageId() {
|
||||
Long messageId = 5L;
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
when(repository.findByPostMessageId(messageId)).thenReturn(post);
|
||||
Optional<StarboardPost> postOptional = testUnit.findByMessageId(messageId);
|
||||
Assert.assertTrue(postOptional.isPresent());
|
||||
postOptional.ifPresent(starboardPost -> Assert.assertEquals(starboardPost, post));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindByMessageIdMissing() {
|
||||
Long messageId = 5L;
|
||||
when(repository.findByPostMessageId(messageId)).thenReturn(null);
|
||||
Optional<StarboardPost> postOptional = testUnit.findByMessageId(messageId);
|
||||
Assert.assertFalse(postOptional.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindByStarboardPostId() {
|
||||
Long postId = 5L;
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
when(repository.findByStarboardMessageId(postId)).thenReturn(post);
|
||||
Optional<StarboardPost> postOptional = testUnit.findByStarboardPostId(postId);
|
||||
Assert.assertTrue(postOptional.isPresent());
|
||||
postOptional.ifPresent(starboardPost -> Assert.assertEquals(starboardPost, post));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindByStarboardPostIdMissing() {
|
||||
Long postId = 5L;
|
||||
when(repository.findByStarboardMessageId(postId)).thenReturn(null);
|
||||
Optional<StarboardPost> postOptional = testUnit.findByStarboardPostId(postId);
|
||||
Assert.assertFalse(postOptional.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrievePostCount() {
|
||||
StarboardPost starboardPost1 = Mockito.mock(StarboardPost.class);
|
||||
StarboardPost starboardPost2 = Mockito.mock(StarboardPost.class);
|
||||
List<StarboardPost> posts = Arrays.asList(starboardPost1, starboardPost2);
|
||||
when(repository.findByServer_Id(SERVER_ID)).thenReturn(posts);
|
||||
Integer retrievedPostCount = testUnit.getPostCount(SERVER_ID);
|
||||
Assert.assertEquals(posts.size(), retrievedPostCount.intValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package dev.sheldan.abstracto.starboard.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.starboard.converter.StarStatsUserConverter;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPostReaction;
|
||||
import dev.sheldan.abstracto.starboard.model.template.StarStatsUser;
|
||||
import dev.sheldan.abstracto.starboard.repository.StarboardPostReactionRepository;
|
||||
import dev.sheldan.abstracto.starboard.repository.result.StarStatsGuildUserResult;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarboardPostReactorManagementServiceBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarboardPostReactorManagementServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private StarboardPostReactionRepository repository;
|
||||
|
||||
@Mock
|
||||
private StarStatsUserConverter converter;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<StarboardPostReaction> reactorCaptor;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer aUserInAServer;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private AUser aUser;
|
||||
|
||||
private static final Long SERVER_ID = 4L;
|
||||
|
||||
@Test
|
||||
public void testAddReactor() {
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(aUser);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
testUnit.addReactor(post, aUserInAServer);
|
||||
verify(repository, times(1)).save(reactorCaptor.capture());
|
||||
StarboardPostReaction reaction = reactorCaptor.getValue();
|
||||
Assert.assertEquals(post, reaction.getStarboardPost());
|
||||
Assert.assertEquals(aUserInAServer, reaction.getReactor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactor() {
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(aUser);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
testUnit.removeReactor(post, aUserInAServer);
|
||||
verify(repository, times(1)).deleteByReactorAndStarboardPost(aUserInAServer, post);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactors() {
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
testUnit.removeReactors(post);
|
||||
verify(repository, times(1)).deleteByStarboardPost(post);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveStarCount() {
|
||||
Integer stars = 5;
|
||||
when(repository.getReactionCountByServer(SERVER_ID)).thenReturn(stars);
|
||||
Integer starCount = testUnit.getStarCount(SERVER_ID);
|
||||
Assert.assertEquals(stars, starCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveTopStarGiverAllAreAvailable() {
|
||||
testTopStarGiver(2, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveTopStarGiverNotAllAreAvailable() {
|
||||
testTopStarGiver(2, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveTopStarGiverMoreAreAvailable() {
|
||||
testTopStarGiver(1, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveTopStarReceiverAllAreAvailable() {
|
||||
testTopStarReceiver(2, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveTopStarReceiverNotAllAreAvailable() {
|
||||
testTopStarReceiver(2, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveTopStarReceiverMoreAreAvailable() {
|
||||
testTopStarReceiver(1, 1);
|
||||
}
|
||||
|
||||
private void testTopStarReceiver(int expectedAmount, Integer amountToRetrieve) {
|
||||
StarStatsUser user1 = Mockito.mock(StarStatsUser.class);
|
||||
StarStatsUser user2 = Mockito.mock(StarStatsUser.class);
|
||||
setupStarStatsReceiverResult(amountToRetrieve, SERVER_ID, user1, user2);
|
||||
List<CompletableFuture<StarStatsUser>> starStatsUsers = testUnit.retrieveTopStarReceiver(SERVER_ID, amountToRetrieve);
|
||||
Assert.assertEquals(expectedAmount, starStatsUsers.size());
|
||||
Assert.assertEquals(user1, starStatsUsers.get(0).join());
|
||||
if(amountToRetrieve > 1) {
|
||||
Assert.assertEquals(user2, starStatsUsers.get(1).join());
|
||||
}
|
||||
}
|
||||
|
||||
private void testTopStarGiver(int expectedAmount, Integer amountToRetrieve) {
|
||||
StarStatsUser user1 = Mockito.mock(StarStatsUser.class);
|
||||
StarStatsUser user2 = Mockito.mock(StarStatsUser.class);
|
||||
setupStarStatsGiverResult(amountToRetrieve, SERVER_ID, user1, user2);
|
||||
List<CompletableFuture<StarStatsUser>> starStatsUsers = testUnit.retrieveTopStarGiver(SERVER_ID, amountToRetrieve);
|
||||
Assert.assertEquals(expectedAmount, starStatsUsers.size());
|
||||
Assert.assertEquals(user1, starStatsUsers.get(0).join());
|
||||
if(amountToRetrieve > 1) {
|
||||
Assert.assertEquals(user2, starStatsUsers.get(1).join());
|
||||
}
|
||||
}
|
||||
|
||||
private void setupStarStatsGiverResult(Integer amountToRetrieve, Long serverId, StarStatsUser user1, StarStatsUser user2) {
|
||||
StarStatsGuildUserResult result1 = Mockito.mock(StarStatsGuildUserResult.class);
|
||||
StarStatsGuildUserResult result2 = Mockito.mock(StarStatsGuildUserResult.class);
|
||||
List<StarStatsGuildUserResult> results = Arrays.asList(result1, result2);
|
||||
when(repository.findTopStarGiverInServer(serverId, amountToRetrieve)).thenReturn(results);
|
||||
List<CompletableFuture<StarStatsUser>> statsUser = new ArrayList<>();
|
||||
statsUser.add(CompletableFuture.completedFuture(user1));
|
||||
if (amountToRetrieve > 1) {
|
||||
statsUser.add(CompletableFuture.completedFuture(user2));
|
||||
}
|
||||
when(converter.convertToStarStatsUser(results, serverId)).thenReturn(statsUser);
|
||||
}
|
||||
|
||||
private void setupStarStatsReceiverResult(Integer amountToRetrieve, Long serverId, StarStatsUser user1, StarStatsUser user2) {
|
||||
StarStatsGuildUserResult result1 = Mockito.mock(StarStatsGuildUserResult.class);
|
||||
StarStatsGuildUserResult result2 = Mockito.mock(StarStatsGuildUserResult.class);
|
||||
List<StarStatsGuildUserResult> results = Arrays.asList(result1, result2);
|
||||
when(repository.retrieveTopStarReceiverInServer(serverId, amountToRetrieve)).thenReturn(results);
|
||||
List<CompletableFuture<StarStatsUser>> statsUser = new ArrayList<>();
|
||||
statsUser.add(CompletableFuture.completedFuture(user1));
|
||||
if (amountToRetrieve > 1) {
|
||||
statsUser.add(CompletableFuture.completedFuture(user2));
|
||||
}
|
||||
when(converter.convertToStarStatsUser(results, serverId)).thenReturn(statsUser);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>starboard</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>starboard-int</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,62 @@
|
||||
package dev.sheldan.abstracto.starboard.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class StarboardFeature implements FeatureConfig {
|
||||
|
||||
public static final String STAR_LVL_CONFIG_PREFIX = "starLvl";
|
||||
public static final String STAR_EMOTE_PREFIX = "star";
|
||||
public static final String STAR_BADGE_EMOTE_PREFIX = "starboardBadge";
|
||||
public static final String STAR_LEVELS_CONFIG_KEY = "starLvls";
|
||||
public static final String STAR_EMOTE = "star";
|
||||
|
||||
@Autowired
|
||||
private DefaultConfigManagementService defaultConfigManagementService;
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StarboardFeatureDefinition.STARBOARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PostTargetEnum> getRequiredPostTargets() {
|
||||
return Arrays.asList(StarboardPostTarget.STARBOARD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
List<String> configKeys = new ArrayList<>();
|
||||
int maxLevels = getMaxLevels();
|
||||
for(int i = maxLevels; i > 0; i--) {
|
||||
configKeys.add(StarboardFeature.STAR_LVL_CONFIG_PREFIX + i);
|
||||
}
|
||||
return configKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredEmotes() {
|
||||
List<String> emoteNames = new ArrayList<>();
|
||||
int maxLevels = getMaxLevels();
|
||||
for(int i = maxLevels; i > 0; i--) {
|
||||
emoteNames.add(StarboardFeature.STAR_EMOTE_PREFIX + i);
|
||||
}
|
||||
emoteNames.add(StarboardFeature.STAR_BADGE_EMOTE_PREFIX + 1);
|
||||
emoteNames.add(StarboardFeature.STAR_BADGE_EMOTE_PREFIX + 2);
|
||||
emoteNames.add(StarboardFeature.STAR_BADGE_EMOTE_PREFIX + 3);
|
||||
return emoteNames;
|
||||
}
|
||||
|
||||
private int getMaxLevels() {
|
||||
return defaultConfigManagementService.getDefaultConfig(STAR_LEVELS_CONFIG_KEY).getLongValue().intValue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.starboard.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum StarboardFeatureDefinition implements FeatureDefinition {
|
||||
STARBOARD("starboard");
|
||||
|
||||
private String key;
|
||||
|
||||
StarboardFeatureDefinition(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.starboard.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum StarboardPostTarget implements PostTargetEnum {
|
||||
STARBOARD("starboard");
|
||||
|
||||
private String key;
|
||||
|
||||
StarboardPostTarget(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package dev.sheldan.abstracto.starboard.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="starboard_post")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class StarboardPost implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "author_user_in_server_id", nullable = false)
|
||||
private AUserInAServer author;
|
||||
|
||||
@Column(name = "starboard_message_id")
|
||||
private Long starboardMessageId;
|
||||
|
||||
@Column(name = "post_message_id")
|
||||
private Long postMessageId;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "channel_id", nullable = false)
|
||||
private AChannel starboardChannel;
|
||||
|
||||
@Getter
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "source_channel_id", nullable = false)
|
||||
private AChannel sourceChannel;
|
||||
|
||||
@Transient
|
||||
private Integer reactionCount;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updated;
|
||||
|
||||
@PostLoad
|
||||
private void onLoad() {
|
||||
this.reactionCount = this.reactions.size();
|
||||
}
|
||||
|
||||
@Getter
|
||||
@OneToMany(fetch = FetchType.LAZY,
|
||||
orphanRemoval = true,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE},
|
||||
mappedBy = "starboardPost")
|
||||
private List<StarboardPostReaction> reactions;
|
||||
|
||||
@Column(name = "starred_date")
|
||||
private Instant starredDate;
|
||||
|
||||
@Column(name = "ignored")
|
||||
private boolean ignored;
|
||||
|
||||
public int getReactionCount() {
|
||||
if(this.reactions == null) {
|
||||
return 0;
|
||||
}
|
||||
return this.reactions.size();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.sheldan.abstracto.starboard.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name="starboard_post_reaction")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class StarboardPostReaction implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "reactor_user_in_server_id", nullable = false)
|
||||
private AUserInAServer reactor;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "post_id")
|
||||
private StarboardPost starboardPost;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updated;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package dev.sheldan.abstracto.starboard.model.template;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class GuildStarStatsModel {
|
||||
private List<StarStatsPost> topPosts;
|
||||
private List<StarStatsUser> starReceiver;
|
||||
private List<StarStatsUser> starGiver;
|
||||
private Integer totalStars;
|
||||
private List<String> badgeEmotes;
|
||||
private Integer starredMessages;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package dev.sheldan.abstracto.starboard.model.template;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class MemberStarStatsModel {
|
||||
private List<StarStatsPost> topPosts;
|
||||
private Long receivedStars;
|
||||
private Long givenStars;
|
||||
private List<String> badgeEmotes;
|
||||
private Member member;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.abstracto.starboard.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.utils.MessageUtils;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class StarStatsPost {
|
||||
private Long serverId;
|
||||
private Long channelId;
|
||||
private Long messageId;
|
||||
private Integer starCount;
|
||||
|
||||
public String getMessageUrl() {
|
||||
return MessageUtils.buildMessageUrl(serverId ,channelId, messageId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package dev.sheldan.abstracto.starboard.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class StarStatsUser {
|
||||
private AUserInAServer user;
|
||||
private Member member;
|
||||
private Integer starCount;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package dev.sheldan.abstracto.starboard.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.context.ServerContext;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
public class StarboardPostModel extends ServerContext {
|
||||
private Member author;
|
||||
private TextChannel channel;
|
||||
private AUser user;
|
||||
private AChannel aChannel;
|
||||
private CachedMessage message;
|
||||
private Integer starCount;
|
||||
private String starLevelEmote;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.abstracto.starboard.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.model.template.GuildStarStatsModel;
|
||||
import dev.sheldan.abstracto.starboard.model.template.MemberStarStatsModel;
|
||||
import dev.sheldan.abstracto.starboard.model.template.StarStatsPost;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface StarboardService {
|
||||
CompletableFuture<Void> createStarboardPost(CachedMessage message, List<AUserInAServer> userExceptAuthor, AUserInAServer userReacting, AUserInAServer starredUser);
|
||||
CompletableFuture<Void> updateStarboardPost(StarboardPost post, CachedMessage message, List<AUserInAServer> userExceptAuthor);
|
||||
void deleteStarboardMessagePost(StarboardPost message);
|
||||
CompletableFuture<GuildStarStatsModel> retrieveStarStats(Long serverId);
|
||||
MemberStarStatsModel retrieveStarStatsForMember(Member member);
|
||||
StarStatsPost fromStarboardPost(StarboardPost starboardPost);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sheldan.abstracto.starboard.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface StarboardPostManagementService {
|
||||
StarboardPost createStarboardPost(CachedMessage starredMessage, AUserInAServer starredUser, AServerAChannelMessage starboardPost);
|
||||
StarboardPost createStarboardPost(StarboardPost post);
|
||||
void setStarboardPostMessageId(StarboardPost post, Long messageId);
|
||||
List<StarboardPost> retrieveTopPosts(Long serverId, Integer count);
|
||||
List<StarboardPost> retrieveTopPostsForUserInServer(Long serverId, Long userId, Integer count);
|
||||
Long retrieveGivenStarsOfUserInServer(Long serverId, Long userId);
|
||||
Long retrieveReceivedStarsOfUserInServer(Long serverId, Long userId);
|
||||
List<StarboardPost> retrieveAllPosts(Long serverId);
|
||||
Integer getPostCount(Long serverId);
|
||||
Optional<StarboardPost> findByMessageId(Long messageId);
|
||||
Optional<StarboardPost> findByStarboardPostId(Long postId);
|
||||
void setStarboardPostIgnored(Long starboardPostId, Boolean newValue);
|
||||
boolean isStarboardPost(Long starboardPostId);
|
||||
void removePost(StarboardPost starboardPost);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.abstracto.starboard.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPostReaction;
|
||||
import dev.sheldan.abstracto.starboard.model.template.StarStatsUser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface StarboardPostReactorManagementService {
|
||||
StarboardPostReaction addReactor(StarboardPost post, AUserInAServer user);
|
||||
void removeReactor(StarboardPost post, AUserInAServer user);
|
||||
void removeReactors(StarboardPost post);
|
||||
Integer getStarCount(Long serverId);
|
||||
List<CompletableFuture<StarStatsUser>> retrieveTopStarGiver(Long serverId, Integer count);
|
||||
List<CompletableFuture<StarStatsUser>> retrieveTopStarReceiver(Long serverId, Integer count);
|
||||
}
|
||||
Reference in New Issue
Block a user