Compare commits

105 Commits

Author SHA1 Message Date
2e5979e6e4 Merge pull request 'migrate to slf4j' (#18) from migrate/slf4j into dev
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 1m45s
Publish / Gradle-Publish (push) Successful in 1m32s
Test / Gradle-Test (push) Successful in 1m38s
Reviewed-on: #18
2025-03-17 19:34:26 +00:00
ab1eb74e85 fix(logging) implement getQualifiedCallerName
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 35s
Test / Gradle-Test (push) Successful in 48s
2025-03-17 14:36:43 +01:00
a5737b9eaa feat(logging): add Fallback logging
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 31s
Test / Gradle-Test (push) Successful in 47s
2025-03-17 14:13:21 +01:00
faca21724c fix(logging): fix wrong getClass method. 2025-03-17 14:13:00 +01:00
4c5e28b679 feat(logging): replace log4j dependency with slf4j and replace imports
All checks were successful
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 38s
Test / Gradle-Test (push) Successful in 51s
2025-03-17 10:52:24 +01:00
33f355e6ea Merge pull request 'improve wrapper and general structure' (#16) from improve/structure into dev
All checks were successful
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 36s
Publish / Gradle-Publish (push) Successful in 32s
Test / Gradle-Test (push) Successful in 48s
Reviewed-on: #16
No new features
2025-03-17 08:26:43 +00:00
d32ac62b4a fix(autocomplete): fix autocomplete using component context objects
All checks were successful
github-mirror / push-github (push) Successful in 1m46s
Build / Gradle-Build (push) Successful in 31s
Test / Gradle-Test (push) Successful in 59s
2025-03-17 08:37:11 +01:00
e7c35d9308 refactor(core): remove redundant distinct method and its uses
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 32s
Test / Gradle-Test (push) Successful in 46s
2025-03-17 00:16:26 +01:00
d4a91f3251 fix(core): fix wrong equality method and refactor a bit 2025-03-17 00:15:10 +01:00
bce4ce7812 fix(wrapper): add condition for CommandRegisterer if api is null 2025-03-16 23:35:39 +01:00
bae077654e refactor(Discord4J): implement CommandRegisterer refactor
Some checks failed
github-mirror / push-github (push) Successful in 1m44s
Build / Gradle-Build (push) Successful in 55s
Test / Gradle-Test (push) Failing after 41s
2025-03-16 17:16:26 +01:00
203498de68 refactor(javacord): implement CommandRegisterer refactor 2025-03-16 17:07:14 +01:00
24df1731da refactor(command): add CommandRegisterer 2025-03-16 17:06:37 +01:00
e3fc10a1ce fix(util): ObjectListAggregator syntax 2025-03-16 02:48:24 +01:00
78cacb7eb6 feat(util): add ObjectListAggregator 2025-03-16 02:47:16 +01:00
7287d44645 refactor(util): add multiple key support to ObjectAggregator 2025-03-16 02:46:55 +01:00
630c8ddee5 feat(register): add convenience getter 2025-03-16 01:49:24 +01:00
4e27e6ce56 feat(struct): introduce ObjectAggregator 2025-03-16 01:36:23 +01:00
432cf78a2e add IdentifierProvider and wrapper implementations
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 33s
Test / Gradle-Test (push) Successful in 48s
2025-03-05 21:44:12 +01:00
f940f48566 move CommandConverter to wrapper package
All checks were successful
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 31s
Test / Gradle-Test (push) Successful in 46s
2025-03-04 11:16:44 +01:00
f4ee258eb1 remove missing parent() call in SlashCommandDefinition#getSubCommands()
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 53s
Test / Gradle-Test (push) Successful in 52s
2025-03-03 23:40:06 +01:00
56b668851b add CommandConverter logic and wrapper implementations
All checks were successful
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 37s
Test / Gradle-Test (push) Successful in 48s
2025-03-03 23:32:25 +01:00
823402e0cd fix base getSubCommands method 2025-03-03 23:32:07 +01:00
91b1df8d5b replace ExecutableCommandDefinition with InteractionIdentifiers
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 42s
Test / Gradle-Test (push) Successful in 45s
2025-03-03 12:42:04 +01:00
76d7e9ef4f Merge branch 'dev' into improve/structure
All checks were successful
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 1m20s
Test / Gradle-Test (push) Successful in 49s
2025-03-01 22:59:40 +00:00
236c584da8 move Choice classes
All checks were successful
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 10s
Test / Gradle-Test (push) Successful in 20s
2025-02-20 09:10:28 +01:00
f6db113deb add CommandConverter stub
All checks were successful
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 10s
Test / Gradle-Test (push) Successful in 21s
2025-02-20 00:41:15 +01:00
9058629af5 remove redundant getFullSlashCommand
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 11s
Test / Gradle-Test (push) Successful in 21s
2025-02-19 21:50:54 +01:00
8f14b0feb9 split up getSubCommands 2025-02-19 21:49:12 +01:00
3e02e7b85b Merge pull request 'Migrate to Mockito' (#15) from migrate/mockito into dev
All checks were successful
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 11s
Publish / Gradle-Publish (push) Successful in 11s
Test / Gradle-Test (push) Successful in 22s
Reviewed-on: #15
2025-02-19 19:22:39 +00:00
ba560cb909 remove deprecated manual mocks
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 10s
Test / Gradle-Test (push) Successful in 21s
2025-02-19 15:34:14 +01:00
6cdca411c6 migrate SlashCommandTest 2025-02-19 15:33:21 +01:00
3a39b268c1 migrate InteractionCheckTest 2025-02-19 14:39:48 +01:00
ca0ab13316 migrate ButtonTest to mockito
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 12s
Test / Gradle-Test (push) Successful in 21s
2025-02-19 14:10:45 +01:00
ded81983e3 migrate AutocompleteTest and add mockito ofc 2025-02-19 14:00:01 +01:00
92704ca230 add correct null handling for api objects 2025-02-19 13:56:45 +01:00
5d8f737481 Merge pull request 'add Discord4J Wrapper' (#14) from wrapper/d4j into dev
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 10s
Publish / Gradle-Publish (push) Successful in 11s
Test / Gradle-Test (push) Successful in 21s
Reviewed-on: #14
2025-02-19 12:43:38 +00:00
8943d6d4a4 add tests
All checks were successful
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 18s
Test / Gradle-Test (push) Successful in 21s
2025-02-19 10:50:30 +01:00
842fcfe5ac add PermissionCheck 2025-02-19 10:50:19 +01:00
858fab5e32 fix: Message ContextObject returning Optional 2025-02-19 09:02:52 +01:00
20471fefea fix: logging causing NullPointerException 2025-02-19 09:01:42 +01:00
8d27ec28db fix: remove Test Line, allow api to be null, fix getCommandDefinition to also allow ChatInputAutoCompleteEvent 2025-02-18 11:21:32 +01:00
f81602f5db restructure and add discord4j test stub
Some checks failed
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 9s
Test / Gradle-Test (push) Failing after 10s
2025-02-17 23:59:08 +01:00
dbad157058 adjust actions to add new wrapper
Some checks failed
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 9s
Test / Gradle-Test (push) Failing after 13s
2025-02-17 20:24:40 +01:00
ad19ed6ada add First prototype of Discord4J wrapper
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 21s
Test / Gradle-Test (push) Successful in 14s
2025-02-17 20:13:31 +01:00
ca822909e3 fix: consistency 2025-02-17 19:55:03 +01:00
caeaec1926 add: fromValue method to SlashCommandOptionType 2025-02-17 19:45:18 +01:00
f4dbdc302d fix: improve consistency 2025-02-17 19:44:52 +01:00
fd87431d51 Merge remote-tracking branch 'origin/dev' into wrapper/d4j 2025-02-17 13:06:27 +01:00
3b65784770 Merge pull request 'Add Choices and Autocomplete' (#8) from feat/choices into dev
All checks were successful
github-mirror / push-github (push) Successful in 30s
Build / Gradle-Build (push) Successful in 14s
Publish / Gradle-Publish (push) Successful in 10s
Test / Gradle-Test (push) Successful in 14s
Reviewed-on: #8
Double choices missing because PR will not get merged since Javacord seized development
2025-02-17 10:14:37 +00:00
b4af922ac2 change: getInteractionType check changed from class based to context based check
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 16s
Test / Gradle-Test (push) Successful in 14s
2025-02-17 09:15:54 +01:00
1146fa1cc6 Merge branch 'dev' into feat/choices
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 34s
Test / Gradle-Test (push) Successful in 41s
2024-12-20 19:30:35 +01:00
9d88ca902d fix NoSuchElement case on command with no options
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 35s
Publish / Gradle-Publish (push) Successful in 36s
Test / Gradle-Test (push) Successful in 43s
2024-12-20 19:27:36 +01:00
e9b5610f3c Merge pull request 'add Logging to various locations' (#11) from feat/logging into dev
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 37s
Publish / Gradle-Publish (push) Successful in 33s
Test / Gradle-Test (push) Successful in 40s
Reviewed-on: #11
2024-12-20 17:51:24 +00:00
8e872e7ada Merge branch 'dev' into feat/logging
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 32s
Test / Gradle-Test (push) Successful in 40s
2024-12-20 17:05:18 +01:00
43c5946227 Merge branch 'dev' into feat/choices
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 32s
Test / Gradle-Test (push) Successful in 40s
2024-12-20 17:04:13 +01:00
71c910ab93 fix equality check of ExecutableSlashCommand
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 32s
Publish / Gradle-Publish (push) Successful in 32s
Test / Gradle-Test (push) Successful in 39s
2024-12-20 17:03:35 +01:00
c5a7f3665e Merge branch 'dev' into feat/choices
All checks were successful
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 32s
Test / Gradle-Test (push) Successful in 40s
2024-12-20 14:56:35 +01:00
3baf1eda9a log the result of an InteractionCheck
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 32s
Test / Gradle-Test (push) Successful in 38s
2024-12-20 00:44:48 +01:00
628abb4239 fix order and wording
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 32s
Test / Gradle-Test (push) Successful in 42s
2024-12-20 00:32:20 +01:00
9a89544a9e Merge branch 'dev' into feat/logging
All checks were successful
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 31s
Test / Gradle-Test (push) Successful in 41s
2024-12-19 22:11:21 +01:00
455fc4955f fix ExecutableSlashCommandDefinition toString method with all various checks
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 33s
Publish / Gradle-Publish (push) Successful in 33s
Test / Gradle-Test (push) Successful in 39s
2024-12-19 22:11:06 +01:00
b72c55fc6e Merge branch 'dev' into feat/logging
Some checks failed
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 32s
Test / Gradle-Test (push) Failing after 39s
2024-12-19 21:23:48 +01:00
3691434f66 fix toString method of ExecutableSlashCommandDefinition and added subCommandGroup display
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 32s
Publish / Gradle-Publish (push) Successful in 33s
Test / Gradle-Test (push) Successful in 39s
2024-12-19 21:23:24 +01:00
74d55d81ca add remaining logging in Javacord wrapper and exceptions
Some checks failed
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 32s
Test / Gradle-Test (push) Failing after 41s
2024-12-19 21:12:36 +01:00
404f221ccf added Logging for InteractionChecks
Some checks failed
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 33s
Test / Gradle-Test (push) Failing after 40s
2024-12-19 21:07:42 +01:00
7249c99b69 add Logging to Parsers 2024-12-19 20:38:04 +01:00
b764972eba make use of new helper method in InteractionMethod 2024-12-19 20:15:22 +01:00
83ee4b1efa add method name helper method 2024-12-19 20:04:53 +01:00
6b86e9ff87 add initialization Logging 2024-12-19 19:41:49 +01:00
7a40aebd6d add Interactionmethod logging 2024-12-19 19:41:37 +01:00
76ab779ab2 fix position of Logging in InteractionRegistry
All checks were successful
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 35s
Test / Gradle-Test (push) Successful in 47s
2024-12-19 18:36:51 +01:00
3d19fae6b8 fix null issue in InteractionRegistry
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 33s
Test / Gradle-Test (push) Successful in 44s
2024-12-19 18:34:00 +01:00
1ecbc563a6 add Logging in InteractionRegistry
Some checks failed
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 34s
Test / Gradle-Test (push) Failing after 44s
2024-12-19 18:07:33 +01:00
bf0022775d add helper LoggerUtil method 2024-12-19 13:30:36 +01:00
a17f5e826f add LoggerUtil to decide which Logger to get
All checks were successful
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 35s
Test / Gradle-Test (push) Successful in 39s
2024-12-19 12:28:45 +01:00
3de0f32074 change to just javacord api dependency 2024-12-19 12:28:27 +01:00
aaf4f3297a add autocomplete option toggle, add double value for non javacord wrappers, rename OptionChoices to match with discords naming and general cleanup
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 31s
Test / Gradle-Test (push) Successful in 39s
2024-12-16 13:03:11 +01:00
445190db89 added Tests for choices 2024-12-16 12:49:51 +01:00
9d3a6b8b85 add Autocomplete Test
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 33s
Test / Gradle-Test (push) Successful in 39s
2024-12-15 23:15:37 +01:00
1cb6cd0e05 clean up code and switch to request instead of getting from cache 2024-12-15 23:15:29 +01:00
a5e1230fc6 fix issues with ExecutableSlashCommandDefinition equals check 2024-12-15 23:13:57 +01:00
432db43bf5 add remaining parts of AutocompleteInteraction
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 33s
Test / Gradle-Test (push) Successful in 40s
2024-12-15 15:09:09 +01:00
7a2c15d877 create seperate class for ContextObjectProviders and renamed some context parameters from parameter to context.
First parts of AutocompleteInteraction added
2024-12-15 15:08:34 +01:00
f32c7045a1 remove unnecessary getClass call fixing test
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 36s
Test / Gradle-Test (push) Successful in 40s
2024-12-14 12:32:03 +01:00
69b27e4554 add prototype choices implementation
Some checks failed
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 50s
Test / Gradle-Test (push) Failing after 41s
2024-12-13 10:50:30 +01:00
d8504a7cde Merge pull request 'add Checks system' (#6) from feat/checks into dev
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 11s
Publish / Gradle-Publish (push) Successful in 11s
Test / Gradle-Test (push) Successful in 16s
Reviewed-on: #6
2024-12-05 07:51:36 +00:00
bef34ee548 fix null issue
All checks were successful
github-mirror / push-github (push) Successful in 3s
Build / Gradle-Build (push) Successful in 12s
Test / Gradle-Test (push) Successful in 16s
2024-12-03 20:20:57 +01:00
29bb7e667e add PermissionCHeck test
Some checks failed
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 11s
Test / Gradle-Test (push) Failing after 16s
2024-12-02 21:21:00 +01:00
94da2a0e3c change logic to always give objects the highest value 2024-12-02 21:20:49 +01:00
7f47130461 add missing annotation annotations 2024-12-02 21:20:26 +01:00
83a3efd4b8 add canRun check which i forgor 2024-12-02 21:19:58 +01:00
aefd8a51a0 change wrong annotation class usage 2024-12-02 21:19:42 +01:00
4332592dfa add Javacord PermissionCheck
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 12s
Test / Gradle-Test (push) Successful in 17s
2024-12-02 13:16:28 +01:00
c363ab9744 add ability to return false to cancel execution in pre Checks and remove return type on post checks
All checks were successful
github-mirror / push-github (push) Successful in 7s
Build / Gradle-Build (push) Successful in 14s
Test / Gradle-Test (push) Successful in 21s
2024-12-01 13:06:42 +01:00
33392b02fb add InteractionCheck test
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 13s
Test / Gradle-Test (push) Successful in 15s
2024-11-29 21:41:46 +01:00
b7333c2e5e fix problem with multiple method overrides in generic types. 2024-11-29 21:41:18 +01:00
239e921e6f change Annotation#getClass to Annotation#annotationType because it was not working as expected 2024-11-29 21:37:13 +01:00
6eb7fb723f add geantyref to fix and simplify generic Type parsing.
Also switch to java 23 to avoid conflicts and issues.
2024-11-29 21:36:02 +01:00
659218682e add context Object to check methods and create the ability to have a specific method for each type of context or one for all by using the superclass and casting yourself
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 12s
Test / Gradle-Test (push) Successful in 17s
2024-11-29 18:17:33 +01:00
019ba8f552 add getMostSpecificMethod method to simplify Check method parsing.
This Method searches the The method that has the best matching parameters with the fewest inheritance levels as possible. Left sided priority
2024-11-29 18:15:47 +01:00
f89ae5e425 - add prototype Interactioncheck impementation.
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 12s
Test / Gradle-Test (push) Successful in 16s
- refactor dependency injection to have all widely used dependencies in the Marinara class.
2024-11-28 10:32:48 +01:00
582e0f0bae implement AnnotationParser system
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 13s
Test / Gradle-Test (push) Successful in 16s
2024-11-24 00:02:19 +01:00
0ea330d48b move to seperate files because gitea does not have expressions yet
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 9s
Publish / Gradle-Publish (push) Successful in 10s
Test / Gradle-Test (push) Successful in 13s
2024-11-20 12:01:47 +01:00
c241f6b1fe enable dev branch publishing
All checks were successful
github-mirror / push-github (push) Successful in 4s
Build / Gradle-Build (push) Successful in 17s
Publish / Gradle-Publish (push) Successful in 6s
Test / Gradle-Test (push) Successful in 13s
2024-11-20 11:52:41 +01:00
91 changed files with 3122 additions and 5758 deletions

View File

@@ -38,7 +38,10 @@ jobs:
run: chmod +x gradlew; ./gradlew assemble run: chmod +x gradlew; ./gradlew assemble
- name: Move artifacts - name: Move artifacts
run: mkdir artifacts; mv lib/build/libs/*.jar artifacts; mv wrapper/javacord/build/libs/*.jar artifacts; run: |
mkdir artifacts; mv lib/build/libs/*.jar artifacts;
mv wrapper/javacord/build/libs/*.jar artifacts;
mv wrapper/discord4j/build/libs/*.jar artifacts;
- name: Upload artifact - name: Upload artifact
uses: christopherhx/gitea-upload-artifact@v4 uses: christopherhx/gitea-upload-artifact@v4

View File

@@ -0,0 +1,40 @@
name: Publish
on:
push:
branches: [dev]
jobs:
Gradle-Publish:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '23'
check-latest: true
distribution: 'zulu'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
add-job-summary: always
cache-cleanup: on-success
- name: Cache Gradle dependencies
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Publish Dev
env:
GITEA_TOKEN: ${{ secrets.PUBLISH_PACKAGE_TOKEN }}
run: chmod +x gradlew; ./gradlew publishAllPublicationsToGiteaRepository

View File

@@ -1,11 +1,11 @@
name: Test name: Publish
on: on:
push: push:
branches: [master] branches: [master]
jobs: jobs:
Gradle-Test: Gradle-Publish:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -34,7 +34,7 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
- name: Publish - name: Publish Release
env: env:
GITEA_TOKEN: ${{ secrets.PUBLISH_PACKAGE_TOKEN }} GITEA_TOKEN: ${{ secrets.PUBLISH_PACKAGE_TOKEN }}
run: chmod +x gradlew; ./gradlew publishAllPublicationsToGiteaRepository run: chmod +x gradlew; ./gradlew publishAllPublicationsToGiteaRepository -Prelease

View File

@@ -44,6 +44,7 @@ jobs:
mkdir test-results/; mkdir test-results/;
[ -d lib/build/test-results/test/ ] && mv lib/build/test-results/test/*.xml test-results/; [ -d lib/build/test-results/test/ ] && mv lib/build/test-results/test/*.xml test-results/;
[ -d wrapper/javacord/build/test-results/test/ ] && mv wrapper/javacord/build/test-results/test/*.xml test-results/; [ -d wrapper/javacord/build/test-results/test/ ] && mv wrapper/javacord/build/test-results/test/*.xml test-results/;
[ -d wrapper/discord4j/build/test-results/test/ ] && mv wrapper/discord4j/build/test-results/test/*.xml test-results/;
- name: Upload Test Result - name: Upload Test Result
uses: christopherhx/gitea-upload-artifact@v4 uses: christopherhx/gitea-upload-artifact@v4

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ build
.vscode .vscode
lib/bin lib/bin
wrapper/javacord/bin wrapper/javacord/bin
wrapper/discord4j/bin

View File

@@ -8,6 +8,7 @@ allprojects {
group = "net.tomatentum.Marinara" group = "net.tomatentum.Marinara"
version = "1.0.0-RC1" + (if (!project.hasProperty("release")) ("-" + getGitHash()) else "") version = "1.0.0-RC1" + (if (!project.hasProperty("release")) ("-" + getGitHash()) else "")
description = "A simple but powerful, library-agnostic Discord Interaction Wrapper." description = "A simple but powerful, library-agnostic Discord Interaction Wrapper."
} }
subprojects { subprojects {
@@ -18,6 +19,8 @@ subprojects {
publishing { publishing {
publications { publications {
create<MavenPublication>("maven") { create<MavenPublication>("maven") {
if (!project.hasProperty("release"))
artifactId = project.getName() + "-dev"
from(components["java"]) from(components["java"])
} }
} }

View File

@@ -3,12 +3,16 @@
[versions] [versions]
junit-jupiter = "5.10.2" junit-jupiter = "5.10.2"
log4j = "2.24.1" slf4j = "2.0.17"
javacord = "3.8.0" javacord = "3.8.0"
discord4j = "3.2.7"
geantyref = "2.0.0" geantyref = "2.0.0"
mockito = "5.15.2"
[libraries] [libraries]
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" } junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
log4j = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j"} slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j"}
javacord = { module = "org.javacord:javacord", version.ref = "javacord"} javacord = { module = "org.javacord:javacord", version.ref = "javacord"}
discord4j = { module = "com.discord4j:discord4j-core", version.ref = "discord4j"}
geantyref = { module = "io.leangen.geantyref:geantyref", version.ref = "geantyref"} geantyref = { module = "io.leangen.geantyref:geantyref", version.ref = "geantyref"}
mockito = {module = "org.mockito:mockito-core", version.ref = "mockito"}

View File

@@ -20,14 +20,14 @@ dependencies {
testImplementation(libs.junit.jupiter) testImplementation(libs.junit.jupiter)
testRuntimeOnly("org.junit.platform:junit-platform-launcher") testRuntimeOnly("org.junit.platform:junit-platform-launcher")
implementation(libs.log4j) implementation(libs.slf4j)
implementation(libs.geantyref)
} }
// Apply a specific Java toolchain to ease working on different environments. // Apply a specific Java toolchain to ease working on different environments.
java { java {
toolchain { toolchain {
languageVersion = JavaLanguageVersion.of(21) languageVersion = JavaLanguageVersion.of(23)
} }
} }

View File

@@ -1,22 +1,40 @@
package net.tomatentum.marinara; package net.tomatentum.marinara;
import org.slf4j.Logger;
import net.tomatentum.marinara.registry.InteractionCheckRegistry;
import net.tomatentum.marinara.registry.InteractionRegistry; import net.tomatentum.marinara.registry.InteractionRegistry;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.LibraryWrapper;
public class Marinara { public class Marinara {
private Logger logger = LoggerUtil.getLogger(getClass());
public static <T extends LibraryWrapper> Marinara load(LibraryWrapper wrapper) { public static <T extends LibraryWrapper> Marinara load(LibraryWrapper wrapper) {
InteractionRegistry registry = new InteractionRegistry(wrapper); return new Marinara(wrapper);
return new Marinara(registry);
} }
private InteractionRegistry registry; private InteractionRegistry registry;
private InteractionCheckRegistry checkRegistry;
private LibraryWrapper wrapper;
private Marinara(InteractionRegistry registry) { private Marinara(LibraryWrapper wrapper) {
this.registry = registry; this.wrapper = wrapper;
this.registry = new InteractionRegistry(this);
this.checkRegistry = new InteractionCheckRegistry();
logger.info("Marinara loaded successfully!");
} }
public InteractionRegistry getRegistry() { public InteractionRegistry getRegistry() {
return registry; return registry;
} }
public InteractionCheckRegistry getCheckRegistry() {
return checkRegistry;
}
public LibraryWrapper getWrapper() {
return wrapper;
}
} }

View File

@@ -0,0 +1,50 @@
package net.tomatentum.marinara.checks;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.slf4j.Logger;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.util.ReflectionUtil;
public record AppliedCheck(InteractionCheck<?> check, Annotation annotation) {
private static Logger logger = LoggerUtil.getLogger(AppliedCheck.class);
public boolean pre(Object context) {
Method[] methods = Arrays.stream(check.getClass().getMethods())
.filter(x -> x.getName().equals("preExec"))
.filter(x -> !x.isBridge())
.toArray(s -> new Method[s]);
Method method = ReflectionUtil.getMostSpecificMethod(methods, context.getClass(), annotation.annotationType());
method.setAccessible(true);
try {
logger.debug("Executing pre check {} with context {}", check.getClass().getName(), context.toString());
boolean result = (boolean) method.invoke(check, context, annotation);
logger.debug("Pre Check {} {} with context {}", check.getClass().getName(), result ? "succeeded" : "failed", context.toString());
return result;
} catch (IllegalAccessException | InvocationTargetException | SecurityException e) {
logger.error("Failed executing pre-check", e);
return false;
}
}
public void post(Object context) {
Method[] methods = Arrays.stream(check.getClass().getMethods())
.filter(x -> x.getName().equals("postExec"))
.filter(x -> !x.isBridge())
.toArray(s -> new Method[s]);
Method method = ReflectionUtil.getMostSpecificMethod(methods, context.getClass(), annotation.annotationType());
method.setAccessible(true);
try {
logger.debug("Executing post check {} with context {}", check.getClass().getName(), context.toString());
method.invoke(check, context, annotation);
} catch (IllegalAccessException | InvocationTargetException | SecurityException e) {
logger.error("Failed executing post-check", e);
}
}
}

View File

@@ -0,0 +1,10 @@
package net.tomatentum.marinara.checks;
import java.lang.annotation.Annotation;
public interface InteractionCheck<A extends Annotation> {
public boolean preExec(Object context, A annotation);
public void postExec(Object context, A annotation);
}

View File

@@ -0,0 +1,12 @@
package net.tomatentum.marinara.interaction.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoComplete {
}

View File

@@ -1,70 +0,0 @@
package net.tomatentum.marinara.interaction.commands;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
public record ExecutableSlashCommandDefinition(
SlashCommand applicationCommand,
SubCommand subCommand,
SubCommandGroup subCommandGroup,
SlashCommandOption[] options) {
@Override
public final boolean equals(Object o) {
if (!(o instanceof ExecutableSlashCommandDefinition))
return false;
ExecutableSlashCommandDefinition other = (ExecutableSlashCommandDefinition) o;
return other.applicationCommand.name().equals(this.applicationCommand.name()) &&
other.subCommandGroup.name().equals(this.subCommandGroup.name()) &&
other.subCommand.name().equals(this.subCommand.name());
}
@Override
public final String toString() {
return applicationCommand.name() + subCommand.name() != null ? "::" + subCommand.name() : "";
}
public boolean isRootCommand() {
return subCommand == null;
}
public static class Builder {
private SlashCommand applicationCommand;
private SubCommand subCommand;
private SubCommandGroup subCommandGroup;
public ExecutableSlashCommandDefinition build() {
if (applicationCommand == null)
throw new IllegalArgumentException("applicationCommandName cant be null");
return new ExecutableSlashCommandDefinition(applicationCommand, subCommand, subCommandGroup, subCommand != null ? subCommand.options() : applicationCommand.options());
}
public void setApplicationCommand(SlashCommand applicationCommand) {
this.applicationCommand = applicationCommand;
}
public void setSubCommand(SubCommand subCommand) {
this.subCommand = subCommand;
}
public void setSubCommandGroup(SubCommandGroup subCommandGroup) {
this.subCommandGroup = subCommandGroup;
}
public SlashCommand getApplicationCommand() {
return applicationCommand;
}
public SubCommand getSubCommand() {
return subCommand;
}
public SubCommandGroup getSubCommandGroup() {
return subCommandGroup;
}
}
}

View File

@@ -1,99 +1,110 @@
package net.tomatentum.marinara.interaction.commands; package net.tomatentum.marinara.interaction.commands;
import java.util.ArrayList; import java.util.HashSet;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Set;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; import org.slf4j.Logger;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption.PlaceHolderEnum;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
import net.tomatentum.marinara.interaction.commands.choice.EnumChoices;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier;
import net.tomatentum.marinara.util.LoggerUtil;
public class SlashCommandDefinition { public class SlashCommandDefinition {
private List<ExecutableSlashCommandDefinition> executableDefinitons;
private SlashCommand slashCommand;
private boolean isRootCommand;
public SlashCommandDefinition(SlashCommand applicationCommand) { public static SlashCommandOptionChoice[] getActualChoices(SlashCommandOption option) {
this.executableDefinitons = new ArrayList<>(); SlashCommandOptionChoice[] choices = option.choices();
this.slashCommand = applicationCommand; if (choices.length <= 0 && !option.choiceEnum().equals(PlaceHolderEnum.class))
choices = EnumChoices.of(option.choiceEnum()).choices();
return choices;
} }
public SlashCommandDefinition addExecutableCommand(ExecutableSlashCommandDefinition def) { private Set<InteractionIdentifier> entries;
if (def.applicationCommand() != null) { private RootCommandIdentifier rootIdentifier;
if (slashCommand == null) private boolean isRootCommand;
this.slashCommand = def.applicationCommand();
if (!this.slashCommand.name().equals(def.applicationCommand().name())) private Logger logger = LoggerUtil.getLogger(getClass());
throw new IllegalArgumentException(def + ": has a non matching Application Command description. Please edit it to equal all other descriptions or remove it to use other definitions descriptions");
public SlashCommandDefinition(RootCommandIdentifier rootIdentifier) {
this.entries = new HashSet<>();
this.rootIdentifier = rootIdentifier;
this.isRootCommand = false;
}
public SlashCommandDefinition addIdentifier(InteractionIdentifier identifier) {
RootCommandIdentifier rootIdentifier = (RootCommandIdentifier) identifier.rootNode();
if (!this.rootIdentifier.equals(rootIdentifier))
throw new IllegalArgumentException("Root Node did not match.");
if (this.rootIdentifier.description() == null)
this.rootIdentifier = rootIdentifier;
if (!isRootCommand)
this.isRootCommand = identifier.parent() == null ? true : false;
if ((isRootCommand && identifier.parent() != null) || (!isRootCommand && identifier.parent() == null)) {
throw new IllegalArgumentException(identifier.toString() + ": cannot have subcommands and rootcommand definitions together");
} }
if (executableDefinitons.isEmpty()) entries.add(identifier);
this.isRootCommand = def.isRootCommand(); this.logger.debug("Added identifer {} to command {}", identifier, rootIdentifier);
if ((isRootCommand && !def.isRootCommand()) || (!isRootCommand && def.isRootCommand())) {
throw new IllegalArgumentException(def + ": cannot have subcommands and rootcommand definitions together");
}
executableDefinitons.add(def);
return this; return this;
} }
public SubCommandGroup[] getSubCommandGroups() { public SlashCommandIdentifier[] getSubCommandGroups() {
List<SubCommandGroup> subCommandGroups = Arrays.stream(getExecutableDefinitons()) if (isRootCommand)
.filter((x) -> x.subCommandGroup() != null) return null;
.map((x) -> x.subCommandGroup())
List<InteractionIdentifier> subCommandGroups = entries().stream()
.filter(x -> x.parent().parent() != null)
.map(x -> x.parent())
.toList(); .toList();
HashMap<String, SubCommandGroup> subCommandGroupMap = new HashMap<>(); return subCommandGroups.toArray(SlashCommandIdentifier[]::new);
subCommandGroups.forEach((x) -> {
SubCommandGroup current = subCommandGroupMap.get(x.name());
if (current == null || (current.description().isBlank() && !x.description().isBlank()))
subCommandGroupMap.put(x.name(), x);
});
return subCommandGroupMap.values().toArray(new SubCommandGroup[0]);
} }
public SubCommand[] getSubCommands(String groupName) { public SlashCommandIdentifier[] getSubCommands() {
List<SubCommand> subCommands; if (isRootCommand)
if (groupName == null) return null;
subCommands = Arrays.stream(getExecutableDefinitons()) return entries.stream().filter(x -> x.parent() instanceof RootCommandIdentifier).toArray(SlashCommandIdentifier[]::new);
.filter((x) -> x.subCommandGroup() == null && x.subCommand() != null) }
.map((x) -> x.subCommand())
.toList(); public SlashCommandIdentifier[] getSubCommands(String groupName) {
else if (isRootCommand)
subCommands = Arrays.stream(getExecutableDefinitons()) return null;
.filter((x) -> x.subCommandGroup().name().equals(groupName) && x.subCommand() != null)
.map((x) -> x.subCommand()) List<InteractionIdentifier> subCommands = entries().stream()
.filter(x -> x.parent().parent() != null && x.parent().name().equals(groupName))
.map(x -> x.parent().parent())
.toList(); .toList();
HashMap<String, SubCommand> subCommandMap = new HashMap<>(); return subCommands.toArray(SlashCommandIdentifier[]::new);
subCommands.forEach((x) -> {
SubCommand current = subCommandMap.get(x.name());
if (current == null || (current.description().isBlank() && !x.description().isBlank()))
subCommandMap.put(x.name(), x);
});
return subCommandMap.values().toArray(new SubCommand[0]);
} }
public SlashCommand getFullSlashCommand() { @Override
if (isRootCommand()) public boolean equals(Object obj) {
return getSlashCommand(); if (!(obj instanceof SlashCommandDefinition))
for (ExecutableSlashCommandDefinition executableSlashCommandDefinition : executableDefinitons) { return false;
if (executableSlashCommandDefinition.options().length > 0) SlashCommandDefinition other = (SlashCommandDefinition) obj;
return executableSlashCommandDefinition.applicationCommand(); return this.rootIdentifier().equals(other.rootIdentifier());
}
return null;
} }
public SlashCommand getSlashCommand() { public long[] serverIds() {
return slashCommand; return rootIdentifier().serverIds();
} }
public ExecutableSlashCommandDefinition[] getExecutableDefinitons() { public Set<InteractionIdentifier> entries() {
return executableDefinitons.toArray(new ExecutableSlashCommandDefinition[0]); return this.entries;
}
public RootCommandIdentifier rootIdentifier() {
return rootIdentifier;
} }
public boolean isRootCommand() { public boolean isRootCommand() {

View File

@@ -14,4 +14,11 @@ public @interface SlashCommandOption {
public String description() default ""; public String description() default "";
public SlashCommandOptionType type() default SlashCommandOptionType.STRING; public SlashCommandOptionType type() default SlashCommandOptionType.STRING;
public boolean required() default false; public boolean required() default false;
public boolean autocomplete() default false;
public SlashCommandOptionChoice[] choices() default {};
public Class<? extends Enum<?>> choiceEnum() default PlaceHolderEnum.class;
public static enum PlaceHolderEnum {
}
} }

View File

@@ -0,0 +1,8 @@
package net.tomatentum.marinara.interaction.commands.annotation;
public @interface SlashCommandOptionChoice {
public String name();
public long longValue() default Long.MAX_VALUE;
public double doubleValue() default Double.MAX_VALUE;
public String stringValue() default "";
}

View File

@@ -0,0 +1,5 @@
package net.tomatentum.marinara.interaction.commands.choice;
public interface ChoiceValueProvider<T> {
T getChoiceValue();
}

View File

@@ -0,0 +1,78 @@
package net.tomatentum.marinara.interaction.commands.choice;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import io.leangen.geantyref.AnnotationFormatException;
import io.leangen.geantyref.GenericTypeReflector;
import io.leangen.geantyref.TypeFactory;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
public record EnumChoices(Class<? extends Enum<?>> enumClass, ChoiceType type, SlashCommandOptionChoice[] choices) {
private static Method method;
static {
try {
method = ChoiceValueProvider.class.getMethod("getChoiceValue");
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
public static EnumChoices of(Class<? extends Enum<?>> enumClass) {
if (!ChoiceValueProvider.class.isAssignableFrom(enumClass))
throw new IllegalArgumentException("Provided class needs to implement the ChoiceValueProvider interface.");
ChoiceType type = parseChoiceType(enumClass);
SlashCommandOptionChoice[] choices = parseChoices(enumClass, type);
return new EnumChoices(enumClass, type, choices);
}
private static ChoiceType parseChoiceType(Class<? extends Enum<?>> enumClass) {
ParameterizedType type = (ParameterizedType) GenericTypeReflector.getExactSuperType(enumClass, ChoiceValueProvider.class);
Type typeParam = type.getActualTypeArguments()[0];
if (!(typeParam instanceof Class<?>))
throw new IllegalArgumentException("ChoiceValueProvider need either a String or Number type parameter.");
if (Long.class.isAssignableFrom((Class<?>) typeParam))
return ChoiceType.INTEGER;
if (Double.class.isAssignableFrom((Class<?>) typeParam))
return ChoiceType.DOUBLE;
if (String.class.isAssignableFrom((Class<?>) typeParam))
return ChoiceType.String;
throw new IllegalArgumentException("ChoiceValueProvider need either a String, Number or Decimal type parameter.");
}
private static SlashCommandOptionChoice[] parseChoices(Class<? extends Enum<?>> enumClass, ChoiceType type) {
Enum<? extends Enum<?>>[] constants = enumClass.getEnumConstants();
List<SlashCommandOptionChoice> choices = new ArrayList<>();
for (Enum<? extends Enum<?>> enumInstance : constants) {
Object value;
try {
value = method.invoke(enumInstance);
if (type.equals(ChoiceType.INTEGER))
choices.add(TypeFactory.annotation(SlashCommandOptionChoice.class, Map.of("name", enumInstance.name(), "longValue", value)));
if (type.equals(ChoiceType.DOUBLE))
choices.add(TypeFactory.annotation(SlashCommandOptionChoice.class, Map.of("name", enumInstance.name(), "doubleValue", value)));
if (type.equals(ChoiceType.String))
choices.add(TypeFactory.annotation(SlashCommandOptionChoice.class, Map.of("name", enumInstance.name(), "stringValue", value)));
} catch (IllegalAccessException | InvocationTargetException | AnnotationFormatException e) {
e.printStackTrace();
return null;
}
}
return choices.toArray(SlashCommandOptionChoice[]::new);
}
public static enum ChoiceType {
String,
INTEGER,
DOUBLE
}
}

View File

@@ -1,16 +1,35 @@
package net.tomatentum.marinara.interaction.commands.option; package net.tomatentum.marinara.interaction.commands.option;
public enum SlashCommandOptionType { public enum SlashCommandOptionType {
ATTACHMENT, SUB_COMMAND(1),
BOOLEAN, SUB_COMMAND_GROUP(2),
CHANNEL, STRING(3),
DECIMAL, INTEGER(4),
LONG, BOOLEAN(5),
MENTIONABLE, USER(6),
ROLE, CHANNEL(7),
STRING, ROLE(8),
SUB_COMMAND, MENTIONABLE(9),
SUB_COMMAND_GROUP, DOUBLE(10),
UNKNOW, ATTACHMENT(11),
USER UNKNOWN(-1);
private final int value;
private SlashCommandOptionType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static SlashCommandOptionType fromValue(int value) {
for (SlashCommandOptionType type : values()) {
if (type.getValue() == value) {
return type;
}
}
return UNKNOWN;
}
} }

View File

@@ -0,0 +1,141 @@
package net.tomatentum.marinara.interaction.ident;
import java.util.Objects;
import net.tomatentum.marinara.interaction.InteractionType;
public class InteractionIdentifier {
public static InteractionIdentifier.Builder builder() {
return new InteractionIdentifier.Builder();
}
public static RootCommandIdentifier.Builder rootBuilder() {
return new RootCommandIdentifier.Builder();
}
public static SlashCommandIdentifier.Builder slashBuilder() {
return new SlashCommandIdentifier.Builder();
}
public static InteractionIdentifier createHierarchy(InteractionType type, String... names) {
InteractionIdentifier last = null;
for (String string : names) {
last = builder().name(string).type(type).parent(last).build();
}
return last;
}
public static void tryAddDescriptions(InteractionIdentifier receiver, InteractionIdentifier provider) {
if (receiver == null || provider == null)
return;
if (receiver.description().isBlank())
receiver.description = provider.description();
tryAddDescriptions(receiver.parent(), provider.parent());
}
private InteractionIdentifier parent;
private String name;
private String description;
private InteractionType type;
InteractionIdentifier(InteractionIdentifier parent, String name, String description, InteractionType type) {
this.parent = parent;
this.name = name;
this.description = description;
this.type = type;
}
public InteractionIdentifier rootNode() { return rootNode(this); }
private InteractionIdentifier rootNode(InteractionIdentifier identifier) {
if (identifier.parent() == null)
return identifier;
return rootNode(identifier.parent());
}
public String name() {
return name;
}
public String description() {
return description;
}
public InteractionIdentifier parent() {
return parent;
}
public InteractionType type() {
return type;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof InteractionIdentifier))
return false;
InteractionIdentifier ident = (InteractionIdentifier) obj;
if (!type().equals(ident.type()))
return false;
if (!name().equals(ident.name()))
return false;
return Objects.equals(ident, obj);
}
@Override
public String toString() {
if (parent() == null)
return name();
return "{}.{}".formatted(name(), parent().toString());
}
public static class Builder {
private InteractionIdentifier parent;
private String name;
private String description;
private InteractionType type;
public InteractionIdentifier parent() {
return parent;
}
public Builder parent(InteractionIdentifier parent) {
this.parent = parent;
return this;
}
public String name() {
return name;
}
public Builder name(String name) {
this.name = name;
return this;
}
public String description() {
return description;
}
public Builder description(String description) {
this.description = description;
return this;
}
public InteractionType type() {
return type;
}
public Builder type(InteractionType type) {
this.type = type;
return this;
}
public InteractionIdentifier build() {
return new InteractionIdentifier(parent, name, description, type);
}
}
}

View File

@@ -0,0 +1,90 @@
package net.tomatentum.marinara.interaction.ident;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
public class RootCommandIdentifier extends SlashCommandIdentifier {
private long[] serverIds;
public RootCommandIdentifier(
InteractionIdentifier parent,
String name,
String description,
InteractionType type,
SlashCommandOption[] options,
long[] serverIds) {
super(parent, name, description, type, options);
this.serverIds = serverIds;
}
public long[] serverIds() {
return serverIds;
}
public static class Builder {
private InteractionIdentifier parent;
private String name;
private String description;
private SlashCommandOption[] options;
private long[] serverIds;
public InteractionIdentifier parent() {
return parent;
}
public Builder parent(InteractionIdentifier parent) {
this.parent = parent;
return this;
}
public String name() {
return name;
}
public Builder name(String name) {
this.name = name;
return this;
}
public String description() {
return this.description;
}
public Builder description(String description) {
this.description = description;
return this;
}
public SlashCommandOption[] options() {
return this.options;
}
public Builder options(SlashCommandOption[] options) {
this.options = options;
return this;
}
public long[] serverIds() {
return this.serverIds;
}
public Builder serverIds(long[] serverIds) {
this.serverIds = serverIds;
return this;
}
public SlashCommandIdentifier build(boolean autocomplete) {
return new RootCommandIdentifier(
parent,
name,
description,
autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND,
options,
serverIds);
}
}
}

View File

@@ -0,0 +1,78 @@
package net.tomatentum.marinara.interaction.ident;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
public class SlashCommandIdentifier extends InteractionIdentifier {
private SlashCommandOption[] options;
protected SlashCommandIdentifier(
InteractionIdentifier parent,
String name,
String description,
InteractionType type,
SlashCommandOption[] options
) {
super(parent, name, description, type);
this.options = options;
}
public SlashCommandOption[] options() {
return this.options;
}
public static class Builder {
private InteractionIdentifier parent;
private String name;
private String description;
private SlashCommandOption[] options;
public InteractionIdentifier parent() {
return parent;
}
public Builder parent(InteractionIdentifier parent) {
this.parent = parent;
return this;
}
public String name() {
return name;
}
public Builder name(String name) {
this.name = name;
return this;
}
public String description() {
return this.description;
}
public Builder description(String description) {
this.description = description;
return this;
}
public SlashCommandOption[] options() {
return this.options;
}
public Builder options(SlashCommandOption[] options) {
this.options = options;
return this;
}
public SlashCommandIdentifier build(boolean autocomplete) {
return new SlashCommandIdentifier(
parent,
name,
description,
autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND,
options);
}
}
}

View File

@@ -0,0 +1,44 @@
package net.tomatentum.marinara.interaction.methods;
import java.lang.reflect.Method;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.parser.AnnotationParser;
import net.tomatentum.marinara.parser.SlashCommandParser;
public class AutoCompleteInteractionMethod extends InteractionMethod {
private InteractionIdentifier interactionIdentifier;
public AutoCompleteInteractionMethod(Method method,
InteractionHandler handler,
Marinara marinara
) {
super(method, handler, marinara);
}
@Override
public AnnotationParser[] parsers() {
return new AnnotationParser[] {
new SlashCommandParser(method, true, (x) -> { this.interactionIdentifier = x; } )
};
}
@Override
public Object getParameter(Object context, int index) {
Class<?> type = method().getParameterTypes()[index+1];
Object autocompleteOptionValue = marinara.getWrapper().getContextObjectProvider().getAutocompleteFocusedOption(context);
if (autocompleteOptionValue != null)
return autocompleteOptionValue;
return marinara.getWrapper().getContextObjectProvider().getInteractionContextObject(context, type);
}
@Override
public InteractionIdentifier identifier() {
return interactionIdentifier;
}
}

View File

@@ -2,39 +2,41 @@ package net.tomatentum.marinara.interaction.methods;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.annotation.Button; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.parser.AnnotationParser;
import net.tomatentum.marinara.parser.ButtonParser;
public class ButtonInteractionMethod extends InteractionMethod { public class ButtonInteractionMethod extends InteractionMethod {
private String customId; private String customId;
ButtonInteractionMethod(Method method, InteractionHandler handler, LibraryWrapper wrapper) { ButtonInteractionMethod(Method method, InteractionHandler handler, Marinara marinara) {
super(method, handler, wrapper); super(method, handler, marinara);
parseMethod();
} }
@Override @Override
public Object getParameter(Object parameter, int index) { public AnnotationParser[] parsers() {
Class<?> type = getMethod().getParameterTypes()[index+1]; return new AnnotationParser[] {
return wrapper.getComponentContextObject(parameter, type); new ButtonParser(method, (x) -> { this.customId = x; } )
};
} }
@Override @Override
public boolean canRun(Object context) { public Object getParameter(Object context, int index) {
return wrapper.getButtonId(context).equals(customId); Class<?> type = method().getParameterTypes()[index+1];
return marinara.getWrapper().getContextObjectProvider().getComponentContextObject(context, type);
} }
@Override @Override
public InteractionType getType() { public InteractionIdentifier identifier() {
return InteractionType.BUTTON; return InteractionIdentifier.builder()
} .name(customId)
.description("Button")
private void parseMethod() { .type(InteractionType.BUTTON)
Button button = getMethod().getAnnotation(Button.class); .build();
this.customId = button.value();
} }
} }

View File

@@ -7,62 +7,99 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.slf4j.Logger;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.checks.AppliedCheck;
import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.annotation.AutoComplete;
import net.tomatentum.marinara.interaction.annotation.Button; import net.tomatentum.marinara.interaction.annotation.Button;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.parser.AnnotationParser;
import net.tomatentum.marinara.parser.InteractionCheckParser;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.util.ReflectionUtil;
public abstract class InteractionMethod { public abstract class InteractionMethod {
public static InteractionMethod create(Method method, InteractionHandler handler, LibraryWrapper wrapper) { public static InteractionMethod create(Method method, InteractionHandler handler, Marinara marinara) {
if (method.isAnnotationPresent(AutoComplete.class))
return new AutoCompleteInteractionMethod(method, handler, marinara);
if (method.isAnnotationPresent(SlashCommand.class) || method.isAnnotationPresent(SubCommand.class)) if (method.isAnnotationPresent(SlashCommand.class) || method.isAnnotationPresent(SubCommand.class))
return new SlashCommandInteractionMethod(method, handler, wrapper); return new SlashCommandInteractionMethod(method, handler, marinara);
if (method.isAnnotationPresent(Button.class)) if (method.isAnnotationPresent(Button.class))
return new ButtonInteractionMethod(method, handler, wrapper); return new ButtonInteractionMethod(method, handler, marinara);
return null; return null;
} }
protected Method method; protected Method method;
protected InteractionHandler handler; protected InteractionHandler handler;
protected LibraryWrapper wrapper; protected Marinara marinara;
protected List<AnnotationParser> parsers;
protected List<AppliedCheck> appliedChecks;
protected InteractionMethod(Method method, InteractionHandler handler, LibraryWrapper wrapper) { private Logger logger = LoggerUtil.getLogger(getClass());
protected InteractionMethod(
Method method,
InteractionHandler handler,
Marinara marinara
) {
if (!Arrays.asList(handler.getClass().getMethods()).contains(method)) if (!Arrays.asList(handler.getClass().getMethods()).contains(method))
throw new InvalidParameterException("Method does not apply to specified handler"); throw new InvalidParameterException("Method does not apply to specified handler");
this.method = method; this.method = method;
this.handler = handler; this.handler = handler;
this.wrapper = wrapper; this.marinara = marinara;
this.parsers = new ArrayList<>(Arrays.asList(parsers()));
this.appliedChecks = new ArrayList<>();
parsers.add(new InteractionCheckParser(method, appliedChecks::add, marinara.getCheckRegistry()));
parsers.stream().forEach(AnnotationParser::parse);
} }
public abstract Object getParameter(Object parameter, int index);
public abstract boolean canRun(Object context);
public abstract InteractionType getType();
public void run(Object context) { public void run(Object context) {
if (this.appliedChecks.stream().filter(x -> !x.pre(context)).count() > 0)
return;
method.setAccessible(true);
try {
method.invoke(handler, getParameters(context));
}catch (IllegalAccessException | InvocationTargetException ex) {
logger.error("InteractionMethod failed to run", ex);
}
this.appliedChecks.forEach(x -> x.post(context));
}
public abstract AnnotationParser[] parsers();
public abstract Object getParameter(Object context, int index);
public abstract InteractionIdentifier identifier();
public Method method() {
return method;
}
private Object[] getParameters(Object context) {
int parameterCount = method.getParameterCount(); int parameterCount = method.getParameterCount();
List<Object> parameters = new ArrayList<>(); List<Object> parameters = new ArrayList<>();
for (int i = 0; i < parameterCount; i++) { for (int i = 0; i < parameterCount; i++) {
Object parameter;
if (i == 0) { if (i == 0) {
parameters.add(context); parameter = context;
continue; }else
} parameter = getParameter(context, i-1);
parameters.add(getParameter(context, i-1));
}
method.setAccessible(true);
try {
method.invoke(handler, parameters.toArray());
}catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
public Method getMethod() { logger.trace("Found parameter {}={} for method {}", parameter != null ? parameter.getClass().toString() : " ", parameter, ReflectionUtil.getFullMethodName(method));
return method; parameters.add(parameter);
}
return parameters.toArray();
} }
} }

View File

@@ -2,62 +2,36 @@ package net.tomatentum.marinara.interaction.methods;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; import net.tomatentum.marinara.parser.AnnotationParser;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; import net.tomatentum.marinara.parser.SlashCommandParser;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
import net.tomatentum.marinara.util.ReflectionUtil;
import net.tomatentum.marinara.wrapper.LibraryWrapper;
public class SlashCommandInteractionMethod extends InteractionMethod { public class SlashCommandInteractionMethod extends InteractionMethod {
private ExecutableSlashCommandDefinition commandDefinition; private SlashCommandIdentifier interactionIdentifier;
SlashCommandInteractionMethod(Method method, InteractionHandler handler, LibraryWrapper wrapper) { SlashCommandInteractionMethod(Method method, InteractionHandler handler, Marinara marinara) {
super(method, handler, wrapper); super(method, handler, marinara);
parseMethod(); }
@Override
public AnnotationParser[] parsers() {
return new AnnotationParser[] {
new SlashCommandParser(method, false, (x) -> { this.interactionIdentifier = x; } )
};
} }
@Override @Override
public Object getParameter(Object context, int index) { public Object getParameter(Object context, int index) {
return wrapper.convertCommandOption(context, commandDefinition.options()[index].type(), commandDefinition.options()[index].name()); return marinara.getWrapper().getContextObjectProvider().convertCommandOption(context, interactionIdentifier.options()[index].name());
} }
@Override @Override
public boolean canRun(Object context) { public InteractionIdentifier identifier() {
ExecutableSlashCommandDefinition other = wrapper.getCommandDefinition(context); return interactionIdentifier;
return commandDefinition.equals(other);
}
@Override
public InteractionType getType() {
return InteractionType.COMMAND;
}
public ExecutableSlashCommandDefinition getCommandDefinition() {
return commandDefinition;
}
private void parseMethod() {
ReflectionUtil.checkValidCommandMethod(method);
SlashCommand cmd = ReflectionUtil.getAnnotation(method, SlashCommand.class);
ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder();
builder.setApplicationCommand(cmd);
if (ReflectionUtil.isAnnotationPresent(method, SubCommandGroup.class)) {
SubCommandGroup cmdGroup = ReflectionUtil.getAnnotation(method, SubCommandGroup.class);
builder.setSubCommandGroup(cmdGroup);
}
if (ReflectionUtil.isAnnotationPresent(method, SubCommand.class)) {
SubCommand subCmd = ReflectionUtil.getAnnotation(method, SubCommand.class);
builder.setSubCommand(subCmd);
}
this.commandDefinition = builder.build();
} }
} }

View File

@@ -0,0 +1,8 @@
package net.tomatentum.marinara.parser;
import java.lang.reflect.Method;
public interface AnnotationParser {
void parse();
Method getMethod();
}

View File

@@ -0,0 +1,36 @@
package net.tomatentum.marinara.parser;
import java.lang.reflect.Method;
import java.util.function.Consumer;
import org.slf4j.Logger;
import net.tomatentum.marinara.interaction.annotation.Button;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.util.ReflectionUtil;
public class ButtonParser implements AnnotationParser {
private Method method;
private Consumer<String> consumer;
private Logger logger = LoggerUtil.getLogger(getClass());
public ButtonParser(Method method, Consumer<String> consumer) {
this.method = method;
this.consumer = consumer;
}
@Override
public void parse() {
Button button = getMethod().getAnnotation(Button.class);
logger.trace("Parsed Button annotation {} for method {}", button.toString(), ReflectionUtil.getFullMethodName(method));
this.consumer.accept(button.value());
}
@Override
public Method getMethod() {
return this.method;
}
}

View File

@@ -0,0 +1,51 @@
package net.tomatentum.marinara.parser;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Consumer;
import org.slf4j.Logger;
import net.tomatentum.marinara.checks.AppliedCheck;
import net.tomatentum.marinara.checks.InteractionCheck;
import net.tomatentum.marinara.registry.InteractionCheckRegistry;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.util.ReflectionUtil;
public class InteractionCheckParser implements AnnotationParser {
private InteractionCheckRegistry checkRegistry;
private Method method;
private Consumer<AppliedCheck> consumer;
private Logger logger = LoggerUtil.getLogger(getClass());
public InteractionCheckParser(Method method, Consumer<AppliedCheck> consumer, InteractionCheckRegistry checkRegistry) {
this.checkRegistry = checkRegistry;
this.method = method;
this.consumer = consumer;
}
@Override
public void parse() {
Annotation[] annotations = method.getAnnotations();
Arrays.stream(annotations).forEach(this::convertAnnotation);
}
private void convertAnnotation(Annotation annotation) {
Optional<InteractionCheck<?>> check = this.checkRegistry.getCheckFromAnnotation(annotation.annotationType());
if (check.isPresent()) {
AppliedCheck appliedCheck = new AppliedCheck(check.get(), annotation);
logger.trace("Parsed InteractionCheck {} for annotation {} for method {}", check.getClass().getName(), annotation.toString(), ReflectionUtil.getFullMethodName(method));
consumer.accept(appliedCheck);
}
}
@Override
public Method getMethod() {
return this.method;
}
}

View File

@@ -0,0 +1,86 @@
package net.tomatentum.marinara.parser;
import java.lang.reflect.Method;
import java.util.function.Consumer;
import org.slf4j.Logger;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.util.ReflectionUtil;
public class SlashCommandParser implements AnnotationParser {
private Method method;
private boolean isAutoComplete;
private Consumer<SlashCommandIdentifier> consumer;
private Logger logger = LoggerUtil.getLogger(getClass());
public SlashCommandParser(Method method, boolean isAutoComplete, Consumer<SlashCommandIdentifier> consumer) {
this.method = method;
this.isAutoComplete = isAutoComplete;
this.consumer = consumer;
}
@Override
public void parse() {
this.checkValidCommandMethod(method);
SlashCommand cmd = ReflectionUtil.getAnnotation(method, SlashCommand.class);
InteractionIdentifier lastIdentifier = InteractionIdentifier.rootBuilder()
.name(cmd.name())
.description(cmd.description())
.options(cmd.options())
.serverIds(cmd.serverIds())
.build(isAutoComplete);
if (ReflectionUtil.isAnnotationPresent(method, SubCommandGroup.class)) {
SubCommandGroup cmdGroup = ReflectionUtil.getAnnotation(method, SubCommandGroup.class);
lastIdentifier = InteractionIdentifier.builder()
.name(cmdGroup.name())
.description(cmdGroup.description())
.type(isAutoComplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND)
.parent(lastIdentifier)
.build();
}
if (ReflectionUtil.isAnnotationPresent(method, SubCommand.class)) {
SubCommand subCmd = ReflectionUtil.getAnnotation(method, SubCommand.class);
lastIdentifier = InteractionIdentifier.slashBuilder()
.name(subCmd.name())
.description(subCmd.description())
.options(subCmd.options())
.build(isAutoComplete);
}
logger.trace("Parsed using SlashCommandParser for method {} with the result: {}", ReflectionUtil.getFullMethodName(method), lastIdentifier.toString());
consumer.accept((SlashCommandIdentifier) lastIdentifier);
}
@Override
public Method getMethod() {
return this.method;
}
private void checkValidCommandMethod(Method method) {
if (method.isAnnotationPresent(SlashCommand.class) &&
method.getDeclaringClass().isAnnotationPresent(SlashCommand.class)) {
throw new RuntimeException(method.getName() + ": Can't have ApplicationCommand Annotation on Class and Method");
}
if (!ReflectionUtil.isAnnotationPresent(method, SlashCommand.class))
throw new RuntimeException(method.getName() + ": Missing ApplicationCommand Annotation on either Class or Method");
if ((method.isAnnotationPresent(SubCommand.class) &&
!ReflectionUtil.isAnnotationPresent(method, SlashCommand.class))) {
throw new RuntimeException(method.getName() + ": Missing ApplicationCommand Annotation on either Method or Class");
}
}
}

View File

@@ -0,0 +1,40 @@
package net.tomatentum.marinara.registry;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.slf4j.Logger;
import io.leangen.geantyref.GenericTypeReflector;
import net.tomatentum.marinara.checks.InteractionCheck;
import net.tomatentum.marinara.util.LoggerUtil;
public class InteractionCheckRegistry {
private List<InteractionCheck<?>> checks;
private Logger logger = LoggerUtil.getLogger(getClass());
public InteractionCheckRegistry() {
this.checks = new ArrayList<>();
}
public void addCheck(InteractionCheck<?> check) {
checks.add(check);
logger.info("Registered Check {}", check.getClass().getName());
}
public Optional<InteractionCheck<?>> getCheckFromAnnotation(Type annotation) {
for (InteractionCheck<?> interactionCheck : checks) {
ParameterizedType type = (ParameterizedType) GenericTypeReflector.getExactSuperType(interactionCheck.getClass(), InteractionCheck.class);
Type typeParam = type.getActualTypeArguments()[0];
if (typeParam.equals(annotation))
return Optional.of(interactionCheck);
}
return Optional.empty();
}
}

View File

@@ -0,0 +1,65 @@
package net.tomatentum.marinara.registry;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.interaction.methods.InteractionMethod;
import net.tomatentum.marinara.util.LoggerUtil;
public class InteractionEntry {
private InteractionIdentifier identifier;
private Set<InteractionMethod> methods;
private Logger logger = LoggerUtil.getLogger(getClass());
public InteractionEntry(InteractionIdentifier identifier) {
this.identifier = identifier;
this.methods = new HashSet<>();
}
public InteractionEntry addMethod(InteractionMethod method) {
if (!method.identifier().equals(this.identifier))
throw new IllegalArgumentException("Method's identifier did not match the entry's identifier");
this.methods.add(method);
InteractionIdentifier.tryAddDescriptions(identifier, method.identifier());
return this;
}
public void runAll(Object context) {
this.methods.stream().forEach(x -> {
logger.debug("Running Method {} from {} with context {}", x.toString(), this.toString(), context.toString());
x.run(context);
});
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof InteractionEntry))
return false;
InteractionEntry other = (InteractionEntry) obj;
return other.identifier().equals(identifier());
}
@Override
public String toString() {
return "InteractionEntry(%s)".formatted(identifier().toString());
}
public InteractionType type() {
return identifier().type();
}
public InteractionIdentifier identifier() {
return identifier;
}
public Set<InteractionMethod> methods() {
return methods;
}
}

View File

@@ -1,61 +1,80 @@
package net.tomatentum.marinara.registry; package net.tomatentum.marinara.registry;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import org.slf4j.Logger;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.interaction.methods.SlashCommandInteractionMethod; import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.util.ObjectAggregator;
import net.tomatentum.marinara.wrapper.IdentifierProvider;
import net.tomatentum.marinara.interaction.methods.InteractionMethod; import net.tomatentum.marinara.interaction.methods.InteractionMethod;
import net.tomatentum.marinara.wrapper.LibraryWrapper;
public class InteractionRegistry { public class InteractionRegistry {
private List<InteractionMethod> interactionMethods; private Logger logger = LoggerUtil.getLogger(getClass());
private LibraryWrapper wrapper; private Set<InteractionEntry> interactions;
private Marinara marinara;
private IdentifierProvider identifierProvider;
public InteractionRegistry(LibraryWrapper wrapper) { public InteractionRegistry(Marinara marinara) {
this.interactionMethods = new ArrayList<>(); this.interactions = new HashSet<>();
this.wrapper = wrapper; this.marinara = marinara;
wrapper.subscribeInteractions(this::handle); this.identifierProvider = marinara.getWrapper().createIdentifierProvider();
marinara.getWrapper().subscribeInteractions(this::handle);
} }
/*
* TODO: Maybe relocate InteractionEntry checking to another class with description merging.
*/
public void addInteractions(InteractionHandler interactionHandler) { public void addInteractions(InteractionHandler interactionHandler) {
for (Method method : interactionHandler.getClass().getMethods()) { for (Method method : interactionHandler.getClass().getMethods()) {
InteractionMethod iMethod = InteractionMethod.create(method, interactionHandler, wrapper); InteractionMethod iMethod = InteractionMethod.create(method, interactionHandler, marinara);
if (iMethod != null) if (iMethod != null) {
this.interactionMethods.add(iMethod); Optional<InteractionEntry> oentry = this.interactions.stream()
.filter(i -> i.identifier().equals(iMethod.identifier()))
.findFirst();
InteractionEntry entry = oentry.orElse(new InteractionEntry(iMethod.identifier())).addMethod(iMethod);
if (oentry.isEmpty()) this.interactions.add(entry);
logger.debug("Added {} method from {}", iMethod.method().getName(), interactionHandler.getClass().getSimpleName());
}
} }
logger.info("Added all Interactions from {}", interactionHandler.getClass().getSimpleName());
} }
public void registerCommands() { public void registerCommands() {
List<SlashCommandDefinition> defs = new ArrayList<>(); List<InteractionIdentifier> slashIdentifiers = interactions.stream()
List<ExecutableSlashCommandDefinition> execDefs = interactionMethods.stream() .filter((x) -> x.type().equals(InteractionType.COMMAND))
.filter((x) -> x.getClass().isAssignableFrom(SlashCommandInteractionMethod.class)) .map((x) -> x.identifier())
.map((x) -> ((SlashCommandInteractionMethod)x).getCommandDefinition())
.toList(); .toList();
execDefs.forEach((def) -> { SlashCommandDefinition[] defs = new ObjectAggregator<InteractionIdentifier, RootCommandIdentifier, SlashCommandDefinition>(
Optional<SlashCommandDefinition> appDef = defs.stream() i -> Arrays.asList((RootCommandIdentifier)i.rootNode()),
.filter((x) -> x.getSlashCommand().equals(def.applicationCommand())) SlashCommandDefinition::addIdentifier,
.findFirst(); SlashCommandDefinition::new)
if (appDef.isPresent()) .aggregate(slashIdentifiers)
appDef.get().addExecutableCommand(def); .toArray(SlashCommandDefinition[]::new);
else
defs.add(new SlashCommandDefinition(def.applicationCommand()).addExecutableCommand(def));
});
wrapper.registerSlashCommands(defs.toArray(new SlashCommandDefinition[0])); marinara.getWrapper().getRegisterer().register(defs);
} }
public void handle(Object context) { public void handle(Object context) {
interactionMethods.forEach((m) -> { logger.debug("Received {} interaction ", context);
InteractionType type = wrapper.getInteractionType(context.getClass()); interactions.forEach((e) -> {
if (m.getType().equals(type)) if (this.identifierProvider.provide(context).equals(e.identifier())) {
m.run(context); logger.info("Running {} interaction using {}\ncontext: {}", e.type(), e.toString(), context.toString());
e.runAll(context);
}
}); });
} }
} }

View File

@@ -0,0 +1,17 @@
package net.tomatentum.marinara.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.NOPLoggerFactory;
public class LoggerUtil {
public static Logger getLogger(String name) {
if (LoggerFactory.getILoggerFactory() instanceof NOPLoggerFactory)
return new SimpleLogger(name);
return LoggerFactory.getLogger(name);
}
public static Logger getLogger(Class<?> clazz) {
return getLogger(clazz.getName());
}
}

View File

@@ -0,0 +1,46 @@
package net.tomatentum.marinara.util;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class ObjectAggregator<O, K, V> {
private Function<O, Iterable<K>> keySupplier;
private BiConsumer<V, O> valueConsumer;
private Function<K, V> defaultGenerator;
public ObjectAggregator(
Function<O, Iterable<K>> keySupplier,
BiConsumer<V, O> valueConsumer,
Function<K, V> defaultGenerator) {
this.keySupplier = keySupplier;
this.valueConsumer = valueConsumer;
this.defaultGenerator = defaultGenerator;
}
public ObjectAggregator(
Function<O, Iterable<K>> keySupplier,
BiConsumer<V, O> valueConsumer,
Supplier<V> defaultGenerator) {
this.keySupplier = keySupplier;
this.valueConsumer = valueConsumer;
this.defaultGenerator = _ -> defaultGenerator.get();
}
public Collection<V> aggregate(Iterable<O> iterator) {
Map<K, V> map = new HashMap<>();
for (O element : iterator) {
Iterable<K> keys = this.keySupplier.apply(element);
for (K key : keys) {
V value = map.getOrDefault(key, this.defaultGenerator.apply(key));
this.valueConsumer.accept(value, element);
map.putIfAbsent(key, value);
}
}
return map.values();
}
}

View File

@@ -0,0 +1,15 @@
package net.tomatentum.marinara.util;
import java.util.ArrayList;
import java.util.function.Function;
public class ObjectListAggregator<O, K, V> extends ObjectAggregator<O, K, ArrayList<V>> {
public ObjectListAggregator(Function<O, Iterable<K>> keySupplier, Function<O, V> valueConsumer) {
super(keySupplier,
(l, o) -> l.add(valueConsumer.apply(o)),
() -> new ArrayList<>());
}
}

View File

@@ -2,9 +2,10 @@ package net.tomatentum.marinara.util;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; import java.util.Arrays;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; import java.util.List;
import java.util.Objects;
public final class ReflectionUtil { public final class ReflectionUtil {
@@ -21,19 +22,86 @@ public final class ReflectionUtil {
method.getDeclaringClass().getAnnotation(annotationClass); method.getDeclaringClass().getAnnotation(annotationClass);
} }
public static void checkValidCommandMethod(Method method) { public static int getCastDepth(Class<?> child, Class<?> parent) {
if (method.isAnnotationPresent(SlashCommand.class) &&
method.getDeclaringClass().isAnnotationPresent(SlashCommand.class)) { if (parent.equals(Object.class))
throw new RuntimeException(method.getName() + ": Can't have ApplicationCommand Annotation on Class and Method"); return Integer.MAX_VALUE;
if (!parent.isAssignableFrom(child)) {
throw new IllegalArgumentException("The specified class is not a child class of the specified parent.");
} }
if (!isAnnotationPresent(method, SlashCommand.class)) int depth = 0;
throw new RuntimeException(method.getName() + ": Missing ApplicationCommand Annotation on either Class or Method"); Class<?> curr = child;
List<Class<?>> parents = new ArrayList<>();
if ((method.isAnnotationPresent(SubCommand.class) && while (!curr.equals(parent)) {
!isAnnotationPresent(method, SlashCommand.class))) { depth++;
throw new RuntimeException(method.getName() + ": Missing ApplicationCommand Annotation on either Method or Class"); parents.add(curr.getSuperclass());
parents.addAll(Arrays.asList(curr.getInterfaces()));
for (Class<?> currParent : parents) {
if (currParent != null && parent.isAssignableFrom(currParent)) {
curr = currParent;
break;
}
}
parents.clear();
} }
return depth;
} }
public static Method getMostSpecificMethod(Method[] methods, Class<?>... parameters) {
List<Method> compatibleMethods = Arrays.stream(methods)
.filter(x -> isMethodCallable(x, parameters))
.toList();
if (compatibleMethods.size() == 0)
throw new IllegalArgumentException("There are no compatible Methods provided");
for (int i = 0; i < parameters.length; i++) {
final int currI = i;
Class<?>[] parameterTypes = compatibleMethods.stream()
.map(x -> x.getParameterTypes()[currI])
.toArray(x -> new Class[x]);
Class<?> mostSpecific = getMostSpecificClass(parameterTypes, parameters[i]);
compatibleMethods = compatibleMethods.stream()
.filter(x -> Objects.equals(x.getParameterTypes()[currI], mostSpecific))
.toList();
}
return compatibleMethods.getFirst();
}
public static Class<?> getMostSpecificClass(Class<?>[] classes, Class<?> base) {
int min = Integer.MAX_VALUE;
Class<?> currMostSpecific = null;
for (Class<?> currClass : classes) {
int currCastDepth = getCastDepth(base, currClass);
if (currCastDepth <= min) {
min = currCastDepth;
currMostSpecific = currClass;
}
}
return currMostSpecific;
}
public static boolean isMethodCallable(Method method, Class<?>... parameters) {
if (!Objects.equals(method.getParameterCount(), parameters.length))
return false;
Class<?>[] methodParams = method.getParameterTypes();
for (int i = 0; i < parameters.length; i++) {
if (!methodParams[i].isAssignableFrom(parameters[i]))
return false;
}
return true;
}
public static String getFullMethodName(Method method) {
return method.getDeclaringClass().getName() + "." + method.getName();
}
} }

View File

@@ -0,0 +1,55 @@
package net.tomatentum.marinara.util;
import org.slf4j.Marker;
import org.slf4j.event.Level;
import org.slf4j.helpers.LegacyAbstractLogger;
import org.slf4j.helpers.MessageFormatter;
public class SimpleLogger extends LegacyAbstractLogger {
private String name;
public SimpleLogger(String name) {
this.name = name;
}
@Override
public boolean isTraceEnabled() {
return true;
}
@Override
public boolean isDebugEnabled() {
return true;
}
@Override
public boolean isInfoEnabled() {
return true;
}
@Override
public boolean isWarnEnabled() {
return true;
}
@Override
public boolean isErrorEnabled() {
return true;
}
@Override
protected String getFullyQualifiedCallerName() {
return this.name;
}
@Override
protected void handleNormalizedLoggingCall(Level level, Marker marker, String messagePattern, Object[] arguments,
Throwable throwable) {
String formatted = MessageFormatter.basicArrayFormat(messagePattern, arguments);
System.out.println("[%s] %s => %s".formatted(level, this.name, formatted));
}
}

View File

@@ -0,0 +1,70 @@
package net.tomatentum.marinara.wrapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier;
import net.tomatentum.marinara.util.LoggerUtil;
public class CommandConverter<A extends Object, O extends Object, C extends Object> {
public static <A, O, C> CommandConverter<A, O, C> of(Spec<A, O, C> spec) {
return new CommandConverter<>(spec);
}
private Logger logger = LoggerUtil.getLogger(getClass());
private Spec<A, O, C> spec;
CommandConverter(Spec<A, O, C> spec) {
this.spec = spec;
}
public A convert(SlashCommandDefinition def) {
logger.debug("Converting command {}", def);
List<O> options = new ArrayList<>();
if (!def.isRootCommand()) {
Arrays.stream(def.getSubCommands()).map(this::convertSubCommand).forEach(options::add);
Arrays.stream(def.getSubCommandGroups()).map(x -> this.convertSubCommandGroup(def, x)).forEach(options::add);
}else
Arrays.stream(def.rootIdentifier().options()).map(this::convertOption).forEach(options::add);
return spec.convertCommand(def.rootIdentifier(), options);
}
private O convertSubCommandGroup(SlashCommandDefinition def, InteractionIdentifier identifier) {
logger.debug("Converting subCommandGroup {} of {}", identifier, def);
SlashCommandIdentifier[] subCommands = def.getSubCommands(identifier.name());
List<O> convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommand).toList();
return spec.convertSubCommandGroup(identifier, convertedSubCommands);
}
private O convertSubCommand(SlashCommandIdentifier identifier) {
logger.debug("Converting subCommand {}", identifier);
List<O> options = Arrays.stream(identifier.options()).map(this::convertOption).toList();
return spec.convertSubCommand(identifier, options);
}
private O convertOption(SlashCommandOption option) {
logger.debug("Converting option {}", option);
List<C> choices = Arrays.stream(SlashCommandDefinition.getActualChoices(option)).map(spec::convertChoice).toList();
return spec.convertOption(option, choices);
}
public static interface Spec<A extends Object, O extends Object, C extends Object> {
public A convertCommand(RootCommandIdentifier rootIdentifier, List<O> options);
public O convertSubCommandGroup(InteractionIdentifier identifier, List<O> subCommands);
public O convertSubCommand(InteractionIdentifier identifier, List<O> options);
public O convertOption(SlashCommandOption option, List<C> choices);
public C convertChoice(SlashCommandOptionChoice choice);
}
}

View File

@@ -0,0 +1,51 @@
package net.tomatentum.marinara.wrapper;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.util.ObjectAggregator;
public class CommandRegisterer<A extends Object> {
public static <A extends Object> CommandRegisterer<A> of(Strategy<A> strategy, CommandConverter<A, ?, ?> converter) {
return new CommandRegisterer<A>(strategy, converter);
}
private Logger logger = LoggerUtil.getLogger(getClass());
private Strategy<A> strategy;
private CommandConverter<A, ?, ?> converter;
CommandRegisterer(Strategy<A> strategy, CommandConverter<A, ?, ?> converter) {
this.strategy = strategy;
this.converter = converter;
}
public void register(SlashCommandDefinition[] slashDefs) {
Set<ServerCommandList<A>> serverCommands = new ObjectAggregator<SlashCommandDefinition, Long, ServerCommandList<A>>(
def -> Arrays.stream(def.serverIds()).boxed().toList(),
(l, o) -> l.add(converter.convert(o)),
ServerCommandList::new)
.aggregate(Arrays.asList(slashDefs)).stream()
.collect(Collectors.toSet());
Set<A> globalCommands = Arrays.stream(slashDefs)
.filter(x -> x.serverIds().length <= 0)
.map(converter::convert)
.collect(Collectors.toSet());
serverCommands.forEach(strategy::registerServer);
strategy.registerGlobal(globalCommands);
logger.info("Registered all SlashCommands");
}
public interface Strategy<A extends Object> {
void registerServer(ServerCommandList<A> commands);
void registerGlobal(Set<A> defs);
}
}

View File

@@ -0,0 +1,11 @@
package net.tomatentum.marinara.wrapper;
public interface ContextObjectProvider {
public Object convertCommandOption(Object context, String optionName);
public Object getComponentContextObject(Object context, Class<?> type);
public Object getInteractionContextObject(Object context, Class<?> type);
public Object getAutocompleteFocusedOption(Object context);
}

View File

@@ -0,0 +1,72 @@
package net.tomatentum.marinara.wrapper;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import io.leangen.geantyref.GenericTypeReflector;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.util.ReflectionUtil;
public class IdentifierProvider {
public static IdentifierProvider of(Converter<?>... converter) {
return new IdentifierProvider(Arrays.asList(converter));
}
private Map<Class<?>, Converter<?>> converter;
private Logger logger = LoggerUtil.getLogger(getClass());
private IdentifierProvider(List<Converter<?>> converter) {
this.converter = new HashMap<>();
for (Converter<?> conv : converter) {
if (conv.getClass().getName().contains("$$Lambda"))
throw new IllegalArgumentException("Lambdas cannot be used for IdentifierConverter because of Type erasure.");
Type type = GenericTypeReflector.getExactSuperType(conv.getClass(), Converter.class);
Type parameterType = (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[0];
if (!(parameterType instanceof Class))
throw new IllegalArgumentException("Only full Class types are supported by IdentiferConverters");
this.converter.put((Class<?>) parameterType, conv);
}
}
public InteractionIdentifier provide(Object context) {
Type type = ReflectionUtil.getMostSpecificClass(
converter.keySet().stream().filter(x -> x.isAssignableFrom(context.getClass())).toArray(Class<?>[]::new),
context.getClass());
if (type == null)
logger.debug("No Identifier converter found for context {}", context.getClass().toString());
@SuppressWarnings("unchecked")
Converter<Object> conv = (Converter<Object>) converter.get(type);
return conv.convert(context);
}
@FunctionalInterface
public interface Converter<T extends Object> {
InteractionIdentifier convert(T context);
}
public static class LambdaWrapper<T extends Object> implements Converter<T> {
private Converter<T> converter;
LambdaWrapper(Converter<T> converter) {
this.converter = converter;
}
@Override
public InteractionIdentifier convert(T context) {
return this.converter.convert(context);
}
}
}

View File

@@ -3,21 +3,14 @@ package net.tomatentum.marinara.wrapper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition;
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
import net.tomatentum.marinara.interaction.InteractionType;
public abstract class LibraryWrapper { public abstract class LibraryWrapper {
private List<Consumer<Object>> interactionSubscriber; private List<Consumer<Object>> interactionSubscriber;
protected LibraryWrapper() { protected LibraryWrapper() {
interactionSubscriber = new ArrayList<>(); this.interactionSubscriber = new ArrayList<>();
} }
public void handleInteraction(Object context) { public void handleInteraction(Object context) {
interactionSubscriber.forEach((o) -> o.accept(context)); interactionSubscriber.forEach((o) -> o.accept(context));
} }
@@ -29,12 +22,8 @@ public abstract class LibraryWrapper {
interactionSubscriber.remove(consumer); interactionSubscriber.remove(consumer);
} }
public abstract InteractionType getInteractionType(Class<?> clazz); public abstract CommandRegisterer<?> getRegisterer();
public abstract IdentifierProvider createIdentifierProvider();
public abstract ContextObjectProvider getContextObjectProvider();
public abstract void registerSlashCommands(SlashCommandDefinition[] defs);
public abstract Object convertCommandOption(Object context, SlashCommandOptionType type, String optionName);
public abstract ExecutableSlashCommandDefinition getCommandDefinition(Object context);
public abstract String getButtonId(Object context);
public abstract Object getComponentContextObject(Object context, Class<?> type);
} }

View File

@@ -0,0 +1,16 @@
package net.tomatentum.marinara.wrapper;
import java.util.HashSet;
public class ServerCommandList<A> extends HashSet<A>{
private long serverId;
public ServerCommandList(long serverId) {
this.serverId = serverId;
}
public long serverId() {
return serverId;
}
}

View File

@@ -13,5 +13,9 @@ plugins {
rootProject.name = "Marinara" rootProject.name = "Marinara"
include(":lib") include(":lib")
include(":wrapper-javacord") include(":wrapper-javacord")
include(":wrapper-discord4j")
project(":wrapper-javacord").projectDir = file("wrapper/javacord") project(":wrapper-javacord").projectDir = file("wrapper/javacord")
project(":wrapper-discord4j").projectDir = file("wrapper/discord4j")

View File

@@ -0,0 +1,43 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java library project to get you started.
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.8/userguide/building_java_projects.html in the Gradle documentation.
*/
plugins {
// Apply the java-library plugin for API and implementation separation.
`java-library`
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
// Use JUnit Jupiter for testing.
testImplementation(libs.junit.jupiter)
testImplementation(libs.mockito)
testImplementation(libs.discord4j)
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
implementation(libs.slf4j)
implementation(libs.discord4j) {
exclude(module="discord4j-voice")
}
implementation(libs.geantyref)
implementation(project(":lib"))
}
// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(23)
}
}
tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}

View File

@@ -0,0 +1,102 @@
package net.tomatentum.marinara.wrapper.discord4j;
import java.util.List;
import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent;
import discord4j.core.event.domain.interaction.ChatInputInteractionEvent;
import discord4j.core.event.domain.interaction.ComponentInteractionEvent;
import discord4j.core.object.command.ApplicationCommandInteractionOption;
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
import net.tomatentum.marinara.wrapper.ContextObjectProvider;
public class Discord4JContextObjectProvider implements ContextObjectProvider {
@Override
public Object convertCommandOption(Object context, String optionName) {
if (!(context instanceof ChatInputInteractionEvent))
return null;
ChatInputInteractionEvent interactionEvent = (ChatInputInteractionEvent) context;
List<ApplicationCommandInteractionOption> subOptions = Discord4JWrapper.SUB_FILTER.apply(interactionEvent.getOptions());
if (subOptions.isEmpty())
return getOptionValue(interactionEvent.getOption(optionName).get());
ApplicationCommandInteractionOption subCommandOption = interactionEvent.getOptions().getFirst();
subOptions = Discord4JWrapper.SUB_FILTER.apply(subCommandOption.getOptions());
if (!subOptions.isEmpty())
subCommandOption = subOptions.getFirst();
return getOptionValue(interactionEvent.getOption(optionName).get());
}
private Object getOptionValue(ApplicationCommandInteractionOption option) {
if (!option.getValue().isPresent())
return null;
SlashCommandOptionType type = getOptionType(option);
switch (type) {
case ATTACHMENT:
return option.getValue().get().asAttachment();
case BOOLEAN:
return option.getValue().get().asBoolean();
case CHANNEL:
return option.getValue().get().asChannel();
case DOUBLE:
return option.getValue().get().asDouble();
case INTEGER:
return option.getValue().get().asLong();
case MENTIONABLE:
return option.getValue().get().asSnowflake();
case ROLE:
return option.getValue().get().asRole();
case STRING:
return option.getValue().get().asString();
case USER:
return option.getValue().get().asUser();
default:
return null;
}
}
private SlashCommandOptionType getOptionType(ApplicationCommandInteractionOption option) {
return SlashCommandOptionType.fromValue(option.getType().getValue());
}
@Override
public Object getComponentContextObject(Object context, Class<?> type) {
ComponentInteractionEvent componentInteractionEvent = (ComponentInteractionEvent) context;
switch (type.getName()) {
case "discord4j.core.object.entity.Message":
return componentInteractionEvent.getMessage().orElse(null);
default:
return getInteractionContextObject(context, type);
}
}
@Override
public Object getInteractionContextObject(Object context, Class<?> type) {
ComponentInteractionEvent componentInteractionEvent = (ComponentInteractionEvent) context;
switch (type.getName()) {
case "discord4j.core.object.entity.channel.MessageChannel":
return componentInteractionEvent.getInteraction().getChannel().block();
case "discord4j.core.object.entity.Guild":
return componentInteractionEvent.getInteraction().getGuild().block();
case "discord4j.core.object.entity.Member":
return componentInteractionEvent.getInteraction().getMember().orElse(null);
case "discord4j.core.object.entity.User":
return componentInteractionEvent.getInteraction().getUser();
}
return null;
}
@Override
public Object getAutocompleteFocusedOption(Object context) {
ChatInputAutoCompleteEvent interaction = (ChatInputAutoCompleteEvent) context;
return getOptionValue(interaction.getFocusedOption());
}
}

View File

@@ -0,0 +1,75 @@
package net.tomatentum.marinara.wrapper.discord4j;
import java.util.List;
import discord4j.core.object.command.ApplicationCommandOption.Type;
import discord4j.discordjson.json.ApplicationCommandOptionChoiceData;
import discord4j.discordjson.json.ApplicationCommandOptionData;
import discord4j.discordjson.json.ApplicationCommandRequest;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
import net.tomatentum.marinara.wrapper.CommandConverter;
public class Discord4JConverterSpec implements CommandConverter.Spec<ApplicationCommandRequest, ApplicationCommandOptionData, ApplicationCommandOptionChoiceData> {
@Override
public ApplicationCommandRequest convertCommand(RootCommandIdentifier rootIdentifier,
List<ApplicationCommandOptionData> options) {
return ApplicationCommandRequest.builder()
.name(rootIdentifier.name())
.description(rootIdentifier.description())
.options(options)
.build();
}
@Override
public ApplicationCommandOptionData convertSubCommandGroup(InteractionIdentifier identifier,
List<ApplicationCommandOptionData> subCommands) {
return ApplicationCommandOptionData.builder()
.type(Type.SUB_COMMAND_GROUP.getValue())
.name(identifier.name())
.description(identifier.description())
.options(subCommands)
.build();
}
@Override
public ApplicationCommandOptionData convertSubCommand(InteractionIdentifier identifier,
List<ApplicationCommandOptionData> options) {
return ApplicationCommandOptionData.builder()
.type(Type.SUB_COMMAND_GROUP.getValue())
.name(identifier.name())
.description(identifier.description())
.options(options)
.build();
}
@Override
public ApplicationCommandOptionData convertOption(SlashCommandOption option,
List<ApplicationCommandOptionChoiceData> choices) {
Type type = Type.of(option.type().getValue());
return ApplicationCommandOptionData.builder()
.type(type.getValue())
.name(option.name())
.description(option.description())
.required(option.required())
.autocomplete(option.autocomplete())
.choices(choices)
.build();
}
@Override
public ApplicationCommandOptionChoiceData convertChoice(SlashCommandOptionChoice choice) {
var builder = ApplicationCommandOptionChoiceData.builder().name(choice.name());
if (choice.longValue() != Long.MAX_VALUE)
builder.value(choice.longValue());
if (choice.doubleValue() != Double.MAX_VALUE)
builder.value(choice.doubleValue());
if (!choice.stringValue().isEmpty())
builder.value(choice.stringValue());
return builder.build();
}
}

View File

@@ -0,0 +1,32 @@
package net.tomatentum.marinara.wrapper.discord4j;
import java.util.ArrayList;
import java.util.Set;
import discord4j.core.GatewayDiscordClient;
import discord4j.discordjson.json.ApplicationCommandRequest;
import discord4j.rest.service.ApplicationService;
import net.tomatentum.marinara.wrapper.CommandRegisterer;
import net.tomatentum.marinara.wrapper.ServerCommandList;
public class Discord4JRegistererStrategy implements CommandRegisterer.Strategy<ApplicationCommandRequest> {
private ApplicationService appService;
private long applicationId;
public Discord4JRegistererStrategy(GatewayDiscordClient api) {
this.appService = api.getRestClient().getApplicationService();
this.applicationId = api.getRestClient().getApplicationId().block();
}
@Override
public void registerServer(ServerCommandList<ApplicationCommandRequest> commands) {
appService.bulkOverwriteGuildApplicationCommand(applicationId, commands.serverId(), new ArrayList<>(commands));
}
@Override
public void registerGlobal(Set<ApplicationCommandRequest> defs) {
appService.bulkOverwriteGlobalApplicationCommand(applicationId, new ArrayList<>(defs));
}
}

View File

@@ -0,0 +1,74 @@
package net.tomatentum.marinara.wrapper.discord4j;
import java.util.List;
import java.util.function.Function;
import org.slf4j.Logger;
import discord4j.core.GatewayDiscordClient;
import discord4j.core.event.domain.interaction.InteractionCreateEvent;
import discord4j.core.object.command.ApplicationCommandInteractionOption;
import discord4j.core.object.command.ApplicationCommandOption.Type;
import discord4j.discordjson.json.ApplicationCommandRequest;
import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.wrapper.CommandConverter;
import net.tomatentum.marinara.wrapper.CommandRegisterer;
import net.tomatentum.marinara.wrapper.ContextObjectProvider;
import net.tomatentum.marinara.wrapper.IdentifierProvider;
import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.discord4j.identifierconverter.AutocompleteIdentifierConverter;
import net.tomatentum.marinara.wrapper.discord4j.identifierconverter.ButtonIdentifierConverter;
import net.tomatentum.marinara.wrapper.discord4j.identifierconverter.SlashCommandIdentifierConverter;
public class Discord4JWrapper extends LibraryWrapper {
public static final Function<List<ApplicationCommandInteractionOption>, List<ApplicationCommandInteractionOption>> SUB_FILTER = (i) ->
i.stream()
.filter(o -> o.getType().equals(Type.SUB_COMMAND) || o.getType().equals(Type.SUB_COMMAND_GROUP))
.toList();
public static final Function<List<ApplicationCommandInteractionOption>, List<ApplicationCommandInteractionOption>> ARG_FILTER = (i) ->
i.stream()
.filter(o -> !o.getType().equals(Type.SUB_COMMAND) && !o.getType().equals(Type.SUB_COMMAND_GROUP))
.toList();
private Discord4JContextObjectProvider contextObjectProvider;
private CommandRegisterer<ApplicationCommandRequest> commandRegisterer;
private Logger logger = LoggerUtil.getLogger(getClass());
public Discord4JWrapper(GatewayDiscordClient api) {
this.contextObjectProvider = new Discord4JContextObjectProvider();
var converter = CommandConverter.of(new Discord4JConverterSpec());
if (api != null) {
this.commandRegisterer = CommandRegisterer.of(new Discord4JRegistererStrategy(api), converter);
api.on(InteractionCreateEvent.class)
.subscribe(event -> handleInteraction(event));
}else
logger.warn("GatewayDiscordClient was null so no Events were subscribed to.");
logger.info("Discord4J wrapper loaded!");
}
@Override
public CommandRegisterer<?> getRegisterer() {
return this.commandRegisterer;
}
@Override
public IdentifierProvider createIdentifierProvider() {
return IdentifierProvider.of(
new SlashCommandIdentifierConverter(),
new AutocompleteIdentifierConverter(),
new ButtonIdentifierConverter()
);
}
@Override
public ContextObjectProvider getContextObjectProvider() {
return this.contextObjectProvider;
}
}

View File

@@ -0,0 +1,42 @@
package net.tomatentum.marinara.wrapper.discord4j.checks;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Optional;
import discord4j.core.event.domain.interaction.InteractionCreateEvent;
import discord4j.core.object.entity.Member;
import discord4j.rest.util.Permission;
import discord4j.rest.util.PermissionSet;
import net.tomatentum.marinara.checks.InteractionCheck;
public class PermissionCheck implements InteractionCheck<PermissionCheck.HasPermission> {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public static @interface HasPermission {
public Permission[] value();
}
@Override
public boolean preExec(Object context, HasPermission annotation) {
throw new UnsupportedOperationException("Unimplemented method 'preExec'");
}
public boolean preExec(InteractionCreateEvent context, HasPermission annotation) {
Optional<Member> member = context.getInteraction().getMember();
if (member.isEmpty())
return false;
PermissionSet ownPerms = PermissionSet.of(annotation.value());
PermissionSet permSet = member.get().getBasePermissions().block();
return permSet.containsAll(ownPerms);
}
@Override
public void postExec(Object context, HasPermission annotation) {
}
}

View File

@@ -0,0 +1,38 @@
package net.tomatentum.marinara.wrapper.discord4j.identifierconverter;
import java.util.List;
import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent;
import discord4j.core.object.command.ApplicationCommandInteractionOption;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.wrapper.IdentifierProvider;
import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper;
public class AutocompleteIdentifierConverter implements IdentifierProvider.Converter<ChatInputAutoCompleteEvent> {
@Override
public InteractionIdentifier convert(ChatInputAutoCompleteEvent context) {
List<ApplicationCommandInteractionOption> options = Discord4JWrapper.SUB_FILTER.apply(context.getOptions());
String commandName = context.getCommandName();
if (!options.isEmpty()) {
List<ApplicationCommandInteractionOption> sub_options = Discord4JWrapper.SUB_FILTER.apply(options.getFirst().getOptions());
if (!sub_options.isEmpty())
return InteractionIdentifier.createHierarchy(
InteractionType.AUTOCOMPLETE,
commandName,
options.getFirst().getName(),
sub_options.getFirst().getName());
else
return InteractionIdentifier.createHierarchy(
InteractionType.AUTOCOMPLETE,
commandName,
options.getFirst().getName());
}else
return InteractionIdentifier.createHierarchy(
InteractionType.AUTOCOMPLETE,
commandName);
}
}

View File

@@ -0,0 +1,15 @@
package net.tomatentum.marinara.wrapper.discord4j.identifierconverter;
import discord4j.core.event.domain.interaction.ButtonInteractionEvent;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.wrapper.IdentifierProvider;
public class ButtonIdentifierConverter implements IdentifierProvider.Converter<ButtonInteractionEvent> {
@Override
public InteractionIdentifier convert(ButtonInteractionEvent context) {
return InteractionIdentifier.builder().name(context.getCustomId()).type(InteractionType.BUTTON).build();
}
}

View File

@@ -0,0 +1,39 @@
package net.tomatentum.marinara.wrapper.discord4j.identifierconverter;
import java.util.List;
import discord4j.core.event.domain.interaction.ChatInputInteractionEvent;
import discord4j.core.object.command.ApplicationCommandInteractionOption;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.wrapper.IdentifierProvider;
import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper;
public class SlashCommandIdentifierConverter implements IdentifierProvider.Converter<ChatInputInteractionEvent> {
@Override
public InteractionIdentifier convert(ChatInputInteractionEvent context) {
List<ApplicationCommandInteractionOption> options = Discord4JWrapper.SUB_FILTER.apply(context.getOptions());
String commandName = context.getCommandName();
if (!options.isEmpty()) {
List<ApplicationCommandInteractionOption> sub_options = Discord4JWrapper.SUB_FILTER.apply(options.getFirst().getOptions());
if (!sub_options.isEmpty())
return InteractionIdentifier.createHierarchy(
InteractionType.COMMAND,
commandName,
options.getFirst().getName(),
sub_options.getFirst().getName());
else
return InteractionIdentifier.createHierarchy(
InteractionType.COMMAND,
commandName,
options.getFirst().getName());
}else
return InteractionIdentifier.createHierarchy(
InteractionType.COMMAND,
commandName);
}
}

View File

@@ -0,0 +1,45 @@
package net.tomatentum.marinara.test.discord4j;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent;
import discord4j.core.object.command.ApplicationCommandInteractionOption;
import discord4j.core.object.command.ApplicationCommandInteractionOptionValue;
import discord4j.core.object.command.ApplicationCommandOption.Type;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper;
public class AutoCompleteTest {
@Test
public void testAutocomplete() {
ApplicationCommandInteractionOption optionMock = mock();
ChatInputAutoCompleteEvent autoCompleteEventMock = mock();
when(optionMock.getName()).thenReturn("foo");
when(optionMock.getType()).thenReturn(Type.STRING);
when(optionMock.getValue()).thenReturn(
Optional.of(
new ApplicationCommandInteractionOptionValue(null, null, Type.STRING.getValue(), "test", null)
));
when(autoCompleteEventMock.getCommandName()).thenReturn("test");
when(autoCompleteEventMock.getOptions()).thenReturn(new ArrayList<>());
when(autoCompleteEventMock.getFocusedOption()).thenReturn(optionMock);
LibraryWrapper wrapper = new Discord4JWrapper(null); //null okay as we don't use the discord API in this test.
Marinara marinara = Marinara.load(wrapper);
marinara.getRegistry().addInteractions(new TestAutocomplete());
wrapper.handleInteraction(autoCompleteEventMock);
verify(autoCompleteEventMock).respondWithSuggestions(any());
}
}

View File

@@ -0,0 +1,29 @@
package net.tomatentum.marinara.test.discord4j;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import discord4j.core.event.domain.interaction.ButtonInteractionEvent;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.test.discord4j.mocks.CommonMocks;
import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper;
@TestInstance(Lifecycle.PER_CLASS)
public class ButtonTest {
@Test
public void testButtonExecution() {
ButtonInteractionEvent buttonEventMock = CommonMocks.getButtonEventMock("test");
LibraryWrapper wrapper = new Discord4JWrapper(null); //null okay as we don't use the discord API in this test.
Marinara marinara = Marinara.load(wrapper);
marinara.getRegistry().addInteractions(new TestButton());
wrapper.handleInteraction(buttonEventMock);
assertTrue(TestButton.didRun);
}
}

View File

@@ -0,0 +1,70 @@
package net.tomatentum.marinara.test.discord4j;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import discord4j.core.event.domain.interaction.ButtonInteractionEvent;
import discord4j.core.object.command.Interaction;
import discord4j.core.object.entity.Member;
import discord4j.rest.util.Permission;
import discord4j.rest.util.PermissionSet;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.test.discord4j.mocks.CommonMocks;
import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper;
import net.tomatentum.marinara.wrapper.discord4j.checks.PermissionCheck;
import reactor.core.publisher.Mono;
@TestInstance(Lifecycle.PER_CLASS)
public class InteractionCheckTest {
@Test
public void testInteractionCheck() {
ButtonInteractionEvent buttonEventMock = CommonMocks.getButtonEventMock("test");
LibraryWrapper wrapper = new Discord4JWrapper(null);
Marinara marinara = Marinara.load(wrapper);
marinara.getCheckRegistry().addCheck(new TestInteractionCheck());
marinara.getRegistry().addInteractions(new TestButton());
wrapper.handleInteraction(buttonEventMock);
assertTrue(TestInteractionCheck.preExecuted);
assertTrue(TestInteractionCheck.postExecuted);
assertTrue(TestButton.didRun);
}
@Test
public void testPermissionCheck() {
Member memberMock = mock();
Interaction interactionMock = mock();
when(memberMock.getBasePermissions()).thenReturn(Mono.just(PermissionSet.none()));
when(interactionMock.getMember()).thenReturn(Optional.of(memberMock));
ButtonInteractionEvent buttonEventMock = CommonMocks.getButtonEventMock("permissionCheck", interactionMock);
LibraryWrapper wrapper = new Discord4JWrapper(null);
Marinara marinara = Marinara.load(wrapper);
marinara.getCheckRegistry().addCheck(new PermissionCheck());
marinara.getRegistry().addInteractions(new TestButton());
wrapper.handleInteraction(buttonEventMock);
assertFalse(TestButton.didPermRun);
TestButton.didPermRun = false;
when(memberMock.getBasePermissions()).thenReturn(Mono.just(PermissionSet.of(Permission.ATTACH_FILES)));
wrapper.handleInteraction(buttonEventMock);
assertTrue(TestButton.didPermRun);
}
}

View File

@@ -0,0 +1,74 @@
package net.tomatentum.marinara.test.discord4j;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Optional;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import discord4j.core.DiscordClient;
import discord4j.core.GatewayDiscordClient;
import discord4j.core.event.domain.interaction.ChatInputInteractionEvent;
import discord4j.core.object.command.ApplicationCommandInteractionOption;
import discord4j.core.object.command.ApplicationCommandInteractionOptionValue;
import discord4j.core.object.command.ApplicationCommandOption.Type;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper;
@TestInstance(Lifecycle.PER_CLASS)
public class SlashCommandTest {
String DISCORD_TOKEN = System.getenv("DISCORD_TEST_TOKEN");
GatewayDiscordClient client;
@BeforeAll
void setUp() {
client = DiscordClient.create(DISCORD_TOKEN).login().block();
}
@AfterAll
void tearDown() {
client.logout().block();
client = null;
}
@Test
void testSlashCommand() {
Marinara marinara = Marinara.load(new Discord4JWrapper(client));
marinara.getRegistry().addInteractions(new TestCommand());
marinara.getRegistry().registerCommands();
System.out.println("Success!");
}
@Test
void testSlashCommandExecution() {
ApplicationCommandInteractionOption optionMock = mock();
ChatInputInteractionEvent eventMock = mock();
when(optionMock.getName()).thenReturn("foo");
when(optionMock.getType()).thenReturn(Type.STRING);
when(optionMock.getValue()).thenReturn(
Optional.of(
new ApplicationCommandInteractionOptionValue(null, null, Type.STRING.getValue(), "test", null)
));
when(eventMock.getCommandName()).thenReturn("test");
when(eventMock.getOptions()).thenReturn(Arrays.asList(optionMock));
when(eventMock.getOption("foo")).thenReturn(Optional.of(optionMock));
LibraryWrapper wrapper = new Discord4JWrapper(client);
Marinara marinara = Marinara.load(wrapper);
marinara.getRegistry().addInteractions(new TestCommand());
wrapper.handleInteraction(eventMock);
}
}

View File

@@ -0,0 +1,22 @@
package net.tomatentum.marinara.test.discord4j;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Collections;
import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent;
import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.annotation.AutoComplete;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
public class TestAutocomplete implements InteractionHandler {
@SlashCommand(name = "test")
@AutoComplete
public void autocomplete(ChatInputAutoCompleteEvent context, String value) {
System.out.println("Success!");
assertEquals(value, "test");
context.respondWithSuggestions(Collections.emptyList());
}
}

View File

@@ -0,0 +1,43 @@
package net.tomatentum.marinara.test.discord4j;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import discord4j.core.event.domain.interaction.ButtonInteractionEvent;
import discord4j.core.object.entity.Guild;
import discord4j.core.object.entity.Member;
import discord4j.core.object.entity.Message;
import discord4j.core.object.entity.User;
import discord4j.core.object.entity.channel.MessageChannel;
import discord4j.rest.util.Permission;
import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.annotation.Button;
import net.tomatentum.marinara.test.discord4j.TestInteractionCheck.TestCheck;
import net.tomatentum.marinara.wrapper.discord4j.checks.PermissionCheck.HasPermission;
public class TestButton implements InteractionHandler {
public static boolean didRun = false;
@Button("test")
@TestCheck
public void exec(ButtonInteractionEvent interaction, MessageChannel channel, Message message, Member member, User user, Guild server) {
assertNotNull(interaction);
assertNotNull(channel);
assertNotNull(message);
assertNotNull(member);
assertNotNull(user);
assertNotNull(server);
didRun = true;
System.out.println("Success!");
}
public static boolean didPermRun = false;
@Button("permissionCheck")
@HasPermission({Permission.ATTACH_FILES})
public void exec(ButtonInteractionEvent interaction) {
didPermRun = true;
System.out.println("It worked!");
}
}

View File

@@ -0,0 +1,20 @@
package net.tomatentum.marinara.test.discord4j;
import net.tomatentum.marinara.interaction.commands.choice.ChoiceValueProvider;
public enum TestChoiceEnum implements ChoiceValueProvider<String> {
TestValue("testValue"),
FooBar("fooBar"),
Spongebob("spongebob");
private String value;
private TestChoiceEnum(String value) {
this.value = value;
}
@Override
public String getChoiceValue() {
return value;
}
}

View File

@@ -0,0 +1,31 @@
package net.tomatentum.marinara.test.discord4j;
import static org.junit.jupiter.api.Assertions.assertEquals;
import discord4j.core.event.domain.interaction.ChatInputInteractionEvent;
import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
public class TestCommand implements InteractionHandler {
@SlashCommand(
name = "test",
description = "testingen",
serverIds = {
1037753048602255440L
},
options = {
@SlashCommandOption(
name = "foo",
description = "foo bar is very fooby",
type = SlashCommandOptionType.STRING,
choiceEnum = TestChoiceEnum.class
)
}
)
public void exec(ChatInputInteractionEvent event, String test) {
assertEquals(test, "test");
System.out.println("Success!");
}
}

View File

@@ -0,0 +1,37 @@
package net.tomatentum.marinara.test.discord4j;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import net.tomatentum.marinara.checks.InteractionCheck;
public class TestInteractionCheck implements InteractionCheck<TestInteractionCheck.TestCheck> {
public static boolean preExecuted = false;
public static boolean postExecuted = false;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public static @interface TestCheck {
}
@Override
public boolean preExec(Object context, TestCheck annotation) {
assertNotNull(annotation);
assertNotNull(context);
preExecuted = true;
return true;
}
@Override
public void postExec(Object context, TestCheck annotation) {
assertNotNull(annotation);
assertNotNull(context);
postExecuted = true;
}
}

View File

@@ -0,0 +1,55 @@
package net.tomatentum.marinara.test.discord4j.mocks;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Optional;
import discord4j.core.event.domain.interaction.ButtonInteractionEvent;
import discord4j.core.object.command.Interaction;
import discord4j.core.object.entity.Guild;
import discord4j.core.object.entity.Member;
import discord4j.core.object.entity.Message;
import discord4j.core.object.entity.User;
import discord4j.core.object.entity.channel.MessageChannel;
import reactor.core.publisher.Mono;
public class CommonMocks {
public static Interaction getInteractionMock() {
Interaction interaction = mock(Interaction.class);
Message message = mock(Message.class);
MessageChannel channel = mock(MessageChannel.class);
Guild guild = mock(Guild.class);
User user = mock(User.class);
Member member = mock(Member.class);
when(interaction.getMessage()).thenReturn(Optional.of(message));
when(interaction.getChannel()).thenReturn(Mono.just(channel));
when(interaction.getGuild()).thenReturn(Mono.just(guild));
when(interaction.getUser()).thenReturn(user);
when(interaction.getMember()).thenReturn(Optional.of(member));
return interaction;
}
public static ButtonInteractionEvent getButtonEventMock(String customId) {
ButtonInteractionEvent buttonEventMock = mock(ButtonInteractionEvent.class);
when(buttonEventMock.getCustomId()).thenReturn(customId);
Interaction interactionMock = getInteractionMock();
when(buttonEventMock.getInteraction()).thenReturn(interactionMock);
Optional<Message> message = interactionMock.getMessage();
when (buttonEventMock.getMessage()).thenReturn(message);
return buttonEventMock;
}
public static ButtonInteractionEvent getButtonEventMock(String customId, Interaction interaction) {
ButtonInteractionEvent buttonEventMock = mock(ButtonInteractionEvent.class);
when(buttonEventMock.getCustomId()).thenReturn(customId);
when(buttonEventMock.getInteraction()).thenReturn(interaction);
return buttonEventMock;
}
}

View File

@@ -18,9 +18,10 @@ repositories {
dependencies { dependencies {
// Use JUnit Jupiter for testing. // Use JUnit Jupiter for testing.
testImplementation(libs.junit.jupiter) testImplementation(libs.junit.jupiter)
testImplementation(libs.mockito)
testRuntimeOnly("org.junit.platform:junit-platform-launcher") testRuntimeOnly("org.junit.platform:junit-platform-launcher")
implementation(libs.log4j) implementation(libs.slf4j)
implementation(libs.javacord) implementation(libs.javacord)
implementation(libs.geantyref) implementation(libs.geantyref)
implementation(project(":lib")) implementation(project(":lib"))
@@ -29,7 +30,7 @@ dependencies {
// Apply a specific Java toolchain to ease working on different environments. // Apply a specific Java toolchain to ease working on different environments.
java { java {
toolchain { toolchain {
languageVersion = JavaLanguageVersion.of(21) languageVersion = JavaLanguageVersion.of(23)
} }
} }

View File

@@ -0,0 +1,110 @@
package net.tomatentum.marinara.wrapper.javacord;
import org.javacord.api.interaction.AutocompleteInteraction;
import org.javacord.api.interaction.ButtonInteraction;
import org.javacord.api.interaction.SlashCommandInteraction;
import org.javacord.api.interaction.SlashCommandInteractionOption;
import org.javacord.api.interaction.SlashCommandOptionType;
import net.tomatentum.marinara.wrapper.ContextObjectProvider;
public class JavacordContextObjectProvider implements ContextObjectProvider {
@Override
public Object convertCommandOption(Object context, String optionName) {
if (!(context instanceof SlashCommandInteraction))
return null;
SlashCommandInteraction interaction = (SlashCommandInteraction) context;
if (!interaction.getArguments().isEmpty())
return getOptionValue(interaction.getOptionByName(optionName).get());
SlashCommandInteractionOption subCommandOption = interaction.getOptions().getFirst();
if (!subCommandOption.getOptions().isEmpty())
subCommandOption = subCommandOption.getOptions().getFirst();
return getOptionValue(subCommandOption.getOptionByName(optionName).get());
}
private Object getOptionValue(SlashCommandInteractionOption option) {
SlashCommandOptionType type = getOptionType(option);
switch (type) {
case ATTACHMENT:
return option.getAttachmentValue().get();
case BOOLEAN:
return option.getBooleanValue().get();
case CHANNEL:
return option.getChannelValue().get();
case DECIMAL:
return option.getDecimalValue().get();
case LONG:
return option.getLongValue().get();
case MENTIONABLE:
return option.requestMentionableValue().get();
case ROLE:
return option.getRoleValue().get();
case STRING:
return option.getStringValue().get();
case USER:
return option.requestUserValue().get();
default:
return null;
}
}
private SlashCommandOptionType getOptionType(SlashCommandInteractionOption option) {
if (option.getAttachmentValue().isPresent())
return SlashCommandOptionType.ATTACHMENT;
if (option.getBooleanValue().isPresent())
return SlashCommandOptionType.BOOLEAN;
if (option.getChannelValue().isPresent())
return SlashCommandOptionType.CHANNEL;
if (option.getDecimalValue().isPresent())
return SlashCommandOptionType.DECIMAL;
if (option.getLongValue().isPresent())
return SlashCommandOptionType.LONG;
if (option.requestMentionableValue().isPresent())
return SlashCommandOptionType.MENTIONABLE;
if (option.getRoleValue().isPresent())
return SlashCommandOptionType.ROLE;
if (option.getStringValue().isPresent())
return SlashCommandOptionType.STRING;
if (option.requestUserValue().isPresent())
return SlashCommandOptionType.USER;
return SlashCommandOptionType.UNKNOWN;
}
@Override
public Object getComponentContextObject(Object context, Class<?> type) {
ButtonInteraction button = (ButtonInteraction) context;
switch (type.getName()) {
case "org.javacord.api.entity.message.Message":
return button.getMessage();
default:
return getInteractionContextObject(context, type);
}
}
@Override
public Object getInteractionContextObject(Object context, Class<?> type) {
ButtonInteraction button = (ButtonInteraction) context;
switch (type.getName()) {
case "org.javacord.api.entity.channel.TextChannel":
return button.getChannel().orElse(null);
case "org.javacord.api.entity.server.Server":
return button.getServer().orElse(null);
case "org.javacord.api.entity.user.User":
return button.getUser();
}
return null;
}
@Override
public Object getAutocompleteFocusedOption(Object context) {
AutocompleteInteraction interaction = (AutocompleteInteraction) context;
return getOptionValue(interaction.getFocusedOption());
}
}

View File

@@ -0,0 +1,73 @@
package net.tomatentum.marinara.wrapper.javacord;
import java.util.List;
import org.javacord.api.interaction.SlashCommand;
import org.javacord.api.interaction.SlashCommandBuilder;
import org.javacord.api.interaction.SlashCommandOption;
import org.javacord.api.interaction.SlashCommandOptionBuilder;
import org.javacord.api.interaction.SlashCommandOptionChoice;
import org.javacord.api.interaction.SlashCommandOptionChoiceBuilder;
import org.javacord.api.interaction.SlashCommandOptionType;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
import net.tomatentum.marinara.wrapper.CommandConverter;
public class JavacordConverterSpec implements CommandConverter.Spec<SlashCommandBuilder, SlashCommandOption, SlashCommandOptionChoice> {
@Override
public SlashCommandBuilder convertCommand(RootCommandIdentifier rootIdentifier, List<SlashCommandOption> options) {
return SlashCommand.with(rootIdentifier.name(), rootIdentifier.description(), options);
}
@Override
public SlashCommandOption convertSubCommandGroup(InteractionIdentifier identifier,
List<SlashCommandOption> subCommands) {
return SlashCommandOption.createWithOptions(
SlashCommandOptionType.SUB_COMMAND_GROUP,
identifier.name(),
identifier.description(),
subCommands);
}
@Override
public SlashCommandOption convertSubCommand(InteractionIdentifier identifier, List<SlashCommandOption> options) {
return SlashCommandOption.createWithOptions(
SlashCommandOptionType.SUB_COMMAND,
identifier.name(),
identifier.description(),
options);
}
@Override
public SlashCommandOption convertOption(
net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption option,
List<SlashCommandOptionChoice> choices) {
SlashCommandOptionType type = SlashCommandOptionType.fromValue(option.type().getValue());
return new SlashCommandOptionBuilder()
.setType(type)
.setName(option.name())
.setDescription(option.description())
.setRequired(option.required())
.setAutocompletable(option.autocomplete())
.setChoices(choices)
.build();
}
@Override
public SlashCommandOptionChoice convertChoice(
net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice choice) {
SlashCommandOptionChoiceBuilder builder = new SlashCommandOptionChoiceBuilder().setName(choice.name());
if (choice.longValue() != Long.MAX_VALUE)
builder.setValue(choice.longValue());
/*
not yet available
if (choice.doubleValue() != Double.MAX_VALUE)
builder.setValue(choice.doubleValue());
*/
if (!choice.stringValue().isEmpty())
builder.setValue(choice.stringValue());
return builder.build();
}
}

View File

@@ -0,0 +1,29 @@
package net.tomatentum.marinara.wrapper.javacord;
import java.util.Set;
import org.javacord.api.DiscordApi;
import org.javacord.api.interaction.SlashCommandBuilder;
import net.tomatentum.marinara.wrapper.CommandRegisterer;
import net.tomatentum.marinara.wrapper.ServerCommandList;
public class JavacordRegistererStrategy implements CommandRegisterer.Strategy<SlashCommandBuilder> {
private DiscordApi api;
public JavacordRegistererStrategy(DiscordApi api) {
this.api = api;
}
@Override
public void registerServer(ServerCommandList<SlashCommandBuilder> commands) {
api.bulkOverwriteServerApplicationCommands(commands.serverId(), commands);
}
@Override
public void registerGlobal(Set<SlashCommandBuilder> defs) {
api.bulkOverwriteGlobalApplicationCommands(defs);
}
}

View File

@@ -1,186 +1,55 @@
package net.tomatentum.marinara.wrapper.javacord; package net.tomatentum.marinara.wrapper.javacord;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.javacord.api.DiscordApi; import org.javacord.api.DiscordApi;
import org.javacord.api.interaction.ApplicationCommandInteraction;
import org.javacord.api.interaction.ButtonInteraction;
import org.javacord.api.interaction.SlashCommandBuilder; import org.javacord.api.interaction.SlashCommandBuilder;
import org.javacord.api.interaction.SlashCommandInteraction; import org.slf4j.Logger;
import org.javacord.api.interaction.SlashCommandInteractionOption;
import io.leangen.geantyref.AnnotationFormatException; import net.tomatentum.marinara.wrapper.CommandConverter;
import io.leangen.geantyref.TypeFactory; import net.tomatentum.marinara.wrapper.CommandRegisterer;
import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.wrapper.ContextObjectProvider;
import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; import net.tomatentum.marinara.wrapper.IdentifierProvider;
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; import net.tomatentum.marinara.util.LoggerUtil;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.javacord.identifierconverter.AutocompleteIdentifierConverter;
import net.tomatentum.marinara.wrapper.javacord.identifierconverter.ButtonIdentifierConverter;
import net.tomatentum.marinara.wrapper.javacord.identifierconverter.SlashCommandIdentifierConverter;
public class JavacordWrapper extends LibraryWrapper { public class JavacordWrapper extends LibraryWrapper {
private DiscordApi api; private JavacordContextObjectProvider contextObjectProvider;
private CommandRegisterer<SlashCommandBuilder> commandRegisterer;
private Logger logger = LoggerUtil.getLogger(getClass());
public JavacordWrapper(DiscordApi api) { public JavacordWrapper(DiscordApi api) {
this.api = api; this.contextObjectProvider = new JavacordContextObjectProvider();
api.addInteractionCreateListener((e) -> handleInteraction(e.getInteraction())); var converter = CommandConverter.of(new JavacordConverterSpec());
if (api != null) {
this.commandRegisterer = CommandRegisterer.of(new JavacordRegistererStrategy(api), converter);
api.addInteractionCreateListener((e) -> handleInteraction(e.getInteraction()));
}else
logger.warn("DiscordApi was null so no Events were subscribed to.");
logger.info("Javacord wrapper loaded!");
} }
@Override @Override
public InteractionType getInteractionType(Class<?> clazz) { public CommandRegisterer<?> getRegisterer() {
if (ApplicationCommandInteraction.class.isAssignableFrom(clazz)) return this.commandRegisterer;
return InteractionType.COMMAND;
if (ButtonInteraction.class.isAssignableFrom(clazz))
return InteractionType.BUTTON;
return null;
} }
@Override @Override
public void registerSlashCommands(SlashCommandDefinition[] defs) { public IdentifierProvider createIdentifierProvider() {
HashMap<Long, Set<SlashCommandBuilder>> serverCommands = new HashMap<>(); return IdentifierProvider.of(
Set<SlashCommandBuilder> globalCommands = new HashSet<>(); new SlashCommandIdentifierConverter(),
for (SlashCommandDefinition slashCommandDefinition : defs) { new AutocompleteIdentifierConverter(),
SlashCommandBuilder builder = convertSlashCommand(slashCommandDefinition); new ButtonIdentifierConverter()
if (slashCommandDefinition.getFullSlashCommand().serverIds().length > 0) { );
for (long serverId : slashCommandDefinition.getFullSlashCommand().serverIds()) {
serverCommands.putIfAbsent(serverId, new HashSet<>());
serverCommands.get(serverId).add(builder);
}
}else
globalCommands.add(builder);
}
for (long serverId : serverCommands.keySet()) {
api.bulkOverwriteServerApplicationCommands(serverId, serverCommands.get(serverId));
}
api.bulkOverwriteGlobalApplicationCommands(globalCommands);
} }
@Override @Override
public Object convertCommandOption(Object context, SlashCommandOptionType type, String optionName) { public ContextObjectProvider getContextObjectProvider() {
if (!(context instanceof SlashCommandInteraction)) return contextObjectProvider;
return null;
SlashCommandInteraction interaction = (SlashCommandInteraction) context;
if (!interaction.getArguments().isEmpty())
return getOptionValue(interaction.getOptionByName(optionName).get(), type);
SlashCommandInteractionOption subCommandOption = interaction.getOptions().getFirst();
if (!subCommandOption.getOptions().isEmpty())
subCommandOption = subCommandOption.getOptions().getFirst();
return getOptionValue(subCommandOption.getOptionByName(optionName).get(), type);
} }
@Override
public ExecutableSlashCommandDefinition getCommandDefinition(Object context) {
if (!(context instanceof SlashCommandInteraction))
return null;
SlashCommandInteraction interaction = (SlashCommandInteraction) context;
ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder();
List<SlashCommandInteractionOption> options = interaction.getOptions();
try {
builder.setApplicationCommand(TypeFactory.annotation(SlashCommand.class, Map.of("name", interaction.getCommandName())));
if (!options.getFirst().getArguments().isEmpty()) {
builder.setSubCommandGroup(TypeFactory.annotation(SubCommandGroup.class, Map.of("name", options.getFirst().getName())));
builder.setSubCommand(TypeFactory.annotation(SubCommand.class, Map.of("name", options.getFirst().getOptions().getFirst().getName())));
}else
builder.setSubCommand(TypeFactory.annotation(SubCommand.class, Map.of("name", options.getFirst().getName())));
} catch (AnnotationFormatException e) {
e.printStackTrace();
}
return builder.build();
}
private SlashCommandBuilder convertSlashCommand(SlashCommandDefinition def) {
List<org.javacord.api.interaction.SlashCommandOption> options = new ArrayList<>();
SlashCommand cmd = def.getFullSlashCommand();
if (!def.isRootCommand()) {
Arrays.stream(def.getSubCommands(null)).map(this::convertSubCommandDef).forEach(options::add);
Arrays.stream(def.getSubCommandGroups()).map((x) -> convertSubCommandGroupDef(def, x)).forEach(options::add);
}else {
Arrays.stream(cmd.options()).map(this::convertOptionDef).forEach(options::add);
}
return org.javacord.api.interaction.SlashCommand.with(cmd.name(), cmd.description(), options);
}
private org.javacord.api.interaction.SlashCommandOption convertSubCommandGroupDef(SlashCommandDefinition def, SubCommandGroup subGroup) {
SubCommand[] subCommands = def.getSubCommands(subGroup.name());
org.javacord.api.interaction.SlashCommandOption[] convertedSubCommands = (org.javacord.api.interaction.SlashCommandOption[]) Arrays.stream(subCommands).map(this::convertSubCommandDef).toArray();
return org.javacord.api.interaction.SlashCommandOption.createWithOptions(org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND_GROUP, subGroup.name(), subGroup.description(), Arrays.asList(convertedSubCommands));
}
private org.javacord.api.interaction.SlashCommandOption convertSubCommandDef(SubCommand sub) {
List<org.javacord.api.interaction.SlashCommandOption> convertedOptions = new ArrayList<>();
Arrays.stream(sub.options()).map(this::convertOptionDef).forEach(convertedOptions::add);
return org.javacord.api.interaction.SlashCommandOption.createWithOptions(org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND, sub.name(), sub.description(), convertedOptions);
}
private org.javacord.api.interaction.SlashCommandOption convertOptionDef(SlashCommandOption option) {
org.javacord.api.interaction.SlashCommandOptionType type = Enum.valueOf(org.javacord.api.interaction.SlashCommandOptionType.class, option.type().toString());
return org.javacord.api.interaction.SlashCommandOption.create(type, option.name(), option.description(), option.required());
}
private Object getOptionValue(SlashCommandInteractionOption option, SlashCommandOptionType type) {
switch (type) {
case ATTACHMENT:
return option.getAttachmentValue().get();
case BOOLEAN:
return option.getBooleanValue().get();
case CHANNEL:
return option.getChannelValue().get();
case DECIMAL:
return option.getDecimalValue().get();
case LONG:
return option.getLongValue().get();
case MENTIONABLE:
return option.getMentionableValue().get();
case ROLE:
return option.getRoleValue().get();
case STRING:
return option.getStringValue().get();
case USER:
return option.getUserValue().get();
default:
return null;
}
}
@Override
public String getButtonId(Object context) {
ButtonInteraction button = (ButtonInteraction) context;
return button.getCustomId();
}
@Override
public Object getComponentContextObject(Object context, Class<?> type) {
ButtonInteraction button = (ButtonInteraction) context;
switch (type.getName()) {
case "org.javacord.api.entity.channel.TextChannel":
return button.getChannel().orElse(null);
case "org.javacord.api.entity.message.Message":
return button.getMessage();
case "org.javacord.api.entity.server.Server":
return button.getServer().orElse(null);
case "org.javacord.api.entity.user.User":
return button.getUser();
}
return null;
}
} }

View File

@@ -0,0 +1,41 @@
package net.tomatentum.marinara.wrapper.javacord.checks;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Optional;
import org.javacord.api.entity.permission.PermissionType;
import org.javacord.api.entity.server.Server;
import org.javacord.api.interaction.InteractionBase;
import net.tomatentum.marinara.checks.InteractionCheck;
public class PermissionCheck implements InteractionCheck<PermissionCheck.HasPermission> {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public static @interface HasPermission {
public PermissionType[] value();
}
@Override
public boolean preExec(Object context, HasPermission annotation) {
throw new UnsupportedOperationException("Unimplemented method 'preExec'");
}
public boolean preExec(InteractionBase context, HasPermission annotation) {
Optional<Server> server = context.getServer();
if (!server.isPresent())
return false;
return server.get().hasPermissions(context.getUser(), annotation.value());
}
@Override
public void postExec(Object context, HasPermission annotation) {
}
}

View File

@@ -0,0 +1,37 @@
package net.tomatentum.marinara.wrapper.javacord.identifierconverter;
import java.util.List;
import org.javacord.api.interaction.AutocompleteInteraction;
import org.javacord.api.interaction.SlashCommandInteractionOption;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.wrapper.IdentifierProvider;
public class AutocompleteIdentifierConverter implements IdentifierProvider.Converter<AutocompleteInteraction> {
@Override
public InteractionIdentifier convert(AutocompleteInteraction context) {
List<SlashCommandInteractionOption> options = context.getOptions();
String commandName = context.getCommandName();
if (!options.isEmpty()) {
List<SlashCommandInteractionOption> sub_options = context.getOptions().getFirst().getOptions();
if (!sub_options.isEmpty())
return InteractionIdentifier.createHierarchy(
InteractionType.AUTOCOMPLETE,
commandName,
options.getFirst().getName(),
sub_options.getFirst().getName());
else
return InteractionIdentifier.createHierarchy(
InteractionType.AUTOCOMPLETE,
commandName,
options.getFirst().getName());
}else
return InteractionIdentifier.createHierarchy(
InteractionType.AUTOCOMPLETE,
commandName);
}
}

View File

@@ -0,0 +1,16 @@
package net.tomatentum.marinara.wrapper.javacord.identifierconverter;
import org.javacord.api.interaction.ButtonInteraction;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.wrapper.IdentifierProvider;
public class ButtonIdentifierConverter implements IdentifierProvider.Converter<ButtonInteraction> {
@Override
public InteractionIdentifier convert(ButtonInteraction context) {
return InteractionIdentifier.builder().name(context.getCustomId()).type(InteractionType.BUTTON).build();
}
}

View File

@@ -0,0 +1,38 @@
package net.tomatentum.marinara.wrapper.javacord.identifierconverter;
import java.util.List;
import org.javacord.api.interaction.SlashCommandInteraction;
import org.javacord.api.interaction.SlashCommandInteractionOption;
import net.tomatentum.marinara.interaction.InteractionType;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
import net.tomatentum.marinara.wrapper.IdentifierProvider;
public class SlashCommandIdentifierConverter implements IdentifierProvider.Converter<SlashCommandInteraction> {
@Override
public InteractionIdentifier convert(SlashCommandInteraction context) {
List<SlashCommandInteractionOption> options = context.getOptions();
String commandName = context.getCommandName();
if (!options.isEmpty()) {
List<SlashCommandInteractionOption> sub_options = context.getOptions().getFirst().getOptions();
if (!sub_options.isEmpty())
return InteractionIdentifier.createHierarchy(
InteractionType.COMMAND,
commandName,
options.getFirst().getName(),
sub_options.getFirst().getName());
else
return InteractionIdentifier.createHierarchy(
InteractionType.COMMAND,
commandName,
options.getFirst().getName());
}else
return InteractionIdentifier.createHierarchy(
InteractionType.COMMAND,
commandName);
}
}

View File

@@ -0,0 +1,40 @@
package net.tomatentum.marinara.test.javacord;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.Optional;
import org.javacord.api.interaction.AutocompleteInteraction;
import org.javacord.api.interaction.SlashCommandInteractionOption;
import org.junit.jupiter.api.Test;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper;
public class AutoCompleteTest {
@Test
public void testAutocomplete() {
SlashCommandInteractionOption optionMock = mock();
AutocompleteInteraction autocompleteInteractionMock = mock();
when(optionMock.getName()).thenReturn("foo");
when(optionMock.getStringValue()).thenReturn(Optional.of("test"));
when(autocompleteInteractionMock.getCommandName()).thenReturn("test");
when(autocompleteInteractionMock.getFocusedOption()).thenReturn(optionMock);
when(autocompleteInteractionMock.getOptions()).thenReturn(Collections.emptyList());
LibraryWrapper wrapper = new JavacordWrapper(null); //null okay as we don't use the discord API in this test.
Marinara marinara = Marinara.load(wrapper);
marinara.getRegistry().addInteractions(new TestAutocomplete());
wrapper.handleInteraction(autocompleteInteractionMock);
verify(autocompleteInteractionMock).respondWithChoices(any());
}
}

View File

@@ -1,4 +1,4 @@
package net.tomatentum.marinara.test; package net.tomatentum.marinara.test.javacord;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -7,8 +7,7 @@ import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.TestInstance.Lifecycle;
import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.test.mocks.ButtonInteractionMock; import net.tomatentum.marinara.test.javacord.mocks.CommonMocks;
import net.tomatentum.marinara.test.mocks.DiscordApiMock;
import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper;
@@ -17,10 +16,10 @@ public class ButtonTest {
@Test @Test
public void testButtonExecution() { public void testButtonExecution() {
LibraryWrapper wrapper = new JavacordWrapper(new DiscordApiMock()); //null okay as we don't use the discord API in this test. LibraryWrapper wrapper = new JavacordWrapper(null); //null okay as we don't use the discord API in this test.
Marinara marinara = Marinara.load(wrapper); Marinara marinara = Marinara.load(wrapper);
marinara.getRegistry().addInteractions(new TestButton()); marinara.getRegistry().addInteractions(new TestButton());
wrapper.handleInteraction(new ButtonInteractionMock()); wrapper.handleInteraction(CommonMocks.getButtonInteractionMock("test"));
assertTrue(TestButton.didRun); assertTrue(TestButton.didRun);
} }

View File

@@ -0,0 +1,53 @@
package net.tomatentum.marinara.test.javacord;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.javacord.api.entity.server.Server;
import org.javacord.api.interaction.ButtonInteraction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.test.javacord.mocks.CommonMocks;
import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper;
import net.tomatentum.marinara.wrapper.javacord.checks.PermissionCheck;
@TestInstance(Lifecycle.PER_CLASS)
public class InteractionCheckTest {
@Test
public void testInteractionCheck() {
LibraryWrapper wrapper = new JavacordWrapper(null);
Marinara marinara = Marinara.load(wrapper);
marinara.getCheckRegistry().addCheck(new TestInteractionCheck());
marinara.getRegistry().addInteractions(new TestButton());
wrapper.handleInteraction(CommonMocks.getButtonInteractionMock("test"));
assertTrue(TestInteractionCheck.preExecuted);
assertTrue(TestInteractionCheck.postExecuted);
}
@Test
public void testPermissionCheck() {
LibraryWrapper wrapper = new JavacordWrapper(null);
Marinara marinara = Marinara.load(wrapper);
marinara.getCheckRegistry().addCheck(new PermissionCheck());
marinara.getRegistry().addInteractions(new TestButton());
Server serverMock = mock();
ButtonInteraction buttonInteractionMock = CommonMocks.getButtonInteractionMock("permissionCheck", serverMock);
when(serverMock.hasPermissions(any(), any())).thenReturn(false);
wrapper.handleInteraction(buttonInteractionMock);
assertFalse(TestButton.didPermRun);
when(serverMock.hasPermissions(any(), any())).thenReturn(true);
wrapper.handleInteraction(buttonInteractionMock);
assertTrue(TestButton.didPermRun);
}
}

View File

@@ -1,7 +1,15 @@
package net.tomatentum.marinara.test; package net.tomatentum.marinara.test.javacord;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Optional;
import org.javacord.api.DiscordApi; import org.javacord.api.DiscordApi;
import org.javacord.api.DiscordApiBuilder; import org.javacord.api.DiscordApiBuilder;
import org.javacord.api.interaction.SlashCommandInteraction;
import org.javacord.api.interaction.SlashCommandInteractionOption;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -9,7 +17,6 @@ import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.TestInstance.Lifecycle;
import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.Marinara;
import net.tomatentum.marinara.test.mocks.SlashCommandInteractionMock;
import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.wrapper.LibraryWrapper;
import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper; import net.tomatentum.marinara.wrapper.javacord.JavacordWrapper;
@TestInstance(Lifecycle.PER_CLASS) @TestInstance(Lifecycle.PER_CLASS)
@@ -45,7 +52,18 @@ public class SlashCommandTest {
Marinara marinara = Marinara.load(wrapper); Marinara marinara = Marinara.load(wrapper);
marinara.getRegistry().addInteractions(new TestCommand()); marinara.getRegistry().addInteractions(new TestCommand());
wrapper.handleInteraction(new SlashCommandInteractionMock()); SlashCommandInteractionOption optionMock = mock();
SlashCommandInteraction interactionMock = mock();
when(optionMock.getName()).thenReturn("foo");
when(optionMock.getStringValue()).thenReturn(Optional.of("test"));
when(interactionMock.getCommandName()).thenReturn("test");
when(interactionMock.getOptions()).thenReturn(Arrays.asList(optionMock));
when(interactionMock.getArguments()).thenReturn(Arrays.asList(optionMock));
when(interactionMock.getOptionByName("foo")).thenReturn(Optional.of(optionMock));
wrapper.handleInteraction(interactionMock);
} }

View File

@@ -0,0 +1,23 @@
package net.tomatentum.marinara.test.javacord;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Collections;
import org.javacord.api.interaction.AutocompleteInteraction;
import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.annotation.AutoComplete;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
public class TestAutocomplete implements InteractionHandler {
@SlashCommand(name = "test")
@AutoComplete
public void autocomplete(AutocompleteInteraction context, String value) {
System.out.println("Success!");
assertEquals(value, "test");
context.respondWithChoices(Collections.emptyList());
}
}

View File

@@ -1,21 +1,25 @@
package net.tomatentum.marinara.test; package net.tomatentum.marinara.test.javacord;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.javacord.api.entity.channel.TextChannel; import org.javacord.api.entity.channel.TextChannel;
import org.javacord.api.entity.message.Message; import org.javacord.api.entity.message.Message;
import org.javacord.api.entity.permission.PermissionType;
import org.javacord.api.entity.server.Server; import org.javacord.api.entity.server.Server;
import org.javacord.api.entity.user.User; import org.javacord.api.entity.user.User;
import org.javacord.api.interaction.ButtonInteraction; import org.javacord.api.interaction.ButtonInteraction;
import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.InteractionHandler;
import net.tomatentum.marinara.interaction.annotation.Button; import net.tomatentum.marinara.interaction.annotation.Button;
import net.tomatentum.marinara.test.javacord.TestInteractionCheck.TestCheck;
import net.tomatentum.marinara.wrapper.javacord.checks.PermissionCheck.HasPermission;
public class TestButton implements InteractionHandler { public class TestButton implements InteractionHandler {
public static boolean didRun = false; public static boolean didRun = false;
@Button("test") @Button("test")
@TestCheck
public void exec(ButtonInteraction interaction, TextChannel channel, Message message, User member, Server server) { public void exec(ButtonInteraction interaction, TextChannel channel, Message message, User member, Server server) {
assertNotNull(interaction); assertNotNull(interaction);
assertNotNull(channel); assertNotNull(channel);
@@ -26,4 +30,13 @@ public class TestButton implements InteractionHandler {
System.out.println("Success!"); System.out.println("Success!");
} }
public static boolean didPermRun = false;
@Button("permissionCheck")
@HasPermission({PermissionType.ADMINISTRATOR})
public void exec(ButtonInteraction interaction) {
didPermRun = true;
System.out.println("It worked!");
}
} }

View File

@@ -0,0 +1,20 @@
package net.tomatentum.marinara.test.javacord;
import net.tomatentum.marinara.interaction.commands.choice.ChoiceValueProvider;
public enum TestChoiceEnum implements ChoiceValueProvider<String> {
TestValue("testValue"),
FooBar("fooBar"),
Spongebob("spongebob");
private String value;
private TestChoiceEnum(String value) {
this.value = value;
}
@Override
public String getChoiceValue() {
return value;
}
}

View File

@@ -1,4 +1,4 @@
package net.tomatentum.marinara.test; package net.tomatentum.marinara.test.javacord;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -20,7 +20,8 @@ public class TestCommand implements InteractionHandler {
@SlashCommandOption( @SlashCommandOption(
name = "foo", name = "foo",
description = "foo bar is very fooby", description = "foo bar is very fooby",
type = SlashCommandOptionType.STRING type = SlashCommandOptionType.STRING,
choiceEnum = TestChoiceEnum.class
) )
} }
) )

View File

@@ -0,0 +1,37 @@
package net.tomatentum.marinara.test.javacord;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import net.tomatentum.marinara.checks.InteractionCheck;
public class TestInteractionCheck implements InteractionCheck<TestInteractionCheck.TestCheck> {
public static boolean preExecuted = false;
public static boolean postExecuted = false;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public static @interface TestCheck {
}
@Override
public boolean preExec(Object context, TestCheck annotation) {
assertNotNull(annotation);
assertNotNull(context);
preExecuted = true;
return true;
}
@Override
public void postExec(Object context, TestCheck annotation) {
assertNotNull(annotation);
assertNotNull(context);
postExecuted = true;
}
}

View File

@@ -0,0 +1,42 @@
package net.tomatentum.marinara.test.javacord.mocks;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Optional;
import org.javacord.api.entity.channel.TextChannel;
import org.javacord.api.entity.message.Message;
import org.javacord.api.entity.server.Server;
import org.javacord.api.entity.user.User;
import org.javacord.api.interaction.ButtonInteraction;
public class CommonMocks {
public static ButtonInteraction getButtonInteractionMock(String customId) {
ButtonInteraction buttonInteractionMock = mock();
when(buttonInteractionMock.getCustomId()).thenReturn(customId);
when(buttonInteractionMock.getMessage()).thenReturn(mock(Message.class));
when(buttonInteractionMock.getServer()).thenReturn(Optional.of(mock(Server.class)));
when(buttonInteractionMock.getChannel()).thenReturn(Optional.of(mock(TextChannel.class)));
when(buttonInteractionMock.getUser()).thenReturn(mock(User.class));
return buttonInteractionMock;
}
public static ButtonInteraction getButtonInteractionMock(String customId, Server serverMock) {
ButtonInteraction buttonInteractionMock = mock();
when(buttonInteractionMock.getCustomId()).thenReturn(customId);
when(buttonInteractionMock.getMessage()).thenReturn(mock(Message.class));
when(buttonInteractionMock.getServer()).thenReturn(Optional.of(serverMock));
when(buttonInteractionMock.getChannel()).thenReturn(Optional.of(mock(TextChannel.class)));
when(buttonInteractionMock.getUser()).thenReturn(mock(User.class));
return buttonInteractionMock;
}
}

View File

@@ -1,137 +0,0 @@
package net.tomatentum.marinara.test.mocks;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.javacord.api.DiscordApi;
import org.javacord.api.entity.channel.TextChannel;
import org.javacord.api.entity.message.Message;
import org.javacord.api.entity.message.component.ComponentType;
import org.javacord.api.entity.message.component.HighLevelComponent;
import org.javacord.api.entity.permission.PermissionType;
import org.javacord.api.entity.server.Server;
import org.javacord.api.entity.user.User;
import org.javacord.api.interaction.ButtonInteraction;
import org.javacord.api.interaction.DiscordLocale;
import org.javacord.api.interaction.InteractionType;
import org.javacord.api.interaction.callback.ComponentInteractionOriginalMessageUpdater;
import org.javacord.api.interaction.callback.InteractionFollowupMessageBuilder;
import org.javacord.api.interaction.callback.InteractionImmediateResponseBuilder;
import org.javacord.api.interaction.callback.InteractionOriginalResponseUpdater;
public class ButtonInteractionMock implements ButtonInteraction {
@Override
public Message getMessage() {
return new MessageMock();
}
@Override
public String getCustomId() {
return "test";
}
@Override
public ComponentType getComponentType() {
return ComponentType.BUTTON;
}
@Override
public CompletableFuture<Void> acknowledge() {
throw new UnsupportedOperationException("Unimplemented method 'acknowledge'");
}
@Override
public ComponentInteractionOriginalMessageUpdater createOriginalMessageUpdater() {
throw new UnsupportedOperationException("Unimplemented method 'createOriginalMessageUpdater'");
}
@Override
public long getApplicationId() {
throw new UnsupportedOperationException("Unimplemented method 'getApplicationId'");
}
@Override
public InteractionType getType() {
return InteractionType.MESSAGE_COMPONENT;
}
@Override
public InteractionImmediateResponseBuilder createImmediateResponder() {
throw new UnsupportedOperationException("Unimplemented method 'createImmediateResponder'");
}
@Override
public CompletableFuture<InteractionOriginalResponseUpdater> respondLater() {
throw new UnsupportedOperationException("Unimplemented method 'respondLater'");
}
@Override
public CompletableFuture<InteractionOriginalResponseUpdater> respondLater(boolean ephemeral) {
throw new UnsupportedOperationException("Unimplemented method 'respondLater'");
}
@Override
public CompletableFuture<Void> respondWithModal(String customId, String title,
List<HighLevelComponent> components) {
throw new UnsupportedOperationException("Unimplemented method 'respondWithModal'");
}
@Override
public InteractionFollowupMessageBuilder createFollowupMessageBuilder() {
throw new UnsupportedOperationException("Unimplemented method 'createFollowupMessageBuilder'");
}
@Override
public Optional<Server> getServer() {
return Optional.of(new ServerMock());
}
@Override
public Optional<TextChannel> getChannel() {
return Optional.of(new ChannelMock());
}
@Override
public User getUser() {
return new UserMock();
}
@Override
public String getToken() {
throw new UnsupportedOperationException("Unimplemented method 'getToken'");
}
@Override
public int getVersion() {
throw new UnsupportedOperationException("Unimplemented method 'getVersion'");
}
@Override
public DiscordLocale getLocale() {
throw new UnsupportedOperationException("Unimplemented method 'getLocale'");
}
@Override
public Optional<DiscordLocale> getServerLocale() {
throw new UnsupportedOperationException("Unimplemented method 'getServerLocale'");
}
@Override
public Optional<EnumSet<PermissionType>> getBotPermissions() {
throw new UnsupportedOperationException("Unimplemented method 'getBotPermissions'");
}
@Override
public DiscordApi getApi() {
throw new UnsupportedOperationException("Unimplemented method 'getApi'");
}
@Override
public long getId() {
throw new UnsupportedOperationException("Unimplemented method 'getId'");
}
}

View File

@@ -1,824 +0,0 @@
package net.tomatentum.marinara.test.mocks;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.javacord.api.DiscordApi;
import org.javacord.api.entity.channel.ChannelType;
import org.javacord.api.entity.channel.TextChannel;
import org.javacord.api.entity.message.Message;
import org.javacord.api.entity.message.MessageSet;
import org.javacord.api.entity.user.User;
import org.javacord.api.entity.webhook.IncomingWebhook;
import org.javacord.api.entity.webhook.Webhook;
import org.javacord.api.listener.ObjectAttachableListener;
import org.javacord.api.listener.channel.ChannelAttachableListener;
import org.javacord.api.listener.channel.ServerThreadChannelAttachableListener;
import org.javacord.api.listener.channel.TextChannelAttachableListener;
import org.javacord.api.listener.channel.server.thread.ServerThreadChannelCreateListener;
import org.javacord.api.listener.channel.server.thread.ServerThreadChannelDeleteListener;
import org.javacord.api.listener.channel.server.thread.ServerThreadChannelMembersUpdateListener;
import org.javacord.api.listener.channel.server.thread.ServerThreadChannelUpdateListener;
import org.javacord.api.listener.interaction.AutocompleteCreateListener;
import org.javacord.api.listener.interaction.ButtonClickListener;
import org.javacord.api.listener.interaction.InteractionCreateListener;
import org.javacord.api.listener.interaction.MessageComponentCreateListener;
import org.javacord.api.listener.interaction.MessageContextMenuCommandListener;
import org.javacord.api.listener.interaction.ModalSubmitListener;
import org.javacord.api.listener.interaction.SelectMenuChooseListener;
import org.javacord.api.listener.interaction.SlashCommandCreateListener;
import org.javacord.api.listener.interaction.UserContextMenuCommandListener;
import org.javacord.api.listener.message.CachedMessagePinListener;
import org.javacord.api.listener.message.CachedMessageUnpinListener;
import org.javacord.api.listener.message.ChannelPinsUpdateListener;
import org.javacord.api.listener.message.MessageCreateListener;
import org.javacord.api.listener.message.MessageDeleteListener;
import org.javacord.api.listener.message.MessageEditListener;
import org.javacord.api.listener.message.MessageReplyListener;
import org.javacord.api.listener.message.reaction.ReactionAddListener;
import org.javacord.api.listener.message.reaction.ReactionRemoveAllListener;
import org.javacord.api.listener.message.reaction.ReactionRemoveListener;
import org.javacord.api.listener.server.thread.ServerPrivateThreadJoinListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeArchiveTimestampListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeArchivedListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeAutoArchiveDurationListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeInvitableListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeLastMessageIdListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeLockedListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeMemberCountListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeMessageCountListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeRateLimitPerUserListener;
import org.javacord.api.listener.server.thread.ServerThreadChannelChangeTotalMessageSentListener;
import org.javacord.api.listener.user.UserStartTypingListener;
import org.javacord.api.util.cache.MessageCache;
import org.javacord.api.util.event.ListenerManager;
public class ChannelMock implements TextChannel {
@Override
public ChannelType getType() {
throw new UnsupportedOperationException("Unimplemented method 'getType'");
}
@Override
public DiscordApi getApi() {
throw new UnsupportedOperationException("Unimplemented method 'getApi'");
}
@Override
public long getId() {
throw new UnsupportedOperationException("Unimplemented method 'getId'");
}
@Override
public <T extends ChannelAttachableListener & ObjectAttachableListener> Collection<ListenerManager<T>> addChannelAttachableListener(
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'addChannelAttachableListener'");
}
@Override
public <T extends ChannelAttachableListener & ObjectAttachableListener> void removeChannelAttachableListener(
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeChannelAttachableListener'");
}
@Override
public <T extends ChannelAttachableListener & ObjectAttachableListener> Map<T, List<Class<T>>> getChannelAttachableListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getChannelAttachableListeners'");
}
@Override
public <T extends ChannelAttachableListener & ObjectAttachableListener> void removeListener(Class<T> listenerClass,
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeListener'");
}
@Override
public ListenerManager<InteractionCreateListener> addInteractionCreateListener(InteractionCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addInteractionCreateListener'");
}
@Override
public List<InteractionCreateListener> getInteractionCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getInteractionCreateListeners'");
}
@Override
public ListenerManager<SlashCommandCreateListener> addSlashCommandCreateListener(
SlashCommandCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addSlashCommandCreateListener'");
}
@Override
public List<SlashCommandCreateListener> getSlashCommandCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getSlashCommandCreateListeners'");
}
@Override
public ListenerManager<AutocompleteCreateListener> addAutocompleteCreateListener(
AutocompleteCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addAutocompleteCreateListener'");
}
@Override
public List<AutocompleteCreateListener> getAutocompleteCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getAutocompleteCreateListeners'");
}
@Override
public ListenerManager<ModalSubmitListener> addModalSubmitListener(ModalSubmitListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addModalSubmitListener'");
}
@Override
public List<ModalSubmitListener> getModalSubmitListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getModalSubmitListeners'");
}
@Override
public ListenerManager<MessageContextMenuCommandListener> addMessageContextMenuCommandListener(
MessageContextMenuCommandListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageContextMenuCommandListener'");
}
@Override
public List<MessageContextMenuCommandListener> getMessageContextMenuCommandListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageContextMenuCommandListeners'");
}
@Override
public ListenerManager<MessageComponentCreateListener> addMessageComponentCreateListener(
MessageComponentCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageComponentCreateListener'");
}
@Override
public List<MessageComponentCreateListener> getMessageComponentCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageComponentCreateListeners'");
}
@Override
public ListenerManager<UserContextMenuCommandListener> addUserContextMenuCommandListener(
UserContextMenuCommandListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserContextMenuCommandListener'");
}
@Override
public List<UserContextMenuCommandListener> getUserContextMenuCommandListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserContextMenuCommandListeners'");
}
@Override
public ListenerManager<SelectMenuChooseListener> addSelectMenuChooseListener(SelectMenuChooseListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addSelectMenuChooseListener'");
}
@Override
public List<SelectMenuChooseListener> getSelectMenuChooseListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getSelectMenuChooseListeners'");
}
@Override
public ListenerManager<ButtonClickListener> addButtonClickListener(ButtonClickListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addButtonClickListener'");
}
@Override
public List<ButtonClickListener> getButtonClickListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getButtonClickListeners'");
}
@Override
public ListenerManager<UserStartTypingListener> addUserStartTypingListener(UserStartTypingListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserStartTypingListener'");
}
@Override
public List<UserStartTypingListener> getUserStartTypingListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserStartTypingListeners'");
}
@Override
public ListenerManager<MessageEditListener> addMessageEditListener(MessageEditListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageEditListener'");
}
@Override
public List<MessageEditListener> getMessageEditListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageEditListeners'");
}
@Override
public ListenerManager<ChannelPinsUpdateListener> addChannelPinsUpdateListener(ChannelPinsUpdateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addChannelPinsUpdateListener'");
}
@Override
public List<ChannelPinsUpdateListener> getChannelPinsUpdateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getChannelPinsUpdateListeners'");
}
@Override
public ListenerManager<ReactionRemoveListener> addReactionRemoveListener(ReactionRemoveListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addReactionRemoveListener'");
}
@Override
public List<ReactionRemoveListener> getReactionRemoveListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getReactionRemoveListeners'");
}
@Override
public ListenerManager<ReactionAddListener> addReactionAddListener(ReactionAddListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addReactionAddListener'");
}
@Override
public List<ReactionAddListener> getReactionAddListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getReactionAddListeners'");
}
@Override
public ListenerManager<ReactionRemoveAllListener> addReactionRemoveAllListener(ReactionRemoveAllListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addReactionRemoveAllListener'");
}
@Override
public List<ReactionRemoveAllListener> getReactionRemoveAllListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getReactionRemoveAllListeners'");
}
@Override
public ListenerManager<MessageCreateListener> addMessageCreateListener(MessageCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageCreateListener'");
}
@Override
public List<MessageCreateListener> getMessageCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageCreateListeners'");
}
@Override
public ListenerManager<CachedMessageUnpinListener> addCachedMessageUnpinListener(
CachedMessageUnpinListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addCachedMessageUnpinListener'");
}
@Override
public List<CachedMessageUnpinListener> getCachedMessageUnpinListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getCachedMessageUnpinListeners'");
}
@Override
public ListenerManager<CachedMessagePinListener> addCachedMessagePinListener(CachedMessagePinListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addCachedMessagePinListener'");
}
@Override
public List<CachedMessagePinListener> getCachedMessagePinListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getCachedMessagePinListeners'");
}
@Override
public ListenerManager<MessageReplyListener> addMessageReplyListener(MessageReplyListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageReplyListener'");
}
@Override
public List<MessageReplyListener> getMessageReplyListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageReplyListeners'");
}
@Override
public ListenerManager<MessageDeleteListener> addMessageDeleteListener(MessageDeleteListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageDeleteListener'");
}
@Override
public List<MessageDeleteListener> getMessageDeleteListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageDeleteListeners'");
}
@Override
public <T extends TextChannelAttachableListener & ObjectAttachableListener> Collection<ListenerManager<? extends TextChannelAttachableListener>> addTextChannelAttachableListener(
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'addTextChannelAttachableListener'");
}
@Override
public <T extends TextChannelAttachableListener & ObjectAttachableListener> void removeTextChannelAttachableListener(
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeTextChannelAttachableListener'");
}
@Override
public <T extends TextChannelAttachableListener & ObjectAttachableListener> Map<T, List<Class<T>>> getTextChannelAttachableListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getTextChannelAttachableListeners'");
}
@Override
public <T extends TextChannelAttachableListener & ObjectAttachableListener> void removeListener(
Class<T> listenerClass, T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeListener'");
}
@Override
public ListenerManager<ServerThreadChannelChangeLastMessageIdListener> addServerThreadChannelChangeLastMessageIdListener(
ServerThreadChannelChangeLastMessageIdListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeLastMessageIdListener'");
}
@Override
public List<ServerThreadChannelChangeLastMessageIdListener> getServerThreadChannelChangeLastMessageIdListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeLastMessageIdListeners'");
}
@Override
public ListenerManager<ServerThreadChannelChangeArchivedListener> addServerThreadChannelChangeArchivedListener(
ServerThreadChannelChangeArchivedListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeArchivedListener'");
}
@Override
public List<ServerThreadChannelChangeArchivedListener> getServerThreadChannelChangeArchivedListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeArchivedListeners'");
}
@Override
public ListenerManager<ServerThreadChannelChangeMemberCountListener> addServerThreadChannelChangeMemberCountListener(
ServerThreadChannelChangeMemberCountListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeMemberCountListener'");
}
@Override
public List<ServerThreadChannelChangeMemberCountListener> getServerThreadChannelChangeMemberCountListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeMemberCountListeners'");
}
@Override
public ListenerManager<ServerPrivateThreadJoinListener> addServerPrivateThreadJoinListener(
ServerPrivateThreadJoinListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerPrivateThreadJoinListener'");
}
@Override
public List<ServerPrivateThreadJoinListener> getServerPrivateThreadJoinListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerPrivateThreadJoinListeners'");
}
@Override
public ListenerManager<ServerThreadChannelChangeInvitableListener> addServerThreadChannelChangeInvitableListener(
ServerThreadChannelChangeInvitableListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeInvitableListener'");
}
@Override
public List<ServerThreadChannelChangeInvitableListener> getServerThreadChannelChangeInvitableListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeInvitableListeners'");
}
@Override
public ListenerManager<ServerThreadChannelChangeAutoArchiveDurationListener> addServerThreadChannelChangeAutoArchiveDurationListener(
ServerThreadChannelChangeAutoArchiveDurationListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeAutoArchiveDurationListener'");
}
@Override
public List<ServerThreadChannelChangeAutoArchiveDurationListener> getServerThreadChannelChangeAutoArchiveDurationListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeAutoArchiveDurationListeners'");
}
@Override
public ListenerManager<ServerThreadChannelChangeRateLimitPerUserListener> addServerThreadChannelChangeRateLimitPerUserListener(
ServerThreadChannelChangeRateLimitPerUserListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeRateLimitPerUserListener'");
}
@Override
public List<ServerThreadChannelChangeRateLimitPerUserListener> getServerThreadChannelChangeRateLimitPerUserListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeRateLimitPerUserListeners'");
}
@Override
public ListenerManager<ServerThreadChannelChangeLockedListener> addServerThreadChannelChangeLockedListener(
ServerThreadChannelChangeLockedListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeLockedListener'");
}
@Override
public List<ServerThreadChannelChangeLockedListener> getServerThreadChannelChangeLockedListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeLockedListeners'");
}
@Override
public ListenerManager<ServerThreadChannelChangeArchiveTimestampListener> addServerThreadChannelChangeArchiveTimestampListener(
ServerThreadChannelChangeArchiveTimestampListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeArchiveTimestampListener'");
}
@Override
public List<ServerThreadChannelChangeArchiveTimestampListener> getServerThreadChannelChangeArchiveTimestampListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeArchiveTimestampListeners'");
}
@Override
public ListenerManager<ServerThreadChannelChangeTotalMessageSentListener> addServerThreadChannelChangeTotalMessageSentListener(
ServerThreadChannelChangeTotalMessageSentListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeTotalMessageSentListener'");
}
@Override
public List<ServerThreadChannelChangeTotalMessageSentListener> getServerThreadChannelChangeTotalMessageSentListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeTotalMessageSentListeners'");
}
@Override
public ListenerManager<ServerThreadChannelChangeMessageCountListener> addServerThreadChannelChangeMessageCountListener(
ServerThreadChannelChangeMessageCountListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelChangeMessageCountListener'");
}
@Override
public List<ServerThreadChannelChangeMessageCountListener> getServerThreadChannelChangeMessageCountListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelChangeMessageCountListeners'");
}
@Override
public ListenerManager<ServerThreadChannelUpdateListener> addServerThreadChannelUpdateListener(
ServerThreadChannelUpdateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelUpdateListener'");
}
@Override
public List<ServerThreadChannelUpdateListener> getServerThreadChannelUpdateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelUpdateListeners'");
}
@Override
public ListenerManager<ServerThreadChannelMembersUpdateListener> addServerThreadChannelMembersUpdateListener(
ServerThreadChannelMembersUpdateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelMembersUpdateListener'");
}
@Override
public List<ServerThreadChannelMembersUpdateListener> getServerThreadChannelMembersUpdateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelMembersUpdateListeners'");
}
@Override
public ListenerManager<ServerThreadChannelCreateListener> addServerThreadChannelCreateListener(
ServerThreadChannelCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelCreateListener'");
}
@Override
public List<ServerThreadChannelCreateListener> getServerThreadChannelCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelCreateListeners'");
}
@Override
public ListenerManager<ServerThreadChannelDeleteListener> addServerThreadChannelDeleteListener(
ServerThreadChannelDeleteListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelDeleteListener'");
}
@Override
public List<ServerThreadChannelDeleteListener> getServerThreadChannelDeleteListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelDeleteListeners'");
}
@Override
public <T extends ServerThreadChannelAttachableListener & ObjectAttachableListener> Collection<ListenerManager<T>> addServerThreadChannelAttachableListener(
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerThreadChannelAttachableListener'");
}
@Override
public <T extends ServerThreadChannelAttachableListener & ObjectAttachableListener> void removeServerThreadChannelAttachableListener(
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeServerThreadChannelAttachableListener'");
}
@Override
public <T extends ServerThreadChannelAttachableListener & ObjectAttachableListener> Map<T, List<Class<T>>> getServerThreadChannelAttachableListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannelAttachableListeners'");
}
@Override
public <T extends ServerThreadChannelAttachableListener & ObjectAttachableListener> void removeListener(
Class<T> listenerClass, T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeListener'");
}
@Override
public CompletableFuture<Void> type() {
throw new UnsupportedOperationException("Unimplemented method 'type'");
}
@Override
public CompletableFuture<Void> bulkDelete(long... messageIds) {
throw new UnsupportedOperationException("Unimplemented method 'bulkDelete'");
}
@Override
public CompletableFuture<Message> getMessageById(long id) {
throw new UnsupportedOperationException("Unimplemented method 'getMessageById'");
}
@Override
public CompletableFuture<MessageSet> getPins() {
throw new UnsupportedOperationException("Unimplemented method 'getPins'");
}
@Override
public CompletableFuture<MessageSet> getMessages(int limit) {
throw new UnsupportedOperationException("Unimplemented method 'getMessages'");
}
@Override
public CompletableFuture<MessageSet> getMessagesUntil(Predicate<Message> condition) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesUntil'");
}
@Override
public CompletableFuture<MessageSet> getMessagesWhile(Predicate<Message> condition) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesWhile'");
}
@Override
public Stream<Message> getMessagesAsStream() {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesAsStream'");
}
@Override
public CompletableFuture<MessageSet> getMessagesBefore(int limit, long before) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesBefore'");
}
@Override
public CompletableFuture<MessageSet> getMessagesBeforeUntil(Predicate<Message> condition, long before) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesBeforeUntil'");
}
@Override
public CompletableFuture<MessageSet> getMessagesBeforeWhile(Predicate<Message> condition, long before) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesBeforeWhile'");
}
@Override
public Stream<Message> getMessagesBeforeAsStream(long before) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesBeforeAsStream'");
}
@Override
public CompletableFuture<MessageSet> getMessagesAfter(int limit, long after) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesAfter'");
}
@Override
public CompletableFuture<MessageSet> getMessagesAfterUntil(Predicate<Message> condition, long after) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesAfterUntil'");
}
@Override
public CompletableFuture<MessageSet> getMessagesAfterWhile(Predicate<Message> condition, long after) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesAfterWhile'");
}
@Override
public Stream<Message> getMessagesAfterAsStream(long after) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesAfterAsStream'");
}
@Override
public CompletableFuture<MessageSet> getMessagesAround(int limit, long around) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesAround'");
}
@Override
public CompletableFuture<MessageSet> getMessagesAroundUntil(Predicate<Message> condition, long around) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesAroundUntil'");
}
@Override
public CompletableFuture<MessageSet> getMessagesAroundWhile(Predicate<Message> condition, long around) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesAroundWhile'");
}
@Override
public Stream<Message> getMessagesAroundAsStream(long around) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesAroundAsStream'");
}
@Override
public CompletableFuture<MessageSet> getMessagesBetween(long from, long to) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesBetween'");
}
@Override
public CompletableFuture<MessageSet> getMessagesBetweenUntil(Predicate<Message> condition, long from, long to) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesBetweenUntil'");
}
@Override
public CompletableFuture<MessageSet> getMessagesBetweenWhile(Predicate<Message> condition, long from, long to) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesBetweenWhile'");
}
@Override
public Stream<Message> getMessagesBetweenAsStream(long from, long to) {
throw new UnsupportedOperationException("Unimplemented method 'getMessagesBetweenAsStream'");
}
@Override
public MessageCache getMessageCache() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageCache'");
}
@Override
public CompletableFuture<List<Webhook>> getWebhooks() {
throw new UnsupportedOperationException("Unimplemented method 'getWebhooks'");
}
@Override
public CompletableFuture<List<Webhook>> getAllIncomingWebhooks() {
throw new UnsupportedOperationException("Unimplemented method 'getAllIncomingWebhooks'");
}
@Override
public CompletableFuture<List<IncomingWebhook>> getIncomingWebhooks() {
throw new UnsupportedOperationException("Unimplemented method 'getIncomingWebhooks'");
}
@Override
public boolean canWrite(User user) {
throw new UnsupportedOperationException("Unimplemented method 'canWrite'");
}
@Override
public boolean canUseExternalEmojis(User user) {
throw new UnsupportedOperationException("Unimplemented method 'canUseExternalEmojis'");
}
@Override
public boolean canEmbedLinks(User user) {
throw new UnsupportedOperationException("Unimplemented method 'canEmbedLinks'");
}
@Override
public boolean canReadMessageHistory(User user) {
throw new UnsupportedOperationException("Unimplemented method 'canReadMessageHistory'");
}
@Override
public boolean canUseTts(User user) {
throw new UnsupportedOperationException("Unimplemented method 'canUseTts'");
}
@Override
public boolean canAttachFiles(User user) {
throw new UnsupportedOperationException("Unimplemented method 'canAttachFiles'");
}
@Override
public boolean canAddNewReactions(User user) {
throw new UnsupportedOperationException("Unimplemented method 'canAddNewReactions'");
}
@Override
public boolean canManageMessages(User user) {
throw new UnsupportedOperationException("Unimplemented method 'canManageMessages'");
}
@Override
public boolean canMentionEveryone(User user) {
throw new UnsupportedOperationException("Unimplemented method 'canMentionEveryone'");
}
}

