mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-01 23:35:29 +00:00
[AB-94] adding command to show the state of a server poll
This commit is contained in:
@@ -0,0 +1,95 @@
|
|||||||
|
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.model.template.PollInfoModel;
|
||||||
|
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 ShowPoll extends AbstractConditionableCommand {
|
||||||
|
|
||||||
|
private static final String COMMAND_NAME = "show";
|
||||||
|
private static final String SHOW_POLL_COMMAND_NAME = "showPoll";
|
||||||
|
private static final String POLL_ID_PARAMETER = "pollId";
|
||||||
|
private static final String SHOW_POLL_TEMPLATE_KEY = "showPoll_response";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SlashCommandParameterService slashCommandParameterService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PollService pollService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InteractionService interactionService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||||
|
Long suggestionId = slashCommandParameterService.getCommandOption(POLL_ID_PARAMETER, event, Long.class, Integer.class).longValue();
|
||||||
|
PollInfoModel pollInfoModel = pollService.getPollInfoModel(suggestionId, event.getGuild().getIdLong());
|
||||||
|
return interactionService.replyEmbed(SHOW_POLL_TEMPLATE_KEY, pollInfoModel, event)
|
||||||
|
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandConfiguration getConfiguration() {
|
||||||
|
List<ParameterValidator> polldIdValidator = Arrays.asList(MinIntegerValueValidator.min(1L));
|
||||||
|
Parameter pollIdParameter = Parameter
|
||||||
|
.builder()
|
||||||
|
.name(POLL_ID_PARAMETER)
|
||||||
|
.validators(polldIdValidator)
|
||||||
|
.type(Long.class)
|
||||||
|
.templated(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HelpInfo helpInfo = HelpInfo
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.hasExample(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
List<Parameter> parameters = Arrays.asList(pollIdParameter);
|
||||||
|
|
||||||
|
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||||
|
.builder()
|
||||||
|
.enabled(true)
|
||||||
|
.rootCommandName(SuggestionSlashCommandNames.POLL)
|
||||||
|
.commandName(COMMAND_NAME)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return CommandConfiguration.builder()
|
||||||
|
.name(SHOW_POLL_COMMAND_NAME)
|
||||||
|
.slashCommandConfig(slashCommandConfig)
|
||||||
|
.module(UtilityModuleDefinition.UTILITY)
|
||||||
|
.templated(true)
|
||||||
|
.async(true)
|
||||||
|
.supportsEmbedException(true)
|
||||||
|
.causesReaction(false)
|
||||||
|
.parameters(parameters)
|
||||||
|
.help(helpInfo)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return SuggestionFeatureDefinition.POLL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -335,7 +335,8 @@ public class PollServiceBean implements PollService {
|
|||||||
public CompletableFuture<Void> addOptionToServerPoll(Long pollId, Long serverId, Member adder, String label, String description) {
|
public CompletableFuture<Void> addOptionToServerPoll(Long pollId, Long serverId, Member adder, String label, String description) {
|
||||||
Poll poll = pollManagementService.getPollByPollId(pollId, serverId, PollType.STANDARD);
|
Poll poll = pollManagementService.getPollByPollId(pollId, serverId, PollType.STANDARD);
|
||||||
log.info("Adding option to server poll {} in server {}.", pollId, serverId);
|
log.info("Adding option to server poll {} in server {}.", pollId, serverId);
|
||||||
pollOptionManagementService.addOptionToPoll(poll, label, description);
|
AUserInAServer adderUser = userInServerManagementService.loadOrCreateUser(adder);
|
||||||
|
pollOptionManagementService.addOptionToPoll(poll, label, description, adderUser);
|
||||||
List<PollMessageOption> options = getOptionsOfPoll(poll);
|
List<PollMessageOption> options = getOptionsOfPoll(poll);
|
||||||
ServerPollMessageModel model = ServerPollMessageModel.fromPoll(poll, options);
|
ServerPollMessageModel model = ServerPollMessageModel.fromPoll(poll, options);
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SERVER_POLL_TEMPLATE_KEY, model);
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(SERVER_POLL_TEMPLATE_KEY, model);
|
||||||
@@ -487,6 +488,37 @@ public class PollServiceBean implements PollService {
|
|||||||
return messageService.deleteMessageInChannelInServer(serverId, poll.getChannel().getId(), poll.getMessageId());
|
return messageService.deleteMessageInChannelInServer(serverId, poll.getChannel().getId(), poll.getMessageId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PollInfoModel getPollInfoModel(Long pollId, Long serverId) {
|
||||||
|
Poll poll = pollManagementService.getPollByPollId(pollId, serverId, PollType.STANDARD);
|
||||||
|
Integer totalVotes = getTotalVotesOfPoll(poll);
|
||||||
|
List<PollOptionInfoModel> optionInfoModels = poll.getOptions().stream().map(pollOption -> {
|
||||||
|
Long voteCount = getVotesOfOption(poll, pollOption);
|
||||||
|
return PollOptionInfoModel
|
||||||
|
.builder()
|
||||||
|
.value(pollOption.getValue())
|
||||||
|
.description(pollOption.getDescription())
|
||||||
|
.label(pollOption.getLabel())
|
||||||
|
.votes(voteCount)
|
||||||
|
.percentage(totalVotes > 0 ? (voteCount / (float) totalVotes) * 100 : 0)
|
||||||
|
.adder(pollOption.getAdder() != null ? MemberDisplay.fromAUserInAServer(pollOption.getAdder()) : null)
|
||||||
|
.build();
|
||||||
|
}).toList();
|
||||||
|
return PollInfoModel
|
||||||
|
.builder()
|
||||||
|
.id(poll.getPollId())
|
||||||
|
.description(poll.getDescription())
|
||||||
|
.creationDate(poll.getCreated())
|
||||||
|
.targetDate(poll.getTargetDate())
|
||||||
|
.totalVotes(totalVotes)
|
||||||
|
.allowAdditions(poll.getAllowAddition())
|
||||||
|
.allowMultiple(poll.getAllowMultiple())
|
||||||
|
.options(optionInfoModels)
|
||||||
|
.showDecisions(poll.getShowDecisions())
|
||||||
|
.pollDuration(Duration.between(poll.getCreated(), poll.getTargetDate()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public CompletableFuture<Void> updateFinalPollMessage(Long pollId, Guild guild) {
|
public CompletableFuture<Void> updateFinalPollMessage(Long pollId, Guild guild) {
|
||||||
Poll poll = pollManagementService.getPollByPollId(pollId, guild.getIdLong(), PollType.STANDARD);
|
Poll poll = pollManagementService.getPollByPollId(pollId, guild.getIdLong(), PollType.STANDARD);
|
||||||
@@ -543,22 +575,13 @@ public class PollServiceBean implements PollService {
|
|||||||
.percentage(0f)
|
.percentage(0f)
|
||||||
.description(description)
|
.description(description)
|
||||||
.build();
|
.build();
|
||||||
}).collect(Collectors.toList());
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PollMessageOption> getOptionsOfPoll(Poll poll) {
|
private List<PollMessageOption> getOptionsOfPoll(Poll poll) {
|
||||||
Integer totalVotes = poll
|
Integer totalVotes = getTotalVotesOfPoll(poll);
|
||||||
.getDecisions()
|
|
||||||
.stream()
|
|
||||||
.map(userDecision -> userDecision.getOptions().size())
|
|
||||||
.mapToInt(Integer::intValue)
|
|
||||||
.sum();
|
|
||||||
return poll.getOptions().stream().map(option -> {
|
return poll.getOptions().stream().map(option -> {
|
||||||
Long voteCount = poll
|
Long voteCount = getVotesOfOption(poll, option);
|
||||||
.getDecisions()
|
|
||||||
.stream()
|
|
||||||
.filter(decision -> decision.getOptions().stream().anyMatch(pollUserDecisionOption -> pollUserDecisionOption.getPollOption().equals(option)))
|
|
||||||
.count();
|
|
||||||
return PollMessageOption
|
return PollMessageOption
|
||||||
.builder()
|
.builder()
|
||||||
.value(option.getValue())
|
.value(option.getValue())
|
||||||
@@ -567,7 +590,24 @@ public class PollServiceBean implements PollService {
|
|||||||
.percentage(totalVotes > 0 ? (voteCount / (float) totalVotes) * 100 : 0)
|
.percentage(totalVotes > 0 ? (voteCount / (float) totalVotes) * 100 : 0)
|
||||||
.description(option.getDescription())
|
.description(option.getDescription())
|
||||||
.build();
|
.build();
|
||||||
}).collect(Collectors.toList());
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getVotesOfOption(Poll poll, PollOption option) {
|
||||||
|
return poll
|
||||||
|
.getDecisions()
|
||||||
|
.stream()
|
||||||
|
.filter(decision -> decision.getOptions().stream().anyMatch(pollUserDecisionOption -> pollUserDecisionOption.getPollOption().equals(option)))
|
||||||
|
.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getTotalVotesOfPoll(Poll poll) {
|
||||||
|
return poll
|
||||||
|
.getDecisions()
|
||||||
|
.stream()
|
||||||
|
.map(userDecision -> userDecision.getOptions().size())
|
||||||
|
.mapToInt(Integer::intValue)
|
||||||
|
.sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.sheldan.abstracto.suggestion.service.management;
|
package dev.sheldan.abstracto.suggestion.service.management;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
import dev.sheldan.abstracto.suggestion.model.PollCreationRequest;
|
import dev.sheldan.abstracto.suggestion.model.PollCreationRequest;
|
||||||
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
||||||
import dev.sheldan.abstracto.suggestion.model.database.PollOption;
|
import dev.sheldan.abstracto.suggestion.model.database.PollOption;
|
||||||
@@ -32,12 +33,18 @@ public class PollOptionManagementServiceBean implements PollOptionManagementServ
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addOptionToPoll(Poll poll, String label, String description) {
|
public void addOptionToPoll(Poll poll, String label, String description) {
|
||||||
|
addOptionToPoll(poll, label, description, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addOptionToPoll(Poll poll, String label, String description, AUserInAServer adder) {
|
||||||
PollOption option = PollOption
|
PollOption option = PollOption
|
||||||
.builder()
|
.builder()
|
||||||
.poll(poll)
|
.poll(poll)
|
||||||
.label(label)
|
.label(label)
|
||||||
.value(label)
|
.value(label)
|
||||||
.server(poll.getServer())
|
.server(poll.getServer())
|
||||||
|
.adder(adder)
|
||||||
.description(description)
|
.description(description)
|
||||||
.build();
|
.build();
|
||||||
pollOptionRepository.save(option);
|
pollOptionRepository.save(option);
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||||
|
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.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"/>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?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="showPoll-command">
|
||||||
|
<insert tableName="command">
|
||||||
|
<column name="name" value="showPoll"/>
|
||||||
|
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||||
|
<column name="feature_id" valueComputed="${pollFeature}"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||||
|
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||||
|
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -13,4 +13,5 @@
|
|||||||
<include file="1.4.0/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.8/collection.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="1.4.26/collection.xml" relativeToChangelogFile="true"/>
|
<include file="1.4.26/collection.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="1.5.6/collection.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package dev.sheldan.abstracto.suggestion.model.template;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class PollInfoModel {
|
||||||
|
private Long id;
|
||||||
|
private String description;
|
||||||
|
private Boolean allowMultiple;
|
||||||
|
private Boolean showDecisions;
|
||||||
|
private Boolean allowAdditions;
|
||||||
|
private Instant creationDate;
|
||||||
|
private Integer totalVotes;
|
||||||
|
private Instant targetDate;
|
||||||
|
private Duration pollDuration;
|
||||||
|
private List<PollOptionInfoModel> options;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package dev.sheldan.abstracto.suggestion.model.template;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class PollOptionInfoModel {
|
||||||
|
private String value;
|
||||||
|
private String label;
|
||||||
|
private String description;
|
||||||
|
private Long votes;
|
||||||
|
private Float percentage;
|
||||||
|
private MemberDisplay adder;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package dev.sheldan.abstracto.suggestion.service;
|
package dev.sheldan.abstracto.suggestion.service;
|
||||||
|
|
||||||
import dev.sheldan.abstracto.suggestion.model.database.PollType;
|
import dev.sheldan.abstracto.suggestion.model.database.PollType;
|
||||||
|
import dev.sheldan.abstracto.suggestion.model.template.PollInfoModel;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||||
|
|
||||||
@@ -26,4 +27,5 @@ public interface PollService {
|
|||||||
CompletableFuture<Void> evaluateQuickPoll(Long pollId, Long serverId);
|
CompletableFuture<Void> evaluateQuickPoll(Long pollId, Long serverId);
|
||||||
CompletableFuture<Void> closePoll(Long pollId, Long serverId, String text, Member cause);
|
CompletableFuture<Void> closePoll(Long pollId, Long serverId, String text, Member cause);
|
||||||
CompletableFuture<Void> cancelPoll(Long pollId, Long serverId, Member cause);
|
CompletableFuture<Void> cancelPoll(Long pollId, Long serverId, Member cause);
|
||||||
|
PollInfoModel getPollInfoModel(Long pollId, Long serverId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.sheldan.abstracto.suggestion.service.management;
|
package dev.sheldan.abstracto.suggestion.service.management;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
import dev.sheldan.abstracto.suggestion.model.PollCreationRequest;
|
import dev.sheldan.abstracto.suggestion.model.PollCreationRequest;
|
||||||
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
import dev.sheldan.abstracto.suggestion.model.database.Poll;
|
||||||
import dev.sheldan.abstracto.suggestion.model.database.PollOption;
|
import dev.sheldan.abstracto.suggestion.model.database.PollOption;
|
||||||
@@ -9,5 +10,6 @@ import java.util.Optional;
|
|||||||
public interface PollOptionManagementService {
|
public interface PollOptionManagementService {
|
||||||
void addOptionsToPoll(Poll poll, PollCreationRequest pollCreationRequest);
|
void addOptionsToPoll(Poll poll, PollCreationRequest pollCreationRequest);
|
||||||
void addOptionToPoll(Poll poll, String label, String description);
|
void addOptionToPoll(Poll poll, String label, String description);
|
||||||
|
void addOptionToPoll(Poll poll, String label, String description, AUserInAServer adder);
|
||||||
Optional<PollOption> getPollOptionByName(Poll poll, String key);
|
Optional<PollOption> getPollOptionByName(Poll poll, String key);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user