mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-14 19:56:29 +00:00
[AB-xxx] adding ability to automate giveaways using modmail and adding storage for give away keys
ignoring message updated events for messages not within servers
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
package dev.sheldan.abstracto.giveaway.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.config.FeatureMode;
|
||||
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.giveaway.config.GiveawayFeatureDefinition;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayMode;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawaySlashCommandNames;
|
||||
import dev.sheldan.abstracto.giveaway.service.management.GiveawayKeyManagementService;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AddGiveawayKey extends AbstractConditionableCommand {
|
||||
|
||||
private static final String KEY_PARAMETER = "key";
|
||||
private static final String DESCRIPTION_PARAMETER = "description";
|
||||
private static final String BENEFACTOR_PARAMETER = "benefactor";
|
||||
private static final String NAME_PARAMETER = "name";
|
||||
private static final String ADD_GIVEAWAY_KEY_COMMAND_NAME = "addGiveawayKey";
|
||||
private static final String ADD_GIVEAWAY_KEY_RESPONSE = "addGiveawayKey_response";
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private GiveawayKeyManagementService giveawayKeyManagementService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String key = slashCommandParameterService.getCommandOption(KEY_PARAMETER, event, String.class);
|
||||
String name = slashCommandParameterService.getCommandOption(NAME_PARAMETER, event, String.class);
|
||||
String description;
|
||||
if(slashCommandParameterService.hasCommandOption(DESCRIPTION_PARAMETER, event)) {
|
||||
description = slashCommandParameterService.getCommandOption(DESCRIPTION_PARAMETER, event, String.class);
|
||||
} else {
|
||||
description = null;
|
||||
}
|
||||
Member benefactor;
|
||||
if(slashCommandParameterService.hasCommandOption(BENEFACTOR_PARAMETER, event)) {
|
||||
benefactor = slashCommandParameterService.getCommandOption(BENEFACTOR_PARAMETER, event, Member.class);
|
||||
} else {
|
||||
benefactor = null;
|
||||
}
|
||||
giveawayKeyManagementService.createGiveawayKey(event.getMember(), benefactor, key, description, name);
|
||||
return interactionService.replyEmbed(ADD_GIVEAWAY_KEY_RESPONSE, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter giveawayKey = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(KEY_PARAMETER)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
Parameter giveawayKeyDescription = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(DESCRIPTION_PARAMETER)
|
||||
.type(String.class)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
|
||||
Parameter giveawayKeyBenefactor = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(BENEFACTOR_PARAMETER)
|
||||
.type(Member.class)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
Parameter giveawayKeyName = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(NAME_PARAMETER)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(giveawayKeyName, giveawayKey, giveawayKeyBenefactor, giveawayKeyDescription);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(GiveawaySlashCommandNames.GIVEAWAY)
|
||||
.groupName("keys")
|
||||
.commandName("add")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(ADD_GIVEAWAY_KEY_COMMAND_NAME)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandOnly(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return GiveawayFeatureDefinition.GIVEAWAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(GiveawayMode.KEY_GIVEAWAYS);
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,7 @@ public class CancelGiveaway extends AbstractConditionableCommand {
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(GiveawaySlashCommandNames.GIVEAWAY)
|
||||
.groupName("management")
|
||||
.commandName("cancel")
|
||||
.build();
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import dev.sheldan.abstracto.giveaway.service.GiveawayService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -25,6 +26,7 @@ import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Component
|
||||
public class GreateGiveaway extends AbstractConditionableCommand {
|
||||
@@ -48,55 +50,62 @@ public class GreateGiveaway extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private GiveawayService giveawayService;
|
||||
|
||||
@Autowired
|
||||
private GreateGiveaway self;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
return event.deferReply()
|
||||
.submit()
|
||||
.thenCompose(interactionHook -> {
|
||||
String title = slashCommandParameterService.getCommandOption(TITLE_PARAMETER, event, String.class);
|
||||
String description;
|
||||
if(slashCommandParameterService.hasCommandOption(DESCRIPTION_PARAMETER, event)) {
|
||||
description = slashCommandParameterService.getCommandOption(DESCRIPTION_PARAMETER, event, String.class);
|
||||
} else {
|
||||
description = null;
|
||||
}
|
||||
.thenCompose(interactionHook -> self.createGiveaway(event, interactionHook))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
|
||||
String durationString = slashCommandParameterService.getCommandOption(DURATION_PARAMETER, event, Duration.class, String.class);
|
||||
Duration duration = ParseUtils.parseDuration(durationString);
|
||||
}
|
||||
|
||||
GuildMessageChannel target = null;
|
||||
if(slashCommandParameterService.hasCommandOption(CHANNEL_PARAMETER, event)) {
|
||||
target = slashCommandParameterService.getCommandOption(CHANNEL_PARAMETER, event, GuildMessageChannel.class);
|
||||
}
|
||||
@Transactional
|
||||
public CompletableFuture<Void> createGiveaway(SlashCommandInteractionEvent event, InteractionHook interactionHook) {
|
||||
String title = slashCommandParameterService.getCommandOption(TITLE_PARAMETER, event, String.class);
|
||||
String description;
|
||||
if(slashCommandParameterService.hasCommandOption(DESCRIPTION_PARAMETER, event)) {
|
||||
description = slashCommandParameterService.getCommandOption(DESCRIPTION_PARAMETER, event, String.class);
|
||||
} else {
|
||||
description = null;
|
||||
}
|
||||
|
||||
Integer winners = 1;
|
||||
if(slashCommandParameterService.hasCommandOption(WINNERS_PARAMETER, event)) {
|
||||
winners = slashCommandParameterService.getCommandOption(WINNERS_PARAMETER, event, Integer.class);
|
||||
}
|
||||
String durationString = slashCommandParameterService.getCommandOption(DURATION_PARAMETER, event, Duration.class, String.class);
|
||||
Duration duration = ParseUtils.parseDuration(durationString);
|
||||
|
||||
Member benefactor;
|
||||
if(slashCommandParameterService.hasCommandOption(BENEFACTOR_PARAMETER, event)) {
|
||||
benefactor = slashCommandParameterService.getCommandOption(BENEFACTOR_PARAMETER, event, Member.class);
|
||||
} else {
|
||||
benefactor = null;
|
||||
}
|
||||
GuildMessageChannel target = null;
|
||||
if(slashCommandParameterService.hasCommandOption(CHANNEL_PARAMETER, event)) {
|
||||
target = slashCommandParameterService.getCommandOption(CHANNEL_PARAMETER, event, GuildMessageChannel.class);
|
||||
}
|
||||
|
||||
Member creator = event.getMember();
|
||||
GiveawayCreationRequest request = GiveawayCreationRequest
|
||||
.builder()
|
||||
.benefactor(benefactor)
|
||||
.creator(creator)
|
||||
.description(description)
|
||||
.duration(duration)
|
||||
.targetChannel(target)
|
||||
.winnerCount(winners)
|
||||
.title(title)
|
||||
.build();
|
||||
Integer winners = 1;
|
||||
if(slashCommandParameterService.hasCommandOption(WINNERS_PARAMETER, event)) {
|
||||
winners = slashCommandParameterService.getCommandOption(WINNERS_PARAMETER, event, Integer.class);
|
||||
}
|
||||
|
||||
return giveawayService.createGiveaway(request)
|
||||
.thenAccept(unused -> interactionService.sendEmbed(CREATE_GIVEAWAY_RESPONSE_TEMPLATE_KEY, interactionHook));
|
||||
}).thenApply(unused -> CommandResult.fromSuccess());
|
||||
Member benefactor;
|
||||
if(slashCommandParameterService.hasCommandOption(BENEFACTOR_PARAMETER, event)) {
|
||||
benefactor = slashCommandParameterService.getCommandOption(BENEFACTOR_PARAMETER, event, Member.class);
|
||||
} else {
|
||||
benefactor = null;
|
||||
}
|
||||
|
||||
Member creator = event.getMember();
|
||||
GiveawayCreationRequest request = GiveawayCreationRequest
|
||||
.builder()
|
||||
.benefactorId(benefactor != null ? benefactor.getIdLong() : null)
|
||||
.creatorId(creator.getIdLong())
|
||||
.description(description)
|
||||
.duration(duration)
|
||||
.targetChannel(target)
|
||||
.winnerCount(winners)
|
||||
.title(title)
|
||||
.build();
|
||||
|
||||
return giveawayService.createGiveaway(request)
|
||||
.thenAccept(unused -> interactionService.sendEmbed(CREATE_GIVEAWAY_RESPONSE_TEMPLATE_KEY, interactionHook));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,6 +168,7 @@ public class GreateGiveaway extends AbstractConditionableCommand {
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(GiveawaySlashCommandNames.GIVEAWAY)
|
||||
.groupName("management")
|
||||
.commandName("create")
|
||||
.build();
|
||||
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
package dev.sheldan.abstracto.giveaway.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.config.FeatureMode;
|
||||
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.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.utils.ParseUtils;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayFeatureConfig;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayFeatureDefinition;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayMode;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawaySlashCommandNames;
|
||||
import dev.sheldan.abstracto.giveaway.exception.GiveawayNotPossibleException;
|
||||
import dev.sheldan.abstracto.giveaway.exception.GiveawayKeyNotFoundException;
|
||||
import dev.sheldan.abstracto.giveaway.model.GiveawayCreationRequest;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.GiveawayKey;
|
||||
import dev.sheldan.abstracto.giveaway.service.GiveawayService;
|
||||
import dev.sheldan.abstracto.giveaway.service.management.GiveawayKeyManagementService;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Component
|
||||
public class GreateKeyGiveaway extends AbstractConditionableCommand {
|
||||
|
||||
private static final String COMMAND_NAME = "createKeyGiveaway";
|
||||
private static final String KEY_ID_PARAMETER = "keyId";
|
||||
private static final String DURATION_PARAMETER = "duration";
|
||||
|
||||
private static final String CREATE_KEY_GIVEAWAY_RESPONSE_TEMPLATE_KEY = "createKeyGiveaway_response";
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private GiveawayService giveawayService;
|
||||
|
||||
@Autowired
|
||||
private GiveawayKeyManagementService giveawayKeyManagementService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private GreateKeyGiveaway self;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Long id = slashCommandParameterService.getCommandOption(KEY_ID_PARAMETER, event, Integer.class).longValue();
|
||||
String durationString;
|
||||
if(slashCommandParameterService.hasCommandOption(DURATION_PARAMETER, event)) {
|
||||
durationString = slashCommandParameterService.getCommandOption(DURATION_PARAMETER, event, Duration.class, String.class);
|
||||
} else {
|
||||
durationString = configService.getStringValueOrConfigDefault(GiveawayFeatureConfig.KEY_GIVEAWAYS_DURATION, event.getGuild().getIdLong()).trim();
|
||||
}
|
||||
Duration duration = ParseUtils.parseDuration(durationString);
|
||||
return event.deferReply()
|
||||
.submit()
|
||||
.thenCompose(interactionHook -> self.createKeyGiveaway(id, interactionHook, duration))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> createKeyGiveaway(Long giveawayKeyId, InteractionHook interactionHook, Duration duration) {
|
||||
Long serverId = interactionHook.getInteraction().getGuild().getIdLong();
|
||||
GiveawayKey giveawayKey = giveawayKeyManagementService.getById(giveawayKeyId, serverId)
|
||||
.orElseThrow(GiveawayKeyNotFoundException::new);
|
||||
if((giveawayKey.getGiveaway() != null && giveawayKey.getGiveaway().getTargetDate().isAfter(Instant.now())) || giveawayKey.getUsed()) {
|
||||
throw new GiveawayNotPossibleException();
|
||||
}
|
||||
GiveawayCreationRequest request = GiveawayCreationRequest
|
||||
.builder()
|
||||
.benefactorId(giveawayKey.getBenefactor() != null ? giveawayKey.getBenefactor().getUserReference().getId() : null)
|
||||
.creatorId(giveawayKey.getCreator().getUserReference().getId())
|
||||
.description(giveawayKey.getDescription())
|
||||
.duration(duration)
|
||||
.serverId(serverId)
|
||||
.giveawayKeyId(giveawayKeyId)
|
||||
.winnerCount(1)
|
||||
.title(giveawayKey.getName())
|
||||
.build();
|
||||
|
||||
return giveawayService.createGiveaway(request)
|
||||
.thenAccept(giveawayId -> {
|
||||
interactionService.sendEmbed(CREATE_KEY_GIVEAWAY_RESPONSE_TEMPLATE_KEY, interactionHook);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter keyParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(KEY_ID_PARAMETER)
|
||||
.type(Long.class)
|
||||
.build();
|
||||
|
||||
Parameter durationParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(DURATION_PARAMETER)
|
||||
.optional(true)
|
||||
.type(Duration.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(keyParameter, durationParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(GiveawaySlashCommandNames.GIVEAWAY)
|
||||
.groupName("key")
|
||||
.commandName("creategiveaway")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(COMMAND_NAME)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return GiveawayFeatureDefinition.GIVEAWAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(GiveawayMode.KEY_GIVEAWAYS);
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,7 @@ public class ReRollGiveaway extends AbstractConditionableCommand {
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(GiveawaySlashCommandNames.GIVEAWAY)
|
||||
.groupName("management")
|
||||
.commandName("reroll")
|
||||
.build();
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package dev.sheldan.abstracto.giveaway.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.config.FeatureMode;
|
||||
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.giveaway.config.GiveawayFeatureDefinition;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayMode;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawaySlashCommandNames;
|
||||
import dev.sheldan.abstracto.giveaway.service.management.GiveawayKeyManagementService;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class RemoveGiveawayKey extends AbstractConditionableCommand {
|
||||
|
||||
|
||||
private static final String ID_PARAMETER = "id";
|
||||
private static final String REMOVE_GIVEAWAY_KEY_COMMAND_NAME = "removeGiveawayKey";
|
||||
private static final String REMOVE_GIVEAWAY_KEY_RESPONSE = "removeGiveawayKey_response";
|
||||
|
||||
@Autowired
|
||||
private GiveawayKeyManagementService giveawayKeyManagementService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Long id = slashCommandParameterService.getCommandOption(ID_PARAMETER, event, Integer.class).longValue();
|
||||
giveawayKeyManagementService.deleteById(id, event.getGuild().getIdLong());
|
||||
return interactionService.replyEmbed(REMOVE_GIVEAWAY_KEY_RESPONSE, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter giveawayKeyId = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(ID_PARAMETER)
|
||||
.type(Long.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(giveawayKeyId);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(GiveawaySlashCommandNames.GIVEAWAY)
|
||||
.groupName("keys")
|
||||
.commandName("remove")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(REMOVE_GIVEAWAY_KEY_COMMAND_NAME)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandOnly(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return GiveawayFeatureDefinition.GIVEAWAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(GiveawayMode.KEY_GIVEAWAYS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package dev.sheldan.abstracto.giveaway.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.config.FeatureMode;
|
||||
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.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.PaginatorService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayFeatureDefinition;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayMode;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawaySlashCommandNames;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.GiveawayKey;
|
||||
import dev.sheldan.abstracto.giveaway.model.template.GiveawayKeyDisplayModel;
|
||||
import dev.sheldan.abstracto.giveaway.model.template.GiveawayKeysDisplayModel;
|
||||
import dev.sheldan.abstracto.giveaway.service.management.GiveawayKeyManagementService;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ShowGiveawayKeys extends AbstractConditionableCommand {
|
||||
|
||||
public static final String SHOW_ALL_PARAMETER_NAME = "all";
|
||||
|
||||
|
||||
private static final String SHOW_GIVEAWAY_KEYS_RESPONSE_TEMPLATE = "showGiveawayKeys_response";
|
||||
private static final String SHOW_GIVEAWAY_NO_KEYS_FOUND_TEMPLATE = "showGiveawayKeys_no_keys_found";
|
||||
|
||||
@Autowired
|
||||
private PaginatorService paginatorService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private GiveawayKeyManagementService giveawayKeyManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
boolean showAll;
|
||||
if(slashCommandParameterService.hasCommandOption(SHOW_ALL_PARAMETER_NAME, event)) {
|
||||
showAll = slashCommandParameterService.getCommandOption(SHOW_ALL_PARAMETER_NAME, event, Boolean.class);
|
||||
} else {
|
||||
showAll = false;
|
||||
}
|
||||
List<GiveawayKey> giveawayKeys = giveawayKeyManagementService.getGiveawayKeys(event.getGuild().getIdLong(), showAll);
|
||||
if(giveawayKeys.isEmpty()) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SHOW_GIVEAWAY_NO_KEYS_FOUND_TEMPLATE, new Object(), event.getGuild().getIdLong());
|
||||
return interactionService.replyMessageToSend(messageToSend, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
List<GiveawayKeyDisplayModel> models = giveawayKeys
|
||||
.stream()
|
||||
.map(giveawayKey -> GiveawayKeyDisplayModel
|
||||
.builder()
|
||||
.key(giveawayKey.getKey())
|
||||
.id(giveawayKey.getId().getKeyId())
|
||||
.used(giveawayKey.getUsed())
|
||||
.description(giveawayKey.getDescription())
|
||||
.name(giveawayKey.getName())
|
||||
.winner(giveawayKey.getWinner() != null ? MemberDisplay.fromAUserInAServer(giveawayKey.getWinner()) : null)
|
||||
.creator(MemberDisplay.fromAUserInAServer(giveawayKey.getCreator()))
|
||||
.benefactor(giveawayKey.getBenefactor() != null ? MemberDisplay.fromAUserInAServer(giveawayKey.getBenefactor()) : null)
|
||||
.build())
|
||||
.toList();
|
||||
GiveawayKeysDisplayModel model = GiveawayKeysDisplayModel
|
||||
.builder()
|
||||
.keys(models)
|
||||
.build();
|
||||
return paginatorService.createPaginatorFromTemplate(SHOW_GIVEAWAY_KEYS_RESPONSE_TEMPLATE, model, event)
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter showAllParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(SHOW_ALL_PARAMETER_NAME)
|
||||
.type(Boolean.class)
|
||||
.optional(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(showAllParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(GiveawaySlashCommandNames.GIVEAWAY)
|
||||
.groupName("keys")
|
||||
.commandName("show")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name("showGiveawayKeys")
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return GiveawayFeatureDefinition.GIVEAWAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(GiveawayMode.KEY_GIVEAWAYS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.abstracto.giveaway.repository;
|
||||
|
||||
import dev.sheldan.abstracto.giveaway.model.database.GiveawayKey;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.embed.GiveawayKeyId;
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface GiveawayKeyRepository extends JpaRepository<GiveawayKey, GiveawayKeyId> {
|
||||
List<GiveawayKey> findGiveawayKeysByUsedAndServer_IdOrderById(Boolean used, Long serverId);
|
||||
List<GiveawayKey> findGiveawayKeysByServer_IdOrderById(Long serverId);
|
||||
}
|
||||
@@ -7,28 +7,38 @@ import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.CounterService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.service.UserService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
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.CompletableFutureList;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayFeatureDefinition;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayMode;
|
||||
import dev.sheldan.abstracto.giveaway.config.GiveawayPostTarget;
|
||||
import dev.sheldan.abstracto.giveaway.exception.GiveawayKeyNotFoundException;
|
||||
import dev.sheldan.abstracto.giveaway.exception.GiveawayNotFoundException;
|
||||
import dev.sheldan.abstracto.giveaway.model.GiveawayCreationRequest;
|
||||
import dev.sheldan.abstracto.giveaway.model.JoinGiveawayPayload;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.Giveaway;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.GiveawayKey;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.GiveawayParticipant;
|
||||
import dev.sheldan.abstracto.giveaway.model.template.GiveawayMessageModel;
|
||||
import dev.sheldan.abstracto.giveaway.model.template.GiveawayResultMessageModel;
|
||||
import dev.sheldan.abstracto.giveaway.model.template.GiveawayWinnerNotificationMessageModel;
|
||||
import dev.sheldan.abstracto.giveaway.service.management.GiveawayKeyManagementService;
|
||||
import dev.sheldan.abstracto.giveaway.service.management.GiveawayManagementService;
|
||||
import dev.sheldan.abstracto.giveaway.service.management.GiveawayParticipantManagementService;
|
||||
import dev.sheldan.abstracto.modmail.service.ModMailThreadService;
|
||||
import dev.sheldan.abstracto.scheduling.model.JobParameters;
|
||||
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
|
||||
import jakarta.transaction.Transactional;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -44,6 +54,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
public class GiveawayServiceBean implements GiveawayService {
|
||||
|
||||
private static final String GIVEAWAY_MESSAGE_TEMPLATE_KEY = "giveaway_post";
|
||||
private static final String GIVEAWAY_WINNER_MODMAIL_NOTIFICATION = "giveaway_winner_modmail_notification";
|
||||
private static final String GIVEAWAY_RESULT_MESSAGE_TEMPLATE_KEY = "giveaway_result";
|
||||
public static final String GIVEAWAY_JOIN_ORIGIN = "JOIN_GIVEAWAY";
|
||||
|
||||
@@ -85,42 +96,55 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
@Autowired
|
||||
private CounterService counterService;
|
||||
|
||||
@Autowired
|
||||
private GiveawayKeyManagementService giveawayKeyManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ModMailThreadService modMailThreadService;
|
||||
|
||||
@Autowired
|
||||
private GiveawayServiceBean self;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createGiveaway(GiveawayCreationRequest giveawayCreationRequest) {
|
||||
public CompletableFuture<Long> createGiveaway(GiveawayCreationRequest giveawayCreationRequest) {
|
||||
String componentId = componentService.generateComponentId();
|
||||
Instant targetDate = Instant.now().plus(giveawayCreationRequest.getDuration());
|
||||
Long serverId = giveawayCreationRequest.getCreator().getGuild().getIdLong();
|
||||
Long serverId = giveawayCreationRequest.getServerId();
|
||||
Long giveawayId = counterService.getNextCounterValue(serverId, GIVEAWAY_COUNTER);
|
||||
GiveawayMessageModel model = GiveawayMessageModel
|
||||
.builder()
|
||||
.title(giveawayCreationRequest.getTitle())
|
||||
.description(giveawayCreationRequest.getDescription())
|
||||
.giveawayId(giveawayId)
|
||||
.benefactor(giveawayCreationRequest.getBenefactor() != null ? MemberDisplay.fromMember(giveawayCreationRequest.getBenefactor()) : null)
|
||||
.creator(MemberDisplay.fromMember(giveawayCreationRequest.getCreator()))
|
||||
.benefactor(giveawayCreationRequest.getBenefactorId() != null ? MemberDisplay.fromIds(giveawayCreationRequest.getServerId(), giveawayCreationRequest.getBenefactorId()) : null)
|
||||
.creator(MemberDisplay.fromIds(giveawayCreationRequest.getServerId(), giveawayCreationRequest.getCreatorId()))
|
||||
.winnerCount(giveawayCreationRequest.getWinnerCount())
|
||||
.targetDate(targetDate)
|
||||
.joinComponentId(componentId)
|
||||
.build();
|
||||
List<CompletableFuture<Message>> messageFutures;
|
||||
log.info("Rendering giveaway message in server {} by user {}", serverId, giveawayCreationRequest.getCreator().getIdLong());
|
||||
log.info("Rendering giveaway message in server {} by user {}", serverId, giveawayCreationRequest.getCreatorId());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GIVEAWAY_MESSAGE_TEMPLATE_KEY, model, serverId);
|
||||
if(giveawayCreationRequest.getTargetChannel() == null) {
|
||||
log.info("Sending giveaway to post target in server {}", serverId);
|
||||
postTargetService.validatePostTarget(GiveawayPostTarget.GIVEAWAYS, giveawayCreationRequest.getCreator().getGuild().getIdLong());
|
||||
postTargetService.validatePostTarget(GiveawayPostTarget.GIVEAWAYS, serverId);
|
||||
messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, GiveawayPostTarget.GIVEAWAYS, serverId);
|
||||
} else {
|
||||
log.info("Sending giveaway to channel {} in server {}.", giveawayCreationRequest.getTargetChannel().getId(), serverId);
|
||||
messageFutures = channelService.sendMessageToSendToChannel(messageToSend, giveawayCreationRequest.getTargetChannel());
|
||||
}
|
||||
CompletableFutureList<Message> messageFutureList = new CompletableFutureList<>(messageFutures);
|
||||
return messageFutureList.getMainFuture().thenAccept(o -> {
|
||||
return messageFutureList.getMainFuture().thenApply(o -> {
|
||||
Message createdMessage = messageFutureList.getFutures().get(0).join();
|
||||
giveawayCreationRequest.setTargetChannel(createdMessage.getGuildChannel());
|
||||
self.persistGiveaway(giveawayCreationRequest, giveawayId, createdMessage.getIdLong(), componentId);
|
||||
return giveawayId;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -140,13 +164,9 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
@Override
|
||||
@Transactional
|
||||
public CompletableFuture<Void> evaluateGiveaway(Long giveawayId, Long serverId) {
|
||||
Optional<Giveaway> giveAwayOptional = giveawayManagementService.loadGiveawayById(giveawayId, serverId);
|
||||
if(giveAwayOptional.isEmpty()) {
|
||||
throw new GiveawayNotFoundException();
|
||||
}
|
||||
Giveaway giveaway = giveawayManagementService.loadGiveawayById(giveawayId, serverId).orElseThrow(GiveawayNotFoundException::new);
|
||||
log.info("Evaluating giveaway {} in server {}.", giveawayId, serverId);
|
||||
Giveaway giveaway = giveAwayOptional.get();
|
||||
Set<Long> winners = new HashSet<>();
|
||||
Set<Long> winnerUserInServerIds = new HashSet<>();
|
||||
Integer winnerCount = giveaway.getWinnerCount();
|
||||
giveaway.getParticipants().forEach(giveawayParticipant -> giveawayParticipant.setWon(false));
|
||||
List<Long> potentialWinners = new ArrayList<>(giveaway
|
||||
@@ -156,20 +176,20 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
.toList());
|
||||
|
||||
if(potentialWinners.size() <= winnerCount) {
|
||||
winners.addAll(potentialWinners);
|
||||
winnerUserInServerIds.addAll(potentialWinners);
|
||||
log.debug("Less participants than total winners - selecting all for giveaway {} in server {}.", giveawayId, serverId);
|
||||
} else {
|
||||
for (int i = 0; i < winnerCount; i++) {
|
||||
int winnerIndex = secureRandom.nextInt(potentialWinners.size());
|
||||
Long winner = potentialWinners.get(winnerIndex);
|
||||
potentialWinners.remove(winnerIndex);
|
||||
winners.add(winner);
|
||||
winnerUserInServerIds.add(winner);
|
||||
}
|
||||
}
|
||||
List<GiveawayParticipant> winningParticipants = giveaway
|
||||
.getParticipants()
|
||||
.stream()
|
||||
.filter(giveawayParticipant -> winners.contains(giveawayParticipant.getParticipant().getUserInServerId()))
|
||||
.filter(giveawayParticipant -> winnerUserInServerIds.contains(giveawayParticipant.getParticipant().getUserInServerId()))
|
||||
.toList();
|
||||
winningParticipants.forEach(giveawayParticipant -> giveawayParticipant.setWon(true));
|
||||
List<MemberDisplay> winnerDisplays = winningParticipants
|
||||
@@ -185,16 +205,55 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
log.info("Sending result message for giveaway {} in server {}.", giveawayId, serverId);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GIVEAWAY_RESULT_MESSAGE_TEMPLATE_KEY, resultModel, serverId);
|
||||
List<CompletableFuture<Message>> resultFutures = channelService.sendMessageEmbedToSendToAChannel(messageToSend, giveaway.getGiveawayChannel());
|
||||
|
||||
long actualWinnerCount = winnerUserInServerIds.size();
|
||||
Long winnerUserId;
|
||||
if(giveaway.getGiveawayKey() != null && !winningParticipants.isEmpty()) {
|
||||
GiveawayParticipant winnerParticipant = winningParticipants.get(0);
|
||||
GiveawayKey giveawayKey = giveaway.getGiveawayKey();
|
||||
giveawayKey.setWinner(winnerParticipant.getParticipant());
|
||||
giveawayKey.setUsed(true);
|
||||
winnerUserId = winnerParticipant.getParticipant().getUserReference().getId();
|
||||
} else {
|
||||
winnerUserId = null;
|
||||
}
|
||||
GiveawayMessageModel giveawayMessageModel = GiveawayMessageModel.fromGiveaway(giveaway);
|
||||
giveawayMessageModel.setWinners(winnerDisplays);
|
||||
giveawayMessageModel.setEnded(true);
|
||||
boolean createGiveawayKeyNotification = giveaway.getGiveawayKey() != null
|
||||
&& featureModeService.featureModeActive(GiveawayFeatureDefinition.GIVEAWAY, serverId, GiveawayMode.AUTO_NOTIFY_GIVEAWAY_KEY_WINNERS)
|
||||
&& featureModeService.featureModeActive(GiveawayFeatureDefinition.GIVEAWAY, serverId, GiveawayMode.KEY_GIVEAWAYS)
|
||||
&& actualWinnerCount > 0
|
||||
&& modMailThreadService != null;
|
||||
MessageToSend giveawayMessageToSend = templateService.renderEmbedTemplate(GIVEAWAY_MESSAGE_TEMPLATE_KEY, giveawayMessageModel, serverId);
|
||||
log.info("Updating original giveaway message for giveaway {} in server {}.", giveawayId, serverId);
|
||||
GuildMessageChannel messageChannel = channelService.getMessageChannelFromServer(giveaway.getServer().getId(), giveaway.getGiveawayChannel().getId());
|
||||
CompletableFuture<Message> giveawayUpdateFuture = channelService.editMessageInAChannelFuture(giveawayMessageToSend, messageChannel, giveaway.getMessageId());
|
||||
resultFutures.add(giveawayUpdateFuture);
|
||||
return new CompletableFutureList<>(resultFutures).getMainFuture();
|
||||
return new CompletableFutureList<>(resultFutures).getMainFuture().thenCompose(unused -> {
|
||||
if(createGiveawayKeyNotification) {
|
||||
return userService.retrieveUserForId(winnerUserId)
|
||||
.thenCompose(user -> self.handleKeyGiveawayNotifications(giveawayId, serverId, winnerUserInServerIds.iterator().next(), user))
|
||||
.exceptionally(throwable -> {
|
||||
log.error("Failed to notify winner of giveaway {} in server {}.", giveawayId, serverId, throwable);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> handleKeyGiveawayNotifications(Long giveawayId, Long serverId, Long winnerInServerId, User user) {
|
||||
if(modMailThreadService == null) {
|
||||
log.info("Modmail service not available - skipping notifications about giveaway {} in server {}.", giveawayId, serverId);
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
Giveaway giveaway = giveawayManagementService.loadGiveawayById(giveawayId, serverId).orElseThrow(GiveawayNotFoundException::new);
|
||||
GiveawayWinnerNotificationMessageModel messageModel = GiveawayWinnerNotificationMessageModel.fromGiveaway(giveaway, giveaway.getGiveawayKey().getKey());
|
||||
AUserInAServer winner = userInServerManagementService.loadOrCreateUser(winnerInServerId);
|
||||
MessageToSend giveawayWinnerNotification = templateService.renderEmbedTemplate(GIVEAWAY_WINNER_MODMAIL_NOTIFICATION, messageModel, serverId);
|
||||
return modMailThreadService.sendMessageToUser(winner, giveawayWinnerNotification, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -241,14 +300,13 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
|
||||
@Transactional
|
||||
public void persistGiveaway(GiveawayCreationRequest giveawayCreationRequest, Long giveawayId, Long messageId, String componentId) {
|
||||
Member creatorMember = giveawayCreationRequest.getCreator();
|
||||
log.info("Persisting giveaway in server {} with message id {}.", creatorMember.getGuild().getIdLong(), messageId);
|
||||
log.info("Persisting giveaway in server {} with message id {}.", giveawayCreationRequest.getServerId(), messageId);
|
||||
Instant targetDate = Instant.now().plus(giveawayCreationRequest.getDuration());
|
||||
AChannel targetChannel = channelManagementService.loadChannel(giveawayCreationRequest.getTargetChannel().getIdLong());
|
||||
AUserInAServer creator = userInServerManagementService.loadOrCreateUser(creatorMember);
|
||||
AUserInAServer creator = userInServerManagementService.loadOrCreateUser(giveawayCreationRequest.getServerId(), giveawayCreationRequest.getCreatorId());
|
||||
AUserInAServer benefactor;
|
||||
if(giveawayCreationRequest.getBenefactor() != null) {
|
||||
benefactor = userInServerManagementService.loadOrCreateUser(giveawayCreationRequest.getBenefactor());
|
||||
if(giveawayCreationRequest.getBenefactorId() != null) {
|
||||
benefactor = userInServerManagementService.loadOrCreateUser(giveawayCreationRequest.getServerId(), giveawayCreationRequest.getBenefactorId());
|
||||
} else {
|
||||
benefactor = null;
|
||||
}
|
||||
@@ -257,6 +315,12 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
giveawayCreationRequest.getTitle(), giveawayCreationRequest.getDescription(), giveawayCreationRequest.getWinnerCount(),
|
||||
messageId, componentId, giveawayId);
|
||||
|
||||
if(giveawayCreationRequest.getGiveawayKeyId() != null) {
|
||||
GiveawayKey giveawayKey = giveawayKeyManagementService.getById(giveawayCreationRequest.getGiveawayKeyId(), giveawayCreationRequest.getServerId())
|
||||
.orElseThrow(GiveawayKeyNotFoundException::new);
|
||||
giveawayKey.setGiveaway(giveaway);
|
||||
giveawayKeyManagementService.saveGiveawayKey(giveawayKey);
|
||||
}
|
||||
HashMap<Object, Object> parameters = new HashMap<>();
|
||||
parameters.put("giveawayId", giveaway.getGiveawayId().getId().toString());
|
||||
parameters.put("serverId", giveaway.getGiveawayId().getServerId().toString());
|
||||
@@ -264,7 +328,7 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
.builder()
|
||||
.parameters(parameters)
|
||||
.build();
|
||||
log.info("Scheduling giveaway reminder for giveaway {} originating from message {} in server {}.", giveaway.getGiveawayId().getId(), messageId, creatorMember.getGuild().getIdLong());
|
||||
log.info("Scheduling giveaway reminder for giveaway {} originating from message {} in server {}.", giveaway.getGiveawayId().getId(), messageId, giveawayCreationRequest.getServerId());
|
||||
String triggerKey = schedulerService.executeJobWithParametersOnce("giveawayEvaluationJob", "giveaway", jobParameters, Date.from(giveaway.getTargetDate()));
|
||||
giveaway.setReminderTriggerKey(triggerKey);
|
||||
JoinGiveawayPayload joinPayload = JoinGiveawayPayload
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package dev.sheldan.abstracto.giveaway.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.CounterService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.giveaway.exception.GiveawayKeyNotFoundException;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.GiveawayKey;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.embed.GiveawayKeyId;
|
||||
import dev.sheldan.abstracto.giveaway.repository.GiveawayKeyRepository;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class GiveawayKeyManagementServiceBean implements GiveawayKeyManagementService {
|
||||
|
||||
@Autowired
|
||||
private GiveawayKeyRepository giveawayKeyRepository;
|
||||
|
||||
@Autowired
|
||||
private CounterService counterService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
public static final String GIVEAWAY_KEYS_COUNTER = "giveaway_keys";
|
||||
|
||||
@Override
|
||||
public GiveawayKey createGiveawayKey(Member creator, Member benefactor, String key, String description, String name) {
|
||||
Long counterValue = counterService.getNextCounterValue(creator.getGuild().getIdLong(), GIVEAWAY_KEYS_COUNTER);
|
||||
GiveawayKeyId id = new GiveawayKeyId(counterValue, creator.getGuild().getIdLong());
|
||||
|
||||
AUserInAServer creatorUser = userInServerManagementService.loadOrCreateUser(creator);
|
||||
AUserInAServer benefactorUser;
|
||||
if(benefactor != null) {
|
||||
benefactorUser = userInServerManagementService.loadOrCreateUser(benefactor);
|
||||
} else {
|
||||
benefactorUser = null;
|
||||
}
|
||||
|
||||
GiveawayKey giveawayKey = GiveawayKey
|
||||
.builder()
|
||||
.id(id)
|
||||
.creator(creatorUser)
|
||||
.used(false)
|
||||
.server(creatorUser.getServerReference())
|
||||
.key(key)
|
||||
.description(description)
|
||||
.benefactor(benefactorUser)
|
||||
.name(name)
|
||||
.build();
|
||||
return giveawayKeyRepository.save(giveawayKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(Long id, Long serverId) {
|
||||
GiveawayKey key = giveawayKeyRepository.findById(new GiveawayKeyId(id, serverId)).orElseThrow(GiveawayKeyNotFoundException::new);
|
||||
key.getGiveaway().setGiveawayKey(null);
|
||||
giveawayKeyRepository.delete(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<GiveawayKey> getById(Long id, Long serverId) {
|
||||
return giveawayKeyRepository.findById(new GiveawayKeyId(id, serverId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public GiveawayKey saveGiveawayKey(GiveawayKey giveawayKey) {
|
||||
return giveawayKeyRepository.save(giveawayKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GiveawayKey> getGiveawayKeys(Long serverId, Boolean showAll) {
|
||||
if(showAll) {
|
||||
return giveawayKeyRepository.findGiveawayKeysByServer_IdOrderById(serverId);
|
||||
} else {
|
||||
return giveawayKeyRepository.findGiveawayKeysByUsedAndServer_IdOrderById(false, serverId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,15 @@
|
||||
abstracto.featureFlags.giveaway.featureName=giveaway
|
||||
abstracto.featureFlags.giveaway.enabled=false
|
||||
|
||||
abstracto.postTargets.giveaways.name=giveaways
|
||||
abstracto.postTargets.giveaways.name=giveaways
|
||||
|
||||
abstracto.featureModes.keyGiveaways.featureName=giveaway
|
||||
abstracto.featureModes.keyGiveaways.mode=keyGiveaways
|
||||
abstracto.featureModes.keyGiveaways.enabled=false
|
||||
|
||||
abstracto.featureModes.autoNotifyGiveawayKeyWinners.featureName=giveaway
|
||||
abstracto.featureModes.autoNotifyGiveawayKeyWinners.mode=autoNotifyGiveawayKeyWinners
|
||||
abstracto.featureModes.autoNotifyGiveawayKeyWinners.enabled=false
|
||||
|
||||
abstracto.systemConfigs.keyGiveawaysDuration.name=keyGiveawaysDuration
|
||||
abstracto.systemConfigs.keyGiveawaysDuration.stringValue=24h
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
|
||||
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<property name="giveawayFeature" value="(SELECT id FROM feature WHERE key = 'giveaway')"/>
|
||||
<changeSet author="Sheldan" id="giveawayKey-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="addGiveawayKey"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${giveawayFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="removeGiveawayKey"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${giveawayFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="showGiveawayKeys"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${giveawayFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="createKeyGiveaway"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${giveawayFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
|
||||
<changeSet author="Sheldan" id="giveaway_key-table">
|
||||
<createTable tableName="giveaway_key">
|
||||
<column name="id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="creator_user_id" type="INTEGER">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="benefactor_user_id" type="INTEGER">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="winner_user_id" type="INTEGER">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="key" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(255)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="used" type="BOOLEAN">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="giveaway_id" type="BIGINT">
|
||||
<constraints nullable="true" />
|
||||
</column>
|
||||
<column name="giveaway_server_id" type="BIGINT">
|
||||
<constraints nullable="true" />
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<addPrimaryKey tableName="giveaway_key" columnNames="id, server_id"/>
|
||||
<addForeignKeyConstraint baseColumnNames="creator_user_id" baseTableName="giveaway_key" constraintName="fk_giveaway_key_creator" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id"
|
||||
referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="benefactor_user_id" baseTableName="giveaway_key" constraintName="fk_giveaway_key_benefactor" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id"
|
||||
referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="winner_user_id" baseTableName="giveaway_key" constraintName="fk_giveaway_key_winner" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id"
|
||||
referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="giveaway_id,giveaway_server_id" baseTableName="giveaway_key" constraintName="fk_giveaway_key_giveaway" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id,server_id"
|
||||
referencedTableName="giveaway" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="giveaway_key" constraintName="fk_giveaway_key_server" deferrable="false" initiallyDeferred="false"
|
||||
onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS giveaway_key_update_trigger ON giveaway_key;
|
||||
CREATE TRIGGER giveaway_update_trigger BEFORE UPDATE ON giveaway_key FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS giveaway_key_insert_trigger ON giveaway_key;
|
||||
CREATE TRIGGER giveaway_insert_trigger BEFORE INSERT ON giveaway_key FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
|
||||
<include file="giveaway_key.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -3,4 +3,5 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
|
||||
<include file="1.5.13/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.5.55/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user