View File

@@ -1,605 +0,0 @@
package net.tomatentum.marinara.test.mocks;
import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import org.javacord.api.DiscordApi;
import org.javacord.api.entity.ApplicationInfo;
import org.javacord.api.entity.activity.Activity;
import org.javacord.api.entity.activity.ActivityType;
import org.javacord.api.entity.channel.Channel;
import org.javacord.api.entity.channel.ChannelCategory;
import org.javacord.api.entity.channel.PrivateChannel;
import org.javacord.api.entity.channel.RegularServerChannel;
import org.javacord.api.entity.channel.ServerChannel;
import org.javacord.api.entity.channel.ServerForumChannel;
import org.javacord.api.entity.channel.ServerStageVoiceChannel;
import org.javacord.api.entity.channel.ServerTextChannel;
import org.javacord.api.entity.channel.ServerThreadChannel;
import org.javacord.api.entity.channel.ServerVoiceChannel;
import org.javacord.api.entity.channel.TextChannel;
import org.javacord.api.entity.channel.VoiceChannel;
import org.javacord.api.entity.emoji.CustomEmoji;
import org.javacord.api.entity.emoji.KnownCustomEmoji;
import org.javacord.api.entity.intent.Intent;
import org.javacord.api.entity.message.Message;
import org.javacord.api.entity.message.MessageSet;
import org.javacord.api.entity.message.UncachedMessageUtil;
import org.javacord.api.entity.server.Server;
import org.javacord.api.entity.server.invite.Invite;
import org.javacord.api.entity.sticker.Sticker;
import org.javacord.api.entity.sticker.StickerPack;
import org.javacord.api.entity.user.User;
import org.javacord.api.entity.user.UserStatus;
import org.javacord.api.entity.webhook.IncomingWebhook;
import org.javacord.api.entity.webhook.Webhook;
import org.javacord.api.interaction.ApplicationCommand;
import org.javacord.api.interaction.ApplicationCommandBuilder;
import org.javacord.api.interaction.MessageContextMenu;
import org.javacord.api.interaction.ServerApplicationCommandPermissions;
import org.javacord.api.interaction.SlashCommand;
import org.javacord.api.interaction.UserContextMenu;
import org.javacord.api.listener.GloballyAttachableListener;
import org.javacord.api.util.concurrent.ThreadPool;
import org.javacord.api.util.event.ListenerManager;
import org.javacord.api.util.ratelimit.Ratelimiter;
public class DiscordApiMock implements DiscordApi{
@Override
public <T extends GloballyAttachableListener> ListenerManager<T> addListener(Class<T> listenerClass, T listener) {
return null;
}
@Override
public Collection<ListenerManager<? extends GloballyAttachableListener>> addListener(
GloballyAttachableListener listener) {
return null;
}
@Override
public void removeListener(GloballyAttachableListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeListener'");
}
@Override
public <T extends GloballyAttachableListener> void removeListener(Class<T> listenerClass, T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeListener'");
}
@Override
public <T extends GloballyAttachableListener> Map<T, List<Class<T>>> getListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getListeners'");
}
@Override
public <T extends GloballyAttachableListener> List<T> getListeners(Class<T> listenerClass) {
throw new UnsupportedOperationException("Unimplemented method 'getListeners'");
}
@Override
public String getToken() {
throw new UnsupportedOperationException("Unimplemented method 'getToken'");
}
@Override
public String getPrefixedToken() {
throw new UnsupportedOperationException("Unimplemented method 'getPrefixedToken'");
}
@Override
public Set<Intent> getIntents() {
throw new UnsupportedOperationException("Unimplemented method 'getIntents'");
}
@Override
public ThreadPool getThreadPool() {
throw new UnsupportedOperationException("Unimplemented method 'getThreadPool'");
}
@Override
public void setEventsDispatchable(boolean dispatchEvents) {
throw new UnsupportedOperationException("Unimplemented method 'setEventsDispatchable'");
}
@Override
public boolean canDispatchEvents() {
throw new UnsupportedOperationException("Unimplemented method 'canDispatchEvents'");
}
@Override
public CompletableFuture<Set<ApplicationCommand>> getGlobalApplicationCommands() {
throw new UnsupportedOperationException("Unimplemented method 'getGlobalApplicationCommands'");
}
@Override
public CompletableFuture<ApplicationCommand> getGlobalApplicationCommandById(long applicationCommandId) {
throw new UnsupportedOperationException("Unimplemented method 'getGlobalApplicationCommandById'");
}
@Override
public CompletableFuture<Set<ApplicationCommand>> getServerApplicationCommands(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getServerApplicationCommands'");
}
@Override
public CompletableFuture<ApplicationCommand> getServerApplicationCommandById(Server server,
long applicationCommandId) {
throw new UnsupportedOperationException("Unimplemented method 'getServerApplicationCommandById'");
}
@Override
public CompletableFuture<Set<SlashCommand>> getGlobalSlashCommands() {
throw new UnsupportedOperationException("Unimplemented method 'getGlobalSlashCommands'");
}
@Override
public CompletableFuture<SlashCommand> getGlobalSlashCommandById(long commandId) {
throw new UnsupportedOperationException("Unimplemented method 'getGlobalSlashCommandById'");
}
@Override
public CompletableFuture<Set<SlashCommand>> getServerSlashCommands(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getServerSlashCommands'");
}
@Override
public CompletableFuture<SlashCommand> getServerSlashCommandById(Server server, long commandId) {
throw new UnsupportedOperationException("Unimplemented method 'getServerSlashCommandById'");
}
@Override
public CompletableFuture<Set<UserContextMenu>> getGlobalUserContextMenus() {
throw new UnsupportedOperationException("Unimplemented method 'getGlobalUserContextMenus'");
}
@Override
public CompletableFuture<UserContextMenu> getGlobalUserContextMenuById(long commandId) {
throw new UnsupportedOperationException("Unimplemented method 'getGlobalUserContextMenuById'");
}
@Override
public CompletableFuture<Set<UserContextMenu>> getServerUserContextMenus(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getServerUserContextMenus'");
}
@Override
public CompletableFuture<UserContextMenu> getServerUserContextMenuById(Server server, long commandId) {
throw new UnsupportedOperationException("Unimplemented method 'getServerUserContextMenuById'");
}
@Override
public CompletableFuture<Set<MessageContextMenu>> getGlobalMessageContextMenus() {
throw new UnsupportedOperationException("Unimplemented method 'getGlobalMessageContextMenus'");
}
@Override
public CompletableFuture<MessageContextMenu> getGlobalMessageContextMenuById(long commandId) {
throw new UnsupportedOperationException("Unimplemented method 'getGlobalMessageContextMenuById'");
}
@Override
public CompletableFuture<Set<MessageContextMenu>> getServerMessageContextMenus(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getServerMessageContextMenus'");
}
@Override
public CompletableFuture<MessageContextMenu> getServerMessageContextMenuById(Server server, long commandId) {
throw new UnsupportedOperationException("Unimplemented method 'getServerMessageContextMenuById'");
}
@Override
public CompletableFuture<Set<ServerApplicationCommandPermissions>> getServerApplicationCommandPermissions(
Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getServerApplicationCommandPermissions'");
}
@Override
public CompletableFuture<ServerApplicationCommandPermissions> getServerApplicationCommandPermissionsById(
Server server, long commandId) {
throw new UnsupportedOperationException("Unimplemented method 'getServerApplicationCommandPermissionsById'");
}
@Override
public CompletableFuture<Set<ApplicationCommand>> bulkOverwriteGlobalApplicationCommands(
Set<? extends ApplicationCommandBuilder<?, ?, ?>> applicationCommandBuilderList) {
throw new UnsupportedOperationException("Unimplemented method 'bulkOverwriteGlobalApplicationCommands'");
}
@Override
public CompletableFuture<Set<ApplicationCommand>> bulkOverwriteServerApplicationCommands(long server,
Set<? extends ApplicationCommandBuilder<?, ?, ?>> applicationCommandBuilderList) {
throw new UnsupportedOperationException("Unimplemented method 'bulkOverwriteServerApplicationCommands'");
}
@Override
public UncachedMessageUtil getUncachedMessageUtil() {
throw new UnsupportedOperationException("Unimplemented method 'getUncachedMessageUtil'");
}
@Override
public Optional<Ratelimiter> getGlobalRatelimiter() {
throw new UnsupportedOperationException("Unimplemented method 'getGlobalRatelimiter'");
}
@Override
public Ratelimiter getGatewayIdentifyRatelimiter() {
throw new UnsupportedOperationException("Unimplemented method 'getGatewayIdentifyRatelimiter'");
}
@Override
public Duration getLatestGatewayLatency() {
throw new UnsupportedOperationException("Unimplemented method 'getLatestGatewayLatency'");
}
@Override
public CompletableFuture<Duration> measureRestLatency() {
throw new UnsupportedOperationException("Unimplemented method 'measureRestLatency'");
}
@Override
public void setMessageCacheSize(int capacity, int storageTimeInSeconds) {
throw new UnsupportedOperationException("Unimplemented method 'setMessageCacheSize'");
}
@Override
public int getDefaultMessageCacheCapacity() {
throw new UnsupportedOperationException("Unimplemented method 'getDefaultMessageCacheCapacity'");
}
@Override
public int getDefaultMessageCacheStorageTimeInSeconds() {
throw new UnsupportedOperationException("Unimplemented method 'getDefaultMessageCacheStorageTimeInSeconds'");
}
@Override
public void setAutomaticMessageCacheCleanupEnabled(boolean automaticMessageCacheCleanupEnabled) {
throw new UnsupportedOperationException("Unimplemented method 'setAutomaticMessageCacheCleanupEnabled'");
}
@Override
public boolean isDefaultAutomaticMessageCacheCleanupEnabled() {
throw new UnsupportedOperationException("Unimplemented method 'isDefaultAutomaticMessageCacheCleanupEnabled'");
}
@Override
public int getCurrentShard() {
throw new UnsupportedOperationException("Unimplemented method 'getCurrentShard'");
}
@Override
public int getTotalShards() {
throw new UnsupportedOperationException("Unimplemented method 'getTotalShards'");
}
@Override
public boolean isWaitingForServersOnStartup() {
throw new UnsupportedOperationException("Unimplemented method 'isWaitingForServersOnStartup'");
}
@Override
public boolean isWaitingForUsersOnStartup() {
throw new UnsupportedOperationException("Unimplemented method 'isWaitingForUsersOnStartup'");
}
@Override
public void updateStatus(UserStatus status) {
throw new UnsupportedOperationException("Unimplemented method 'updateStatus'");
}
@Override
public UserStatus getStatus() {
throw new UnsupportedOperationException("Unimplemented method 'getStatus'");
}
@Override
public void updateActivity(String name) {
throw new UnsupportedOperationException("Unimplemented method 'updateActivity'");
}
@Override
public void updateActivity(ActivityType type, String name) {
throw new UnsupportedOperationException("Unimplemented method 'updateActivity'");
}
@Override
public void updateActivity(String name, String streamingUrl) {
throw new UnsupportedOperationException("Unimplemented method 'updateActivity'");
}
@Override
public void unsetActivity() {
throw new UnsupportedOperationException("Unimplemented method 'unsetActivity'");
}
@Override
public Optional<Activity> getActivity() {
throw new UnsupportedOperationException("Unimplemented method 'getActivity'");
}
@Override
public User getYourself() {
throw new UnsupportedOperationException("Unimplemented method 'getYourself'");
}
@Override
public CompletableFuture<Void> disconnect() {
throw new UnsupportedOperationException("Unimplemented method 'disconnect'");
}
@Override
public void setReconnectDelay(Function<Integer, Integer> reconnectDelayProvider) {
throw new UnsupportedOperationException("Unimplemented method 'setReconnectDelay'");
}
@Override
public int getReconnectDelay(int attempt) {
throw new UnsupportedOperationException("Unimplemented method 'getReconnectDelay'");
}
@Override
public ApplicationInfo getCachedApplicationInfo() {
throw new UnsupportedOperationException("Unimplemented method 'getCachedApplicationInfo'");
}
@Override
public CompletableFuture<ApplicationInfo> requestApplicationInfo() {
throw new UnsupportedOperationException("Unimplemented method 'requestApplicationInfo'");
}
@Override
public CompletableFuture<Webhook> getWebhookById(long id) {
throw new UnsupportedOperationException("Unimplemented method 'getWebhookById'");
}
@Override
public CompletableFuture<IncomingWebhook> getIncomingWebhookByIdAndToken(String id, String token) {
throw new UnsupportedOperationException("Unimplemented method 'getIncomingWebhookByIdAndToken'");
}
@Override
public Set<Long> getUnavailableServers() {
throw new UnsupportedOperationException("Unimplemented method 'getUnavailableServers'");
}
@Override
public CompletableFuture<Invite> getInviteByCode(String code) {
throw new UnsupportedOperationException("Unimplemented method 'getInviteByCode'");
}
@Override
public CompletableFuture<Invite> getInviteWithMemberCountsByCode(String code) {
throw new UnsupportedOperationException("Unimplemented method 'getInviteWithMemberCountsByCode'");
}
@Override
public boolean isUserCacheEnabled() {
throw new UnsupportedOperationException("Unimplemented method 'isUserCacheEnabled'");
}
@Override
public Set<User> getCachedUsers() {
throw new UnsupportedOperationException("Unimplemented method 'getCachedUsers'");
}
@Override
public Optional<User> getCachedUserById(long id) {
throw new UnsupportedOperationException("Unimplemented method 'getCachedUserById'");
}
@Override
public CompletableFuture<User> getUserById(long id) {
throw new UnsupportedOperationException("Unimplemented method 'getUserById'");
}
@Override
public MessageSet getCachedMessages() {
throw new UnsupportedOperationException("Unimplemented method 'getCachedMessages'");
}
@Override
public Optional<Message> getCachedMessageById(long id) {
throw new UnsupportedOperationException("Unimplemented method 'getCachedMessageById'");
}
@Override
public Set<Server> getServers() {
throw new UnsupportedOperationException("Unimplemented method 'getServers'");
}
@Override
public Set<KnownCustomEmoji> getCustomEmojis() {
throw new UnsupportedOperationException("Unimplemented method 'getCustomEmojis'");
}
@Override
public CustomEmoji getKnownCustomEmojiOrCreateCustomEmoji(long id, String name, boolean animated) {
throw new UnsupportedOperationException("Unimplemented method 'getKnownCustomEmojiOrCreateCustomEmoji'");
}
@Override
public CompletableFuture<Set<StickerPack>> getNitroStickerPacks() {
throw new UnsupportedOperationException("Unimplemented method 'getNitroStickerPacks'");
}
@Override
public Optional<Sticker> getStickerById(long id) {
throw new UnsupportedOperationException("Unimplemented method 'getStickerById'");
}
@Override
public CompletableFuture<Sticker> requestStickerById(long id) {
throw new UnsupportedOperationException("Unimplemented method 'requestStickerById'");
}
@Override
public Set<Channel> getChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getChannels'");
}
@Override
public Set<PrivateChannel> getPrivateChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getPrivateChannels'");
}
@Override
public Set<ServerChannel> getServerChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getServerChannels'");
}
@Override
public Set<RegularServerChannel> getRegularServerChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getRegularServerChannels'");
}
@Override
public Set<ChannelCategory> getChannelCategories() {
throw new UnsupportedOperationException("Unimplemented method 'getChannelCategories'");
}
@Override
public Set<ServerTextChannel> getServerTextChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getServerTextChannels'");
}
@Override
public Set<ServerForumChannel> getServerForumChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getServerForumChannels'");
}
@Override
public Set<ServerThreadChannel> getServerThreadChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getServerThreadChannels'");
}
@Override
public Set<ServerThreadChannel> getPrivateServerThreadChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getPrivateServerThreadChannels'");
}
@Override
public Set<ServerThreadChannel> getPublicServerThreadChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getPublicServerThreadChannels'");
}
@Override
public Set<ServerVoiceChannel> getServerVoiceChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getServerVoiceChannels'");
}
@Override
public Set<ServerStageVoiceChannel> getServerStageVoiceChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getServerStageVoiceChannels'");
}
@Override
public Set<TextChannel> getTextChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getTextChannels'");
}
@Override
public Set<VoiceChannel> getVoiceChannels() {
throw new UnsupportedOperationException("Unimplemented method 'getVoiceChannels'");
}
@Override
public Optional<Channel> getChannelById(long id) {
throw new UnsupportedOperationException("Unimplemented method 'getChannelById'");
}
}

