mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-07 18:03:50 +00:00
Compare commits
135 Commits
abstracto-
...
v1.5.13
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af5f9a8361 | ||
|
|
e84b5ecbb5 | ||
|
|
1ba8219d7b | ||
|
|
60d2c669a2 | ||
|
|
3a122a72e5 | ||
|
|
d53126e5a5 | ||
|
|
208d9a28ed | ||
|
|
6643359953 | ||
|
|
bd7149d159 | ||
|
|
c0b6a19bca | ||
|
|
58eece0814 | ||
|
|
abfd2c9591 | ||
|
|
a71a448b4b | ||
|
|
4d1ce7158f | ||
|
|
9bbb9430d9 | ||
|
|
a608fba082 | ||
|
|
f97fe42e65 | ||
|
|
f12581f322 | ||
|
|
e8f630c94c | ||
|
|
14f35caede | ||
|
|
915eb8ced9 | ||
|
|
148c10f250 | ||
|
|
74e5154e29 | ||
|
|
baad696a20 | ||
|
|
b7b5dc7b6a | ||
|
|
f27f59c0b3 | ||
|
|
ccd7ace8d9 | ||
|
|
73a73dc4f2 | ||
|
|
156725afa6 | ||
|
|
b369b56823 | ||
|
|
7482bf545d | ||
|
|
9804d165ca | ||
|
|
59ddb0b27d | ||
|
|
9aea9d2b4f | ||
|
|
b042e586a7 | ||
|
|
91e2bea2fc | ||
|
|
f03bee8b1e | ||
|
|
f3144eb094 | ||
|
|
2396bf300b | ||
|
|
06ebf4c882 | ||
|
|
ff534c03ac | ||
|
|
67c76487e2 | ||
|
|
9a2f47e244 | ||
|
|
2f33d19171 | ||
|
|
f6fc02e758 | ||
|
|
007929cfa5 | ||
|
|
77e2eec3d1 | ||
|
|
74c8cf7b6b | ||
|
|
c8739b90ec | ||
|
|
d39a303207 | ||
|
|
3e326fe47e | ||
|
|
a1d460973c | ||
|
|
d2475179e6 | ||
|
|
5adc304e77 | ||
|
|
4940577383 | ||
|
|
bba0a2ace6 | ||
|
|
b7c427026d | ||
|
|
cee10de915 | ||
|
|
1786231e11 | ||
|
|
2231fdf289 | ||
|
|
a46e22b5b2 | ||
|
|
1c9b9af833 | ||
|
|
3cafc95ceb | ||
|
|
6409bbaa1d | ||
|
|
346e462185 | ||
|
|
46baa79d3e | ||
|
|
650d062808 | ||
|
|
bac9832819 | ||
|
|
efbcb5c84b | ||
|
|
fd70e6ac90 | ||
|
|
29bde70796 | ||
|
|
ecd4feabb2 | ||
|
|
abf60409f1 | ||
|
|
080733957f | ||
|
|
8a41f366ae | ||
|
|
dbf478c44c | ||
|
|
3df688571f | ||
|
|
ca530949c6 | ||
|
|
724930e5a4 | ||
|
|
2875da117a | ||
|
|
f95ba6c28f | ||
|
|
1b2e7654f9 | ||
|
|
54976ed1d4 | ||
|
|
735816f5dd | ||
|
|
a984bdb84e | ||
|
|
21add6585d | ||
|
|
99e72245f3 | ||
|
|
9d184ff560 | ||
|
|
97895f5c56 | ||
|
|
f091559c49 | ||
|
|
fa7730975e | ||
|
|
03d7b9e2e2 | ||
|
|
a0bff12263 | ||
|
|
70e708601e | ||
|
|
f01418d0de | ||
|
|
ad539adb2a | ||
|
|
3c9fec989f | ||
|
|
21db3e3ee5 | ||
|
|
5b1ad2e075 | ||
|
|
63b3f68bdb | ||
|
|
7c1537c4a7 | ||
|
|
9836998087 | ||
|
|
8a1bb4cad8 | ||
|
|
a9dadec8ef | ||
|
|
3eaffaef87 | ||
|
|
b3a943e155 | ||
|
|
06dd4af131 | ||
|
|
0d51469975 | ||
|
|
aa10c88588 | ||
|
|
db27f64832 | ||
|
|
3903039aac | ||
|
|
41f42ee110 | ||
|
|
74f54e1257 | ||
|
|
a72e48f690 | ||
|
|
a813af8b1f | ||
|
|
abee7b2732 | ||
|
|
4c71ffbb7e | ||
|
|
18050e2a8a | ||
|
|
a0d83763d4 | ||
|
|
0461c8e4ec | ||
|
|
072f32975a | ||
|
|
6810d28c50 | ||
|
|
650a9099c4 | ||
|
|
1217e03725 | ||
|
|
2e837d8738 | ||
|
|
9ddd386c6f | ||
|
|
4e1db26df7 | ||
|
|
de335a1e2a | ||
|
|
9ba0ed711e | ||
|
|
b7376bf522 | ||
|
|
0d6182c5d5 | ||
|
|
96c38763b1 | ||
|
|
97b3099156 | ||
|
|
a0b2fc9c31 | ||
|
|
2db36ef96b |
24
.github/workflows/build.yml
vendored
24
.github/workflows/build.yml
vendored
@@ -1,7 +1,7 @@
|
||||
# This workflow will build a Java project with Maven
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
name: Execute build and Sonar
|
||||
name: Execute Build
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -19,26 +19,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 1.8
|
||||
distribution: 'corretto'
|
||||
java-version: 17
|
||||
- name: Build with Maven
|
||||
run: mvn -B install --file abstracto-application/pom.xml
|
||||
- name: Setup sonarqube
|
||||
uses: warchant/setup-sonar-scanner@v3
|
||||
- name: Run sonarqube
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: sonar-scanner
|
||||
-Dsonar.login=${{ secrets.SONAR_TOKEN }}
|
||||
-Dsonar.organization=sheldan
|
||||
-Dsonar.host.url=https://sonarcloud.io/
|
||||
-Dsonar.projectKey=abstracto-core
|
||||
-Dsonar.java.binaries=**/target/classes
|
||||
-Dsonar.coverage.jacoco.xmlReportPaths=abstracto-application/coverage/target/site/jacoco-aggregate/jacoco.xml
|
||||
-Dsonar.coverage.exclusions=**/*Test.java
|
||||
- uses: actions/setup-ruby@v1
|
||||
- name: Send Webhook Notification
|
||||
if: always()
|
||||
|
||||
34
.github/workflows/release.yml
vendored
34
.github/workflows/release.yml
vendored
@@ -6,13 +6,14 @@ jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Java for publishing to GitHub Packages
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 1.8
|
||||
distribution: 'corretto'
|
||||
java-version: 17
|
||||
- name: Load current version
|
||||
id: version
|
||||
run: echo "version=$(mvn --file abstracto-application/pom.xml -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive exec:exec)" >> $GITHUB_ENV
|
||||
@@ -21,7 +22,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Deploy documentation to GitHub pages
|
||||
uses: JamesIves/github-pages-deploy-action@4.1.0
|
||||
uses: JamesIves/github-pages-deploy-action@v4
|
||||
with:
|
||||
repository-name: Sheldan/abstracto-docs
|
||||
target-folder: docs/${{ env.version }}
|
||||
@@ -29,22 +30,27 @@ jobs:
|
||||
ssh-key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
|
||||
folder: abstracto-application/documentation/target/generated-docs
|
||||
- name: Deploy documentation to GitHub pages latest
|
||||
uses: JamesIves/github-pages-deploy-action@4.1.0
|
||||
uses: JamesIves/github-pages-deploy-action@v4
|
||||
with:
|
||||
repository-name: Sheldan/abstracto-docs
|
||||
target-folder: docs/current
|
||||
branch: master
|
||||
ssh-key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
|
||||
folder: abstracto-application/documentation/target/generated-docs
|
||||
- name: Login to GitHub Packages Docker Registry
|
||||
uses: docker/login-action@v1
|
||||
- name: Login to Harbor
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: docker.pkg.github.com
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Push deployment container
|
||||
working-directory: ./abstracto-application/installer/src/main/docker/deployment
|
||||
registry: harbor.sheldan.dev
|
||||
username: ${{ secrets.HARBOR_USERNAME }}
|
||||
password: ${{ secrets.HARBOR_TOKEN }}
|
||||
- name: Load env files
|
||||
id: dotenv
|
||||
uses: falti/dotenv-action@v1.0.4
|
||||
with:
|
||||
path: ./deployment/installer/.env
|
||||
- name: Push container
|
||||
run: docker-compose build && docker-compose push
|
||||
working-directory: ./deployment/installer/
|
||||
env:
|
||||
REGISTRY_PREFIX: docker.pkg.github.com/sheldan/abstracto/
|
||||
VERSION: ${{ env.version }}
|
||||
REGISTRY_PREFIX: ${{ steps.dotenv.outputs.registry_prefix }}
|
||||
VERSION: ${{ steps.dotenv.outputs.version }}
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Sheldan
|
||||
Copyright (c) 2023 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
|
||||
|
||||
14
README.md
14
README.md
@@ -1,8 +1,6 @@
|
||||
# Abstracto
|
||||
|
||||

|
||||
[](https://sonarcloud.io/dashboard?id=abstracto-core)
|
||||
[](https://sonarcloud.io/dashboard?id=abstracto-core)
|
||||

|
||||
[](https://github.com/Sheldan/abstracto/blob/master/LICENSE)
|
||||
|
||||
|
||||
@@ -14,22 +12,20 @@ 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 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)
|
||||
* [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper in the version 5.0.0-beta.13
|
||||
* [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.
|
||||
* [Ehcache](https://github.com/ehcache/ehcache3) is used as a caching implementation.
|
||||
* [Lombok](https://github.com/rzwitserloot/lombok) is used as a framework in order to speed up creation of container classes and builders.
|
||||
* [Quartz](https://github.com/quartz-scheduler/quartz) is used as a scheduling framework in order to provide functionalities which either require a delayed or cronjob behaviour.
|
||||
* [Docker](https://github.com/docker) is used to package the application into a container and [Docker Compose](https://github.com/docker/compose) is used to connect the required containers together.
|
||||
* [Quartz](https://github.com/quartz-scheduler/quartz) is used as a scheduling framework in order to provide functionalities which either require a scheduled or cronjob behaviour.
|
||||
* [Docker](https://github.com/docker) is used to package the application into an image and [Docker Compose](https://github.com/docker/compose) is used to build the images
|
||||
* [Liquibase](https://github.com/liquibase/liquibase) is used to manage changes to the database
|
||||
|
||||
## Documentation
|
||||
A detailed documentation of the pure form of Abstracto including the terminology and commands in HTML form is available [here](https://sheldan.github.io/abstracto-docs/current). The PDF is available [here](https://sheldan.github.io/abstracto-docs/current/documentation.pdf)
|
||||
If you want to view the documentation to an earlier released version you need to append the desired version to the URL. The current version will be available aforementioned URL, but it is not right now, because Abstracto has not been released yet.
|
||||
|
||||
## Customization documentation
|
||||
TBD when Abstracto is released, as the current version is still being adapted, because of findings from the example customization in Crimson.
|
||||
|
||||
## Issues
|
||||
If you find any issue, feel free to create a GitHub issue.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -41,13 +41,19 @@ public class ActivateAssignableRolePlace extends AbstractConditionableCommand {
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter placeName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter placeName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(placeName);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("activateAssignableRolePlace")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.messageCommandOnly(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
|
||||
@@ -36,16 +36,40 @@ public class AddAssignableRoleCondition extends AbstractConditionableCommand {
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter placeName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter role = Parameter.builder().name("role").type(Role.class).templated(true).build();
|
||||
Parameter conditionKey = Parameter.builder().name("conditionKey").type(AssignableRoleConditionType.class).templated(true).build();
|
||||
Parameter conditionValue = Parameter.builder().name("conditionParameter").type(String.class).templated(true).build();
|
||||
Parameter placeName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter role = Parameter
|
||||
.builder()
|
||||
.name("role")
|
||||
.type(Role.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter conditionKey = Parameter
|
||||
.builder()
|
||||
.name("conditionKey")
|
||||
.type(AssignableRoleConditionType.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter conditionValue = Parameter
|
||||
.builder()
|
||||
.name("conditionParameter")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(placeName, role, conditionKey, conditionValue);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("addAssignableRoleCondition")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.messageCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -62,17 +62,42 @@ public class AddRoleToAssignableRolePost extends AbstractConditionableCommand {
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter placeName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter role = Parameter.builder().name("role").type(Role.class).templated(true).build();
|
||||
Parameter rolePostName = Parameter.builder().name("displayText").type(String.class).templated(true).build();
|
||||
Parameter emote = Parameter.builder().name("emote").type(FullEmote.class).optional(true).templated(true).build();
|
||||
Parameter placeName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter role = Parameter
|
||||
.builder()
|
||||
.name("role")
|
||||
.type(Role.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter rolePostName = Parameter
|
||||
.builder()
|
||||
.name("displayText")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter emote = Parameter
|
||||
.builder()
|
||||
.name("emote")
|
||||
.type(FullEmote.class)
|
||||
.optional(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(placeName, role, rolePostName, emote);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("addRoleToAssignableRolePlace")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.messageCommandOnly(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -47,9 +47,24 @@ public class ChangeAssignableRolePlaceConfig extends AbstractConditionableComman
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter assignableRolePlaceName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter parameterKey = Parameter.builder().name("key").type(AssignableRolePlaceParameterKey.class).templated(true).build();
|
||||
Parameter parameterValue = Parameter.builder().name("value").type(String.class).templated(true).build();
|
||||
Parameter assignableRolePlaceName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter parameterKey = Parameter
|
||||
.builder()
|
||||
.name("key")
|
||||
.type(AssignableRolePlaceParameterKey.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter parameterValue = Parameter
|
||||
.builder()
|
||||
.name("value")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(assignableRolePlaceName, parameterKey, parameterValue);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
@@ -57,6 +72,7 @@ public class ChangeAssignableRolePlaceConfig extends AbstractConditionableComman
|
||||
.name("changeAssignableRolePlaceConfig")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.messageCommandOnly(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
|
||||
@@ -33,9 +33,6 @@ public class CreateAssignableRolePost extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
@@ -57,20 +54,47 @@ public class CreateAssignableRolePost extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<ParameterValidator> rolePlaceNameValidator = Arrays.asList(MaxStringLengthValidator.max(AssignableRolePlace.ASSIGNABLE_PLACE_NAME_LIMIT));
|
||||
Parameter rolePostName = Parameter.builder().name("name").validators(rolePlaceNameValidator).type(String.class).templated(true).build();
|
||||
Parameter channel = Parameter.builder().name("channel").type(TextChannel.class).templated(true).build();
|
||||
Parameter type = Parameter.builder().name("type").type(AssignableRolePlaceType.class).templated(true).optional(true).build();
|
||||
Parameter rolePostName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.validators(rolePlaceNameValidator)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter channel = Parameter
|
||||
.builder()
|
||||
.name("channel")
|
||||
.type(TextChannel.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter type = Parameter
|
||||
.builder()
|
||||
.name("type")
|
||||
.type(AssignableRolePlaceType.class)
|
||||
.templated(true)
|
||||
.optional(true)
|
||||
.build();
|
||||
List<ParameterValidator> rolePlaceDescriptionValidator = Arrays.asList(MaxStringLengthValidator.max(AssignableRolePlace.ASSIGNABLE_PLACE_NAME_LIMIT));
|
||||
Parameter text = Parameter.builder().name("text").validators(rolePlaceDescriptionValidator).type(String.class).templated(true).build();
|
||||
Parameter text = Parameter
|
||||
.builder()
|
||||
.name("text")
|
||||
.validators(rolePlaceDescriptionValidator)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<String> aliases = Arrays.asList("crRPl", "crAssRoPl");
|
||||
List<Parameter> parameters = Arrays.asList(rolePostName, channel, text, type);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("createAssignableRolePlace")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.messageCommandOnly(true)
|
||||
.parameters(parameters)
|
||||
.aliases(aliases)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -41,7 +41,12 @@ public class DeactivateAssignableRolePlace extends AbstractConditionableCommand
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter rolePostName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(rolePostName);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
@@ -49,6 +54,7 @@ public class DeactivateAssignableRolePlace extends AbstractConditionableCommand
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.messageCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -41,7 +41,12 @@ public class DeleteAssignableRolePlace extends AbstractConditionableCommand {
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter rolePostName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(rolePostName);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
@@ -50,6 +55,7 @@ public class DeleteAssignableRolePlace extends AbstractConditionableCommand {
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.async(true)
|
||||
.messageCommandOnly(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -46,15 +46,29 @@ public class EditAssignableRolePlaceText extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<ParameterValidator> rolePlaceNameValidator = Arrays.asList(MaxStringLengthValidator.max(AssignableRolePlace.ASSIGNABLE_PLACE_NAME_LIMIT));
|
||||
Parameter rolePostName = Parameter.builder().name("name").validators(rolePlaceNameValidator).type(String.class).templated(true).build();
|
||||
Parameter newText = Parameter.builder().name("newText").type(String.class).templated(true).build();
|
||||
Parameter rolePostName = Parameter
|
||||
.builder().name("name")
|
||||
.validators(rolePlaceNameValidator)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter newText = Parameter
|
||||
.builder()
|
||||
.name("newText")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(rolePostName, newText);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("editAssignableRolePlaceText")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.messageCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -67,6 +67,7 @@ public class MoveAssignableRolePlace extends AbstractConditionableCommand {
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.messageCommandOnly(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -35,15 +35,31 @@ public class RemoveAssignableRoleCondition extends AbstractConditionableCommand
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter placeName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter role = Parameter.builder().name("role").type(Role.class).templated(true).build();
|
||||
Parameter conditionKey = Parameter.builder().name("conditionKey").type(AssignableRoleConditionType.class).templated(true).build();
|
||||
Parameter placeName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter role = Parameter
|
||||
.builder()
|
||||
.name("role")
|
||||
.type(Role.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter conditionKey = Parameter
|
||||
.builder()
|
||||
.name("conditionKey")
|
||||
.type(AssignableRoleConditionType.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(placeName, role, conditionKey);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("removeAssignableRoleCondition")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.messageCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -44,16 +44,30 @@ public class RemoveRoleFromAssignableRolePlace extends AbstractConditionableComm
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter role = Parameter.builder().name("role").type(ARole.class).templated(true).build();
|
||||
Parameter rolePostName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
Parameter role = Parameter
|
||||
.builder()
|
||||
.name("role")
|
||||
.type(ARole.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(rolePostName, role);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("removeRoleFromAssignableRolePlace")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.async(true)
|
||||
.messageCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -48,14 +48,23 @@ public class SetupAssignableRolePlace extends AbstractConditionableCommand {
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter rolePostName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(rolePostName);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("setupAssignableRolePlace")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.messageCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -48,15 +48,24 @@ public class ShowAssignableRolePlaceConfig extends AbstractConditionableCommand
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
|
||||
Parameter rolePostName = Parameter
|
||||
.builder()
|
||||
.name("name")
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(rolePostName);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("showAssignableRolePlaceConfig")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.causesReaction(false)
|
||||
.messageCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -45,11 +45,15 @@ public class ShowAssignableRolePlaces extends AbstractConditionableCommand {
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("showAssignableRolePlaces")
|
||||
.module(AssignableRoleModuleDefinition.ASSIGNABLE_ROLES)
|
||||
.templated(true)
|
||||
.messageCommandOnly(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>assignable-roles-int</artifactId>
|
||||
|
||||
@@ -6,7 +6,7 @@ import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.ComponentPayload;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.assignableroles.model.database;
|
||||
import dev.sheldan.abstracto.assignableroles.model.condition.AssignableRoleConditionType;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "assignable_role_condition")
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.assignableroles.model.database;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package dev.sheldan.abstracto.customcommand.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.customcommand.config.CustomCommandFeatureDefinition;
|
||||
import dev.sheldan.abstracto.customcommand.config.CustomCommandSlashCommandNames;
|
||||
import dev.sheldan.abstracto.customcommand.service.management.CustomCommandService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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
|
||||
@Slf4j
|
||||
public class CreateCustomCommand extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CREATE_CUSTOM_COMMAND_COMMAND = "createCustomCommand";
|
||||
private static final String CUSTOM_COMMAND_NAME_PARAMETER = "commandName";
|
||||
private static final String CUSTOM_COMMAND_CONTENT_PARAMETER = "response";
|
||||
private static final String CREATE_CUSTOM_COMMAND_RESPONSE_TEMPLATE_KEY = "createCustomCommand_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private CustomCommandService customCommandService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String name = slashCommandParameterService.getCommandOption(CUSTOM_COMMAND_NAME_PARAMETER, event, String.class);
|
||||
String content = slashCommandParameterService.getCommandOption(CUSTOM_COMMAND_CONTENT_PARAMETER, event, String.class);
|
||||
|
||||
customCommandService.createCustomCommand(name, content, event.getMember());
|
||||
return interactionService.replyEmbed(CREATE_CUSTOM_COMMAND_RESPONSE_TEMPLATE_KEY, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return CustomCommandFeatureDefinition.CUSTOM_COMMAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter commandNameParameter = Parameter
|
||||
.builder()
|
||||
.name(CUSTOM_COMMAND_NAME_PARAMETER)
|
||||
.templated(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
Parameter commandContentParameter = Parameter
|
||||
.builder()
|
||||
.name(CUSTOM_COMMAND_CONTENT_PARAMETER)
|
||||
.templated(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(commandNameParameter, commandContentParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(CustomCommandSlashCommandNames.CUSTOM_COMMAND)
|
||||
.commandName("create")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(CREATE_CUSTOM_COMMAND_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.causesReaction(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package dev.sheldan.abstracto.customcommand.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.customcommand.config.CustomCommandFeatureDefinition;
|
||||
import dev.sheldan.abstracto.customcommand.config.CustomCommandSlashCommandNames;
|
||||
import dev.sheldan.abstracto.customcommand.service.management.CustomCommandService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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
|
||||
@Slf4j
|
||||
public class DeleteCustomCommand extends AbstractConditionableCommand {
|
||||
|
||||
private static final String DELETE_CUSTOM_COMMAND_COMMAND = "deleteCustomCommand";
|
||||
private static final String DELETE_CUSTOM_COMMAND_RESPONSE_TEMPLATE_KEY = "deleteCustomCommand_response";
|
||||
private static final String CUSTOM_COMMAND_NAME_PARAMETER = "commandName";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private CustomCommandService customCommandService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String name = slashCommandParameterService.getCommandOption(CUSTOM_COMMAND_NAME_PARAMETER, event, String.class);
|
||||
|
||||
customCommandService.deleteCustomCommand(name, event.getGuild());
|
||||
return interactionService.replyEmbed(DELETE_CUSTOM_COMMAND_RESPONSE_TEMPLATE_KEY, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter commandNameParameter = Parameter
|
||||
.builder()
|
||||
.name(CUSTOM_COMMAND_NAME_PARAMETER)
|
||||
.templated(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(commandNameParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(CustomCommandSlashCommandNames.CUSTOM_COMMAND)
|
||||
.commandName("delete")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(DELETE_CUSTOM_COMMAND_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.causesReaction(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return CustomCommandFeatureDefinition.CUSTOM_COMMAND;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package dev.sheldan.abstracto.customcommand.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.customcommand.config.CustomCommandFeatureDefinition;
|
||||
import dev.sheldan.abstracto.customcommand.config.CustomCommandSlashCommandNames;
|
||||
import dev.sheldan.abstracto.customcommand.model.command.CustomCommandResponseModel;
|
||||
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
|
||||
import dev.sheldan.abstracto.customcommand.service.management.CustomCommandService;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
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 GetCustomCommand extends AbstractConditionableCommand {
|
||||
|
||||
private static final String GET_CUSTOM_COMMAND_COMMAND = "getCustomCommand";
|
||||
private static final String CUSTOM_COMMAND_NAME_PARAMETER = "commandName";
|
||||
private static final String GET_CUSTOM_COMMAND_RESPONSE_TEMPLATE_KEY = "getCustomCommand_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private CustomCommandService customCommandService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandAutoCompleteService slashCommandAutoCompleteService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String name = slashCommandParameterService.getCommandOption(CUSTOM_COMMAND_NAME_PARAMETER, event, String.class);
|
||||
CustomCommand customCommand = customCommandService.getCustomCommand(name, event.getGuild());
|
||||
CustomCommandResponseModel model = CustomCommandResponseModel
|
||||
.builder()
|
||||
.additionalText(customCommand.getAdditionalMessage())
|
||||
.build();
|
||||
return interactionService.replyEmbed(GET_CUSTOM_COMMAND_RESPONSE_TEMPLATE_KEY, model, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> performAutoComplete(CommandAutoCompleteInteractionEvent event) {
|
||||
if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), CUSTOM_COMMAND_NAME_PARAMETER)) {
|
||||
String input = event.getFocusedOption().getValue();
|
||||
return customCommandService.getCustomCommandsStartingWith(input, event.getGuild())
|
||||
.stream()
|
||||
.map(CustomCommand::getName)
|
||||
.limit(25)
|
||||
.toList();
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return CustomCommandFeatureDefinition.CUSTOM_COMMAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter commandNameParameter = Parameter
|
||||
.builder()
|
||||
.name(CUSTOM_COMMAND_NAME_PARAMETER)
|
||||
.templated(true)
|
||||
.supportsAutoComplete(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(commandNameParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(CustomCommandSlashCommandNames.CUSTOM_COMMAND_PUBLIC)
|
||||
.commandName("get")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(GET_CUSTOM_COMMAND_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.causesReaction(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package dev.sheldan.abstracto.customcommand.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.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.service.PaginatorService;
|
||||
import dev.sheldan.abstracto.customcommand.config.CustomCommandFeatureDefinition;
|
||||
import dev.sheldan.abstracto.customcommand.config.CustomCommandSlashCommandNames;
|
||||
import dev.sheldan.abstracto.customcommand.model.command.ListCustomCommandsResponseModel;
|
||||
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
|
||||
import dev.sheldan.abstracto.customcommand.service.management.CustomCommandService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ListCustomCommands extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CREATE_CUSTOM_COMMAND_COMMAND = "listCustomCommands";
|
||||
private static final String LIST_CUSTOM_COMMANDS_TEMPLATE_KEY = "listCustomCommands_response";
|
||||
private static final String NO_CUSTOM_COMMANDS_TEMPLATE_KEY = "listCustomCommands_no_commands_response";
|
||||
|
||||
@Autowired
|
||||
private CustomCommandService customCommandService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private PaginatorService paginatorService;
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
List<CustomCommand> customCommands = customCommandService.getCustomCommands(event.getGuild());
|
||||
if(customCommands.isEmpty()) {
|
||||
return interactionService.replyEmbed(NO_CUSTOM_COMMANDS_TEMPLATE_KEY, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
ListCustomCommandsResponseModel model = ListCustomCommandsResponseModel.fromCommands(customCommands);
|
||||
return paginatorService.createPaginatorFromTemplate(LIST_CUSTOM_COMMANDS_TEMPLATE_KEY, model, event)
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return CustomCommandFeatureDefinition.CUSTOM_COMMAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(CustomCommandSlashCommandNames.CUSTOM_COMMAND_PUBLIC)
|
||||
.commandName("list")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(CREATE_CUSTOM_COMMAND_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.causesReaction(true)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,13 @@ import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface CustomCommandRepository extends JpaRepository<CustomCommand, Long> {
|
||||
Optional<CustomCommand> getByNameIgnoreCaseAndServer(String name, AServer server);
|
||||
void deleteByNameAndServer(String name, AServer server);
|
||||
List<CustomCommand> findByServer(AServer server);
|
||||
List<CustomCommand> findByNameStartsWithIgnoreCaseAndServer(String prefix, AServer server);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package dev.sheldan.abstracto.customcommand.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.customcommand.exception.CustomCommandExistsException;
|
||||
import dev.sheldan.abstracto.customcommand.exception.CustomCommandNotFoundException;
|
||||
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
|
||||
import dev.sheldan.abstracto.customcommand.service.management.CustomCommandManagementService;
|
||||
import dev.sheldan.abstracto.customcommand.service.management.CustomCommandService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class CustomCommandServiceBean implements CustomCommandService {
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private CustomCommandManagementService customCommandManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public CustomCommand createCustomCommand(String name, String content, Member creator) {
|
||||
if(customCommandManagementService.getCustomCommandByName(name, creator.getGuild().getIdLong()).isPresent()) {
|
||||
throw new CustomCommandExistsException();
|
||||
}
|
||||
AUserInAServer creatorUser = userInServerManagementService.loadOrCreateUser(creator);
|
||||
return customCommandManagementService.createCustomCommand(name, content, creatorUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCustomCommand(String name, Guild guild) {
|
||||
if(customCommandManagementService.getCustomCommandByName(name, guild.getIdLong()).isEmpty()) {
|
||||
throw new CustomCommandNotFoundException();
|
||||
}
|
||||
AServer server = serverManagementService.loadServer(guild);
|
||||
customCommandManagementService.deleteCustomCommand(name, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CustomCommand> getCustomCommands(Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild);
|
||||
return customCommandManagementService.getCustomCommands(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomCommand getCustomCommand(String name, Guild guild) {
|
||||
return customCommandManagementService.getCustomCommandByName(name, guild.getIdLong())
|
||||
.orElseThrow(CustomCommandNotFoundException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CustomCommand> getCustomCommandsStartingWith(String prefix, Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild);
|
||||
return customCommandManagementService.getCustomCommandsStartingWith(prefix, server);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package dev.sheldan.abstracto.customcommand.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
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.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@@ -23,4 +25,32 @@ public class CustomCommandManagementServiceBean implements CustomCommandManageme
|
||||
AServer server = serverManagementService.loadServer(serverId);
|
||||
return repository.getByNameIgnoreCaseAndServer(name, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomCommand createCustomCommand(String name, String content, AUserInAServer creator) {
|
||||
CustomCommand customCommand = CustomCommand
|
||||
.builder()
|
||||
.name(name)
|
||||
.additionalMessage(content)
|
||||
.server(creator.getServerReference())
|
||||
.creator(creator)
|
||||
.build();
|
||||
return repository.save(customCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCustomCommand(String name, AServer server) {
|
||||
repository.deleteByNameAndServer(name, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CustomCommand> getCustomCommands(AServer server) {
|
||||
return repository.findByServer(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CustomCommand> getCustomCommandsStartingWith(String prefix, AServer server) {
|
||||
return repository.findByNameStartsWithIgnoreCaseAndServer(prefix, server);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<property name="customCommandFeature" value="(SELECT id FROM feature WHERE key = 'customCommand')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="customCommand-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="createCustomCommand"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${customCommandFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="deleteCustomCommand"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${customCommandFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="getCustomCommand"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${customCommandFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="listCustomCommands"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${customCommandFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?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-add_auto_increment">
|
||||
<sql>
|
||||
create sequence custom_command_id_seq;
|
||||
alter table custom_command alter id set default nextval('custom_command_id_seq');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="custom_command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -7,4 +7,5 @@
|
||||
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"/>
|
||||
<include file="1.5.8/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.abstracto.customcommand.config;
|
||||
|
||||
public class CustomCommandSlashCommandNames {
|
||||
public static final String CUSTOM_COMMAND = "cc";
|
||||
public static final String CUSTOM_COMMAND_PUBLIC = "customCommands";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.customcommand.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
public class CustomCommandExistsException extends AbstractoTemplatableException {
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "custom_command_exists_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.customcommand.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
public class CustomCommandNotFoundException extends AbstractoTemplatableException {
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "custom_command_not_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package dev.sheldan.abstracto.customcommand.model.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class ListCustomCommandModel {
|
||||
private String name;
|
||||
private String content;
|
||||
private MemberDisplay creator;
|
||||
|
||||
public static ListCustomCommandModel fromCustomCommand(CustomCommand customCommand) {
|
||||
return ListCustomCommandModel
|
||||
.builder()
|
||||
.name(customCommand.getName())
|
||||
.content(customCommand.getAdditionalMessage())
|
||||
.creator(MemberDisplay.fromAUserInAServer(customCommand.getCreator()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package dev.sheldan.abstracto.customcommand.model.command;
|
||||
|
||||
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class ListCustomCommandsResponseModel {
|
||||
private List<ListCustomCommandModel> customCommands;
|
||||
|
||||
public static ListCustomCommandsResponseModel fromCommands(List<CustomCommand> customCommands) {
|
||||
return ListCustomCommandsResponseModel
|
||||
.builder()
|
||||
.customCommands(customCommands
|
||||
.stream()
|
||||
.map(ListCustomCommandModel::fromCustomCommand)
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.customcommand.model.database;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
package dev.sheldan.abstracto.customcommand.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface CustomCommandManagementService {
|
||||
Optional<CustomCommand> getCustomCommandByName(String name, Long serverId);
|
||||
CustomCommand createCustomCommand(String name, String content, AUserInAServer creator);
|
||||
void deleteCustomCommand(String name, AServer server);
|
||||
List<CustomCommand> getCustomCommands(AServer server);
|
||||
List<CustomCommand> getCustomCommandsStartingWith(String prefix, AServer server);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.customcommand.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.customcommand.model.database.CustomCommand;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CustomCommandService {
|
||||
CustomCommand createCustomCommand(String name, String content, Member creator);
|
||||
void deleteCustomCommand(String name, Guild guild);
|
||||
List<CustomCommand> getCustomCommands(Guild guild);
|
||||
CustomCommand getCustomCommand(String name, Guild guild);
|
||||
List<CustomCommand> getCustomCommandsStartingWith(String prefix, Guild guild);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package dev.sheldan.abstracto.activity.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -52,14 +52,28 @@ public class React extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("message").type(Message.class).templated(true).build());
|
||||
parameters.add(Parameter.builder().name("text").type(String.class).remainder(true).templated(true).build());
|
||||
Parameter messageParameter = Parameter
|
||||
.builder()
|
||||
.name("message")
|
||||
.type(Message.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
parameters.add(messageParameter);
|
||||
Parameter textParameter = Parameter
|
||||
.builder()
|
||||
.name("text")
|
||||
.type(String.class)
|
||||
.remainder(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
parameters.add(textParameter);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("react")
|
||||
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.messageCommandOnly(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -89,14 +89,14 @@ public class Slots extends AbstractConditionableCommand {
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
Parameter lowParameter = Parameter
|
||||
Parameter bidParameter = Parameter
|
||||
.builder()
|
||||
.name(BID_PARAMETER)
|
||||
.type(Integer.class)
|
||||
.templated(true)
|
||||
.validators(Arrays.asList(MinIntegerValueValidator.min(0L)))
|
||||
.build();
|
||||
parameters.add(lowParameter);
|
||||
parameters.add(bidParameter);
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
package dev.sheldan.abstracto.entertainment.command.games;
|
||||
|
||||
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.ServerUser;
|
||||
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.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.exception.NotEnoughCreditsException;
|
||||
import dev.sheldan.abstracto.entertainment.model.command.games.MineBoard;
|
||||
import dev.sheldan.abstracto.entertainment.model.database.EconomyUser;
|
||||
import dev.sheldan.abstracto.entertainment.service.GameService;
|
||||
import dev.sheldan.abstracto.entertainment.service.management.EconomyUserManagementService;
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class Mines extends AbstractConditionableCommand {
|
||||
|
||||
private static final String MINES_COMMAND_NAME = "mines";
|
||||
private static final String WIDTH_PARAMETER = "width";
|
||||
private static final String HEIGHT_PARAMETER = "height";
|
||||
private static final String MINES_PARAMETER = "mines";
|
||||
private static final String CREDITS_PARAMETER = "credits";
|
||||
public static final String MINE_BOARD_TEMPLATE_KEY = "mines_board_response";
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private GameService gameService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private EconomyUserManagementService economyUserManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Integer width = 5;
|
||||
if(slashCommandParameterService.hasCommandOption(WIDTH_PARAMETER, event)) {
|
||||
width = slashCommandParameterService.getCommandOption(WIDTH_PARAMETER, event, Integer.class);
|
||||
}
|
||||
Integer height = 5;
|
||||
if(slashCommandParameterService.hasCommandOption(HEIGHT_PARAMETER, event)) {
|
||||
height = slashCommandParameterService.getCommandOption(HEIGHT_PARAMETER, event, Integer.class);
|
||||
}
|
||||
Integer mines = 5;
|
||||
if(slashCommandParameterService.hasCommandOption(MINES_PARAMETER, event)) {
|
||||
mines = slashCommandParameterService.getCommandOption(MINES_PARAMETER, event, Integer.class);
|
||||
}
|
||||
Integer credit = null;
|
||||
long serverId = event.getGuild().getIdLong();
|
||||
boolean economyEnabled = featureFlagService.getFeatureFlagValue(EntertainmentFeatureDefinition.ECONOMY, serverId);
|
||||
if(economyEnabled){
|
||||
credit = 50;
|
||||
if(slashCommandParameterService.hasCommandOption(CREDITS_PARAMETER, event)) {
|
||||
credit = slashCommandParameterService.getCommandOption(CREDITS_PARAMETER, event, Integer.class);
|
||||
}
|
||||
|
||||
Optional<EconomyUser> userOptional = economyUserManagementService.getUser(ServerUser.fromMember(event.getMember()));
|
||||
if(!userOptional.isPresent()) {
|
||||
throw new NotEnoughCreditsException();
|
||||
}
|
||||
EconomyUser user = userOptional.get();
|
||||
if(user.getCredits() < credit) {
|
||||
throw new NotEnoughCreditsException();
|
||||
}
|
||||
}
|
||||
MineBoard board = gameService.createBoard(width, height, mines, serverId);
|
||||
board.setCreditsEnabled(economyEnabled);
|
||||
board.setUserId(event.getMember().getIdLong());
|
||||
board.setServerId(serverId);
|
||||
board.setCredits(credit);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(MINE_BOARD_TEMPLATE_KEY, board);
|
||||
return interactionService.replyMessageToSend(messageToSend, event)
|
||||
.thenCompose(interactionHook -> interactionHook.retrieveOriginal().submit())
|
||||
.thenApply(message -> {
|
||||
gameService.persistMineBoardMessage(board, message);
|
||||
return CommandResult.fromSuccess();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
Integer width = 5;
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
if(!parameters.isEmpty()) {
|
||||
width = (Integer) parameters.get(0);
|
||||
}
|
||||
Integer height = 5;
|
||||
if(parameters.size() >= 2) {
|
||||
height = (Integer) parameters.get(1);
|
||||
}
|
||||
Integer mines = 5;
|
||||
if(parameters.size() >= 3) {
|
||||
mines = (Integer) parameters.get(2);
|
||||
}
|
||||
Integer credit = null;
|
||||
long serverId = commandContext.getGuild().getIdLong();
|
||||
boolean economyEnabled = featureFlagService.getFeatureFlagValue(EntertainmentFeatureDefinition.ECONOMY, serverId);
|
||||
if(economyEnabled){
|
||||
credit = 50;
|
||||
if(parameters.size() == 4) {
|
||||
credit = (Integer) parameters.get(3);
|
||||
}
|
||||
|
||||
Optional<EconomyUser> userOptional = economyUserManagementService.getUser(ServerUser.fromMember(commandContext.getAuthor()));
|
||||
if(!userOptional.isPresent()) {
|
||||
throw new NotEnoughCreditsException();
|
||||
}
|
||||
EconomyUser user = userOptional.get();
|
||||
if(user.getCredits() < credit) {
|
||||
throw new NotEnoughCreditsException();
|
||||
}
|
||||
}
|
||||
MineBoard board = gameService.createBoard(width, height, mines, serverId);
|
||||
board.setCreditsEnabled(economyEnabled);
|
||||
board.setUserId(commandContext.getAuthor().getIdLong());
|
||||
board.setServerId(serverId);
|
||||
board.setCredits(credit);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(MINE_BOARD_TEMPLATE_KEY, board);
|
||||
List<CompletableFuture<Message>> futures = channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel());
|
||||
return FutureUtils.toSingleFutureGeneric(futures)
|
||||
.thenAccept(unused -> gameService.persistMineBoardMessage(board, futures.get(0).join()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
Parameter widthParameter = Parameter
|
||||
.builder()
|
||||
.name(WIDTH_PARAMETER)
|
||||
.type(Integer.class)
|
||||
.optional(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
parameters.add(widthParameter);
|
||||
|
||||
Parameter heightParameter = Parameter
|
||||
.builder()
|
||||
.name(HEIGHT_PARAMETER)
|
||||
.type(Integer.class)
|
||||
.optional(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
parameters.add(heightParameter);
|
||||
|
||||
Parameter minesParameter = Parameter
|
||||
.builder()
|
||||
.name(MINES_PARAMETER)
|
||||
.type(Integer.class)
|
||||
.optional(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
parameters.add(minesParameter);
|
||||
|
||||
Parameter creditsParameter = Parameter
|
||||
.builder()
|
||||
.name(CREDITS_PARAMETER)
|
||||
.type(Integer.class)
|
||||
.optional(true)
|
||||
.templated(true)
|
||||
.dependentFeatures(Arrays.asList(EntertainmentFeatureDefinition.ECONOMY.getKey()))
|
||||
.build();
|
||||
parameters.add(creditsParameter);
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(EntertainmentSlashCommandNames.GAME)
|
||||
.commandName(MINES_COMMAND_NAME)
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(MINES_COMMAND_NAME)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return EntertainmentFeatureDefinition.GAMES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package dev.sheldan.abstracto.entertainment.listener.interaction;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListener;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerModel;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerResult;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.entertainment.command.games.Mines;
|
||||
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
|
||||
import dev.sheldan.abstracto.entertainment.model.command.games.MineBoard;
|
||||
import dev.sheldan.abstracto.entertainment.model.command.games.MineBoardPayload;
|
||||
import dev.sheldan.abstracto.entertainment.service.GameService;
|
||||
import dev.sheldan.abstracto.entertainment.service.GameServiceBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MinesButtonClickedListener implements ButtonClickedListener {
|
||||
|
||||
@Autowired
|
||||
private GameService gameService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Override
|
||||
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
|
||||
MineBoardPayload payload = (MineBoardPayload) model.getDeserializedPayload();
|
||||
if(model.getEvent().getUser().getIdLong() != payload.getMineBoard().getUserId()) {
|
||||
return ButtonClickedListenerResult.IGNORED;
|
||||
}
|
||||
MineBoard mineBoard = payload.getMineBoard();
|
||||
if(!mineBoard.getState().equals(GameService.MineResult.CONTINUE)) {
|
||||
return ButtonClickedListenerResult.IGNORED;
|
||||
}
|
||||
GameService.MineResult mineResult = gameService.uncoverField(mineBoard, payload.getX(), payload.getY());
|
||||
mineBoard.setState(mineResult);
|
||||
if(mineBoard.getState() != GameService.MineResult.CONTINUE) {
|
||||
if(featureFlagService.getFeatureFlagValue(EntertainmentFeatureDefinition.ECONOMY, model.getServerId())){
|
||||
gameService.evaluateCreditChanges(mineBoard);
|
||||
}
|
||||
gameService.uncoverBoard(mineBoard);
|
||||
}
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(Mines.MINE_BOARD_TEMPLATE_KEY, mineBoard);
|
||||
interactionService.editOriginal(messageToSend, model.getEvent().getHook()).thenAccept(message -> {
|
||||
gameService.updateMineBoard(mineBoard);
|
||||
log.info("Updated original mineboard for board {}.", mineBoard.getBoardId());
|
||||
});
|
||||
return ButtonClickedListenerResult.ACKNOWLEDGED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return EntertainmentFeatureDefinition.GAMES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return model.getOrigin().equals(GameServiceBean.MINES_BUTTON_ORIGIN);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import java.util.Optional;
|
||||
@Repository
|
||||
public interface EconomyUserRepository extends JpaRepository<EconomyUser, Long> {
|
||||
Optional<EconomyUser> findByUser(AUserInAServer aUserInAServer);
|
||||
Optional<EconomyUser> findByServer_IdAndUser_UserReference_Id(Long serverId, Long userId);
|
||||
|
||||
@Query(value = "WITH economy_user_ranked AS" +
|
||||
"( " +
|
||||
|
||||
@@ -9,8 +9,6 @@ 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;
|
||||
@@ -19,14 +17,8 @@ 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 {
|
||||
|
||||
@@ -70,42 +62,6 @@ public class EconomyServiceBean implements EconomyService {
|
||||
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);
|
||||
@@ -137,11 +93,6 @@ public class EconomyServiceBean implements EconomyService {
|
||||
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())
|
||||
@@ -160,17 +111,12 @@ public class EconomyServiceBean implements EconomyService {
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
package dev.sheldan.abstracto.entertainment.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadService;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentService;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.entertainment.exception.InvalidGameBoardException;
|
||||
import dev.sheldan.abstracto.entertainment.model.command.games.MineBoard;
|
||||
import dev.sheldan.abstracto.entertainment.model.command.games.MineBoardField;
|
||||
import dev.sheldan.abstracto.entertainment.model.command.games.MineBoardPayload;
|
||||
import dev.sheldan.abstracto.entertainment.model.command.games.MineBoardRow;
|
||||
import dev.sheldan.abstracto.entertainment.model.database.EconomyUser;
|
||||
import dev.sheldan.abstracto.entertainment.service.management.EconomyUserManagementService;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.sheldan.abstracto.entertainment.config.GamesFeatureConfig.MINES_CREDITS_FACTOR;
|
||||
import static dev.sheldan.abstracto.entertainment.config.GamesFeatureConfig.MINES_MINIMUM_MINES_RATIO;
|
||||
|
||||
@Component
|
||||
public class GameServiceBean implements GameService {
|
||||
|
||||
public static final String MINES_BUTTON_ORIGIN = "MINES_BUTTON";
|
||||
@Autowired
|
||||
private SecureRandom secureRandom;
|
||||
|
||||
@Autowired
|
||||
private ComponentService componentService;
|
||||
|
||||
@Autowired
|
||||
private ComponentPayloadService componentPayloadService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private EconomyService economyService;
|
||||
|
||||
@Autowired
|
||||
private EconomyUserManagementService economyUserManagementService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Override
|
||||
public MineBoard createBoard(Integer width, Integer height, Integer mines, Long serverId) {
|
||||
double minMinesRatio = configService.getDoubleValueOrConfigDefault(MINES_MINIMUM_MINES_RATIO, serverId);
|
||||
if(mines >= width * height || width > 5 || height > 5 || mines <= 1 || height <= 1 || width <= 1) {
|
||||
throw new InvalidGameBoardException(minMinesRatio);
|
||||
}
|
||||
if((double) mines / (width * height) < minMinesRatio) {
|
||||
throw new InvalidGameBoardException(minMinesRatio);
|
||||
}
|
||||
MineBoard mineBoard = generateEmptyBoard(width, height);
|
||||
mineBoard.setMineCount(mines);
|
||||
fillWithMines(mineBoard);
|
||||
evaluateCounters(mineBoard);
|
||||
|
||||
return mineBoard;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void persistMineBoardMessage(MineBoard mineBoard, Message message) {
|
||||
mineBoard.setMessageId(message.getIdLong());
|
||||
mineBoard.setChannelId(message.getChannel().getIdLong());
|
||||
AServer server = serverManagementService.loadServer(message.getGuild());
|
||||
mineBoard.getFields().forEach(mineBoardField -> {
|
||||
MineBoardPayload payload = MineBoardPayload
|
||||
.builder()
|
||||
.x(mineBoardField.getX())
|
||||
.y(mineBoardField.getY())
|
||||
.mineBoard(mineBoard)
|
||||
.build();
|
||||
String componentId = mineBoard.getBoardId() + "_" + mineBoardField.getX() + "_" + mineBoardField.getY();
|
||||
componentPayloadService.createButtonPayload(componentId, payload, MINES_BUTTON_ORIGIN, server);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateMineBoard(MineBoard mineBoard) {
|
||||
mineBoard.getFields().forEach(mineBoardField -> {
|
||||
MineBoardPayload newPayload = MineBoardPayload
|
||||
.builder()
|
||||
.x(mineBoardField.getX())
|
||||
.y(mineBoardField.getY())
|
||||
.mineBoard(mineBoard)
|
||||
.build();
|
||||
String componentId = mineBoard.getBoardId() + "_" + mineBoardField.getX() + "_" + mineBoardField.getY();
|
||||
componentPayloadService.updateButtonPayload(componentId, newPayload);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncoverBoard(MineBoard mineBoard) {
|
||||
mineBoard.getFields().forEach(mineBoardField -> {
|
||||
if(mineBoardField.getType().equals(MineBoardField.MineBoardFieldType.COVERED)) {
|
||||
mineBoardField.setType(MineBoardField.MineBoardFieldType.UNCOVERED);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluateCreditChanges(MineBoard mineBoard) {
|
||||
Long credits = mineBoard.getCredits().longValue();
|
||||
Integer mineCount = mineBoard.getMineCount();
|
||||
List<MineBoardField> allFields = mineBoard.getFields();
|
||||
Integer leftFields = (int) allFields
|
||||
.stream()
|
||||
.filter(mineBoardField -> mineBoardField.getType().equals(MineBoardField.MineBoardFieldType.COVERED)
|
||||
|| mineBoardField.getType().equals(MineBoardField.MineBoardFieldType.MINE))
|
||||
.count();
|
||||
Integer fieldCount = allFields.size();
|
||||
Integer uncoveredFields = fieldCount - leftFields;
|
||||
Long creditChange = (long) (calculateCreditFactor(fieldCount, mineCount, uncoveredFields) * credits);
|
||||
if(mineBoard.getState().equals(MineResult.WON)) {
|
||||
Double factor = configService.getDoubleValueOrConfigDefault(MINES_CREDITS_FACTOR, mineBoard.getServerId());
|
||||
creditChange = (long) (creditChange * factor);
|
||||
}
|
||||
ServerUser serverUser = ServerUser
|
||||
.builder()
|
||||
.serverId(mineBoard.getServerId())
|
||||
.userId(mineBoard.getUserId())
|
||||
.build();
|
||||
Optional<EconomyUser> economyUserOptional = economyUserManagementService.getUser(serverUser);
|
||||
if(economyUserOptional.isPresent()) {
|
||||
economyService.addCredits(economyUserOptional.get(), -credits);
|
||||
economyService.addCredits(economyUserOptional.get(), creditChange);
|
||||
}
|
||||
mineBoard.setCreditChange(creditChange);
|
||||
}
|
||||
|
||||
private double calculateCreditFactor(int totalFields, int mines, int uncovered) {
|
||||
return ((double) uncovered / (totalFields - mines)) + totalFields / 25.0 - ((totalFields - mines) / 25.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MineResult uncoverField(MineBoard board, Integer x, Integer y) {
|
||||
return uncoverFieldOnBoard(board, x, y);
|
||||
}
|
||||
|
||||
public GameService.MineResult uncoverFieldOnBoard(MineBoard board, Integer x, Integer y) {
|
||||
MineBoardField field = board.getField(x, y);
|
||||
if(!MineBoardField.canInteract(field.getType())) {
|
||||
return GameService.MineResult.CONTINUE;
|
||||
}
|
||||
if(field.getType().equals(MineBoardField.MineBoardFieldType.MINE)) {
|
||||
field.setType(MineBoardField.MineBoardFieldType.EXPLODED);
|
||||
return GameService.MineResult.LOST;
|
||||
}
|
||||
if(field.getType().equals(MineBoardField.MineBoardFieldType.COVERED)) {
|
||||
if(field.getCounterValue() == 0) {
|
||||
Set<String> alreadyConsidered = new HashSet<>();
|
||||
Queue<MineBoardField> toUncover = new LinkedList<>();
|
||||
toUncover.add(field);
|
||||
while(!toUncover.isEmpty()) {
|
||||
MineBoardField fieldToHandle = toUncover.poll();
|
||||
fieldToHandle.setType(MineBoardField.MineBoardFieldType.UNCOVERED);
|
||||
alreadyConsidered.add(fieldToHandle.getX() + "_" + fieldToHandle.getY());
|
||||
// only when we actually got a free field, we should add its neighbors to the next one to uncover
|
||||
if(fieldToHandle.getCounterValue() == 0) {
|
||||
List<MineBoardField> neighbors = getNeighbors(board, fieldToHandle.getX(), fieldToHandle.getY(), false);
|
||||
List<MineBoardField> uncoverableNeighbors = neighbors
|
||||
.stream().filter(mineBoardField -> mineBoardField.getType().equals(MineBoardField.MineBoardFieldType.COVERED))
|
||||
.collect(Collectors.toList());
|
||||
uncoverableNeighbors.forEach(mineBoardField -> {
|
||||
if(!alreadyConsidered.contains(mineBoardField.getX() + "_" + mineBoardField.getY())) {
|
||||
mineBoardField.setType(MineBoardField.MineBoardFieldType.UNCOVERED);
|
||||
// only if t he newly found neighbor is a free field, we should discover its neighbors
|
||||
if(mineBoardField.getCounterValue() == 0) {
|
||||
toUncover.addAll(uncoverableNeighbors);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
field.setType(MineBoardField.MineBoardFieldType.UNCOVERED);
|
||||
}
|
||||
if(hasWon(board)) {
|
||||
return GameService.MineResult.WON;
|
||||
}
|
||||
return GameService.MineResult.CONTINUE;
|
||||
}
|
||||
throw new IllegalStateException("Did not find correct type of field.");
|
||||
}
|
||||
|
||||
private List<MineBoardField> getNeighbors(MineBoard mineBoard, int xPosition, int yPosition) {
|
||||
return getNeighbors(mineBoard, xPosition, yPosition, false);
|
||||
}
|
||||
|
||||
private List<MineBoardField> getNeighbors(MineBoard board, int xPosition, int yPosition, boolean directOnly) {
|
||||
List<MineBoardField> neighbors = new ArrayList<>();
|
||||
boolean isFirstRow = yPosition == 0;
|
||||
boolean isLastRow = yPosition == board.getRowCount() - 1;
|
||||
boolean isFirstColumn = xPosition == 0;
|
||||
boolean isLastColumn = xPosition == board.getColumnCount() - 1;
|
||||
if(!isFirstColumn) {
|
||||
if(!isFirstRow && !directOnly) {
|
||||
neighbors.add(board.getField(xPosition - 1, yPosition - 1));
|
||||
}
|
||||
neighbors.add(board.getField(xPosition - 1, yPosition));
|
||||
if(!isLastRow && !directOnly) {
|
||||
neighbors.add(board.getField(xPosition - 1, yPosition + 1));
|
||||
}
|
||||
}
|
||||
if(!isFirstRow && !directOnly) {
|
||||
neighbors.add(board.getField(xPosition, yPosition - 1));
|
||||
}
|
||||
if(!isLastRow && !directOnly) {
|
||||
neighbors.add(board.getField(xPosition, yPosition + 1));
|
||||
}
|
||||
if(!isLastColumn) {
|
||||
if(!isFirstRow && !directOnly) {
|
||||
neighbors.add(board.getField(xPosition + 1, yPosition - 1));
|
||||
}
|
||||
neighbors.add(board.getField(xPosition + 1, yPosition));
|
||||
if(!isLastRow && !directOnly) {
|
||||
neighbors.add(board.getField(xPosition + 1, yPosition + 1));
|
||||
}
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
|
||||
public MineBoard generateEmptyBoard(Integer width, Integer height) {
|
||||
List<MineBoardRow> rows = new ArrayList<>();
|
||||
for (int y = 0; y < height; y++) {
|
||||
List<MineBoardField> fields = new ArrayList<>();
|
||||
for (int x = 0; x < width; x++) {
|
||||
MineBoardField field = MineBoardField
|
||||
.builder()
|
||||
.y(y)
|
||||
.x(x)
|
||||
.counterValue(0)
|
||||
.type(MineBoardField.MineBoardFieldType.COVERED)
|
||||
.build();
|
||||
fields.add(field);
|
||||
}
|
||||
MineBoardRow row = MineBoardRow
|
||||
.builder()
|
||||
.fields(fields)
|
||||
.build();
|
||||
rows.add(row);
|
||||
}
|
||||
return MineBoard
|
||||
.builder()
|
||||
.rows(rows)
|
||||
.state(MineResult.CONTINUE)
|
||||
.columnCount(width)
|
||||
.creditChange(0L)
|
||||
.rowCount(height)
|
||||
.boardId(UUID.randomUUID().toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
public void fillWithMines(MineBoard board) {
|
||||
Set<String> usedKeys = new HashSet<>();
|
||||
int maxIterations = 1_0000_000;
|
||||
int iterations = 0;
|
||||
List<Pair<Integer, Integer>> foundPositions = new ArrayList<>();
|
||||
do {
|
||||
int x = secureRandom.nextInt(board.getColumnCount());
|
||||
int y = secureRandom.nextInt(board.getRowCount());
|
||||
String positionKey = x + "_" + y;
|
||||
if(!usedKeys.contains(positionKey)) {
|
||||
foundPositions.add(Pair.of(x, y));
|
||||
usedKeys.add(positionKey);
|
||||
iterations = 0;
|
||||
}
|
||||
iterations++;
|
||||
} while(foundPositions.size() < board.getMineCount() && iterations < maxIterations);
|
||||
foundPositions.forEach(xYPair -> board.getRows().get(xYPair.getRight()).getFields().get(xYPair.getLeft()).setType(MineBoardField.MineBoardFieldType.MINE));
|
||||
}
|
||||
|
||||
public void evaluateCounters(MineBoard board) {
|
||||
board.getRows().forEach(mineBoardRow -> mineBoardRow.getFields().forEach(mineBoardField -> {
|
||||
if(!mineBoardField.getType().equals(MineBoardField.MineBoardFieldType.MINE)) {
|
||||
long mineCounts = getMineCounts(board, mineBoardField.getX(), mineBoardField.getY());
|
||||
mineBoardField.setCounterValue((int) mineCounts);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private long getMineCounts(MineBoard board, int xPosition, int yPosition) {
|
||||
List<MineBoardField> neighbors = getNeighbors(board, xPosition, yPosition);
|
||||
return neighbors
|
||||
.stream()
|
||||
.filter(mineBoardField -> mineBoardField.getType().equals(MineBoardField.MineBoardFieldType.MINE))
|
||||
.count();
|
||||
}
|
||||
|
||||
private boolean hasWon(MineBoard board) {
|
||||
return board
|
||||
.getFields()
|
||||
.stream()
|
||||
.noneMatch(mineBoardField ->
|
||||
mineBoardField.getType().equals(MineBoardField.MineBoardFieldType.COVERED)
|
||||
&& !mineBoardField.getType().equals(MineBoardField.MineBoardFieldType.MINE));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.entertainment.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.entertainment.model.database.EconomyLeaderboardResult;
|
||||
@@ -26,8 +27,6 @@ public class EconomyUserManagementServiceBean implements EconomyUserManagementSe
|
||||
.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();
|
||||
@@ -39,6 +38,11 @@ public class EconomyUserManagementServiceBean implements EconomyUserManagementSe
|
||||
return repository.findByUser(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<EconomyUser> getUser(ServerUser serverUser) {
|
||||
return repository.findByServer_IdAndUser_UserReference_Id(serverUser.getServerId(), serverUser.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyLeaderboardResult getRankOfUserInServer(AUserInAServer aUserInAServer) {
|
||||
return repository.getRankOfUserInServer(aUserInAServer.getUserInServerId(), aUserInAServer.getServerReference().getId());
|
||||
|
||||
@@ -10,16 +10,18 @@ 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
|
||||
|
||||
abstracto.featureFlags.games.featureName=games
|
||||
abstracto.featureFlags.games.enabled=false
|
||||
|
||||
abstracto.systemConfigs.minesCreditsFactor.name=minesCreditsFactor
|
||||
abstracto.systemConfigs.minesCreditsFactor.doubleValue=5
|
||||
|
||||
abstracto.systemConfigs.minesMinMineRatio.name=minesMinMineRatio
|
||||
abstracto.systemConfigs.minesMinMineRatio.doubleValue=0.2
|
||||
|
||||
# for now this is fine
|
||||
abstracto.systemConfigs.creditGambleJackpot.name=creditGambleJackpot
|
||||
abstracto.systemConfigs.creditGambleJackpot.longValue=1000
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<property name="entertainmentModule" value="(SELECT id FROM module WHERE name = 'entertainment')"/>
|
||||
<property name="gamesFeature" value="(SELECT id FROM feature WHERE key = 'games')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="mines-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="mines"/>
|
||||
<column name="module_id" valueComputed="${entertainmentModule}"/>
|
||||
<column name="feature_id" valueComputed="${gamesFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -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>
|
||||
@@ -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="games_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="games"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -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="system_config.xml" relativeToChangelogFile="true"/>
|
||||
<include file="economy_user.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?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-delete-cooldown-columns">
|
||||
<dropColumn tableName="economy_user">
|
||||
<column name="last_pay_day" />
|
||||
<column name="last_slots" />
|
||||
</dropColumn>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -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" >
|
||||
|
||||
<changeSet author="Sheldan" id="economy_cooldown-system-config-deletions">
|
||||
<delete tableName="system_config">
|
||||
<where>name='paydayCooldown'</where>
|
||||
</delete>
|
||||
<delete tableName="system_config">
|
||||
<where>name='slotsCooldown'</where>
|
||||
</delete>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="cleanup/deletions.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -11,4 +11,6 @@
|
||||
<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"/>
|
||||
<include file="1.4.11/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.5.8/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ import java.util.List;
|
||||
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() {
|
||||
@@ -21,6 +19,6 @@ public class EconomyFeatureConfig implements FeatureConfig {
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
return Arrays.asList(PAYDAY_CREDITS_CONFIG_KEY, PAYDAY_COOLDOWN_CONFIG_KEY, SLOTS_COOLDOWN_CONFIG_KEY);
|
||||
return Arrays.asList(PAYDAY_CREDITS_CONFIG_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum EntertainmentFeatureDefinition implements FeatureDefinition {
|
||||
ENTERTAINMENT("entertainment"), ECONOMY("economy");
|
||||
ENTERTAINMENT("entertainment"), ECONOMY("economy"), GAMES("games");
|
||||
|
||||
private String key;
|
||||
|
||||
|
||||
@@ -4,4 +4,5 @@ public class EntertainmentSlashCommandNames {
|
||||
public static final String ENTERTAINMENT = "entertainment";
|
||||
public static final String UTILITY = "utility";
|
||||
public static final String ECONOMY = "economy";
|
||||
public static final String GAME = "game";
|
||||
}
|
||||
|
||||
@@ -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 GamesFeatureConfig implements FeatureConfig {
|
||||
|
||||
public static final String MINES_CREDITS_FACTOR = "minesCreditsFactor";
|
||||
public static final String MINES_MINIMUM_MINES_RATIO = "minesMinMineRatio";
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return EntertainmentFeatureDefinition.GAMES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
return Arrays.asList(MINES_CREDITS_FACTOR, MINES_MINIMUM_MINES_RATIO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.sheldan.abstracto.entertainment.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
import dev.sheldan.abstracto.entertainment.model.exception.InvalidGameBoardExceptionModel;
|
||||
|
||||
public class InvalidGameBoardException extends AbstractoTemplatableException {
|
||||
|
||||
private final InvalidGameBoardExceptionModel model;
|
||||
|
||||
public InvalidGameBoardException(Double minRatio) {
|
||||
super();
|
||||
this.model = InvalidGameBoardExceptionModel
|
||||
.builder()
|
||||
.minMinesRatio(minRatio)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "invalid_mine_board_config_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.sheldan.abstracto.entertainment.model.command.games;
|
||||
|
||||
import dev.sheldan.abstracto.entertainment.service.GameService;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class MineBoard {
|
||||
private String boardId;
|
||||
private Long userId;
|
||||
private Long serverId;
|
||||
private Long messageId;
|
||||
private Long channelId;
|
||||
private Integer rowCount;
|
||||
private Integer columnCount;
|
||||
private Integer credits;
|
||||
private Long creditChange;
|
||||
private boolean creditsEnabled;
|
||||
private Integer mineCount;
|
||||
private List<MineBoardRow> rows;
|
||||
private GameService.MineResult state;
|
||||
|
||||
public MineBoardField getField(int x, int y) {
|
||||
if(x > columnCount || y > rowCount) {
|
||||
throw new IllegalArgumentException("Out of bounds access to board.");
|
||||
}
|
||||
MineBoardRow mineBoardRow = rows.get(y);
|
||||
return mineBoardRow.getFields().get(x);
|
||||
}
|
||||
|
||||
public List<MineBoardField> getFields() {
|
||||
List<MineBoardField> fields = new ArrayList<>();
|
||||
rows.forEach(mineBoardRow -> fields.addAll(mineBoardRow.getFields()));
|
||||
return fields;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package dev.sheldan.abstracto.entertainment.model.command.games;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@Setter
|
||||
public class MineBoardField {
|
||||
private MineBoardField.MineBoardFieldType type;
|
||||
private Integer x;
|
||||
private Integer y;
|
||||
private Integer counterValue;
|
||||
|
||||
public enum MineBoardFieldType {
|
||||
MINE, UNCOVERED, COVERED, EXPLODED
|
||||
}
|
||||
|
||||
public static boolean canInteract(MineBoardFieldType currentType) {
|
||||
return currentType != MineBoardFieldType.UNCOVERED && currentType != MineBoardFieldType.EXPLODED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.entertainment.model.command.games;
|
||||
|
||||
import dev.sheldan.abstracto.core.interaction.button.ButtonPayload;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@Setter
|
||||
public class MineBoardPayload implements ButtonPayload {
|
||||
private MineBoard mineBoard;
|
||||
private Integer x;
|
||||
private Integer y;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.sheldan.abstracto.entertainment.model.command.games;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class MineBoardRow {
|
||||
private List<MineBoardField> fields;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
@@ -33,12 +33,6 @@ public class EconomyUser implements Serializable {
|
||||
@Column(name = "credits", nullable = false)
|
||||
private Long credits;
|
||||
|
||||
@Column(name = "last_slots", nullable = false)
|
||||
private Instant lastSlots;
|
||||
|
||||
@Column(name = "last_pay_day", nullable = false)
|
||||
private Instant lastPayDay;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
|
||||
@@ -3,10 +3,8 @@ package dev.sheldan.abstracto.entertainment.model.exception;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class SlotsCooldownExceptionModel {
|
||||
private Duration tryAgainDuration;
|
||||
@Builder
|
||||
public class InvalidGameBoardExceptionModel {
|
||||
private Double minMinesRatio;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package dev.sheldan.abstracto.entertainment.model.exception;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class PayDayCooldownExceptionModel {
|
||||
private Duration tryAgainDuration;
|
||||
}
|
||||
@@ -10,16 +10,9 @@ import dev.sheldan.abstracto.entertainment.model.database.EconomyUser;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
public interface EconomyService {
|
||||
boolean canTriggerPayDay(AUserInAServer aUserInAServer);
|
||||
boolean canTriggerSlots(AUserInAServer aUserInAServer);
|
||||
boolean canTriggerPayDay(EconomyUser economyUser);
|
||||
boolean canTriggerSlots(EconomyUser economyUser);
|
||||
Duration payDayTriggerIn(EconomyUser economyUser);
|
||||
Duration slotsTriggerIn(EconomyUser economyUser);
|
||||
EconomyUser addCredits(AUserInAServer aUserInAServer, Long credits);
|
||||
void addCredits(EconomyUser economyUser, Long credits);
|
||||
void addPayDayCredits(AUserInAServer aUserInAServer);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.abstracto.entertainment.service;
|
||||
|
||||
import dev.sheldan.abstracto.entertainment.model.command.games.MineBoard;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
|
||||
public interface GameService {
|
||||
MineBoard createBoard(Integer width, Integer height, Integer mines, Long serverId);
|
||||
void persistMineBoardMessage(MineBoard mineBoard, Message message);
|
||||
void updateMineBoard(MineBoard mineBoard);
|
||||
void uncoverBoard(MineBoard mineBoard);
|
||||
void evaluateCreditChanges(MineBoard mineBoard);
|
||||
MineResult uncoverField(MineBoard board, Integer x, Integer y);
|
||||
|
||||
|
||||
enum MineResult {
|
||||
WON, LOST, CONTINUE
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.entertainment.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.entertainment.model.database.EconomyLeaderboardResult;
|
||||
@@ -11,6 +12,7 @@ import java.util.Optional;
|
||||
public interface EconomyUserManagementService {
|
||||
EconomyUser createUser(AUserInAServer aUserInAServer);
|
||||
Optional<EconomyUser> getUser(AUserInAServer aUserInAServer);
|
||||
Optional<EconomyUser> getUser(ServerUser serverUser);
|
||||
EconomyLeaderboardResult getRankOfUserInServer(AUserInAServer aUserInAServer);
|
||||
List<EconomyUser> getRanksInServer(AServer server, Integer page, Integer size);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.4.9</version>
|
||||
<version>1.5.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package dev.sheldan.abstracto.experience.command;
|
||||
|
||||
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.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceSlashCommandNames;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
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 ExpLevelUpNotification extends AbstractConditionableCommand {
|
||||
|
||||
private static final String FLAG_PARAMETER = "newValue";
|
||||
private static final String EXP_LEVEL_UP_NOTIFICATION_COMMAND = "expLevelUpNotification";
|
||||
private static final String EXP_LEVEL_UP_NOTIFICATION_RESPONSE = "expLevelUpNotification_response";
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private AUserExperienceService aUserExperienceService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
Boolean newValue = (Boolean) commandContext.getParameters().getParameters().get(0);
|
||||
updateExpLevelNotification(commandContext.getAuthor(), newValue);
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Boolean newValue = slashCommandParameterService.getCommandOption(FLAG_PARAMETER, event, Boolean.class);
|
||||
updateExpLevelNotification(event.getMember(), newValue);
|
||||
return interactionService.replyEmbed(EXP_LEVEL_UP_NOTIFICATION_RESPONSE, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
private void updateExpLevelNotification(Member member, Boolean newValue) {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
|
||||
aUserExperienceService.setLevelUpNotification(aUserInAServer, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ExperienceFeatureDefinition.EXPERIENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter memberParameter = Parameter
|
||||
.builder()
|
||||
.name(FLAG_PARAMETER)
|
||||
.templated(true)
|
||||
.type(Boolean.class)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(memberParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(ExperienceSlashCommandNames.EXPERIENCE)
|
||||
.commandName(EXP_LEVEL_UP_NOTIFICATION_COMMAND)
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(EXP_LEVEL_UP_NOTIFICATION_COMMAND)
|
||||
.module(ExperienceModuleDefinition.EXPERIENCE)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.causesReaction(true)
|
||||
.supportsEmbedException(true)
|
||||
.templated(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,17 @@ public class Rank extends AbstractConditionableCommand {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(toRender);
|
||||
AUserExperience experienceObj = userExperienceManagementService.findUserInServer(aUserInAServer);
|
||||
log.info("Rendering rank for user {} in server {}.", toRender.getId(), toRender.getGuild().getId());
|
||||
rankModel.setExperienceToNextLevel(experienceLevelService.calculateExperienceToNextLevel(experienceObj.getCurrentLevel().getLevel(), experienceObj.getExperience()));
|
||||
Long currentExpNeeded = experienceObj.getCurrentLevel().getExperienceNeeded();
|
||||
Long experienceNeededToNextLevel = experienceLevelService.calculateExperienceToNextLevel(experienceObj.getCurrentLevel().getLevel(), experienceObj.getExperience());
|
||||
Long nextLevelExperience = experienceLevelService.calculateNextLevel(experienceObj.getCurrentLevel().getLevel()).getExperienceNeeded();
|
||||
Long levelExperience = nextLevelExperience - currentExpNeeded;
|
||||
Long inLevelExperience = experienceObj.getExperience() - currentExpNeeded;
|
||||
rankModel.setExperienceForCurrentLevel(currentExpNeeded);
|
||||
rankModel.setCurrentLevelPercentage(((float) inLevelExperience / levelExperience) * 100);
|
||||
rankModel.setLevelExperience(levelExperience);
|
||||
rankModel.setExperienceToNextLevel(experienceNeededToNextLevel);
|
||||
rankModel.setInLevelExperience(inLevelExperience);
|
||||
rankModel.setNextLevelExperience(nextLevelExperience);
|
||||
return templateService.renderEmbedTemplate(RANK_POST_EMBED_TEMPLATE, rankModel, toRender.getGuild().getIdLong());
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ public class SetExpRole extends AbstractConditionableCommand {
|
||||
.module(ExperienceModuleDefinition.EXPERIENCE)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.messageCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.requiresConfirmation(true)
|
||||
|
||||
@@ -46,7 +46,10 @@ public class SyncRoles extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("syncExpRoles")
|
||||
.module(ExperienceModuleDefinition.EXPERIENCE)
|
||||
@@ -54,6 +57,7 @@ public class SyncRoles extends AbstractConditionableCommand {
|
||||
.async(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.messageCommandOnly(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -59,13 +59,20 @@ public class UnSetExpRole extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("role").templated(true).type(ARole.class).build());
|
||||
Parameter roleParameter = Parameter
|
||||
.builder()
|
||||
.name("role")
|
||||
.templated(true)
|
||||
.type(ARole.class)
|
||||
.build();
|
||||
parameters.add(roleParameter);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("unSetExpRole")
|
||||
.module(ExperienceModuleDefinition.EXPERIENCE)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.messageCommandOnly(true)
|
||||
.causesReaction(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user