Compare commits

...

113 Commits

Author SHA1 Message Date
Sheldan
08b3913b04 [maven-release-plugin] prepare release abstracto-application-1.4.9 2022-11-20 22:39:36 +01:00
Sheldan
7a7ec5654f [AB-25] changing member loading to be partitioned 2022-11-20 22:37:10 +01:00
Sheldan
74679c2ccc [maven-release-plugin] prepare for next development iteration 2022-11-20 19:53:42 +01:00
Sheldan
063581ba1a [maven-release-plugin] prepare release abstracto-application-1.4.8 2022-11-20 19:53:38 +01:00
Sheldan
5c7b018b2a [AB-25] refactoring experience collection to work instantly instead of delayed job
adding level up notification for experience
2022-11-20 19:49:34 +01:00
Sheldan
d315113395 [AB-76] adding evaluation job for suggestions 2022-11-11 00:06:16 +01:00
Sheldan
ea2f62b721 [AB-74] adding more information to output of transfer credits command 2022-11-09 22:53:36 +01:00
Sheldan
1a91275a2d [maven-release-plugin] prepare for next development iteration 2022-10-27 20:56:03 +02:00
Sheldan
e76b22ca59 [maven-release-plugin] prepare release abstracto-application-1.4.7 2022-10-27 20:55:58 +02:00
Sheldan
5a21f9642c [CCR] fixing order of execution for updating suggestion
using edit components instead of full message edit in message service bean
2022-10-27 20:49:36 +02:00
Sheldan
e3dd89b0ef [AB-75] adding thread reader command 2022-10-22 14:55:18 +02:00
Sheldan
4fe81c0ea2 [maven-release-plugin] prepare for next development iteration 2022-10-16 13:24:50 +02:00
Sheldan
ab55f5ee07 [maven-release-plugin] prepare release abstracto-application-1.4.6 2022-10-16 13:24:46 +02:00
Sheldan
92cec30898 [AB-xx] fixing version 2022-10-16 13:22:38 +02:00
Sheldan
3a40ccccda [maven-release-plugin] prepare release abstracto-application-1.4.5 2022-10-16 13:19:35 +02:00
Sheldan
e6802a0851 [AB-xx] fixing javadoc 2022-10-16 13:16:50 +02:00
Sheldan
ce90370b9c [maven-release-plugin] prepare for next development iteration 2022-10-16 12:04:14 +02:00
Sheldan
b21afce1ad [maven-release-plugin] prepare release abstracto-application-1.4.5 2022-10-16 12:04:10 +02:00
Sheldan
58fd11a561 [AB-xx] upgrade to JDA 5.0.0-alpha.21 2022-10-16 12:02:10 +02:00
Sheldan
3e38085a25 [AB-xx] upgrade to JDA 5.0.0-alpha.21 2022-10-16 11:54:23 +02:00
Sheldan
48f62f8bdf [AB-xx] make close log by default 2022-10-08 11:39:55 +02:00
Sheldan
ad92ccd181 [AB-71] adding cache flag to cached message 2022-10-06 00:34:22 +02:00
Sheldan
8ab0eaedda [AB-73] refactoring reminder notification model to not use entities 2022-10-06 00:10:32 +02:00
Sheldan
e2a7d3b9e8 [AB-72] adding joined reminders to list of reminders
refactored reminder display to not use entities
2022-10-06 00:01:48 +02:00
Sheldan
8c101793a3 [AB-8] fixing test 2022-09-18 16:00:38 +02:00
Sheldan
4e1f9e0018 [AB-8] upgrading to new JDA alpha version 19
cleaning up imports
2022-09-18 15:51:49 +02:00
Sheldan
102209aaca [maven-release-plugin] prepare for next development iteration 2022-09-02 15:48:29 +02:00
Sheldan
9a64da480b [maven-release-plugin] prepare release abstracto-application-1.4.4 2022-09-02 15:48:25 +02:00
Sheldan
11c36691ce [AB-xx] fixing reaction reports being stored when they should not be 2022-09-02 15:41:18 +02:00
Sheldan
337ef87e47 [maven-release-plugin] prepare for next development iteration 2022-08-28 23:30:52 +02:00
Sheldan
056a7fe297 [maven-release-plugin] prepare release abstracto-application-1.4.3 2022-08-28 23:30:47 +02:00
Sheldan
82383449c0 [AB-55] fixing custom command not considering feature flag
ignoring case for custom command
2022-08-28 23:24:08 +02:00
Sheldan
30655dbfef [AB-65] adding ability to join a reminder via button 2022-08-28 23:13:40 +02:00
Sheldan
a43725df39 [AB-69] adding additional info to userInfo command 2022-08-27 14:44:46 +02:00
Sheldan
9a0bff154b [AB-67] adding missing tracking trigger for infraction parameter 2022-08-25 00:41:37 +02:00
Sheldan
4d54b11400 [AB-68] adding message context menu and slash command for mock 2022-08-25 00:33:14 +02:00
Sheldan
9c621954c8 adding more logging for lash command exceptions 2022-08-19 15:56:23 +02:00
Sheldan
f24552fdf2 [maven-release-plugin] prepare for next development iteration 2022-08-01 23:02:25 +02:00
Sheldan
e643080516 [maven-release-plugin] prepare release abstracto-application-1.4.2 2022-08-01 23:02:20 +02:00
Sheldan
b747516881 fixing command alternatives being required
fixing filename for export emote stats
fixing reaction report message update
2022-08-01 22:59:48 +02:00
Sheldan
0a4238c9f5 [maven-release-plugin] prepare for next development iteration 2022-07-27 22:20:45 +02:00
Sheldan
99fe84914b [maven-release-plugin] prepare release abstracto-application-1.4.1 2022-07-27 22:20:41 +02:00
Sheldan
f9b85feeaf enabling auto complete for youtube command 2022-07-27 22:13:48 +02:00
Sheldan
51edb50eee fixing null handling for server channel message 2022-07-25 19:13:39 +02:00
Sheldan
43a78a4989 [AB-8] adding slash command and message context commands to metrics 2022-07-25 18:23:44 +02:00
Sheldan
e3e0ad98ba [maven-release-plugin] prepare for next development iteration 2022-07-23 10:33:34 +02:00
Sheldan
9c02be7299 [maven-release-plugin] prepare release abstracto-application-1.4.0 2022-07-23 10:33:31 +02:00
Sheldan
9954515db0 [AB-53] adding economy related commands
adding runtime exception to root command handling
adding simple custom command module
disabling slash command for show emote the utility is not given (the bot cannot show any emotes from servers its not in)
fixing post target setup not allowing threads
fixing post targets not supporting threads
fixing interactions not considering the actual amount of embeds
fixing some cases for events which are not in a guild
2022-07-23 10:20:41 +02:00
Sheldan
68cae74819 [AB-52] upgrading to alpha 12
adding anonymous reporting
reworking message context commands
refactoring interaction packages
adding post execution handling for message context commands and modals
reworking feature mode response
fixing setup using component ids
storing infraction parameters, for example mute duration, with every infraction
adding infractions for more moderation actions
creating general method to format a duration string
adding infractions command
reworking muting to use built-in functionality of discord
enabling chunking of members
removing manual unmuting feature mode
adding ability to update infractions with a command
implemented infraction listeners for ban and warn
refactored infraction notifications
storing log messages to the infraction for editing said log messages
2022-07-18 21:52:12 +02:00
Sheldan
1a1fde0800 [AB-11] fixing still considering bots when calculating the star amount
fixes #11
2022-06-21 00:15:47 +02:00
Sheldan
74cee39f1a [AB-12] fixing not ignoring ignored starboard posts in starstats
fixes #12
2022-06-20 23:50:39 +02:00
dependabot[bot]
5ad3e30cc1 Bump gson from 2.8.6 to 2.8.9 in /abstracto-application
Bumps [gson](https://github.com/google/gson) from 2.8.6 to 2.8.9.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.8.6...gson-parent-2.8.9)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-20 23:35:23 +02:00
Sheldan
c02bf4aa8e [AB-10] attempt to fix the race condition when creating a starboard post
fixes #10
2022-06-20 23:32:33 +02:00
Sheldan
c84a76b6a3 [maven-release-plugin] prepare for next development iteration 2022-06-20 00:20:23 +02:00
Sheldan
120df02dd0 [maven-release-plugin] prepare release abstracto-application-1.4.0.RC2 2022-06-20 00:20:18 +02:00
Sheldan
61f43f6bc9 [AB-365] javadoc fixes 2022-06-20 00:18:26 +02:00
Sheldan
982cbb82d7 [maven-release-plugin] prepare for next development iteration 2022-06-20 00:11:37 +02:00
Sheldan
b4627d1ab0 [maven-release-plugin] prepare release abstracto-application-1.4.0.RC1 2022-06-20 00:11:32 +02:00
Sheldan
1d6de3f1e8 [AB-365] introducing slash commands for a selection of commands
adding method for pinning a message
moving suggestion to correct deployment
2022-06-20 00:03:30 +02:00
Sheldan
1913bc930d [AB-xxx] adding issue templates 2022-05-29 23:51:26 +02:00
Sheldan
09450429dd [AB-358] upgrading to JDA 5
removal of jda-utils
adding message context commands
[AB-360] fixing confirmation buttons being triggered by somebody not the author
2022-05-17 00:27:30 +02:00
Sheldan
17470f9718 [maven-release-plugin] prepare for next development iteration 2022-05-15 17:38:21 +02:00
Sheldan
91a23f870c [maven-release-plugin] prepare release abstracto-application-1.3.13 2022-05-15 17:38:18 +02:00
Sheldan
b047d3eb49 [AB-xxx] adding another autoload macro for templates 2022-05-15 14:02:17 +02:00
Sheldan
db5b420f0a [maven-release-plugin] prepare for next development iteration 2022-04-07 22:27:00 +02:00
Sheldan
a7e60f6338 [maven-release-plugin] prepare release abstracto-application-1.3.12 2022-04-07 22:26:55 +02:00
Sheldan
eed90c1406 [AB-360] fixing warnings not being stored in case the message was not deliverable 2022-04-07 22:07:35 +02:00
Sheldan
78027ee980 [maven-release-plugin] prepare for next development iteration 2022-02-12 11:37:13 +01:00
Sheldan
e35071d8d5 [maven-release-plugin] prepare release abstracto-application-1.3.11 2022-02-12 11:37:08 +01:00
Sheldan
14865a32f2 [AB-xxx] fixing year 2022-02-12 11:34:41 +01:00
Sheldan
ae3c66384f [AB-xxx] not requiring async voice channel listeners
fixing duplicated error reporting for command received handler
2022-02-10 23:05:35 +01:00
Sheldan
986b65a1e4 [AB-347] adding support for multiple and generic attachments to modmail
fixing editing messages with multiple embeds
fixing message limit also bein imposed on pure embed count
2021-12-25 16:29:23 +01:00
Sheldan
cc898b27bb [AB-353] reducing chance of concurrent modification exception when registering a new metric on the fly 2021-12-25 10:53:55 +01:00
Sheldan
9ce07a1a4a [AB-352] removing conversion tests 2021-12-24 23:49:26 +01:00
Sheldan
ee01a3f07c [AB-352] adding caching to the loading of members for warnings/user notes/mutes. this becomes relevant as members which left the guild are not cached by jda, which means, we retry it again
improved models for templates to simplify the objects passed
2021-12-24 23:41:27 +01:00
Sheldan
9230a13218 [maven-release-plugin] prepare for next development iteration 2021-12-24 13:47:56 +01:00
Sheldan
c248351721 [maven-release-plugin] prepare release abstracto-application-1.3.10 2021-12-24 13:47:52 +01:00
Sheldan
b0376778fe [AB-xxx] adding utility function to change color of a role 2021-12-24 13:44:57 +01:00
Sheldan
7f5d17e4dc [AB-349] supporting multiple embeds in templating mechanism
fixing paginator without embeds
2021-12-08 16:26:11 +01:00
Sheldan
0e7ea25aef [AB-291] refactoring pagination to custom button pagination
adding mutes command
fixing edit message not considering components
reversing the origin comparison in a few button click listeners
fixing ordering of warnings and mutes from converter
2021-12-01 23:22:46 +01:00
Sheldan
f2aa7035aa [AB-307] enabling dependent features and including them into the setup wizard
this comes with the usual limitation, that dependent features must be referenced via importing
2021-11-28 13:19:17 +01:00
Sheldan
c10296251c [AB-327] adding a third state to the result of a system condition: Ignored, this means that the condition was not evaluated, and is neither true nor false, this is for example used when the feature the condition is about is disabled
adding server ID to has level condition parameters
2021-11-27 22:08:12 +01:00
Sheldan
15fb9d95a8 [AB-343] fixing link buttons not being properly supported in templates 2021-11-23 19:57:16 +01:00
Sheldan
79633d7a8e [AB-341] fixing unSuggest not working correctly in case there are votes on the suggestion 2021-11-20 11:44:07 +01:00
Sheldan
cef46737c5 [AB-170] adding emote stat command for single emote
fixing naming of fields in show tracked emotes
2021-10-27 00:25:10 +02:00
Sheldan
c7076795a2 [AB-340] fixing test 2021-10-26 13:59:48 +02:00
Sheldan
9e1527ccd1 [AB-340] adding timestamp support for serverInfo command 2021-10-26 13:53:13 +02:00
Sheldan
326d488059 [maven-release-plugin] prepare for next development iteration 2021-10-25 23:20:39 +02:00
Sheldan
a39b6695a6 [maven-release-plugin] prepare release abstracto-application-1.3.9 2021-10-25 23:20:31 +02:00
Sheldan
362d87778e [AB-339] repurposing the softban command for a ban command with deletion days 2021-10-25 01:11:32 +02:00
Sheldan
0514d355c7 [AB-167] adding warning created events and infraction counter
adding disabling of post targets
adding some logging for message sending failure consumer
2021-10-25 00:04:08 +02:00
Sheldan
8909e8ebe5 [AB-333] providing some dates as separate instants instead of relying on the member attributes
truncating date to day when displaying the date for export emote stats
fixing wrong message when confirming a command and adding missing exception handling
2021-10-14 01:31:52 +02:00
Sheldan
36ca9b11e4 [AB-334] adding vote result to suggestion reminder 2021-10-13 18:00:54 +02:00
Sheldan
4a66b7fc67 [AB-331] showing separate notifications for the decision on a suggestion 2021-09-28 22:20:11 +02:00
Sheldan
b2a94059e2 [AB-332] showing separate message in case there are no warnings 2021-09-28 22:05:51 +02:00
Sheldan
16e6caa1f0 [AB-196] adding confirmation requirement to various commands
refactoring command received handler in order to re-use when confirmation has been given
removing reaction from showSuggestion and remind command
adding log message for message deleted message, in case the member left
all commands from now on must work without the member field from the message, as this is not available when retrieving the message
2021-09-27 00:22:37 +02:00
Sheldan
da1a71ecdc [AB-319] splitting emotes into two separate fields (animated and static) for server info
adding emote display model
2021-09-10 00:41:15 +02:00
Sheldan
0646efe33d [AB-163] fixing printing all possible feature modes in case an unknown one was provided for enableMode/disableMode 2021-09-10 00:21:30 +02:00
Sheldan
db856f2647 [AB-xxx] improving documentation 2021-09-09 02:20:45 +02:00
Sheldan
1d85eb1e7e [AB-297] adding server names to invite deletion log (if available) 2021-09-08 23:04:35 +02:00
Sheldan
5e6999cd45 [AB-328] fixing case sensitivity of allowed invite links 2021-09-07 01:13:34 +02:00
Sheldan
9659a3487a [maven-release-plugin] prepare for next development iteration 2021-09-06 01:54:00 +02:00
Sheldan
6d27c487f2 [maven-release-plugin] prepare release abstracto-application-1.3.8 2021-09-06 01:53:55 +02:00
Sheldan
8ac3b327e4 [AB-268] adding button feature mode to suggestions which allows for hidden suggestion votes
moving gateway metric to separate service in case JDA is not ready yet
2021-09-06 01:39:27 +02:00
Sheldan
448332f24f [AB-318] adding a mention of the original message to link embed
updating JDA version
2021-09-04 16:30:16 +02:00
Sheldan
d7f889971d [AB-325] adding async command conditions - as this is required for some conditions
adding user parameter to immune user condition evaluation
2021-09-04 13:47:03 +02:00
Sheldan
69abff77fb [AB-xxx] fixing test 2021-08-21 16:05:01 +02:00
Sheldan
2c31fa1c1e [AB-xxx] not always creating a user instance in the experience listener
adding logging in case the warn decay notification fails
2021-08-21 15:50:11 +02:00
Sheldan
19a4858da1 [AB-323] improving logging when using whenComplete 2021-08-14 12:15:18 +02:00
Sheldan
3ed1f0c54a [AB-322] adding possibility to define a max age in days for messages to be eligible for stars 2021-08-14 09:45:25 +02:00
Sheldan
d01e46a9a6 [AB-xxx] fixing modmail sometimes failing to log messages 2021-08-14 08:02:04 +02:00
Sheldan
222250b795 [AB-321] changing caching policy
changing logging messages
2021-08-14 08:00:40 +02:00
Sheldan
9a87b75998 [maven-release-plugin] prepare for next development iteration 2021-08-09 23:52:49 +02:00
1113 changed files with 25450 additions and 11092 deletions

42
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: Bug Report
description: Found a bug that needs fixing?
body:
- type: checkboxes
attributes:
label: General Troubleshooting
description: You confirm to have made the following checks first.
options:
- label: I have checked for similar issues on the Issue-tracker.
required: true
- label: I have updated to the latest version
required: true
- label: I have checked the branches or the maintainers' PRs for upcoming bug fixes.
required: true
- type: textarea
attributes:
label: "Description"
description: "General information about the bug"
placeholder: "..."
validations:
required: true
- type: textarea
attributes:
label: "Steps to reproduce"
description: "What happened when the bug occurred?"
placeholder: "1. ..."
validations:
required: true
- type: textarea
attributes:
label: "Expected behaviour"
description: "What should happen?"
placeholder: "It should..."
validations:
required: true
- type: textarea
attributes:
label: "Actual behaviour"
description: "What did happen instead?"
placeholder: "It actually ..."
validations:
required: true

36
.github/ISSUE_TEMPLATE/feature.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: Feature request
description: Want some functionality added?
body:
- type: checkboxes
attributes:
label: General Information
description: You confirm to have made the following checks first.
options:
- label: I have checked for similar issues on the Issue-tracker.
required: true
- label: I have updated to the latest version
required: true
- label: I have checked the branches or the maintainers' PRs for upcoming features fixes.
required: true
- type: textarea
attributes:
label: "Description"
description: "General description of the feature"
placeholder: "..."
validations:
required: true
- type: textarea
attributes:
label: "Feature worth and general use"
description: "Why should this be in abstracto?"
placeholder: "..."
validations:
required: true
- type: textarea
attributes:
label: "Suggestions for implementation"
description: "Any ideas about what the feature should behave/look like? Commands?"
placeholder: "It should..."
validations:
required: false

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020 Sheldan
Copyright (c) 2022 Sheldan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -14,7 +14,7 @@ An example implementation of this bot can be seen [here](https://github.com/Shel
## Technologies
* [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper in the version 4.3.0_284
* [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper in the version 5.0.0-alpha.21
* [Spring boot](https://github.com/spring-projects/spring-boot) is used as a framework to create standalone application in Java with Java EE methods. (including Dependency injection and more)
* [Hibernate](https://github.com/hibernate/hibernate-orm) is used as a reference implementation of JPA.
* [Freemarker](https://github.com/apache/freemarker) is used as a templating engine. This is used to provide internationalization for user facing text and enable dynamic embed configuration.

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>anti-raid</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -7,8 +7,8 @@ import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageReceivedListener;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.ChannelType;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

View File

@@ -5,9 +5,7 @@ import dev.sheldan.abstracto.antiraid.model.MassPingNotificationModel;
import dev.sheldan.abstracto.core.models.ConditionContextInstance;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
import dev.sheldan.abstracto.core.service.ConditionService;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
@@ -34,6 +32,7 @@ public class MassPingServiceBean implements MassPingService {
private static final String LEVEL_CONDITION_NAME = "HAS_LEVEL";
private static final String LEVEL_CONDITION_USER_ID_PARAMETER = "userId";
private static final String LEVEL_CONDITION_LEVEL_PARAMETER = "level";
private static final String LEVEL_CONDITION_SERVER_PARAMETER = "serverId";
@Autowired
private ConfigService configService;
@@ -59,19 +58,22 @@ public class MassPingServiceBean implements MassPingService {
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private MemberService memberService;
@Override
public CompletableFuture<Void> processMessage(Message message) {
if(message.getMentionedMembers().size() > maxAllowedMentions) {
if(message.getMentions().getUsers().size() > maxAllowedMentions) {
Integer level = configService.getLongValueOrConfigDefault(MassPingService.MAX_AFFECTED_LEVEL_KEY, message.getGuild().getIdLong()).intValue();
boolean allowed = allowedToMassMention(message, level);
if(!allowed) {
return muteService.muteMemberWithoutContext(message.getMember())
return memberService.timeoutUserMaxDuration(message.getMember())
.thenAccept(unused -> self.sendMassPingMuteNotification(message))
.thenAccept(unused -> log.info("Muted member {} in server {} because of too many member mentions. (> {}).",
message.getMember().getIdLong(), message.getGuild().getIdLong(), maxAllowedMentions));
message.getAuthor().getIdLong(), message.getGuild().getIdLong(), maxAllowedMentions));
} else {
log.info("User {} in server {} is allowed to mass mention, because of level (or lack of level configuration).",
message.getMember().getIdLong(), message.getGuild().getIdLong());
message.getAuthor().getIdLong(), message.getGuild().getIdLong());
return CompletableFuture.completedFuture(null);
}
} else {
@@ -85,12 +87,14 @@ public class MassPingServiceBean implements MassPingService {
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(message.getMember());
parameters.put(LEVEL_CONDITION_USER_ID_PARAMETER, userInAServer.getUserInServerId());
parameters.put(LEVEL_CONDITION_LEVEL_PARAMETER, level);
parameters.put(LEVEL_CONDITION_SERVER_PARAMETER, message.getGuild().getIdLong());
ConditionContextInstance contextInstance = ConditionContextInstance
.builder()
.conditionName(LEVEL_CONDITION_NAME)
.parameters(parameters)
.build();
return conditionService.checkConditions(contextInstance);
SystemCondition.Result result = conditionService.checkConditions(contextInstance);
return SystemCondition.Result.consideredSuccessful(result);
}
@Transactional
@@ -99,7 +103,7 @@ public class MassPingServiceBean implements MassPingService {
MassPingNotificationModel model = MassPingNotificationModel
.builder()
.messageLink(message.getJumpUrl())
.mentionCount(message.getMentionedMembers().size())
.mentionCount(message.getMentions().getUsers().size())
.messageContent(message.getContentRaw())
.memberDisplay(MemberDisplay.fromMember(member))
.build();

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>anti-raid</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>assignable-roles</artifactId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -17,7 +17,7 @@ import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

View File

@@ -50,6 +50,7 @@ public class DeleteAssignableRolePlace extends AbstractConditionableCommand {
.templated(true)
.causesReaction(true)
.async(true)
.requiresConfirmation(true)
.supportsEmbedException(true)
.parameters(parameters)
.help(helpInfo)

View File

@@ -12,7 +12,7 @@ import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -48,8 +48,18 @@ public class MoveAssignableRolePlace extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter channel = Parameter.builder().name("channel").type(TextChannel.class).templated(true).build();
Parameter rolePostName = Parameter
.builder()
.name("name")
.type(String.class)
.templated(true)
.build();
Parameter channel = Parameter
.builder()
.name("channel")
.type(TextChannel.class)
.templated(true)
.build();
List<Parameter> parameters = Arrays.asList(rolePostName, channel);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()

View File

@@ -11,6 +11,7 @@ import dev.sheldan.abstracto.core.models.ConditionContextInstance;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.template.display.RoleDisplay;
import dev.sheldan.abstracto.core.service.ConditionService;
import dev.sheldan.abstracto.core.service.SystemCondition;
import net.dv8tion.jda.api.entities.Role;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -24,6 +25,7 @@ public class AssignableRoleMinimumLevelConditionImpl implements AssignableRoleCo
private final String conditionName = "HAS_LEVEL";
private final String userIdParameter = "userId";
private final String levelParameter = "level";
private final String serverParameter = "serverId";
@Autowired
private ConditionService conditionService;
@@ -34,13 +36,15 @@ public class AssignableRoleMinimumLevelConditionImpl implements AssignableRoleCo
Map<String, Object> parameters = new HashMap<>();
parameters.put(userIdParameter, aUserInAServer.getUserInServerId());
parameters.put(levelParameter, level);
parameters.put(serverParameter, aUserInAServer.getServerReference().getId());
ConditionContextInstance contextInstance = ConditionContextInstance
.builder()
.conditionName(conditionName)
.parameters(parameters)
.build();
return conditionService.checkConditions(contextInstance);
SystemCondition.Result result = conditionService.checkConditions(contextInstance);
return SystemCondition.Result.consideredSuccessful(result);
}
@Override

View File

@@ -19,10 +19,10 @@ import dev.sheldan.abstracto.assignableroles.service.management.AssignedRoleUser
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.ListenerPriority;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.listener.ButtonClickedListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.ButtonClickedListener;
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerResult;
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListener;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.listener.ButtonClickedListenerModel;
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerModel;
import dev.sheldan.abstracto.core.service.RoleService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
@@ -31,8 +31,8 @@ import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.events.interaction.ButtonClickEvent;
import net.dv8tion.jda.api.interactions.components.ButtonInteraction;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.interactions.components.buttons.ButtonInteraction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -74,7 +74,7 @@ public class AssignableRoleButtonClickedListener implements ButtonClickedListene
@Override
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
ButtonClickEvent event = model.getEvent();
ButtonInteractionEvent event = model.getEvent();
Member member = event.getMember();
if(event.getGuild() != null && member != null) {
AssignableRolePlacePayload payload = (AssignableRolePlacePayload) model.getDeserializedPayload();
@@ -149,6 +149,9 @@ public class AssignableRoleButtonClickedListener implements ButtonClickedListene
self.persistAssignableUser(member, payload, false);
});
}
}).exceptionally(throwable -> {
log.error("Failed to perform role change in assignable role place.", throwable);
return null;
});
} else {
assignableRoleService.removeAssignableRoleFromUser(roleById, member)
@@ -216,7 +219,7 @@ public class AssignableRoleButtonClickedListener implements ButtonClickedListene
@Override
public Boolean handlesEvent(ButtonClickedListenerModel model) {
return model.getOrigin().equals(AssignableRolePlaceServiceBean.ASSIGNABLE_ROLE_COMPONENT_ORIGIN);
return AssignableRolePlaceServiceBean.ASSIGNABLE_ROLE_COMPONENT_ORIGIN.equals(model.getOrigin()) && model.getEvent().isFromGuild();
}
@Override

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.assignableroles.model;
import dev.sheldan.abstracto.core.models.template.button.ButtonPayload;
import dev.sheldan.abstracto.core.interaction.button.ButtonPayload;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

View File

@@ -11,6 +11,9 @@ import dev.sheldan.abstracto.assignableroles.service.management.*;
import dev.sheldan.abstracto.core.command.exception.CommandParameterKeyValueWrongTypeException;
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
import dev.sheldan.abstracto.core.exception.EmoteNotUsableException;
import dev.sheldan.abstracto.core.interaction.ComponentPayloadManagementService;
import dev.sheldan.abstracto.core.interaction.ComponentPayloadService;
import dev.sheldan.abstracto.core.interaction.ComponentService;
import dev.sheldan.abstracto.core.models.FullEmote;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.ARole;
@@ -24,7 +27,9 @@ import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.interactions.components.ButtonStyle;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -114,13 +119,13 @@ public class AssignableRolePlaceServiceBean implements AssignableRolePlaceServic
// it only may be unusable if its a custom emote
log.debug("Using custom emote {} to create assignable role {} for assignable role place {} in server {}.",
fakeEmote.getEmote().getId(), role.getId(), placeId, serverId);
if (!emoteService.isEmoteUsableByBot(fakeEmote.getEmote()) && fakeEmote.getEmote().isAvailable()) {
if (!emoteService.isEmoteUsableByBot(fakeEmote.getEmote())) {
throw new EmoteNotUsableException(fakeEmote.getEmote());
}
}
Optional<TextChannel> channelOptional = channelService.getTextChannelFromServerOptional(server.getId(), assignableRolePlace.getChannel().getId());
Optional<GuildMessageChannel> channelOptional = channelService.getMessageChannelFromServerOptional(server.getId(), assignableRolePlace.getChannel().getId());
if (channelOptional.isPresent()) {
TextChannel textChannel = channelOptional.get();
GuildMessageChannel textChannel = channelOptional.get();
String buttonId = componentService.generateComponentId();
String emoteMarkdown = fakeEmote != null ? fakeEmote.getEmoteRepr() : null;
if (assignableRolePlace.getMessageId() != null) {
@@ -205,16 +210,15 @@ public class AssignableRolePlaceServiceBean implements AssignableRolePlaceServic
if (throwable != null) {
log.warn("Not able to delete old messages of assignable role place {} in server {}.", assignablePlaceId, serverId);
}
try {
self.createAssignableRolePlacePost(serverId, assignablePlaceId)
.thenAccept(unused1 -> postingFuture.complete(null))
.exceptionally(innerThrowable -> {
postingFuture.completeExceptionally(innerThrowable);
return null;
});
} catch (Exception ex) {
postingFuture.completeExceptionally(ex);
}
self.createAssignableRolePlacePost(serverId, assignablePlaceId)
.thenAccept(unused1 -> postingFuture.complete(null))
.exceptionally(innerThrowable -> {
postingFuture.completeExceptionally(innerThrowable);
return null;
});
}).exceptionally(throwable -> {
postingFuture.completeExceptionally(throwable);
return null;
});
return postingFuture;
}
@@ -224,7 +228,7 @@ public class AssignableRolePlaceServiceBean implements AssignableRolePlaceServic
AssignablePostMessage model = prepareAssignablePostMessageModel(place);
MessageToSend messageToSend = templateService.renderEmbedTemplate(ASSIGNABLE_ROLES_POST_TEMPLATE_KEY, model, place.getServer().getId());
Long channelId = place.getChannel().getId();
Optional<TextChannel> channelOptional = channelService.getTextChannelFromServerOptional(place.getServer().getId(), channelId);
Optional<GuildMessageChannel> channelOptional = channelService.getMessageChannelFromServerOptional(place.getServer().getId(), channelId);
if (channelOptional.isPresent()) {
log.info("Refreshing text for assignable role place {} in channel {} in post {}.", place.getId(), channelId, place.getMessageId());
return channelService.editEmbedMessageInAChannel(messageToSend.getEmbeds().get(0), channelOptional.get(), place.getMessageId()).thenCompose(message -> CompletableFuture.completedFuture(null));
@@ -361,17 +365,16 @@ public class AssignableRolePlaceServiceBean implements AssignableRolePlaceServic
if (throwable != null) {
log.warn("Not able to delete old messages of assignable role place {} in server {}.", assignablePlaceId, serverId);
}
try {
self.setupAssignableRolePlaceInChannel(serverId, assignablePlaceId, newChannel)
.thenAccept(unused1 -> self.updateAssignableRolePlaceChannel(name, newChannel))
.thenAccept(unused1 -> returnFuture.complete(null))
.exceptionally(innerThrowable -> {
returnFuture.completeExceptionally(innerThrowable);
return null;
});
} catch (Exception ex) {
returnFuture.completeExceptionally(ex);
}
self.setupAssignableRolePlaceInChannel(serverId, assignablePlaceId, newChannel)
.thenAccept(unused1 -> self.updateAssignableRolePlaceChannel(name, newChannel))
.thenAccept(unused1 -> returnFuture.complete(null))
.exceptionally(innerThrowable -> {
returnFuture.completeExceptionally(innerThrowable);
return null;
});
}).exceptionally(throwable -> {
returnFuture.completeExceptionally(throwable);
return null;
});
return returnFuture;
@@ -437,7 +440,7 @@ public class AssignableRolePlaceServiceBean implements AssignableRolePlaceServic
.build();
}
private CompletableFuture<Void> sendAssignablePostMessage(AssignableRolePlace place, TextChannel channel) {
private CompletableFuture<Void> sendAssignablePostMessage(AssignableRolePlace place, GuildMessageChannel channel) {
AssignablePostMessage model = prepareAssignablePostMessageModel(place);
MessageToSend messageToSend = templateService.renderEmbedTemplate(ASSIGNABLE_ROLES_POST_TEMPLATE_KEY, model, place.getServer().getId());
log.info("Sending message for assignable role place {}.", place.getId());
@@ -503,9 +506,9 @@ public class AssignableRolePlaceServiceBean implements AssignableRolePlaceServic
@Transactional
public CompletableFuture<Void> createAssignableRolePlacePost(Long serverId, Long assignablePlaceId) {
AssignableRolePlace assignableRolePlace = rolePlaceManagementService.findByPlaceId(assignablePlaceId);
Optional<TextChannel> channelOptional = channelService.getTextChannelFromServerOptional(serverId, assignableRolePlace.getChannel().getId());
Optional<GuildMessageChannel> channelOptional = channelService.getMessageChannelFromServerOptional(serverId, assignableRolePlace.getChannel().getId());
if (channelOptional.isPresent()) {
TextChannel channel = channelOptional.get();
GuildMessageChannel channel = channelOptional.get();
log.info("Sending assignable role place posts for place {} in channel {} in server {}.", assignableRolePlace.getId(), channel.getId(), serverId);
return sendAssignablePostMessage(assignableRolePlace, channel);
} else {

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>assignable-roles</artifactId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>assignable-roles-int</artifactId>

View File

@@ -9,7 +9,7 @@ import net.dv8tion.jda.api.entities.Role;
/**
* Exception thrown in case the {@link dev.sheldan.abstracto.assignableroles.model.database.AssignableRole} has already been
* defined for an {@link dev.sheldan.abstracto.assignableroles.model.database.AssignableRolePlace}. This is identified
* via the {@link net.dv8tion.jda.api.entities.Emote} which is used to react.
* via the emote which is used to react.
*/
public class AssignableRoleAlreadyDefinedException extends AbstractoRunTimeException implements Templatable {
private final AssignableRoleAlreadyDefinedExceptionModel model;

View File

@@ -6,7 +6,7 @@ import dev.sheldan.abstracto.core.templating.Templatable;
/**
* Exception thrown in case the {@link dev.sheldan.abstracto.assignableroles.model.database.AssignableRolePlace place}
* identified by {@link dev.sheldan.abstracto.assignableroles.model.database.AssignableRolePlace#key}
* identified by {@link dev.sheldan.abstracto.assignableroles.model.database.AssignableRolePlace} key
*/
public class AssignableRolePlaceAlreadyExistsException extends AbstractoRunTimeException implements Templatable {

View File

@@ -11,7 +11,7 @@ import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import java.util.concurrent.CompletableFuture;

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>custom-command</artifactId>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>custom-command-impl</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/liquibase.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>custom-command-int</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,18 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
<id>liquibase</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<outputDirectory>.</outputDirectory>
<directory>${project.basedir}/src/main/resources/migrations</directory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,73 @@
package dev.sheldan.abstracto.customcommand.command;
import dev.sheldan.abstracto.core.command.CommandAlternative;
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
import dev.sheldan.abstracto.core.command.service.CommandRegistry;
import dev.sheldan.abstracto.core.config.ListenerPriority;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.customcommand.config.CustomCommandFeatureConfig;
import dev.sheldan.abstracto.customcommand.model.command.CustomCommandResponseModel;
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
import dev.sheldan.abstracto.customcommand.service.management.CustomCommandManagementService;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@Component
public class CustomCommandAlternative implements CommandAlternative {
private static final String CUSTOM_COMMAND_RESPONSE = "custom_command_response";
@Autowired
private CommandRegistry commandRegistry;
@Autowired
private CustomCommandManagementService customCommandManagementService;
@Autowired
private ChannelService channelService;
@Autowired
private TemplateService templateService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private CustomCommandFeatureConfig customCommandFeatureConfig;
@Override
public boolean shouldExecute(UnParsedCommandParameter parameter, Guild guild) {
return featureFlagService.isFeatureEnabled(customCommandFeatureConfig, guild.getIdLong());
}
@Override
public void execute(UnParsedCommandParameter parameter, Message message) {
String contentStripped = message.getContentRaw();
List<String> parameters = Arrays.asList(contentStripped.split(" "));
String commandName = commandRegistry.getCommandName(parameters.get(0), message.getGuild().getIdLong());
Optional<CustomCommand> customCommandOptional = customCommandManagementService.getCustomCommandByName(commandName, message.getGuild().getIdLong());
customCommandOptional.ifPresent(customCommand -> {
CustomCommandResponseModel model = CustomCommandResponseModel
.builder()
.additionalText(customCommand.getAdditionalMessage())
.build();
MessageToSend messageToSend = templateService.renderEmbedTemplate(CUSTOM_COMMAND_RESPONSE, model, message.getGuild().getIdLong());
channelService.sendMessageToSendToChannel(messageToSend, message.getChannel());
});
}
@Override
public Integer getPriority() {
return ListenerPriority.MEDIUM;
}
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.customcommand.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:custom-command-config.properties")
public class CustomCommandConfig {
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.customcommand.repository;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface CustomCommandRepository extends JpaRepository<CustomCommand, Long> {
Optional<CustomCommand> getByNameIgnoreCaseAndServer(String name, AServer server);
}

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.customcommand.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
import dev.sheldan.abstracto.customcommand.repository.CustomCommandRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class CustomCommandManagementServiceBean implements CustomCommandManagementService {
@Autowired
private CustomCommandRepository repository;
@Autowired
private ServerManagementService serverManagementService;
@Override
public Optional<CustomCommand> getCustomCommandByName(String name, Long serverId) {
AServer server = serverManagementService.loadServer(serverId);
return repository.getByNameIgnoreCaseAndServer(name, server);
}
}

View File

@@ -0,0 +1,2 @@
abstracto.featureFlags.customCommand.featureName=customCommand
abstracto.featureFlags.customCommand.enabled=false

View File

@@ -0,0 +1,11 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="feature.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,14 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="custom_command-feature-insertion">
<insert tableName="feature">
<column name="key" value="customCommand"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,51 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="custom_command-table">
<createTable tableName="custom_command">
<column name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="custom_command_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="creator_user_in_server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="additional_message" type="VARCHAR(2048)">
<constraints nullable="false"/>
</column>
<column name="NAME" type="VARCHAR(64)">
<constraints nullable="false"/>
</column>
<column name="server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
<addUniqueConstraint columnNames="name"
constraintName="uc_custom_command_name"
disabled="false"
tableName="custom_command"/>
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="custom_command"
constraintName="fk_custom_command_server" deferrable="false" initiallyDeferred="false"
onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
<addForeignKeyConstraint baseColumnNames="creator_user_in_server_id" baseTableName="custom_command"
constraintName="fk_custom_command_creator" deferrable="false" initiallyDeferred="false"
onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS custom_command_update_trigger ON custom_command;
CREATE TRIGGER custom_command_update_trigger BEFORE UPDATE ON custom_command FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS custom_command_insert_trigger ON custom_command;
CREATE TRIGGER custom_command_insert_trigger BEFORE INSERT ON custom_command FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="custom_command.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="1.4.0/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>custom-command</artifactId>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>custom-command-int</artifactId>
</project>

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.customcommand.config;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import org.springframework.stereotype.Component;
@Component
public class CustomCommandFeatureConfig implements FeatureConfig {
@Override
public FeatureDefinition getFeature() {
return CustomCommandFeatureDefinition.CUSTOM_COMMAND;
}
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.customcommand.config;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import lombok.Getter;
@Getter
public enum CustomCommandFeatureDefinition implements FeatureDefinition {
CUSTOM_COMMAND("customCommand");
private String key;
CustomCommandFeatureDefinition(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.customcommand.model.command;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class CustomCommandResponseModel {
private String additionalText;
}

View File

@@ -0,0 +1,45 @@
package dev.sheldan.abstracto.customcommand.model.database;
import dev.sheldan.abstracto.core.models.database.*;
import lombok.*;
import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
@Entity
@Table(name = "custom_command")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode
public class CustomCommand implements Serializable {
@Id
@Column(name = "id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "additional_message")
private String additionalMessage;
@Column(name = "name")
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "server_id", nullable = false)
private AServer server;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "creator_user_in_server_id", nullable = false)
private AUserInAServer creator;
@Column(name = "created", nullable = false, insertable = false, updatable = false)
private Instant created;
@Column(name = "updated", insertable = false, updatable = false)
private Instant updated;
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.customcommand.service.management;
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
import java.util.Optional;
public interface CustomCommandManagementService {
Optional<CustomCommand> getCustomCommandByName(String name, Long serverId);
}

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>custom-command</artifactId>
<packaging>pom</packaging>
<modules>
<module>custom-command-int</module>
<module>custom-command-impl</module>
</modules>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core-int</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>dynamic-activity</artifactId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>dynamic-activity</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>entertainment</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,16 +4,20 @@ 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.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
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.service.ChannelService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.model.command.ChooseResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -25,30 +29,81 @@ import java.util.concurrent.CompletableFuture;
public class Choose extends AbstractConditionableCommand {
public static final String CHOOSE_RESPONSE_TEMPLATE_KEY = "choose_response";
private static final String CHOOSE_COMMAND = "choose";
private static final String TEXT_PARAMETER = "text";
private static final int CHOICES_SIZE = 5;
@Autowired
private EntertainmentService entertainmentService;
@Autowired
private ChannelService channelService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private InteractionService interactionService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<String> choices = (List) commandContext.getParameters().getParameters().get(0);
String choice = entertainmentService.takeChoice(choices, commandContext.getAuthor());
ChooseResponseModel responseModel = (ChooseResponseModel) ContextConverter.slimFromCommandContext(commandContext, ChooseResponseModel.class);
responseModel.setChosenValue(choice);
ChooseResponseModel responseModel = ChooseResponseModel
.builder()
.chosenValue(choice)
.build();
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(CHOOSE_RESPONSE_TEMPLATE_KEY, responseModel, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
List<String> choices = new ArrayList<>();
for (int i = 0; i < CHOICES_SIZE; i++) {
if(slashCommandParameterService.hasCommandOption(TEXT_PARAMETER + "_" + i, event)) {
String choice = slashCommandParameterService.getCommandOption(TEXT_PARAMETER + "_" + i, event, String.class);
choices.add(choice);
}
}
String choice = entertainmentService.takeChoice(choices, event.getMember());
ChooseResponseModel responseModel = ChooseResponseModel
.builder()
.chosenValue(choice)
.build();
return interactionService.replyEmbed(CHOOSE_RESPONSE_TEMPLATE_KEY, responseModel, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("text").type(String.class).templated(true).remainder(true).isListParam(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
Parameter textParameter = Parameter
.builder()
.name(TEXT_PARAMETER)
.type(String.class)
.templated(true)
.remainder(true)
.listSize(CHOICES_SIZE)
.isListParam(true)
.build();
parameters.add(textParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.UTILITY)
.commandName(CHOOSE_COMMAND)
.build();
return CommandConfiguration.builder()
.name("choose")
.name(CHOOSE_COMMAND)
.async(true)
.slashCommandConfig(slashCommandConfig)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.supportsEmbedException(true)

View File

@@ -4,17 +4,22 @@ 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.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
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.service.ChannelService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.model.command.EightBallResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -26,6 +31,8 @@ import java.util.concurrent.CompletableFuture;
public class EightBall extends AbstractConditionableCommand {
public static final String EIGHT_BALL_RESPONSE_TEMPLATE_KEY = "eight_ball_response";
public static final String BALL_COMMAND = "8Ball";
public static final String TEXT_PARAMETER = "text";
@Autowired
private EntertainmentService entertainmentService;
@@ -35,24 +42,65 @@ public class EightBall extends AbstractConditionableCommand {
@Autowired
private ChannelService channelService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private InteractionService interactionService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
String text = (String) commandContext.getParameters().getParameters().get(0);
String chosenKey = entertainmentService.getEightBallValue(text);
EightBallResponseModel responseModel = (EightBallResponseModel) ContextConverter.slimFromCommandContext(commandContext, EightBallResponseModel.class);
responseModel.setChosenKey(chosenKey);
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(EIGHT_BALL_RESPONSE_TEMPLATE_KEY, responseModel, commandContext.getChannel()))
MessageToSend messageToSend = getMessageToSend(text, commandContext.getGuild().getIdLong());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
String text = slashCommandParameterService.getCommandOption(TEXT_PARAMETER, event, String.class);
MessageToSend messageToSend = getMessageToSend(text, event.getGuild().getIdLong());
return interactionService.replyMessageToSend(messageToSend, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
private MessageToSend getMessageToSend(String text, Long serverId) {
String chosenKey = entertainmentService.getEightBallValue(text);
EightBallResponseModel responseModel = EightBallResponseModel
.builder()
.chosenKey(chosenKey)
.build();
return templateService.renderEmbedTemplate(EIGHT_BALL_RESPONSE_TEMPLATE_KEY, responseModel, serverId);
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("text").type(String.class).templated(true).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
Parameter textParameter = Parameter
.builder()
.name(TEXT_PARAMETER)
.type(String.class)
.templated(true)
.remainder(true)
.build();
parameters.add(textParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.UTILITY)
.commandName(BALL_COMMAND)
.build();
return CommandConfiguration.builder()
.name("8Ball")
.name(BALL_COMMAND)
.async(true)
.slashCommandConfig(slashCommandConfig)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.supportsEmbedException(true)

View File

@@ -4,16 +4,22 @@ 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.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
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.service.ChannelService;
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.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.model.command.LoveCalcResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -25,6 +31,9 @@ import java.util.concurrent.CompletableFuture;
public class LoveCalc extends AbstractConditionableCommand {
public static final String LOVE_CALC_RESPONSE_TEMPLATE_KEY = "loveCalc_response";
public static final String FIRST_SUBJECT_PARAMETER = "firstSubject";
public static final String SECOND_SUBJECT_PARAMETER = "secondSubject";
public static final String LOVE_CALC_COMMAND = "loveCalc";
@Autowired
private ChannelService channelService;
@@ -32,28 +41,77 @@ public class LoveCalc extends AbstractConditionableCommand {
@Autowired
private EntertainmentService entertainmentService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private InteractionService interactionService;
@Autowired
private TemplateService templateService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
String firstPart = (String) parameters.get(0);
String secondPart = (String) parameters.get(1);
Integer rolled = entertainmentService.getLoveCalcValue(firstPart, secondPart);
LoveCalcResponseModel model = (LoveCalcResponseModel) ContextConverter.slimFromCommandContext(commandContext, LoveCalcResponseModel.class);
model.setRolled(rolled);
model.setFirstPart(firstPart);
model.setSecondPart(secondPart);
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(LOVE_CALC_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
MessageToSend messageToSend = getMessageToSend(commandContext.getGuild().getIdLong(), firstPart, secondPart);
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
String firstPart = slashCommandParameterService.getCommandOption(FIRST_SUBJECT_PARAMETER, event, String.class);
String secondPart = slashCommandParameterService.getCommandOption(SECOND_SUBJECT_PARAMETER, event, String.class);
MessageToSend messageToSend = getMessageToSend(event.getGuild().getIdLong(), firstPart, secondPart);
return interactionService.replyMessageToSend(messageToSend, event.getInteraction())
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
private MessageToSend getMessageToSend(Long serverId, String firstPart, String secondPart) {
Integer rolled = entertainmentService.getLoveCalcValue(firstPart, secondPart);
LoveCalcResponseModel model = LoveCalcResponseModel
.builder()
.rolled(rolled)
.firstPart(firstPart)
.secondPart(secondPart)
.build();
return templateService.renderEmbedTemplate(LOVE_CALC_RESPONSE_TEMPLATE_KEY, model, serverId);
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("firstSubject").type(String.class).templated(true).build());
parameters.add(Parameter.builder().name("secondSubject").type(String.class).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
Parameter firstSubjectParameter = Parameter
.builder()
.name(FIRST_SUBJECT_PARAMETER)
.type(String.class)
.templated(true)
.build();
parameters.add(firstSubjectParameter);
Parameter secondSubjectParameter = Parameter
.builder()
.name(SECOND_SUBJECT_PARAMETER)
.type(String.class)
.templated(true)
.build();
parameters.add(secondSubjectParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.UTILITY)
.commandName(LOVE_CALC_COMMAND)
.build();
return CommandConfiguration.builder()
.name("loveCalc")
.name(LOVE_CALC_COMMAND)
.slashCommandConfig(slashCommandConfig)
.async(true)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)

View File

@@ -6,17 +6,21 @@ import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.command.handler.parameter.CombinedParameter;
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.service.ChannelService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.model.command.MockResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -29,12 +33,20 @@ import static dev.sheldan.abstracto.core.command.config.Parameter.ADDITIONAL_TYP
public class Mock extends AbstractConditionableCommand {
public static final String MOCK_RESPONSE_TEMPLATE_KEY = "mock_response";
public static final String MOCK_COMMAND = "mock";
public static final String MESSAGE_PARAMETER = "message";
@Autowired
private EntertainmentService entertainmentService;
@Autowired
private ChannelService channelService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private InteractionService interactionService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
Object givenParameter = commandContext.getParameters().getParameters().get(0);
@@ -48,26 +60,63 @@ public class Mock extends AbstractConditionableCommand {
messageText = givenParameter.toString();
}
String mockingText = entertainmentService.createMockText(messageText, commandContext.getAuthor(), mockedMember);
MockResponseModel model = (MockResponseModel) ContextConverter.slimFromCommandContext(commandContext, MockResponseModel.class);
model.setOriginalText(messageText);
model.setMockingText(mockingText);
MockResponseModel model = MockResponseModel
.builder()
.originalText(messageText)
.mockingText(mockingText)
.build();
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(MOCK_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
String text = slashCommandParameterService.getCommandOption(MESSAGE_PARAMETER, event, String.class);
String mockingText = entertainmentService.createMockText(text, event.getMember(), null);
MockResponseModel model = MockResponseModel
.builder()
.originalText(text)
.mockingText(mockingText)
.build();
return interactionService.replyEmbed(MOCK_RESPONSE_TEMPLATE_KEY, model, event.getInteraction())
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
Map<String, Object> parameterAlternatives = new HashMap<>();
parameterAlternatives.put(ADDITIONAL_TYPES_KEY, Arrays.asList(Message.class, String.class));
parameters.add(Parameter.builder().name("message").type(CombinedParameter.class).remainder(true)
.additionalInfo(parameterAlternatives).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
Parameter messageParameter = Parameter
.builder()
.name(MESSAGE_PARAMETER)
.type(CombinedParameter.class)
.remainder(true)
.additionalInfo(parameterAlternatives)
.templated(true)
.build();
parameters.add(messageParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.ENTERTAINMENT)
.commandName(MOCK_COMMAND)
.build();
return CommandConfiguration.builder()
.name("mock")
.name(MOCK_COMMAND)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.async(true)
.slashCommandConfig(slashCommandConfig)
.supportsEmbedException(true)
.parameters(parameters)
.help(helpInfo)

View File

@@ -4,19 +4,23 @@ 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.interaction.slash.SlashCommandConfig;
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.command.execution.ContextConverter;
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.service.ChannelService;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureConfig;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.model.command.RollResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -29,6 +33,9 @@ import java.util.concurrent.CompletableFuture;
public class Roll extends AbstractConditionableCommand {
public static final String ROLL_RESPONSE_TEMPLATE_KEY = "roll_response";
private static final String ROLL_COMMAND = "roll";
private static final String LOW_PARAMETER = "low";
private static final String HIGH_PARAMETER = "high";
@Autowired
private ChannelService channelService;
@@ -39,6 +46,12 @@ public class Roll extends AbstractConditionableCommand {
@Autowired
private ConfigService configService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private InteractionService interactionService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
@@ -52,20 +65,73 @@ public class Roll extends AbstractConditionableCommand {
}
Integer rolled = entertainmentService.calculateRollResult(low, high);
RollResponseModel model = (RollResponseModel) ContextConverter.slimFromCommandContext(commandContext, RollResponseModel.class);
model.setRolled(rolled);
RollResponseModel model = RollResponseModel
.builder()
.rolled(rolled)
.build();
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(ROLL_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
Integer low;
if(slashCommandParameterService.hasCommandOption(LOW_PARAMETER, event)) {
low = slashCommandParameterService.getCommandOption(LOW_PARAMETER, event, Integer.class);
} else {
low = 1;
}
Integer high;
if(slashCommandParameterService.hasCommandOption(HIGH_PARAMETER, event)) {
high = slashCommandParameterService.getCommandOption(HIGH_PARAMETER, event, Integer.class);
} else {
high = configService.getLongValueOrConfigDefault(EntertainmentFeatureConfig.ROLL_DEFAULT_HIGH_KEY, event.getGuild().getIdLong()).intValue();
}
Integer rolled = entertainmentService.calculateRollResult(low, high);
RollResponseModel model = RollResponseModel
.builder()
.rolled(rolled)
.build();
return interactionService.replyEmbed(ROLL_RESPONSE_TEMPLATE_KEY, model, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("high").type(Integer.class).templated(true).validators(Arrays.asList(MinIntegerValueValidator.min(2L))).optional(true).build());
parameters.add(Parameter.builder().name("low").type(Integer.class).templated(true).validators(Arrays.asList(MinIntegerValueValidator.min(0L))).optional(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
Parameter highParameter = Parameter
.builder()
.name(HIGH_PARAMETER)
.type(Integer.class)
.templated(true)
.validators(Arrays.asList(MinIntegerValueValidator.min(2L)))
.optional(true)
.build();
parameters.add(highParameter);
Parameter lowParameter = Parameter
.builder()
.name(LOW_PARAMETER)
.type(Integer.class)
.templated(true)
.validators(Arrays.asList(MinIntegerValueValidator.min(0L)))
.optional(true)
.build();
parameters.add(lowParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.UTILITY)
.commandName(ROLL_COMMAND)
.build();
return CommandConfiguration.builder()
.name("roll")
.name(ROLL_COMMAND)
.slashCommandConfig(slashCommandConfig)
.async(true)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)

View File

@@ -4,16 +4,19 @@ 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.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.model.command.RouletteResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -25,28 +28,57 @@ import java.util.concurrent.CompletableFuture;
public class Roulette extends AbstractConditionableCommand {
public static final String ROULETTE_RESPONSE_TEMPLATE_KEY = "roulette_response";
public static final String ROULETTE_COMMAND = "roulette";
@Autowired
private ChannelService channelService;
@Autowired
private EntertainmentService entertainmentService;
@Autowired
private InteractionService interactionService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
boolean rouletteResult = entertainmentService.executeRoulette(commandContext.getAuthor());
RouletteResponseModel responseModel = (RouletteResponseModel) ContextConverter.slimFromCommandContext(commandContext, RouletteResponseModel.class);
responseModel.setResult(rouletteResult);
RouletteResponseModel responseModel = RouletteResponseModel
.builder()
.result(rouletteResult)
.build();
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(ROULETTE_RESPONSE_TEMPLATE_KEY, responseModel, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
boolean rouletteResult = entertainmentService.executeRoulette(event.getMember());
RouletteResponseModel responseModel = RouletteResponseModel
.builder()
.result(rouletteResult)
.build();
return interactionService.replyEmbed(ROULETTE_RESPONSE_TEMPLATE_KEY, responseModel, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.UTILITY)
.commandName(ROULETTE_COMMAND)
.build();
return CommandConfiguration.builder()
.name("roulette")
.name(ROULETTE_COMMAND)
.async(true)
.slashCommandConfig(slashCommandConfig)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.supportsEmbedException(true)

View File

@@ -0,0 +1,102 @@
package dev.sheldan.abstracto.entertainment.command.economy;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ChannelService;
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.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.dto.CreditGambleResult;
import dev.sheldan.abstracto.entertainment.model.command.CreditGambleResultModel;
import dev.sheldan.abstracto.entertainment.service.EconomyService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class CreditGamble extends AbstractConditionableCommand {
private static final String CREDIT_GAMBLE_COMMAND = "creditGamble";
private static final String CREDIT_GAMBLE_RESPONSE = "creditGamble_response";
@Autowired
private EconomyService economyService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private InteractionService interactionService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
CreditGambleResult result = economyService.triggerCreditGamble(aUserInAServer);
CreditGambleResultModel model = CreditGambleResultModel.fromCreditGambleResult(result);
MessageToSend messageToSend = templateService.renderEmbedTemplate(CREDIT_GAMBLE_RESPONSE, model, commandContext.getGuild().getIdLong());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(event.getMember());
CreditGambleResult result = economyService.triggerCreditGamble(aUserInAServer);
CreditGambleResultModel model = CreditGambleResultModel.fromCreditGambleResult(result);
return interactionService.replyEmbed(CREDIT_GAMBLE_RESPONSE, model, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.ECONOMY)
.commandName("creditgamble")
.build();
return CommandConfiguration.builder()
.name(CREDIT_GAMBLE_COMMAND)
.slashCommandConfig(slashCommandConfig)
.async(true)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.supportsEmbedException(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return EntertainmentFeatureDefinition.ECONOMY;
}
}

View File

@@ -0,0 +1,179 @@
package dev.sheldan.abstracto.entertainment.command.economy;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.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.MemberService;
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.CompletableFutureList;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.model.command.CreditsLeaderboardEntry;
import dev.sheldan.abstracto.entertainment.model.command.CreditsLeaderboardResponseModel;
import dev.sheldan.abstracto.entertainment.service.EconomyService;
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;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@Component
public class CreditLeaderboard extends AbstractConditionableCommand {
private static final String CREDIT_LEADERBOARD_COMMAND_NAME = "creditLeaderboard";
private static final String CREDIT_LEADERBOARD_RESPONSE = "creditLeaderboard_response";
private static final String PAGE_PARAMETER = "page";
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private EconomyService economyService;
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private InteractionService interactionService;
@Autowired
private ChannelService channelService;
@Autowired
private TemplateService templateService;
@Autowired
private MemberService memberService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
AServer server = serverManagementService.loadServer(commandContext.getGuild());
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;
List<CreditsLeaderboardEntry> creditLeaderboard = economyService.getCreditLeaderboard(server, page);
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
CreditsLeaderboardEntry ownRank = economyService.getRankOfUser(aUserInAServer);
CreditsLeaderboardResponseModel model = CreditsLeaderboardResponseModel
.builder()
.entries(creditLeaderboard)
.ownRank(ownRank)
.build();
return enrichModelWithMembers(model, commandContext.getGuild().getIdLong())
.thenCompose(model1 -> {
MessageToSend message = templateService.renderEmbedTemplate(CREDIT_LEADERBOARD_RESPONSE, model1, commandContext.getGuild().getIdLong());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(message, commandContext.getChannel()));
})
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
event.deferReply().queue();
Integer page;
if(slashCommandParameterService.hasCommandOption(PAGE_PARAMETER, event)) {
page = slashCommandParameterService.getCommandOption(PAGE_PARAMETER, event, Integer.class);
} else {
page = 1;
}
AServer server = serverManagementService.loadServer(event.getGuild());
List<CreditsLeaderboardEntry> creditLeaderboard = economyService.getCreditLeaderboard(server, page);
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(event.getMember());
CreditsLeaderboardEntry ownRank = economyService.getRankOfUser(aUserInAServer);
CreditsLeaderboardResponseModel model = CreditsLeaderboardResponseModel
.builder()
.entries(creditLeaderboard)
.ownRank(ownRank)
.build();
return enrichModelWithMembers(model, event.getGuild().getIdLong())
.thenCompose(model1 -> FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(CREDIT_LEADERBOARD_RESPONSE, model1, event.getHook())))
.thenApply(unused -> CommandResult.fromSuccess());
}
private CompletableFuture<CreditsLeaderboardResponseModel> enrichModelWithMembers(CreditsLeaderboardResponseModel model, Long serverId) {
List<CompletableFuture<Member>> memberFutures = new ArrayList<>();
model.getEntries().forEach(creditsLeaderboardEntry -> {
memberFutures.add(memberService.getMemberInServerAsync(serverId, creditsLeaderboardEntry.getMemberDisplay().getUserId()));
});
memberFutures.add(memberService.getMemberInServerAsync(serverId, model.getOwnRank().getMemberDisplay().getUserId()));
CompletableFuture<CreditsLeaderboardResponseModel> modelFuture = new CompletableFuture<>();
CompletableFutureList<Member> futureList = new CompletableFutureList<>(memberFutures);
futureList.getMainFuture().whenComplete((unused, throwable) -> {
Map<Long, Member> memberMap = new HashMap<>();
futureList.getObjects().forEach(member -> memberMap.put(member.getIdLong(), member));
model.getEntries().forEach(creditsLeaderboardEntry -> {
if(memberMap.containsKey(creditsLeaderboardEntry.getMemberDisplay().getUserId())) {
creditsLeaderboardEntry.setMember(memberMap.get(creditsLeaderboardEntry.getMemberDisplay().getUserId()));
}
});
if(memberMap.containsKey(model.getOwnRank().getMemberDisplay().getUserId())) {
model.getOwnRank().setMember(memberMap.get(model.getOwnRank().getMemberDisplay().getUserId()));
}
modelFuture.complete(model);
});
return modelFuture;
}
@Override
public CommandConfiguration getConfiguration() {
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
Parameter pageParameter = Parameter
.builder()
.name(PAGE_PARAMETER)
.optional(true)
.templated(true)
.type(Integer.class)
.build();
List<Parameter> parameters = Arrays.asList(pageParameter);
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.ECONOMY)
.commandName("creditboard")
.build();
return CommandConfiguration.builder()
.name(CREDIT_LEADERBOARD_COMMAND_NAME)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.async(true)
.slashCommandConfig(slashCommandConfig)
.supportsEmbedException(true)
.causesReaction(false)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return EntertainmentFeatureDefinition.ECONOMY;
}
}

View File

@@ -0,0 +1,111 @@
package dev.sheldan.abstracto.entertainment.command.economy;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ChannelService;
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.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.model.command.CreditsLeaderboardEntry;
import dev.sheldan.abstracto.entertainment.model.command.CreditsModel;
import dev.sheldan.abstracto.entertainment.service.EconomyService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class Credits extends AbstractConditionableCommand {
private static final String CREDITS_COMMAND = "credits";
private static final String CREDITS_RESPONSE = "credits_response";
@Autowired
private EconomyService economyService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private InteractionService interactionService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
AUserInAServer targetUser = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
CreditsLeaderboardEntry rankEntry = economyService.getRankOfUser(targetUser);
rankEntry.setMember(commandContext.getAuthor());
CreditsModel model = CreditsModel
.builder()
.entry(rankEntry)
.build();
MessageToSend messageToSend = templateService.renderEmbedTemplate(CREDITS_RESPONSE, model, commandContext.getGuild().getIdLong());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
AUserInAServer targetUser = userInServerManagementService.loadOrCreateUser(event.getMember());
CreditsLeaderboardEntry rankEntry = economyService.getRankOfUser(targetUser);
rankEntry.setMember(event.getMember());
CreditsModel model = CreditsModel
.builder()
.entry(rankEntry)
.build();
return interactionService.replyEmbed(CREDITS_RESPONSE, model, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.ECONOMY)
.commandName("credits")
.build();
return CommandConfiguration.builder()
.name(CREDITS_COMMAND)
.slashCommandConfig(slashCommandConfig)
.async(true)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.supportsEmbedException(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return EntertainmentFeatureDefinition.ECONOMY;
}
}

View File

@@ -0,0 +1,124 @@
package dev.sheldan.abstracto.entertainment.command.economy;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ChannelService;
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.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.dto.PayDayResult;
import dev.sheldan.abstracto.entertainment.model.command.PayDayResponseModel;
import dev.sheldan.abstracto.entertainment.model.database.EconomyLeaderboardResult;
import dev.sheldan.abstracto.entertainment.service.EconomyService;
import dev.sheldan.abstracto.entertainment.service.management.EconomyUserManagementService;
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;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class Payday extends AbstractConditionableCommand {
private static final String PAYDAY_COMMAND_NAME = "payday";
@Autowired
private EconomyService economyService;
@Autowired
private EconomyUserManagementService economyUserManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private InteractionService interactionService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
private static final String PAYDAY_RESPONSE = "payday_response";
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
Member member = commandContext.getAuthor();
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
PayDayResult payDayResult = economyService.triggerPayDay(aUserInAServer);
EconomyLeaderboardResult rank = economyUserManagementService.getRankOfUserInServer(aUserInAServer);
PayDayResponseModel responseModel = PayDayResponseModel
.builder()
.currentCredits(payDayResult.getCurrentCredits())
.gainedCredits(payDayResult.getGainedCredits())
.leaderboardPosition(rank.getRank().longValue())
.build();
MessageToSend messageToSend = templateService.renderEmbedTemplate(PAYDAY_RESPONSE, responseModel, member.getGuild().getIdLong());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
Member member = event.getMember();
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
PayDayResult payDayResult = economyService.triggerPayDay(aUserInAServer);
EconomyLeaderboardResult rank = economyUserManagementService.getRankOfUserInServer(aUserInAServer);
PayDayResponseModel responseModel = PayDayResponseModel
.builder()
.currentCredits(payDayResult.getCurrentCredits())
.gainedCredits(payDayResult.getGainedCredits())
.leaderboardPosition(rank.getRank().longValue())
.build();
return interactionService.replyEmbed(PAYDAY_RESPONSE, responseModel, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.ECONOMY)
.commandName("payday")
.build();
return CommandConfiguration.builder()
.name(PAYDAY_COMMAND_NAME)
.slashCommandConfig(slashCommandConfig)
.async(true)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.supportsEmbedException(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return EntertainmentFeatureDefinition.ECONOMY;
}
}

View File

@@ -0,0 +1,124 @@
package dev.sheldan.abstracto.entertainment.command.economy;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.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.AUserInAServer;
import dev.sheldan.abstracto.core.service.ChannelService;
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.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.dto.SlotsResult;
import dev.sheldan.abstracto.entertainment.model.command.SlotsResponseModel;
import dev.sheldan.abstracto.entertainment.service.EconomyServiceBean;
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;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class Slots extends AbstractConditionableCommand {
private static final String SLOTS_COMMAND_NAME = "slots";
private static final String BID_PARAMETER = "bid";
private static final String SLOTS_RESPONSE = "slots_response";
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private InteractionService interactionService;
@Autowired
private EconomyServiceBean economyUserServiceBean;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
Integer bid = (Integer) commandContext.getParameters().getParameters().get(0);
Member member = commandContext.getAuthor();
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
SlotsResult slotsResult = economyUserServiceBean.triggerSlots(aUserInAServer, bid.longValue());
SlotsResponseModel responseModel = SlotsResponseModel.fromSlotsResult(slotsResult);
MessageToSend messageToSend = templateService.renderEmbedTemplate(SLOTS_RESPONSE, responseModel, member.getGuild().getIdLong());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
Long bid = slashCommandParameterService.getCommandOption(BID_PARAMETER, event, Integer.class).longValue();
Member member = event.getMember();
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
SlotsResult slotsResult = economyUserServiceBean.triggerSlots(aUserInAServer, bid);
SlotsResponseModel responseModel = SlotsResponseModel.fromSlotsResult(slotsResult);
return interactionService.replyEmbed(SLOTS_RESPONSE, responseModel, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
Parameter lowParameter = Parameter
.builder()
.name(BID_PARAMETER)
.type(Integer.class)
.templated(true)
.validators(Arrays.asList(MinIntegerValueValidator.min(0L)))
.build();
parameters.add(lowParameter);
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.ECONOMY)
.commandName("slots")
.build();
return CommandConfiguration.builder()
.name(SLOTS_COMMAND_NAME)
.slashCommandConfig(slashCommandConfig)
.async(true)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.supportsEmbedException(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return EntertainmentFeatureDefinition.ECONOMY;
}
}

View File

@@ -0,0 +1,138 @@
package dev.sheldan.abstracto.entertainment.command.economy;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.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.AUserInAServer;
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentSlashCommandNames;
import dev.sheldan.abstracto.entertainment.model.command.TransferCreditsModel;
import dev.sheldan.abstracto.entertainment.service.EconomyService;
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;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class TransferCredits extends AbstractConditionableCommand {
private static final String TRANSFER_CREDITS_COMMAND = "transferCredits";
private static final String TRANSFER_CREDITS_RESPONSE = "transferCredits_response";
private static final String MEMBER_PARAMETER = "targetMember";
private static final String AMOUNT_PARAMETER = "amount";
@Autowired
private InteractionService interactionService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private EconomyService economyService;
@Autowired
private ChannelService channelService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Member targetMember = (Member) parameters.get(0);
Integer amount = (Integer) parameters.get(1);
AUserInAServer targetUser = userInServerManagementService.loadOrCreateUser(targetMember);
AUserInAServer sourceUser = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
economyService.transferCredits(sourceUser, targetUser, amount.longValue());
TransferCreditsModel responseModel = TransferCreditsModel
.builder()
.sourceMember(MemberDisplay.fromMember(commandContext.getAuthor()))
.targetMember(MemberDisplay.fromMember(targetMember))
.credits(amount)
.build();
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(TRANSFER_CREDITS_RESPONSE, responseModel, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
Member targetMember = slashCommandParameterService.getCommandOption(MEMBER_PARAMETER, event, Member.class);
Integer amount = slashCommandParameterService.getCommandOption(AMOUNT_PARAMETER, event, Integer.class);
AUserInAServer targetUser = userInServerManagementService.loadOrCreateUser(targetMember);
AUserInAServer sourceUser = userInServerManagementService.loadOrCreateUser(event.getMember());
TransferCreditsModel responseModel = TransferCreditsModel
.builder()
.sourceMember(MemberDisplay.fromMember(event.getMember()))
.targetMember(MemberDisplay.fromMember(targetMember))
.credits(amount)
.build();
economyService.transferCredits(sourceUser, targetUser, amount.longValue());
return interactionService.replyEmbed(TRANSFER_CREDITS_RESPONSE, responseModel, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
Parameter memberParameter = Parameter
.builder()
.name(MEMBER_PARAMETER)
.templated(true)
.type(Member.class)
.optional(true)
.build();
Parameter amountParameter = Parameter
.builder()
.name(AMOUNT_PARAMETER)
.templated(true)
.type(Integer.class)
.optional(true)
.build();
List<Parameter> parameters = Arrays.asList(memberParameter, amountParameter);
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(EntertainmentSlashCommandNames.ECONOMY)
.commandName("transfer")
.build();
return CommandConfiguration.builder()
.name(TRANSFER_CREDITS_COMMAND)
.slashCommandConfig(slashCommandConfig)
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.supportsEmbedException(true)
.parameters(parameters)
.causesReaction(false)
.async(true)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return EntertainmentFeatureDefinition.ECONOMY;
}
}

View File

@@ -0,0 +1,64 @@
package dev.sheldan.abstracto.entertainment.listener.interaction;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.MessageContextConfig;
import dev.sheldan.abstracto.core.interaction.context.ContextCommandService;
import dev.sheldan.abstracto.core.interaction.context.message.listener.MessageContextCommandListener;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.models.listener.interaction.MessageContextInteractionModel;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.model.command.MockResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import static dev.sheldan.abstracto.entertainment.command.Mock.MOCK_RESPONSE_TEMPLATE_KEY;
@Component
public class MockMessageContextCommandListener implements MessageContextCommandListener {
@Autowired
private ContextCommandService contextCommandService;
@Autowired
private EntertainmentService entertainmentService;
@Autowired
private InteractionService interactionService;
@Override
public DefaultListenerResult execute(MessageContextInteractionModel eventModel) {
Message targetMessage = eventModel.getEvent().getTarget();
String mockText = entertainmentService.createMockText(targetMessage.getContentRaw(), eventModel.getEvent().getMember(), targetMessage.getMember());
MockResponseModel model = MockResponseModel
.builder()
.originalText(targetMessage.getContentRaw())
.mockingText(mockText)
.build();
interactionService.replyEmbed(MOCK_RESPONSE_TEMPLATE_KEY, model, eventModel.getEvent());
return DefaultListenerResult.PROCESSED;
}
@Override
public FeatureDefinition getFeature() {
return EntertainmentFeatureDefinition.ENTERTAINMENT;
}
@Override
public MessageContextConfig getConfig() {
return MessageContextConfig
.builder()
.isTemplated(true)
.name("mock")
.templateKey("mock_message_context_menu_label")
.build();
}
@Override
public Boolean handlesEvent(MessageContextInteractionModel model) {
return contextCommandService.matchesGuildContextName(model, getConfig(), model.getServerId());
}
}

View File

@@ -0,0 +1,41 @@
package dev.sheldan.abstracto.entertainment.repository;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.entertainment.model.database.EconomyLeaderboardResult;
import dev.sheldan.abstracto.entertainment.model.database.EconomyUser;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface EconomyUserRepository extends JpaRepository<EconomyUser, Long> {
Optional<EconomyUser> findByUser(AUserInAServer aUserInAServer);
@Query(value = "WITH economy_user_ranked AS" +
"( " +
" SELECT eu.id, eu.credits, uis.user_id, ROW_NUMBER() OVER ( ORDER BY credits DESC ) " +
" FROM economy_user eu INNER JOIN user_in_server uis ON eu.id = uis.user_in_server_id INNER JOIN server s ON s.id = uis.server_id WHERE s.id = :serverId" +
") " +
"SELECT rank.id as \"id\", rank.user_id as \"userid\", rank.credits as \"credits\", rank.row_number as \"rank\" " +
"FROM economy_user_ranked rank " +
"WHERE rank.id = :userInServerId", nativeQuery = true)
EconomyLeaderboardResult getRankOfUserInServer(@Param("userInServerId") Long id, @Param("serverId") Long serverId);
@Query(value = "WITH economy_user_ranked AS" +
"( " +
" SELECT eu.id, eu.credits, uis.user_id, ROW_NUMBER() OVER ( ORDER BY credits DESC ) " +
" FROM economy_user eu INNER JOIN user_in_server uis ON eu.id = uis.user_in_server_id INNER JOIN server s ON s.id = uis.server_id WHERE s.id = :serverId" +
") " +
"SELECT rank.id as \"id\", rank.user_id as \"userid\", rank.credits as \"credits\", rank.row_number as \"rank\" " +
"FROM economy_user_ranked rank ", nativeQuery = true)
List<EconomyLeaderboardResult> getRanksInServer(@Param("serverId") Long serverId);
List<EconomyUser> findTop10ByServerOrderByCreditsDesc(AServer server, Pageable pageable);
List<EconomyUser> findByServerOrderByCredits(AServer server);
}

View File

@@ -0,0 +1,353 @@
package dev.sheldan.abstracto.entertainment.service;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.entertainment.config.EconomyFeatureConfig;
import dev.sheldan.abstracto.entertainment.dto.CreditGambleResult;
import dev.sheldan.abstracto.entertainment.dto.PayDayResult;
import dev.sheldan.abstracto.entertainment.dto.SlotsResult;
import dev.sheldan.abstracto.entertainment.exception.NotEnoughCreditsException;
import dev.sheldan.abstracto.entertainment.exception.PayDayCooldownException;
import dev.sheldan.abstracto.entertainment.exception.SlotsCooldownException;
import dev.sheldan.abstracto.entertainment.model.command.CreditsLeaderboardEntry;
import dev.sheldan.abstracto.entertainment.model.database.EconomyLeaderboardResult;
import dev.sheldan.abstracto.entertainment.model.database.EconomyUser;
import dev.sheldan.abstracto.entertainment.service.management.EconomyUserManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.security.SecureRandom;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;
import static dev.sheldan.abstracto.entertainment.config.EconomyFeatureConfig.PAYDAY_COOLDOWN_CONFIG_KEY;
import static dev.sheldan.abstracto.entertainment.config.EconomyFeatureConfig.SLOTS_COOLDOWN_CONFIG_KEY;
@Component
public class EconomyServiceBean implements EconomyService {
@Autowired
private ConfigService configService;
@Autowired
private EconomyUserManagementService economyUserManagementService;
@Autowired
private SecureRandom secureRandom;
private static final String CREDIT_GAMBLE_STORAGE = "creditGambleJackpot";
private static final String SNOWFLAKE = "";
private static final String CHERRY = "🍒";
private static final String COOKIE = "🍪";
private static final String TWO = "2";
private static final String CLOVER = "🍀";
private static final String MUSHROOM = "🍄";
private static final String SUNFLOWER = "🌻";
private static final String HEART = "";
private static final String SIX = "6";
private static final String CYCLONE = "🌀";
private static final String OUTCOME_KEY_THREE_CHERRIES = "threecherries";
private static final String OUTCOME_KEY_NOTHING = "nothing";
private static final String OUTCOME_KEY_JACKPOT = "jackpot";
private static final String OUTCOME_KEY_CLOVERS = "clovers";
private static final String OUTCOME_KEY_TWO_CHERRIES = "twocherries";
private static final String OUTCOME_KEY_TWOSIX = "twosix";
private static final String OUTCOME_KEY_3SYMBOLS = "threesymbols";
private static final String OUTCOME_KEY_2SYMBOLS = "twosymbols";
private static final List<String> POSSIBLE_SLOTS = Arrays.asList(SNOWFLAKE, CHERRY, COOKIE, TWO, CLOVER, MUSHROOM, SUNFLOWER, HEART, SIX, CYCLONE);
private static final List<SlotMapping> WINNING_PATTERNS = Arrays.asList(
new SlotMapping(Arrays.asList(CHERRY, CHERRY, CHERRY), 20, OUTCOME_KEY_THREE_CHERRIES),
new SlotMapping(Arrays.asList(CLOVER, CLOVER, CLOVER), 25, OUTCOME_KEY_CLOVERS),
new SlotMapping(Arrays.asList(TWO, TWO, SIX), 50, OUTCOME_KEY_JACKPOT),
new SlotMapping(Arrays.asList(TWO, SIX), 4, OUTCOME_KEY_TWOSIX),
new SlotMapping(Arrays.asList(CHERRY, CHERRY), 3, OUTCOME_KEY_TWO_CHERRIES)
);
private static final Integer TRIPLE_FACTOR = 10;
private static final Integer DOUBLE_FACTOR = 2;
@Override
public boolean canTriggerPayDay(AUserInAServer aUserInAServer) {
Optional<EconomyUser> userOptional = economyUserManagementService.getUser(aUserInAServer);
return userOptional.map(this::canTriggerPayDay).orElse(true);
}
@Override
public boolean canTriggerSlots(AUserInAServer aUserInAServer) {
Optional<EconomyUser> userOptional = economyUserManagementService.getUser(aUserInAServer);
return userOptional.map(this::canTriggerSlots).orElse(true);
}
@Override
public boolean canTriggerPayDay(EconomyUser economyUser) {
return slotsTriggerIn(economyUser).isNegative();
}
@Override
public boolean canTriggerSlots(EconomyUser economyUser) {
return payDayTriggerIn(economyUser).isNegative();
}
@Override
public Duration payDayTriggerIn(EconomyUser economyUser) {
Long cooldownSeconds = configService.getLongValueOrConfigDefault(PAYDAY_COOLDOWN_CONFIG_KEY, economyUser.getServer().getId());
Instant minTimeStamp = Instant.now().minus(cooldownSeconds, ChronoUnit.SECONDS);
return Duration.between(economyUser.getLastPayDay(), minTimeStamp);
}
@Override
public Duration slotsTriggerIn(EconomyUser economyUser) {
Long cooldownSeconds = configService.getLongValueOrConfigDefault(SLOTS_COOLDOWN_CONFIG_KEY, economyUser.getServer().getId());
Instant minTimeStamp = Instant.now().minus(cooldownSeconds, ChronoUnit.SECONDS);
return Duration.between(economyUser.getLastSlots(), minTimeStamp);
}
@Override
public EconomyUser addCredits(AUserInAServer aUserInAServer, Long credits) {
Optional<EconomyUser> existingUserOptional = economyUserManagementService.getUser(aUserInAServer);
if (existingUserOptional.isPresent()) {
EconomyUser existingUser = existingUserOptional.get();
addCredits(existingUser, credits);
return existingUser;
} else {
EconomyUser user = economyUserManagementService.createUser(aUserInAServer);
user.setCredits(credits);
return user;
}
}
@Override
public void addCredits(EconomyUser economyUser, Long credits) {
economyUser.setCredits(economyUser.getCredits() + credits);
}
@Override
public void addPayDayCredits(AUserInAServer aUserInAServer) {
Long creditsToAdd = configService.getLongValueOrConfigDefault(EconomyFeatureConfig.PAYDAY_CREDITS_CONFIG_KEY,
aUserInAServer.getServerReference().getId());
addCredits(aUserInAServer, creditsToAdd);
}
@Override
public PayDayResult triggerPayDay(AUserInAServer aUserInAServer) {
Long creditsToAdd = configService.getLongValueOrConfigDefault(EconomyFeatureConfig.PAYDAY_CREDITS_CONFIG_KEY,
aUserInAServer.getServerReference().getId());
EconomyUser economyUser = addCredits(aUserInAServer, creditsToAdd);
Duration durationForPayday = payDayTriggerIn(economyUser);
if (durationForPayday.isNegative()) {
throw new PayDayCooldownException(durationForPayday.abs());
}
economyUser.setLastPayDay(Instant.now());
return PayDayResult
.builder()
.currentCredits(economyUser.getCredits())
.gainedCredits(creditsToAdd)
.build();
}
@Override
public SlotsResult triggerSlots(AUserInAServer aUserInAServer, Long bid) {
Optional<EconomyUser> userOptional = economyUserManagementService.getUser(aUserInAServer);
if(!userOptional.isPresent()) {
throw new NotEnoughCreditsException();
}
EconomyUser user = userOptional.get();
Long oldCredits = user.getCredits();
if(user.getCredits() < bid) {
throw new NotEnoughCreditsException();
}
Duration durationForSlots = slotsTriggerIn(user);
if (durationForSlots.isNegative()) {
throw new SlotsCooldownException(durationForSlots.abs());
}
SlotGame slotGame = playSlots();
Integer factor = slotGame.getResultFactor();
Long creditChange = bid * factor;
addCredits(user, -bid);
addCredits(user, creditChange);
user.setLastSlots(Instant.now());
return SlotsResult
.builder()
.bid(bid)
.factor(factor.longValue())
.newCredits(user.getCredits())
.outComeKey(slotGame.getOutcome())
.oldCredits(oldCredits)
.winnings(creditChange)
.rows(slotGame.getRows())
.build();
}
@Override
public SlotGame playSlots() {
List<String> result = new ArrayList<>();
for (int i = 0; i < 3; i++) {
List<String> tempSlots = new ArrayList<>(POSSIBLE_SLOTS);
Collections.rotate(tempSlots, secureRandom.nextInt(2000) - 1000);
result.add(tempSlots.get(0));
result.add(tempSlots.get(1));
result.add(tempSlots.get(2));
}
List<List<String>> rows = new ArrayList<>();
rows.add(Arrays.asList(result.get(0), result.get(3), result.get(6)));
List<String> decidingRow = Arrays.asList(result.get(1), result.get(4), result.get(7));
rows.add(decidingRow);
rows.add(Arrays.asList(result.get(2), result.get(5), result.get(8)));
String decidingRowAsString = String.join("", decidingRow);
SlotMapping specialPattern = getSpecialPattern(decidingRowAsString);
Integer factor = 0;
String outcomeKey = OUTCOME_KEY_NOTHING;
if(specialPattern != null){
factor = specialPattern.factor;
outcomeKey = specialPattern.outcome;
} else {
Set<String> uniqueChars = new HashSet<>(decidingRow);
if(uniqueChars.size() == 1) {
factor = TRIPLE_FACTOR;
outcomeKey = OUTCOME_KEY_3SYMBOLS;
} else if(decidingRow.get(0).equals(decidingRow.get(1)) || decidingRow.get(1).equals(decidingRow.get(2)) ) {
factor = DOUBLE_FACTOR;
outcomeKey = OUTCOME_KEY_2SYMBOLS;
}
}
return SlotGame
.builder()
.rows(rows)
.outcome(outcomeKey)
.resultFactor(factor)
.build();
}
@Override
public List<CreditsLeaderboardEntry> getCreditLeaderboard(AServer server, Integer page) {
if(page <= 0) {
throw new IllegalArgumentException("Page needs to be >= 1");
}
page--;
int pageSize = 10;
List<CreditsLeaderboardEntry> entries = new ArrayList<>();
List<EconomyUser> ranks = economyUserManagementService.getRanksInServer(server, page, pageSize);
int pageOffset = page * pageSize;
for (int i = 0; i < ranks.size(); i++) {
EconomyUser rank = ranks.get(i);
CreditsLeaderboardEntry entry = CreditsLeaderboardEntry
.builder()
.credits(rank.getCredits())
.memberDisplay(MemberDisplay.fromAUserInAServer(rank.getUser()))
.rank(pageOffset + i + 1)
.build();
entries.add(entry);
}
return entries;
}
@Override
public CreditsLeaderboardEntry getRankOfUser(AUserInAServer aUserInAServer) {
EconomyLeaderboardResult rank = economyUserManagementService.getRankOfUserInServer(aUserInAServer);
if(rank != null) {
return CreditsLeaderboardEntry
.builder()
.credits(rank.getCredits())
.memberDisplay(MemberDisplay.fromAUserInAServer(aUserInAServer))
.rank(rank.getRank())
.build();
} else {
return CreditsLeaderboardEntry
.builder()
.credits(0L)
.memberDisplay(MemberDisplay.fromAUserInAServer(aUserInAServer))
.rank(-1)
.build();
}
}
@Override
public void transferCredits(AUserInAServer source, AUserInAServer target, Long amount) {
Optional<EconomyUser> userOptional = economyUserManagementService.getUser(source);
if(!userOptional.isPresent()) {
throw new NotEnoughCreditsException();
}
EconomyUser user = userOptional.get();
if(user.getCredits() < amount) {
throw new NotEnoughCreditsException();
}
addCredits(target, amount);
addCredits(user, -amount);
}
@Override
public CreditGambleResult triggerCreditGamble(AUserInAServer aUserInAServer) {
// TODO move these constants to system configs
Optional<EconomyUser> userOptional = economyUserManagementService.getUser(aUserInAServer);
if(!userOptional.isPresent()) {
throw new NotEnoughCreditsException();
}
EconomyUser user = userOptional.get();
Long bid = 25L;
if(user.getCredits() < bid) {
throw new NotEnoughCreditsException();
}
Long serverId = aUserInAServer.getServerReference().getId();
Long currentJackpot = configService.getLongValueOrConfigDefault(CREDIT_GAMBLE_STORAGE, serverId);
List<Integer> diceRoles = new ArrayList<>();
diceRoles.add(creditGambleDiceResult());
diceRoles.add(creditGambleDiceResult());
diceRoles.add(creditGambleDiceResult());
diceRoles.add(creditGambleDiceResult());
Long toJackpot = 20L;
Integer uniqueNumbers = new HashSet<>(diceRoles).size();
Boolean won = uniqueNumbers == 1;
CreditGambleResult result = CreditGambleResult
.builder()
.uniqueNumbers(uniqueNumbers)
.won(won)
.bid(bid)
.toBank(bid - toJackpot)
.toJackpot(toJackpot)
.rolls(diceRoles)
.currentJackpot(currentJackpot + toJackpot)
.build();
if(won) {
addCredits(user, currentJackpot);
currentJackpot = 1000L;
} else {
currentJackpot += toJackpot;
addCredits(user, -bid);
}
configService.setOrCreateConfigValue(CREDIT_GAMBLE_STORAGE, serverId, currentJackpot.toString());
return result;
}
private Integer creditGambleDiceResult() {
return secureRandom.nextInt(7) + 1;
}
private SlotMapping getSpecialPattern(String row){
return WINNING_PATTERNS
.stream()
.filter(slotMapping -> row.contains(slotMapping.processedMapping))
.findFirst()
.orElse(null);
}
private static class SlotMapping {
private Integer factor;
private String processedMapping;
private String outcome;
public SlotMapping(List<String> slots, Integer factor, String outcome) {
this.factor = factor;
this.processedMapping = String.join("", slots);
this.outcome = outcome;
}
}
}

View File

@@ -0,0 +1,51 @@
package dev.sheldan.abstracto.entertainment.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.entertainment.model.database.EconomyLeaderboardResult;
import dev.sheldan.abstracto.entertainment.model.database.EconomyUser;
import dev.sheldan.abstracto.entertainment.repository.EconomyUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Optional;
@Component
public class EconomyUserManagementServiceBean implements EconomyUserManagementService {
@Autowired
private EconomyUserRepository repository;
@Override
public EconomyUser createUser(AUserInAServer aUserInAServer) {
EconomyUser user = EconomyUser
.builder()
.id(aUserInAServer.getUserInServerId())
.server(aUserInAServer.getServerReference())
.lastPayDay(Instant.now().minus(1, ChronoUnit.DAYS))
.lastSlots(Instant.now().minus(1, ChronoUnit.DAYS))
.credits(0L)
.user(aUserInAServer)
.build();
return repository.save(user);
}
@Override
public Optional<EconomyUser> getUser(AUserInAServer aUserInAServer) {
return repository.findByUser(aUserInAServer);
}
@Override
public EconomyLeaderboardResult getRankOfUserInServer(AUserInAServer aUserInAServer) {
return repository.getRankOfUserInServer(aUserInAServer.getUserInServerId(), aUserInAServer.getServerReference().getId());
}
@Override
public List<EconomyUser> getRanksInServer(AServer server, Integer page, Integer pagesize) {
return repository.findTop10ByServerOrderByCreditsDesc(server, PageRequest.of(page, pagesize));
}
}

View File

@@ -6,3 +6,20 @@ abstracto.systemConfigs.rollDefaultHigh.longValue=6
abstracto.featureFlags.entertainment.featureName=entertainment
abstracto.featureFlags.entertainment.enabled=false
abstracto.systemConfigs.paydayCredits.name=paydayCredits
abstracto.systemConfigs.paydayCredits.longValue=120
# maybe replace this by command cooldowns which are globally on the server, instead of only channel group based
abstracto.systemConfigs.paydayCooldown.name=paydayCooldown
abstracto.systemConfigs.paydayCooldown.longValue=300
abstracto.systemConfigs.slotsCooldown.name=slotsCooldown
abstracto.systemConfigs.slotsCooldown.longValue=30
abstracto.featureFlags.economy.featureName=economy
abstracto.featureFlags.economy.enabled=false
# for now this is fine
abstracto.systemConfigs.creditGambleJackpot.name=creditGambleJackpot
abstracto.systemConfigs.creditGambleJackpot.longValue=1000

View File

@@ -0,0 +1,11 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,45 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<property name="entertainmentModule" value="(SELECT id FROM module WHERE name = 'entertainment')"/>
<property name="economyFeature" value="(SELECT id FROM feature WHERE key = 'economy')"/>
<changeSet author="Sheldan" id="economy-command">
<insert tableName="command">
<column name="name" value="payday"/>
<column name="module_id" valueComputed="${entertainmentModule}"/>
<column name="feature_id" valueComputed="${economyFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="slots"/>
<column name="module_id" valueComputed="${entertainmentModule}"/>
<column name="feature_id" valueComputed="${economyFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="creditLeaderboard"/>
<column name="module_id" valueComputed="${entertainmentModule}"/>
<column name="feature_id" valueComputed="${economyFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="credits"/>
<column name="module_id" valueComputed="${entertainmentModule}"/>
<column name="feature_id" valueComputed="${economyFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="creditGamble"/>
<column name="module_id" valueComputed="${entertainmentModule}"/>
<column name="feature_id" valueComputed="${economyFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="transferCredits"/>
<column name="module_id" valueComputed="${entertainmentModule}"/>
<column name="feature_id" valueComputed="${economyFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,11 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,14 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="economy_feature-insertion">
<insert tableName="feature">
<column name="key" value="economy"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,44 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="economy_user-table">
<createTable tableName="economy_user">
<column name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="economy_user_pkey"/>
</column>
<column name="credits" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_pay_day" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="last_slots" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="economy_user" constraintName="fk_economy_user_server"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
referencedColumnNames="id" referencedTableName="server" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS economy_user_update_trigger ON economy_user;
CREATE TRIGGER economy_user_update_trigger BEFORE UPDATE ON economy_user FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS economy_user_insert_trigger ON economy_user;
CREATE TRIGGER economy_user_insert_trigger BEFORE INSERT ON economy_user FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="economy_user.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,19 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<property name="entertainmentFeature" value="(SELECT id FROM feature WHERE key = 'entertainment')"/>
<changeSet author="Sheldan" id="mock_context_command">
<insert tableName="context_command">
<column name="name" value="mock"/>
<column name="type" value="MESSAGE"/>
<column name="feature_id" valueComputed="${entertainmentFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="context_command.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -9,4 +9,6 @@
<include file="1.0-entertainment/collection.xml" relativeToChangelogFile="true"/>
<include file="1.2.8-entertainment/collection.xml" relativeToChangelogFile="true"/>
<include file="1.2.9-entertainment/collection.xml" relativeToChangelogFile="true"/>
<include file="1.4.0/collection.xml" relativeToChangelogFile="true"/>
<include file="1.4.3/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,56 +0,0 @@
package dev.sheldan.abstracto.entertainment.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.entertainment.model.command.ChooseResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class ChooseTest {
@InjectMocks
private Choose testUnit;
@Mock
private EntertainmentService entertainmentService;
@Mock
private ChannelService channelService;
@Captor
private ArgumentCaptor<ChooseResponseModel> responseModelArgumentCaptor;
@Test
public void executeChooseCommand() {
List<String> choices = Arrays.asList("choice1", "choice2");
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(choices));
when(entertainmentService.takeChoice(choices, parameters.getAuthor())).thenReturn(choices.get(0));
when(channelService.sendEmbedTemplateInTextChannelList(eq(Choose.CHOOSE_RESPONSE_TEMPLATE_KEY), responseModelArgumentCaptor.capture(), eq(parameters.getChannel()))).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
Assert.assertEquals(choices.get(0), responseModelArgumentCaptor.getValue().getChosenValue());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -1,57 +0,0 @@
package dev.sheldan.abstracto.entertainment.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.entertainment.model.command.EightBallResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class EightBallTest {
@InjectMocks
private EightBall testUnit;
@Mock
private EntertainmentService entertainmentService;
@Mock
private ChannelService channelService;
@Captor
private ArgumentCaptor<EightBallResponseModel> responseModelArgumentCaptor;
@Test
public void execute8BallCommand() {
String inputText = "text";
String chosenKey = "key";
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(inputText));
when(entertainmentService.getEightBallValue(inputText)).thenReturn(chosenKey);
when(channelService.sendEmbedTemplateInTextChannelList(eq(EightBall.EIGHT_BALL_RESPONSE_TEMPLATE_KEY), responseModelArgumentCaptor.capture(), eq(parameters.getChannel()))).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
Assert.assertEquals(chosenKey, responseModelArgumentCaptor.getValue().getChosenKey());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -1,61 +0,0 @@
package dev.sheldan.abstracto.entertainment.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.entertainment.model.command.LoveCalcResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.entertainment.command.LoveCalc.LOVE_CALC_RESPONSE_TEMPLATE_KEY;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class LoveCalcTest {
@InjectMocks
private LoveCalc testUnit;
@Mock
private EntertainmentService entertainmentService;
@Mock
private ChannelService channelService;
@Captor
private ArgumentCaptor<LoveCalcResponseModel> responseModelArgumentCaptor;
@Test
public void execute8BallCommand() {
String inputText = "text";
String inputText2 = "text2";
Integer loveResult = 2;
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(inputText, inputText2));
when(entertainmentService.getLoveCalcValue(inputText, inputText2)).thenReturn(loveResult);
when(channelService.sendEmbedTemplateInTextChannelList(eq(LOVE_CALC_RESPONSE_TEMPLATE_KEY), responseModelArgumentCaptor.capture(), eq(parameters.getChannel()))).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
Assert.assertEquals(loveResult, responseModelArgumentCaptor.getValue().getRolled());
Assert.assertEquals(inputText, responseModelArgumentCaptor.getValue().getFirstPart());
Assert.assertEquals(inputText2, responseModelArgumentCaptor.getValue().getSecondPart());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -1,87 +0,0 @@
package dev.sheldan.abstracto.entertainment.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.entertainment.model.command.RollResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureConfig.ROLL_DEFAULT_HIGH_KEY;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class RollTest {
@InjectMocks
private Roll testUnit;
@Mock
private EntertainmentService entertainmentService;
@Mock
private ChannelService channelService;
@Mock
private ConfigService configService;
@Captor
private ArgumentCaptor<RollResponseModel> responseModelArgumentCaptor;
@Test
public void executeWithNoParameter() {
CommandContext noParameters = CommandTestUtilities.getNoParameters();
Integer result = 4;
Long serverId = 3L;
Integer max = 10;
when(noParameters.getGuild().getIdLong()).thenReturn(serverId);
when(configService.getLongValueOrConfigDefault(ROLL_DEFAULT_HIGH_KEY, serverId)).thenReturn(max.longValue());
when(entertainmentService.calculateRollResult(1, max)).thenReturn(result);
when(channelService.sendEmbedTemplateInTextChannelList(eq(Roll.ROLL_RESPONSE_TEMPLATE_KEY), responseModelArgumentCaptor.capture(), eq(noParameters.getChannel()))).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> futureResult = testUnit.executeAsync(noParameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(futureResult);
Assert.assertEquals(4, responseModelArgumentCaptor.getValue().getRolled().intValue());
}
@Test
public void executeWithHighParameter() {
CommandContext noParameters = CommandTestUtilities.getWithParameters(Arrays.asList(20));
Integer result = 4;
when(entertainmentService.calculateRollResult(1, 20)).thenReturn(result);
when(channelService.sendEmbedTemplateInTextChannelList(eq(Roll.ROLL_RESPONSE_TEMPLATE_KEY), responseModelArgumentCaptor.capture(), eq(noParameters.getChannel()))).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> futureResult = testUnit.executeAsync(noParameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(futureResult);
Assert.assertEquals(4, responseModelArgumentCaptor.getValue().getRolled().intValue());
}
@Test
public void executeWithBothParameters() {
CommandContext noParameters = CommandTestUtilities.getWithParameters(Arrays.asList(20, 10));
Integer result = 4;
when(entertainmentService.calculateRollResult(10, 20)).thenReturn(result);
when(channelService.sendEmbedTemplateInTextChannelList(eq(Roll.ROLL_RESPONSE_TEMPLATE_KEY), responseModelArgumentCaptor.capture(), eq(noParameters.getChannel()))).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> futureResult = testUnit.executeAsync(noParameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(futureResult);
Assert.assertEquals(4, responseModelArgumentCaptor.getValue().getRolled().intValue());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -1,55 +0,0 @@
package dev.sheldan.abstracto.entertainment.command;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
import dev.sheldan.abstracto.entertainment.model.command.RouletteResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.concurrent.CompletableFuture;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class RouletteTest {
@InjectMocks
private Roulette testUnit;
@Mock
private EntertainmentService entertainmentService;
@Mock
private ChannelService channelService;
@Captor
private ArgumentCaptor<RouletteResponseModel> responseModelArgumentCaptor;
@Test
public void executeWithNoParameter() {
CommandContext noParameters = CommandTestUtilities.getNoParameters();
Boolean result = false;
when(entertainmentService.executeRoulette(noParameters.getAuthor())).thenReturn(result);
when(channelService.sendEmbedTemplateInTextChannelList(eq(Roulette.ROULETTE_RESPONSE_TEMPLATE_KEY), responseModelArgumentCaptor.capture(), eq(noParameters.getChannel()))).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> futureResult = testUnit.executeAsync(noParameters);
CommandTestUtilities.checkSuccessfulCompletionAsync(futureResult);
Assert.assertEquals(result, responseModelArgumentCaptor.getValue().getResult());
}
@Test
public void validateCommand() {
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
}
}

View File

@@ -11,7 +11,6 @@ import net.dv8tion.jda.api.entities.Member;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
@@ -20,7 +19,6 @@ import org.springframework.core.io.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Reader;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.HashMap;

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>entertainment</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.3.7</version>
<version>1.4.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.entertainment.config;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class EconomyFeatureConfig implements FeatureConfig {
public static final String PAYDAY_CREDITS_CONFIG_KEY = "paydayCredits";
public static final String PAYDAY_COOLDOWN_CONFIG_KEY = "paydayCooldown";
public static final String SLOTS_COOLDOWN_CONFIG_KEY = "slotsCooldown";
@Override
public FeatureDefinition getFeature() {
return EntertainmentFeatureDefinition.ECONOMY;
}
@Override
public List<String> getRequiredSystemConfigKeys() {
return Arrays.asList(PAYDAY_CREDITS_CONFIG_KEY, PAYDAY_COOLDOWN_CONFIG_KEY, SLOTS_COOLDOWN_CONFIG_KEY);
}
}

View File

@@ -5,7 +5,7 @@ import lombok.Getter;
@Getter
public enum EntertainmentFeatureDefinition implements FeatureDefinition {
ENTERTAINMENT("entertainment");
ENTERTAINMENT("entertainment"), ECONOMY("economy");
private String key;

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.entertainment.config;
public class EntertainmentSlashCommandNames {
public static final String ENTERTAINMENT = "entertainment";
public static final String UTILITY = "utility";
public static final String ECONOMY = "economy";
}

View File

@@ -0,0 +1,18 @@
package dev.sheldan.abstracto.entertainment.dto;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
@Builder
@Getter
public class CreditGambleResult {
private List<Integer> rolls;
private Integer uniqueNumbers;
private Long bid;
private Long toBank;
private Long toJackpot;
private Long currentJackpot;
private Boolean won;
}

View File

@@ -0,0 +1,11 @@
package dev.sheldan.abstracto.entertainment.dto;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
public class PayDayResult {
private Long currentCredits;
private Long gainedCredits;
}

View File

@@ -0,0 +1,18 @@
package dev.sheldan.abstracto.entertainment.dto;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
@Builder
@Getter
public class SlotsResult {
private Long bid;
private Long oldCredits;
private Long newCredits;
private Long winnings;
private Long factor;
private String outComeKey;
private List<List<String>> rows;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.entertainment.exception;
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
public class NotEnoughCreditsException extends AbstractoTemplatableException {
@Override
public String getTemplateName() {
return "not_enough_wealth_exception";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.entertainment.exception;
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
import dev.sheldan.abstracto.entertainment.model.exception.PayDayCooldownExceptionModel;
import java.time.Duration;
public class PayDayCooldownException extends AbstractoTemplatableException {
private final PayDayCooldownExceptionModel model;
public PayDayCooldownException(Duration duration) {
this.model = PayDayCooldownExceptionModel
.builder()
.tryAgainDuration(duration)
.build();
}
@Override
public String getTemplateName() {
return "payday_cooldown_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.entertainment.exception;
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
import dev.sheldan.abstracto.entertainment.model.exception.SlotsCooldownExceptionModel;
import java.time.Duration;
public class SlotsCooldownException extends AbstractoTemplatableException {
private final SlotsCooldownExceptionModel model;
public SlotsCooldownException(Duration duration) {
this.model = SlotsCooldownExceptionModel
.builder()
.tryAgainDuration(duration)
.build();
}
@Override
public String getTemplateName() {
return "slots_cooldown_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -1,13 +1,12 @@
package dev.sheldan.abstracto.entertainment.model.command;
import dev.sheldan.abstracto.core.models.context.SlimUserInitiatedServerContext;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Getter
@Setter
@SuperBuilder
public class ChooseResponseModel extends SlimUserInitiatedServerContext {
@Builder
public class ChooseResponseModel {
private String chosenValue;
}

View File

@@ -0,0 +1,32 @@
package dev.sheldan.abstracto.entertainment.model.command;
import dev.sheldan.abstracto.entertainment.dto.CreditGambleResult;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
@Getter
@Builder
public class CreditGambleResultModel {
private List<Integer> rolls;
private Integer uniqueNumbers;
private Long bid;
private Long toBank;
private Long toJackpot;
private Long currentJackpot;
private Boolean won;
public static CreditGambleResultModel fromCreditGambleResult(CreditGambleResult creditGambleResult) {
return CreditGambleResultModel
.builder()
.rolls(creditGambleResult.getRolls())
.uniqueNumbers(creditGambleResult.getUniqueNumbers())
.bid(creditGambleResult.getBid())
.toBank(creditGambleResult.getToBank())
.toJackpot(creditGambleResult.getToJackpot())
.currentJackpot(creditGambleResult.getCurrentJackpot())
.won(creditGambleResult.getWon())
.build();
}
}

View File

@@ -0,0 +1,17 @@
package dev.sheldan.abstracto.entertainment.model.command;
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Member;
@Getter
@Setter
@Builder
public class CreditsLeaderboardEntry {
private MemberDisplay memberDisplay;
private Member member;
private Long credits;
private Integer rank;
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.entertainment.model.command;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
@Getter
@Builder
public class CreditsLeaderboardResponseModel {
private List<CreditsLeaderboardEntry> entries;
private CreditsLeaderboardEntry ownRank;
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.entertainment.model.command;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class CreditsModel {
private CreditsLeaderboardEntry entry;
}

View File

@@ -1,13 +1,12 @@
package dev.sheldan.abstracto.entertainment.model.command;
import dev.sheldan.abstracto.core.models.context.SlimUserInitiatedServerContext;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Getter
@Setter
@SuperBuilder
public class EightBallResponseModel extends SlimUserInitiatedServerContext {
@Builder
public class EightBallResponseModel {
private String chosenKey;
}

View File

@@ -1,14 +1,13 @@
package dev.sheldan.abstracto.entertainment.model.command;
import dev.sheldan.abstracto.core.models.context.SlimUserInitiatedServerContext;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Getter
@Setter
@SuperBuilder
public class LoveCalcResponseModel extends SlimUserInitiatedServerContext {
@Builder
public class LoveCalcResponseModel {
private String firstPart;
private String secondPart;
private Integer rolled;

View File

@@ -1,14 +1,13 @@
package dev.sheldan.abstracto.entertainment.model.command;
import dev.sheldan.abstracto.core.models.context.SlimUserInitiatedServerContext;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Getter
@Setter
@SuperBuilder
public class MockResponseModel extends SlimUserInitiatedServerContext {
@Builder
public class MockResponseModel {
private String originalText;
private String mockingText;
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.entertainment.model.command;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class PayDayResponseModel {
private Long currentCredits;
private Long leaderboardPosition;
private Long gainedCredits;
}

View File

@@ -1,13 +1,12 @@
package dev.sheldan.abstracto.entertainment.model.command;
import dev.sheldan.abstracto.core.models.context.SlimUserInitiatedServerContext;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Getter
@Setter
@SuperBuilder
public class RollResponseModel extends SlimUserInitiatedServerContext {
@Builder
public class RollResponseModel {
private Integer rolled;
}

Some files were not shown because too many files have changed in this diff Show More