View File

@@ -1,443 +0,0 @@
package net.tomatentum.marinara.test.mocks;
import java.time.Instant;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import org.javacord.api.DiscordApi;
import org.javacord.api.entity.channel.TextChannel;
import org.javacord.api.entity.emoji.CustomEmoji;
import org.javacord.api.entity.message.Message;
import org.javacord.api.entity.message.MessageActivity;
import org.javacord.api.entity.message.MessageAttachment;
import org.javacord.api.entity.message.MessageAuthor;
import org.javacord.api.entity.message.MessageFlag;
import org.javacord.api.entity.message.MessageReference;
import org.javacord.api.entity.message.MessageType;
import org.javacord.api.entity.message.Reaction;
import org.javacord.api.entity.message.component.HighLevelComponent;
import org.javacord.api.entity.message.embed.Embed;
import org.javacord.api.entity.permission.Role;
import org.javacord.api.entity.sticker.StickerItem;
import org.javacord.api.entity.user.User;
import org.javacord.api.interaction.MessageInteraction;
import org.javacord.api.listener.ObjectAttachableListener;
import org.javacord.api.listener.interaction.ButtonClickListener;
import org.javacord.api.listener.interaction.MessageComponentCreateListener;
import org.javacord.api.listener.interaction.MessageContextMenuCommandListener;
import org.javacord.api.listener.interaction.SelectMenuChooseListener;
import org.javacord.api.listener.message.CachedMessagePinListener;
import org.javacord.api.listener.message.CachedMessageUnpinListener;
import org.javacord.api.listener.message.MessageAttachableListener;
import org.javacord.api.listener.message.MessageDeleteListener;
import org.javacord.api.listener.message.MessageEditListener;
import org.javacord.api.listener.message.MessageReplyListener;
import org.javacord.api.listener.message.reaction.ReactionAddListener;
import org.javacord.api.listener.message.reaction.ReactionRemoveAllListener;
import org.javacord.api.listener.message.reaction.ReactionRemoveListener;
import org.javacord.api.util.event.ListenerManager;
public class MessageMock implements Message{
@Override
public DiscordApi getApi() {
throw new UnsupportedOperationException("Unimplemented method 'getApi'");
}
@Override
public long getId() {
throw new UnsupportedOperationException("Unimplemented method 'getId'");
}
@Override
public int compareTo(Message arg0) {
throw new UnsupportedOperationException("Unimplemented method 'compareTo'");
}
@Override
public ListenerManager<MessageContextMenuCommandListener> addMessageContextMenuCommandListener(
MessageContextMenuCommandListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageContextMenuCommandListener'");
}
@Override
public List<MessageContextMenuCommandListener> getMessageContextMenuCommandListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageContextMenuCommandListeners'");
}
@Override
public ListenerManager<MessageComponentCreateListener> addMessageComponentCreateListener(
MessageComponentCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageComponentCreateListener'");
}
@Override
public List<MessageComponentCreateListener> getMessageComponentCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageComponentCreateListeners'");
}
@Override
public ListenerManager<SelectMenuChooseListener> addSelectMenuChooseListener(SelectMenuChooseListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addSelectMenuChooseListener'");
}
@Override
public List<SelectMenuChooseListener> getSelectMenuChooseListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getSelectMenuChooseListeners'");
}
@Override
public ListenerManager<ButtonClickListener> addButtonClickListener(ButtonClickListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addButtonClickListener'");
}
@Override
public List<ButtonClickListener> getButtonClickListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getButtonClickListeners'");
}
@Override
public ListenerManager<MessageEditListener> addMessageEditListener(MessageEditListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageEditListener'");
}
@Override
public List<MessageEditListener> getMessageEditListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageEditListeners'");
}
@Override
public ListenerManager<ReactionRemoveListener> addReactionRemoveListener(ReactionRemoveListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addReactionRemoveListener'");
}
@Override
public List<ReactionRemoveListener> getReactionRemoveListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getReactionRemoveListeners'");
}
@Override
public ListenerManager<ReactionAddListener> addReactionAddListener(ReactionAddListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addReactionAddListener'");
}
@Override
public List<ReactionAddListener> getReactionAddListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getReactionAddListeners'");
}
@Override
public ListenerManager<ReactionRemoveAllListener> addReactionRemoveAllListener(ReactionRemoveAllListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addReactionRemoveAllListener'");
}
@Override
public List<ReactionRemoveAllListener> getReactionRemoveAllListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getReactionRemoveAllListeners'");
}
@Override
public ListenerManager<CachedMessageUnpinListener> addCachedMessageUnpinListener(
CachedMessageUnpinListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addCachedMessageUnpinListener'");
}
@Override
public List<CachedMessageUnpinListener> getCachedMessageUnpinListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getCachedMessageUnpinListeners'");
}
@Override
public ListenerManager<CachedMessagePinListener> addCachedMessagePinListener(CachedMessagePinListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addCachedMessagePinListener'");
}
@Override
public List<CachedMessagePinListener> getCachedMessagePinListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getCachedMessagePinListeners'");
}
@Override
public ListenerManager<MessageReplyListener> addMessageReplyListener(MessageReplyListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageReplyListener'");
}
@Override
public List<MessageReplyListener> getMessageReplyListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageReplyListeners'");
}
@Override
public ListenerManager<MessageDeleteListener> addMessageDeleteListener(MessageDeleteListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageDeleteListener'");
}
@Override
public List<MessageDeleteListener> getMessageDeleteListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageDeleteListeners'");
}
@Override
public <T extends MessageAttachableListener & ObjectAttachableListener> Collection<ListenerManager<T>> addMessageAttachableListener(
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageAttachableListener'");
}
@Override
public <T extends MessageAttachableListener & ObjectAttachableListener> void removeMessageAttachableListener(
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeMessageAttachableListener'");
}
@Override
public <T extends MessageAttachableListener & ObjectAttachableListener> Map<T, List<Class<T>>> getMessageAttachableListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageAttachableListeners'");
}
@Override
public <T extends MessageAttachableListener & ObjectAttachableListener> void removeListener(Class<T> listenerClass,
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeListener'");
}
@Override
public boolean canYouReadContent() {
throw new UnsupportedOperationException("Unimplemented method 'canYouReadContent'");
}
@Override
public String getContent() {
throw new UnsupportedOperationException("Unimplemented method 'getContent'");
}
@Override
public Optional<Instant> getLastEditTimestamp() {
throw new UnsupportedOperationException("Unimplemented method 'getLastEditTimestamp'");
}
@Override
public List<MessageAttachment> getAttachments() {
throw new UnsupportedOperationException("Unimplemented method 'getAttachments'");
}
@Override
public List<CustomEmoji> getCustomEmojis() {
throw new UnsupportedOperationException("Unimplemented method 'getCustomEmojis'");
}
@Override
public MessageType getType() {
throw new UnsupportedOperationException("Unimplemented method 'getType'");
}
@Override
public TextChannel getChannel() {
throw new UnsupportedOperationException("Unimplemented method 'getChannel'");
}
@Override
public Optional<MessageActivity> getActivity() {
throw new UnsupportedOperationException("Unimplemented method 'getActivity'");
}
@Override
public EnumSet<MessageFlag> getFlags() {
throw new UnsupportedOperationException("Unimplemented method 'getFlags'");
}
@Override
public boolean isPinned() {
throw new UnsupportedOperationException("Unimplemented method 'isPinned'");
}
@Override
public boolean isTts() {
throw new UnsupportedOperationException("Unimplemented method 'isTts'");
}
@Override
public boolean mentionsEveryone() {
throw new UnsupportedOperationException("Unimplemented method 'mentionsEveryone'");
}
@Override
public List<Embed> getEmbeds() {
throw new UnsupportedOperationException("Unimplemented method 'getEmbeds'");
}
@Override
public Optional<User> getUserAuthor() {
throw new UnsupportedOperationException("Unimplemented method 'getUserAuthor'");
}
@Override
public MessageAuthor getAuthor() {
throw new UnsupportedOperationException("Unimplemented method 'getAuthor'");
}
@Override
public Optional<MessageReference> getMessageReference() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageReference'");
}
@Override
public Optional<Message> getReferencedMessage() {
throw new UnsupportedOperationException("Unimplemented method 'getReferencedMessage'");
}
@Override
public boolean isCachedForever() {
throw new UnsupportedOperationException("Unimplemented method 'isCachedForever'");
}
@Override
public void setCachedForever(boolean cachedForever) {
throw new UnsupportedOperationException("Unimplemented method 'setCachedForever'");
}
@Override
public List<Reaction> getReactions() {
throw new UnsupportedOperationException("Unimplemented method 'getReactions'");
}
@Override
public Optional<MessageInteraction> getMessageInteraction() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageInteraction'");
}
@Override
public List<HighLevelComponent> getComponents() {
throw new UnsupportedOperationException("Unimplemented method 'getComponents'");
}
@Override
public List<User> getMentionedUsers() {
throw new UnsupportedOperationException("Unimplemented method 'getMentionedUsers'");
}
@Override
public List<Role> getMentionedRoles() {
throw new UnsupportedOperationException("Unimplemented method 'getMentionedRoles'");
}
@Override
public Optional<String> getNonce() {
throw new UnsupportedOperationException("Unimplemented method 'getNonce'");
}
@Override
public Set<StickerItem> getStickerItems() {
throw new UnsupportedOperationException("Unimplemented method 'getStickerItems'");
}
@Override
public Optional<Integer> getPosition() {
throw new UnsupportedOperationException("Unimplemented method 'getPosition'");
}
@Override
public CompletableFuture<Void> addReactions(String... unicodeEmojis) {
throw new UnsupportedOperationException("Unimplemented method 'addReactions'");
}
@Override
public CompletableFuture<Void> removeReactionByEmoji(User user, String unicodeEmoji) {
throw new UnsupportedOperationException("Unimplemented method 'removeReactionByEmoji'");
}
@Override
public CompletableFuture<Void> removeReactionByEmoji(String unicodeEmoji) {
throw new UnsupportedOperationException("Unimplemented method 'removeReactionByEmoji'");
}
@Override
public CompletableFuture<Void> removeReactionsByEmoji(User user, String... unicodeEmojis) {
throw new UnsupportedOperationException("Unimplemented method 'removeReactionsByEmoji'");
}
@Override
public CompletableFuture<Void> removeReactionsByEmoji(String... unicodeEmojis) {
throw new UnsupportedOperationException("Unimplemented method 'removeReactionsByEmoji'");
}
@Override
public CompletableFuture<Void> removeOwnReactionByEmoji(String unicodeEmoji) {
throw new UnsupportedOperationException("Unimplemented method 'removeOwnReactionByEmoji'");
}
@Override
public CompletableFuture<Void> removeOwnReactionsByEmoji(String... unicodeEmojis) {
throw new UnsupportedOperationException("Unimplemented method 'removeOwnReactionsByEmoji'");
}
}

