mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-21 05:32:43 +00:00
[AB-197] splitting utility maven module into separate maven modules
aligning some package names removing some unnecessary computed values from liquibase
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
|
||||
<id>liquibase</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<outputDirectory>.</outputDirectory>
|
||||
<directory>${project.basedir}/src/main/resources/migrations</directory>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
@@ -0,0 +1,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
|
||||
Reference in New Issue
Block a user