mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-01 15:28:35 +00:00
Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df8eb399f7 | ||
|
|
3b7157714d | ||
|
|
ef7e5b4a46 | ||
|
|
c28286bf3f | ||
|
|
15e998e05d | ||
|
|
cdbdb395ac | ||
|
|
8819c12b81 | ||
|
|
a4e0971c27 | ||
|
|
726fc27331 | ||
|
|
a9d6a1221e | ||
|
|
84cc32e3b3 | ||
|
|
983c747bc3 | ||
|
|
a901d8a3ba | ||
|
|
fed2d24a55 | ||
|
|
aa359f60f3 | ||
|
|
353fda7770 | ||
|
|
b88ae377b1 | ||
|
|
3d915b96e7 | ||
|
|
9a1e0f330a | ||
|
|
afeef80878 | ||
|
|
453378f0b6 | ||
|
|
0e95ddf198 | ||
|
|
90816649e2 | ||
|
|
5b90d429c2 | ||
|
|
7b1774b73e | ||
|
|
618155a464 | ||
|
|
feabe6426e | ||
|
|
2dc21ce996 | ||
|
|
5643a41fd8 | ||
|
|
08d0561998 | ||
|
|
879c1b0173 | ||
|
|
d5bf70f586 | ||
|
|
4525fbc861 | ||
|
|
4671a78ff9 | ||
|
|
c4174562c6 | ||
|
|
bfaa5d6140 | ||
|
|
d2e8398fa4 | ||
|
|
c67209925a | ||
|
|
f3ac7895eb | ||
|
|
6d893e39bb | ||
|
|
94140104de | ||
|
|
6d80423244 | ||
|
|
27040e506a | ||
|
|
3bbf5a2391 | ||
|
|
11cb3b9ee1 | ||
|
|
dccf314e53 | ||
|
|
a0daeee3a1 | ||
|
|
1b7c383ced | ||
|
|
087dd266cc | ||
|
|
beda17f672 | ||
|
|
5c234295aa | ||
|
|
9cfe4bf353 | ||
|
|
75c45541c9 |
2
.env
2
.env
@@ -1,2 +1,2 @@
|
||||
REGISTRY_PREFIX=harbor.sheldan.dev/abstracto/
|
||||
VERSION=1.5.42
|
||||
VERSION=1.5.55
|
||||
13
.github/workflows/build.yml
vendored
13
.github/workflows/build.yml
vendored
@@ -37,15 +37,4 @@ jobs:
|
||||
- name: Build ui application
|
||||
working-directory: ./ui/experience-tracking
|
||||
run: npm run build
|
||||
- uses: actions/setup-ruby@v1
|
||||
- name: Send Webhook Notification
|
||||
if: always()
|
||||
env:
|
||||
JOB_STATUS: ${{ job.status }}
|
||||
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
|
||||
HOOK_OS_NAME: ${{ runner.os }}
|
||||
WORKFLOW_NAME: ${{ github.workflow }}
|
||||
run: |
|
||||
git clone https://github.com/DiscordHooks/github-actions-discord-webhook.git webhook
|
||||
bash webhook/send.sh $JOB_STATUS $WEBHOOK_URL
|
||||
shell: bash
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,7 +14,6 @@ target/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.zip
|
||||
*.tar.gz
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public class ShowAssignableRolePlaceConfig extends AbstractConditionableCommand
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
String name = (String) parameters.get(0);
|
||||
AssignableRolePlaceConfig config = service.getAssignableRolePlaceConfig(commandContext.getGuild(), name);
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(ASSIGNABLE_ROLES_CONFIG_POST_TEMPLATE_KEY, config, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannel(ASSIGNABLE_ROLES_CONFIG_POST_TEMPLATE_KEY, config, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public class ShowAssignableRolePlaces extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
AssignablePlaceOverview model = service.getAssignableRolePlaceOverview(commandContext.getGuild());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(ASSIGNABLE_ROLE_PLACES_OVERVIEW_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannel(ASSIGNABLE_ROLE_PLACES_OVERVIEW_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</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.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public class Choose extends AbstractConditionableCommand {
|
||||
.builder()
|
||||
.chosenValue(choice)
|
||||
.build();
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(CHOOSE_RESPONSE_TEMPLATE_KEY, responseModel, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannel(CHOOSE_RESPONSE_TEMPLATE_KEY, responseModel, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ public class Mock extends AbstractConditionableCommand {
|
||||
.originalText(messageText)
|
||||
.mockingText(mockingText)
|
||||
.build();
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(MOCK_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannel(MOCK_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ public class PressFCommand extends AbstractConditionableCommand {
|
||||
Long defaultDurationSeconds = configService.getLongValueOrConfigDefault(PRESS_F_DEFAULT_DURATION_SECONDS, commandContext.getGuild().getIdLong());
|
||||
Duration duration = Duration.ofSeconds(defaultDurationSeconds);
|
||||
PressFPromptModel pressFModel = entertainmentService.getPressFModel(text);
|
||||
List<CompletableFuture<Message>> messages = channelService.sendEmbedTemplateInMessageChannelList(RESPONSE_TEMPLATE, pressFModel, commandContext.getChannel());
|
||||
List<CompletableFuture<Message>> messages = channelService.sendEmbedTemplateInMessageChannel(RESPONSE_TEMPLATE, pressFModel, commandContext.getChannel());
|
||||
return FutureUtils.toSingleFutureGeneric(messages)
|
||||
.thenAccept(unused -> entertainmentService.persistPressF(text, duration, commandContext.getAuthor(),
|
||||
pressFModel.getPressFComponentId(), commandContext.getChannel(), messages.get(0).join().getIdLong()))
|
||||
|
||||
@@ -69,7 +69,7 @@ public class Roll extends AbstractConditionableCommand {
|
||||
.builder()
|
||||
.rolled(rolled)
|
||||
.build();
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(ROLL_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannel(ROLL_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public class Roulette extends AbstractConditionableCommand {
|
||||
.builder()
|
||||
.result(rouletteResult)
|
||||
.build();
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(ROULETTE_RESPONSE_TEMPLATE_KEY, responseModel, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannel(ROULETTE_RESPONSE_TEMPLATE_KEY, responseModel, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public class TransferCredits extends AbstractConditionableCommand {
|
||||
.targetMember(MemberDisplay.fromMember(targetMember))
|
||||
.credits(amount)
|
||||
.build();
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(TRANSFER_CREDITS_RESPONSE, responseModel, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannel(TRANSFER_CREDITS_RESPONSE, responseModel, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public class Mines extends AbstractConditionableCommand {
|
||||
board.setUserId(event.getMember().getIdLong());
|
||||
board.setServerId(serverId);
|
||||
board.setCredits(credit);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(MINE_BOARD_TEMPLATE_KEY, board);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(MINE_BOARD_TEMPLATE_KEY, board, serverId);
|
||||
return interactionService.replyMessageToSend(messageToSend, event)
|
||||
.thenCompose(interactionHook -> interactionHook.retrieveOriginal().submit())
|
||||
.thenApply(message -> {
|
||||
@@ -151,7 +151,7 @@ public class Mines extends AbstractConditionableCommand {
|
||||
board.setUserId(commandContext.getAuthor().getIdLong());
|
||||
board.setServerId(serverId);
|
||||
board.setCredits(credit);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(MINE_BOARD_TEMPLATE_KEY, board);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(MINE_BOARD_TEMPLATE_KEY, board, serverId);
|
||||
List<CompletableFuture<Message>> futures = channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel());
|
||||
return FutureUtils.toSingleFutureGeneric(futures)
|
||||
.thenAccept(unused -> gameService.persistMineBoardMessage(board, futures.get(0).join()))
|
||||
|
||||
@@ -54,7 +54,7 @@ public class MinesButtonClickedListener implements ButtonClickedListener {
|
||||
}
|
||||
gameService.uncoverBoard(mineBoard);
|
||||
}
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(Mines.MINE_BOARD_TEMPLATE_KEY, mineBoard);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(Mines.MINE_BOARD_TEMPLATE_KEY, mineBoard, model.getServerId());
|
||||
interactionService.editOriginal(messageToSend, model.getEvent().getHook()).thenAccept(message -> {
|
||||
gameService.updateMineBoard(mineBoard);
|
||||
log.info("Updated original mineboard for board {}.", mineBoard.getBoardId());
|
||||
|
||||
@@ -105,7 +105,9 @@ public class EntertainmentServiceBean implements EntertainmentService {
|
||||
|
||||
@Override
|
||||
public Integer getLoveCalcValue(String firstPart, String secondPart) {
|
||||
return secureRandom.nextInt(100);
|
||||
String fullInput = firstPart.toLowerCase() + secondPart.toLowerCase();
|
||||
Random random = new Random(fullInput.hashCode());
|
||||
return random.nextInt(100);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -191,8 +193,8 @@ public class EntertainmentServiceBean implements EntertainmentService {
|
||||
.text(pressF.getText())
|
||||
.messageId(pressF.getMessageId())
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(PRESS_F_RESULT_TEMPLATE_KEY, model);
|
||||
Long serverId = pressF.getServer().getId();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(PRESS_F_RESULT_TEMPLATE_KEY, model, serverId);
|
||||
Long channelId = pressF.getPressFChannel().getId();
|
||||
Long messageId = pressF.getMessageId();
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageEmbedToSendToAChannel(messageToSend, pressF.getPressFChannel()))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
package dev.sheldan.abstracto.experience.api;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.frontend.RoleDisplay;
|
||||
import dev.sheldan.abstracto.core.models.frontend.UserDisplay;
|
||||
import dev.sheldan.abstracto.core.service.GuildService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.model.api.UserExperienceDisplay;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceLevel;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceRole;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.model.database.LeaderBoardEntryResult;
|
||||
import dev.sheldan.abstracto.experience.service.ExperienceLevelService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
@@ -22,6 +34,7 @@ import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@@ -37,9 +50,21 @@ public class LeaderboardController {
|
||||
@Autowired
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceLevelService experienceLevelService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceRoleManagementService experienceRoleManagementService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceLevelManagementService experienceLevelManagementService;
|
||||
|
||||
@GetMapping(value = "/leaderboards/{serverId}", produces = "application/json")
|
||||
public Page<UserExperienceDisplay> getLeaderboard(@PathVariable("serverId") Long serverId,
|
||||
@PageableDefault(value = 25, page = 0)
|
||||
@PageableDefault(value = 50, page = 0)
|
||||
@SortDefault(sort = "experience", direction = Sort.Direction.DESC)
|
||||
Pageable pageable) {
|
||||
AServer server = serverManagementService.loadServer(serverId);
|
||||
@@ -49,12 +74,31 @@ public class LeaderboardController {
|
||||
.map(userExperience -> convertFromUser(guild, userExperience, pageable, allElements));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/leaderboards/{serverId}/{userId}", produces = "application/json")
|
||||
public List<UserExperienceDisplay> getLeaderboardForUser(@PathVariable("serverId") Long serverId, @PathVariable("userId") Long userId,
|
||||
@RequestParam("windowSize") Integer windowSize) {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(ServerUser.fromId(serverId, userId));
|
||||
Map<Long, AExperienceRole> experienceRolesForServer = experienceRoleManagementService.getExperienceRolesForServer(aUserInAServer.getServerReference())
|
||||
.stream()
|
||||
.collect(Collectors.toMap(AExperienceRole::getId, Function.identity()));
|
||||
|
||||
Map<Integer, AExperienceLevel> levels =
|
||||
experienceLevelManagementService.getLevelConfig().stream().collect(Collectors.toMap(AExperienceLevel::getLevel, Function.identity()));
|
||||
Guild guild = guildService.getGuildById(serverId);
|
||||
List<LeaderBoardEntryResult> allElements = userExperienceManagementService.getWindowedLeaderboardEntriesForUser(aUserInAServer, windowSize);
|
||||
return allElements.stream()
|
||||
.map(leaderboardEntry -> convertFromLeaderboardEntry(guild, leaderboardEntry, experienceRolesForServer, levels))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private UserExperienceDisplay convertFromUser(Guild guild, AUserExperience aUserExperience, Pageable pageable, Page<AUserExperience> page) {
|
||||
Long userId = aUserExperience.getUser().getUserReference().getId();
|
||||
Member member = guild.getMember(UserSnowflake.fromId(userId));
|
||||
AExperienceRole experienceRole = aUserExperience.getCurrentExperienceRole();
|
||||
UserDisplay userDisplay = null;
|
||||
RoleDisplay roleDisplay = null;
|
||||
Long experienceNeededToNextLevel = experienceLevelService.calculateExperienceToNextLevel(aUserExperience.getCurrentLevel().getLevel(), aUserExperience.getExperience());
|
||||
Long nextLevelExperience = experienceLevelService.calculateNextLevel(aUserExperience.getCurrentLevel().getLevel()).getExperienceNeeded();
|
||||
if(experienceRole != null) {
|
||||
Role role = guild.getRoleById(experienceRole.getRole().getId());
|
||||
if(role != null) {
|
||||
@@ -66,6 +110,9 @@ public class LeaderboardController {
|
||||
if(member != null) {
|
||||
userDisplay = UserDisplay.fromMember(member);
|
||||
}
|
||||
Long currentExpNeeded = aUserExperience.getCurrentLevel().getExperienceNeeded();
|
||||
Long experienceWithinLevel = aUserExperience.getExperience() - currentExpNeeded;
|
||||
Long experienceNeededForCurrentLevel = nextLevelExperience - currentExpNeeded;
|
||||
return UserExperienceDisplay
|
||||
.builder()
|
||||
.id(String.valueOf(userId))
|
||||
@@ -73,9 +120,56 @@ public class LeaderboardController {
|
||||
.level(aUserExperience.getLevelOrDefault())
|
||||
.rank((int) pageable.getOffset() + page.getContent().indexOf(aUserExperience) + 1)
|
||||
.experience(aUserExperience.getExperience())
|
||||
.experienceToNextLevel(experienceNeededToNextLevel)
|
||||
.currentLevelExperienceNeeded(experienceNeededForCurrentLevel)
|
||||
.experienceOnCurrentLevel(experienceWithinLevel)
|
||||
.percentage(((float) experienceWithinLevel / experienceNeededForCurrentLevel) * 100)
|
||||
.nextLevelExperienceNeeded(nextLevelExperience)
|
||||
.role(roleDisplay)
|
||||
.member(userDisplay)
|
||||
.build();
|
||||
}
|
||||
|
||||
private UserExperienceDisplay convertFromLeaderboardEntry(Guild guild, LeaderBoardEntryResult leaderBoardEntryResult,
|
||||
Map<Long, AExperienceRole> experienceRolesForServer, Map<Integer, AExperienceLevel> levels) {
|
||||
Long userId = leaderBoardEntryResult.getUserId();
|
||||
Member member = guild.getMember(UserSnowflake.fromId(userId));
|
||||
UserDisplay userDisplay = null;
|
||||
RoleDisplay roleDisplay = null;
|
||||
Long experienceNeededToNextLevel = experienceLevelService.calculateExperienceToNextLevel(leaderBoardEntryResult.getLevel(),
|
||||
leaderBoardEntryResult.getExperience());
|
||||
AExperienceLevel currentExperienceLevel = levels.get(leaderBoardEntryResult.getLevel());
|
||||
Long nextLevelExperience = experienceLevelService.calculateNextLevel(leaderBoardEntryResult.getLevel()).getExperienceNeeded();
|
||||
if(experienceRolesForServer.containsKey(leaderBoardEntryResult.getRoleId())) {
|
||||
AExperienceRole experienceRole = experienceRolesForServer.get(leaderBoardEntryResult.getRoleId());
|
||||
Role role = guild.getRoleById(experienceRole.getRole().getId());
|
||||
if(role != null) {
|
||||
roleDisplay = RoleDisplay.fromRole(role);
|
||||
} else {
|
||||
roleDisplay = RoleDisplay.fromARole(experienceRole.getRole());
|
||||
}
|
||||
}
|
||||
if(member != null) {
|
||||
userDisplay = UserDisplay.fromMember(member);
|
||||
}
|
||||
Long currentExpNeeded = currentExperienceLevel.getExperienceNeeded();
|
||||
Long experienceWithinLevel = leaderBoardEntryResult.getExperience() - currentExpNeeded;
|
||||
Long experienceNeededForCurrentLevel = nextLevelExperience - currentExpNeeded;
|
||||
return UserExperienceDisplay
|
||||
.builder()
|
||||
.id(String.valueOf(userId))
|
||||
.messages(leaderBoardEntryResult.getMessageCount())
|
||||
.level(leaderBoardEntryResult.getLevel())
|
||||
.rank(leaderBoardEntryResult.getRank())
|
||||
.experience(leaderBoardEntryResult.getExperience())
|
||||
.experienceToNextLevel(experienceNeededToNextLevel)
|
||||
.currentLevelExperienceNeeded(experienceNeededForCurrentLevel)
|
||||
.experienceOnCurrentLevel(experienceWithinLevel)
|
||||
.percentage(((float) experienceWithinLevel / experienceNeededForCurrentLevel) * 100)
|
||||
.nextLevelExperienceNeeded(nextLevelExperience)
|
||||
.role(roleDisplay)
|
||||
.member(userDisplay)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
package dev.sheldan.abstracto.experience.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.*;
|
||||
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.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
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.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
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.experience.config.ExperienceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceSlashCommandNames;
|
||||
@@ -23,8 +28,10 @@ import dev.sheldan.abstracto.experience.model.LeaderBoardEntry;
|
||||
import dev.sheldan.abstracto.experience.model.template.LeaderBoardEntryModel;
|
||||
import dev.sheldan.abstracto.experience.model.template.LeaderBoardModel;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
@@ -33,11 +40,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Shows the experience gain information of the top 10 users in the server, or if a page number is provided as a parameter, only the members which are on this page.
|
||||
*/
|
||||
@@ -48,6 +50,7 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
|
||||
public static final String LEADER_BOARD_POST_EMBED_TEMPLATE = "leaderboard_post";
|
||||
private static final String LEDERBOARD_COMMAND_NAME = "leaderboard";
|
||||
private static final String PAGE_PARAMETER = "page";
|
||||
private static final String FOCUS_PARAMETER = "focus";
|
||||
@Autowired
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@@ -80,21 +83,26 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
// parameter is optional, in case its not present, we default to the 0th page
|
||||
Integer page = !parameters.isEmpty() ? (Integer) parameters.get(0) : 1;
|
||||
return getMessageToSend(commandContext.getAuthor(), page)
|
||||
return getMessageToSend(commandContext.getAuthor(), page, false)
|
||||
.thenCompose(messageToSend -> FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel())))
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
private CompletableFuture<MessageToSend> getMessageToSend(Member actorUser, Integer page) {
|
||||
private CompletableFuture<MessageToSend> getMessageToSend(Member actorUser, Integer page, boolean focusMe) {
|
||||
AServer server = serverManagementService.loadServer(actorUser.getGuild());
|
||||
LeaderBoard leaderBoard = userExperienceService.findLeaderBoardData(server, page);
|
||||
LeaderBoard leaderBoard;
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(actorUser);
|
||||
if (focusMe) {
|
||||
leaderBoard = userExperienceService.findLeaderBoardDataForUserFocus(aUserInAServer);
|
||||
} else {
|
||||
leaderBoard = userExperienceService.findLeaderBoardData(server, page);
|
||||
}
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> completableFutures = converter.fromLeaderBoard(leaderBoard);
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> completableFutures = converter.fromLeaderBoard(leaderBoard, actorUser.getGuild().getIdLong());
|
||||
futures.add(completableFutures);
|
||||
log.info("Rendering leaderboard for page {} in server {} for user {}.", page, actorUser.getId(), actorUser.getGuild().getId());
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(actorUser);
|
||||
LeaderBoardEntry userRank = userExperienceService.getRankOfUserInServer(aUserInAServer);
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> userRankFuture = converter.fromLeaderBoardEntry(Arrays.asList(userRank));
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> userRankFuture = converter.fromLeaderBoardEntry(Arrays.asList(userRank), actorUser.getGuild().getIdLong());
|
||||
futures.add(userRankFuture);
|
||||
String leaderboardUrl;
|
||||
if(!StringUtils.isBlank(leaderboardExternalURL)) {
|
||||
@@ -108,6 +116,7 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
|
||||
.builder()
|
||||
.userExperiences(finalModels)
|
||||
.leaderboardUrl(leaderboardUrl)
|
||||
.showPlacement(!focusMe)
|
||||
.userExecuting(userRankFuture.join().get(0))
|
||||
.build();
|
||||
return CompletableFuture.completedFuture(templateService.renderEmbedTemplate(LEADER_BOARD_POST_EMBED_TEMPLATE, leaderBoardModel, actorUser.getGuild().getIdLong()));
|
||||
@@ -118,12 +127,18 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Integer page;
|
||||
boolean focusMe;
|
||||
if (slashCommandParameterService.hasCommandOption(FOCUS_PARAMETER, event)) {
|
||||
focusMe = slashCommandParameterService.getCommandOption(FOCUS_PARAMETER, event, Boolean.class);
|
||||
} else {
|
||||
focusMe = false;
|
||||
}
|
||||
if(slashCommandParameterService.hasCommandOption(PAGE_PARAMETER, event)) {
|
||||
page = slashCommandParameterService.getCommandOption(PAGE_PARAMETER, event, Integer.class);
|
||||
} else {
|
||||
page = 1;
|
||||
}
|
||||
return getMessageToSend(event.getMember(), page)
|
||||
return getMessageToSend(event.getMember(), page, focusMe)
|
||||
.thenCompose(messageToSend -> interactionService.replyMessageToSend(messageToSend, event))
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
}
|
||||
@@ -139,7 +154,17 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
|
||||
.templated(true)
|
||||
.type(Integer.class)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(pageParameter);
|
||||
|
||||
Parameter focusMe = Parameter
|
||||
.builder()
|
||||
.name(FOCUS_PARAMETER)
|
||||
.validators(leaderBoardPageValidators)
|
||||
.optional(true)
|
||||
.slashCommandOnly(true)
|
||||
.templated(true)
|
||||
.type(Boolean.class)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(pageParameter, focusMe);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
|
||||
@@ -30,7 +30,9 @@ import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
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;
|
||||
|
||||
@@ -78,6 +80,9 @@ public class Rank extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Value("${abstracto.experience.leaderboard.externalUrl}")
|
||||
private String leaderboardExternalURL;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
@@ -87,7 +92,7 @@ public class Rank extends AbstractConditionableCommand {
|
||||
}
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(targetMember);
|
||||
LeaderBoardEntry userRank = userExperienceService.getRankOfUserInServer(aUserInAServer);
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> future = converter.fromLeaderBoardEntry(Arrays.asList(userRank));
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> future = converter.fromLeaderBoardEntry(Arrays.asList(userRank), commandContext.getGuild().getIdLong());
|
||||
RankModel rankModel = RankModel
|
||||
.builder()
|
||||
.member(targetMember)
|
||||
@@ -107,14 +112,21 @@ public class Rank extends AbstractConditionableCommand {
|
||||
Long currentExpNeeded = experienceObj.getCurrentLevel().getExperienceNeeded();
|
||||
Long experienceNeededToNextLevel = experienceLevelService.calculateExperienceToNextLevel(experienceObj.getCurrentLevel().getLevel(), experienceObj.getExperience());
|
||||
Long nextLevelExperience = experienceLevelService.calculateNextLevel(experienceObj.getCurrentLevel().getLevel()).getExperienceNeeded();
|
||||
Long levelExperience = nextLevelExperience - currentExpNeeded;
|
||||
Long inLevelExperience = experienceObj.getExperience() - currentExpNeeded;
|
||||
Long experienceNeededForCurrentLevel = nextLevelExperience - currentExpNeeded;
|
||||
Long experienceWithinLevel = experienceObj.getExperience() - currentExpNeeded;
|
||||
rankModel.setExperienceForCurrentLevel(currentExpNeeded);
|
||||
rankModel.setCurrentLevelPercentage(((float) inLevelExperience / levelExperience) * 100);
|
||||
rankModel.setLevelExperience(levelExperience);
|
||||
rankModel.setCurrentLevelPercentage(((float) experienceWithinLevel / experienceNeededForCurrentLevel) * 100);
|
||||
rankModel.setLevelExperience(experienceNeededForCurrentLevel);
|
||||
rankModel.setExperienceToNextLevel(experienceNeededToNextLevel);
|
||||
rankModel.setInLevelExperience(inLevelExperience);
|
||||
rankModel.setInLevelExperience(experienceWithinLevel);
|
||||
rankModel.setNextLevelExperience(nextLevelExperience);
|
||||
String leaderboardUrl;
|
||||
if(!StringUtils.isBlank(leaderboardExternalURL)) {
|
||||
leaderboardUrl = String.format("%s/experience/leaderboards/%s/%s", leaderboardExternalURL, toRender.getGuild().getIdLong(), toRender.getId());
|
||||
} else {
|
||||
leaderboardUrl = null;
|
||||
}
|
||||
rankModel.setLeaderboardUrl(leaderboardUrl);
|
||||
return templateService.renderEmbedTemplate(RANK_POST_EMBED_TEMPLATE, rankModel, toRender.getGuild().getIdLong());
|
||||
}
|
||||
|
||||
@@ -128,7 +140,7 @@ public class Rank extends AbstractConditionableCommand {
|
||||
}
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(targetMember);
|
||||
LeaderBoardEntry userRank = userExperienceService.getRankOfUserInServer(aUserInAServer);
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> future = converter.fromLeaderBoardEntry(Arrays.asList(userRank));
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> future = converter.fromLeaderBoardEntry(Arrays.asList(userRank), event.getGuild().getIdLong());
|
||||
RankModel rankModel = RankModel
|
||||
.builder()
|
||||
.member(targetMember)
|
||||
|
||||
@@ -3,7 +3,6 @@ package dev.sheldan.abstracto.experience.converter;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoard;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoardEntry;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.model.template.LeaderBoardEntryModel;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -42,26 +41,23 @@ public class LeaderBoardModelConverter {
|
||||
* @return The list of {@link LeaderBoardEntryModel leaderboarEntryModels} which contain the fully fledged information provided to the
|
||||
* leader board template
|
||||
*/
|
||||
public CompletableFuture<List<LeaderBoardEntryModel>> fromLeaderBoard(LeaderBoard leaderBoard) {
|
||||
public CompletableFuture<List<LeaderBoardEntryModel>> fromLeaderBoard(LeaderBoard leaderBoard, Long serverId) {
|
||||
log.debug("Converting {} entries to a list of leaderboard entries.", leaderBoard.getEntries().size());
|
||||
return fromLeaderBoardEntry(leaderBoard.getEntries());
|
||||
return fromLeaderBoardEntry(leaderBoard.getEntries(), serverId);
|
||||
}
|
||||
|
||||
public CompletableFuture<List<LeaderBoardEntryModel>> fromLeaderBoardEntry(List<LeaderBoardEntry> leaderBoardEntries) {
|
||||
public CompletableFuture<List<LeaderBoardEntryModel>> fromLeaderBoardEntry(List<LeaderBoardEntry> leaderBoardEntries, Long serverId) {
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
Long serverId = leaderBoardEntries.get(0).getExperience().getServer().getId();
|
||||
Map<Long, LeaderBoardEntryModel> models = leaderBoardEntries
|
||||
.stream()
|
||||
.map(leaderBoardEntry -> {
|
||||
AUserExperience experience = leaderBoardEntry.getExperience();
|
||||
Long userId = experience.getUser().getUserReference().getId();
|
||||
userIds.add(userId);
|
||||
userIds.add(leaderBoardEntry.getUserId());
|
||||
return LeaderBoardEntryModel
|
||||
.builder()
|
||||
.userId(userId)
|
||||
.experience(experience.getExperience())
|
||||
.messageCount(experience.getMessageCount())
|
||||
.level(experience.getLevelOrDefault())
|
||||
.userId(leaderBoardEntry.getUserId())
|
||||
.experience(leaderBoardEntry.getExperience())
|
||||
.messageCount(leaderBoardEntry.getMessageCount())
|
||||
.level(leaderBoardEntry.getLevel())
|
||||
.rank(leaderBoardEntry.getRank())
|
||||
.build();
|
||||
})
|
||||
|
||||
@@ -16,4 +16,9 @@ public class UserExperienceDisplay {
|
||||
private Long experience;
|
||||
private Long messages;
|
||||
private RoleDisplay role;
|
||||
private Long experienceToNextLevel;
|
||||
private Long experienceOnCurrentLevel;
|
||||
private Long currentLevelExperienceNeeded;
|
||||
private Float percentage;
|
||||
private Long nextLevelExperienceNeeded;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,33 @@ public interface UserExperienceRepository extends JpaRepository<AUserExperience
|
||||
"WHERE rank.id = :userInServerId", nativeQuery = true)
|
||||
LeaderBoardEntryResult getRankOfUserInServer(@Param("userInServerId") Long id, @Param("serverId") Long serverId);
|
||||
|
||||
@Query(value = "WITH user_experience_ranked AS" +
|
||||
" ( " +
|
||||
" SELECT us.id, uis.user_id, us.experience, us.role_id, us.level_id, us.message_count, ROW_NUMBER() OVER ( ORDER BY experience DESC ) as rank" +
|
||||
" FROM user_experience us INNER JOIN user_in_server uis ON us.id = uis.user_in_server_id " +
|
||||
" INNER JOIN server s ON s.id = uis.server_id WHERE s.id = :serverId" +
|
||||
" )," +
|
||||
" user_experience_target as (" +
|
||||
" SELECT ranking.id as id, ranking.user_id, ranking.experience as experience, ranking.message_count, ranking.level_id as level, ranking.rank " +
|
||||
" FROM user_experience_ranked ranking" +
|
||||
" WHERE ranking.id = :userInServerId" +
|
||||
" )" +
|
||||
" (SELECT r.id, r.user_id as userId, r.experience, r.level_id as level, r.role_id as roleId, r.message_count as messageCount, r.rank as rank" +
|
||||
" FROM user_experience_ranked r " +
|
||||
" CROSS JOIN user_experience_target t" +
|
||||
" WHERE r.rank <= t.rank " +
|
||||
" ORDER BY r.rank DESC " +
|
||||
" LIMIT :before) " +
|
||||
"UNION ALL " +
|
||||
" (SELECT r.id, r.user_id as userId, r.experience, r.level_id as level, r.role_id as roleId, r.message_count as messageCount, r.rank as rank" +
|
||||
" FROM user_experience_ranked r" +
|
||||
" CROSS JOIN user_experience_target t" +
|
||||
" WHERE r.rank > t.rank " +
|
||||
" ORDER BY r.rank " +
|
||||
" LIMIT :after) " +
|
||||
"ORDER BY rank", nativeQuery = true)
|
||||
List<LeaderBoardEntryResult> getRankOfUserWithWindow(@Param("userInServerId") Long id, @Param("serverId") Long serverId, @Param("before") Long beforeInclusive, @Param("after") Long after);
|
||||
|
||||
@Modifying(clearAutomatically = true)
|
||||
@Query("update AUserExperience u set u.currentExperienceRole = null where u.currentExperienceRole.id = :roleId")
|
||||
void removeExperienceRoleFromUsers(@Param("roleId") Long experienceRoleId);
|
||||
|
||||
@@ -361,7 +361,7 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
.newRole(oldRoleId != null ? RoleDisplay.fromRole(oldRoleId) : null)
|
||||
.newRole(newRoleId != null ? RoleDisplay.fromRole(newRoleId) : null)
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("experience_level_up_notification", model);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("experience_level_up_notification", model, serverId);
|
||||
FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, message.getChannel())).thenAccept(unused -> {
|
||||
log.info("Sent level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId, message.getChannel().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
@@ -491,11 +491,32 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
int pageOffset = page * pageSize;
|
||||
for (int i = 0; i < experiences.size(); i++) {
|
||||
AUserExperience userExperience = experiences.get(i);
|
||||
entries.add(LeaderBoardEntry.builder().experience(userExperience).rank(pageOffset + i + 1).build());
|
||||
LeaderBoardEntry entry = LeaderBoardEntry.fromAUserExperience(userExperience);
|
||||
entry.setRank(pageOffset + i + 1);
|
||||
entries.add(entry);
|
||||
}
|
||||
return LeaderBoard.builder().entries(entries).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeaderBoard findLeaderBoardDataForUserFocus(AUserInAServer aUserInAServer) {
|
||||
List<LeaderBoardEntry> allEntries =
|
||||
userExperienceManagementService.getWindowedLeaderboardEntriesForUser(aUserInAServer, 10)
|
||||
.stream().map(leaderBoardEntryResult -> LeaderBoardEntry
|
||||
.builder()
|
||||
.experience(leaderBoardEntryResult.getExperience())
|
||||
.level(leaderBoardEntryResult.getLevel())
|
||||
.userId(leaderBoardEntryResult.getUserId())
|
||||
.messageCount(leaderBoardEntryResult.getMessageCount())
|
||||
.rank(leaderBoardEntryResult.getRank())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
return LeaderBoard
|
||||
.builder()
|
||||
.entries(allEntries)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeaderBoardEntry getRankOfUserInServer(AUserInAServer userInAServer) {
|
||||
log.debug("Retrieving rank for {}", userInAServer.getUserReference().getId());
|
||||
@@ -509,7 +530,9 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
if(rankOfUserInServer != null) {
|
||||
rank = rankOfUserInServer.getRank();
|
||||
}
|
||||
return LeaderBoardEntry.builder().experience(aUserExperience).rank(rank).build();
|
||||
LeaderBoardEntry entry = LeaderBoardEntry.fromAUserExperience(aUserExperience);
|
||||
entry.setRank(rank);
|
||||
return entry;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,6 +82,12 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
|
||||
return repository.findTop10ByUser_ServerReferenceOrderByExperienceDesc(aServer, PageRequest.of(page, size));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LeaderBoardEntryResult> getWindowedLeaderboardEntriesForUser(AUserInAServer aUserInAServer, Integer windowSize) {
|
||||
return repository.getRankOfUserWithWindow(aUserInAServer.getUserInServerId(), aUserInAServer.getServerReference().getId(), windowSize.longValue() / 2 + 1,
|
||||
windowSize.longValue() / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeaderBoardEntryResult getRankOfUserInServer(AUserExperience userExperience) {
|
||||
return repository.getRankOfUserInServer(userExperience.getId(), userExperience.getServer().getId());
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
package dev.sheldan.abstracto.experience.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoard;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoardEntry;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.model.template.LeaderBoardEntryModel;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LeaderBoardModelConverterTest {
|
||||
|
||||
@InjectMocks
|
||||
public LeaderBoardModelConverter testUnit;
|
||||
|
||||
@Mock
|
||||
private MemberService memberService;
|
||||
|
||||
@Mock
|
||||
private LeaderBoardModelConverter self;
|
||||
|
||||
private static final Long SERVER_ID = 4L;
|
||||
private static final Long USER_ID = 5L;
|
||||
private static final Long USER_ID_2 = 6L;
|
||||
private static final Long USER_IN_SERVER_ID = 7L;
|
||||
private static final Long USER_IN_SERVER_ID_2 = 8L;
|
||||
private static final Long EXPERIENCE = 9L;
|
||||
private static final Long MESSAGES = 10L;
|
||||
private static final Integer LEVEL = 54;
|
||||
|
||||
@Test
|
||||
public void testFromLeaderBoard() {
|
||||
Integer firstRank = 1;
|
||||
|
||||
LeaderBoardEntry entry = getEntry(firstRank, USER_ID, USER_IN_SERVER_ID);
|
||||
Integer secondRank = 2;
|
||||
LeaderBoardEntry entry2 = getEntry(secondRank, USER_ID_2, USER_IN_SERVER_ID_2);
|
||||
List<LeaderBoardEntry> entries = Arrays.asList(entry, entry2);
|
||||
LeaderBoard leaderBoard = Mockito.mock(LeaderBoard.class);
|
||||
when(leaderBoard.getEntries()).thenReturn(entries);
|
||||
Member member = Mockito.mock(Member.class);
|
||||
when(member.getIdLong()).thenReturn(USER_ID);
|
||||
when(memberService.getMembersInServerAsync(SERVER_ID, Arrays.asList(USER_ID, USER_ID_2))).thenReturn(CompletableFuture.completedFuture(Arrays.asList(member)));
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> leaderBoardEntryModels = testUnit.fromLeaderBoard(leaderBoard);
|
||||
LeaderBoardEntryModel firstEntry = leaderBoardEntryModels.join().get(0);
|
||||
Assert.assertEquals(USER_ID, firstEntry.getUserId());
|
||||
LeaderBoardEntryModel secondEntry = leaderBoardEntryModels.join().get(1);
|
||||
Assert.assertEquals(USER_ID_2, secondEntry.getUserId());
|
||||
Assert.assertEquals(entries.size(), leaderBoardEntryModels.join().size());
|
||||
}
|
||||
|
||||
private LeaderBoardEntry getEntry(Integer rank, Long userId, Long userInServerId) {
|
||||
AUserExperience experience = Mockito.mock(AUserExperience.class);
|
||||
when(experience.getMessageCount()).thenReturn(MESSAGES);
|
||||
when(experience.getExperience()).thenReturn(EXPERIENCE);
|
||||
AUserInAServer userInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(experience.getUser()).thenReturn(userInAServer);
|
||||
AUser user = Mockito.mock(AUser.class);
|
||||
when(userInAServer.getUserReference()).thenReturn(user);
|
||||
when(user.getId()).thenReturn(userId);
|
||||
AServer server = Mockito.mock(AServer.class);
|
||||
when(experience.getServer()).thenReturn(server);
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
LeaderBoardEntry entry = Mockito.mock(LeaderBoardEntry.class);
|
||||
when(entry.getRank()).thenReturn(rank);
|
||||
when(entry.getExperience()).thenReturn(experience);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -12,12 +12,19 @@ import lombok.Setter;
|
||||
@Setter
|
||||
@Builder
|
||||
public class LeaderBoardEntry {
|
||||
/**
|
||||
* Object representing the current experience status of a user in a guild.
|
||||
*/
|
||||
private AUserExperience experience;
|
||||
/**
|
||||
* The rank this user has in the respective guild.
|
||||
*/
|
||||
private Long userId;
|
||||
private Integer level;
|
||||
private Long experience;
|
||||
private Long messageCount;
|
||||
private Integer rank;
|
||||
|
||||
public static LeaderBoardEntry fromAUserExperience(AUserExperience aUserExperience) {
|
||||
return LeaderBoardEntry
|
||||
.builder()
|
||||
.experience(aUserExperience.getExperience())
|
||||
.userId(aUserExperience.getUser().getUserReference().getId())
|
||||
.messageCount(aUserExperience.getMessageCount())
|
||||
.level(aUserExperience.getLevelOrDefault())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,8 @@ public interface LeaderBoardEntryResult {
|
||||
|
||||
Long getId();
|
||||
|
||||
/**
|
||||
* The {@link dev.sheldan.abstracto.core.models.database.AUserInAServer} id of the user
|
||||
* @return The ID of the user in a server
|
||||
*/
|
||||
Long getUserInServerId();
|
||||
Long getUserId();
|
||||
Long getRoleId();
|
||||
|
||||
/**
|
||||
* The experience of the {@link dev.sheldan.abstracto.core.models.database.AUserInAServer}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.experience.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.context.SlimUserInitiatedServerContext;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
@@ -25,4 +26,9 @@ public class LeaderBoardModel extends SlimUserInitiatedServerContext {
|
||||
*/
|
||||
private LeaderBoardEntryModel userExecuting;
|
||||
private String leaderboardUrl;
|
||||
/**
|
||||
* Whether to show the users own placement
|
||||
*/
|
||||
@Builder.Default
|
||||
private boolean showPlacement = true;
|
||||
}
|
||||
|
||||
@@ -47,4 +47,5 @@ public class RankModel {
|
||||
* The member to show the rank for
|
||||
*/
|
||||
private Member member;
|
||||
private String leaderboardUrl;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ public interface AUserExperienceService {
|
||||
* from the desired page
|
||||
*/
|
||||
LeaderBoard findLeaderBoardData(AServer server, Integer page);
|
||||
LeaderBoard findLeaderBoardDataForUserFocus(AUserInAServer aUserInAServer);
|
||||
|
||||
/**
|
||||
* Retrieves the {@link LeaderBoardEntry} from a specific {@link AUserInAServer} containing information about the
|
||||
|
||||
@@ -62,6 +62,7 @@ public interface UserExperienceManagementService {
|
||||
* @return A list desc ordered by {@link AUserExperience} experience only containing the elements between {@code start} and @{code end}
|
||||
*/
|
||||
List<AUserExperience> findLeaderBoardUsersPaginated(AServer server, Integer page, Integer size);
|
||||
List<LeaderBoardEntryResult> getWindowedLeaderboardEntriesForUser(AUserInAServer aUserInAServer, Integer windowSize);
|
||||
|
||||
/**
|
||||
* Returns the {@link LeaderBoardEntryResult} of the given {@link AUserExperience}.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>giveaway</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>giveaway-impl</artifactId>
|
||||
@@ -38,6 +38,12 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>metrics-int</artifactId>
|
||||
|
||||
@@ -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,63 @@ 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)
|
||||
.serverId(creator.getGuild().getIdLong())
|
||||
.title(title)
|
||||
.build();
|
||||
|
||||
return giveawayService.createGiveaway(request)
|
||||
.thenAccept(unused -> interactionService.sendEmbed(CREATE_GIVEAWAY_RESPONSE_TEMPLATE_KEY, interactionHook));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,6 +169,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;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -130,7 +154,7 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
giveawayMessageModel.setJoinedUserCount(giveaway.getParticipants().size() + 1L);
|
||||
Long giveawayId = giveaway.getGiveawayId().getId();
|
||||
log.info("Adding giveaway participating of user {} to giveaway {} in server {}.", member.getIdLong(), giveawayId, member.getGuild().getIdLong());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GIVEAWAY_MESSAGE_TEMPLATE_KEY, giveawayMessageModel);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GIVEAWAY_MESSAGE_TEMPLATE_KEY, giveawayMessageModel, member.getGuild().getIdLong());
|
||||
return channelService.editEmbedMessageInAChannel(messageToSend.getEmbeds().get(0), messageChannel, giveaway.getMessageId())
|
||||
.thenAccept(message -> {
|
||||
self.persistAddedParticipant(member, 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
|
||||
@@ -183,18 +203,57 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
.winners(winnerDisplays)
|
||||
.build();
|
||||
log.info("Sending result message for giveaway {} in server {}.", giveawayId, serverId);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GIVEAWAY_RESULT_MESSAGE_TEMPLATE_KEY, resultModel);
|
||||
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);
|
||||
MessageToSend giveawayMessageToSend = templateService.renderEmbedTemplate(GIVEAWAY_MESSAGE_TEMPLATE_KEY, giveawayMessageModel);
|
||||
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
|
||||
@@ -208,7 +267,7 @@ public class GiveawayServiceBean implements GiveawayService {
|
||||
GiveawayMessageModel giveawayMessageModel = GiveawayMessageModel.fromGiveaway(giveaway);
|
||||
giveawayMessageModel.setCancelled(true);
|
||||
schedulerService.stopTrigger(giveaway.getReminderTriggerKey());
|
||||
MessageToSend giveawayMessageToSend = templateService.renderEmbedTemplate(GIVEAWAY_MESSAGE_TEMPLATE_KEY, giveawayMessageModel);
|
||||
MessageToSend giveawayMessageToSend = templateService.renderEmbedTemplate(GIVEAWAY_MESSAGE_TEMPLATE_KEY, giveawayMessageModel, serverId);
|
||||
|
||||
GuildMessageChannel messageChannel = channelService.getMessageChannelFromServer(giveaway.getServer().getId(), giveaway.getGiveawayChannel().getId());
|
||||
log.debug("Updating original giveaway message to consider cancellation for giveaway {} in server {}.", giveawayId, serverId);
|
||||
@@ -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>
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>giveaway</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>giveaway-int</artifactId>
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.giveaway.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 org.springframework.stereotype.Component;
|
||||
|
||||
@@ -11,6 +12,8 @@ import java.util.List;
|
||||
@Component
|
||||
public class GiveawayFeatureConfig implements FeatureConfig {
|
||||
|
||||
public static final String KEY_GIVEAWAYS_DURATION = "keyGiveawaysDuration";
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return GiveawayFeatureDefinition.GIVEAWAY;
|
||||
@@ -20,4 +23,14 @@ public class GiveawayFeatureConfig implements FeatureConfig {
|
||||
public List<PostTargetEnum> getRequiredPostTargets() {
|
||||
return Arrays.asList(GiveawayPostTarget.GIVEAWAYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getAvailableModes() {
|
||||
return Arrays.asList(GiveawayMode.KEY_GIVEAWAYS, GiveawayMode.AUTO_NOTIFY_GIVEAWAY_KEY_WINNERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
return Arrays.asList(KEY_GIVEAWAYS_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.sheldan.abstracto.giveaway.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum GiveawayMode implements FeatureMode {
|
||||
KEY_GIVEAWAYS("keyGiveaways"),
|
||||
AUTO_NOTIFY_GIVEAWAY_KEY_WINNERS("autoNotifyGiveawayKeyWinners");
|
||||
|
||||
private final String key;
|
||||
|
||||
GiveawayMode(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package dev.sheldan.abstracto.giveaway.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
public class GiveawayKeyNotFoundException extends AbstractoTemplatableException {
|
||||
public GiveawayKeyNotFoundException() {
|
||||
super("Giveaway key not found.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "giveaway_key_not_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package dev.sheldan.abstracto.giveaway.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
public class GiveawayNotPossibleException extends AbstractoTemplatableException {
|
||||
public GiveawayNotPossibleException() {
|
||||
super("Giveaway not possible.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "giveaway_not_possible_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package dev.sheldan.abstracto.giveaway.model;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -12,8 +11,10 @@ import java.time.Duration;
|
||||
@Getter
|
||||
public class GiveawayCreationRequest {
|
||||
|
||||
private Member creator;
|
||||
private Member benefactor;
|
||||
private Long creatorId;
|
||||
private Long serverId;
|
||||
private Long benefactorId;
|
||||
private Long giveawayKeyId;
|
||||
private String title;
|
||||
private String description;
|
||||
private Duration duration;
|
||||
|
||||
@@ -65,6 +65,9 @@ public class Giveaway {
|
||||
@Column(name = "message_id", nullable = false)
|
||||
private Long messageId;
|
||||
|
||||
@OneToOne(mappedBy = "giveaway")
|
||||
private GiveawayKey giveawayKey;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package dev.sheldan.abstracto.giveaway.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.embed.GiveawayKeyId;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.EmbeddedId;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.MapsId;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "giveaway_key")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class GiveawayKey {
|
||||
@Id
|
||||
@EmbeddedId
|
||||
private GiveawayKeyId id;
|
||||
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumns(
|
||||
{
|
||||
@JoinColumn(name = "giveaway_id", referencedColumnName = "id"),
|
||||
@JoinColumn(name = "giveaway_server_id", referencedColumnName = "server_id")
|
||||
})
|
||||
private Giveaway giveaway;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
|
||||
@MapsId("serverId")
|
||||
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "creator_user_id", nullable = false)
|
||||
private AUserInAServer creator;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "winner_user_id")
|
||||
private AUserInAServer winner;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "benefactor_user_id")
|
||||
private AUserInAServer benefactor;
|
||||
|
||||
@Column(name = "key", nullable = false)
|
||||
private String key;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "used")
|
||||
private Boolean used;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.sheldan.abstracto.giveaway.model.database.embed;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Embeddable
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@EqualsAndHashCode
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class GiveawayKeyId implements Serializable {
|
||||
@Column(name = "id")
|
||||
private Long keyId;
|
||||
|
||||
@Column(name = "server_id")
|
||||
private Long serverId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.abstracto.giveaway.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class GiveawayKeyDisplayModel {
|
||||
private String key;
|
||||
private String name;
|
||||
private Long id;
|
||||
private String description;
|
||||
private Boolean used;
|
||||
private MemberDisplay creator;
|
||||
private MemberDisplay benefactor;
|
||||
private MemberDisplay winner;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package dev.sheldan.abstracto.giveaway.model.template;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class GiveawayKeysDisplayModel {
|
||||
private List<GiveawayKeyDisplayModel> keys;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.sheldan.abstracto.giveaway.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.giveaway.model.database.Giveaway;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
@Setter
|
||||
public class GiveawayWinnerNotificationMessageModel {
|
||||
private String title;
|
||||
private String description;
|
||||
private String key;
|
||||
private Long giveawayId;
|
||||
private MemberDisplay creator;
|
||||
private MemberDisplay benefactor;
|
||||
|
||||
public static GiveawayWinnerNotificationMessageModel fromGiveaway(Giveaway giveaway, String key) {
|
||||
return GiveawayWinnerNotificationMessageModel
|
||||
.builder()
|
||||
.title(giveaway.getTitle())
|
||||
.description(giveaway.getDescription())
|
||||
.key(key)
|
||||
.benefactor(giveaway.getBenefactor() != null ? MemberDisplay.fromAUserInAServer(giveaway.getBenefactor()) : null)
|
||||
.creator(MemberDisplay.fromAUserInAServer(giveaway.getCreator()))
|
||||
.giveawayId(giveaway.getGiveawayId().getId())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface GiveawayService {
|
||||
CompletableFuture<Void> createGiveaway(GiveawayCreationRequest giveawayCreationRequest);
|
||||
CompletableFuture<Long> createGiveaway(GiveawayCreationRequest giveawayCreationRequest);
|
||||
CompletableFuture<Void> addGiveawayParticipant(Giveaway giveaway, Member member, MessageChannel messageChannel);
|
||||
CompletableFuture<Void> evaluateGiveaway(Long giveawayId, Long serverId);
|
||||
CompletableFuture<Void> cancelGiveaway(Long giveawayId, Long serverId);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.abstracto.giveaway.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.giveaway.model.database.GiveawayKey;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
public interface GiveawayKeyManagementService {
|
||||
GiveawayKey createGiveawayKey(Member creator, Member benefactor, String key, String description, String name);
|
||||
void deleteById(Long id, Long serverId);
|
||||
Optional<GiveawayKey> getById(Long id, Long serverId);
|
||||
GiveawayKey saveGiveawayKey(GiveawayKey giveawayKey);
|
||||
List<GiveawayKey> getGiveawayKeys(Long serverId, Boolean ignoreUsedFlag);
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>giveaway</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>image-generation</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>image-generation-impl</artifactId>
|
||||
|
||||
@@ -58,7 +58,7 @@ public class AmongusText extends AbstractConditionableCommand {
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
String text = (String) commandContext.getParameters().getParameters().get(0);
|
||||
File amongusTextImage = imageGenerationService.getAmongusTextImage(text);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(AMONGUS_TEXT_EMBED_TEMPLATE_KEY, new Object());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(AMONGUS_TEXT_EMBED_TEMPLATE_KEY, new Object(), commandContext.getGuild().getIdLong());
|
||||
// template support does not support binary files
|
||||
AttachedFile file = AttachedFile
|
||||
.builder()
|
||||
@@ -76,7 +76,7 @@ public class AmongusText extends AbstractConditionableCommand {
|
||||
event.deferReply().queue();
|
||||
String text = slashCommandParameterService.getCommandOption(TEXT_PARAMETER_KEY, event, String.class);
|
||||
File amongusTextImage = imageGenerationService.getAmongusTextImage(text);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(AMONGUS_TEXT_EMBED_TEMPLATE_KEY, new Object());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(AMONGUS_TEXT_EMBED_TEMPLATE_KEY, new Object(), event.getGuild().getIdLong());
|
||||
// template support does not support binary files
|
||||
AttachedFile file = AttachedFile
|
||||
.builder()
|
||||
|
||||
@@ -76,7 +76,7 @@ public class Bonk extends AbstractConditionableCommand {
|
||||
}
|
||||
}
|
||||
File bonkGifFile = imageGenerationService.getBonkGif(member.getEffectiveAvatar().getUrl(imageSize));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(BONK_EMBED_TEMPLATE_KEY, new Object());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(BONK_EMBED_TEMPLATE_KEY, new Object(), commandContext.getGuild().getIdLong());
|
||||
// template support does not support binary files
|
||||
AttachedFile file = AttachedFile
|
||||
.builder()
|
||||
@@ -99,7 +99,7 @@ public class Bonk extends AbstractConditionableCommand {
|
||||
targetMember = event.getMember();
|
||||
}
|
||||
File bonkGifFile = imageGenerationService.getBonkGif(targetMember.getEffectiveAvatar().getUrl(imageSize));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(BONK_EMBED_TEMPLATE_KEY, new Object());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(BONK_EMBED_TEMPLATE_KEY, new Object(), event.getGuild().getIdLong());
|
||||
// template support does not support binary files
|
||||
AttachedFile file = AttachedFile
|
||||
.builder()
|
||||
|
||||
@@ -76,7 +76,7 @@ public class Pat extends AbstractConditionableCommand {
|
||||
}
|
||||
}
|
||||
File patGifFile = imageGenerationService.getPatGif(member.getEffectiveAvatar().getUrl(imageSize));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(PAT_EMBED_TEMPLATE_KEY, new Object());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(PAT_EMBED_TEMPLATE_KEY, new Object(), commandContext.getGuild().getIdLong());
|
||||
// template support does not support binary files
|
||||
AttachedFile file = AttachedFile
|
||||
.builder()
|
||||
@@ -99,7 +99,7 @@ public class Pat extends AbstractConditionableCommand {
|
||||
targetMember = event.getMember();
|
||||
}
|
||||
File patGifFile = imageGenerationService.getPatGif(targetMember.getEffectiveAvatar().getUrl(imageSize));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(PAT_EMBED_TEMPLATE_KEY, new Object());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(PAT_EMBED_TEMPLATE_KEY, new Object(), event.getGuild().getIdLong());
|
||||
// template support does not support binary files
|
||||
AttachedFile file = AttachedFile
|
||||
.builder()
|
||||
|
||||
@@ -68,7 +68,7 @@ public class Triggered extends AbstractConditionableCommand {
|
||||
member = (Member) parameters.get(0);
|
||||
}
|
||||
File triggeredGifFile = imageGenerationService.getTriggeredGif(member.getEffectiveAvatar().getUrl(imageSize));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(TRIGGERED_EMBED_TEMPLATE_KEY, new Object());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(TRIGGERED_EMBED_TEMPLATE_KEY, new Object(), commandContext.getGuild().getIdLong());
|
||||
// template support does not support binary files
|
||||
AttachedFile file = AttachedFile
|
||||
.builder()
|
||||
@@ -91,7 +91,7 @@ public class Triggered extends AbstractConditionableCommand {
|
||||
targetMember = event.getMember();
|
||||
}
|
||||
File triggeredGifFile = imageGenerationService.getTriggeredGif(targetMember.getEffectiveAvatar().getUrl(imageSize));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(TRIGGERED_EMBED_TEMPLATE_KEY, new Object());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(TRIGGERED_EMBED_TEMPLATE_KEY, new Object(), event.getGuild().getIdLong());
|
||||
// template support does not support binary files
|
||||
AttachedFile file = AttachedFile
|
||||
.builder()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>image-generation</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>image-generation-int</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>image-generation</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation-int</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.5.43</version>
|
||||
<version>1.5.56</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public class MyWarnings extends AbstractConditionableCommand {
|
||||
.totalWarnCount(totalWarnCount)
|
||||
.currentWarnCount(currentWarnCount)
|
||||
.build();
|
||||
channelService.sendEmbedTemplateInTextChannelList(MY_WARNINGS_RESPONSE_EMBED_TEMPLATE, model, commandContext.getChannel());
|
||||
channelService.sendEmbedTemplateInMessageChannel(MY_WARNINGS_RESPONSE_EMBED_TEMPLATE, model, commandContext.getChannel());
|
||||
return CommandResult.fromIgnored();
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ public class UserNotes extends AbstractConditionableCommand {
|
||||
CompletableFuture<List<NoteEntryModel>> listCompletableFuture = userNotesConverter.fromNotes(userNotes);
|
||||
return listCompletableFuture.thenCompose(noteEntryModels -> {
|
||||
model.setUserNotes(noteEntryModels);
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(USER_NOTES_RESPONSE_TEMPLATE, model, commandContext.getChannel()))
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannel(USER_NOTES_RESPONSE_TEMPLATE, model, commandContext.getChannel()))
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class BanModerationActionModalListener implements ModalInteractionListene
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if(StringUtils.isBlank(tempReason)) {
|
||||
reason = templateService.renderSimpleTemplate(DEFAULT_BAN_REASON_TEMPLATE_KEY);
|
||||
reason = templateService.renderSimpleTemplate(DEFAULT_BAN_REASON_TEMPLATE_KEY, model.getServerId());
|
||||
} else {
|
||||
reason = tempReason;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user