View File

@@ -1,146 +0,0 @@
package net.tomatentum.marinara.test.mocks;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.javacord.api.DiscordApi;
import org.javacord.api.entity.channel.TextChannel;
import org.javacord.api.entity.message.component.HighLevelComponent;
import org.javacord.api.entity.permission.PermissionType;
import org.javacord.api.entity.server.Server;
import org.javacord.api.entity.user.User;
import org.javacord.api.interaction.DiscordLocale;
import org.javacord.api.interaction.InteractionType;
import org.javacord.api.interaction.SlashCommandInteraction;
import org.javacord.api.interaction.SlashCommandInteractionOption;
import org.javacord.api.interaction.callback.InteractionFollowupMessageBuilder;
import org.javacord.api.interaction.callback.InteractionImmediateResponseBuilder;
import org.javacord.api.interaction.callback.InteractionOriginalResponseUpdater;
public class SlashCommandInteractionMock implements SlashCommandInteraction{
@Override
public long getCommandId() {
throw new UnsupportedOperationException("Unimplemented method 'getCommandId'");
}
@Override
public String getCommandIdAsString() {
throw new UnsupportedOperationException("Unimplemented method 'getCommandIdAsString'");
}
@Override
public String getCommandName() {
return "test";
}
@Override
public Optional<Long> getRegisteredCommandServerId() {
throw new UnsupportedOperationException("Unimplemented method 'getRegisteredCommandServerId'");
}
@Override
public long getApplicationId() {
throw new UnsupportedOperationException("Unimplemented method 'getApplicationId'");
}
@Override
public InteractionType getType() {
return InteractionType.APPLICATION_COMMAND;
}
@Override
public InteractionImmediateResponseBuilder createImmediateResponder() {
throw new UnsupportedOperationException("Unimplemented method 'createImmediateResponder'");
}
@Override
public CompletableFuture<InteractionOriginalResponseUpdater> respondLater() {
throw new UnsupportedOperationException("Unimplemented method 'respondLater'");
}
@Override
public CompletableFuture<InteractionOriginalResponseUpdater> respondLater(boolean ephemeral) {
throw new UnsupportedOperationException("Unimplemented method 'respondLater'");
}
@Override
public CompletableFuture<Void> respondWithModal(String customId, String title,
List<HighLevelComponent> components) {
throw new UnsupportedOperationException("Unimplemented method 'respondWithModal'");
}
@Override
public InteractionFollowupMessageBuilder createFollowupMessageBuilder() {
throw new UnsupportedOperationException("Unimplemented method 'createFollowupMessageBuilder'");
}
@Override
public Optional<Server> getServer() {
throw new UnsupportedOperationException("Unimplemented method 'getServer'");
}
@Override
public Optional<TextChannel> getChannel() {
throw new UnsupportedOperationException("Unimplemented method 'getChannel'");
}
@Override
public User getUser() {
throw new UnsupportedOperationException("Unimplemented method 'getUser'");
}
@Override
public String getToken() {
throw new UnsupportedOperationException("Unimplemented method 'getToken'");
}
@Override
public int getVersion() {
throw new UnsupportedOperationException("Unimplemented method 'getVersion'");
}
@Override
public DiscordLocale getLocale() {
throw new UnsupportedOperationException("Unimplemented method 'getLocale'");
}
@Override
public Optional<DiscordLocale> getServerLocale() {
throw new UnsupportedOperationException("Unimplemented method 'getServerLocale'");
}
@Override
public Optional<EnumSet<PermissionType>> getBotPermissions() {
throw new UnsupportedOperationException("Unimplemented method 'getBotPermissions'");
}
@Override
public DiscordApi getApi() {
throw new UnsupportedOperationException("Unimplemented method 'getApi'");
}
@Override
public long getId() {
throw new UnsupportedOperationException("Unimplemented method 'getId'");
}
@Override
public List<SlashCommandInteractionOption> getOptions() {
return Arrays.asList(new SlashCommandInteractionOptionMock());
}
@Override
public List<SlashCommandInteractionOption> getArguments() {
return Arrays.asList(new SlashCommandInteractionOptionMock());
}
@Override
public String getFullCommandName() {
return "test";
}
}

