mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-22 07:38:09 +00:00
Compare commits
9 Commits
abstracto-
...
abstracto-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
650d062808 | ||
|
|
bac9832819 | ||
|
|
efbcb5c84b | ||
|
|
fd70e6ac90 | ||
|
|
29bde70796 | ||
|
|
ecd4feabb2 | ||
|
|
abf60409f1 | ||
|
|
080733957f | ||
|
|
8a41f366ae |
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>assignable-roles-int</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto</groupId>
|
||||
<artifactId>abstracto-application</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>profanity-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>profanity-filter</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>remind</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>remind</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>repost-detection</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>repost-detection</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>starboard</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ public class StarboardServiceBean implements StarboardService {
|
||||
public void persistPost(CachedMessage message, List<Long> userExceptAuthorIds, List<CompletableFuture<Message>> completableFutures, Long starboardChannelId, Long starredUserId, Long userReactingId) {
|
||||
AUserInAServer innerStarredUser = userInServerManagementService.loadUserOptional(starredUserId).orElseThrow(() -> new UserInServerNotFoundException(starredUserId));
|
||||
AChannel starboardChannel = channelManagementService.loadChannel(starboardChannelId);
|
||||
Message starboardMessage = completableFutures.get(0).join();
|
||||
Message starboardMessage = completableFutures.get(0).join(); // TODO null pointer if post target is disabled
|
||||
AServerAChannelMessage aServerAChannelMessage = AServerAChannelMessage
|
||||
.builder()
|
||||
.messageId(starboardMessage.getIdLong())
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>starboard</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic</artifactId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>suggestion</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package dev.sheldan.abstracto.suggestion.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.config.ParameterValidator;
|
||||
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionSlashCommandNames;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class CancelPoll extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CANCEL_POLL_COMMAND = "cancelPoll";
|
||||
private static final String POLL_ID_PARAMETER = "pollId";
|
||||
private static final String CANCEL_POLL_RESPONSE = "cancelPoll_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Long pollId = slashCommandParameterService.getCommandOption(POLL_ID_PARAMETER, event, Integer.class).longValue();
|
||||
return pollService.cancelPoll(pollId, event.getGuild().getIdLong(), event.getMember())
|
||||
.thenCompose(unused -> interactionService.replyEmbed(CANCEL_POLL_RESPONSE, event))
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return SuggestionFeatureDefinition.POLL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<ParameterValidator> pollIdValidator = Arrays.asList(MinIntegerValueValidator.min(1L));
|
||||
Parameter pollIdParameter = Parameter
|
||||
.builder()
|
||||
.name(POLL_ID_PARAMETER)
|
||||
.validators(pollIdValidator)
|
||||
.type(Long.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(pollIdParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(SuggestionSlashCommandNames.POLL_PUBLIC)
|
||||
.commandName("cancel")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(CANCEL_POLL_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package dev.sheldan.abstracto.suggestion.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.config.ParameterValidator;
|
||||
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionSlashCommandNames;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class ClosePoll extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CLOSE_POLL_COMMAND = "closePoll";
|
||||
private static final String POLL_ID_PARAMETER = "pollId";
|
||||
private static final String TEXT_PARAMETER = "text";
|
||||
private static final String CLOSE_POLL_RESPONSE = "closePoll_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Long pollId = slashCommandParameterService.getCommandOption(POLL_ID_PARAMETER, event, Integer.class).longValue();
|
||||
String text;
|
||||
if(slashCommandParameterService.hasCommandOption(TEXT_PARAMETER, event)) {
|
||||
text = slashCommandParameterService.getCommandOption(TEXT_PARAMETER, event, String.class);
|
||||
} else {
|
||||
text = "";
|
||||
}
|
||||
return pollService.closePoll(pollId, event.getGuild().getIdLong(), text, event.getMember())
|
||||
.thenCompose(unused -> interactionService.replyEmbed(CLOSE_POLL_RESPONSE, event))
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return SuggestionFeatureDefinition.POLL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<ParameterValidator> pollIdValidator = Arrays.asList(MinIntegerValueValidator.min(1L));
|
||||
Parameter pollIdParameter = Parameter
|
||||
.builder()
|
||||
.name(POLL_ID_PARAMETER)
|
||||
.validators(pollIdValidator)
|
||||
.type(Long.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
Parameter textParameter = Parameter
|
||||
.builder()
|
||||
.name(TEXT_PARAMETER)
|
||||
.type(String.class)
|
||||
.optional(true)
|
||||
.remainder(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(pollIdParameter, textParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(SuggestionSlashCommandNames.POLL)
|
||||
.commandName("close")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(CLOSE_POLL_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package dev.sheldan.abstracto.suggestion.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.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.utils.ParseUtils;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionSlashCommandNames;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class Poll extends AbstractConditionableCommand {
|
||||
|
||||
private static final String POLL_COMMAND = "poll";
|
||||
private static final String ALLOW_MULTIPLE_PARAMETER = "allowMultiple";
|
||||
private static final String SHOW_DECISIONS_PARAMETER = "showDecisions";
|
||||
private static final String ALLOW_ADDITIONS_PARAMETER = "allowAdditions";
|
||||
private static final String POLL_DURATION_PARAMETER = "pollDuration";
|
||||
private static final String POLL_DESCRIPTION_PARAMETER = "description";
|
||||
private static final String POLL_OPTIONS_PARAMETER = "options";
|
||||
private static final Integer OPTIONS_COUNT = 15;
|
||||
private static final String POLL_RESPONSE_TEMPLATE_KEY = "poll_server_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
List<String> options = new ArrayList<>();
|
||||
for (int i = 0; i < OPTIONS_COUNT; i++) {
|
||||
if(slashCommandParameterService.hasCommandOption(POLL_OPTIONS_PARAMETER + "_" + i, event)) {
|
||||
String choice = slashCommandParameterService.getCommandOption(POLL_OPTIONS_PARAMETER + "_" + i, event, String.class);
|
||||
options.add(choice);
|
||||
}
|
||||
}
|
||||
Boolean allowMultiple = false;
|
||||
if(slashCommandParameterService.hasCommandOption(ALLOW_MULTIPLE_PARAMETER, event)) {
|
||||
allowMultiple = slashCommandParameterService.getCommandOption(ALLOW_MULTIPLE_PARAMETER, event, Boolean.class);
|
||||
}
|
||||
|
||||
Boolean showDecisions = false;
|
||||
if(slashCommandParameterService.hasCommandOption(SHOW_DECISIONS_PARAMETER, event)) {
|
||||
showDecisions = slashCommandParameterService.getCommandOption(SHOW_DECISIONS_PARAMETER, event, Boolean.class);
|
||||
}
|
||||
|
||||
Boolean allowAdditions = false;
|
||||
if(slashCommandParameterService.hasCommandOption(ALLOW_ADDITIONS_PARAMETER, event)) {
|
||||
allowAdditions = slashCommandParameterService.getCommandOption(ALLOW_ADDITIONS_PARAMETER, event, Boolean.class);
|
||||
}
|
||||
Duration pollDuration = null;
|
||||
if(slashCommandParameterService.hasCommandOption(POLL_DURATION_PARAMETER, event)) {
|
||||
String durationString = slashCommandParameterService.getCommandOption(POLL_DURATION_PARAMETER, event, Duration.class, String.class);
|
||||
pollDuration = ParseUtils.parseDuration(durationString);
|
||||
}
|
||||
Boolean actualMultiple = allowMultiple;
|
||||
Boolean actualDecisions = showDecisions;
|
||||
Boolean actualAdditions = allowAdditions;
|
||||
Duration actualDuration = pollDuration;
|
||||
String description = slashCommandParameterService.getCommandOption(POLL_DESCRIPTION_PARAMETER, event, String.class);
|
||||
return event.deferReply()
|
||||
.submit()
|
||||
.thenCompose(interactionHook -> pollService.createServerPoll(event.getMember(), options, description, actualMultiple, actualAdditions, actualDecisions, actualDuration)
|
||||
.thenAccept(unused -> interactionService.sendMessageToInteraction(POLL_RESPONSE_TEMPLATE_KEY, new Object(), interactionHook)))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter allowMultipleParameter = Parameter
|
||||
.builder()
|
||||
.name(ALLOW_MULTIPLE_PARAMETER)
|
||||
.type(Boolean.class)
|
||||
.templated(true)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
Parameter showDecisions = Parameter
|
||||
.builder()
|
||||
.name(SHOW_DECISIONS_PARAMETER)
|
||||
.type(Boolean.class)
|
||||
.templated(true)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
Parameter allowAdditions = Parameter
|
||||
.builder()
|
||||
.name(ALLOW_ADDITIONS_PARAMETER)
|
||||
.type(Boolean.class)
|
||||
.templated(true)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
Parameter description = Parameter
|
||||
.builder()
|
||||
.name(POLL_DESCRIPTION_PARAMETER)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
Parameter duration = Parameter
|
||||
.builder()
|
||||
.name(POLL_DURATION_PARAMETER)
|
||||
.type(Duration.class)
|
||||
.templated(true)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
Parameter optionsParameter = Parameter
|
||||
.builder()
|
||||
.name(POLL_OPTIONS_PARAMETER)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.remainder(true)
|
||||
.listSize(OPTIONS_COUNT)
|
||||
.isListParam(true)
|
||||
.build();
|
||||
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(description, optionsParameter, allowMultipleParameter, showDecisions, allowAdditions, duration);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(SuggestionSlashCommandNames.POLL_PUBLIC)
|
||||
.commandName("server")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(POLL_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return SuggestionFeatureDefinition.POLL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package dev.sheldan.abstracto.suggestion.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.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.utils.ParseUtils;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionSlashCommandNames;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class QuickPoll extends AbstractConditionableCommand {
|
||||
|
||||
private static final String POLL_COMMAND = "quickPoll";
|
||||
private static final String ALLOW_MULTIPLE_PARAMETER = "allowMultiple";
|
||||
private static final String POLL_DURATION_PARAMETER = "pollDuration";
|
||||
private static final String SHOW_DECISIONS_PARAMETER = "showDecisions";
|
||||
private static final String POLL_DESCRIPTION_PARAMETER = "description";
|
||||
private static final String POLL_OPTIONS_PARAMETER = "options";
|
||||
private static final Integer OPTIONS_COUNT = 15;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
List<String> options = new ArrayList<>();
|
||||
for (int i = 0; i < OPTIONS_COUNT; i++) {
|
||||
if(slashCommandParameterService.hasCommandOption(POLL_OPTIONS_PARAMETER + "_" + i, event)) {
|
||||
String choice = slashCommandParameterService.getCommandOption(POLL_OPTIONS_PARAMETER + "_" + i, event, String.class);
|
||||
options.add(choice);
|
||||
}
|
||||
}
|
||||
|
||||
Boolean allowMultiple = false;
|
||||
if(slashCommandParameterService.hasCommandOption(ALLOW_MULTIPLE_PARAMETER, event)) {
|
||||
allowMultiple = slashCommandParameterService.getCommandOption(ALLOW_MULTIPLE_PARAMETER, event, Boolean.class);
|
||||
}
|
||||
|
||||
Boolean showDecisions = false;
|
||||
if(slashCommandParameterService.hasCommandOption(SHOW_DECISIONS_PARAMETER, event)) {
|
||||
showDecisions = slashCommandParameterService.getCommandOption(SHOW_DECISIONS_PARAMETER, event, Boolean.class);
|
||||
}
|
||||
|
||||
Duration pollDuration = null;
|
||||
if(slashCommandParameterService.hasCommandOption(POLL_DURATION_PARAMETER, event)) {
|
||||
String durationString = slashCommandParameterService.getCommandOption(POLL_DURATION_PARAMETER, event, Duration.class, String.class);
|
||||
pollDuration = ParseUtils.parseDuration(durationString);
|
||||
}
|
||||
|
||||
Boolean actualMultiple = allowMultiple;
|
||||
Boolean actualShowDecisions = showDecisions;
|
||||
Duration actualDuration = pollDuration;
|
||||
String description = slashCommandParameterService.getCommandOption(POLL_DESCRIPTION_PARAMETER, event, String.class);
|
||||
|
||||
return event.deferReply()
|
||||
.submit()
|
||||
.thenCompose(interactionHook -> pollService.createQuickPoll(event.getMember(), options, description, actualMultiple, actualShowDecisions, interactionHook, actualDuration))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter allowMultipleParameter = Parameter
|
||||
.builder()
|
||||
.name(ALLOW_MULTIPLE_PARAMETER)
|
||||
.type(Boolean.class)
|
||||
.templated(true)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
Parameter description = Parameter
|
||||
.builder()
|
||||
.name(POLL_DESCRIPTION_PARAMETER)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
|
||||
Parameter showDecisions = Parameter
|
||||
.builder()
|
||||
.name(SHOW_DECISIONS_PARAMETER)
|
||||
.type(Boolean.class)
|
||||
.templated(true)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
|
||||
Parameter duration = Parameter
|
||||
.builder()
|
||||
.name(POLL_DURATION_PARAMETER)
|
||||
.type(Duration.class)
|
||||
.templated(true)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
Parameter optionsParameter = Parameter
|
||||
.builder()
|
||||
.name(POLL_OPTIONS_PARAMETER)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.remainder(true)
|
||||
.listSize(OPTIONS_COUNT)
|
||||
.isListParam(true)
|
||||
.build();
|
||||
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(description, optionsParameter, allowMultipleParameter, showDecisions, duration);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(SuggestionSlashCommandNames.POLL_PUBLIC)
|
||||
.commandName("quick")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(POLL_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return SuggestionFeatureDefinition.POLL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package dev.sheldan.abstracto.suggestion.job;
|
||||
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.quartz.PersistJobDataAfterExecution;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@DisallowConcurrentExecution
|
||||
@Component
|
||||
@PersistJobDataAfterExecution
|
||||
@Getter
|
||||
@Setter
|
||||
public class QuickPollEvaluationJob extends QuartzJobBean {
|
||||
|
||||
private Long pollId;
|
||||
private Long serverId;
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
log.info("Executing poll evaluation job for quick poll {} in server {}.", pollId, serverId);
|
||||
try {
|
||||
pollService.evaluateQuickPoll(pollId, serverId).thenAccept(unused -> {
|
||||
log.info("Evaluated quick poll {} in server {}.", pollId, serverId);
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to evaluate quick poll {} in server {}.", pollId, serverId, throwable);
|
||||
return null;
|
||||
});
|
||||
} catch (Exception exception) {
|
||||
log.error("Quick poll evaluation job failed.", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package dev.sheldan.abstracto.suggestion.job;
|
||||
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.quartz.PersistJobDataAfterExecution;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@DisallowConcurrentExecution
|
||||
@Component
|
||||
@PersistJobDataAfterExecution
|
||||
@Getter
|
||||
@Setter
|
||||
public class ServerPollEvaluationJob extends QuartzJobBean {
|
||||
|
||||
private Long pollId;
|
||||
private Long serverId;
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
log.info("Executing poll evaluation job for server poll {} in server {}.", pollId, serverId);
|
||||
try {
|
||||
pollService.evaluateServerPoll(pollId, serverId).thenAccept(unused -> {
|
||||
log.info("Evaluated server poll {} in server {}.", pollId, serverId);
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to evaluate server poll {} in server {}.", pollId, serverId, throwable);
|
||||
return null;
|
||||
});
|
||||
} catch (Exception exception) {
|
||||
log.error("Server poll evaluation job failed.", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package dev.sheldan.abstracto.suggestion.job;
|
||||
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.quartz.PersistJobDataAfterExecution;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@DisallowConcurrentExecution
|
||||
@Component
|
||||
@PersistJobDataAfterExecution
|
||||
@Getter
|
||||
@Setter
|
||||
public class ServerPollReminderJob extends QuartzJobBean {
|
||||
|
||||
private Long pollId;
|
||||
private Long serverId;
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
log.info("Executing server poll reminder job for server poll {} in server {}.", pollId, serverId);
|
||||
try {
|
||||
pollService.remindServerPoll(pollId, serverId).thenAccept(unused -> {
|
||||
log.info("Evaluated server poll {} in server {}.", pollId, serverId);
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to evaluate server poll {} in server {}.", pollId, serverId, throwable);
|
||||
return null;
|
||||
});
|
||||
} catch (Exception exception) {
|
||||
log.error("Server poll evaluation job failed.", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package dev.sheldan.abstracto.suggestion.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.menu.listener.StringSelectMenuListener;
|
||||
import dev.sheldan.abstracto.core.interaction.menu.listener.StringSelectMenuListenerModel;
|
||||
import dev.sheldan.abstracto.core.interaction.menu.listener.StringSelectMenuListenerResult;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberNameDisplay;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollType;
|
||||
import dev.sheldan.abstracto.suggestion.model.payload.QuickPollSelectionMenuPayload;
|
||||
import dev.sheldan.abstracto.suggestion.model.template.PollDecisionNotificationModel;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollServiceBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class QuickPollDecisionListener implements StringSelectMenuListener {
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
private static final String POLL_DECISION_NOTIFICATION = "poll_quick_decision_notification";
|
||||
|
||||
@Override
|
||||
public StringSelectMenuListenerResult execute(StringSelectMenuListenerModel model) {
|
||||
StringSelectInteractionEvent event = model.getEvent();
|
||||
QuickPollSelectionMenuPayload payload = (QuickPollSelectionMenuPayload) model.getDeserializedPayload();
|
||||
PollDecisionNotificationModel notificationModel = PollDecisionNotificationModel
|
||||
.builder()
|
||||
.chosenValues(event.getValues())
|
||||
.pollId(payload.getPollId())
|
||||
.memberNameDisplay(MemberNameDisplay.fromMember(event.getMember()))
|
||||
.serverId(model.getServerId())
|
||||
.build();
|
||||
pollService.setDecisionsInPollTo(event.getMember(), event.getValues(), payload.getPollId(), PollType.QUICK)
|
||||
.thenCompose(unused -> FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(POLL_DECISION_NOTIFICATION, notificationModel, event.getInteraction().getHook())))
|
||||
.exceptionally(throwable -> {
|
||||
log.info("Failed to member {} in server {} about decision in poll {}.", event.getMember().getIdLong(), model.getServerId(), payload.getPollId(), throwable);
|
||||
return null;
|
||||
}).thenAccept(unused1 -> {
|
||||
log.info("Notified member {} in server {} about decision in poll {}.", event.getMember().getIdLong(), model.getServerId(), payload.getPollId());
|
||||
});
|
||||
return StringSelectMenuListenerResult.ACKNOWLEDGED;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(StringSelectMenuListenerModel model) {
|
||||
return model.getOrigin().equals(PollServiceBean.QUICK_POLL_SELECTION_MENU_ORIGIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return SuggestionFeatureDefinition.POLL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package dev.sheldan.abstracto.suggestion.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadManagementService;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentService;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListener;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerModel;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerResult;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.ModalConfigPayload;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.ModalService;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.model.payload.PollAddOptionButtonPayload;
|
||||
import dev.sheldan.abstracto.suggestion.model.template.PollAddOptionModalModel;
|
||||
import dev.sheldan.abstracto.suggestion.model.payload.PollAddOptionModalPayload;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollServiceBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ServerPollAddOptionButtonListener implements ButtonClickedListener {
|
||||
|
||||
@Autowired
|
||||
private ComponentService componentService;
|
||||
|
||||
@Autowired
|
||||
private ModalService modalService;
|
||||
|
||||
@Autowired
|
||||
private ServerPollAddOptionButtonListener self;
|
||||
|
||||
@Autowired
|
||||
private ComponentPayloadManagementService componentPayloadManagementService;
|
||||
|
||||
private static final String SERVER_POLL_ADD_OPTION_MODAL_TEMPLATE = "poll_add_option";
|
||||
public static final String SERVER_POLL_ADD_OPTION_MODAL_ORIGIN = "SERVER_POLL_ADD_OPTION_MODAL";
|
||||
|
||||
@Override
|
||||
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
|
||||
PollAddOptionButtonPayload payload = (PollAddOptionButtonPayload) model.getDeserializedPayload();
|
||||
String modalId = componentService.generateComponentId();
|
||||
String labelInputId = componentService.generateComponentId();
|
||||
String descriptionInputId = componentService.generateComponentId();
|
||||
PollAddOptionModalModel modalModel = PollAddOptionModalModel
|
||||
.builder()
|
||||
.descriptionInputComponentId(descriptionInputId)
|
||||
.modalId(modalId)
|
||||
.labelInputComponentId(labelInputId)
|
||||
.build();
|
||||
modalService.replyModal(model.getEvent(), SERVER_POLL_ADD_OPTION_MODAL_TEMPLATE, modalModel).thenAccept(unused -> {
|
||||
log.info("Opened a model for entering a new option for poll {} in server {} for user {}.",
|
||||
payload.getPollId(), payload.getServerId(), model.getEvent().getMember().getIdLong());
|
||||
self.persistModalPayload(modalModel, model.getServerId(), payload.getPollId());
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to show modal for entering a new option for poll {} in server {} for user {}.",
|
||||
payload.getPollId(), payload.getServerId(), model.getEvent().getMember().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
return ButtonClickedListenerResult.ACKNOWLEDGED;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void persistModalPayload(PollAddOptionModalModel model, Long serverId, Long pollId) {
|
||||
PollAddOptionModalPayload payload = PollAddOptionModalPayload
|
||||
.builder()
|
||||
.modalId(model.getModalId())
|
||||
.labelInputComponentId(model.getLabelInputComponentId())
|
||||
.descriptionInputComponentId(model.getDescriptionInputComponentId())
|
||||
.serverId(serverId)
|
||||
.pollId(pollId)
|
||||
.build();
|
||||
ModalConfigPayload payloadConfig = ModalConfigPayload
|
||||
.builder()
|
||||
.modalPayload(payload)
|
||||
.origin(SERVER_POLL_ADD_OPTION_MODAL_ORIGIN)
|
||||
.payloadType(payload.getClass())
|
||||
.modalId(model.getModalId())
|
||||
.build();
|
||||
componentPayloadManagementService.createModalPayload(payloadConfig, serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean autoAcknowledgeEvent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return PollServiceBean.SERVER_POLL_ADD_OPTION_ORIGIN.equals(model.getOrigin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return SuggestionFeatureDefinition.POLL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package dev.sheldan.abstracto.suggestion.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListener;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListenerModel;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListenerResult;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberNameDisplay;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.exception.PollOptionAlreadyExistsException;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollType;
|
||||
import dev.sheldan.abstracto.suggestion.model.payload.PollAddOptionModalPayload;
|
||||
import dev.sheldan.abstracto.suggestion.model.template.PollAddOptionNotificationModel;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import dev.sheldan.abstracto.suggestion.service.management.PollManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ServerPollAddOptionModalListener implements ModalInteractionListener {
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Autowired
|
||||
private ServerPollAddOptionModalListener self;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private PollManagementService pollManagementService;
|
||||
|
||||
private static final String POLL_ADD_OPTION_NOTIFICATION = "poll_add_option_notification";
|
||||
|
||||
@Override
|
||||
public ModalInteractionListenerResult execute(ModalInteractionListenerModel model) {
|
||||
PollAddOptionModalPayload payload = (PollAddOptionModalPayload) model.getDeserializedPayload();
|
||||
log.info("Handling modal event to add options to poll {} in server {} by member {}.", payload.getPollId(), payload.getServerId(), model.getEvent().getMember().getIdLong());
|
||||
String labelContent = model
|
||||
.getEvent()
|
||||
.getValues()
|
||||
.stream()
|
||||
.filter(modalMapping -> modalMapping.getId().equals(payload.getLabelInputComponentId()))
|
||||
.map(ModalMapping::getAsString)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
Poll affectedPoll = pollManagementService.getPollByPollId(payload.getPollId(), payload.getServerId(), PollType.STANDARD);
|
||||
if(affectedPoll.getOptions().stream().anyMatch(pollOption -> pollOption.getLabel().equals(labelContent))) {
|
||||
throw new PollOptionAlreadyExistsException();
|
||||
}
|
||||
|
||||
String descriptionContent = model
|
||||
.getEvent()
|
||||
.getValues()
|
||||
.stream()
|
||||
.filter(modalMapping -> modalMapping.getId().equals(payload.getDescriptionInputComponentId()))
|
||||
.map(ModalMapping::getAsString)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
PollAddOptionNotificationModel pollAddOptionNotificationModel = PollAddOptionNotificationModel
|
||||
.builder()
|
||||
.description(descriptionContent)
|
||||
.memberNameDisplay(MemberNameDisplay.fromMember(model.getEvent().getMember()))
|
||||
.label(labelContent)
|
||||
.value(labelContent)
|
||||
.pollId(payload.getPollId())
|
||||
.serverId(payload.getServerId())
|
||||
.build();
|
||||
|
||||
|
||||
model.getEvent().deferReply(true).queue(interactionHook -> {
|
||||
self.updatePoll(model, payload, labelContent, descriptionContent);
|
||||
FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(POLL_ADD_OPTION_NOTIFICATION, pollAddOptionNotificationModel, model.getEvent().getInteraction().getHook())).thenAccept(unused -> {
|
||||
log.info("Send notification about successfully adding option to poll {} in server {} to member {}", payload.getPollId(), payload.getServerId(), model.getEvent().getMember().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.info("Failed to send notification about adding option to poll {} in server {} to member {}", payload.getPollId(), payload.getServerId(), model.getEvent().getMember().getIdLong());
|
||||
return null;
|
||||
});
|
||||
}, throwable -> {
|
||||
log.error("Failed to acknowledge modal interaction for poll add option modal listener in guild {}.", model.getServerId(), throwable);
|
||||
});
|
||||
|
||||
return ModalInteractionListenerResult.ACKNOWLEDGED;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updatePoll(ModalInteractionListenerModel model, PollAddOptionModalPayload payload, String labelContent, String descriptionContent) {
|
||||
pollService.addOptionToServerPoll(payload.getPollId(), payload.getServerId(), model.getEvent().getMember(), labelContent, descriptionContent).thenAccept(unused -> {
|
||||
log.info("Added option to poll {} in server {} by member {}.", payload.getPollId(), payload.getServerId(), model.getEvent().getMember().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to add option to poll {} in server {} by member {}.",
|
||||
payload.getPollId(), payload.getServerId(), model.getEvent().getMember().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return SuggestionFeatureDefinition.POLL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ModalInteractionListenerModel model) {
|
||||
return ServerPollAddOptionButtonListener.SERVER_POLL_ADD_OPTION_MODAL_ORIGIN.equals(model.getOrigin());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package dev.sheldan.abstracto.suggestion.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.menu.listener.StringSelectMenuListener;
|
||||
import dev.sheldan.abstracto.core.interaction.menu.listener.StringSelectMenuListenerModel;
|
||||
import dev.sheldan.abstracto.core.interaction.menu.listener.StringSelectMenuListenerResult;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberNameDisplay;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollType;
|
||||
import dev.sheldan.abstracto.suggestion.model.template.PollDecisionNotificationModel;
|
||||
import dev.sheldan.abstracto.suggestion.model.payload.ServerPollSelectionMenuPayload;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollServiceBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ServerPollDecisionListener implements StringSelectMenuListener {
|
||||
|
||||
@Autowired
|
||||
private PollService pollService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
private static final String POLL_DECISION_NOTIFICATION = "poll_decision_notification";
|
||||
|
||||
@Override
|
||||
public StringSelectMenuListenerResult execute(StringSelectMenuListenerModel model) {
|
||||
StringSelectInteractionEvent event = model.getEvent();
|
||||
ServerPollSelectionMenuPayload payload = (ServerPollSelectionMenuPayload) model.getDeserializedPayload();
|
||||
PollDecisionNotificationModel notificationModel = PollDecisionNotificationModel
|
||||
.builder()
|
||||
.chosenValues(event.getValues())
|
||||
.pollId(payload.getPollId())
|
||||
.memberNameDisplay(MemberNameDisplay.fromMember(event.getMember()))
|
||||
.serverId(model.getServerId())
|
||||
.build();
|
||||
pollService.setDecisionsInPollTo(event.getMember(), event.getValues(), payload.getPollId(), PollType.STANDARD)
|
||||
.thenCompose(unused -> FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(POLL_DECISION_NOTIFICATION, notificationModel, event.getInteraction().getHook())))
|
||||
.exceptionally(throwable -> {
|
||||
log.info("Failed to member {} in server {} about decision in poll {}.", event.getMember().getIdLong(), model.getServerId(), payload.getPollId(), throwable);
|
||||
return null;
|
||||
}).thenAccept(unused1 -> {
|
||||
log.info("Notified member {} in server {} about decision in poll {}.", event.getMember().getIdLong(), model.getServerId(), payload.getPollId());
|
||||
});
|
||||
return StringSelectMenuListenerResult.ACKNOWLEDGED;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(StringSelectMenuListenerModel model) {
|
||||
return model.getOrigin().equals(PollServiceBean.SERVER_POLL_SELECTION_MENU_ORIGIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return SuggestionFeatureDefinition.POLL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.abstracto.suggestion.repository;
|
||||
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollOption;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface PollOptionRepository extends JpaRepository<PollOption, Long> {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.abstracto.suggestion.repository;
|
||||
|
||||
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollType;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface PollRepository extends JpaRepository<Poll, Long> {
|
||||
Optional<Poll> findByPollIdAndServer_IdAndType(Long pollId, Long serverId, PollType pollType);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.abstracto.suggestion.repository;
|
||||
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollUserDecisionOption;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface PollUserDecisionOptionRepository extends JpaRepository<PollUserDecisionOption, Long> {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.abstracto.suggestion.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollUserDecision;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface PollUserDecisionRepository extends JpaRepository<PollUserDecision, Long> {
|
||||
Optional<PollUserDecision> findPollUserDecisionByPollAndVoter(Poll poll, AUserInAServer voter);
|
||||
}
|
||||
@@ -0,0 +1,567 @@
|
||||
package dev.sheldan.abstracto.suggestion.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadManagementService;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentService;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.button.ButtonConfigModel;
|
||||
import dev.sheldan.abstracto.core.interaction.menu.SelectMenuConfigModel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberNameDisplay;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
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.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.core.utils.MessageUtils;
|
||||
import dev.sheldan.abstracto.scheduling.model.JobParameters;
|
||||
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
|
||||
import dev.sheldan.abstracto.suggestion.config.PollFeatureMode;
|
||||
import dev.sheldan.abstracto.suggestion.config.PollPostTarget;
|
||||
import dev.sheldan.abstracto.suggestion.config.SuggestionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.suggestion.exception.PollCancellationNotPossibleException;
|
||||
import dev.sheldan.abstracto.suggestion.exception.PollOptionAlreadyExistsException;
|
||||
import dev.sheldan.abstracto.suggestion.model.payload.PollAddOptionButtonPayload;
|
||||
import dev.sheldan.abstracto.suggestion.model.PollCreationRequest;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.*;
|
||||
import dev.sheldan.abstracto.suggestion.model.payload.QuickPollSelectionMenuPayload;
|
||||
import dev.sheldan.abstracto.suggestion.model.template.*;
|
||||
import dev.sheldan.abstracto.suggestion.model.payload.ServerPollSelectionMenuPayload;
|
||||
import dev.sheldan.abstracto.suggestion.service.management.PollManagementService;
|
||||
import dev.sheldan.abstracto.suggestion.service.management.PollOptionManagementService;
|
||||
import dev.sheldan.abstracto.suggestion.service.management.PollUserDecisionManagementService;
|
||||
import dev.sheldan.abstracto.suggestion.service.management.PollUserDecisionOptionManagementService;
|
||||
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.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class PollServiceBean implements PollService {
|
||||
|
||||
@Autowired
|
||||
private CounterService counterService;
|
||||
|
||||
@Autowired
|
||||
private PollManagementService pollManagementService;
|
||||
|
||||
@Autowired
|
||||
private PollOptionManagementService pollOptionManagementService;
|
||||
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ComponentService componentService;
|
||||
|
||||
@Autowired
|
||||
private ComponentPayloadManagementService componentPayloadManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private PollUserDecisionManagementService pollUserDecisionManagementService;
|
||||
|
||||
@Autowired
|
||||
private PollUserDecisionOptionManagementService pollUserDecisionOptionManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private SchedulerService schedulerService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private PollServiceBean self;
|
||||
|
||||
private static final String POLLS_COUNTER_KEY = "POLLS";
|
||||
public static final String SERVER_POLL_SELECTION_MENU_ORIGIN = "SERVER_POLL_SELECTION_MENU";
|
||||
public static final String SERVER_POLL_ADD_OPTION_ORIGIN = "SERVER_POLL_ADD_OPTION_BUTTON";
|
||||
private static final String SERVER_POLL_TEMPLATE_KEY = "poll_server_message";
|
||||
private static final String SERVER_POLL_CLOSE_MESSAGE = "poll_server_close_message";
|
||||
private static final String SERVER_POLL_REMINDER_TEMPLATE_KEY = "poll_server_reminder_message";
|
||||
private static final String SERVER_POLL_EVALUATION_UPDATE_TEMPLATE_KEY = "poll_server_evaluation_update_message";
|
||||
private static final String QUICK_POLLS_COUNTER_KEY = "QUICK_POLLS";
|
||||
public static final String QUICK_POLL_SELECTION_MENU_ORIGIN = "QUICK_POLL_SELECTION_MENU";
|
||||
private static final String QUICK_POLL_TEMPLATE_KEY = "poll_quick_message";
|
||||
private static final String QUICK_POLL_EVALUATION_UPDATE_TEMPLATE_KEY = "poll_quick_evaluation_update_message";
|
||||
|
||||
@Value("${abstracto.feature.poll.removalMaxAge}")
|
||||
private Long removalMaxAgeSeconds;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CompletableFuture<Void> createServerPoll(Member creator, List<String> options, String description,
|
||||
Boolean allowMultiple, Boolean allowAddition, Boolean showDecisions, Duration pollDuration) {
|
||||
Long serverId = creator.getGuild().getIdLong();
|
||||
HashSet<String> optionAsSet = new HashSet<>(options);
|
||||
if(optionAsSet.size() != options.size()) {
|
||||
throw new PollOptionAlreadyExistsException();
|
||||
}
|
||||
Long pollId = counterService.getNextCounterValue(serverId, POLLS_COUNTER_KEY);
|
||||
log.info("Creating server poll {} in server {} because of user {}.", pollId, serverId, creator.getIdLong());
|
||||
List<PollMessageOption> parsedOptions = parseOptions(options);
|
||||
String selectionMenuId = componentService.generateComponentId();
|
||||
String addOptionButtonId = componentService.generateComponentId();
|
||||
if(pollDuration == null) {
|
||||
Long pollDurationSeconds = configService.getLongValueOrConfigDefault(PollService.SERVER_POLL_DURATION_SECONDS, serverId);
|
||||
log.info("No duration provided - using {} seconds from configuration.", pollDurationSeconds);
|
||||
pollDuration = Duration.ofSeconds(pollDurationSeconds);
|
||||
}
|
||||
Instant targetDate = Instant.now().plus(pollDuration);
|
||||
HashMap<Object, Object> parameters = new HashMap<>();
|
||||
parameters.put("serverId", serverId.toString());
|
||||
parameters.put("pollId", pollId.toString());
|
||||
JobParameters jobParameters = JobParameters.builder().parameters(parameters).build();
|
||||
String triggerKey = null;
|
||||
if(featureModeService.featureModeActive(SuggestionFeatureDefinition.POLL, serverId, PollFeatureMode.POLL_AUTO_EVALUATE)) {
|
||||
log.info("Creating scheduled job to evaluate poll {} in server {} at {}.", pollId, serverId, targetDate);
|
||||
triggerKey = schedulerService.executeJobWithParametersOnce("serverPollEvaluationJob", "poll", jobParameters, Date.from(targetDate));
|
||||
}
|
||||
String reminderTriggerKey = null;
|
||||
if(featureModeService.featureModeActive(SuggestionFeatureDefinition.POLL, serverId, PollFeatureMode.POLL_REMINDER)) {
|
||||
log.info("Creating scheduled job to remind about poll {} in server {} at {}.", pollId, serverId, targetDate);
|
||||
reminderTriggerKey = schedulerService.executeJobWithParametersOnce("serverPollReminderJob", "poll", jobParameters, Date.from(targetDate));
|
||||
}
|
||||
PollCreationRequest pollCreationRequest = PollCreationRequest
|
||||
.builder()
|
||||
.pollId(pollId)
|
||||
.type(PollType.STANDARD)
|
||||
.allowAddition(allowAddition)
|
||||
.allowMultiple(allowMultiple)
|
||||
.showDecisions(showDecisions)
|
||||
.addOptionButtonId(addOptionButtonId)
|
||||
.reminderJobTrigger(reminderTriggerKey)
|
||||
.selectionMenuId(selectionMenuId)
|
||||
.serverId(serverId)
|
||||
.evaluationJobTrigger(triggerKey)
|
||||
.targetDate(targetDate)
|
||||
.creatorId(creator.getIdLong())
|
||||
.description(description)
|
||||
.options(parsedOptions)
|
||||
.build();
|
||||
|
||||
ServerPollMessageModel model = ServerPollMessageModel
|
||||
.builder()
|
||||
.creator(MemberDisplay.fromMember(creator))
|
||||
.description(description)
|
||||
.pollId(pollId)
|
||||
.state(PollState.NEW)
|
||||
.allowMultiple(allowMultiple)
|
||||
.showDecisions(showDecisions)
|
||||
.allowAdditions(allowAddition)
|
||||
.endDate(targetDate)
|
||||
.options(parsedOptions)
|
||||
.addOptionButtonId(addOptionButtonId)
|
||||
.selectionMenuId(selectionMenuId)
|
||||
.build();
|
||||
ServerPollSelectionMenuPayload payload = ServerPollSelectionMenuPayload
|
||||
.builder()
|
||||
.serverId(serverId)
|
||||
.pollId(pollId)
|
||||
.build();
|
||||
SelectMenuConfigModel selectMenuConfigModel = SelectMenuConfigModel
|
||||
.builder()
|
||||
.selectMenuId(selectionMenuId)
|
||||
.origin(SERVER_POLL_SELECTION_MENU_ORIGIN)
|
||||
.selectMenuPayload(payload)
|
||||
.payloadType(ServerPollSelectionMenuPayload.class)
|
||||
.build();
|
||||
componentPayloadManagementService.createStringSelectMenuPayload(selectMenuConfigModel, serverId);
|
||||
PollAddOptionButtonPayload buttonPayload = PollAddOptionButtonPayload
|
||||
.builder()
|
||||
.serverId(serverId)
|
||||
.pollId(pollId)
|
||||
.build();
|
||||
ButtonConfigModel buttonConfigModel = ButtonConfigModel
|
||||
.builder()
|
||||
.buttonId(addOptionButtonId)
|
||||
.buttonPayload(buttonPayload)
|
||||
.origin(SERVER_POLL_ADD_OPTION_ORIGIN)
|
||||
.payloadType(PollAddOptionButtonPayload.class)
|
||||
.build();
|
||||
componentPayloadManagementService.createButtonPayload(buttonConfigModel, serverId);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SERVER_POLL_TEMPLATE_KEY, model);
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, PollPostTarget.POLLS, serverId);
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures)
|
||||
.thenAccept(unused -> self.persistPoll(messageFutures.get(0).join(), pollCreationRequest));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createQuickPoll(Member creator, List<String> options, String description,
|
||||
Boolean allowMultiple, Boolean showDecisions, InteractionHook interactionHook, Duration pollDuration) {
|
||||
HashSet<String> optionAsSet = new HashSet<>(options);
|
||||
if(optionAsSet.size() != options.size()) {
|
||||
throw new PollOptionAlreadyExistsException();
|
||||
}
|
||||
Long serverId = creator.getGuild().getIdLong();
|
||||
Long pollId = counterService.getNextCounterValue(serverId, QUICK_POLLS_COUNTER_KEY);
|
||||
log.info("Creating quick poll {} in server {} because of user {}.", pollId, serverId, creator.getIdLong());
|
||||
List<PollMessageOption> parsedOptions = parseOptions(options);
|
||||
String selectionMenuId = componentService.generateComponentId();
|
||||
if(pollDuration == null) {
|
||||
Long pollDurationSeconds = configService.getLongValueOrConfigDefault(PollService.QUICK_POLL_DURATION_SECONDS, serverId);
|
||||
log.info("No duration provided - using {} seconds from configuration.", pollDurationSeconds);
|
||||
pollDuration = Duration.ofSeconds(pollDurationSeconds);
|
||||
}
|
||||
Instant targetDate = Instant.now().plus(pollDuration);
|
||||
HashMap<Object, Object> parameters = new HashMap<>();
|
||||
parameters.put("serverId", serverId.toString());
|
||||
parameters.put("pollId", pollId.toString());
|
||||
JobParameters jobParameters = JobParameters.builder().parameters(parameters).build();
|
||||
String triggerKey = schedulerService.executeJobWithParametersOnce("quickPollEvaluationJob", "poll", jobParameters, Date.from(targetDate));
|
||||
log.info("Starting scheduled job to evaluate quick poll.");
|
||||
PollCreationRequest pollCreationRequest = PollCreationRequest
|
||||
.builder()
|
||||
.pollId(pollId)
|
||||
.type(PollType.QUICK)
|
||||
.allowMultiple(allowMultiple)
|
||||
.evaluationJobTrigger(triggerKey)
|
||||
.showDecisions(showDecisions)
|
||||
.selectionMenuId(selectionMenuId)
|
||||
.serverId(serverId)
|
||||
.allowAddition(false)
|
||||
.targetDate(targetDate)
|
||||
.creatorId(creator.getIdLong())
|
||||
.description(description)
|
||||
.options(parsedOptions)
|
||||
.build();
|
||||
|
||||
QuickPollMessageModel model = QuickPollMessageModel
|
||||
.builder()
|
||||
.creator(MemberDisplay.fromMember(creator))
|
||||
.description(description)
|
||||
.pollId(pollId)
|
||||
.allowMultiple(allowMultiple)
|
||||
.showDecisions(showDecisions)
|
||||
.endDate(targetDate)
|
||||
.options(parsedOptions)
|
||||
.selectionMenuId(selectionMenuId)
|
||||
.build();
|
||||
QuickPollSelectionMenuPayload payload = QuickPollSelectionMenuPayload
|
||||
.builder()
|
||||
.serverId(serverId)
|
||||
.pollId(pollId)
|
||||
.build();
|
||||
SelectMenuConfigModel selectMenuConfigModel = SelectMenuConfigModel
|
||||
.builder()
|
||||
.selectMenuId(selectionMenuId)
|
||||
.origin(QUICK_POLL_SELECTION_MENU_ORIGIN)
|
||||
.selectMenuPayload(payload)
|
||||
.payloadType(QuickPollSelectionMenuPayload.class)
|
||||
.build();
|
||||
componentPayloadManagementService.createStringSelectMenuPayload(selectMenuConfigModel, serverId);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(QUICK_POLL_TEMPLATE_KEY, model);
|
||||
List<CompletableFuture<Message>> messageFutures = interactionService.sendMessageToInteraction(messageToSend, interactionHook);
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures)
|
||||
.thenAccept(unused -> self.persistPoll(messageFutures.get(0).join(), pollCreationRequest));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> setDecisionsInPollTo(Member voter, List<String> chosenValues, Long pollId, PollType pollType) {
|
||||
Poll poll = pollManagementService.getPollByPollId(pollId, voter.getGuild().getIdLong(), pollType);
|
||||
log.info("Adding decisions of user {} to poll {}.", voter.getIdLong(), poll.getPollId());
|
||||
AUserInAServer userInServer = userInServerManagementService.loadOrCreateUser(voter);
|
||||
Optional<PollUserDecision> decisionOptional = pollUserDecisionManagementService.getUserDecisionOptional(poll, userInServer);
|
||||
PollUserDecision decision;
|
||||
boolean needToSave = false;
|
||||
if(decisionOptional.isPresent()) {
|
||||
decision = decisionOptional.get();
|
||||
} else {
|
||||
needToSave = true;
|
||||
decision = pollUserDecisionManagementService.createUserDecision(poll, userInServer);
|
||||
}
|
||||
Long optionsAdded = 0L;
|
||||
for (PollOption pollOption : poll.getOptions()) {
|
||||
if (chosenValues.contains(pollOption.getValue()) &&
|
||||
(decision.getOptions() == null || decision.getOptions().stream().noneMatch(pollUserDecisionOption -> pollUserDecisionOption.getPollOption().getLabel().equals(pollOption.getValue())))) {
|
||||
pollUserDecisionOptionManagementService.addDecisionForUser(decision, pollOption);
|
||||
optionsAdded += 1;
|
||||
}
|
||||
}
|
||||
log.info("Added {} options to poll {} for user {}.", optionsAdded, pollId, voter.getIdLong());
|
||||
|
||||
if(decision.getOptions() != null) {
|
||||
List<PollUserDecisionOption> toRemove = decision
|
||||
.getOptions()
|
||||
.stream()
|
||||
.filter(pollUserDecisionOption -> !chosenValues.contains(pollUserDecisionOption.getPollOption().getLabel()))
|
||||
.collect(Collectors.toList());
|
||||
log.info("Removing {} options from poll {} for user {}.", toRemove.size(), pollId, voter.getIdLong());
|
||||
pollUserDecisionOptionManagementService.deleteDecisionOptions(decision, toRemove);
|
||||
}
|
||||
if(needToSave) {
|
||||
pollUserDecisionManagementService.savePollUserDecision(decision);
|
||||
}
|
||||
if(poll.getShowDecisions()) {
|
||||
return updatePollMessage(poll, voter.getGuild());
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> addOptionToServerPoll(Long pollId, Long serverId, Member adder, String label, String description) {
|
||||
Poll poll = pollManagementService.getPollByPollId(pollId, serverId, PollType.STANDARD);
|
||||
log.info("Adding option to server poll {} in server {}.", pollId, serverId);
|
||||
pollOptionManagementService.addOptionToPoll(poll, label, description);
|
||||
List<PollMessageOption> options = getOptionsOfPoll(poll);
|
||||
ServerPollMessageModel model = ServerPollMessageModel.fromPoll(poll, options);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SERVER_POLL_TEMPLATE_KEY, model);
|
||||
MessageChannel pollChannel = adder.getGuild().getChannelById(MessageChannel.class, poll.getChannel().getId());
|
||||
List<CompletableFuture<Message>> messageFutures = channelService.editMessagesInAChannelFuture(messageToSend, pollChannel, Arrays.asList(poll.getMessageId()));
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CompletableFuture<Void> evaluateServerPoll(Long pollId, Long serverId) {
|
||||
Poll poll = pollManagementService.getPollByPollId(pollId, serverId, PollType.STANDARD);
|
||||
log.info("Evaluating server poll {} in server {}.", pollId, serverId);
|
||||
poll.setState(PollState.FINISHED);
|
||||
List<PollMessageOption> allOptions = getOptionsOfPoll(poll);
|
||||
List<PollMessageOption> topOptions = allOptions;
|
||||
if(!allOptions.isEmpty()) {
|
||||
Integer mostVotes = allOptions
|
||||
.stream()
|
||||
.sorted(Comparator.comparingInt(PollMessageOption::getVotes).reversed())
|
||||
.collect(Collectors.toList()).get(0).getVotes();
|
||||
topOptions = allOptions
|
||||
.stream()
|
||||
.filter(pollMessageOption -> pollMessageOption.getVotes().equals(mostVotes))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
ServerPollEvaluationModel model = ServerPollEvaluationModel
|
||||
.builder()
|
||||
.pollId(pollId)
|
||||
.options(allOptions)
|
||||
.pollMessageId(poll.getMessageId())
|
||||
.topOptions(topOptions)
|
||||
.description(poll.getDescription())
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SERVER_POLL_EVALUATION_UPDATE_TEMPLATE_KEY, model);
|
||||
log.info("Sending update message for poll evaluation of server poll {} in server {}.", pollId, serverId);
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, PollPostTarget.POLLS, serverId);
|
||||
GuildMessageChannel channel = channelService.getMessageChannelFromServer(serverId, poll.getChannel().getId());
|
||||
log.info("Cleaning existing components in message {} for server poll {} in server {}.", poll.getMessageId(), pollId, serverId);
|
||||
CompletableFuture<Message> cleanMessageFuture = channelService.removeComponents(channel, poll.getMessageId());
|
||||
return CompletableFuture.allOf(FutureUtils.toSingleFutureGeneric(messageFutures), cleanMessageFuture)
|
||||
.thenAccept(unused -> self.updateFinalPollMessage(pollId, channel.getGuild()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CompletableFuture<Void> remindServerPoll(Long pollId, Long serverId) {
|
||||
Poll poll = pollManagementService.getPollByPollId(pollId, serverId, PollType.STANDARD);
|
||||
log.info("Reminding about server poll {} in server {}.", pollId, serverId);
|
||||
List<PollMessageOption> allOptions = getOptionsOfPoll(poll);
|
||||
List<PollMessageOption> topOptions = allOptions;
|
||||
if(!allOptions.isEmpty()) {
|
||||
Integer mostVotes = allOptions
|
||||
.stream()
|
||||
.sorted(Comparator.comparingInt(PollMessageOption::getVotes).reversed())
|
||||
.collect(Collectors.toList()).get(0).getVotes();
|
||||
topOptions = allOptions
|
||||
.stream()
|
||||
.filter(pollMessageOption -> pollMessageOption.getVotes().equals(mostVotes))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
ServerPollReminderModel model = ServerPollReminderModel
|
||||
.builder()
|
||||
.pollId(pollId)
|
||||
.options(allOptions)
|
||||
.topOptions(topOptions)
|
||||
.messageLink(MessageUtils.buildMessageUrl(serverId, poll.getChannel().getId(), poll.getMessageId()))
|
||||
.description(poll.getDescription())
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SERVER_POLL_REMINDER_TEMPLATE_KEY, model);
|
||||
log.info("Sending poll reminder about server poll {} in server {}.", pollId, serverId);
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, PollPostTarget.POLL_REMINDER, serverId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CompletableFuture<Void> evaluateQuickPoll(Long pollId, Long serverId) {
|
||||
Poll poll = pollManagementService.getPollByPollId(pollId, serverId, PollType.QUICK);
|
||||
log.info("Evaluating quick poll {} in server {}.", pollId, serverId);
|
||||
poll.setState(PollState.FINISHED);
|
||||
List<PollMessageOption> allOptions = getOptionsOfPoll(poll);
|
||||
List<PollMessageOption> topOptions = allOptions;
|
||||
if(!allOptions.isEmpty()) {
|
||||
Integer mostVotes = allOptions
|
||||
.stream()
|
||||
.sorted(Comparator.comparingInt(PollMessageOption::getVotes).reversed())
|
||||
.collect(Collectors.toList()).get(0).getVotes();
|
||||
topOptions = allOptions
|
||||
.stream()
|
||||
.filter(pollMessageOption -> pollMessageOption.getVotes().equals(mostVotes))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
QuickPollEvaluationModel model = QuickPollEvaluationModel
|
||||
.builder()
|
||||
.pollId(pollId)
|
||||
.options(allOptions)
|
||||
.pollMessageId(poll.getMessageId())
|
||||
.topOptions(topOptions)
|
||||
.description(poll.getDescription())
|
||||
.build();
|
||||
MessageChannel channel = channelService.getMessageChannelFromServer(serverId, poll.getChannel().getId());
|
||||
CompletableFuture<Message> removeComponentFuture = channelService.removeComponents(channel, poll.getMessageId());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(QUICK_POLL_EVALUATION_UPDATE_TEMPLATE_KEY, model);
|
||||
CompletableFuture<Void> updateMessageFuture = FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, channel));
|
||||
return CompletableFuture.allOf(removeComponentFuture, updateMessageFuture)
|
||||
.thenApply(message -> null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> closePoll(Long pollId, Long serverId, String text, Member cause) {
|
||||
Poll poll = pollManagementService.getPollByPollId(pollId, serverId, PollType.STANDARD);
|
||||
log.info("Member {} closes poll {} in server {}.", cause.getIdLong(), pollId, serverId);
|
||||
PollClosingMessageModel model = PollClosingMessageModel
|
||||
.builder()
|
||||
.pollMessageId(poll.getMessageId())
|
||||
.cause(MemberNameDisplay.fromMember(cause))
|
||||
.pollId(pollId)
|
||||
.text(text)
|
||||
.serverId(serverId)
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SERVER_POLL_CLOSE_MESSAGE, model);
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, PollPostTarget.POLLS, serverId);
|
||||
MessageChannel channel = channelService.getMessageChannelFromServer(serverId, poll.getChannel().getId());
|
||||
CompletableFuture<Message> removeComponentsFuture = channelService.removeComponents(channel, poll.getMessageId());
|
||||
return CompletableFuture.allOf(FutureUtils.toSingleFutureGeneric(messageFutures), removeComponentsFuture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> cancelPoll(Long pollId, Long serverId, Member cause) {
|
||||
Poll poll = pollManagementService.getPollByPollId(pollId, serverId, PollType.STANDARD);
|
||||
log.info("Member {} cancelled poll {} in server {}.", cause.getIdLong(), pollId, serverId);
|
||||
if(!poll.getCreator().getUserReference().getId().equals(cause.getIdLong()) ||
|
||||
poll.getCreated().isBefore(Instant.now().minus(Duration.ofSeconds(removalMaxAgeSeconds)))) {
|
||||
throw new PollCancellationNotPossibleException();
|
||||
}
|
||||
if(poll.getReminderJobTriggerKey() != null) {
|
||||
schedulerService.stopTrigger(poll.getReminderJobTriggerKey());
|
||||
}
|
||||
if(poll.getEvaluationJobTriggerKey() != null) {
|
||||
schedulerService.stopTrigger(poll.getEvaluationJobTriggerKey());
|
||||
}
|
||||
poll.setState(PollState.CANCELLED);
|
||||
return messageService.deleteMessageInChannelInServer(serverId, poll.getChannel().getId(), poll.getMessageId());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> updateFinalPollMessage(Long pollId, Guild guild) {
|
||||
Poll poll = pollManagementService.getPollByPollId(pollId, guild.getIdLong(), PollType.STANDARD);
|
||||
List<PollMessageOption> options = getOptionsOfPoll(poll);
|
||||
ServerPollMessageModel model = ServerPollMessageModel.fromPoll(poll, options);
|
||||
model.setAllowAdditions(false);
|
||||
model.setShowDecisions(true);
|
||||
model.setAllowMultiple(false);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SERVER_POLL_TEMPLATE_KEY, model);
|
||||
MessageChannel pollChannel = guild.getChannelById(MessageChannel.class, poll.getChannel().getId());
|
||||
return channelService.editEmbedMessageInAChannel(messageToSend.getEmbeds().get(0), pollChannel, poll.getMessageId())
|
||||
.thenApply(message -> null);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> updatePollMessage(Poll poll, Guild guild) {
|
||||
List<PollMessageOption> options = getOptionsOfPoll(poll);
|
||||
ServerPollMessageModel model = ServerPollMessageModel.fromPoll(poll, options);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SERVER_POLL_TEMPLATE_KEY, model);
|
||||
MessageChannel pollChannel = guild.getChannelById(MessageChannel.class, poll.getChannel().getId());
|
||||
return channelService.editEmbedMessageInAChannel(messageToSend.getEmbeds().get(0), pollChannel, poll.getMessageId())
|
||||
.thenApply(message -> null);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void persistPoll(Message message, PollCreationRequest pollCreationRequest) {
|
||||
if(message == null) {
|
||||
log.info("Post target was not setup - no message created.");
|
||||
return;
|
||||
}
|
||||
pollCreationRequest.setPollMessageId(message.getIdLong());
|
||||
pollCreationRequest.setPollChannelId(message.getChannel().getIdLong());
|
||||
log.info("Persisting poll {} shown in message {} in channel {} in server {}.",
|
||||
pollCreationRequest.getPollId(), pollCreationRequest.getPollMessageId(), pollCreationRequest.getPollChannelId(),
|
||||
pollCreationRequest.getServerId());
|
||||
Poll createdPoll = pollManagementService.createPoll(pollCreationRequest);
|
||||
log.info("Adding {} options to poll {}.", pollCreationRequest.getOptions().size(), pollCreationRequest.getPollId());
|
||||
pollOptionManagementService.addOptionsToPoll(createdPoll, pollCreationRequest);
|
||||
}
|
||||
|
||||
private List<PollMessageOption> parseOptions(List<String> options) {
|
||||
return options.stream().map(s -> {
|
||||
String label = s;
|
||||
String description = "";
|
||||
if(s.contains(";")) {
|
||||
String[] splitOption = s.split(";");
|
||||
label = splitOption[0];
|
||||
description = splitOption[1];
|
||||
}
|
||||
return PollMessageOption
|
||||
.builder()
|
||||
.label(label)
|
||||
.value(label)
|
||||
.votes(0)
|
||||
.percentage(0f)
|
||||
.description(description)
|
||||
.build();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<PollMessageOption> getOptionsOfPoll(Poll poll) {
|
||||
Integer totalVotes = poll
|
||||
.getDecisions()
|
||||
.stream()
|
||||
.map(userDecision -> userDecision.getOptions().size())
|
||||
.mapToInt(Integer::intValue)
|
||||
.sum();
|
||||
return poll.getOptions().stream().map(option -> {
|
||||
Long voteCount = poll
|
||||
.getDecisions()
|
||||
.stream()
|
||||
.filter(decision -> decision.getOptions().stream().anyMatch(pollUserDecisionOption -> pollUserDecisionOption.getPollOption().equals(option)))
|
||||
.count();
|
||||
return PollMessageOption
|
||||
.builder()
|
||||
.value(option.getValue())
|
||||
.label(option.getLabel())
|
||||
.votes(voteCount.intValue())
|
||||
.percentage(totalVotes > 0 ? (voteCount / (float) totalVotes) * 100 : 0)
|
||||
.description(option.getDescription())
|
||||
.build();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package dev.sheldan.abstracto.suggestion.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
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.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.suggestion.exception.PollNotFoundException;
|
||||
import dev.sheldan.abstracto.suggestion.model.PollCreationRequest;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollState;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollType;
|
||||
import dev.sheldan.abstracto.suggestion.repository.PollRepository;
|
||||
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 PollManagementServiceBean implements PollManagementService {
|
||||
|
||||
@Autowired
|
||||
private PollRepository pollRepository;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Override
|
||||
public Poll createPoll(PollCreationRequest pollCreationRequest) {
|
||||
ServerUser creatorServerUser = ServerUser
|
||||
.builder()
|
||||
.userId(pollCreationRequest.getCreatorId())
|
||||
.serverId(pollCreationRequest.getServerId())
|
||||
.build();
|
||||
AUserInAServer creator = userInServerManagementService.loadOrCreateUser(creatorServerUser);
|
||||
AChannel channel = channelManagementService.loadChannel(pollCreationRequest.getPollChannelId());
|
||||
Poll pollInstance = Poll
|
||||
.builder()
|
||||
.description(pollCreationRequest.getDescription())
|
||||
.server(creator.getServerReference())
|
||||
.pollId(pollCreationRequest.getPollId())
|
||||
.allowMultiple(pollCreationRequest.getAllowMultiple())
|
||||
.allowAddition(pollCreationRequest.getAllowAddition())
|
||||
.showDecisions(pollCreationRequest.getShowDecisions())
|
||||
.reminderJobTriggerKey(pollCreationRequest.getReminderJobTrigger())
|
||||
.targetDate(pollCreationRequest.getTargetDate())
|
||||
.evaluationJobTriggerKey(pollCreationRequest.getEvaluationJobTrigger())
|
||||
.messageId(pollCreationRequest.getPollMessageId())
|
||||
.channel(channel)
|
||||
.addOptionButtonId(pollCreationRequest.getAddOptionButtonId())
|
||||
.selectionMenuId(pollCreationRequest.getSelectionMenuId())
|
||||
.creator(creator)
|
||||
.state(PollState.NEW)
|
||||
.type(pollCreationRequest.getType())
|
||||
.build();
|
||||
return pollRepository.save(pollInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Poll getPollByPollId(Long pollId, Long serverId, PollType pollType) {
|
||||
return getPollByPollIdOptional(pollId, serverId, pollType).orElseThrow(() -> new PollNotFoundException(pollId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Poll> getPollByPollIdOptional(Long pollId, Long serverId, PollType pollType) {
|
||||
return pollRepository.findByPollIdAndServer_IdAndType(pollId, serverId, pollType);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dev.sheldan.abstracto.suggestion.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.suggestion.model.PollCreationRequest;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollOption;
|
||||
import dev.sheldan.abstracto.suggestion.repository.PollOptionRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class PollOptionManagementServiceBean implements PollOptionManagementService {
|
||||
|
||||
@Autowired
|
||||
private PollOptionRepository pollOptionRepository;
|
||||
|
||||
@Override
|
||||
public void addOptionsToPoll(Poll poll, PollCreationRequest pollCreationRequest) {
|
||||
List<PollOption> options = pollCreationRequest.getOptions().stream().map(option -> PollOption
|
||||
.builder()
|
||||
.poll(poll)
|
||||
.server(poll.getServer())
|
||||
.label(option.getLabel())
|
||||
.value(option.getLabel())
|
||||
.description(option.getDescription())
|
||||
.build()).collect(Collectors.toList());
|
||||
pollOptionRepository.saveAll(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOptionToPoll(Poll poll, String label, String description) {
|
||||
PollOption option = PollOption
|
||||
.builder()
|
||||
.poll(poll)
|
||||
.label(label)
|
||||
.value(label)
|
||||
.server(poll.getServer())
|
||||
.description(description)
|
||||
.build();
|
||||
pollOptionRepository.save(option);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PollOption> getPollOptionByName(Poll poll, String key) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.sheldan.abstracto.suggestion.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollUserDecision;
|
||||
import dev.sheldan.abstracto.suggestion.repository.PollUserDecisionRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class PollUserDecisionManagementServiceBean implements PollUserDecisionManagementService {
|
||||
|
||||
@Autowired
|
||||
private PollUserDecisionRepository repository;
|
||||
|
||||
@Override
|
||||
public PollUserDecision addUserDecision(Poll poll, AUserInAServer user) {
|
||||
return repository.save(createUserDecision(poll, user));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PollUserDecision createUserDecision(Poll poll, AUserInAServer user) {
|
||||
return PollUserDecision
|
||||
.builder()
|
||||
.server(user.getServerReference())
|
||||
.voter(user)
|
||||
.options(new ArrayList<>())
|
||||
.poll(poll)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PollUserDecision> getUserDecisionOptional(Poll poll, AUserInAServer user) {
|
||||
return repository.findPollUserDecisionByPollAndVoter(poll, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PollUserDecision getUserDecision(Poll poll, AUserInAServer user) {
|
||||
return repository.findPollUserDecisionByPollAndVoter(poll, user).orElseThrow(() -> new AbstractoRunTimeException("User decision not found."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void savePollUserDecision(PollUserDecision pollUserDecision) {
|
||||
repository.save(pollUserDecision);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package dev.sheldan.abstracto.suggestion.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollOption;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollUserDecision;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollUserDecisionOption;
|
||||
import dev.sheldan.abstracto.suggestion.repository.PollUserDecisionOptionRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class PollUserDecisionOptionManagementServiceBean implements PollUserDecisionOptionManagementService {
|
||||
|
||||
@Autowired
|
||||
private PollUserDecisionOptionRepository repository;
|
||||
|
||||
@Override
|
||||
public PollUserDecisionOption addDecisionForUser(PollUserDecision decision, PollOption pollOption) {
|
||||
PollUserDecisionOption option = PollUserDecisionOption
|
||||
.builder()
|
||||
.decision(decision)
|
||||
.poll(decision.getPoll())
|
||||
.pollOption(pollOption)
|
||||
.build();
|
||||
decision.getOptions().add(option);
|
||||
return option;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearOptions(PollUserDecision pollUserDecision) {
|
||||
repository.deleteAll(pollUserDecision.getOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDecisionOptions(PollUserDecision decision, List<PollUserDecisionOption> decisionOptionList) {
|
||||
decision.getOptions().removeAll(decisionOptionList);
|
||||
repository.deleteAll(decisionOptionList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<property name="pollFeature" value="(SELECT id FROM feature WHERE key = 'poll')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="poll-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="poll"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${pollFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="quickPoll"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${pollFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="closePoll"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${pollFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="cancelPoll"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${pollFeature}"/>
|
||||
</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.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="feature.xml" relativeToChangelogFile="true"/>
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
<include file="poll_jobs.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="poll_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="poll"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="poll_jobs-insert">
|
||||
<insert tableName="scheduler_job">
|
||||
<column name="name" value="serverPollEvaluationJob"/>
|
||||
<column name="group_name" value="poll"/>
|
||||
<column name="clazz" value="dev.sheldan.abstracto.suggestion.job.ServerPollEvaluationJob"/>
|
||||
<column name="active" value="true"/>
|
||||
<column name="recovery" value="false"/>
|
||||
</insert>
|
||||
<insert tableName="scheduler_job">
|
||||
<column name="name" value="quickPollEvaluationJob"/>
|
||||
<column name="group_name" value="poll"/>
|
||||
<column name="clazz" value="dev.sheldan.abstracto.suggestion.job.QuickPollEvaluationJob"/>
|
||||
<column name="active" value="true"/>
|
||||
<column name="recovery" value="false"/>
|
||||
</insert>
|
||||
<insert tableName="scheduler_job">
|
||||
<column name="name" value="serverPollReminderJob"/>
|
||||
<column name="group_name" value="poll"/>
|
||||
<column name="clazz" value="dev.sheldan.abstracto.suggestion.job.ServerPollReminderJob"/>
|
||||
<column name="active" value="true"/>
|
||||
<column name="recovery" value="false"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,89 @@
|
||||
<?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.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="poll-table">
|
||||
<createTable tableName="poll">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="poll_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="message_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="type" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="channel_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="state" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="selection_menu_id" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="add_option_button_id" type="VARCHAR(100)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="creator_user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(2000)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="evaluation_job_trigger_key" type="varchar(255)"/>
|
||||
<column name="reminder_job_trigger_key" type="varchar(255)"/>
|
||||
<column name="target_date" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="allow_multiple" type="BOOLEAN">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="show_decisions" type="BOOLEAN">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="allow_addition" type="BOOLEAN">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addUniqueConstraint
|
||||
columnNames="poll_id, server_id, type"
|
||||
constraintName="uq_poll_id"
|
||||
tableName="poll"
|
||||
/>
|
||||
<addForeignKeyConstraint baseColumnNames="channel_id" baseTableName="poll" constraintName="fk_poll_channel"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="channel" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="creator_user_in_server_id" baseTableName="poll" constraintName="fk_poll_creator"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="poll" constraintName="fk_poll_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS poll_update_trigger ON poll;
|
||||
CREATE TRIGGER poll_update_trigger BEFORE UPDATE ON poll FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS poll_insert_trigger ON poll;
|
||||
CREATE TRIGGER poll_insert_trigger BEFORE INSERT ON poll FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
ALTER TABLE poll ADD CONSTRAINT check_poll_state CHECK (state IN ('NEW', 'FINISHED','CANCELLED', 'VETOED'));
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,56 @@
|
||||
<?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.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="poll_option-table">
|
||||
<createTable tableName="poll_option">
|
||||
<column name="id" autoIncrement="true" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="poll_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="label" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="value" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="adder_user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addPrimaryKey columnNames="id" tableName="poll_option" constraintName="pk_poll_option" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="adder_user_in_server_id" baseTableName="poll_option" constraintName="fk_poll_option_adder"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="poll_option" constraintName="fk_poll_option_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="poll_id" baseTableName="poll_option" constraintName="fk_poll_option_poll"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="poll" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS poll_option_update_trigger ON poll_option;
|
||||
CREATE TRIGGER poll_option_update_trigger BEFORE UPDATE ON poll_option FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS poll_option_insert_trigger ON poll_option;
|
||||
CREATE TRIGGER poll_option_insert_trigger BEFORE INSERT ON poll_option FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="poll_user_decision-table">
|
||||
<createTable tableName="poll_user_decision">
|
||||
<column name="id" autoIncrement="true" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="poll_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addUniqueConstraint
|
||||
columnNames="user_in_server_id, poll_id"
|
||||
constraintName="uq_poll_user_decision"
|
||||
tableName="poll_user_decision"
|
||||
/>
|
||||
<addForeignKeyConstraint baseColumnNames="user_in_server_id" baseTableName="poll_user_decision" constraintName="fk_poll_user_decision_user"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="poll_user_decision" constraintName="fk_poll_user_decision_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="poll_id" baseTableName="poll_user_decision" constraintName="fk_poll_user_decision_poll"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="poll" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS poll_user_decision_update_trigger ON poll_user_decision;
|
||||
CREATE TRIGGER poll_user_decision_update_trigger BEFORE UPDATE ON poll_user_decision FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS poll_user_decision_insert_trigger ON poll_user_decision;
|
||||
CREATE TRIGGER poll_user_decision_insert_trigger BEFORE INSERT ON poll_user_decision FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="poll_user_decision_option-table">
|
||||
<createTable tableName="poll_user_decision_option">
|
||||
<column name="id" autoIncrement="true" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="user_decision_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="poll_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="option_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<addUniqueConstraint
|
||||
columnNames="user_decision_id, poll_id, option_id"
|
||||
constraintName="uq_poll_user_decision_option"
|
||||
tableName="poll_user_decision_option"
|
||||
/>
|
||||
<addForeignKeyConstraint baseColumnNames="user_decision_id" baseTableName="poll_user_decision_option" constraintName="fk_poll_user_decision_option_decision"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="poll_user_decision" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="option_id" baseTableName="poll_user_decision_option" constraintName="fk_poll_user_decision_option_option"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="poll_option" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="poll_id" baseTableName="poll_user_decision_option" constraintName="fk_poll_user_decision_option_poll"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="poll" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS poll_user_decision_option_update_trigger ON poll_user_decision_option;
|
||||
CREATE TRIGGER poll_user_decision_option_trigger BEFORE UPDATE ON poll_user_decision_option FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS poll_user_decision_option_insert_trigger ON poll_user_decision_option;
|
||||
CREATE TRIGGER poll_user_decision_option_insert_trigger BEFORE INSERT ON poll_user_decision_option FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?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.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="poll.xml" relativeToChangelogFile="true"/>
|
||||
<include file="poll_option.xml" relativeToChangelogFile="true"/>
|
||||
<include file="poll_user_decision.xml" relativeToChangelogFile="true"/>
|
||||
<include file="poll_user_decision_option.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -12,4 +12,5 @@
|
||||
<include file="1.3.8/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.0/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.8/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.26/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -30,4 +30,26 @@ abstracto.featureModes.suggestionAutoEvaluate.enabled=false
|
||||
|
||||
abstracto.featureModes.suggestionButton.featureName=suggestion
|
||||
abstracto.featureModes.suggestionButton.mode=suggestionButton
|
||||
abstracto.featureModes.suggestionButton.enabled=true
|
||||
abstracto.featureModes.suggestionButton.enabled=true
|
||||
|
||||
abstracto.featureFlags.poll.featureName=poll
|
||||
abstracto.featureFlags.poll.enabled=false
|
||||
|
||||
abstracto.postTargets.poll.name=polls
|
||||
abstracto.postTargets.pollReminder.name=pollReminder
|
||||
|
||||
abstracto.featureModes.pollAutoEvaluate.featureName=poll
|
||||
abstracto.featureModes.pollAutoEvaluate.mode=pollAutoEvaluate
|
||||
abstracto.featureModes.pollAutoEvaluate.enabled=false
|
||||
|
||||
abstracto.featureModes.pollReminder.featureName=poll
|
||||
abstracto.featureModes.pollReminder.mode=pollReminder
|
||||
abstracto.featureModes.pollReminder.enabled=false
|
||||
|
||||
abstracto.systemConfigs.serverPollDurationSeconds.name=serverPollDurationSeconds
|
||||
abstracto.systemConfigs.serverPollDurationSeconds.longValue=604800
|
||||
|
||||
abstracto.systemConfigs.quickPollDurationSeconds.name=quickPollDurationSeconds
|
||||
abstracto.systemConfigs.quickPollDurationSeconds.longValue=90
|
||||
|
||||
abstracto.feature.poll.removalMaxAge=3600
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>suggestion</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.23</version>
|
||||
<version>1.4.26</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.sheldan.abstracto.suggestion.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import dev.sheldan.abstracto.suggestion.service.PollService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class PollFeatureConfig implements FeatureConfig {
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return SuggestionFeatureDefinition.POLL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PostTargetEnum> getRequiredPostTargets() {
|
||||
return Arrays.asList(PollPostTarget.POLLS, PollPostTarget.POLL_REMINDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
return Arrays.asList(PollService.SERVER_POLL_DURATION_SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getAvailableModes() {
|
||||
return Arrays.asList(PollFeatureMode.POLL_AUTO_EVALUATE, PollFeatureMode.POLL_REMINDER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package dev.sheldan.abstracto.suggestion.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum PollFeatureMode implements FeatureMode {
|
||||
POLL_AUTO_EVALUATE("pollAutoEvaluate"),
|
||||
POLL_REMINDER("pollReminder");
|
||||
|
||||
private final String key;
|
||||
|
||||
PollFeatureMode(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.suggestion.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum PollPostTarget implements PostTargetEnum {
|
||||
POLLS("polls"), POLL_REMINDER("pollReminder");
|
||||
|
||||
private String key;
|
||||
|
||||
PollPostTarget(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -37,13 +37,16 @@ public class SuggestionFeatureConfig implements FeatureConfig {
|
||||
SuggestionFeatureMode.SUGGESTION_REMINDER,
|
||||
SuggestionFeatureMode.SUGGESTION_BUTTONS,
|
||||
SuggestionFeatureMode.SUGGESTION_AUTO_EVALUATE,
|
||||
SuggestionFeatureMode.SUGGESTION_THREAD);
|
||||
SuggestionFeatureMode.SUGGESTION_THREAD
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
return Arrays.asList(SuggestionService.SUGGESTION_REMINDER_DAYS_CONFIG_KEY,
|
||||
return Arrays.asList(
|
||||
SuggestionService.SUGGESTION_REMINDER_DAYS_CONFIG_KEY,
|
||||
SuggestionService.SUGGESTION_AUTO_EVALUATE_DAYS_CONFIG_KEY,
|
||||
SuggestionService.SUGGESTION_AUTO_EVALUATE_PERCENTAGE_CONFIG_KEY);
|
||||
SuggestionService.SUGGESTION_AUTO_EVALUATE_PERCENTAGE_CONFIG_KEY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum SuggestionFeatureDefinition implements FeatureDefinition {
|
||||
SUGGEST("suggestion");
|
||||
SUGGEST("suggestion"), POLL("poll");
|
||||
|
||||
private String key;
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package dev.sheldan.abstracto.suggestion.config;
|
||||
|
||||
public class SuggestionSlashCommandNames {
|
||||
private SuggestionSlashCommandNames() {
|
||||
|
||||
}
|
||||
public static final String SUGGEST = "suggest";
|
||||
public static final String SUGGEST_PUBLIC = "suggestpublic";
|
||||
public static final String POLL_PUBLIC = "pollpublic";
|
||||
public static final String POLL = "poll";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.abstracto.suggestion.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||
|
||||
public class PollCancellationNotPossibleException extends AbstractoRunTimeException implements Templatable {
|
||||
public PollCancellationNotPossibleException() {
|
||||
super("Not possible to cancel poll.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "poll_cancellation_not_possible_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.sheldan.abstracto.suggestion.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||
import dev.sheldan.abstracto.suggestion.model.exception.PollNotFoundExceptionModel;
|
||||
|
||||
public class PollNotFoundException extends AbstractoRunTimeException implements Templatable {
|
||||
private final PollNotFoundExceptionModel model;
|
||||
|
||||
public PollNotFoundException(Long pollId) {
|
||||
super("Poll not found");
|
||||
this.model = PollNotFoundExceptionModel
|
||||
.builder()
|
||||
.pollId(pollId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "poll_does_not_exist_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.abstracto.suggestion.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||
|
||||
public class PollOptionAlreadyExistsException extends AbstractoRunTimeException implements Templatable {
|
||||
|
||||
public PollOptionAlreadyExistsException() {
|
||||
super("Poll option already exists.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "poll_option_already_exists_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package dev.sheldan.abstracto.suggestion.model;
|
||||
|
||||
import dev.sheldan.abstracto.suggestion.model.database.PollType;
|
||||
import dev.sheldan.abstracto.suggestion.model.template.PollMessageOption;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class PollCreationRequest {
|
||||
private Long pollId;
|
||||
private String description;
|
||||
private List<PollMessageOption> options;
|
||||
private Boolean allowMultiple;
|
||||
private Boolean allowAddition;
|
||||
private Boolean showDecisions;
|
||||
private String evaluationJobTrigger;
|
||||
private String reminderJobTrigger;
|
||||
private String addOptionButtonId;
|
||||
private Instant targetDate;
|
||||
private String selectionMenuId;
|
||||
private Long serverId;
|
||||
@Setter
|
||||
private Long pollChannelId;
|
||||
private Long creatorId;
|
||||
@Setter
|
||||
private Long pollMessageId;
|
||||
private PollType type;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package dev.sheldan.abstracto.suggestion.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.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="poll")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class Poll {
|
||||
|
||||
@Id
|
||||
@Column(name = "id", nullable = false)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "poll_id", nullable = false)
|
||||
private Long pollId;
|
||||
|
||||
@Column(name = "message_id", nullable = false)
|
||||
private Long messageId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "type", nullable = false)
|
||||
private PollType type;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "creator_user_in_server_id", nullable = false)
|
||||
private AUserInAServer creator;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "channel_id", nullable = false)
|
||||
private AChannel channel;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "state", nullable = false)
|
||||
private PollState state;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
|
||||
@Column(name = "description", nullable = false)
|
||||
private String description;
|
||||
|
||||
@Column(name = "evaluation_job_trigger_key")
|
||||
private String evaluationJobTriggerKey;
|
||||
|
||||
@Column(name = "reminder_job_trigger_key")
|
||||
private String reminderJobTriggerKey;
|
||||
|
||||
@Column(name = "target_date")
|
||||
private Instant targetDate;
|
||||
|
||||
@Column(name = "allow_multiple")
|
||||
private Boolean allowMultiple;
|
||||
|
||||
@Column(name = "show_decisions")
|
||||
private Boolean showDecisions;
|
||||
|
||||
@Column(name = "allow_addition")
|
||||
private Boolean allowAddition;
|
||||
|
||||
@Column(name = "selection_menu_id")
|
||||
private String selectionMenuId;
|
||||
|
||||
@Column(name = "add_option_button_id")
|
||||
private String addOptionButtonId;
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||
mappedBy = "poll")
|
||||
@Builder.Default
|
||||
private List<PollOption> options = new ArrayList<>();
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||
mappedBy = "poll")
|
||||
@Builder.Default
|
||||
private List<PollUserDecision> decisions = new ArrayList<>();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.sheldan.abstracto.suggestion.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.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name="poll_option")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class PollOption {
|
||||
|
||||
@Id
|
||||
@Column(name = "id", nullable = false)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "poll_id", nullable = false)
|
||||
private Poll poll;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@Column(name = "label", nullable = false)
|
||||
private String label;
|
||||
|
||||
@Column(name = "value", nullable = false)
|
||||
private String value;
|
||||
|
||||
@Column(name = "description", nullable = false)
|
||||
private String description;
|
||||
|
||||
@Getter
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "adder_user_in_server_id")
|
||||
private AUserInAServer adder;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.sheldan.abstracto.suggestion.model.database;
|
||||
|
||||
public enum PollState {
|
||||
NEW, FINISHED, CANCELLED, VETOED
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.sheldan.abstracto.suggestion.model.database;
|
||||
|
||||
public enum PollType {
|
||||
STANDARD, QUICK
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.sheldan.abstracto.suggestion.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.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="poll_user_decision")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class PollUserDecision {
|
||||
|
||||
@Id
|
||||
@Column(name = "id", nullable = false)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "user_in_server_id", nullable = false)
|
||||
private AUserInAServer voter;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "poll_id", nullable = false)
|
||||
private Poll poll;
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||
mappedBy = "decision", orphanRemoval = true)
|
||||
@Builder.Default
|
||||
private List<PollUserDecisionOption> options = new ArrayList<>();
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user