242 Commits

Author SHA1 Message Date
Lee
45a0a4332e test 2024-12-27 13:49:04 +00:00
Lee
9089767dc5 test 2024-12-27 13:48:53 +00:00
Lee
b3a6284e40 cleanup 2024-12-27 13:04:57 +00:00
Lee
5f099a97f0 remove some things and bump depends 2024-12-27 12:50:13 +00:00
577c895169 Merge remote-tracking branch 'origin/master' 2024-11-29 03:38:35 +00:00
6db2a01bb3 expire pastes after a month 2024-11-29 03:38:28 +00:00
Lee
4cc4334df4 Merge pull request 'Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.5' (#44) from renovate/spring-boot into master
Reviewed-on: Fascinated/Bat#44
2024-11-02 23:16:31 +00:00
Lee
a4acdc2ec1 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.1' (#45) from renovate/org.apache.httpcomponents.client5-httpclient5-5.x into master
Reviewed-on: Fascinated/Bat#45
2024-11-02 23:16:18 +00:00
Lee
7ca984e785 Merge pull request 'Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.16.0' (#46) from renovate/io.sentry-sentry-spring-boot-starter-jakarta-7.x into master
Reviewed-on: Fascinated/Bat#46
2024-11-02 23:16:13 +00:00
Lee
53730a82cf Merge pull request 'Update dependency io.mongock:mongock-bom to v5.5.0' (#47) from renovate/io.mongock-mongock-bom-5.x into master
Reviewed-on: Fascinated/Bat#47
2024-11-02 23:16:06 +00:00
Lee
6f4a787ccb Merge pull request 'Update dependency io.mongock:mongock-springboot-v3 to v5.5.0' (#48) from renovate/io.mongock-mongock-springboot-v3-5.x into master
Reviewed-on: Fascinated/Bat#48
2024-11-02 23:16:02 +00:00
Lee
2b588a5940 Merge pull request 'Update dependency io.mongock:mongodb-springdata-v4-driver to v5.5.0' (#49) from renovate/io.mongock-mongodb-springdata-v4-driver-5.x into master
Reviewed-on: Fascinated/Bat#49
2024-11-02 23:15:56 +00:00
Lee
fe4cf3bbf4 Merge pull request 'Update eclipse-temurin Docker tag to v17.0.13_11-jre-focal' (#50) from renovate/eclipse-temurin-17.x into master
Reviewed-on: Fascinated/Bat#50
2024-11-02 23:15:51 +00:00
ede931f994 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.1 2024-10-28 18:01:11 +00:00
d5ed2b0b13 Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.5 2024-10-24 14:01:29 +00:00
4479bce0a4 Update eclipse-temurin Docker tag to v17.0.13_11-jre-focal 2024-10-24 04:01:33 +00:00
3c80b3ca4b Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.16.0 2024-10-23 14:01:31 +00:00
65fd68f76c Update dependency io.mongock:mongodb-springdata-v4-driver to v5.5.0 2024-10-17 00:02:24 +00:00
6640dd4368 Update dependency io.mongock:mongock-springboot-v3 to v5.5.0 2024-10-16 23:00:45 +00:00
96cb634fd4 Update dependency io.mongock:mongock-bom to v5.5.0 2024-10-16 23:00:43 +00:00
Lee
0f9a23e4a2 Update pom.xml 2024-09-02 08:25:19 +00:00
Lee
eb3d8eea29 Merge pull request 'Update dependency maven to v3.9.9' (#42) from renovate/maven-3.x into master
Reviewed-on: Fascinated/Bat#42
2024-09-02 08:24:54 +00:00
Lee
7e45b5d880 Merge pull request 'Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.3' (#43) from renovate/spring-boot into master
Reviewed-on: Fascinated/Bat#43
2024-09-01 01:50:49 +00:00
892b85ccb4 update msg log paste 2024-08-25 01:58:07 +01:00
f291344c45 oops 2024-08-22 20:47:11 +01:00
df9b0e2604 oopsie 2024-08-22 20:31:22 +01:00
2695a2994a add coin flip command 2024-08-22 20:23:11 +01:00
fa50eb9873 Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.3 2024-08-22 19:01:10 +00:00
58bb976f96 Update dependency maven to v3.9.9 2024-08-19 21:01:17 +00:00
3615ef4b92 Merge remote-tracking branch 'origin/master' 2024-08-15 13:59:19 +01:00
5c78ec907f fix minecraft player lookup error handling 2024-08-15 13:59:13 +01:00
Lee
c380878039 Merge pull request 'Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.14.0' (#40) from renovate/io.sentry-sentry-spring-boot-starter-jakarta-7.x into master
Reviewed-on: Fascinated/Bat#40
2024-08-13 17:28:28 +00:00
cfaa501377 Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.14.0 2024-08-13 09:01:17 +00:00
Lee
6f12062311 Merge pull request 'Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.13.0' (#39) from renovate/io.sentry-sentry-spring-boot-starter-jakarta-7.x into master
Reviewed-on: Fascinated/Bat#39
2024-07-31 15:59:30 +00:00
3edfab3adb Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.13.0 2024-07-31 10:00:36 +00:00
Lee
25d4b247b3 Merge pull request 'Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.2' (#38) from renovate/org.springframework.boot-spring-boot-starter-parent-3.x into master
Reviewed-on: Fascinated/Bat#38
2024-07-30 20:52:04 +00:00
Lee
393c7741ca Merge pull request 'Update eclipse-temurin Docker tag to v17.0.12_7-jre-focal' (#18) from renovate/eclipse-temurin-17.x into master
Reviewed-on: Fascinated/Bat#18
2024-07-30 20:51:59 +00:00
Lee
001836c88b Merge pull request 'Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.12.1' (#16) from renovate/io.sentry-sentry-spring-boot-starter-jakarta-7.x into master
Reviewed-on: Fascinated/Bat#16
2024-07-30 20:51:53 +00:00
Lee
be7e03d641 Merge pull request 'Update dependency se.michaelthelin.spotify:spotify-web-api-java to v8.4.1' (#19) from renovate/se.michaelthelin.spotify-spotify-web-api-java-8.x into master
Reviewed-on: Fascinated/Bat#19
2024-07-30 20:51:46 +00:00
db357a63f5 Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.2 2024-07-26 12:03:33 +00:00
e50fe57ee6 Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.12.1 2024-07-25 13:00:41 +00:00
2c017d0603 Update dependency se.michaelthelin.spotify:spotify-web-api-java to v8.4.1 2024-07-24 20:01:06 +00:00
f32d278a6c Update eclipse-temurin Docker tag to v17.0.12_7-jre-focal 2024-07-23 01:01:16 +00:00
b8ebc1de24 fix in dms 2024-07-16 14:40:53 +01:00
2b2e10d994 oopsie 2024-07-16 14:37:46 +01:00
8526036044 add scoresaber score summary 2024-07-16 14:35:02 +01:00
f5c31195da fix log title 2024-07-10 10:42:19 +01:00
d6175b3f92 oops 2024-07-10 06:00:40 +01:00
96e7518f72 fix interactions 2024-07-09 23:02:12 +01:00
f1bc2b2aaa add user validation to moderation and to user lookup 2024-07-09 20:34:56 +01:00
4ec65c8d6e validate id when getting user 2024-07-09 20:24:50 +01:00
38465f544d fix past tense 2024-07-09 20:19:21 +01:00
a3f4e2b918 finish moderation 2024-07-09 19:46:48 +01:00
bc57834366 fix spelling 2024-07-07 07:02:49 +01:00
87a56700ec add stat channels feature 2024-07-07 06:50:25 +01:00
6d98977198 Merge remote-tracking branch 'origin/master' 2024-07-07 05:50:21 +01:00
1256d2ddf9 change bot motd 2024-07-07 05:46:48 +01:00
Lee
7cf970df77 Merge pull request 'Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.0' (#14) from renovate/org.apache.maven.plugins-maven-shade-plugin-3.x into master
Reviewed-on: Fascinated/Bat#14
2024-07-07 02:35:48 +00:00
Lee
52557b5c65 Merge pull request 'Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.11.0' (#13) from renovate/io.sentry-sentry-spring-boot-starter-jakarta-7.x into master
Reviewed-on: Fascinated/Bat#13
2024-07-07 02:35:24 +00:00
898a39e99c change some command categories 2024-07-07 03:01:36 +01:00
7a66ed4d87 Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.0 2024-07-07 02:00:30 +00:00
5cc504d4ed Update dependency io.sentry:sentry-spring-boot-starter-jakarta to v7.11.0 2024-07-07 02:00:28 +00:00
29b44edc6b Merge remote-tracking branch 'origin/master' 2024-07-07 02:18:16 +01:00
2a7e2acc88 cleanup 2024-07-07 02:18:10 +01:00
Lee
0d92a49d95 Merge pull request 'Update dependency io.mongock:mongock-bom to v5.4.4' (#12) from renovate/io.mongock-mongock-bom-5.x into master
Reviewed-on: Fascinated/Bat#12
2024-07-07 01:00:59 +00:00
Lee
2d8779d8e0 Merge pull request 'Update dependency com.google.code.gson:gson to v2.11.0' (#11) from renovate/com.google.code.gson-gson-2.x into master
Reviewed-on: Fascinated/Bat#11
2024-07-07 01:00:50 +00:00
765805fa7a Update dependency io.mongock:mongock-bom to v5.4.4 2024-07-07 01:00:30 +00:00
1d36479a82 Update dependency com.google.code.gson:gson to v2.11.0 2024-07-07 01:00:28 +00:00
Lee
9d6f3b9fef Merge pull request 'Update dependency org.projectlombok:lombok to v1.18.34' (#10) from renovate/org.projectlombok-lombok-1.x into master
Reviewed-on: Fascinated/Bat#10
2024-07-07 00:44:25 +00:00
Lee
9be60fee4c Merge pull request 'Update dependency maven to v3.9.8' (#9) from renovate/maven-3.x into master
Reviewed-on: Fascinated/Bat#9
2024-07-07 00:44:19 +00:00
cb82716a17 Update dependency org.projectlombok:lombok to v1.18.34 2024-07-07 00:42:58 +00:00
80439a3329 Update dependency maven to v3.9.8 2024-07-07 00:42:57 +00:00
Lee
627062ef23 Update renovate.json 2024-07-07 00:42:09 +00:00
25dd6cb0dc silly me 2024-07-07 01:34:46 +01:00
217b284f14 move lookup to a sub command and add mem usage to the bot stats command 2024-07-07 01:34:27 +01:00
843bb34fb4 add paste command 2024-07-07 01:23:20 +01:00
8a01359f6e Merge remote-tracking branch 'origin/master' 2024-07-07 01:19:31 +01:00
8f85ce91da oopsie!!!!!!!!! 2024-07-07 01:12:22 +01:00
Lee
93f232805e revert 585d3e079390a9dd5f24d87499b0da27556ca617
revert add version number to the embeds
2024-07-06 23:58:09 +00:00
Lee
41f92400c7 Update src/main/java/cc/fascinated/bat/features/base/BaseFeature.java 2024-07-06 23:57:58 +00:00
585d3e0793 add version number to the embeds 2024-07-07 00:28:58 +01:00
b5ac5d6a9b only allow sniped messages to be sniped for 1 hour after deletion 2024-07-07 00:10:39 +01:00
d9dd175174 update bot invite url 2024-07-06 21:17:23 +01:00
7a1ffc0538 update cache expiration policy 2024-07-06 21:14:20 +01:00
04c4533c40 update command log 2024-07-06 20:08:26 +01:00
353962e569 enable spotify linking (even tho it doesn't work w/o me adding you rn) 2024-07-06 20:02:20 +01:00
d0ba6e72a4 fix pp size for not in guild 2024-07-06 19:41:16 +01:00
b63b25f8ab update pp size command 2024-07-06 19:37:26 +01:00
2627b80148 update pp size command 2024-07-06 19:36:27 +01:00
16bbda57f6 add ppsize command 2024-07-06 19:34:03 +01:00
e65b7b8232 Merge remote-tracking branch 'origin/master' 2024-07-06 17:26:37 +01:00
d90bdfe3b6 cleanup bot admin 2024-07-06 17:26:31 +01:00
8def168ef7 bob 2024-07-06 09:22:58 +01:00
9379ebb33d make the server watcher list command look better 2024-07-06 07:35:06 +01:00
bbbbce557b oopsie 2024-07-06 07:21:19 +01:00
6fef1d0092 check feature states 2024-07-06 06:26:33 +01:00
f7aba7a49b lower retry limit 2024-07-06 06:24:53 +01:00
514f4757a9 impl server watcher for minecraft servers 2024-07-06 06:21:05 +01:00
ee7e8b64c5 add minecraft server and player lookups 2024-07-06 05:34:50 +01:00
6de1e8b2b1 fix access token refreshing?!??! 2024-07-06 04:18:10 +01:00
98e9003129 update bot joining guild message 2024-07-06 04:14:06 +01:00
9d78432211 add leveling feature 2024-07-06 04:04:38 +01:00
60ce8df108 consistency 2024-07-06 02:11:02 +01:00
ab5cec535b update sync cmd title 2024-07-06 02:04:37 +01:00
ec9b0cc862 add auto role sync command 2024-07-06 02:01:20 +01:00
d45cd48ff6 no need for this, oops 2024-07-06 00:42:14 +01:00
3126935057 add checks to the skip command 2024-07-06 00:41:31 +01:00
27244d0d98 use expiring map for users 2024-07-06 00:34:53 +01:00
de1da2391d add currently playing cache to spotify 2024-07-06 00:31:48 +01:00
9395ae73b9 use Sentry hints 2024-07-06 00:24:06 +01:00
fa932b7fc2 oops 2024-07-06 00:19:52 +01:00
bd340448a1 catch exceptions 2024-07-06 00:18:06 +01:00
45460f8b90 update check mark emoji 2024-07-06 00:10:31 +01:00
fbb292a591 oopsie 2024-07-06 00:05:52 +01:00
31aad2744c oopsie 2024-07-06 00:02:45 +01:00
35b8fff808 fix npe 2024-07-06 00:00:53 +01:00
8cc465e53d clean spotify commands 2024-07-05 23:59:27 +01:00
ec54d5427e update interaction error message 2024-07-05 23:35:41 +01:00
07c5a7358b fix help cmd 2024-07-05 23:24:36 +01:00
4aae21b594 update help cmd for running outside a guild 2024-07-05 23:21:28 +01:00
650556079b fix help not working without a guild 2024-07-05 23:15:29 +01:00
29d3fe3701 fix npe part 2 2024-07-05 23:13:12 +01:00
4cc48412f7 don't log as much when getting scores for SS 2024-07-05 23:02:27 +01:00
ccdeebdc1c fix npe 2024-07-05 22:58:32 +01:00
6dc801dda6 yes! 2024-07-05 22:38:14 +01:00
d01c7d4965 maybe fix this? 2024-07-05 22:35:29 +01:00
0e33179260 maybe fix this? 2024-07-05 22:33:00 +01:00
36d29caa7a change avatar url in the log 2024-07-05 22:29:25 +01:00
a605ab2dba fix some logging things 2024-07-05 21:47:29 +01:00
863206bb9f change log color for voice channel switching 2024-07-05 21:42:47 +01:00
a7af4108c6 switch voice channel log 2024-07-05 21:38:21 +01:00
fdd36d4385 fix markdown in the message breaking the log 2024-07-05 21:12:25 +01:00
0cfccc70d8 update log format for messages 2024-07-05 21:03:56 +01:00
2791d6328e update depend 2024-07-05 21:02:18 +01:00
b4f4a12da8 fix double interaction reply 2024-07-05 20:49:22 +01:00
bb81c098b2 update scoresaber me/user command to show raw per global 2024-07-05 20:44:43 +01:00
bef2b695f5 remove some debug and fix depends on for scoresaber service 2024-07-05 19:49:16 +01:00
d575e0ec9e fix for real this time 2024-07-05 19:46:06 +01:00
4f97e181a7 fix log error 2024-07-05 19:43:18 +01:00
b5b306cc6d fix welcome msg 2024-07-05 19:40:01 +01:00
5b917af1ca fix intent 2024-07-05 19:35:33 +01:00
0b09b8ba5f default disable all features and add bot join guild message 2024-07-05 19:33:10 +01:00
4e866895a0 impl counter feature 2024-07-05 19:07:32 +01:00
f6a23e4888 update role log embed 2024-07-04 18:15:05 +01:00
75da7a4b51 a lil cleanup and add role perms when adding and removing a role to the log 2024-07-04 18:04:15 +01:00
313f43172d who even cares about this 2024-07-04 18:00:44 +01:00
6efb042f14 fix role log color 2024-07-04 18:00:16 +01:00
9be80a0f7e nvm to this too 2024-07-04 17:56:56 +01:00
cd9563f77e nvm 2024-07-04 17:56:39 +01:00
0ba532a9b5 add channel position update log 2024-07-04 17:55:10 +01:00
96c4e03e81 add role update position log 2024-07-04 17:54:06 +01:00
3995bf9992 add thread archive event 2024-07-04 17:50:56 +01:00
8946a18b0b update log message 2024-07-04 17:45:39 +01:00
6ebfb4b289 fix log 2024-07-04 17:17:26 +01:00
35223c376a holy new events that are getting logged 2024-07-04 17:15:34 +01:00
f637faf0b6 yes 2024-07-04 15:59:16 +01:00
16e956d718 fix button interactions 2024-07-04 15:53:49 +01:00
ee62eae519 fix button interactions 2024-07-04 15:52:43 +01:00
f7aea851b2 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/cc/fascinated/bat/features/tmdb/command/MovieSubCommand.java
2024-07-04 15:52:17 +01:00
0e781f3d9a fix button interactions 2024-07-04 15:51:50 +01:00
0c6f3a0b4c silly resource leak nick 2024-07-04 14:50:45 +00:00
c78033f409 fix cached footer 2024-07-04 15:44:05 +01:00
9a5609f40e update scoresaber command messages 2024-07-04 15:42:16 +01:00
7abdcd4d95 fix 2024-07-04 15:36:52 +01:00
92a0c23b49 yes 2024-07-04 15:32:24 +01:00
65ba1d91ac Update src/main/java/cc/fascinated/bat/command/InternalCommandInfo.java 2024-07-04 14:31:30 +00:00
4ae2e7566a ples bby gurl 2024-07-04 15:27:08 +01:00
5e17f655a4 ples bby gurl 2024-07-04 15:25:03 +01:00
11299b3ca7 fix? 2024-07-04 15:20:26 +01:00
d023e21575 help menu use proper button ids 2024-07-04 14:57:54 +01:00
d70a29d363 use a perm check for the list buttons 2024-07-04 14:43:15 +01:00
7bf468b470 fix invite log channel 2024-07-04 14:36:07 +01:00
0d9b6ed8f8 oops, cleanup imports 2024-07-04 14:21:30 +01:00
69adc56e4e re-impl help cmd and fix cmd categories 2024-07-04 14:21:02 +01:00
57d5dc0c42 Merge pull request 'lol' (#8) from Rainnny/Bat:master into master
Reviewed-on: Fascinated/Bat#8
2024-07-04 13:02:29 +00:00
ee1b2e0ae0 lol 2024-07-04 09:01:56 -04:00
Lee
65af4c8c16 Merge pull request 'New command system' (#7) from Rainnny/Bat:master into master
Reviewed-on: Fascinated/Bat#7
2024-07-04 12:58:35 +00:00
47b4796695 fix subcomamnds not having options 2024-07-04 08:51:27 -04:00
4fdd00453a rework command system 2024-07-04 08:47:32 -04:00
e19334a9ef dont require sentry 2024-07-04 07:20:31 -04:00
66a2d8b2a9 ????? 2024-07-04 12:05:37 +01:00
cbc28701c9 fix cmds?? 2024-07-04 12:02:12 +01:00
de6eabc1b7 user install commands 2024-07-04 11:58:54 +01:00
26fddc0493 pls fix 2024-07-04 11:53:25 +01:00
50796d00f0 MAYBE USER INSTALL COMMANDS PLEASE??~!?!?!?!?!?!?!!!?!?!!?!!?!?!?!!!?!??!??!?!?!?!?!?!?!?!?!?!?!?!?! 2024-07-04 11:46:54 +01:00
bf2e046718 jda is wank! 2024-07-04 11:16:25 +01:00
05bc0f0a41 jda is wank! 2024-07-04 11:12:42 +01:00
21e7ddf549 slowmode update logging 2024-07-04 11:00:32 +01:00
14ff692b87 add channel region changing logging 2024-07-04 10:49:21 +01:00
26b7b7158a add role color and icon update, and add channel nsfw and user limit update logging 2024-07-04 10:40:51 +01:00
626a9bd77d update log messages and add bitrate and topic change logs 2024-07-04 10:22:19 +01:00
06ded19492 fix new avatar being broken if they remove their avatar 2024-07-04 09:57:12 +01:00
6ba802912f add role create, delete, rename and update permissions logs 2024-07-04 09:56:06 +01:00
c284bb8a7f update the log remove command to be the same design as the set one 2024-07-04 09:41:21 +01:00
dbe6fb4762 add channel permission update logging 2024-07-04 09:36:40 +01:00
a0e0b82f40 add user lookup command 2024-07-04 09:15:26 +01:00
96e675a6be update msg 2024-07-04 07:53:03 +01:00
ed79a46af3 update format for messages in logging 2024-07-04 07:51:04 +01:00
ee138cb5a9 update format for messages in logging 2024-07-04 07:49:35 +01:00
45bfae281e update logging topics 2024-07-04 07:43:53 +01:00
52d4b65d92 update message 2024-07-04 07:09:01 +01:00
5b0f06efc2 add topics to logs 2024-07-04 07:06:54 +01:00
43c5473a4f don't show old avatar url and make the thumbnail of the log the new avatar 2024-07-04 07:03:48 +01:00
dc04a2f36a fix channel rename log 2024-07-04 07:01:46 +01:00
407ee6f1e9 log errors to a channel 2024-07-04 06:55:56 +01:00
09d850146a add creation time for user and guild log 2024-07-04 06:47:19 +01:00
e8fa4c72dd disable user and guild load log 2024-07-04 06:46:33 +01:00
c31ec09e0f make the log embeds more fancy 2024-07-04 06:44:55 +01:00
4148f6e05f check if the member is still boosting and update log set messages 2024-07-04 06:41:17 +01:00
0120fa24ef find users in a voice channel when starting to make logs more accurate 2024-07-04 06:24:51 +01:00
4a522c084d add emojis to the log category buttons and add a home button 2024-07-04 06:21:31 +01:00
188124991e fix for losing data... LOL 2024-07-04 05:54:13 +01:00
7f09c6d06c remove unneeded check 2024-07-04 05:49:47 +01:00
e873988c47 use pages for the log list command and tell the user about the list command 2024-07-04 05:48:20 +01:00
79d20672c5 update log 2024-07-04 05:28:06 +01:00
772787a98e make log messages more consistent 2024-07-04 05:25:19 +01:00
b6ba778ff2 fixes 2024-07-04 05:14:47 +01:00
cdd953351a add emoji logs and fix log channels that are set from vanishing 2024-07-04 05:10:35 +01:00
c1d775c9d0 maybe fix boost event?? 2024-07-04 04:43:53 +01:00
a4e3598986 update voice channel join/leave logs 2024-07-04 04:38:02 +01:00
8cdc2a853b auto log names 2024-07-04 04:34:20 +01:00
f940bd526c fix channel delete logging for non text channel channels 2024-07-04 04:32:14 +01:00
490080b17a add seperate events for boosting 2024-07-04 04:30:45 +01:00
595c61e789 impl boost logging???? 2024-07-04 04:28:42 +01:00
040c644ab1 use the util for getting channels 2024-07-04 03:52:33 +01:00
fa1f18e11b don't log every channel find 2024-07-04 03:42:56 +01:00
ece36f7f27 maybe fix loading log channels 2024-07-04 03:40:12 +01:00
3b3ea2b3cc maybe fix some NPEs when calling events 2024-07-04 03:33:06 +01:00
c98d8d7e26 log correct name in user creation 2024-07-04 03:17:07 +01:00
49beb864d2 use generic embed for interaction errors 2024-07-04 03:15:53 +01:00
750b8cbfea handle errors on interactions 2024-07-04 03:07:08 +01:00
2fcc1b66c1 update original message 2024-07-04 02:58:29 +01:00
040846ef0a fix shutdown db saving (fr this time) and fixed embed color parsing 2024-07-04 02:47:36 +01:00
96486bb3a1 fix shutdown db saving 2024-07-04 02:25:26 +01:00
78daf4531b log user name not id 2024-07-04 01:58:06 +01:00
a9e4626dfd fix tmdb command errors 2024-07-04 01:47:01 +01:00
dc7e44239f fix npe and maybe fix null users???????? 2024-07-04 01:33:24 +01:00
2349f10b35 fix message and fix category name 2024-07-04 01:17:21 +01:00
bd9f4ef971 fix non null 2024-07-04 01:11:26 +01:00
6698b7c656 Merge remote-tracking branch 'origin/master' 2024-07-04 01:04:50 +01:00
0a80db8195 return a msg if it's not your cancel request 2024-07-04 01:04:38 +01:00
Lee
a3af3c3637 Merge pull request 'TMDB Support' (#6) from okNick/Bat:master into master
Reviewed-on: Fascinated/Bat#6
2024-07-03 23:58:40 +00:00
280 changed files with 9179 additions and 5609 deletions

View File

@ -16,4 +16,4 @@
# under the License. # under the License.
wrapperVersion=3.3.2 wrapperVersion=3.3.2
distributionType=only-script distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip

View File

@ -1,5 +1,5 @@
# Stage 1: Build the application # Stage 1: Build the application
FROM maven:3.9.6-eclipse-temurin-17-alpine AS builder FROM 3.9.9-eclipse-temurin-21-alpine AS builder
# Set the working directory # Set the working directory
WORKDIR /home/container WORKDIR /home/container
@ -11,7 +11,7 @@ COPY . .
RUN mvn package -q -Dmaven.test.skip -DskipTests -T2C RUN mvn package -q -Dmaven.test.skip -DskipTests -T2C
# Stage 2: Create the final lightweight image # Stage 2: Create the final lightweight image
FROM eclipse-temurin:17.0.11_9-jre-focal FROM eclipse-temurin:17.0.13_11-jre-focal
# Set the working directory # Set the working directory
WORKDIR /home/container WORKDIR /home/container

117
pom.xml
View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version> <version>3.4.1</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
@ -16,60 +16,40 @@
<description>Bat Bot for Discord</description> <description>Bat Bot for Discord</description>
<properties> <properties>
<java.version>17</java.version> <java.version>21</java.version>
</properties> </properties>
<!-- Build Config -->
<build> <build>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>
<plugins> <plugins>
<!-- Used for compiling the source code with the proper Java version --> <!-- Spring -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<!-- Enable incremental builds, this is reversed due to -->
<!-- a bug as seen in https://issues.apache.org/jira/browse/MCOMPILER-209 -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<!-- Handles shading of dependencies in the final output jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.3</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <id>build-info</id>
<goals> <goals>
<goal>shade</goal> <goal>build-info</goal>
</goals> </goals>
<configuration>
<additionalProperties>
<description>${project.description}</description>
</additionalProperties>
</configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- Specify the apps main class -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>cc.fascinated.bat.BatApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies> <dependencies>
<!-- Spring --> <!-- Spring -->
@ -88,24 +68,7 @@
<dependency> <dependency>
<groupId>io.sentry</groupId> <groupId>io.sentry</groupId>
<artifactId>sentry-spring-boot-starter-jakarta</artifactId> <artifactId>sentry-spring-boot-starter-jakarta</artifactId>
<version>7.10.0</version> <version>7.16.0</version>
</dependency>
<dependency>
<groupId>io.mongock</groupId>
<artifactId>mongock-bom</artifactId>
<version>5.2.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.mongock</groupId>
<artifactId>mongock-springboot-v3</artifactId>
<version>5.2.4</version>
</dependency>
<dependency>
<groupId>io.mongock</groupId>
<artifactId>mongodb-springdata-v4-driver</artifactId>
<version>5.2.4</version>
</dependency> </dependency>
<!-- Redis for caching --> <!-- Redis for caching -->
@ -129,52 +92,42 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.32</version> <version>1.18.34</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Dependencies -->
<dependency> <dependency>
<groupId>net.dv8tion</groupId> <groupId>io.github.freya022</groupId>
<artifactId>JDA</artifactId> <artifactId>JDA</artifactId>
<version>5.0.0-beta.24</version> <version>2ed819ad15</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.10.1</version> <version>2.11.0</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.httpcomponents.client5</groupId> <groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId> <artifactId>httpclient5</artifactId>
<version>5.3.1</version> <version>5.4.1</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.jodah</groupId> <groupId>net.jodah</groupId>
<artifactId>expiringmap</artifactId> <artifactId>expiringmap</artifactId>
<version>0.5.11</version> <version>0.5.11</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>se.michaelthelin.spotify</groupId> <groupId>org.apache.commons</groupId>
<artifactId>spotify-web-api-java</artifactId> <artifactId>commons-text</artifactId>
<version>8.4.0</version> <version>1.12.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.ben-manes.caffeine</groupId> <groupId>com.github.Steppschuh</groupId>
<artifactId>caffeine</artifactId> <artifactId>Java-Markdown-Generator</artifactId>
<version>3.1.8</version> <version>1.3.2</version>
</dependency>
<dependency>
<groupId>uk.co.conoregan</groupId>
<artifactId>themoviedbapi</artifactId>
<version>2.1.1</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,6 +1,3 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["config:recommended", ":dependencyDashboard"]
"extends": [
"local>Fascinated/renovate-config"
]
} }

View File

@ -5,13 +5,12 @@ import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.service.EventService; import cc.fascinated.bat.service.EventService;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import io.mongock.runner.springboot.EnableMongock;
import jakarta.annotation.PreDestroy;
import lombok.NonNull; import lombok.NonNull;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import java.io.File; import java.io.File;
@ -20,8 +19,7 @@ import java.nio.file.StandardCopyOption;
import java.util.Objects; import java.util.Objects;
@EnableScheduling @EnableScheduling
@SpringBootApplication(scanBasePackages = "cc.fascinated.bat") @SpringBootApplication
@EnableMongock
@Log4j2(topic = "Bat") @Log4j2(topic = "Bat")
public class BatApplication { public class BatApplication {
public static Gson GSON = new GsonBuilder().create(); public static Gson GSON = new GsonBuilder().create();
@ -39,16 +37,20 @@ public class BatApplication {
} }
log.info("Found configuration at '{}'", config.getAbsolutePath()); // Log the found config log.info("Found configuration at '{}'", config.getAbsolutePath()); // Log the found config
// Start the app // Start the application
SpringApplication.run(BatApplication.class, args); SpringApplication app = new SpringApplication(BatApplication.class);
app.setRegisterShutdownHook(false); // Disable the default shutdown hook
ConfigurableApplicationContext context = app.run(args);
// Register the shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
log.info("Shutting down...");
for (EventListener listener : EventService.LISTENERS) {
listener.onShutdown();
}
context.close();
}));
log.info("APP IS RUNNING IN %s MODE!!!!!!!!!".formatted(Config.isProduction() ? "PRODUCTION" : "DEVELOPMENT")); log.info("APP IS RUNNING IN %s MODE!!!!!!!!!".formatted(Config.isProduction() ? "PRODUCTION" : "DEVELOPMENT"));
} }
@PreDestroy
public void onShutdown() {
log.info("Shutting down...");
for (EventListener listener : EventService.LISTENERS) {
listener.onSpringShutdown();
}
}
} }

View File

@ -4,7 +4,7 @@ package cc.fascinated.bat;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
public class Consts { public class Consts {
public static final String INVITE_URL = "https://discord.com/oauth2/authorize?client_id=1254161119975833652&permissions=8&integration_type=0&scope=bot+applications.commands"; public static final String INVITE_URL = "https://dsc.gg/batbot";
public static final String SUPPORT_INVITE_URL = "https://discord.gg/invite/yjj2U3ctEG"; public static final String SUPPORT_INVITE_URL = "https://discord.gg/invite/yjj2U3ctEG";
public static final String BOT_OWNER = "474221560031608833"; public static final String BOT_OWNER = "474221560031608833";
public static final String PRIVACY_POLICY_URL = "https://git.fascinated.cc/Fascinated/Bat/raw/branch/master/privacy-policy.txt"; public static final String PRIVACY_POLICY_URL = "https://git.fascinated.cc/Fascinated/Bat/raw/branch/master/privacy-policy.txt";

View File

@ -8,7 +8,7 @@ import net.dv8tion.jda.api.entities.emoji.Emoji;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Log4j2 @Log4j2(topic = "Emojis")
public class Emojis { public class Emojis {
public static final Emoji SPOTIFY_EMOJI; public static final Emoji SPOTIFY_EMOJI;
public static final Emoji CHECK_MARK_EMOJI; public static final Emoji CHECK_MARK_EMOJI;
@ -17,29 +17,19 @@ public class Emojis {
public static final Emoji PAUSE_EMOJI; public static final Emoji PAUSE_EMOJI;
public static final Emoji PLAY_EMOJI; public static final Emoji PLAY_EMOJI;
public static final Emoji SKIP_EMOJI; public static final Emoji SKIP_EMOJI;
public static final Emoji HOME_EMOJI;
/**
* Presence Status Emojis
*/
public static final Emoji ONLINE_EMOJI;
public static final Emoji IDLE_EMOJI;
public static final Emoji DND_EMOJI;
public static final Emoji OFFLINE_EMOJI;
static { static {
log.info("Loading emojis..."); log.info("Loading emojis...");
JDA jda = DiscordService.JDA; JDA jda = DiscordService.JDA;
SPOTIFY_EMOJI = jda.getEmojiById("1256629771975266479"); SPOTIFY_EMOJI = jda.getEmojiById("1256629771975266479");
CHECK_MARK_EMOJI = jda.getEmojiById("1256633734065557676"); CHECK_MARK_EMOJI = jda.getEmojiById("1258922852669853817");
CROSS_MARK_EMOJI = jda.getEmojiById("1256634487429922897"); CROSS_MARK_EMOJI = jda.getEmojiById("1256634487429922897");
SAD_FACE_EMOJI = jda.getEmojiById("1256636078258131055"); SAD_FACE_EMOJI = jda.getEmojiById("1256636078258131055");
ONLINE_EMOJI = jda.getEmojiById("1256662465668710430");
IDLE_EMOJI = jda.getEmojiById("1256662632203685991");
DND_EMOJI = jda.getEmojiById("1256662572933845032");
OFFLINE_EMOJI = jda.getEmojiById("1256662679402053662");
PAUSE_EMOJI = Emoji.fromUnicode(""); PAUSE_EMOJI = Emoji.fromUnicode("");
PLAY_EMOJI = Emoji.fromUnicode(""); PLAY_EMOJI = Emoji.fromUnicode("");
SKIP_EMOJI = Emoji.fromUnicode(""); SKIP_EMOJI = Emoji.fromUnicode("");
HOME_EMOJI = Emoji.fromUnicode("🏠");
log.info("Loaded emojis!"); log.info("Loaded emojis!");
} }
} }

View File

@ -1,9 +1,9 @@
package cc.fascinated.bat.features.afk; package cc.fascinated.bat.afk;
import cc.fascinated.bat.command.Category; import cc.fascinated.bat.common.feature.Feature;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.common.feature.FeatureProfile;
import cc.fascinated.bat.features.afk.command.AfkCommand; import cc.fascinated.bat.afk.command.AfkCommand;
import cc.fascinated.bat.service.CommandService; import cc.fascinated.bat.service.OldCommandService;
import lombok.NonNull; import lombok.NonNull;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -13,8 +13,8 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
public class AfkFeature extends Feature { public class AfkFeature extends Feature {
public AfkFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) { public AfkFeature(@NonNull ApplicationContext context, @NonNull OldCommandService commandService) {
super("AFK", true, Category.GENERAL); super("AFK", FeatureProfile.FeatureState.DISABLED, true);
registerCommand(commandService, context.getBean(AfkCommand.class)); registerCommand(commandService, context.getBean(AfkCommand.class));
} }

View File

@ -1,9 +1,9 @@
package cc.fascinated.bat.features.afk; package cc.fascinated.bat.afk;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.features.afk.profile.AfkProfile; import cc.fascinated.bat.afk.profile.AfkProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.User;

View File

@ -1,9 +1,9 @@
package cc.fascinated.bat.features.afk; package cc.fascinated.bat.afk;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.features.afk.profile.AfkProfile; import cc.fascinated.bat.afk.profile.AfkProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@ -1,31 +1,45 @@
package cc.fascinated.bat.features.afk.command; package cc.fascinated.bat.afk.command;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.MemberUtils; import cc.fascinated.bat.common.MemberUtils;
import cc.fascinated.bat.features.afk.profile.AfkProfile; import cc.fascinated.bat.afk.profile.AfkProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "afk", description = "Sets your AFK status") @CommandInfo(name = "afk", description = "Sets your AFK status", category = Category.GENERAL)
public class AfkCommand extends BatCommand { public class AfkCommand extends BatCommand {
public AfkCommand() { public AfkCommand() {
super.addOption(OptionType.STRING, "reason", "The reason for being AFK", false); super.addOptions(new OptionData(OptionType.STRING, "reason", "The reason for being AFK", false));
} }
/**
* Fired when this command is executed.
*
* @param guild the guild the command was executed in, if any
* @param user the user who executed the command
* @param channel the channel the command was executed in
* @param member the member who executed the command, null if not a guild
* @param commandMessage
* @param arguments
* @param event the event that invoked this command
*/
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
AfkProfile profile = guild.getProfile(AfkProfile.class); AfkProfile profile = guild.getProfile(AfkProfile.class);
String reason = null; String reason = null;
OptionMapping reasonOption = event.getOption("reason"); OptionMapping reasonOption = event.getOption("reason");

View File

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.afk.profile; package cc.fascinated.bat.afk.profile;
import cc.fascinated.bat.common.Serializable; import cc.fascinated.bat.common.Serializable;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import com.google.gson.Gson; import com.google.gson.Gson;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;

View File

@ -1,9 +1,9 @@
package cc.fascinated.bat.features.autorole; package cc.fascinated.bat.autorole;
import cc.fascinated.bat.command.Category; import cc.fascinated.bat.common.feature.Feature;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.common.feature.FeatureProfile;
import cc.fascinated.bat.features.autorole.command.AutoRoleCommand; import cc.fascinated.bat.autorole.command.AutoRoleCommand;
import cc.fascinated.bat.service.CommandService; import cc.fascinated.bat.service.OldCommandService;
import lombok.NonNull; import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
@ -15,8 +15,8 @@ import org.springframework.stereotype.Component;
@Component @Component
public class AutoRoleFeature extends Feature { public class AutoRoleFeature extends Feature {
@Autowired @Autowired
public AutoRoleFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) { public AutoRoleFeature(@NonNull ApplicationContext context, @NonNull OldCommandService commandService) {
super("Auto Role",true, Category.SERVER); super("Auto Role", FeatureProfile.FeatureState.DISABLED, true);
registerCommand(commandService, context.getBean(AutoRoleCommand.class)); registerCommand(commandService, context.getBean(AutoRoleCommand.class));
} }

View File

@ -1,9 +1,9 @@
package cc.fascinated.bat.features.autorole; package cc.fascinated.bat.autorole;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; import cc.fascinated.bat.autorole.profile.AutoRoleProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.service.FeatureService; import cc.fascinated.bat.service.FeatureService;
import lombok.NonNull; import lombok.NonNull;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
@ -19,7 +19,7 @@ import java.util.List;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@Log4j2 @Log4j2(topic = "AutoRole Listener")
public class AutoRoleListener implements EventListener { public class AutoRoleListener implements EventListener {
private final FeatureService featureService; private final FeatureService featureService;

View File

@ -1,19 +1,21 @@
package cc.fascinated.bat.features.autorole.command; package cc.fascinated.bat.autorole.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.RoleUtils; import cc.fascinated.bat.common.RoleUtils;
import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; import cc.fascinated.bat.autorole.profile.AutoRoleProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,14 +24,14 @@ import org.springframework.stereotype.Component;
*/ */
@Component("autoroles:add.sub") @Component("autoroles:add.sub")
@CommandInfo(name = "add", description = "Adds a role to the auto roles list") @CommandInfo(name = "add", description = "Adds a role to the auto roles list")
public class AddSubCommand extends BatSubCommand { public class AddSubCommand extends BatCommand {
@Autowired @Autowired
public AddSubCommand() { public AddSubCommand() {
super.addOption(OptionType.ROLE, "role", "The role to add", true); super.addOptions(new OptionData(OptionType.ROLE, "role", "The role to add", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);
// Check if the guild has reached the maximum auto roles count // Check if the guild has reached the maximum auto roles count
int maxRoleSlots = AutoRoleProfile.getMaxRoleSlots(guild); int maxRoleSlots = AutoRoleProfile.getMaxRoleSlots(guild);
@ -42,12 +44,7 @@ public class AddSubCommand extends BatSubCommand {
} }
OptionMapping option = event.getOption("role"); OptionMapping option = event.getOption("role");
if (option == null) { assert option != null;
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("Please provide a role to add")
.build()).queue();
return;
}
Role role = option.getAsRole(); Role role = option.getAsRole();
// Check if the role is already in the auto roles list // Check if the role is already in the auto roles list

View File

@ -0,0 +1,31 @@
package cc.fascinated.bat.autorole.command;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import lombok.NonNull;
import net.dv8tion.jda.api.Permission;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component("autoroles.command")
@CommandInfo(
name = "autorole",
description = "Set up the automatic role system for members on join",
requiredPermissions = Permission.MANAGE_SERVER,
category = Category.SERVER
)
public class AutoRoleCommand extends BatCommand {
public AutoRoleCommand(@NonNull ApplicationContext context) {
super.addSubCommands(
context.getBean(ListSubCommand.class),
context.getBean(AddSubCommand.class),
context.getBean(RemoveSubCommand.class),
context.getBean(ClearSubCommand.class),
context.getBean(SyncSubCommand.class)
);
}
}

View File

@ -1,13 +1,14 @@
package cc.fascinated.bat.features.autorole.command; package cc.fascinated.bat.autorole.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; import cc.fascinated.bat.autorole.profile.AutoRoleProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -17,9 +18,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component("autoroles:clear.sub") @Component("autoroles:clear.sub")
@CommandInfo(name = "clear", description = "Clears all auto roles") @CommandInfo(name = "clear", description = "Clears all auto roles")
public class ClearSubCommand extends BatSubCommand { public class ClearSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);
profile.reset(); profile.reset();

View File

@ -1,14 +1,15 @@
package cc.fascinated.bat.features.autorole.command; package cc.fascinated.bat.autorole.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; import cc.fascinated.bat.autorole.profile.AutoRoleProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -18,9 +19,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component("autoroles:list.sub") @Component("autoroles:list.sub")
@CommandInfo(name = "list", description = "Lists all auto roles") @CommandInfo(name = "list", description = "Lists all auto roles")
public class ListSubCommand extends BatSubCommand { public class ListSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);
if (profile.getRoles().isEmpty()) { if (profile.getRoles().isEmpty()) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()

View File

@ -1,18 +1,20 @@
package cc.fascinated.bat.features.autorole.command; package cc.fascinated.bat.autorole.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; import cc.fascinated.bat.autorole.profile.AutoRoleProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -21,22 +23,17 @@ import org.springframework.stereotype.Component;
*/ */
@Component("autoroles:remove.sub") @Component("autoroles:remove.sub")
@CommandInfo(name = "remove", description = "Removes a role from the auto roles list") @CommandInfo(name = "remove", description = "Removes a role from the auto roles list")
public class RemoveSubCommand extends BatSubCommand { public class RemoveSubCommand extends BatCommand {
@Autowired @Autowired
public RemoveSubCommand() { public RemoveSubCommand() {
super.addOption(OptionType.ROLE, "role", "The role to remove", true); super.addOptions(new OptionData(OptionType.ROLE, "role", "The role to remove", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);
OptionMapping option = event.getOption("role"); OptionMapping option = event.getOption("role");
if (option == null) { assert option != null;
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("Please provide a role to remove")
.build()).queue();
return;
}
Role role = option.getAsRole(); Role role = option.getAsRole();
if (!profile.hasRole(role.getId())) { if (!profile.hasRole(role.getId())) {

View File

@ -0,0 +1,113 @@
package cc.fascinated.bat.autorole.command;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.DescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.autorole.profile.AutoRoleProfile;
import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull;
import lombok.extern.log4j.Log4j2;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/**
* @author Fascinated (fascinated7)
*/
@Log4j2(topic = "AutoRole Sync SubCommand")
@Component("autoroles:sync.sub")
@CommandInfo(name = "sync", description = "Gives everyone their missing auto roles")
public class SyncSubCommand extends BatCommand {
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);
if (profile.getRoles().isEmpty()) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("There are no auto roles set")
.build()).queue();
return;
}
Guild discordGuild = guild.getDiscordGuild();
event.replyEmbeds(EmbedUtils.genericEmbed()
.setDescription("Finding members that are missing auto roles...")
.build())
.queue(message -> {
log.info("Finding members that are missing auto roles in guild \"{}\"", discordGuild.getName());
List<Member> members = discordGuild.loadMembers().get();
Map<Role, Integer> rolesGiven = new HashMap<>();
// Find members that are missing the auto roles
members.removeIf(foundMember -> {
if (foundMember.getUser().isBot() || foundMember.getId().equals(discordGuild.getSelfMember().getId())) {
return true;
}
return new HashSet<>(foundMember.getRoles()).containsAll(profile.getRoles());
});
log.info("Found {} members that are missing auto roles in guild \"{}\"", members.size(), discordGuild.getName());
// No members were missing roles
if (members.isEmpty()) {
message.editOriginalEmbeds(EmbedUtils.successEmbed()
.setDescription("There are no members missing auto roles")
.build()).queue();
return;
}
int finished = 0;
for (Member foundMember : members) {
// Check if the user doesn't have the role, so we can
// show the incremented count when we're done
for (Role role : profile.getRoles()) {
if (foundMember.getRoles().contains(role)) {
continue;
}
rolesGiven.put(role, rolesGiven.getOrDefault(role, 0) + 1);
}
// Give the user the roles
discordGuild.modifyMemberRoles(foundMember, profile.getRoles(), null).queue();
finished++;
// Update the message every 10 members
if (finished % 10 == 0 || finished == 1) {
message.editOriginalEmbeds(EmbedUtils.genericEmbed()
.setDescription("""
Giving auto roles...
Completed: `%s`/`%s`
""".formatted(finished, members.size()))
.build()).queue();
}
// We're finished giving all the roles
if (finished == members.size()) {
DescriptionBuilder description = new DescriptionBuilder(
"Successfully gave auto roles to `%s` member%s".formatted(
members.size(),
members.size() == 1 ? "" : "s"
));
description.emptyLine();
description.appendLine("**Auto Roles Given:**", false);
for (Map.Entry<Role, Integer> entry : rolesGiven.entrySet()) {
description.appendLine("%s: %s member%s".formatted(
entry.getKey().getAsMention(),
entry.getValue(),
entry.getValue() == 1 ? "" : "s"
), true);
}
message.editOriginalEmbeds(EmbedUtils.successEmbed().setDescription(description.build()).build()).queue();
}
}
});
}
}

View File

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.autorole.profile; package cc.fascinated.bat.autorole.profile;
import cc.fascinated.bat.common.Serializable; import cc.fascinated.bat.common.Serializable;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.service.DiscordService; import cc.fascinated.bat.service.DiscordService;
import com.google.gson.Gson; import com.google.gson.Gson;
import lombok.Getter; import lombok.Getter;

View File

@ -0,0 +1,52 @@
package cc.fascinated.bat.base;
import cc.fascinated.bat.common.feature.Feature;
import cc.fascinated.bat.common.feature.FeatureProfile;
import cc.fascinated.bat.base.commands.botadmin.BotAdminCommand;
import cc.fascinated.bat.base.commands.fun.CoinFlipCommand;
import cc.fascinated.bat.base.commands.fun.EightBallCommand;
import cc.fascinated.bat.base.commands.fun.PPSizeCommand;
import cc.fascinated.bat.base.commands.fun.image.ImageCommand;
import cc.fascinated.bat.base.commands.general.*;
import cc.fascinated.bat.base.commands.general.avatar.AvatarCommand;
import cc.fascinated.bat.base.commands.general.banner.BannerCommand;
import cc.fascinated.bat.base.commands.server.MemberCountCommand;
import cc.fascinated.bat.base.commands.server.PremiumCommand;
import cc.fascinated.bat.base.commands.server.channel.ChannelCommand;
import cc.fascinated.bat.base.commands.server.feature.FeatureCommand;
import cc.fascinated.bat.base.commands.utility.PastebinCommand;
import cc.fascinated.bat.base.commands.utility.lookup.LookupCommand;
import cc.fascinated.bat.service.OldCommandService;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component
public class BaseFeature extends Feature {
@Autowired
public BaseFeature(@NonNull ApplicationContext context, @NonNull OldCommandService commandService) {
super("Base", FeatureProfile.FeatureState.ENABLED, false);
super.registerCommand(commandService, context.getBean(PremiumCommand.class));
super.registerCommand(commandService, context.getBean(BotAdminCommand.class));
super.registerCommand(commandService, context.getBean(MemberCountCommand.class));
super.registerCommand(commandService, context.getBean(ChannelCommand.class));
super.registerCommand(commandService, context.getBean(VoteCommand.class));
super.registerCommand(commandService, context.getBean(PingCommand.class));
super.registerCommand(commandService, context.getBean(InviteCommand.class));
super.registerCommand(commandService, context.getBean(BotStatsCommand.class));
super.registerCommand(commandService, context.getBean(BannerCommand.class));
super.registerCommand(commandService, context.getBean(AvatarCommand.class));
super.registerCommand(commandService, context.getBean(ImageCommand.class));
super.registerCommand(commandService, context.getBean(FeatureCommand.class));
super.registerCommand(commandService, context.getBean(EightBallCommand.class));
super.registerCommand(commandService, context.getBean(LookupCommand.class));
super.registerCommand(commandService, context.getBean(PPSizeCommand.class));
super.registerCommand(commandService, context.getBean(PastebinCommand.class));
super.registerCommand(commandService, context.getBean(CoinFlipCommand.class));
}
}

View File

@ -0,0 +1,25 @@
package cc.fascinated.bat.base.commands.botadmin;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.base.commands.botadmin.premium.PremiumRemoveSubCommand;
import cc.fascinated.bat.base.commands.botadmin.premium.PremiumSetSubCommand;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component
@CommandInfo(name = "bot-admin", description = "Bot admin commands", botOwnerOnly = true)
public class BotAdminCommand extends BatCommand {
@Autowired
public BotAdminCommand(@NonNull ApplicationContext context) {
super.addSubCommands(
context.getBean(PremiumSetSubCommand.class),
context.getBean(PremiumRemoveSubCommand.class)
);
}
}

View File

@ -1,17 +1,19 @@
package cc.fascinated.bat.features.base.commands.botadmin.premium; package cc.fascinated.bat.base.commands.botadmin.premium;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.premium.PremiumProfile; import cc.fascinated.bat.premium.PremiumProfile;
import cc.fascinated.bat.service.GuildService; import cc.fascinated.bat.service.GuildService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -19,18 +21,18 @@ import org.springframework.stereotype.Component;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "remove", description = "Remove premium from a guild") @CommandInfo(name = "premium-remove", description = "Remove premium from a guild")
public class RemoveSubCommand extends BatSubCommand { public class PremiumRemoveSubCommand extends BatCommand {
private final GuildService guildService; private final GuildService guildService;
@Autowired @Autowired
public RemoveSubCommand(GuildService guildService) { public PremiumRemoveSubCommand(GuildService guildService) {
this.guildService = guildService; this.guildService = guildService;
super.addOption(OptionType.STRING, "guild", "The guild id to set as premium", true); super.addOptions(new OptionData(OptionType.STRING, "guild", "The guild id to set as premium", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
OptionMapping guildOption = event.getOption("guild"); OptionMapping guildOption = event.getOption("guild");
if (guildOption == null) { if (guildOption == null) {
event.reply("Please provide a guild id").queue(); event.reply("Please provide a guild id").queue();

View File

@ -1,17 +1,19 @@
package cc.fascinated.bat.features.base.commands.botadmin.premium; package cc.fascinated.bat.base.commands.botadmin.premium;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.premium.PremiumProfile; import cc.fascinated.bat.premium.PremiumProfile;
import cc.fascinated.bat.service.GuildService; import cc.fascinated.bat.service.GuildService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -19,19 +21,21 @@ import org.springframework.stereotype.Component;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "set", description = "Adds premium to a guild") @CommandInfo(name = "premium-set", description = "Adds premium to a guild")
public class SetSubCommand extends BatSubCommand { public class PremiumSetSubCommand extends BatCommand {
private final GuildService guildService; private final GuildService guildService;
@Autowired @Autowired
public SetSubCommand(@NonNull GuildService guildService) { public PremiumSetSubCommand(@NonNull GuildService guildService) {
this.guildService = guildService; this.guildService = guildService;
super.addOption(OptionType.STRING, "guild", "The guild id to set as premium", true); super.addOptions(
super.addOption(OptionType.BOOLEAN, "infinite", "Whether the premium length should be infinite", true); new OptionData(OptionType.STRING, "guild", "The guild id to set as premium", true),
new OptionData(OptionType.BOOLEAN, "infinite", "Whether the premium length should be infinite", true)
);
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
OptionMapping guildOption = event.getOption("guild"); OptionMapping guildOption = event.getOption("guild");
if (guildOption == null) { if (guildOption == null) {
event.reply("Please provide a guild id").queue(); event.reply("Please provide a guild id").queue();

View File

@ -0,0 +1,40 @@
package cc.fascinated.bat.base.commands.fun;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component;
import java.util.Random;
/**
* @author Fascinated (fascinated7)
*/
@CommandInfo(
name = "coinflip",
description = "Flips a coin",
userInstall = true
)
@Component
public class CoinFlipCommand extends BatCommand {
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member,
Message commandMessage, String[] arguments, SlashCommandInteraction event) {
event.reply("%s, you flipped a coin and got **%s**!".formatted(user.getDiscordUser().getAsMention(), flip())).queue();
}
/**
* Flips a coin
*
* @return The result of the coin flip
*/
public String flip() {
return new Random().nextBoolean() ? "heads" : "tails";
}
}

View File

@ -1,23 +1,31 @@
package cc.fascinated.bat.features.base.commands.fun; package cc.fascinated.bat.base.commands.fun;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "8ball", description = "Ask the magic 8ball a question") @CommandInfo(
name = "8ball", description = "Ask the magic 8ball a question",
guildOnly = false,
userInstall = true,
prefixAllowed = true,
category = Category.FUN
)
public class EightBallCommand extends BatCommand { public class EightBallCommand extends BatCommand {
private final String[] responses = new String[]{ private final String[] responses = new String[]{
"It is certain", "It is certain",
@ -43,20 +51,22 @@ public class EightBallCommand extends BatCommand {
}; };
public EightBallCommand() { public EightBallCommand() {
super.addOption(OptionType.STRING, "question", "The question you want to ask the 8ball", true); super.addOptions(new OptionData(OptionType.STRING, "question", "The question you want to ask the 8ball", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
OptionMapping questionOption = event.getOption("question"); String question = super.getArgument("question", arguments, 0, true, event).getAsString();
if (questionOption == null) { if (question == null) {
super.replyEmbed(commandMessage, event, EmbedUtils.errorEmbed()
.setDescription("You need to provide a question to ask the 8ball")
);
return; return;
} }
String question = questionOption.getAsString();
String response = responses[(int) (Math.random() * responses.length)]; String response = responses[(int) (Math.random() * responses.length)];
event.replyEmbeds(EmbedUtils.successEmbed() super.replyEmbed(commandMessage, event, EmbedUtils.successEmbed()
.setDescription("You asked: `%s`\n\n:8ball: The magic 8ball says: `%s`".formatted(question, response)) .setDescription("You asked: `%s`\n\n:8ball: The magic 8ball says: `%s`".formatted(question, response))
.build()) );
.queue();
} }
} }

View File

@ -0,0 +1,57 @@
package cc.fascinated.bat.base.commands.fun;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.DescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.MathUtils;
import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component
@CommandInfo(
name = "ppsize",
description = "Get the size of someone's pp",
userInstall = true,
category = Category.FUN
)
public class PPSizeCommand extends BatCommand {
public PPSizeCommand() {
super.addOptions(new OptionData(OptionType.USER, "user", "The user you want to get the pp size of", true));
}
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
OptionMapping userOption = event.getOption("user");
assert userOption != null; // This should never be null
User target = userOption.getAsUser();
int size = (int) MathUtils.random(1, 12);
event.replyEmbeds(EmbedUtils.genericEmbed()
.setDescription(new DescriptionBuilder("PP Size")
.appendLine("""
The size of %s's pp is %s inches
**8%sD**
""".formatted(
target.getAsMention(),
size,
"=".repeat(size)
), false)
.build())
.build()).queue();
}
}

View File

@ -1,14 +1,15 @@
package cc.fascinated.bat.features.base.commands.fun.image; package cc.fascinated.bat.base.commands.fun.image;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest; import cc.fascinated.bat.common.WebRequest;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.model.token.thecatapi.CatImageToken; import cc.fascinated.bat.common.model.token.thecatapi.CatImageToken;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -18,9 +19,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "cat", description = "Get a random cat image") @CommandInfo(name = "cat", description = "Get a random cat image")
public class CatSubCommand extends BatSubCommand { public class CatSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
CatImageToken[] responseEntity = WebRequest.getAsEntity("https://api.thecatapi.com/v1/images/search", CatImageToken[].class); CatImageToken[] responseEntity = WebRequest.getAsEntity("https://api.thecatapi.com/v1/images/search", CatImageToken[].class);
if (responseEntity == null || responseEntity.length == 0) { if (responseEntity == null || responseEntity.length == 0) {
event.reply("Failed to get a cat image!").queue(); event.reply("Failed to get a cat image!").queue();

View File

@ -1,14 +1,15 @@
package cc.fascinated.bat.features.base.commands.fun.image; package cc.fascinated.bat.base.commands.fun.image;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest; import cc.fascinated.bat.common.WebRequest;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.model.token.dogceo.RandomImage; import cc.fascinated.bat.common.model.token.dogceo.RandomImage;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -18,9 +19,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "dog", description = "Get a random dog image") @CommandInfo(name = "dog", description = "Get a random dog image")
public class DogSubCommand extends BatSubCommand { public class DogSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
RandomImage responseEntity = WebRequest.getAsEntity("https://dog.ceo/api/breeds/image/random", RandomImage.class); RandomImage responseEntity = WebRequest.getAsEntity("https://dog.ceo/api/breeds/image/random", RandomImage.class);
if (responseEntity == null) { if (responseEntity == null) {
event.reply("Failed to get a dog image!").queue(); event.reply("Failed to get a dog image!").queue();

View File

@ -1,14 +1,15 @@
package cc.fascinated.bat.features.base.commands.fun.image; package cc.fascinated.bat.base.commands.fun.image;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest; import cc.fascinated.bat.common.WebRequest;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.model.token.randomd.RandomDuck; import cc.fascinated.bat.common.model.token.randomd.RandomDuck;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -18,9 +19,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "duck", description = "Get a random duck image") @CommandInfo(name = "duck", description = "Get a random duck image")
public class DuckSubCommand extends BatSubCommand { public class DuckSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
RandomDuck responseEntity = WebRequest.getAsEntity("https://random-d.uk/api/v2/random", RandomDuck.class); RandomDuck responseEntity = WebRequest.getAsEntity("https://random-d.uk/api/v2/random", RandomDuck.class);
if (responseEntity == null) { if (responseEntity == null) {
event.reply("Failed to get a duck image!").queue(); event.reply("Failed to get a duck image!").queue();

View File

@ -1,14 +1,15 @@
package cc.fascinated.bat.features.base.commands.fun.image; package cc.fascinated.bat.base.commands.fun.image;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest; import cc.fascinated.bat.common.WebRequest;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.model.token.randomfox.RandomFoxToken; import cc.fascinated.bat.common.model.token.randomfox.RandomFoxToken;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -18,9 +19,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "fox", description = "Get a random fox image") @CommandInfo(name = "fox", description = "Get a random fox image")
public class FoxSubCommand extends BatSubCommand { public class FoxSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
RandomFoxToken responseEntity = WebRequest.getAsEntity("https://randomfox.ca/floof/", RandomFoxToken.class); RandomFoxToken responseEntity = WebRequest.getAsEntity("https://randomfox.ca/floof/", RandomFoxToken.class);
if (responseEntity == null) { if (responseEntity == null) {
event.reply("Failed to get a fox image!").queue(); event.reply("Failed to get a fox image!").queue();

View File

@ -0,0 +1,26 @@
package cc.fascinated.bat.base.commands.fun.image;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component
@CommandInfo(name = "image", description = "View a random image", guildOnly = false, userInstall = true, category = Category.FUN)
public class ImageCommand extends BatCommand {
@Autowired
public ImageCommand(@NonNull ApplicationContext context) {
super.addSubCommands(
context.getBean(CatSubCommand.class),
context.getBean(DogSubCommand.class),
context.getBean(FoxSubCommand.class),
context.getBean(DuckSubCommand.class)
);
}
}

View File

@ -1,19 +1,18 @@
package cc.fascinated.bat.features.base.commands.general; package cc.fascinated.bat.base.commands.general;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.EmbedDescriptionBuilder; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.*;
import cc.fascinated.bat.common.NumberFormatter; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.common.TimeUtils; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.service.DiscordService; import cc.fascinated.bat.service.DiscordService;
import cc.fascinated.bat.service.GuildService; import cc.fascinated.bat.service.GuildService;
import cc.fascinated.bat.service.UserService; import cc.fascinated.bat.service.UserService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -26,11 +25,12 @@ import java.lang.management.RuntimeMXBean;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "botstats", description = "Shows the bot statistics", guildOnly = false) @CommandInfo(name = "botstats", description = "Shows the bot statistics", guildOnly = false, userInstall = true, category = Category.GENERAL)
public class BotStatsCommand extends BatCommand { public class BotStatsCommand extends BatCommand {
private final GuildService guildService; private final GuildService guildService;
private final UserService userService; private final UserService userService;
private final RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean(); private final RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
private final Runtime runtime = Runtime.getRuntime();
@Autowired @Autowired
public BotStatsCommand(@NonNull GuildService guildService, @NonNull UserService userService) { public BotStatsCommand(@NonNull GuildService guildService, @NonNull UserService userService) {
@ -39,17 +39,19 @@ public class BotStatsCommand extends BatCommand {
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
JDA jda = DiscordService.JDA; JDA jda = DiscordService.JDA;
long memoryUsed = (runtime.totalMemory() - runtime.freeMemory());
event.replyEmbeds(EmbedUtils.genericEmbed().setDescription( event.replyEmbeds(EmbedUtils.genericEmbed().setDescription(
new EmbedDescriptionBuilder("Bat Statistics") new DescriptionBuilder("Bat Statistics")
.appendLine("Guilds: **%s**".formatted(NumberFormatter.format(jda.getGuilds().size())), true) .appendLine("Guilds: **%s**".formatted(NumberFormatter.format(jda.getGuilds().size())), true)
.appendLine("Users: **%s**".formatted(NumberFormatter.format(jda.getUsers().size())), true) .appendLine("Users: **%s**".formatted(NumberFormatter.format(jda.getUsers().size())), true)
.appendLine("Gateway Ping: **%sms**".formatted(jda.getGatewayPing()), true) .appendLine("Gateway Ping: **%sms**".formatted(jda.getGatewayPing()), true)
.emptyLine() .emptyLine()
.appendSubtitle("Bot Statistics") .appendSubtitle("Bot Statistics")
.appendLine("Uptime: **%s**".formatted(TimeUtils.format(bean.getUptime())), true) .appendLine("Uptime: **%s**".formatted(TimeUtils.format(bean.getUptime())), true)
.appendLine("Memory Usage: **%s**".formatted(StringUtils.formatBytes(memoryUsed)), true)
.appendLine("Cached Guilds: **%s**".formatted(NumberFormatter.format(guildService.getGuilds().size())), true) .appendLine("Cached Guilds: **%s**".formatted(NumberFormatter.format(guildService.getGuilds().size())), true)
.appendLine("Cached Users: **%s**".formatted(NumberFormatter.format(userService.getUsers().size())), true) .appendLine("Cached Users: **%s**".formatted(NumberFormatter.format(userService.getUsers().size())), true)
.build() .build()

View File

@ -1,13 +1,15 @@
package cc.fascinated.bat.features.base.commands.general; package cc.fascinated.bat.base.commands.general;
import cc.fascinated.bat.Consts; import cc.fascinated.bat.Consts;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -16,10 +18,10 @@ import org.springframework.stereotype.Component;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "invite", description = "Invite the bot to your server!", guildOnly = false) @CommandInfo(name = "invite", description = "Invite the bot to your server!", guildOnly = false, category = Category.GENERAL)
public class InviteCommand extends BatCommand { public class InviteCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
event.replyEmbeds(EmbedUtils.genericEmbed() event.replyEmbeds(EmbedUtils.genericEmbed()
.setDescription("You can invite the bot to your server by clicking [here](%s)".formatted(Consts.INVITE_URL)) .setDescription("You can invite the bot to your server by clicking [here](%s)".formatted(Consts.INVITE_URL))
.build()) .build())

View File

@ -1,12 +1,14 @@
package cc.fascinated.bat.features.base.commands.general; package cc.fascinated.bat.base.commands.general;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.service.DiscordService; import cc.fascinated.bat.service.DiscordService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -15,10 +17,16 @@ import org.springframework.stereotype.Component;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "ping", description = "Gets the ping of the bot", guildOnly = false) @CommandInfo(
name = "ping",
description = "Gets the ping of the bot",
guildOnly = false,
userInstall = true,
category = Category.GENERAL
)
public class PingCommand extends BatCommand { public class PingCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
event.reply("Pinging...").queue(response -> { event.reply("Pinging...").queue(response -> {
response.editOriginal("Gateway response time: `%sms`\nAPI response time `%sms`".formatted( response.editOriginal("Gateway response time: `%sms`\nAPI response time `%sms`".formatted(

View File

@ -1,13 +1,15 @@
package cc.fascinated.bat.features.base.commands.general; package cc.fascinated.bat.base.commands.general;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.EmbedDescriptionBuilder; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.DescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -16,7 +18,7 @@ import org.springframework.stereotype.Component;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "vote", description = "Vote for the bot", guildOnly = false) @CommandInfo(name = "vote", description = "Vote for the bot", guildOnly = false, userInstall = true, category = Category.GENERAL)
public class VoteCommand extends BatCommand { public class VoteCommand extends BatCommand {
private static final String[] VOTE_LINKS = new String[]{ private static final String[] VOTE_LINKS = new String[]{
"https://top.gg/bot/1254161119975833652/vote", "https://top.gg/bot/1254161119975833652/vote",
@ -24,8 +26,8 @@ public class VoteCommand extends BatCommand {
}; };
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
EmbedDescriptionBuilder description = new EmbedDescriptionBuilder("Vote Links"); DescriptionBuilder description = new DescriptionBuilder("Vote Links");
description.appendLine("Vote for the bot on the following websites to support us!", false); description.appendLine("Vote for the bot on the following websites to support us!", false);
for (String link : VOTE_LINKS) { for (String link : VOTE_LINKS) {
description.appendLine(link, true); description.appendLine(link, true);

View File

@ -0,0 +1,24 @@
package cc.fascinated.bat.base.commands.general.avatar;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Nick (okNick)
*/
@Component
@CommandInfo(name = "avatar", description = "View the avatar of the guild or a user", guildOnly = false, category = Category.GENERAL)
public class AvatarCommand extends BatCommand {
@Autowired
public AvatarCommand(@NonNull ApplicationContext context) {
super.addSubCommands(
context.getBean(GuildSubCommand.class),
context.getBean(UserSubCommand.class)
);
}
}

View File

@ -1,12 +1,14 @@
package cc.fascinated.bat.features.base.commands.general.avatar; package cc.fascinated.bat.base.commands.general.avatar;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.utils.ImageProxy; import net.dv8tion.jda.api.utils.ImageProxy;
@ -16,12 +18,11 @@ import org.springframework.stereotype.Component;
* @author Nick (okNick) * @author Nick (okNick)
*/ */
@Component("avatar:guild.sub") @Component("avatar:guild.sub")
@CommandInfo(name = "guild", description = "View the avatar of the guild") @CommandInfo(name = "guild", description = "View the avatar of the guild", category = Category.GENERAL)
public class GuildSubCommand extends BatSubCommand { public class GuildSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
ImageProxy icon = guild.getDiscordGuild().getIcon(); ImageProxy icon = guild.getDiscordGuild().getIcon();
if (icon == null) { if (icon == null) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("**%s** does not have an avatar!".formatted(guild.getName())) .setDescription("**%s** does not have an avatar!".formatted(guild.getName()))

View File

@ -1,41 +1,38 @@
package cc.fascinated.bat.features.base.commands.general.avatar; package cc.fascinated.bat.base.commands.general.avatar;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* @author Nick (okNick) * @author Nick (okNick)
*/ */
@Component("avatar:user.sub") @Component("avatar:user.sub")
@CommandInfo(name = "user", description = "View the avatar of a user", guildOnly = false) @CommandInfo(name = "user", description = "View the avatar of a user", guildOnly = false, category = Category.GENERAL)
public class UserSubCommand extends BatSubCommand { public class UserSubCommand extends BatCommand {
public UserSubCommand() { public UserSubCommand() {
super.addOption(OptionType.USER, "user", "The user to view the avatar of", true); super.addOptions(new OptionData(OptionType.USER, "user", "The user to view the avatar of", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
OptionMapping userOption = event.getOption("user"); OptionMapping userOption = event.getOption("user");
if (userOption == null) { assert userOption != null;
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You must provide a user to view the avatar of!")
.build())
.queue();
return;
}
User target = userOption.getAsUser(); User target = userOption.getAsUser();
event.replyEmbeds(EmbedUtils.genericEmbed() event.replyEmbeds(EmbedUtils.genericEmbed()
.setAuthor("%s's Avatar".formatted(target.getName()), null, target.getEffectiveAvatarUrl()) .setAuthor("%s's Avatar".formatted(target.getName()), null, target.getEffectiveAvatarUrl())
.setImage(target.getEffectiveAvatarUrl()) .setImage(target.getEffectiveAvatarUrl())

View File

@ -0,0 +1,24 @@
package cc.fascinated.bat.base.commands.general.banner;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Nick (okNick)
*/
@Component
@CommandInfo(name = "banner", description = "View the banner of the guild or a user", guildOnly = false, category = Category.GENERAL)
public class BannerCommand extends BatCommand {
@Autowired
public BannerCommand(@NonNull ApplicationContext context) {
super.addSubCommands(
context.getBean(GuildSubCommand.class),
context.getBean(UserSubCommand.class)
);
}
}

View File

@ -1,12 +1,14 @@
package cc.fascinated.bat.features.base.commands.general.banner; package cc.fascinated.bat.base.commands.general.banner;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.utils.ImageProxy; import net.dv8tion.jda.api.utils.ImageProxy;
@ -16,10 +18,10 @@ import org.springframework.stereotype.Component;
* @author Nick (okNick) * @author Nick (okNick)
*/ */
@Component("banner:guild.sub") @Component("banner:guild.sub")
@CommandInfo(name = "guild", description = "View the banner of the guild") @CommandInfo(name = "guild", description = "View the banner of the guild", category = Category.GENERAL)
public class GuildSubCommand extends BatSubCommand { public class GuildSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
ImageProxy banner = guild.getDiscordGuild().getBanner(); ImageProxy banner = guild.getDiscordGuild().getBanner();
if (banner == null) { if (banner == null) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()

View File

@ -1,17 +1,20 @@
package cc.fascinated.bat.features.base.commands.general.banner; package cc.fascinated.bat.base.commands.general.banner;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.utils.ImageProxy; import net.dv8tion.jda.api.utils.ImageProxy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -19,23 +22,16 @@ import org.springframework.stereotype.Component;
* @author Nick (okNick) * @author Nick (okNick)
*/ */
@Component("banner:user.sub") @Component("banner:user.sub")
@CommandInfo(name = "user", description = "View the banner of a user", guildOnly = false) @CommandInfo(name = "user", description = "View the banner of a user", guildOnly = false, category = Category.GENERAL)
public class UserSubCommand extends BatSubCommand { public class UserSubCommand extends BatCommand {
public UserSubCommand() { public UserSubCommand() {
super.addOption(OptionType.USER, "user", "The user to view the banner of", true); super.addOptions(new OptionData(OptionType.USER, "user", "The user to view the banner of", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
OptionMapping userOption = event.getOption("user"); OptionMapping userOption = event.getOption("user");
if (userOption == null) { assert userOption != null;
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You must provide a user to view the banner of!")
.build())
.queue();
return;
}
User target = userOption.getAsUser(); User target = userOption.getAsUser();
ImageProxy banner = target.retrieveProfile().complete().getBanner(); ImageProxy banner = target.retrieveProfile().complete().getBanner();
if (banner == null) { if (banner == null) {

View File

@ -0,0 +1,47 @@
package cc.fascinated.bat.base.commands.server;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component;
/**
* @author Nick (okNick)
*/
@Component
@CommandInfo(name = "membercount", description = "View the member count of the server!")
public class MemberCountCommand extends BatCommand {
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
Guild discordGuild = guild.getDiscordGuild();
int totalMembers = 0, totalUsers = 0, totalBots = 0;
for (Member guildMember : discordGuild.getMembers()) {
if (guildMember.getUser().isBot()) {
totalBots++;
} else {
totalUsers++;
}
totalMembers++;
}
event.replyEmbeds(EmbedUtils.genericEmbed()
.setDescription("""
**Member Count**
Total Members: `%s`
Total Users: `%s`
Total Bots: `%s`
""".formatted(
NumberFormatter.format(totalMembers),
NumberFormatter.format(totalUsers),
NumberFormatter.format(totalBots)
)).build()).queue();
}
}

View File

@ -1,15 +1,16 @@
package cc.fascinated.bat.features.base.commands.server; package cc.fascinated.bat.base.commands.server;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.premium.PremiumProfile; import cc.fascinated.bat.premium.PremiumProfile;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -21,7 +22,7 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "premium", description = "View the premium information for the guild", requiredPermissions = Permission.ADMINISTRATOR) @CommandInfo(name = "premium", description = "View the premium information for the guild", requiredPermissions = Permission.ADMINISTRATOR)
public class PremiumCommand extends BatCommand { public class PremiumCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
PremiumProfile premium = guild.getPremiumProfile(); PremiumProfile premium = guild.getPremiumProfile();
EmbedBuilder embed = EmbedUtils.genericEmbed().setAuthor("Premium Information"); EmbedBuilder embed = EmbedUtils.genericEmbed().setAuthor("Premium Information");
if (premium.hasPremium()) { if (premium.hasPremium()) {

View File

@ -1,8 +1,8 @@
package cc.fascinated.bat.features.base.commands.server.channel; package cc.fascinated.bat.base.commands.server.channel;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.Category; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import lombok.NonNull; import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
@ -16,8 +16,10 @@ import org.springframework.stereotype.Component;
public class ChannelCommand extends BatCommand { public class ChannelCommand extends BatCommand {
@Autowired @Autowired
public ChannelCommand(@NonNull ApplicationContext context) { public ChannelCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(ViewTopicSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(SetTopicSubCommand.class)); context.getBean(ViewTopicSubCommand.class),
super.addSubCommand(context.getBean(RemoveTopicSubCommand.class)); context.getBean(SetTopicSubCommand.class),
context.getBean(RemoveTopicSubCommand.class)
);
} }
} }

View File

@ -1,18 +1,20 @@
package cc.fascinated.bat.features.base.commands.server.channel; package cc.fascinated.bat.base.commands.server.channel;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.Channel; import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -20,13 +22,13 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "removetopic", description = "Remove the topic of a channel", requiredPermissions = Permission.MANAGE_CHANNEL) @CommandInfo(name = "removetopic", description = "Remove the topic of a channel", requiredPermissions = Permission.MANAGE_CHANNEL)
public class RemoveTopicSubCommand extends BatSubCommand { public class RemoveTopicSubCommand extends BatCommand {
public RemoveTopicSubCommand() { public RemoveTopicSubCommand() {
super.addOption(OptionType.CHANNEL, "channel", "The channel to remove the topic of", false); super.addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel to remove the topic of", false));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
Channel target = event.getOption("channel") == null ? channel : event.getOption("channel").getAsChannel(); Channel target = event.getOption("channel") == null ? channel : event.getOption("channel").getAsChannel();
if (!(target instanceof TextChannel textChannel)) { if (!(target instanceof TextChannel textChannel)) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()

View File

@ -1,34 +1,40 @@
package cc.fascinated.bat.features.base.commands.server.channel; package cc.fascinated.bat.base.commands.server.channel;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.Channel; import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Objects;
/** /**
* @author Nick (okNick) * @author Nick (okNick)
*/ */
@Component @Component
@CommandInfo(name = "settopic", description = "Set the topic of a channel", requiredPermissions = Permission.MANAGE_CHANNEL) @CommandInfo(name = "settopic", description = "Set the topic of a channel", requiredPermissions = Permission.MANAGE_CHANNEL)
public class SetTopicSubCommand extends BatSubCommand { public class SetTopicSubCommand extends BatCommand {
public SetTopicSubCommand() { public SetTopicSubCommand() {
super.addOption(OptionType.STRING, "topic", "The topic to set", true); super.addOptions(
super.addOption(OptionType.CHANNEL, "channel", "The channel to set the topic of", false); new OptionData(OptionType.STRING, "topic", "The topic to set", true),
new OptionData(OptionType.CHANNEL, "channel", "The channel to set the topic of", false)
);
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
Channel target = event.getOption("channel") == null ? channel : event.getOption("channel").getAsChannel(); Channel target = event.getOption("channel") == null ? channel : Objects.requireNonNull(event.getOption("channel")).getAsChannel();
if (!(target instanceof TextChannel textChannel)) { if (!(target instanceof TextChannel textChannel)) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("<#%s> is not a text channel!".formatted(target.getId())) .setDescription("<#%s> is not a text channel!".formatted(target.getId()))
@ -37,7 +43,7 @@ public class SetTopicSubCommand extends BatSubCommand {
return; return;
} }
String topic = event.getOption("topic").getAsString(); String topic = Objects.requireNonNull(event.getOption("topic")).getAsString();
if (topic.length() > 1024) { if (topic.length() > 1024) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("The topic must be 1024 characters or less!") .setDescription("The topic must be 1024 characters or less!")
@ -45,11 +51,8 @@ public class SetTopicSubCommand extends BatSubCommand {
.queue(); .queue();
return; return;
} }
event.deferReply().queue(hook -> textChannel.getManager().setTopic(topic).queue((voidd) -> hook.editOriginalEmbeds(EmbedUtils.successEmbed()
textChannel.getManager().setTopic(topic).queue();
event.replyEmbeds(EmbedUtils.successEmbed()
.setDescription("Successfully set the topic of <#%s> to: \"%s\"".formatted(textChannel.getId(), topic)) .setDescription("Successfully set the topic of <#%s> to: \"%s\"".formatted(textChannel.getId(), topic))
.build() .build()).queue()));
).queue();
} }
} }

View File

@ -1,17 +1,19 @@
package cc.fascinated.bat.features.base.commands.server.channel; package cc.fascinated.bat.base.commands.server.channel;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.Channel; import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -19,13 +21,13 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "viewtopic", description = "View the topic of a channel") @CommandInfo(name = "viewtopic", description = "View the topic of a channel")
public class ViewTopicSubCommand extends BatSubCommand { public class ViewTopicSubCommand extends BatCommand {
public ViewTopicSubCommand() { public ViewTopicSubCommand() {
super.addOption(OptionType.CHANNEL, "channel", "The channel to view the topic of", false); super.addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel to view the topic of", false));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
Channel target = event.getOption("channel") == null ? channel : event.getOption("channel").getAsChannel(); Channel target = event.getOption("channel") == null ? channel : event.getOption("channel").getAsChannel();
if (!(target instanceof TextChannel textChannel)) { if (!(target instanceof TextChannel textChannel)) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()

View File

@ -1,19 +1,21 @@
package cc.fascinated.bat.features.base.commands.server.feature; package cc.fascinated.bat.base.commands.server.feature;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.common.feature.Feature;
import cc.fascinated.bat.features.base.profile.FeatureProfile; import cc.fascinated.bat.common.feature.FeatureProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.service.FeatureService; import cc.fascinated.bat.service.FeatureService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,14 +24,14 @@ import org.springframework.stereotype.Component;
*/ */
@Component("feature:disable.sub") @Component("feature:disable.sub")
@CommandInfo(name = "disable", description = "Disables a feature") @CommandInfo(name = "disable", description = "Disables a feature")
public class DisableSubCommand extends BatSubCommand { public class DisableSubCommand extends BatCommand {
@Autowired @Autowired
public DisableSubCommand() { public DisableSubCommand() {
super.addOption(OptionType.STRING, "feature", "The feature to disable", true); super.addOptions(new OptionData(OptionType.STRING, "feature", "The feature to disable", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
FeatureProfile featureProfile = guild.getFeatureProfile(); FeatureProfile featureProfile = guild.getFeatureProfile();
OptionMapping featureOption = event.getOption("feature"); OptionMapping featureOption = event.getOption("feature");
if (featureOption == null) { if (featureOption == null) {

View File

@ -1,19 +1,21 @@
package cc.fascinated.bat.features.base.commands.server.feature; package cc.fascinated.bat.base.commands.server.feature;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.common.feature.Feature;
import cc.fascinated.bat.features.base.profile.FeatureProfile; import cc.fascinated.bat.common.feature.FeatureProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.service.FeatureService; import cc.fascinated.bat.service.FeatureService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,14 +24,14 @@ import org.springframework.stereotype.Component;
*/ */
@Component("feature:enable.sub") @Component("feature:enable.sub")
@CommandInfo(name = "enable", description = "Enables a feature") @CommandInfo(name = "enable", description = "Enables a feature")
public class EnableSubCommand extends BatSubCommand { public class EnableSubCommand extends BatCommand {
@Autowired @Autowired
public EnableSubCommand() { public EnableSubCommand() {
super.addOption(OptionType.STRING, "feature", "The feature to enable", true); super.addOptions(new OptionData(OptionType.STRING, "feature", "The feature to enable", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
FeatureProfile featureProfile = guild.getFeatureProfile(); FeatureProfile featureProfile = guild.getFeatureProfile();
OptionMapping featureOption = event.getOption("feature"); OptionMapping featureOption = event.getOption("feature");
if (featureOption == null) { if (featureOption == null) {

View File

@ -1,8 +1,8 @@
package cc.fascinated.bat.features.base.commands.server.feature; package cc.fascinated.bat.base.commands.server.feature;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.Category; import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -17,8 +17,10 @@ import org.springframework.stereotype.Component;
public class FeatureCommand extends BatCommand { public class FeatureCommand extends BatCommand {
@Autowired @Autowired
public FeatureCommand(@NonNull ApplicationContext context) { public FeatureCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(EnableSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(DisableSubCommand.class)); context.getBean(EnableSubCommand.class),
super.addSubCommand(context.getBean(ListSubCommand.class)); context.getBean(DisableSubCommand.class),
context.getBean(ListSubCommand.class)
);
} }
} }

View File

@ -1,15 +1,16 @@
package cc.fascinated.bat.features.base.commands.server.feature; package cc.fascinated.bat.base.commands.server.feature;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.common.feature.Feature;
import cc.fascinated.bat.features.base.profile.FeatureProfile; import cc.fascinated.bat.common.feature.FeatureProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.service.FeatureService; import cc.fascinated.bat.service.FeatureService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -19,9 +20,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component("feature:list.sub") @Component("feature:list.sub")
@CommandInfo(name = "list", description = "Lists the features and their states") @CommandInfo(name = "list", description = "Lists the features and their states")
public class ListSubCommand extends BatSubCommand { public class ListSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
StringBuilder featureStates = new StringBuilder(); StringBuilder featureStates = new StringBuilder();
for (Feature feature : FeatureService.INSTANCE.getFeaturesSorted()) { for (Feature feature : FeatureService.INSTANCE.getFeaturesSorted()) {
FeatureProfile featureProfile = guild.getFeatureProfile(); FeatureProfile featureProfile = guild.getFeatureProfile();

View File

@ -0,0 +1,54 @@
package cc.fascinated.bat.base.commands.utility;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.DescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.PasteUtils;
import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component
@CommandInfo(
name = "pastebin",
description = "Uploads the given text to Paste",
userInstall = true,
category = Category.UTILITY
)
public class PastebinCommand extends BatCommand {
public PastebinCommand() {
super.addOptions(
new OptionData(OptionType.STRING, "text", "The text to upload to Paste", true)
);
}
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
OptionMapping textOption = event.getOption("text");
assert textOption != null;
String text = textOption.getAsString();
// Upload the text to pastebin
String url = PasteUtils.uploadPaste(text).getUrl();
event.replyEmbeds(EmbedUtils.successEmbed()
.setDescription(new DescriptionBuilder("The text has been uploaded to Paste!")
.appendLine("URL: %s".formatted(url), true)
.build())
.build())
.setEphemeral(true)
.queue();
}
}

View File

@ -0,0 +1,28 @@
package cc.fascinated.bat.base.commands.utility.lookup;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Nick (okNick)
*/
@Component
@CommandInfo(
name = "lookup",
description = "View the banner of the guild or a user",
userInstall = true,
category = Category.UTILITY
)
public class LookupCommand extends BatCommand {
@Autowired
public LookupCommand(@NonNull ApplicationContext context) {
super.addSubCommands(
context.getBean(UserSubCommand.class)
);
}
}

View File

@ -0,0 +1,75 @@
package cc.fascinated.bat.base.commands.utility.lookup;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.DescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.service.UserService;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component("lookup.user:sub")
@CommandInfo(name = "user", description = "Lookup a user")
public class UserSubCommand extends BatCommand {
private final UserService userService;
@Autowired
public UserSubCommand(@NonNull UserService userService) {
this.userService = userService;
super.addOptions(new OptionData(OptionType.STRING, "id", "The id of the user", true));
}
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
OptionMapping idOption = event.getOption("id");
if (idOption == null) {
return;
}
User target = userService.getUser(idOption.getAsString()).getDiscordUser();
if (target == null) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("User `%s` not found".formatted(idOption.getAsString()))
.build())
.setEphemeral(true)
.queue();
return;
}
// The flags of the user (eg. Discord Partner, Hypesquad Events, etc.)
StringBuilder flags = new StringBuilder();
for (User.UserFlag flag : target.getFlags()) {
flags.append("`").append(flag.getName()).append("`, ");
}
String name = target.getGlobalName() == null ? target.getName() : target.getGlobalName().replaceAll("`", "");
target.retrieveProfile().queue(profile -> event.replyEmbeds(EmbedUtils.genericEmbed()
.setDescription(new DescriptionBuilder("User Lookup")
.appendLine("Name: `%s`".formatted(name), true)
.appendLine("Username: `%s`".formatted(target.getName()), true)
.appendLine("ID: `%s`".formatted(target.getId()), true)
.appendLine("Flags: %s".formatted(flags.toString().isEmpty() ? "None" : flags.substring(0, flags.length() - 2)), true)
.appendLine("Joined Discord: <t:%s:R>".formatted(target.getTimeCreated().toEpochSecond()), true)
.appendLine("Avatar: %s".formatted(target.getAvatar() == null ? "None"
: "[click here](%s)".formatted(target.getAvatar().getUrl(4096))), true)
.appendLine("Banner: %s".formatted(profile.getBanner() == null ? "None"
: "[click here](%s)".formatted(profile.getBanner().getUrl(4096))), true)
.build())
.setThumbnail(target.getAvatar() == null ? null : target.getAvatar().getUrl(4096))
.build())
.setEphemeral(true)
.queue());
}
}

View File

@ -1,12 +1,12 @@
package cc.fascinated.bat.features.birthday; package cc.fascinated.bat.birthday;
import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.common.feature.Feature;
import cc.fascinated.bat.features.birthday.command.BirthdayCommand; import cc.fascinated.bat.common.feature.FeatureProfile;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.birthday.command.BirthdayCommand;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.birthday.profile.BirthdayProfile;
import cc.fascinated.bat.service.CommandService; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.service.OldCommandService;
import cc.fascinated.bat.service.DiscordService; import cc.fascinated.bat.service.DiscordService;
import cc.fascinated.bat.service.GuildService; import cc.fascinated.bat.service.GuildService;
import lombok.NonNull; import lombok.NonNull;
@ -22,8 +22,8 @@ import org.springframework.stereotype.Component;
public class BirthdayFeature extends Feature implements EventListener { public class BirthdayFeature extends Feature implements EventListener {
private final GuildService guildService; private final GuildService guildService;
public BirthdayFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService, @NonNull GuildService guildService) { public BirthdayFeature(@NonNull ApplicationContext context, @NonNull OldCommandService commandService, @NonNull GuildService guildService) {
super("Birthday", true, Category.UTILITY); super("Birthday", FeatureProfile.FeatureState.DISABLED, true);
this.guildService = guildService; this.guildService = guildService;
registerCommand(commandService, context.getBean(BirthdayCommand.class)); registerCommand(commandService, context.getBean(BirthdayCommand.class));
@ -36,7 +36,7 @@ public class BirthdayFeature extends Feature implements EventListener {
private void checkBirthdays() { private void checkBirthdays() {
for (Guild guild : DiscordService.JDA.getGuilds()) { for (Guild guild : DiscordService.JDA.getGuilds()) {
BatGuild batGuild = guildService.getGuild(guild.getId()); BatGuild batGuild = guildService.getGuild(guild.getId());
if (batGuild == null) { if (batGuild.getFeatureProfile().isFeatureDisabled(this)) { // Check if the feature is disabled
continue; continue;
} }
BirthdayProfile profile = batGuild.getBirthdayProfile(); BirthdayProfile profile = batGuild.getBirthdayProfile();

View File

@ -1,4 +1,4 @@
package cc.fascinated.bat.features.birthday; package cc.fascinated.bat.birthday;
import cc.fascinated.bat.common.Serializable; import cc.fascinated.bat.common.Serializable;
import com.google.gson.Gson; import com.google.gson.Gson;
@ -58,7 +58,5 @@ public class UserBirthday extends Serializable {
} }
@Override @Override
public void reset() { public void reset() {}
}
} }

View File

@ -0,0 +1,28 @@
package cc.fascinated.bat.birthday.command;
import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.common.oldcommand.Category;
import cc.fascinated.bat.common.oldcommand.CommandInfo;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component
@CommandInfo(name = "birthday", description = "Modify your birthday settings.", category = Category.UTILITY)
public class BirthdayCommand extends BatCommand {
@Autowired
public BirthdayCommand(@NonNull ApplicationContext context) {
super.addSubCommands(
context.getBean(SetSubCommand.class),
context.getBean(RemoveSubCommand.class),
context.getBean(ChannelSubCommand.class),
context.getBean(MessageSubCommand.class),
context.getBean(ViewSubCommand.class),
context.getBean(PrivateSubCommand.class)
);
}
}

View File

@ -1,21 +1,23 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.TextChannelUtils; import cc.fascinated.bat.common.TextChannelUtils;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.birthday.profile.BirthdayProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -24,14 +26,14 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:channel.sub") @Component("birthday:channel.sub")
@CommandInfo(name = "channel", description = "Sets the birthday notification channel", requiredPermissions = Permission.MANAGE_SERVER) @CommandInfo(name = "channel", description = "Sets the birthday notification channel", requiredPermissions = Permission.MANAGE_SERVER)
public class ChannelSubCommand extends BatSubCommand { public class ChannelSubCommand extends BatCommand {
@Autowired @Autowired
public ChannelSubCommand() { public ChannelSubCommand() {
super.addOption(OptionType.CHANNEL, "channel", "The channel birthdays will be sent in", false); super.addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel birthdays will be sent in", false));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
BirthdayProfile profile = guild.getBirthdayProfile(); BirthdayProfile profile = guild.getBirthdayProfile();
OptionMapping option = event.getOption("channel"); OptionMapping option = event.getOption("channel");
if (option == null) { if (option == null) {

View File

@ -1,18 +1,20 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.birthday.profile.BirthdayProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,24 +24,19 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:message.sub") @Component("birthday:message.sub")
@CommandInfo(name = "message", description = "Changes the message that is sent when it is a user's birthday", requiredPermissions = Permission.MANAGE_SERVER) @CommandInfo(name = "message", description = "Changes the message that is sent when it is a user's birthday", requiredPermissions = Permission.MANAGE_SERVER)
public class MessageSubCommand extends BatSubCommand { public class MessageSubCommand extends BatCommand {
@Autowired @Autowired
public MessageSubCommand() { public MessageSubCommand() {
super.addOption(OptionType.STRING, "message", "The message that is sent. (Placeholders: {user}, {age})", true); super.addOptions(new OptionData(OptionType.STRING, "message", "The message that is sent. (Placeholders: {user}, {age})", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
BirthdayProfile profile = guild.getBirthdayProfile(); BirthdayProfile profile = guild.getBirthdayProfile();
OptionMapping messageOption = event.getOption("message"); OptionMapping messageOption = event.getOption("message");
if (messageOption == null) { assert messageOption != null;
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You must provide a message")
.build()).queue();
return;
}
String message = messageOption.getAsString(); String message = messageOption.getAsString();
if (message.length() > 2000) { if (message.length() > 2000) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("The message must be less than 2000 characters") .setDescription("The message must be less than 2000 characters")

View File

@ -1,18 +1,20 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.UserBirthday; import cc.fascinated.bat.birthday.UserBirthday;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.birthday.profile.BirthdayProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,24 +24,19 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:private.sub") @Component("birthday:private.sub")
@CommandInfo(name = "private", description = "Changes whether your birthday is private or not") @CommandInfo(name = "private", description = "Changes whether your birthday is private or not")
public class PrivateSubCommand extends BatSubCommand { public class PrivateSubCommand extends BatCommand {
@Autowired @Autowired
public PrivateSubCommand() { public PrivateSubCommand() {
super.addOption(OptionType.BOOLEAN, "enabled", "Whether your birthday is private or not", true); super.addOptions(new OptionData(OptionType.BOOLEAN, "enabled", "Whether your birthday is private or not", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
BirthdayProfile profile = guild.getBirthdayProfile(); BirthdayProfile profile = guild.getBirthdayProfile();
OptionMapping enabledOption = event.getOption("enabled"); OptionMapping enabledOption = event.getOption("enabled");
if (enabledOption == null) { assert enabledOption != null;
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You must provide whether your birthday is private or not")
.build()).queue();
return;
}
boolean enabled = enabledOption.getAsBoolean(); boolean enabled = enabledOption.getAsBoolean();
UserBirthday birthday = profile.getBirthday(user.getId()); UserBirthday birthday = profile.getBirthday(user.getId());
if (birthday == null) { if (birthday == null) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()

View File

@ -1,13 +1,14 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.birthday.profile.BirthdayProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -18,9 +19,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:remove.sub") @Component("birthday:remove.sub")
@CommandInfo(name = "remove", description = "Remove your birthday from this guild") @CommandInfo(name = "remove", description = "Remove your birthday from this guild")
public class RemoveSubCommand extends BatSubCommand { public class RemoveSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
BirthdayProfile profile = guild.getBirthdayProfile(); BirthdayProfile profile = guild.getBirthdayProfile();
profile.removeBirthday(user.getId()); profile.removeBirthday(user.getId());

View File

@ -1,18 +1,20 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.UserBirthday; import cc.fascinated.bat.birthday.UserBirthday;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.birthday.profile.BirthdayProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -26,16 +28,16 @@ import java.util.Date;
*/ */
@Component("birthday:add.sub") @Component("birthday:add.sub")
@CommandInfo(name = "set", description = "Add your birthday to this guild") @CommandInfo(name = "set", description = "Add your birthday to this guild")
public class SetSubCommand extends BatSubCommand { public class SetSubCommand extends BatCommand {
private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd/MM/yyyy"); private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd/MM/yyyy");
@Autowired @Autowired
public SetSubCommand() { public SetSubCommand() {
super.addOption(OptionType.STRING, "birthday", "Your birthday (format: DAY/MONTH/YEAR - 01/05/2004)", true); super.addOptions(new OptionData(OptionType.STRING, "birthday", "Your birthday (format: DAY/MONTH/YEAR - 01/05/2004)", true));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
BirthdayProfile profile = guild.getBirthdayProfile(); BirthdayProfile profile = guild.getBirthdayProfile();
if (!profile.hasChannelSetup()) { if (!profile.hasChannelSetup()) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()
@ -45,13 +47,9 @@ public class SetSubCommand extends BatSubCommand {
} }
OptionMapping birthdayOption = event.getOption("birthday"); OptionMapping birthdayOption = event.getOption("birthday");
if (birthdayOption == null) { assert birthdayOption != null;
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You must provide a birthday")
.build()).queue();
return;
}
String birthdayString = birthdayOption.getAsString(); String birthdayString = birthdayOption.getAsString();
Date birthday = parseBirthday(birthdayString); Date birthday = parseBirthday(birthdayString);
if (birthday == null) { if (birthday == null) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()

View File

@ -1,19 +1,21 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.oldcommand.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.UserBirthday; import cc.fascinated.bat.birthday.UserBirthday;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.birthday.profile.BirthdayProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import cc.fascinated.bat.service.UserService; import cc.fascinated.bat.service.UserService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -23,17 +25,17 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:view.sub") @Component("birthday:view.sub")
@CommandInfo(name = "view", description = "Add your birthday to this guild") @CommandInfo(name = "view", description = "Add your birthday to this guild")
public class ViewSubCommand extends BatSubCommand { public class ViewSubCommand extends BatCommand {
private final UserService userService; private final UserService userService;
@Autowired @Autowired
public ViewSubCommand(@NonNull UserService userService) { public ViewSubCommand(@NonNull UserService userService) {
this.userService = userService; this.userService = userService;
super.addOption(OptionType.USER, "user", "The user to view the birthday of", false); super.addOptions(new OptionData(OptionType.USER, "user", "The user to view the birthday of", false));
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, Message commandMessage, String[] arguments, SlashCommandInteraction event) {
BirthdayProfile profile = guild.getBirthdayProfile(); BirthdayProfile profile = guild.getBirthdayProfile();
if (!profile.hasChannelSetup()) { if (!profile.hasChannelSetup()) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()

View File

@ -1,8 +1,9 @@
package cc.fascinated.bat.features.birthday.profile; package cc.fascinated.bat.birthday.profile;
import cc.fascinated.bat.common.ChannelUtils;
import cc.fascinated.bat.common.Serializable; import cc.fascinated.bat.common.Serializable;
import cc.fascinated.bat.features.birthday.UserBirthday; import cc.fascinated.bat.birthday.UserBirthday;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import com.google.gson.Gson; import com.google.gson.Gson;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -157,7 +158,7 @@ public class BirthdayProfile extends Serializable {
return; return;
} }
TextChannel channel = discordGuild.getTextChannelById(channelId); TextChannel channel = ChannelUtils.getTextChannel(channelId);
if (channel == null) { // this should never happen if (channel == null) { // this should never happen
channelId = null; channelId = null;
return; return;

View File

@ -1,97 +1,140 @@
package cc.fascinated.bat.command; package cc.fascinated.bat.command;
import cc.fascinated.bat.features.Feature;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter; import lombok.Setter;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.internal.interactions.CommandDataImpl; import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
import java.util.HashMap; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author Fascinated (fascinated7) * @author Braydon
*/ */
@Getter @Setter@Getter
@Setter public abstract class BatCommand extends ListenerAdapter implements IBatCommand {
public abstract class BatCommand implements BatCommandExecutor {
/** /**
* The information about the command * The snowflake of this command, if it
* was successfully registered on Discord.
*/ */
private final CommandInfo commandInfo; private Long snowflake;
/** /**
* The command data for the slash command * The data for this command.
*/ */
private final CommandDataImpl commandData; @NonNull private final SlashCommandData commandData;
/** /**
* The sub commands of the command * The category of this command.
*/ */
private final Map<String, BatSubCommand> subCommands = new HashMap<>(); @NonNull private final CommandCategory category;
/** /**
* The category of the command * The sub-commands for this command.
*/ */
private Category category; @NonNull private final List<BatSubCommand> subCommands = Collections.synchronizedList(new ArrayList<>());
/** public BatCommand(@NonNull String name, @NonNull String description, @NonNull CommandCategory category, @NonNull OptionData... options) {
* The feature that the command belongs to this(name, description, category, DefaultMemberPermissions.ENABLED, options);
*/ }
private Feature feature;
/** public BatCommand(@NonNull String name, @NonNull String description, @NonNull CommandCategory category, @NonNull DefaultMemberPermissions defaultPermissions, @NonNull OptionData... options) {
* Whether the command can only be used by the bot owner commandData = Commands.slash(name, description)
*/ .setDefaultPermissions(defaultPermissions)
private boolean botOwnerOnly; .addOptions(options);
this.category = category;
/**
* The command snowflake from Discord
*/
private long commandSnowflake;
public BatCommand() {
this.commandInfo = getClass().getAnnotation(CommandInfo.class);
this.category = this.commandInfo.category();
this.botOwnerOnly = this.commandInfo.botOwnerOnly();
this.commandData = new CommandDataImpl(this.commandInfo.name(), this.commandInfo.description())
.setGuildOnly(this.commandInfo.guildOnly());
} }
/** /**
* Adds a sub command to the command * Get the name of this command.
* *
* @param subCommand The sub command * @return the command name
*/ */
public void addSubCommand(@NonNull BatSubCommand subCommand) { @Override @NonNull
this.subCommands.put(subCommand.getCommandInfo().name().toLowerCase(), subCommand); public String getName() {
this.commandData.addSubcommands(subCommand.getCommandData()); return commandData.getName();
} }
/** /**
* Adds an option to the sub command * Get the full name of this command.
* *
* @param optionType the type of the option * @return the full name
* @param name the name of the option
* @param description the description of the option
* @param required whether the option is required
*/ */
protected void addOption(OptionType optionType, String name, String description, boolean required) { @Override @NonNull
this.commandData.addOption(optionType, name, description, required); public String getFullName() {
return getName();
} }
/** /**
* Gets all the options for the command * Get the description of this command.
* *
* @param interaction The slash command interaction * @return the command description
* @return The option strings
*/ */
public List<String> getOptions(SlashCommandInteraction interaction) { @Override @NonNull
return interaction.getOptions().stream().map(OptionMapping::getName).toList(); public String getDescription() {
return commandData.getDescription();
}
/**
* Get the mentionable name of this command.
*
* @return the mentionable name
*/
@Override @NonNull
public final String getMentionable() {
return "</%s:%s>".formatted(getName(), getSnowflake());
}
/**
* Register a sub-command to this command.
*
* @param subCommand the sub-command to register
*/
protected final void withSubCommand(@NonNull BatSubCommand subCommand) {
subCommands.add(subCommand);
// Add the sub-command to the command data
if (subCommand.getGroupName() == null) { // No command group
getCommandData().addSubcommands(subCommand.getCommandData());
} else {
// Add to any existing command group, otherwise create a new one
for (SubcommandGroupData subCommandGroup : getCommandData().getSubcommandGroups()) {
if (subCommand.getGroupName().equals(subCommandGroup.getName())) {
subCommandGroup.addSubcommands(subCommand.getCommandData());
return;
}
}
getCommandData().addSubcommandGroups(new SubcommandGroupData(
subCommand.getGroupName(),
"The " + subCommand.getGroupName() + " group for /" + getName() + " " + subCommand.getName()
).addSubcommands(subCommand.getCommandData()));
}
}
/**
* Get a sub-command by name.
*
* @param group the sub-command group, null if none
* @param name the sub-command name
* @return the sub-command, null if not found
*/
public final BatSubCommand getSubCommand(String group, @NonNull String name) {
for (BatSubCommand subCommand : subCommands) {
String commandGroup = subCommand.getGroupName();
// Check if groups match (both null or both equal)
boolean groupsMatch = (group == null && commandGroup == null) ||
(commandGroup != null && commandGroup.equals(group));
if (subCommand.getName().equals(name) && groupsMatch) {
return subCommand;
}
}
return null;
} }
} }

View File

@ -1,31 +0,0 @@
package cc.fascinated.bat.command;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
/**
* @author Fascinated (fascinated7)
*/
public interface BatCommandExecutor {
/**
* Executes the command using a slash command event.
*
* @param guild the bat guild the command was executed in (null if the command was executed in a DM)
* @param user the bat user that executed the command
* @param channel the channel the command was executed in
* @param member the member that executed the command
* @param event the slash command event
*/
default void execute(
BatGuild guild,
@NonNull BatUser user,
@NonNull MessageChannel channel,
Member member,
@NonNull SlashCommandInteraction event
) {
}
}

View File

@ -1,45 +1,82 @@
package cc.fascinated.bat.command; package cc.fascinated.bat.command;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull;
import lombok.Setter; import lombok.Setter;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
/** /**
* @author Fascinated (fascinated7) * A sub-command for a {@link BatCommand}.
*
* @author Braydon
*/ */
@Getter @Setter @Getter
@Setter public abstract class BatSubCommand implements IBatCommand {
public class BatSubCommand implements BatCommandExecutor {
/** /**
* The information about the sub command * The parent of this sub-command.
*/ */
private final CommandInfo commandInfo; @NonNull private final BatCommand parent;
/** /**
* The command data for the slash command * The snowflake of this sub=command, if it
* was successfully registered on Discord.
*/ */
private final SubcommandData commandData; private Long snowflake;
/** /**
* The commands snowflake from Discord * The full name of this command, including the
* parent name, category, and sub-command name.
*/ */
private long commandSnowflake; private String fullName;
public BatSubCommand() { /**
this.commandInfo = getClass().getAnnotation(CommandInfo.class); * The optional group name for this sub-command.
this.commandData = new SubcommandData(this.commandInfo.name(), this.commandInfo.description()); */
private final String groupName;
/**
* The data for this sub-command.
*/
@NonNull private final SubcommandData commandData;
public BatSubCommand(@NonNull BatCommand parent, @NonNull String name, @NonNull String description, @NonNull OptionData... options) {
this(parent, null, name, description, options);
}
public BatSubCommand(@NonNull BatCommand parent, String groupName, @NonNull String name, @NonNull String description, @NonNull OptionData... options) {
this.parent = parent;
this.groupName = groupName;
commandData = new SubcommandData(name, description).addOptions(options);
} }
/** /**
* Adds an option to the sub command * Get the name of this command.
* *
* @param optionType the type of the option * @return the command name
* @param name the name of the option
* @param description the description of the option
* @param required whether the option is required
*/ */
public void addOption(OptionType optionType, String name, String description, boolean required) { @Override @NonNull
this.commandData.addOption(optionType, name, description, required); public String getName() {
return commandData.getName();
}
/**
* Get the description of this command.
*
* @return the command description
*/
@Override @NonNull
public String getDescription() {
return commandData.getDescription();
}
/**
* Get the mentionable name of this command.
*
* @return the mentionable name
*/
@Override @NonNull
public final String getMentionable() {
return "</%s:%s>".formatted(getFullName(), getSnowflake());
} }
} }

View File

@ -1,66 +0,0 @@
package cc.fascinated.bat.command;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import java.util.Arrays;
import java.util.List;
/**
* @author Fascinated (fascinated7)
*/
@AllArgsConstructor
@Getter
public enum Category {
GENERAL(Emoji.fromUnicode("U+2699"), "General", false),
FUN(Emoji.fromFormatted("U+1F973"), "Fun", false),
SERVER(Emoji.fromFormatted("U+1F5A5"), "Server", false),
MODERATION(Emoji.fromFormatted("U+1F6E0"), "Moderation", false),
UTILITY(Emoji.fromFormatted("U+1F6E0"), "Utility", false),
MUSIC(Emoji.fromFormatted("U+1F3B5"), "Music", false),
MOVIES_TV(Emoji.fromFormatted("U+1F3A5"), "Movies & TV", false),
MESSAGES(Emoji.fromFormatted("U+1F4A3"), "Snipe", false),
LOGS(Emoji.fromFormatted("U+1F4D1"), "Logs", false),
BEAT_SABER(Emoji.fromFormatted("U+1FA84"), "Beat Saber", false),
BOT_ADMIN(null, null, true);
/**
* The emoji for the category
*/
private final Emoji emoji;
/**
* The name of the category
*/
private final String name;
/**
* If the category is hidden
*/
private final boolean hidden;
/**
* Gets a category by its name
*
* @param name the name of the category
* @return the category
*/
public static Category getByName(String name) {
for (Category category : Category.values()) {
if (category.getName().equalsIgnoreCase(name)) {
return category;
}
}
return null;
}
/**
* Gets all the visible categories
*
* @return the visible categories
*/
public static List<Category> getCategories() {
return Arrays.stream(Category.values()).filter(category -> !category.isHidden()).toList();
}
}

View File

@ -0,0 +1,25 @@
package cc.fascinated.bat.command;
import lombok.Getter;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.emoji.Emoji;
/**
* The categories of {@link BatCommand}'s.
*
* @author Braydon
*/
@Getter
public enum CommandCategory {
GENERAL("⚙️"),
GUILD("🏠");
/**
* The emoji for this category.
*/
@NonNull private final Emoji emoji;
CommandCategory(@NonNull String unicode) {
emoji = Emoji.fromUnicode(unicode);
}
}

View File

@ -0,0 +1,97 @@
package cc.fascinated.bat.command;
import cc.fascinated.bat.common.EnumUtils;
import cc.fascinated.bat.common.InteractionResponder;
import cc.fascinated.bat.common.model.BatGuild;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.Command;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* A base Rufus command.
*
* @author Braydon
*/
public interface IBatCommand {
/**
* Get the name of this command.
*
* @return the command name
*/
@NonNull String getName();
/**
* Get the full name of this command.
*
* @return the full name
*/
@NonNull String getFullName();
/**
* Get the description of this command.
*
* @return the command description
*/
@NonNull String getDescription();
/**
* Get the mentionable name of this command.
*
* @return the mentionable name
*/
@NonNull String getMentionable();
/**
* Fired when this command is executed.
* <p>
* If this command has {@link BatSubCommand}'s, this
* will not be invoked for the parent, and instead only
* for the sub-commands.
* </p>
*
* @param guild the ticket guild that executed this command
* @param discordGuild the Discord guild that executed this command
* @param member the member that executed this command
* @param responder the responder to the interaction
* @param event the event that triggered this command
*/
default void execute(@NonNull BatGuild guild, @NonNull Guild discordGuild, @NonNull Member member, @NonNull InteractionResponder responder, @NonNull SlashCommandInteractionEvent event) {
event.deferReply().queue(); // Thinking by default
}
/**
* Auto complete this command.
*
* @param guild the ticket guild that executed this command
* @param discordGuild the Discord guild that executed this command
* @param member the member that executed this command
* @param event the event that triggered this auto completion
* @return the choices to auto complete
*/
@NonNull
default List<Command.Choice> autoComplete(@NonNull BatGuild guild, @NonNull Guild discordGuild, @NonNull Member member, @NonNull CommandAutoCompleteInteractionEvent event) {
return List.of();
}
/**
* Get the choices for an enum.
*
* @param enumClass the enum class to get the choices for
* @return the enum choices
* @param <T> the enum type
*/
@NonNull
default <T extends Enum<T>> List<Command.Choice> getEnumChoices(@NonNull Class<T> enumClass) {
return Arrays.stream(enumClass.getEnumConstants())
.map(constant -> new Command.Choice(EnumUtils.getEnumName(constant), constant.name()))
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,16 @@
package cc.fascinated.bat.command.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Commands annotated with this will only
* be executable by the bot owner.
*
* @author Braydon
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface BotOwner { }

View File

@ -0,0 +1,16 @@
package cc.fascinated.bat.command.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Commands annotated with this will send
* "thinking..." message when executed.
*
* @author Braydon
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Thinking {}

View File

@ -0,0 +1,186 @@
package cc.fascinated.bat.command.command;
import cc.fascinated.bat.common.BatEmoji;
import cc.fascinated.bat.common.Colors;
import cc.fascinated.bat.common.InteractionResponder;
import cc.fascinated.bat.common.MiscUtils;
import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.service.CommandService;
import cc.fascinated.bat.service.DiscordService;
import jakarta.annotation.Nonnull;
import lombok.NonNull;
import cc.fascinated.bat.command.CommandCategory;
import cc.fascinated.bat.command.IBatCommand;
import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.BatSubCommand;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.info.BuildProperties;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author Braydon
*/
public final class HelpCommand extends BatCommand {
private static final String CATEGORY_DROPDOWN_ID = "select-category";
private static final String MAIN_MENU_BUTTON_ID = "main-help-menu";
/**
* The command service to use for the registry.
*/
@NonNull private final CommandService commandService;
/**
* The build properties for this app, null if not available.
*/
private final BuildProperties buildProperties;
public HelpCommand(@NonNull CommandService commandService, BuildProperties buildProperties) {
super("helpbob", "View the commands for Rufus", CommandCategory.GENERAL);
this.commandService = commandService;
this.buildProperties = buildProperties;
}
/**
* Fired when this command is executed.
* <p>
* If this command has {@link BatSubCommand}'s, this
* will not be invoked for the parent, and instead only
* for the sub-commands.
* </p>
*
* @param guild the ticket guild that executed this command
* @param discordGuild the Discord guild that executed this command
* @param member the member that executed this command
* @param responder the responder to the interaction
* @param event the event that triggered this command
*/
@Override
public void execute(@NonNull BatGuild guild, @NonNull Guild discordGuild, @NonNull Member member, @NonNull InteractionResponder responder, @NonNull SlashCommandInteractionEvent event) {
responder.reply(true, buildMainMenu(member, discordGuild), buildMainMenuComponents(discordGuild).toArray(new LayoutComponent[0])).queue();
}
@Override
public void onStringSelectInteraction(@NotNull StringSelectInteractionEvent event) {
// Switch to the selected category
if (event.getComponentId().equals(CATEGORY_DROPDOWN_ID)) {
event.editMessageEmbeds(buildCategoryEmbed(Objects.requireNonNull(event.getMember()), CommandCategory.valueOf(event.getSelectedOptions().getFirst().getValue())))
.setComponents(
ActionRow.of(buildCategoryMenu()),
ActionRow.of(Button.primary(MAIN_MENU_BUTTON_ID, "Main Menu").withEmoji(Emoji.fromUnicode("🏠")))
).queue();
}
}
@Override
public void onButtonInteraction(@NotNull ButtonInteractionEvent event) {
// Switch to the main menu
if (event.getComponentId().equals(MAIN_MENU_BUTTON_ID)) {
event.editMessageEmbeds(buildMainMenu(Objects.requireNonNull(event.getMember()),
Objects.requireNonNull(event.getGuild()))).setComponents(buildMainMenuComponents(event.getGuild())).queue();
}
}
/**
* Build the embed for the main menu.
*
* @param member the member to build for
* @param discordGuild the discord guild
* @return the main menu
*/
@NonNull
private MessageEmbed buildMainMenu(@NonNull Member member, @NonNull Guild discordGuild) {
String categoryNames = Arrays.stream(CommandCategory.values())
.map(category -> "- **%s Commands**: `%s`".formatted(MiscUtils.capitalize(category.name()), commandService.getCommands(member, category).size()))
.collect(Collectors.joining("\n"));
// Send the help menu
return new EmbedBuilder()
.setColor(Colors.DEFAULT)
.setTitle(BatEmoji.RUFUS + " Rufus Help Menu")
.setDescription(MiscUtils.arrayToString(
"Rufus is a smart and efficient Discord bot that streamlines ticket management for your server. With a focus on simplicity and responsiveness, Rufus helps your staff team handle support requests, bug reports, and general inquiries with ease.",
"",
"Here are my commands:",
categoryNames,
"",
"To get a list of commands for an individual category, select it from the dropdown below. Interested and wanna use me in your server? [Invite Me](" + MiscUtils.getInviteUrl(discordGuild.getJDA()) + ")!"
)).setFooter("Rufus v%s".formatted(buildProperties == null ? "0" : buildProperties.getVersion())).build();
}
/**
* Build the components for the main menu.
*
* @param guild the guild to use for the JDA instance
* @return the components
*/
@NonNull
private List<LayoutComponent> buildMainMenuComponents(@NonNull Guild guild) {
return Arrays.asList(
ActionRow.of(buildCategoryMenu()),
ActionRow.of(
Button.link("https://rufus.rainnny.club", "Support Server").withEmoji(Emoji.fromUnicode("🏠")),
Button.link(MiscUtils.getInviteUrl(guild.getJDA()), "Invite Me").withEmoji(Emoji.fromUnicode("🤖"))
)
);
}
/**
* Build the dropdown menu for categories.
*
* @return the category dropdown menu
*/
@NonNull
private StringSelectMenu buildCategoryMenu() {
StringSelectMenu.Builder categoryDropdown = StringSelectMenu.create(CATEGORY_DROPDOWN_ID).setPlaceholder("👉🏼 Select a category...");
for (CommandCategory category : CommandCategory.values()) {
categoryDropdown.addOption(MiscUtils.capitalize(category.name()) + " Commands", category.name(), category.getEmoji());
}
return categoryDropdown.build();
}
/**
* Build the embed for the category menu.
*
* @param member the member to build for
* @param category the category to build for
* @return the category menu
*/
@NonNull
private MessageEmbed buildCategoryEmbed(@NonNull Member member, @NonNull CommandCategory category) {
// Build the command list
StringBuilder commands = new StringBuilder();
for (IBatCommand command : commandService.getCommands(member, category)) {
// Skip parents that have sub-commands
if (command instanceof BatCommand parentCommand && !parentCommand.getSubCommands().isEmpty()) {
continue;
}
commands.append("- ").append(command.getMentionable()).append(" - ").append(command.getDescription()).append("\n");
}
// Build the embed
return new EmbedBuilder()
.setColor(Colors.DEFAULT)
.setTitle(category.getEmoji().getFormatted() + " " + MiscUtils.capitalize(category.name()) + " Commands")
.setDescription(MiscUtils.arrayToString(
"Here are the commands for the " + MiscUtils.capitalize(category.name()) + " category:",
"",
commands.toString()
)).setFooter("Rufus v%s".formatted(buildProperties == null ? "0" : buildProperties.getVersion())).build();
}
}

View File

@ -0,0 +1,44 @@
package cc.fascinated.bat.common;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/**
* Emojis used by Rufus.
*
* @author Braydon
*/
@AllArgsConstructor @RequiredArgsConstructor @Getter
public enum BatEmoji {
RUFUS("rufus", "1319317309608689674"),
LOADING("loading", "1319483685787013212", true),
SUCCESS("success", "1319483459781132410"),
CROSS("cross", "1319483437928677446");
/**
* The name of this emoji.
*/
@NonNull private final String name;
/**
* The ID of this emoji.
*/
@NonNull private final String id;
/**
* Whether this emoji is animated.
*/
private boolean animated;
/**
* Get the formatted emoji.
*
* @return the formatted emoji
*/
@Override @NonNull
public String toString() {
return (animated ? "<a:" : "<:") + name + ":" + id + ">";
}
}

View File

@ -0,0 +1,48 @@
package cc.fascinated.bat.common;
import cc.fascinated.bat.service.DiscordService;
import lombok.experimental.UtilityClass;
import lombok.extern.log4j.Log4j2;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
/**
* @author Fascinated (fascinated7)
*/
@UtilityClass
@Log4j2(topic = "ChannelUtils")
public class ChannelUtils {
/**
* Gets the user with the given id
*
* @param id the id of the user
* @param retries the amount of retries
* @return the user with the given id
*/
private static TextChannel getTextChannel(String id, int retries) {
if (retries >= 10) {
log.error("Failed to find user \"{}\" after {} retries.", id, retries);
return null;
}
if (id == null) {
return null;
}
TextChannel channel = DiscordService.JDA.getTextChannelById(id);
if (channel == null) {
return getTextChannel(id, retries + 1);
}
if (retries >= 5) {
log.info("Found text channel \"{}\" after {} retries.", channel.getName(), retries);
}
return channel;
}
/**
* Gets the user with the given id
*
* @param id the id of the user
* @return the user with the given id
*/
public static TextChannel getTextChannel(String id) {
return getTextChannel(id, 0);
}
}

View File

@ -3,12 +3,18 @@ package cc.fascinated.bat.common;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Date; import java.util.Date;
import java.util.Locale;
@UtilityClass @UtilityClass
public class DateUtils { public class DateUtils {
private static final ZoneId ZONE_ID = ZoneId.of("Europe/London");
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_INSTANT; private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_INSTANT;
private static final DateTimeFormatter SIMPLE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z")
.withLocale(Locale.UK)
.withZone(ZONE_ID);
/** /**
* Gets the date from a string. * Gets the date from a string.
@ -19,4 +25,14 @@ public class DateUtils {
public static Date getDateFromString(String date) { public static Date getDateFromString(String date) {
return Date.from(Instant.from(FORMATTER.parse(date))); return Date.from(Instant.from(FORMATTER.parse(date)));
} }
/**
* Formats a date to a string.
*
* @param date The date to format.
* @return The formatted date.
*/
public String formatDate(Date date) {
return SIMPLE_FORMATTER.format(date.toInstant());
}
} }

View File

@ -5,30 +5,33 @@ import lombok.NonNull;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
public class EmbedDescriptionBuilder { public class DescriptionBuilder {
/** /**
* Where the description is stored * Where the description is stored
*/ */
private final StringBuilder builder = new StringBuilder(); private final StringBuilder builder = new StringBuilder();
public EmbedDescriptionBuilder(String title) { public DescriptionBuilder(String title) {
if (title == null) {
return;
}
builder.append("**").append(title).append("**").append("\n"); builder.append("**").append(title).append("**").append("\n");
} }
@NonNull @NonNull
public EmbedDescriptionBuilder appendLine(@NonNull String line, boolean arrow) { public DescriptionBuilder appendLine(@NonNull String line, boolean arrow) {
builder.append(arrow ? "" : "").append(line).append("\n"); builder.append(arrow ? "" : "").append(line).append("\n");
return this; return this;
} }
@NonNull @NonNull
public EmbedDescriptionBuilder appendSubtitle(@NonNull String title) { public DescriptionBuilder appendSubtitle(@NonNull String title) {
builder.append("**").append(title).append("**").append("\n"); builder.append("**").append(title).append("**").append("\n");
return this; return this;
} }
@NonNull @NonNull
public EmbedDescriptionBuilder emptyLine() { public DescriptionBuilder emptyLine() {
builder.append("\n"); builder.append("\n");
return this; return this;
} }

View File

@ -1,7 +1,9 @@
package cc.fascinated.bat.common; package cc.fascinated.bat.common;
import cc.fascinated.bat.config.Config;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -42,4 +44,30 @@ public class EmbedUtils {
.setTimestamp(LocalDateTime.now()) .setTimestamp(LocalDateTime.now())
.setColor(Colors.SUCCESS); .setColor(Colors.SUCCESS);
} }
/**
* Builds a generic interaction error embed
*
* @param ex the exceptionk
* @return the embed builder
*/
public static EmbedBuilder genericInteractionError(Exception ex) {
TextChannel channel = ChannelUtils.getTextChannel(Config.INSTANCE.getLogsChannel());
EmbedBuilder embed = errorEmbed()
.setDescription("""
An error has occurred while processing %s interaction. If this issue persists, please contact the developers.
Cause: `%s`
```java
%s
```""".formatted(
channel == null ? "an" : "your",
ex.getStackTrace()[0].getClassName(),
ex.getLocalizedMessage()
));
if (channel != null) {
channel.sendMessageEmbeds(embed.build()).queue();
}
return embed;
}
} }

View File

@ -1,8 +1,11 @@
package cc.fascinated.bat.common; package cc.fascinated.bat.common;
import lombok.experimental.UtilityClass;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@UtilityClass
public class EnumUtils { public class EnumUtils {
/** /**
* Gets the name of the enum * Gets the name of the enum

View File

@ -0,0 +1,58 @@
package cc.fascinated.bat.common;
import lombok.experimental.UtilityClass;
import java.awt.*;
/**
* @author Fascinated (fascinated7)
*/
@UtilityClass
public class HexColorUtils {
/**
* Checks if the given string is a hex color
*
* @param hexColor the hex color to check
* @return if the given string is a hex color
*/
public static boolean isHexColor(String hexColor) {
return hexColor.matches("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$");
}
/**
* Converts a hex color to a Color object
*
* @param hex the hex color to convert
* @return the Color object
*/
public static Color hexToColor(String hex) {
if (hex == null || (!hex.matches("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"))) {
throw new IllegalArgumentException("Invalid hex color code");
}
// Remove the '#' character
hex = hex.substring(1);
// If the hex code is 3 characters long, expand it to 6 characters
if (hex.length() == 3) {
char r = hex.charAt(0);
char g = hex.charAt(1);
char b = hex.charAt(2);
hex = "" + r + r + g + g + b + b;
}
// Convert the hex string to an integer and create a Color object
int rgb = Integer.parseInt(hex, 16);
return new Color(rgb);
}
/**
* Converts a Color object to a hex color
*
* @param color the Color object to convert
* @return the hex color
*/
public static String colorToHex(Color color) {
return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue());
}
}

View File

@ -0,0 +1,105 @@
package cc.fascinated.bat.common;
import cc.fascinated.bat.service.InteractionService;
import lombok.Getter;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
/**
* @author Fascinated (fascinated7)
*/
@Getter
public class InteractionBuilder {
/**
* The button interactions
*/
private final Map<Button, Consumer<ButtonInteractionEvent>> buttonInteractions = new HashMap<>();
/**
* The select menu interactions
*/
private final Map<SelectOption, Consumer<StringSelectInteractionEvent>> selectMenuInteractions = new HashMap<>();
/**
* The select menu id
*/
private String selectMenuId;
public InteractionBuilder() {
InteractionService.INSTANCE.addInteractionBuilder(this);
}
/**
* Adds a button to the interaction builder
*
* @param display The display of the button
* @param onClick The consumer to run when the button is clicked
* @return - The interaction builder
*/
public InteractionBuilder addButton(String display, Consumer<ButtonInteractionEvent> onClick) {
String id = StringUtils.randomString(8);
this.buttonInteractions.put(Button.primary(id, display), onClick);
return this;
}
/**
* Adds a URL button to the interaction builder
*
* @param display The display of the button
* @param url The url to open when the button is clicked
* @return - The interaction builder
*/
public InteractionBuilder addUrlButton(String display, String url, Emoji emoji) {
this.buttonInteractions.put(Button.link(url, display).withEmoji(emoji), event -> {});
return this;
}
/**
* Adds a string selection to the interaction builder
*
* @param display the name of the selection
* @param description the description of the selection
* @param emoji the emoji of the selection
* @param onClick the consumer to run when the selection is clicked
* @return the interaction builder
*/
public InteractionBuilder addStringSelect(String display, String description, Emoji emoji, Consumer<StringSelectInteractionEvent> onClick) {
String id = StringUtils.randomString(8);
this.selectMenuInteractions.put(SelectOption.of(display, id).withDescription(description).withEmoji(emoji), onClick);
return this;
}
/**
* Builds the interactions into an action row
*
* @return The action row
*/
public List<ActionRow> build() {
List<ActionRow> components = new ArrayList<>();
if (!this.getButtonInteractions().isEmpty()) {
List<Button> buttons = new ArrayList<>(this.getButtonInteractions().keySet());
components.add(ActionRow.of(buttons));
}
if (!this.getSelectMenuInteractions().isEmpty()) {
List<SelectOption> options = new ArrayList<>(this.getSelectMenuInteractions().keySet());
String id = StringUtils.randomString(8);
this.selectMenuId = id;
components.add(ActionRow.of(StringSelectMenu.create(id)
.addOptions(options)
.build()));
}
return components;
}
}

View File

@ -0,0 +1,294 @@
package cc.fascinated.bat.common;
import cc.fascinated.bat.Consts;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.interactions.InteractionHook;
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.api.requests.restaction.WebhookMessageCreateAction;
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
import java.awt.*;
/**
* A simple utility class to make
* responding to interactions easier.
*
* @author Braydon
*/
@AllArgsConstructor
public final class InteractionResponder {
/**
* The interaction event to respond to.
*/
@NonNull private final IReplyCallback event;
/**
* Respond to the interaction with a generic embed.
*
* @param content the content to respond with
* @param args the optional arguments to format the content with
* @return the reply action
*/
@NonNull
public RestAction<Message> replyGenericEmbed(@NonNull String content, Object... args) {
return replyGenericEmbed(content, args, (LayoutComponent[]) null);
}
/**
* Respond to the interaction with a generic embed.
*
* @param content the content to respond with
* @param args the optional arguments to format the content with
* @param components the optional components to add to the message
* @return the reply action
*/
@NonNull
public RestAction<Message> replyGenericEmbed(@NonNull String content, Object[] args, LayoutComponent... components) {
return replyGenericEmbed(false, content, args, components);
}
/**
* Respond to the interaction with a generic embed.
*
* @param ephemeral whether the message should be ephemeral
* @param content the content to respond with
* @param args the optional arguments to format the content with
* @return the reply action
*/
@NonNull
public RestAction<Message> replyGenericEmbed(boolean ephemeral, @NonNull String content, Object... args) {
return replyGenericEmbed(ephemeral, content, args, (LayoutComponent[]) null);
}
/**
* Respond to the interaction with a generic embed.
*
* @param ephemeral whether the message should be ephemeral
* @param content the content to respond with
* @param components the optional components to add to the message
* @return the reply action
*/
@NonNull
public RestAction<Message> replyGenericEmbed(boolean ephemeral, @NonNull String content, LayoutComponent... components) {
return replyGenericEmbed(ephemeral, content, null, components);
}
/**
* Respond to the interaction with a generic embed.
*
* @param ephemeral whether the message should be ephemeral
* @param content the content to respond with
* @param args the optional arguments to format the content with
* @param components the optional components to add to the message
* @return the reply action
*/
@NonNull
public RestAction<Message> replyGenericEmbed(boolean ephemeral, @NonNull String content, Object[] args, LayoutComponent... components) {
content = format(content, args);
return reply(ephemeral, buildGenericEmbed(content, args), components);
}
/**
* Build a generic embed.
*
* @param content the content to respond with
* @param args the optional arguments to format the content with
* @return the embed
*/
@NonNull
public MessageEmbed buildGenericEmbed(@NonNull String content, Object... args) {
content = format(content, args);
return new EmbedBuilder()
.setColor(Colors.DEFAULT)
.setDescription(format(content, args))
.build();
}
/**
* Respond to the interaction with a success embed.
*
* @param content the content to respond with
* @param args the optional arguments to format the content with
* @return the reply action
*/
@NonNull
public RestAction<Message> replySuccess(@NonNull String content, Object... args) {
return replySuccess(false, content, args);
}
/**
* Respond to the interaction with a success embed.
*
* @param content the content to respond with
* @param args the optional arguments to format the content with
* @param components the optional components to add to the message
* @return the reply action
*/
@NonNull
public RestAction<Message> replySuccess(@NonNull String content, Object[] args, LayoutComponent... components) {
return replySuccess(false, content, args, components);
}
/**
* Respond to the interaction with a success embed.
*
* @param ephemeral whether the message should be ephemeral
* @param content the content to respond with
* @param args the optional arguments to format the content with
* @return the reply action
*/
@NonNull
public RestAction<Message> replySuccess(boolean ephemeral, @NonNull String content, Object... args) {
return replySuccess(ephemeral, content, args, (LayoutComponent[]) null);
}
/**
* Respond to the interaction with a success embed.
*
* @param ephemeral whether the message should be ephemeral
* @param content the content to respond with
* @param args the optional arguments to format the content with
* @param components the optional components to add to the message
* @return the reply action
*/
@NonNull
public RestAction<Message> replySuccess(boolean ephemeral, @NonNull String content, Object[] args, LayoutComponent... components) {
content = format(content, args);
return reply(ephemeral, new EmbedBuilder()
.setColor(Color.GREEN)
.setDescription(BatEmoji.SUCCESS + " " + content)
.build(), components);
}
/**
* Respond to the interaction with an error embed.
*
* @param error the error to respond with
* @param args the optional arguments to format the error with
* @return the reply action
*/
@NonNull
public RestAction<Message> replyError(@NonNull String error, Object... args) {
return replyError(false, error, args);
}
/**
* Respond to the interaction with an error embed.
*
* @param ephemeral whether the message should be ephemeral
* @param error the error to respond with
* @param args the optional arguments to format the error with
* @return the reply action
*/
@NonNull
public RestAction<Message> replyError(boolean ephemeral, @NonNull String error, Object... args) {
error = format(error, args);
return reply(ephemeral, new EmbedBuilder()
.setColor(Color.RED)
.setDescription(BatEmoji.CROSS + " " + error)
.build());
}
/**
* Respond to the interaction with an embed.
*
* @param embed the embed to respond with
* @return the reply action
*/
@NonNull
public RestAction<Message> reply(@NonNull MessageEmbed embed) {
return reply(false, embed);
}
/**
* Respond to the interaction with an embed.
*
* @param embed the embed to respond with
* @param components the optional components to add to the message
* @return the reply action
*/
@NonNull
public RestAction<Message> reply(@NonNull MessageEmbed embed, LayoutComponent... components) {
return reply(false, embed, components);
}
/**
* Respond to the interaction with an embed.
*
* @param ephemeral whether the message should be ephemeral
* @param embed the embed to respond with
* @return the reply action
*/
@NonNull
public RestAction<Message> reply(boolean ephemeral, @NonNull MessageEmbed embed) {
return reply(ephemeral, embed, (LayoutComponent[]) null);
}
/**
* Respond to the interaction with an embed.
*
* @param ephemeral whether the message should be ephemeral
* @param embed the embed to respond with
* @param components the optional components to add to the message
* @return the reply action
*/
@NonNull
public RestAction<Message> reply(boolean ephemeral, @NonNull MessageEmbed embed, LayoutComponent... components) {
boolean hasComponents = components != null && (components.length > 0);
if (event.isAcknowledged()) {
WebhookMessageCreateAction<Message> action = event.getHook()
.setEphemeral(ephemeral)
.sendMessageEmbeds(embed);
return hasComponents ? action.setComponents(components) : action;
}
ReplyCallbackAction action = event.replyEmbeds(embed).setEphemeral(ephemeral);
return (hasComponents ? action.setComponents(components) : action).flatMap(InteractionHook::retrieveOriginal);
}
/**
* Respond to the interaction with a message.
*
* @param content the message to respond with
* @param args the optional arguments to format the message with
* @return the reply action
*/
@NonNull
public RestAction<Message> reply(@NonNull String content, Object... args) {
return reply(false, content, args);
}
/**
* Respond to the interaction with a message.
*
* @param ephemeral whether the message should be ephemeral
* @param content the message to respond with
* @param args the optional arguments to format the message with
* @return the reply action
*/
@NonNull
public RestAction<Message> reply(boolean ephemeral, @NonNull String content, Object... args) {
content = format(content, args);
if (event.isAcknowledged()) {
return event.getHook().setEphemeral(ephemeral).sendMessage(content);
}
return event.reply(content).setEphemeral(ephemeral).flatMap(InteractionHook::retrieveOriginal);
}
/**
* Format the given content with the given arguments.
*
* @param content the content to format
* @param args the arguments to format with
* @return the formatted content
*/
@NonNull
private String format(@NonNull String content, Object... args) {
return args != null && (args.length > 0) ? content.formatted(args) : content;
}
}

View File

@ -0,0 +1,21 @@
package cc.fascinated.bat.common;
/**
* @author Fascinated (fascinated7)
*/
public class LongUtils {
/**
* Checks if a string is a long
*
* @param string the string to check
* @return if the string is a long
*/
public static boolean isLong(String string) {
try {
Long.parseLong(string);
return true;
} catch (NumberFormatException exception) {
return false;
}
}
}

View File

@ -24,4 +24,39 @@ public final class MathUtils {
).format(number) ).format(number)
); );
} }
/**
* Clamps a value between a minimum and maximum.
*
* @param value The value to clamp.
* @param min The minimum value.
* @param max The maximum value.
* @return The clamped value.
*/
public static double clamp(double value, double min, double max) {
return Math.max(min, Math.min(max, value));
}
/**
* Linearly interpolates between two values.
*
* @param a The first value.
* @param b The second value.
* @param t The interpolation value.
* @return The interpolated value.
*/
public static double lerp(double a, double b, double t) {
return a + t * (b - a);
}
/**
* Generates a random number between a minimum and maximum.
*
* @param min The minimum value.
* @param max The maximum value.
* @return The random value.
*/
public static double random(double min, double max) {
return Math.random() * (max - min) + min;
}
} }

View File

@ -1,7 +1,8 @@
package cc.fascinated.bat.common; package cc.fascinated.bat.common;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.common.model.BatUser;
import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
@ -10,6 +11,7 @@ import java.util.Comparator;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@UtilityClass
public class MemberUtils { public class MemberUtils {
/** /**
* Checks if a user has permission to edit another user * Checks if a user has permission to edit another user

View File

@ -0,0 +1,96 @@
package cc.fascinated.bat.common;
import lombok.NonNull;
import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.JDA;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;
@UtilityClass
public final class MiscUtils {
/**
* Get the invite url for the bot.
*
* @param jda the JDA instance
* @return the invite url
*/
@NonNull
public static String getInviteUrl(@NonNull JDA jda) {
return "https://discord.com/oauth2/authorize?client_id=" + jda.getSelfUser().getId();
}
/**
* Convert an array of strings to a single string.
*
* @param lines the lines to convert
* @return the string
*/
@NonNull
public static String arrayToString(String... lines) {
return Arrays.stream(lines)
.filter(Objects::nonNull)
.collect(Collectors.joining("\n"));
}
/**
* Capitalize the first letter of
* every word in the given string.
*
* @param input the input to capitalize
* @return the capitalized string
*/
@NonNull
public static String capitalize(@NonNull String input) {
input = input.toLowerCase().replace('_', ' ');
StringBuilder result = new StringBuilder();
boolean capitalizeNext = true;
for (char character : input.toCharArray()) {
if (Character.isSpaceChar(character)) {
capitalizeNext = true;
result.append(character);
} else if (capitalizeNext) {
result.append(Character.toUpperCase(character));
capitalizeNext = false;
} else {
result.append(character);
}
}
return result.toString();
}
/**
* Get the enum constant with the given
* name from the given enum class.
*
* @param enumClass the enum class
* @param enumName the enum name
* @param <T> the enum type
* @return the enum constant, null if not found
*/
public static <T extends Enum<T>> T getEnum(@NonNull Class<T> enumClass, String enumName) {
return getEnum(enumClass, enumName, null);
}
/**
* Get the enum constant with the given
* name from the given enum class.
*
* @param enumClass the enum class
* @param enumName the enum name
* @param defaultValue the default value
* @param <T> the enum type
* @return the enum constant, default value if not found
*/
public static <T extends Enum<T>> T getEnum(@NonNull Class<T> enumClass, String enumName, T defaultValue) {
if (enumName == null) {
return defaultValue;
}
try {
return Enum.valueOf(enumClass, enumName);
} catch (IllegalArgumentException ex) {
return defaultValue;
}
}
}

View File

@ -1,17 +1,20 @@
package cc.fascinated.bat.common; package cc.fascinated.bat.common;
import lombok.experimental.UtilityClass;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.Locale; import java.util.Locale;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@UtilityClass
public class NumberFormatter { public class NumberFormatter {
/** /**
* The suffixes for the numbers * The suffixes for the numbers
*/ */
private static final String[] SUFFIXES = new String[] { "K", "M", "B", "T", "Q", "QT", "S", "SP", "O", "N", "D", "UD", "DD", "TD" }; private static final String[] SUFFIXES = new String[] { "K", "M", "B", "T", "Q", "QT", "S", "SP", "O", "N", "D", "UD", "DD", "TD" };
private static final DecimalFormat FORMAT = new DecimalFormat("###.##"); private static final DecimalFormat FORMAT = new DecimalFormat("#,##0.##");
/** /**
* Format the provided double * Format the provided double
@ -44,8 +47,8 @@ public class NumberFormatter {
* @param input the value to format * @param input the value to format
* @return the formatted double, in the format of xx,xxx,xxx * @return the formatted double, in the format of xx,xxx,xxx
*/ */
public static String formatCommas(double input) { public static String simpleFormat(double input) {
return String.format("%,.0f", input); return FORMAT.format(input);
} }
/** /**

View File

@ -0,0 +1,20 @@
package cc.fascinated.bat.common;
/**
* @author Fascinated (fascinated7)
*/
public class NumberUtils {
/**
* Parses a string to an integer
*
* @param input the string to parse
* @return the parsed integer, or -1 if invalid
*/
public static int parseInt(String input) {
try {
return Integer.parseInt(input);
} catch (NumberFormatException exception) {
return -1;
}
}
}

View File

@ -1,8 +1,9 @@
package cc.fascinated.bat.common; package cc.fascinated.bat.common;
import cc.fascinated.bat.BatApplication; import cc.fascinated.bat.BatApplication;
import cc.fascinated.bat.model.token.paste.PasteUploadToken; import cc.fascinated.bat.common.model.token.paste.PasteUploadToken;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import java.net.URI; import java.net.URI;
@ -13,10 +14,11 @@ import java.net.http.HttpResponse;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Log4j2 @UtilityClass
@Log4j2(topic = "PasteUtils")
public class PasteUtils { public class PasteUtils {
private static final String PASTE_URL = "https://paste.fascinated.cc/"; private static final String PASTE_URL = "https://paste.fascinated.cc/";
private static final String PASTE_UPLOAD_URL = PASTE_URL + "api/upload"; private static final String PASTE_UPLOAD_URL = PASTE_URL + "api/upload?expires=" + 60 * 60 * 24 * 30; // 30 days
private static final HttpClient httpClient = HttpClient.newHttpClient(); private static final HttpClient httpClient = HttpClient.newHttpClient();
/** /**

View File

@ -1,12 +1,18 @@
package cc.fascinated.bat.common; package cc.fascinated.bat.common;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.common.model.BatGuild;
import lombok.experimental.UtilityClass;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
import java.awt.*;
import java.util.EnumSet;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@UtilityClass
public class RoleUtils { public class RoleUtils {
/** /**
* Checks if a member has permission to give the role to another member * Checks if a member has permission to give the role to another member
@ -19,4 +25,60 @@ public class RoleUtils {
public static boolean hasPermissionToGiveRole(BatGuild guild, Member member, Role role) { public static boolean hasPermissionToGiveRole(BatGuild guild, Member member, Role role) {
return member.getRoles().stream().anyMatch(r -> r.getPosition() > role.getPosition()); return member.getRoles().stream().anyMatch(r -> r.getPosition() > role.getPosition());
} }
/**
* Checks if a member has a higher role than the specified role
*
* @param member the member to check
* @param targetMember the member to check against
* @return if the member has a higher role
*/
public static boolean hasHigherRole(Member member, Member targetMember) {
return member.getRoles().stream().anyMatch(r -> targetMember.getRoles().stream().anyMatch(tr -> tr.getPosition() < r.getPosition()));
}
/**
* Gets the formatted permissions of a role
*
* @param role the role to get the formatted permissions of
* @return the formatted permissions
*/
public String getFormattedPermissions(Role role) {
StringBuilder formattedPermissions = new StringBuilder();
EnumSet<Permission> permissions = role.getPermissions();
if (permissions.isEmpty()) {
return "`None`";
}
for (Permission permission : permissions) {
formattedPermissions.append("`").append(permission.getName()).append("`, ");
}
return formattedPermissions.substring(0, formattedPermissions.length() - 2);
}
/**
* Gets the formatted color of a role
*
* @param color the color string to get the formatted color of
* @return the formatted color
*/
public String getFormattedColor(Color color) {
if (color == null) {
return "Default";
}
String colorHex = HexColorUtils.colorToHex(color);
return "`%s` *[(view)](%s)*".formatted(
colorHex,
"https://www.colorhexa.com/%s".formatted(colorHex.substring(1))
);
}
/**
* Gets the formatted color of a role
*
* @param role the role to get the formatted icon of
* @return the formatted icon
*/
public String getFormattedColor(Role role) {
return getFormattedColor(role.getColor());
}
} }

View File

@ -1,69 +0,0 @@
package cc.fascinated.bat.common;
import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.service.SpotifyService;
import lombok.NonNull;
import lombok.extern.log4j.Log4j2;
import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlaying;
import se.michaelthelin.spotify.model_objects.specification.Track;
/**
* @author Fascinated (fascinated7)
*/
@Log4j2
public class SpotifyUtils {
/**
* Gets the URL of the track that is currently playing.
*
* @param currentlyPlaying The currently playing object.
* @return The URL of the track that is currently playing.
*/
public static String getTrackUrl(CurrentlyPlaying currentlyPlaying) {
return "https://open.spotify.com/track/" + currentlyPlaying.getItem().getId();
}
/**
* Gets the formatted time of the currently playing track
*
* @param currentlyPlaying the currently playing track
* @return the formatted time
*/
public static String getFormattedTime(@NonNull CurrentlyPlaying currentlyPlaying) {
Track track = (Track) currentlyPlaying.getItem();
int currentMinutes = currentlyPlaying.getProgress_ms() / 1000 / 60;
int currentSeconds = currentlyPlaying.getProgress_ms() / 1000 % 60;
int totalMinutes = track.getDurationMs() / 1000 / 60;
int totalSeconds = track.getDurationMs() / 1000 % 60;
return "`%02d:%02d`/`%02d:%02d`".formatted(currentMinutes, currentSeconds, totalMinutes, totalSeconds);
}
/**
* Get the next track that is playing
*
* @param user The user to get the track for
* @param oldName The name of the old track
* @return The new track
*/
public static CurrentlyPlaying getNewTrack(@NonNull SpotifyService spotifyService, @NonNull BatUser user, @NonNull String oldName) {
int checks = 0;
try {
Thread.sleep(150);
while (checks < 10) {
CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user);
Track track = (Track) currentlyPlaying.getItem();
if (track.getName().equals(oldName)) {
Thread.sleep(250);
checks++;
} else {
log.info("Found new track \"{}\" in {} check{}", track.getName(), checks, checks == 1 ? "" : "s");
return currentlyPlaying;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -1,8 +1,11 @@
package cc.fascinated.bat.common; package cc.fascinated.bat.common;
import lombok.experimental.UtilityClass;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@UtilityClass
public class StringUtils { public class StringUtils {
/** /**
* Generates a random string * Generates a random string
@ -34,4 +37,18 @@ public class StringUtils {
} }
return inputString; return inputString;
} }
/**
* Formats bytes into a human-readable format
*
* @param bytes the bytes
* @return the formatted bytes
*/
public static String formatBytes(long bytes) {
int unit = 1024;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
char pre = "KMGTPE".charAt(exp-1);
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
} }

View File

@ -1,6 +1,5 @@
package cc.fascinated.bat.common; package cc.fascinated.bat.common;
import cc.fascinated.bat.service.DiscordService;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
/** /**
@ -18,7 +17,7 @@ public class TextChannelUtils {
if (id == null) { if (id == null) {
return false; return false;
} }
return DiscordService.JDA.getTextChannelById(id) != null; return ChannelUtils.getTextChannel(id) != null;
} }
/** /**

View File

@ -0,0 +1,45 @@
package cc.fascinated.bat.common;
import cc.fascinated.bat.service.DiscordService;
import lombok.experimental.UtilityClass;
import lombok.extern.log4j.Log4j2;
import net.dv8tion.jda.api.entities.User;
/**
* @author Fascinated (fascinated7)
*/
@UtilityClass
@Log4j2(topic = "UserUtils")
public class UserUtils {
/**
* Gets the user with the given id
*
* @param id the id of the user
* @param retries the amount of retries
* @return the user with the given id
*/
private static User getUser(String id, int retries) {
if (retries >= 10) {
log.error("Failed to find user \"{}\" after {} retries.", id, retries);
return null;
}
User user = DiscordService.JDA.retrieveUserById(id).complete();
if (user == null) {
return getUser(id, retries + 1);
}
if (retries >= 5) {
log.info("Found user \"{}\" after {} retries.", user.getGlobalName(), retries);
}
return user;
}
/**
* Gets the user with the given id
*
* @param id the id of the user
* @return the user with the given id
*/
public static User getUser(String id) {
return getUser(id, 0);
}
}

View File

@ -1,8 +1,7 @@
package cc.fascinated.bat.features; package cc.fascinated.bat.common.feature;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.common.oldcommand.BatCommand;
import cc.fascinated.bat.command.Category; import cc.fascinated.bat.service.OldCommandService;
import cc.fascinated.bat.service.CommandService;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -20,28 +19,27 @@ public abstract class Feature {
*/ */
private final String name; private final String name;
/**
* The default state of the feature
*/
private final FeatureProfile.FeatureState defaultState;
/** /**
* The description of the feature * The description of the feature
*/ */
public final boolean canBeDisabled; public final boolean canBeDisabled;
/**
* The category of the feature
*/
private final Category category;
/** /**
* Registers the command for the feature * Registers the command for the feature
* *
* @param commandService The command service * @param commandService The command service
* @param command The command to register * @param command The command to register
*/ */
public void registerCommand(@NonNull CommandService commandService, @NonNull BatCommand command) { public void registerCommand(@NonNull OldCommandService commandService, @NonNull BatCommand command) {
// If the command using the default category then set the category to the feature's category
if (command.getCategory() == Category.GENERAL) {
command.setCategory(this.category);
}
command.setFeature(this); command.setFeature(this);
for (BatCommand subCommand : command.getSubCommands().values()) {
subCommand.setFeature(this);
}
commandService.registerCommand(command); commandService.registerCommand(command);
} }
} }

View File

@ -1,11 +1,11 @@
package cc.fascinated.bat.features.base.profile; package cc.fascinated.bat.common.feature;
import cc.fascinated.bat.common.Serializable; import cc.fascinated.bat.common.Serializable;
import cc.fascinated.bat.features.Feature;
import com.google.gson.Gson; import com.google.gson.Gson;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.NonNull;
import org.bson.Document; import org.bson.Document;
import java.util.HashMap; import java.util.HashMap;
@ -16,8 +16,6 @@ import java.util.Map;
*/ */
@NoArgsConstructor @NoArgsConstructor
public class FeatureProfile extends Serializable { public class FeatureProfile extends Serializable {
private static final FeatureState DEFAULT_STATE = FeatureState.ENABLED;
/** /**
* The feature states * The feature states
*/ */
@ -28,13 +26,13 @@ public class FeatureProfile extends Serializable {
* *
* @return the feature states * @return the feature states
*/ */
public FeatureState getFeatureState(Feature feature) { public FeatureState getFeatureState(@NonNull Feature feature) {
if (feature == null) { if (!feature.isCanBeDisabled()) {
return DEFAULT_STATE; return FeatureProfile.FeatureState.ENABLED;
} }
String featureName = feature.getName().toUpperCase(); String featureName = feature.getName().toUpperCase();
if (!this.featureStates.containsKey(featureName)) { if (!this.featureStates.containsKey(featureName)) {
this.featureStates.put(featureName, DEFAULT_STATE); this.featureStates.put(featureName, feature.getDefaultState());
} }
return this.featureStates.get(featureName); return this.featureStates.get(featureName);
} }

View File

@ -1,14 +1,18 @@
package cc.fascinated.bat.model; package cc.fascinated.bat.common.model;
import cc.fascinated.bat.BatApplication; import cc.fascinated.bat.BatApplication;
import cc.fascinated.bat.common.ProfileHolder; import cc.fascinated.bat.common.ProfileHolder;
import cc.fascinated.bat.common.Serializable; import cc.fascinated.bat.common.Serializable;
import cc.fascinated.bat.features.base.profile.FeatureProfile; import cc.fascinated.bat.common.feature.FeatureProfile;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.birthday.profile.BirthdayProfile;
import cc.fascinated.bat.features.logging.LogProfile; import cc.fascinated.bat.counter.CounterProfile;
import cc.fascinated.bat.features.namehistory.profile.guild.NameHistoryProfile; import cc.fascinated.bat.leveling.LevelingProfile;
import cc.fascinated.bat.features.reminder.ReminderProfile; import cc.fascinated.bat.logging.LogProfile;
import cc.fascinated.bat.features.welcomer.WelcomerProfile; import cc.fascinated.bat.moderation.punish.PunishmentProfile;
import cc.fascinated.bat.namehistory.profile.guild.NameHistoryProfile;
import cc.fascinated.bat.reminder.ReminderProfile;
import cc.fascinated.bat.statschannel.StatsChannelProfile;
import cc.fascinated.bat.welcomer.WelcomerProfile;
import cc.fascinated.bat.premium.PremiumProfile; import cc.fascinated.bat.premium.PremiumProfile;
import cc.fascinated.bat.service.DiscordService; import cc.fascinated.bat.service.DiscordService;
import cc.fascinated.bat.service.MongoService; import cc.fascinated.bat.service.MongoService;
@ -16,9 +20,8 @@ import com.mongodb.client.model.ReplaceOptions;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter; import lombok.Setter;
import lombok.extern.log4j.Log4j2;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import java.util.Date; import java.util.Date;
@ -30,8 +33,10 @@ import java.util.Map;
*/ */
@Getter @Getter
@Setter @Setter
@Log4j2
public class BatGuild extends ProfileHolder { public class BatGuild extends ProfileHolder {
private static final Logger log = LoggerFactory.getLogger(BatGuild.class); private static final String DEFAULT_PREFIX = "!";
/** /**
* The document that belongs to this guild * The document that belongs to this guild
*/ */
@ -44,6 +49,11 @@ public class BatGuild extends ProfileHolder {
@Id @Id
private final String id; private final String id;
/**
* The prefix of the guild
*/
private final String prefix;
/** /**
* The time this guild was joined * The time this guild was joined
*/ */
@ -58,6 +68,7 @@ public class BatGuild extends ProfileHolder {
this.id = id; this.id = id;
this.document = document; this.document = document;
boolean newAccount = this.document.isEmpty(); boolean newAccount = this.document.isEmpty();
this.prefix = newAccount ? DEFAULT_PREFIX : (String) document.getOrDefault("prefix", DEFAULT_PREFIX);
this.createdAt = newAccount ? new Date() : document.getDate("createdAt"); this.createdAt = newAccount ? new Date() : document.getDate("createdAt");
Guild guild = DiscordService.JDA.getGuildById(id); Guild guild = DiscordService.JDA.getGuildById(id);
@ -150,6 +161,42 @@ public class BatGuild extends ProfileHolder {
return getProfile(WelcomerProfile.class); return getProfile(WelcomerProfile.class);
} }
/**
* Gets the counter profile
*
* @return the counter profile
*/
public CounterProfile getCounterProfile() {
return getProfile(CounterProfile.class);
}
/**
* Gets the leveling profile
*
* @return the leveling profile
*/
public LevelingProfile getLevelingProfile() {
return getProfile(LevelingProfile.class);
}
/**
* Gets the stats channel profile
*
* @return the stats channel profile
*/
public StatsChannelProfile getStatsChannelProfile() {
return getProfile(StatsChannelProfile.class);
}
/**
* Gets the punishment profile
*
* @return the punishment profile
*/
public PunishmentProfile getPunishmentProfile() {
return getProfile(PunishmentProfile.class);
}
/** /**
* Saves the user * Saves the user
*/ */
@ -158,7 +205,7 @@ public class BatGuild extends ProfileHolder {
document.put("_id", id); document.put("_id", id);
document.put("createdAt", createdAt); document.put("createdAt", createdAt);
Map<String, org.bson.Document> profileDocuments = new HashMap<>(); Map<String, org.bson.Document> profileDocuments = this.document.get("profiles", new HashMap<>());
for (Serializable profile : getProfiles().values()) { for (Serializable profile : getProfiles().values()) {
profileDocuments.put(profile.getClass().getSimpleName(), profile.serialize(BatApplication.GSON)); profileDocuments.put(profile.getClass().getSimpleName(), profile.serialize(BatApplication.GSON));
} }

View File

@ -1,10 +1,10 @@
package cc.fascinated.bat.model; package cc.fascinated.bat.common.model;
import cc.fascinated.bat.BatApplication; import cc.fascinated.bat.BatApplication;
import cc.fascinated.bat.common.ProfileHolder; import cc.fascinated.bat.common.ProfileHolder;
import cc.fascinated.bat.common.Serializable; import cc.fascinated.bat.common.Serializable;
import cc.fascinated.bat.features.namehistory.profile.user.NameHistoryProfile; import cc.fascinated.bat.common.UserUtils;
import cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile; import cc.fascinated.bat.namehistory.profile.user.NameHistoryProfile;
import cc.fascinated.bat.service.DiscordService; import cc.fascinated.bat.service.DiscordService;
import cc.fascinated.bat.service.MongoService; import cc.fascinated.bat.service.MongoService;
import com.mongodb.client.model.ReplaceOptions; import com.mongodb.client.model.ReplaceOptions;
@ -53,17 +53,18 @@ public class BatUser extends ProfileHolder {
*/ */
private User user; private User user;
public BatUser(@NonNull String id, @NonNull org.bson.Document document) { public BatUser(@NonNull String id, User user, @NonNull org.bson.Document document) {
this.id = id; this.id = id;
this.document = document; this.document = document;
boolean newAccount = this.document.isEmpty(); boolean newAccount = this.document.isEmpty();
this.createdAt = newAccount ? new Date() : document.getDate("createdAt"); this.createdAt = newAccount ? new Date() : document.getDate("createdAt");
User user = DiscordService.JDA.getUserById(id); // User was not passed through
if (user != null) { if (user == null) {
this.user = user; user = UserUtils.getUser(id);
this.globalName = user.getGlobalName();
} }
this.user = user;
this.globalName = user.getGlobalName();
} }
/** /**
@ -85,15 +86,6 @@ public class BatUser extends ProfileHolder {
return user; return user;
} }
/**
* Gets the user's ScoreSaber profile
*
* @return the user's ScoreSaber profile
*/
public ScoreSaberProfile getScoreSaberProfile() {
return getProfile(ScoreSaberProfile.class);
}
/** /**
* Gets the user's name history profile * Gets the user's name history profile
* *
@ -111,7 +103,7 @@ public class BatUser extends ProfileHolder {
document.put("_id", id); document.put("_id", id);
document.put("createdAt", createdAt); document.put("createdAt", createdAt);
Map<String, org.bson.Document> profileDocuments = new HashMap<>(); Map<String, org.bson.Document> profileDocuments = this.document.get("profiles", new HashMap<>());
for (Serializable profile : getProfiles().values()) { for (Serializable profile : getProfiles().values()) {
profileDocuments.put(profile.getClass().getSimpleName(), profile.serialize(BatApplication.GSON)); profileDocuments.put(profile.getClass().getSimpleName(), profile.serialize(BatApplication.GSON));
} }

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