View File

@@ -1,97 +0,0 @@
package net.tomatentum.marinara.test.mocks;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.javacord.api.entity.Attachment;
import org.javacord.api.entity.Mentionable;
import org.javacord.api.entity.channel.ServerChannel;
import org.javacord.api.entity.permission.Role;
import org.javacord.api.entity.user.User;
import org.javacord.api.interaction.SlashCommandInteractionOption;
public class SlashCommandInteractionOptionMock implements SlashCommandInteractionOption{
@Override
public List<SlashCommandInteractionOption> getArguments() {
return Collections.emptyList();
}
@Override
public String getName() {
return "foo";
}
@Override
public Optional<Boolean> isFocused() {
throw new UnsupportedOperationException("Unimplemented method 'isFocused'");
}
@Override
public Optional<String> getStringRepresentationValue() {
throw new UnsupportedOperationException("Unimplemented method 'getStringRepresentationValue'");
}
@Override
public Optional<String> getStringValue() {
return Optional.of("test");
}
@Override
public Optional<Long> getLongValue() {
throw new UnsupportedOperationException("Unimplemented method 'getLongValue'");
}
@Override
public Optional<Boolean> getBooleanValue() {
throw new UnsupportedOperationException("Unimplemented method 'getBooleanValue'");
}
@Override
public Optional<User> getUserValue() {
throw new UnsupportedOperationException("Unimplemented method 'getUserValue'");
}
@Override
public Optional<CompletableFuture<User>> requestUserValue() {
throw new UnsupportedOperationException("Unimplemented method 'requestUserValue'");
}
@Override
public Optional<ServerChannel> getChannelValue() {
throw new UnsupportedOperationException("Unimplemented method 'getChannelValue'");
}
@Override
public Optional<Attachment> getAttachmentValue() {
throw new UnsupportedOperationException("Unimplemented method 'getAttachmentValue'");
}
@Override
public Optional<Role> getRoleValue() {
throw new UnsupportedOperationException("Unimplemented method 'getRoleValue'");
}
@Override
public Optional<Mentionable> getMentionableValue() {
throw new UnsupportedOperationException("Unimplemented method 'getMentionableValue'");
}
@Override
public Optional<Double> getDecimalValue() {
throw new UnsupportedOperationException("Unimplemented method 'getDecimalValue'");
}
@Override
public Optional<CompletableFuture<Mentionable>> requestMentionableValue() {
throw new UnsupportedOperationException("Unimplemented method 'requestMentionableValue'");
}
@Override
public List<SlashCommandInteractionOption> getOptions() {
return Collections.emptyList();
}
}

View File

@@ -1,752 +0,0 @@
package net.tomatentum.marinara.test.mocks;
import java.awt.Color;
import java.time.Instant;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import org.javacord.api.DiscordApi;
import org.javacord.api.entity.DiscordClient;
import org.javacord.api.entity.Icon;
import org.javacord.api.entity.activity.Activity;
import org.javacord.api.entity.channel.PrivateChannel;
import org.javacord.api.entity.permission.Role;
import org.javacord.api.entity.server.Server;
import org.javacord.api.entity.user.User;
import org.javacord.api.entity.user.UserFlag;
import org.javacord.api.entity.user.UserStatus;
import org.javacord.api.listener.ObjectAttachableListener;
import org.javacord.api.listener.channel.server.ServerChannelChangeOverwrittenPermissionsListener;
import org.javacord.api.listener.channel.server.voice.ServerVoiceChannelMemberJoinListener;
import org.javacord.api.listener.channel.server.voice.ServerVoiceChannelMemberLeaveListener;
import org.javacord.api.listener.channel.user.PrivateChannelCreateListener;
import org.javacord.api.listener.channel.user.PrivateChannelDeleteListener;
import org.javacord.api.listener.interaction.AutocompleteCreateListener;
import org.javacord.api.listener.interaction.ButtonClickListener;
import org.javacord.api.listener.interaction.InteractionCreateListener;
import org.javacord.api.listener.interaction.MessageComponentCreateListener;
import org.javacord.api.listener.interaction.MessageContextMenuCommandListener;
import org.javacord.api.listener.interaction.ModalSubmitListener;
import org.javacord.api.listener.interaction.SelectMenuChooseListener;
import org.javacord.api.listener.interaction.SlashCommandCreateListener;
import org.javacord.api.listener.interaction.UserContextMenuCommandListener;
import org.javacord.api.listener.message.MessageCreateListener;
import org.javacord.api.listener.message.MessageReplyListener;
import org.javacord.api.listener.message.reaction.ReactionAddListener;
import org.javacord.api.listener.message.reaction.ReactionRemoveListener;
import org.javacord.api.listener.server.member.ServerMemberBanListener;
import org.javacord.api.listener.server.member.ServerMemberJoinListener;
import org.javacord.api.listener.server.member.ServerMemberLeaveListener;
import org.javacord.api.listener.server.member.ServerMemberUnbanListener;
import org.javacord.api.listener.server.role.UserRoleAddListener;
import org.javacord.api.listener.server.role.UserRoleRemoveListener;
import org.javacord.api.listener.user.UserAttachableListener;
import org.javacord.api.listener.user.UserChangeActivityListener;
import org.javacord.api.listener.user.UserChangeAvatarListener;
import org.javacord.api.listener.user.UserChangeDeafenedListener;
import org.javacord.api.listener.user.UserChangeDiscriminatorListener;
import org.javacord.api.listener.user.UserChangeMutedListener;
import org.javacord.api.listener.user.UserChangeNameListener;
import org.javacord.api.listener.user.UserChangeNicknameListener;
import org.javacord.api.listener.user.UserChangePendingListener;
import org.javacord.api.listener.user.UserChangeSelfDeafenedListener;
import org.javacord.api.listener.user.UserChangeSelfMutedListener;
import org.javacord.api.listener.user.UserChangeServerAvatarListener;
import org.javacord.api.listener.user.UserChangeStatusListener;
import org.javacord.api.listener.user.UserChangeTimeoutListener;
import org.javacord.api.listener.user.UserStartTypingListener;
import org.javacord.api.util.event.ListenerManager;
public class UserMock implements User {
@Override
public DiscordApi getApi() {
throw new UnsupportedOperationException("Unimplemented method 'getApi'");
}
@Override
public long getId() {
throw new UnsupportedOperationException("Unimplemented method 'getId'");
}
@Override
public String getName() {
throw new UnsupportedOperationException("Unimplemented method 'getName'");
}
@Override
public ListenerManager<InteractionCreateListener> addInteractionCreateListener(InteractionCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addInteractionCreateListener'");
}
@Override
public List<InteractionCreateListener> getInteractionCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getInteractionCreateListeners'");
}
@Override
public ListenerManager<SlashCommandCreateListener> addSlashCommandCreateListener(
SlashCommandCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addSlashCommandCreateListener'");
}
@Override
public List<SlashCommandCreateListener> getSlashCommandCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getSlashCommandCreateListeners'");
}
@Override
public ListenerManager<AutocompleteCreateListener> addAutocompleteCreateListener(
AutocompleteCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addAutocompleteCreateListener'");
}
@Override
public List<AutocompleteCreateListener> getAutocompleteCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getAutocompleteCreateListeners'");
}
@Override
public ListenerManager<ModalSubmitListener> addModalSubmitListener(ModalSubmitListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addModalSubmitListener'");
}
@Override
public List<ModalSubmitListener> getModalSubmitListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getModalSubmitListeners'");
}
@Override
public ListenerManager<MessageContextMenuCommandListener> addMessageContextMenuCommandListener(
MessageContextMenuCommandListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageContextMenuCommandListener'");
}
@Override
public List<MessageContextMenuCommandListener> getMessageContextMenuCommandListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageContextMenuCommandListeners'");
}
@Override
public ListenerManager<MessageComponentCreateListener> addMessageComponentCreateListener(
MessageComponentCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageComponentCreateListener'");
}
@Override
public List<MessageComponentCreateListener> getMessageComponentCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageComponentCreateListeners'");
}
@Override
public ListenerManager<UserContextMenuCommandListener> addUserContextMenuCommandListener(
UserContextMenuCommandListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserContextMenuCommandListener'");
}
@Override
public List<UserContextMenuCommandListener> getUserContextMenuCommandListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserContextMenuCommandListeners'");
}
@Override
public ListenerManager<SelectMenuChooseListener> addSelectMenuChooseListener(SelectMenuChooseListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addSelectMenuChooseListener'");
}
@Override
public List<SelectMenuChooseListener> getSelectMenuChooseListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getSelectMenuChooseListeners'");
}
@Override
public ListenerManager<ButtonClickListener> addButtonClickListener(ButtonClickListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addButtonClickListener'");
}
@Override
public List<ButtonClickListener> getButtonClickListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getButtonClickListeners'");
}
@Override
public ListenerManager<ServerMemberJoinListener> addServerMemberJoinListener(ServerMemberJoinListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerMemberJoinListener'");
}
@Override
public List<ServerMemberJoinListener> getServerMemberJoinListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerMemberJoinListeners'");
}
@Override
public ListenerManager<ServerMemberLeaveListener> addServerMemberLeaveListener(ServerMemberLeaveListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerMemberLeaveListener'");
}
@Override
public List<ServerMemberLeaveListener> getServerMemberLeaveListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerMemberLeaveListeners'");
}
@Override
public ListenerManager<ServerMemberBanListener> addServerMemberBanListener(ServerMemberBanListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerMemberBanListener'");
}
@Override
public List<ServerMemberBanListener> getServerMemberBanListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerMemberBanListeners'");
}
@Override
public ListenerManager<ServerMemberUnbanListener> addServerMemberUnbanListener(ServerMemberUnbanListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerMemberUnbanListener'");
}
@Override
public List<ServerMemberUnbanListener> getServerMemberUnbanListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerMemberUnbanListeners'");
}
@Override
public ListenerManager<UserRoleRemoveListener> addUserRoleRemoveListener(UserRoleRemoveListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserRoleRemoveListener'");
}
@Override
public List<UserRoleRemoveListener> getUserRoleRemoveListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserRoleRemoveListeners'");
}
@Override
public ListenerManager<UserRoleAddListener> addUserRoleAddListener(UserRoleAddListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserRoleAddListener'");
}
@Override
public List<UserRoleAddListener> getUserRoleAddListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserRoleAddListeners'");
}
@Override
public ListenerManager<ServerChannelChangeOverwrittenPermissionsListener> addServerChannelChangeOverwrittenPermissionsListener(
ServerChannelChangeOverwrittenPermissionsListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerChannelChangeOverwrittenPermissionsListener'");
}
@Override
public List<ServerChannelChangeOverwrittenPermissionsListener> getServerChannelChangeOverwrittenPermissionsListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerChannelChangeOverwrittenPermissionsListeners'");
}
@Override
public ListenerManager<ServerVoiceChannelMemberLeaveListener> addServerVoiceChannelMemberLeaveListener(
ServerVoiceChannelMemberLeaveListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerVoiceChannelMemberLeaveListener'");
}
@Override
public List<ServerVoiceChannelMemberLeaveListener> getServerVoiceChannelMemberLeaveListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerVoiceChannelMemberLeaveListeners'");
}
@Override
public ListenerManager<ServerVoiceChannelMemberJoinListener> addServerVoiceChannelMemberJoinListener(
ServerVoiceChannelMemberJoinListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addServerVoiceChannelMemberJoinListener'");
}
@Override
public List<ServerVoiceChannelMemberJoinListener> getServerVoiceChannelMemberJoinListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getServerVoiceChannelMemberJoinListeners'");
}
@Override
public ListenerManager<PrivateChannelDeleteListener> addPrivateChannelDeleteListener(
PrivateChannelDeleteListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addPrivateChannelDeleteListener'");
}
@Override
public List<PrivateChannelDeleteListener> getPrivateChannelDeleteListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getPrivateChannelDeleteListeners'");
}
@Override
public ListenerManager<PrivateChannelCreateListener> addPrivateChannelCreateListener(
PrivateChannelCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addPrivateChannelCreateListener'");
}
@Override
public List<PrivateChannelCreateListener> getPrivateChannelCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getPrivateChannelCreateListeners'");
}
@Override
public ListenerManager<UserChangeDeafenedListener> addUserChangeDeafenedListener(
UserChangeDeafenedListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeDeafenedListener'");
}
@Override
public List<UserChangeDeafenedListener> getUserChangeDeafenedListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeDeafenedListeners'");
}
@Override
public ListenerManager<UserChangeNicknameListener> addUserChangeNicknameListener(
UserChangeNicknameListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeNicknameListener'");
}
@Override
public List<UserChangeNicknameListener> getUserChangeNicknameListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeNicknameListeners'");
}
@Override
public ListenerManager<UserChangePendingListener> addUserChangePendingListener(UserChangePendingListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangePendingListener'");
}
@Override
public List<UserChangePendingListener> getUserChangePendingListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangePendingListeners'");
}
@Override
public ListenerManager<UserStartTypingListener> addUserStartTypingListener(UserStartTypingListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserStartTypingListener'");
}
@Override
public List<UserStartTypingListener> getUserStartTypingListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserStartTypingListeners'");
}
@Override
public ListenerManager<UserChangeDiscriminatorListener> addUserChangeDiscriminatorListener(
UserChangeDiscriminatorListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeDiscriminatorListener'");
}
@Override
public List<UserChangeDiscriminatorListener> getUserChangeDiscriminatorListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeDiscriminatorListeners'");
}
@Override
public ListenerManager<UserChangeStatusListener> addUserChangeStatusListener(UserChangeStatusListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeStatusListener'");
}
@Override
public List<UserChangeStatusListener> getUserChangeStatusListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeStatusListeners'");
}
@Override
public ListenerManager<UserChangeServerAvatarListener> addUserChangeServerAvatarListener(
UserChangeServerAvatarListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeServerAvatarListener'");
}
@Override
public List<UserChangeServerAvatarListener> getUserChangeServerAvatarListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeServerAvatarListeners'");
}
@Override
public ListenerManager<UserChangeSelfMutedListener> addUserChangeSelfMutedListener(
UserChangeSelfMutedListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeSelfMutedListener'");
}
@Override
public List<UserChangeSelfMutedListener> getUserChangeSelfMutedListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeSelfMutedListeners'");
}
@Override
public ListenerManager<UserChangeNameListener> addUserChangeNameListener(UserChangeNameListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeNameListener'");
}
@Override
public List<UserChangeNameListener> getUserChangeNameListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeNameListeners'");
}
@Override
public ListenerManager<UserChangeTimeoutListener> addUserChangeTimeoutListener(UserChangeTimeoutListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeTimeoutListener'");
}
@Override
public List<UserChangeTimeoutListener> getUserChangeTimeoutListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeTimeoutListeners'");
}
@Override
public ListenerManager<UserChangeAvatarListener> addUserChangeAvatarListener(UserChangeAvatarListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeAvatarListener'");
}
@Override
public List<UserChangeAvatarListener> getUserChangeAvatarListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeAvatarListeners'");
}
@Override
public ListenerManager<UserChangeSelfDeafenedListener> addUserChangeSelfDeafenedListener(
UserChangeSelfDeafenedListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeSelfDeafenedListener'");
}
@Override
public List<UserChangeSelfDeafenedListener> getUserChangeSelfDeafenedListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeSelfDeafenedListeners'");
}
@Override
public ListenerManager<UserChangeMutedListener> addUserChangeMutedListener(UserChangeMutedListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeMutedListener'");
}
@Override
public List<UserChangeMutedListener> getUserChangeMutedListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeMutedListeners'");
}
@Override
public ListenerManager<UserChangeActivityListener> addUserChangeActivityListener(
UserChangeActivityListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserChangeActivityListener'");
}
@Override
public List<UserChangeActivityListener> getUserChangeActivityListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserChangeActivityListeners'");
}
@Override
public ListenerManager<ReactionRemoveListener> addReactionRemoveListener(ReactionRemoveListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addReactionRemoveListener'");
}
@Override
public List<ReactionRemoveListener> getReactionRemoveListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getReactionRemoveListeners'");
}
@Override
public ListenerManager<ReactionAddListener> addReactionAddListener(ReactionAddListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addReactionAddListener'");
}
@Override
public List<ReactionAddListener> getReactionAddListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getReactionAddListeners'");
}
@Override
public ListenerManager<MessageCreateListener> addMessageCreateListener(MessageCreateListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageCreateListener'");
}
@Override
public List<MessageCreateListener> getMessageCreateListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageCreateListeners'");
}
@Override
public ListenerManager<MessageReplyListener> addMessageReplyListener(MessageReplyListener listener) {
throw new UnsupportedOperationException("Unimplemented method 'addMessageReplyListener'");
}
@Override
public List<MessageReplyListener> getMessageReplyListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getMessageReplyListeners'");
}
@Override
public <T extends UserAttachableListener & ObjectAttachableListener> Collection<ListenerManager<T>> addUserAttachableListener(
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'addUserAttachableListener'");
}
@Override
public <T extends UserAttachableListener & ObjectAttachableListener> void removeUserAttachableListener(T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeUserAttachableListener'");
}
@Override
public <T extends UserAttachableListener & ObjectAttachableListener> Map<T, List<Class<T>>> getUserAttachableListeners() {
throw new UnsupportedOperationException("Unimplemented method 'getUserAttachableListeners'");
}
@Override
public <T extends UserAttachableListener & ObjectAttachableListener> void removeListener(Class<T> listenerClass,
T listener) {
throw new UnsupportedOperationException("Unimplemented method 'removeListener'");
}
@Override
public String getDiscriminator() {
throw new UnsupportedOperationException("Unimplemented method 'getDiscriminator'");
}
@Override
public boolean isBot() {
throw new UnsupportedOperationException("Unimplemented method 'isBot'");
}
@Override
public Set<Activity> getActivities() {
throw new UnsupportedOperationException("Unimplemented method 'getActivities'");
}
@Override
public UserStatus getStatus() {
throw new UnsupportedOperationException("Unimplemented method 'getStatus'");
}
@Override
public UserStatus getStatusOnClient(DiscordClient client) {
throw new UnsupportedOperationException("Unimplemented method 'getStatusOnClient'");
}
@Override
public EnumSet<UserFlag> getUserFlags() {
throw new UnsupportedOperationException("Unimplemented method 'getUserFlags'");
}
@Override
public Optional<String> getAvatarHash() {
throw new UnsupportedOperationException("Unimplemented method 'getAvatarHash'");
}
@Override
public Icon getAvatar() {
throw new UnsupportedOperationException("Unimplemented method 'getAvatar'");
}
@Override
public Icon getAvatar(int size) {
throw new UnsupportedOperationException("Unimplemented method 'getAvatar'");
}
@Override
public Optional<String> getServerAvatarHash(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getServerAvatarHash'");
}
@Override
public Optional<Icon> getServerAvatar(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getServerAvatar'");
}
@Override
public Optional<Icon> getServerAvatar(Server server, int size) {
throw new UnsupportedOperationException("Unimplemented method 'getServerAvatar'");
}
@Override
public Icon getEffectiveAvatar(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getEffectiveAvatar'");
}
@Override
public Icon getEffectiveAvatar(Server server, int size) {
throw new UnsupportedOperationException("Unimplemented method 'getEffectiveAvatar'");
}
@Override
public boolean hasDefaultAvatar() {
throw new UnsupportedOperationException("Unimplemented method 'hasDefaultAvatar'");
}
@Override
public Set<Server> getMutualServers() {
throw new UnsupportedOperationException("Unimplemented method 'getMutualServers'");
}
@Override
public String getDisplayName(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getDisplayName'");
}
@Override
public Optional<String> getNickname(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getNickname'");
}
@Override
public Optional<Instant> getServerBoostingSinceTimestamp(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getServerBoostingSinceTimestamp'");
}
@Override
public Optional<Instant> getTimeout(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getTimeout'");
}
@Override
public boolean isPending(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'isPending'");
}
@Override
public boolean isSelfMuted(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'isSelfMuted'");
}
@Override
public boolean isSelfDeafened(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'isSelfDeafened'");
}
@Override
public Optional<Instant> getJoinedAtTimestamp(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getJoinedAtTimestamp'");
}
@Override
public List<Role> getRoles(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getRoles'");
}
@Override
public Optional<Color> getRoleColor(Server server) {
throw new UnsupportedOperationException("Unimplemented method 'getRoleColor'");
}
@Override
public Optional<PrivateChannel> getPrivateChannel() {
throw new UnsupportedOperationException("Unimplemented method 'getPrivateChannel'");
}
@Override
public CompletableFuture<PrivateChannel> openPrivateChannel() {
throw new UnsupportedOperationException("Unimplemented method 'openPrivateChannel'");
}
}